部署到 Cloudflare Workers
使用 D1、Better Auth、上游模型和独立静态文档 Worker 部署 TinyShip 主应用。
架构
| 位置 | 职责 |
|---|---|
apps/tanstack-app | 主站、控制台、Playground、API 路由和定时清理。 |
libs/system-one | 原生传输与观察式校验、精确 JSON 标识、密钥、上游适配、限制与用量。 |
libs/auth、libs/database | 现有 Better Auth 会话和共享 D1 数据模型。 |
libs/credits、libs/payment | 现有余额、积分账本、订单和经过验证的支付到账。 |
config | 产品限制、积分包和共享能力配置。 |
apps/docs-app | 本 Fumadocs / Next.js 静态导出文档,独立部署。 |
此发行版本只维护 TanStack 主应用与文档应用。业务逻辑保留在 TinyShip 共享模块,路由只做适配编排。系统没有替代语言模型或生产模拟推理;上游未配置时返回 503 provider_not_configured,不产生新扣费。
本地运行
使用 Node.js 22 或更新版本,以及项目固定的 pnpm 9.4.0。在仓库根目录执行:
npx --yes pnpm@9.4.0 install --frozen-lockfile
npx --yes pnpm@9.4.0 setup:local
npx --yes pnpm@9.4.0 db:migrate:local
npx --yes pnpm@9.4.0 dev主应用地址为 http://localhost:7001。setup:local 会创建根目录 .env 与 apps/tanstack-app/.dev.vars,生成本地 Better Auth 密钥,且不会覆盖已有文件。它们包含秘密信息,应始终排除在版本控制之外。
需要调用模型时,在本地配置中填入真实上游凭据。根 .env 与 Worker .dev.vars 同时使用时,请保持对应设置一致。本地初始化允许未验证邮箱登录,但不会给未验证账户发放欢迎积分。生产环境应开启邮箱验证并配置邮件发送服务。
创建并迁移生产 D1
让 Wrangler 登录你的 Cloudflare 账户,随后创建数据库:
npx --yes pnpm@9.4.0 --filter @system-one/web exec wrangler login
npx --yes pnpm@9.4.0 --filter @system-one/web exec wrangler d1 create system-one在 apps/tanstack-app/wrangler.jsonc 中将占位 database_id 替换为返回的真实 ID,保留绑定名 DB 和迁移目录 ../../libs/database/drizzle-sqlite。应用完整迁移链,包括原有 TinyShip 表和 0006_system_one.sql:
npx --yes pnpm@9.4.0 db:migrate:remote先确认目标远程数据库并完成迁移,再对外提供新应用。不要用独立的决策数据库替换现有认证、订单和积分表。
配置主 Worker
在主 Worker 的 Wrangler vars 中设置以下非秘密配置:
| 变量 | 值 |
|---|---|
DB_DIALECT | d1 |
APP_BASE_URL | 主应用的精确公开源,例如 https://app.example.com。 |
BETTER_AUTH_URL | 与主应用相同的源。 |
AUTH_REQUIRE_EMAIL_VERIFICATION | 生产环境设为 true。 |
EMAIL_PROVIDER | 默认 resend,也可选用既有的 cloudflare 邮件集成。 |
EMAIL_DEFAULT_FROM | 已配置邮件域名下的发送地址。 |
SYSTEM_ONE_PROVIDER | typesafe 或 openrouter。 |
SYSTEM_ONE_MODEL | 仅在请求省略模型时使用的默认值;未配置为 jev-latest。可设为受支持别名或版本,显式 TypeSafe 请求模型优先。 |
SYSTEM_ONE_RATE_LIMIT | 默认 120,同账户共享。 |
SYSTEM_ONE_SIGNUP_CREDITS | 默认 100,0 关闭欢迎赠送。 |
SYSTEM_ONE_DOCS_URL | 公开文档地址,例如 https://docs.example.com/zh-CN/docs。 |
不要直接发布示例域名或占位数据库 ID。同源检查依赖 APP_BASE_URL,Cookie 与验证邮件需要正确的 Better Auth 地址。保留主 Worker 的 nodejs_compat 和清理计划 */15 * * * *。
通过 Worker secrets 设置凭据,在交互提示中输入值,不要把秘密直接写进命令:
npx --yes pnpm@9.4.0 --filter @system-one/web exec wrangler secret put BETTER_AUTH_SECRET
npx --yes pnpm@9.4.0 --filter @system-one/web exec wrangler secret put SYSTEM_ONE_UPSTREAM_API_KEY
npx --yes pnpm@9.4.0 --filter @system-one/web exec wrangler secret put RESEND_API_KEY使用新的高强度生产认证密钥,不复用本地开发值。上面的邮件配置使用 TinyShip 的 Resend 集成。启用其他登录提供者时,还需要对应的既有 TinyShip 配置。
选择上游
| 上游 | 默认基础地址 | 上游模型 |
|---|---|---|
typesafe | https://api.typesafe.ai/v1 | jev-latest |
openrouter | https://openrouter.ai/api/alpha | ~typesafe/jev-latest |
SYSTEM_ONE_UPSTREAM_URL 可覆盖兼容上游 HTTPS 地址,不能带凭据、查询或片段。SYSTEM_ONE_UPSTREAM_API_KEY 必须匹配所选服务。TypeSafe 原生路径使用受限 Fetch 并标记 X-System-One-Response-Mode: typesafe-native:校验后保留显式模型及请求文本、成功响应文本、状态和扩展。省略模型时直接插入根 JSON,不舍入既有数字。State 字段必填但可为 null,instructions 可省略或为 null,Noul criteria 可为 null,最终接受情况由上游决定。
OpenRouter 是 Worker 内部的显式适配器。匹配 jev-* 的请求名称会映射为 ~typesafe/jev-*,适配器构造 /decisions 请求。响应保留上游 usage、cost 与元数据,标记 openrouter-adapted,不承诺 TypeSafe 字节保真;不支持的顶层请求扩展会被拒绝。客户端仍连接平台 /v1,无需直连上游的适配器。原生 GET /v1/models 需要平台密钥并返回真实 TypeSafe { models };OpenRouter 返回 501 model_listing_not_supported。
Worker 会向上游发送状态与问题,对外开放前请阅读数据处理。上游可用性和实测性能需要在你的部署环境中验证。
兼容契约升级
契约 typesafe-2026-09-18 将 Choice 上限改为独立的 255 项、Score 上限改为 10 档;请求体仍为 65,536 字节、32 道问题、深度 32。客户端校验导入共享配置。重复 JSON 键会被拒绝,精确数字 token 用于区分幂等请求,别名或版本不再受本地 latest-only 列表限制。
调用方应从成功正文计费和 ID 迁移到 X-System-One-Credits、X-Request-Id、X-Upstream-Request-Id 与 X-Idempotency-Replayed。网关不补默认 usage、warnings 或 rounding。原生 Choice/Score 必须含分布及 confidence,Score 还必须含 legend。项目 SDK 0.3.0 可能转换自己的结果并补默认值;官方 SDK 0.6.0 提供独立兼容检查。
上游 JSON 错误保留 4xx/5xx 与 Retry-After,包括 401/403、429/529;UI 稳定错误码与来源读取响应头。含凭据的错误替换为安全正文;含敏感信息的成功响应、格式无效、超限和重定向会被拒绝。上游共用 20 秒期限,不重试。退款对账失败返回 503 且不带扣费头。变更客户端恢复逻辑前请阅读错误参考。
重放存储无需结构迁移。新版本记录保存文本、状态及允许的头;旧记录以 legacy-cache 读取,移除旧平台计费、请求 ID 与 replayed 正文扩展,保留原 24 小时过期规则。过去合成的 warnings/rounding 无法可靠撤销。常规部署前应备份应用数据,不要为了应用此契约而清空账户或积分账本。
启用 Stripe 积分包
用 wrangler secret put 设置 STRIPE_SECRET_KEY 和 STRIPE_WEBHOOK_SECRET,支付配置中的 STRIPE_PUBLIC_KEY 使用对应的可公开密钥。所有密钥与 webhook 端点应处于相同 Stripe 模式。
注册 webhook 地址 https://YOUR_MAIN_ORIGIN/api/payment/webhook/stripe,接收 checkout.session.completed 和 checkout.session.async_payment_succeeded,使用该端点的签名密钥。处理器验证签名事件与服务端订单,浏览器跳转不能增加积分。
config/plans.ts 定义 Starter、Builder 和 Scale 三个美元一次性积分包。集成会按这些配置生成 Stripe 内联价格数据,不需要额外虚构 price-ID 环境变量。接受真实付款前,使用 Stripe 测试模式验证结账与签名到账。本指南不代表你的部署已经完成真实 Stripe 购买测试。
构建、检查并部署主应用
npx --yes pnpm@9.4.0 typecheck:tanstack
npx --yes pnpm@9.4.0 build:tanstack
npx --yes pnpm@9.4.0 deploy:check
npx --yes pnpm@9.4.0 deploydeploy:check 构建 Cloudflare 目标并执行 Wrangler dry run,deploy 发布主 Worker。可通过 pnpm preview 预览本地生产构建。这些命令本身不能证明真实模型凭据、邮件投递、支付到账或决策质量已验证。
2026 年 9 月 18 日的最终构建报告主 Worker 未压缩大小为 39,422.77 KiB,gzip 为 7,350.28 KiB。请用 Wrangler 的 未压缩 Total Upload 对照目标账户实际生效的限制。同日核对的官方 Worker 大小规则写明 Free 与 Paid 均为未压缩 64 MiB,不设压缩体积限制,因此不能仅凭 gzip 数值判断是否必须付费;CPU 等其他配额仍需考虑。
以上是历史构建测量,不代表本次兼容修改后的构建大小。
部署后应检查 /health、带平台 Bearer 密钥的 /v1/models、注册与邮箱验证、密钥创建和撤销、两个客户端路径、Playground 可编辑模型、用量、重放响应头及签名支付到账。上线前运行离线原生契约与 D1 测试,它们检查实际 Fetch 参数及同次响应文本。pnpm test:contract:live 是单独显式执行的计费检查,不是文档构建的一部分;它对比某一次调用实际收到的上游文本与网关返回,不要求独立模型调用数值相同。真实推理会消耗上游用量和平台积分。
独立部署文档
文档应用将全部中英文页面和静态搜索索引导出至 apps/docs-app/out。它使用系统字体,不需要运行时数据库或秘密凭据。构建时将公开变量 SYSTEM_ONE_DOCS_URL 设为文档域名,确保 canonical 与社交元数据地址正确。
npx --yes pnpm@9.4.0 --filter @system-one/docs typecheck
npx --yes pnpm@9.4.0 build:docs
npx --yes pnpm@9.4.0 --filter @system-one/web exec wrangler deploy --config ../docs-app/wrangler.jsonc --dry-run
npx --yes pnpm@9.4.0 --filter @system-one/web exec wrangler deploy --config ../docs-app/wrangler.jsonc文档配置使用 Worker 名称 system-one-docs,以静态资源方式提供 out 目录,并对未知路径返回已导出的 404 页面。本地预览命令:
npx --yes pnpm@9.4.0 --filter @system-one/web exec wrangler dev --config ../docs-app/wrangler.jsonc --port 3001静态导出不能用 next start 启动,文档预览也不会提供 /v1/systemone。配置自定义域名后,将主 Worker 的 SYSTEM_ONE_DOCS_URL 指向已发布的文档。
仓库内运行指南位于 docs/deployment.md。框架参考:Cloudflare 静态资源、D1 迁移、Next.js 静态导出。