此页描述当前源码协议,SDK、Indiana 部署与数据库迁移须匹配;npm 已发布 0.0.1 beta,不代表后续工作区版本已发布。宿主负责真实会话与持久化 start 输入,切换账号须关闭并丢弃旧运行。
相关:服务端回执、任务与恢复
import { createFunnelStartClient, createGrooveServer, createGuestToken,} from "@tinkerlandai/indiana-sdk/server"; const options = { baseUrl: process.env.GROOVE_BASE_URL!, apiKey: process.env.GROOVE_SECRET_KEY!, scope: { projectId: process.env.GROOVE_PROJECT_ID!, environment: "sandbox" },} as const;const groove = createGrooveServer(options);const funnels = createFunnelStartClient(options); export async function POST(request: Request) { if (request.headers.get("origin") !== process.env.APP_ORIGIN) return new Response("Forbidden", { status: 403 }); const session = await requireHostSession(request); // Every run has a customer: the signed-in customer, or a guest kept in this session. let customerToken: string; if (session.grooveCustomerId) { ({ customerToken } = await groove.createCustomerSession(session.grooveCustomerId)); } else { session.grooveGuestToken ??= createGuestToken(); await session.save(); await groove.createGuestCustomer({ guestToken: session.grooveGuestToken }); ({ customerToken } = await groove.resumeGuestSession({ guestToken: session.grooveGuestToken })); } // Persist before the first request. Retries reuse the whole original input. if (!session.funnelStart) { session.funnelStart = { source: { type: "funnel", id: process.env.GROOVE_FUNNEL_ID! }, requestId: crypto.randomUUID(), locale: session.locale, commerce: { provider: "stripe", currency: "USD" }, }; await session.save(); } const result = await funnels.start({ ...session.funnelStart, customerToken }); session.grooveRunToken = result.runToken; await session.save(); return Response.json({ runToken: result.runToken }, { headers: { "Cache-Control": "private, no-store" }, });}