T3 Connect 中继(relay)
NOTE
在应用中通过设置 > 共享与访问登录 T3 Connect。
中继是 T3 Connect 的托管控制平面。它帮助客户端发现并连接到远程环境,管理这些连接所需的云端记录,并投递可选的移动通知和实时活动(Live Activities)。
中继有意不处在普通 T3 Code 流量的热路径上。客户端连接之后,常规的 API 与 WebSocket 流量直接在该客户端和所选环境之间传输。更大范围的系统设计见 T3 Connect 架构说明。
职责
中继目前负责:
- 将 T3 Code 环境关联到云账户。
- 预配并跟踪托管环境端点。
- 签发用于把客户端连接到已关联环境的短期凭证。
- 列出某个账户的已关联环境和已注册移动设备。
- 注册移动通知偏好,以及 APNs 或 FCM 令牌。
- 接收已发布的智能体活动,并投递通知或实时活动更新。
- 持久化中继状态,并暴露中继专用的追踪信息以供诊断。
环境服务器和中继拥有各自的凭证与信任边界。在更改令牌、凭证或授权行为之前,请阅读环境身份验证档案。
代码地图
alchemy.run.ts定义已部署的 Alchemy 技术栈。src/worker.ts接入 Cloudflare 绑定、运行时层、队列和 HTTP API。src/http/Api.ts包含中继的 HTTP 处理程序和身份验证边界。src/environments包含环境关联、凭证、端点预配和连接流程。src/agentActivity包含移动设备注册、活动状态、APNs 与 FCM 投递,以及队列处理。src/auth包含中继令牌和 DPoP 证明的处理。src/persistence/schema.ts定义已持久化的中继状态。请把模式变更和迁移变更放在一起。
共享的请求与响应模式位于 packages/contracts/src/relay.ts。共享的客户端侧中继调用位于 packages/client-runtime/src/relay/managedRelay.ts。
在本地工作
从仓库根目录安装依赖,然后在此目录运行面向中继的检查:
vp install
cd infra/relay
vp test run
vp run typecheck迭代时若要运行较小的测试集:
vp test run src/environments/EnvironmentLinker.test.ts在认为一项更改完成之前,从根目录运行仓库范围的检查:
vp check
vp run typecheck后端更改应当包含测试。优先测试真实的业务逻辑,在边界处表示外部依赖,而不是模拟内部行为。
部署
中继使用 Alchemy CLI 部署(在此目录中,vp run --filter t3code-relay deploy 就是 alchemy deploy):
vp run --filter t3code-relay deploy该技术栈会预配 Cloudflare Worker 与队列、托管端点资源、数据库连接以及中继追踪资源。部署之前,将 infra/relay/.env.example 复制为 infra/relay/.env,并填入该部署专用的值。Alchemy 会从中继目录加载该文件。运行时密钥包括 Clerk、APNs 以及可选的 FCM 凭证。对于没有 Apple 凭证、仅面向 Android 的开发部署,请设置 APNS_ENABLED=false。生产环境会将已配置的 API 与隧道 DNS 区域采纳为保留的 Cloudflare 资源。个人阶段引用生产环境所拥有的区域。
prod 这一 Alchemy 阶段拥有保留的 PlanetScale 数据库,并且是稳定版与每夜版客户端共用的托管中继。其他每个阶段都引用该数据库,并为本地开发预配隔离的 PlanetScale 分支和运行时角色,因此在创建开发者阶段之前先部署 prod:
vp run --filter t3code-relay deploy -- --stage prod
vp run --filter t3code-relay deploy -- --env-file .env.localAlchemy 默认把个人部署放到 dev_$USER 阶段。中继自定义域名采用与 Alchemy 物理资源名称相同的 DNS 安全净化,因此 prod 使用 relay.<RELAY_API_ZONE_NAME>,而 dev_julius 使用 relay-dev-julius.<RELAY_API_ZONE_NAME>。托管环境端点预配在 RELAY_TUNNEL_ZONE_NAME 之下,该区域可能是另一个 Cloudflare 区域。生产隧道主机名使用 prod-<digest>.<RELAY_TUNNEL_ZONE_NAME>;个人阶段使用 <stage>-<digest>.<RELAY_TUNNEL_ZONE_NAME>。RELAY_DOMAIN 仍可作为显式的 API 域名覆盖使用。
该技术栈的 PublishClientConfig 操作(src/clientConfig.ts)会把已部署的中继 URL 和追踪配置写入仓库根目录的 .env,因此后续源码构建会指向刚刚部署的中继,无需手动复制这些值。仅当这些输出之一发生变化时它才会运行,而 T3CODE_RELAY_CLIENT_CONFIG_ENV 会把它重定向到另一个文件。
部署 CI
中继与客户端发布分开版本管理。.github/workflows/deploy-relay.yml 会部署共享的 Alchemy prod 阶段,时机是每次推送到 main。稳定版和每夜版的发布构建都从同一个 production GitHub 环境解析其静态公共配置。给同一仓库内的拉取请求(PR)打上 relay:preview 标签会部署一个 pr-<number> 阶段,清理工作流会把它拆除;参见 relay-preview.yml。开发者可以在本地使用除 prod 以外的任意阶段名称,部署个人的非生产阶段。
仓库必须定义这些由中继部署共享的 Actions 变量:
CLOUDFLARE_ACCOUNT_IDPLANETSCALE_ORGANIZATIONAXIOM_ORG_ID
仓库必须定义这些由中继部署共享的 Actions 密钥:
CLOUDFLARE_API_TOKENPLANETSCALE_API_TOKEN_IDPLANETSCALE_API_TOKENAXIOM_TOKEN
production GitHub 环境必须定义这些 Actions 变量:
RELAY_API_ZONE_NAMERELAY_TUNNEL_ZONE_NAME- 若要覆盖推导出的生产中继域名,则需要
RELAY_DOMAIN RELAY_ALERT_NOTIFIER_ID,即中继告警用来寻呼的 Axiom 通知器。没有它,此次部署不会创建监视器或健康仪表板。参见 中继告警。RELAY_WARNING_NOTIFIER_ID,可选,用于中继警告的 Axiom 通知器CLERK_PUBLISHABLE_KEYCLERK_JWT_AUDIENCECLERK_JWT_TEMPLATEAPNS_ENVIRONMENTAPNS_TEAM_IDAPNS_KEY_IDAPNS_BUNDLE_ID
production GitHub 环境必须定义这些 Actions 密钥:
CLERK_SECRET_KEYAPNS_PRIVATE_KEY- 启用 Android 推送时需要
FCM_SERVICE_ACCOUNT T3CHAT_LINK_SECRET,可选,与 T3 Chat 的T3CODE_LINK_SECRET共享。没有它,T3 Chat 账户关联处于关闭状态。本地和预览阶段可以设置T3CHAT_URL,以指向另一个 T3 Chat 部署;生产环境使用https://t3.chat。
账户范围的仓库凭证由 Alchemy 在预配中继阶段时使用;它们不会绑定到中继 Worker 中。生产部署使用 Axiom 个人访问令牌,因此 AXIOM_ORG_ID 必须与 AXIOM_TOKEN 一起提供。发布工作流会从同一环境读取生产中继推导出的公共 URL 和 Clerk 可发布密钥,供下游的桌面、CLI 和托管 Web 构建使用。
参见:
- T3 Connect 设置,了解 Clerk 密钥、JWT 模板和注册限制。
- 中继可观测性,了解部署追踪和诊断。
- T3 Connect 架构,了解环境关联和信任边界。