T3 Code 更新指南:服务端、桌面端与移动端的完整升级流程
2026/9/15 16:47:37 网站建设 项目流程

T3 Code 更新指南:服务端、桌面端与移动端的完整升级流程

【免费下载链接】t3code项目地址: https://gitcode.com/GitHub_Trending/t3/t3code

导读

T3 Code 采用"客户端与服务端分离"的架构:你日常使用的应用(桌面端、Web 端、移动端)与真正运行 Agent 的服务器可能位于完全不同的机器上。因此"更新"不是简单地升级一个安装包,而是要在正确识别"哪个组件落后于哪个版本"的前提下,用与运行方式匹配的手段完成升级。本文基于 docs/user/updating.md 整理完整更新流程,并结合 apps/server/src/serviceLauncher.ts、apps/server/src/cli/service.ts、apps/mobile/src/features/updates/app-updates.ts 等源码,深入讲解后台服务更新的事务性提交机制、失败回滚与移动端后台下载更新的实现原理。读完本文,你将掌握:如何判断更新提示指向哪台机器、三种服务器运行形态各自对应的更新动作、npx t3@<client-version> service update的正确用法、更新失败的排查步骤,以及桌面端与移动端的更新行为差异。

一、更新模型:先搞清楚"谁落后于谁"

你使用的应用和运行 Agent 的服务器可能在不同的机器上。当服务器位于你的 Web 应用或桌面应用之后时,版本不匹配会产生更新提示,提示出现在两处:

  • 对话(conversation)中
  • Settings → Connections设置页

更新提示会明确指出版本落后的机器名称。升级时务必更新提示中指定的那台机器,而不是你当前正在操作的设备——这是最常见的误操作来源:用户在客户端所在机器上反复点击更新,却始终无法消除提示,因为真正需要更新的是另一台机器上的服务器。

从源码结构看,服务器侧的版本协调逻辑集中在 apps/server/src/cloud/serviceProtocol.ts 中,它定义了服务状态文件(SERVICE_STATE_FILE)、launcher 与子进程间的 IPC 消息(update-acceptedupdate-rejectedcommitted等)以及精确版本比较函数。所谓"精确版本"(exact version)指形如0.0.41-preview.20260912.1595的完整版本号,远程更新只接受比当前版本更新的精确版本(serviceLauncher.ts 中的#handleUpdateRequest会拒绝非精确版本、非绝对路径以及不高于当前版本的目标)。

二、更新前的准备:理解更新会带来什么影响

服务器更新会重启连接,并可能中断正在运行的 Agent 与终端命令。但以下数据会完整保留:

  • 已保存的会话(saved threads)
  • 设置(settings)
  • 项目文件(project files)

2.1 Continue threads after restarts 设置

Settings → General → Continue threads after restarts默认关闭。开启后,可在更新、崩溃或机器重启后恢复支持的活跃会话(supported active threads)。

需要注意的细节:

  1. 该设置会保存到支持此设置的已连接环境中;先更新旧服务器,再启用该设置效果最佳。
  2. 如果某个受支持的环境当时离线,或保存的值不同,可等它连接后,在 Settings 中使用Apply to all统一应用。
  3. 该设置不会自动启动 T3 Code——你必须在该机器上手动重新启动它。
  4. 终端命令仍可能被中断;没有保存 provider 恢复状态的会话,需要发送一条新消息才能继续。
  5. 如果你此前为更新启用了会话延续,只需再开启一次该设置,即可在无客户端连接的情况下允许恢复。

三、更新已连接的服务器:三种动作与运行形态的对应关系

更新提示给出的操作取决于服务器以何种方式运行:

动作(Action)你需要做什么
Update server保持客户端打开,等待其安装并重新连接。受支持的后台服务支持远程更新。对于桌面端托管的服务器,该操作还会关闭并重新启动宿主机上的桌面应用。
Update the desktop app在运行服务器的机器上更新桌面应用,需要时再重新打开它。
Copy update command在其宿主机上停止命令行服务器,用复制到的命令重新启动,保留你惯用的启动选项。

3.1 后台服务:使用匹配版本的 CLI 更新

对于以后台服务(background service)方式运行的服务器,请在宿主机上运行与提示中版本匹配的 CLI:

npx t3@<client-version> service update

<client-version>替换为提示中显示的版本。关键限制:

  • 只有在你的客户端正处于该 release 上时,使用@latest才能解决版本不匹配问题;
  • 较旧的服务 launcher 可能需要先完成本次本地更新,之后才支持远程更新与回滚。

这条限制的根源在于 launcher 协议:按 docs/internals/server-updates.md 的说明,安装与预检(preflight)在发布不可变运行时之前于 staging 阶段完成,其中预检会校验 launcher 协议——需要新回滚保证的目标运行时,无法安全地在旧 launcher 下运行。升级 launcher 本身只能通过本地service update完成。

3.2 前台服务器:复制更新命令

对于前台运行的 CLI 服务器(foreground server),复制到的命令是npx t3@<client-version>。如果你平时不带浏览器运行,请追加serve;同时保留诸如--host--tailscale-serve之类的启动选项。例如:

npx t3@0.0.41-preview.20260912.1595 serve --host 0.0.0.0

关于服务管理的更多细节,参见 background services。

四、深入后台服务更新命令

service子命令族定义于 apps/server/src/cli/service.ts,包含四个子命令:

子命令说明
service install以当前 CLI 版本安装后台服务
service update以当前 CLI 版本更新或修复后台服务
service uninstall停止并移除后台服务
service status查看服务是否已安装、运行状态与日志路径

核心逻辑是reconcileService:它会先检查已安装服务的状态,若已安装且版本与当前 CLI 一致则不做任何改动;若已安装版本比当前 CLI 更新,且未显式传入--allow-downgrade,则直接拒绝(抛出BootServiceDowngradeRefusedError)。service updateservice install共享同一套 reconcile 逻辑,因此"更新或修复"其实是同一路径。

与更新相关的常用选项:

  • --allow-downgrade:允许用较旧的 CLI 版本替换已安装的较新服务。旧 CLI 默认拒绝替换更新的服务,必须显式加上该参数。
  • 使用npx t3@nightly service update可更新到 nightly 通道;用精确版本号替换nightly可固定到某一版本。

service status的输出会给出完整状态:安装的版本、unit 路径、日志路径,以及诸如"已安装t3@<version>(比当前 CLI 更新)"之类的提示,并建议下一步执行npx t3@<installedVersion> service update修复,或显式传--allow-downgrade

4.1 自包含构建与t3 update

自包含构建(self-contained builds)以 GitHub release 归档形式下载,而非通过 npm 安装,因此运行服务的机器在 CLI 就位后不再需要 Node.js 或 npm。将 CLI 带到无 Node 的机器上:

curl -fsSL https://t3.codes/install.sh | sh

Windows 在 PowerShell 中运行:

irm https://t3.codes/install.ps1 | iex

脚本会把t3放到~/.local/bin,后续t3 service install会复用同一份下载。默认跟随 stable 通道,可用环境变量调整:

  • T3CODE_CHANNEL=nightly:跟随 nightly 通道;
  • T3CODE_VERSION:固定精确版本;
  • T3CODE_RELEASE_BASE_URL:从镜像下载。

此外还有第三个通道preview,由维护者从未发布的开发分支手工裁切,用于演练发布流水线。这些构建可能损坏、不提供修复、也从不作为更新推送;只有当显式请求该通道时,安装器和t3 update才会前往该通道,且会给出警告。从 apps/server/src/cli/update.ts 的实现可见:从 stable/nightly 切到 preview 需要显式确认,非交互脚本会被直接拒绝("Refusing to install a preview build without confirmation")。

自包含安装就绪后,t3 update可在不依赖 npm 的情况下将机器切换到更新版本:下载运行中t3所属通道的最新 release、校验、并把t3launcher 指向新版本。相关命令形态:

t3 update # 跟随当前通道更新到最新 t3 update 0.0.41-preview.20260912.1595 # 固定精确版本 t3 update --channel nightly # 切换到其他发布通道 t3 update --allow-downgrade # 允许回退到更旧版本

t3 update的降级保护逻辑位于 apps/server/src/cli/update.ts 的runUpdate:若目标版本低于当前安装的 CLI 或服务版本,会报错并提示加--allow-downgrade。当同一 T3 home 安装了后台服务时,更新前会询问是否重启服务(因为重启会中断运行中的 Agent 回合、终端与远程客户端);非交互脚本中无提示,必须传--yes(或-y)才能重启服务。手工启动的服务器不会被自动触碰,命令会明确告知它仍停留在旧版本,需要你自行重启。

t3 uninstall是安装脚本的逆向操作:它会展示将要移除的内容(后台服务、t3launcher、~/.t3/runtime下的每个已下载版本),确认后移除。你的项目、会话与设置保存在~/.t3/userdata,不会被删除;如需彻底清除请自行删除该目录。脚本场景传--yes跳过确认。

五、源码视角:launcher 如何安全地提交一次更新

docs/internals/server-updates.md 与 apps/server/src/serviceLauncher.ts 揭示了后台服务更新的事务性设计——这也是"保持客户端打开等待重连"这一操作要求背后的原因。

5.1 谁拥有更新权

稳定 launcher(serviceLauncher.ts)是被 systemd 或 launchd 选中的运行时所有者,也是唯一可以持久写入服务状态的组件。服务器子进程通过继承的 IPC 请求更新,从不自行重写自己的服务定义或选择替代版本;本地service命令可在服务停止时替换 launcher 与状态。前台 CLI 进程不会自更新。

5.2 提交边界(Commit boundary)

更新流程是一个严格的状态机:

  1. launcher 在确认更新前,先把待更新状态(PendingServiceUpdate,含updateIdfromVersiontargetVersiondbPath持久化记录,然后停止旧子进程,将目标版本作为trial(试验)启动。
  2. trial 必须完成迁移(migrations)、获取依赖、绑定 HTTP,并在激活门(activation gate)处驻留所有长生命周期根,然后才上报prepared
  3. launcher 收到prepared持久化提交目标版本(状态变为committed),才回复子进程committed。此后子进程才能释放门、接受命令、发布 ready。
  4. 试验超时(PREPARED_TIMEOUT_MS = 120_000,即 2 分钟)或退出,则回滚到旧版本。

服务状态的每次写入都采用同目录替换(same-directory replacement)并同时 fsync 文件与目录(见writeServiceState:写入临时文件 → fsync → rename → fsync 目录)。无效状态会直接中止启动,而不是猜测该启动哪个运行时。

5.3 数据库回滚(Database rollback)

旧子进程退出后,launcher 会为 SQLite 的三个文件(主文件、-wal-shm)各做一次快照。这样 trial 期间的数据库迁移就是可逆的,无需编写 down 迁移。快照每个更新只做一次(backupDatabaseOnce),且可跨 launcher 重启存活——重试时不会覆盖,以免捕获失败 trial 产生的脏数据。

回滚时先写.restore-pending标记再恢复,确保中断的恢复能在任一版本启动前完成。快照会保留到提交完成(或恢复与终态回滚都持久化)为止。SQLite 之外的附件等文件不在回滚边界内——这也呼应了更新前应完成手头工作的建议。

5.4 客户端确认(Client acknowledgement)

被接受的更新仍是"pending"状态。客户端在重连后,将 launcher 的 update ID 与 ready 事件关联,再核对结果与目标版本。仅凭重连无法区分"替换成功"与"回滚"——因此界面要求你保持客户端打开直到重连或报错。旧版服务器没有 update ID,只能退化为仅按版本关联。

桌面端更新另有独立的两阶段交接(two-phase handoff):安装桌面应用会停止其内嵌的后端,因此准备阶段在连接存活时返回 token,客户端收到后才提交该 token——否则后端关闭可能丢失唯一的成功 RPC 结果。安装失败时,桌面端会重启已停止的后端,并为同一 token 重放失败。

六、如果更新失败怎么办

保持客户端打开,直到它重连或报告失败。服务更新失败时可以回滚到上一版本。若仍然失败,按以下顺序排查:

  1. 重试一次界面提供的动作;
  2. 确认更新的是服务器的机器,而不只是你正在使用的设备——这是最常被忽略的一步;
  3. 对于命令行服务器:停止它,然后用提示中显示的精确版本重新启动,例如npx t3@<exact-version> serve

后台服务相关的故障排查,可先运行t3 service status查看日志路径与状态问题(如linger-disabledservice-disabledservice-stopped等),具体处理方式见 background services 的 Troubleshooting 章节;T3 Connect 登录后的连接故障,参见 remote-access.md。

七、移动端更新

移动端走常规渠道:按 App Store 或 Google Play 的惯例安装发行版更新即可。T3 Code 移动应用还支持后台下载更新并在下次离开应用时应用

  • 重启前会先保存草稿(drafts)与排队消息(queued messages),避免更新造成状态丢失;
  • 如果你长时间保持应用在前台,它可能会询问是否立即安装;选择Later会将更新排队,留待下一个合适的时机(下次进入后台时)自动安装。

移动端的这一机制实现在 apps/mobile/src/features/updates/app-updates.ts 中,基于 expo-updates:

  • 默认applyMode: "background":更新下载完成后,在下一次进入后台时静默安装(onNextBackground触发applyDeferredAppUpdateInstall)。之所以选后台时机,是因为"重启过程中原生界面仍挂载"是 expo-updates 最易崩溃的时刻——后台没有渲染内容,拆除过程对用户不可见;
  • 重启前调用flushPendingWrites落盘 composer 草稿与 thread outbox,写失败时自动更新会中止(flush-failed),而不是冒着丢失未保存状态的风险重启;
  • 前台停留超过 30 分钟(DEFERRED_INSTALL_PROMPT_AFTER_MS = 30 * 60 * 1000)仍无后台机会时,弹出确认框询问立即安装还是稍后(对应界面中的Install Now / Later);选择 Later 保持后台安装挂起;
  • 回滚指令(eas update:rollback)会绕过提示与延迟,立即应用,以尽快拉回损坏的 bundle;
  • 应用常驻内存数天,仅启动时检查不够,因此每次前台恢复且距上次后台超过 15 分钟(FOREGROUND_APP_UPDATE_RECHECK_AFTER_MS)时会重新检查。

八、更新流程速查

场景操作
提示指向后台服务在宿主机运行npx t3@<client-version> service update
提示指向桌面应用在运行服务器的机器更新桌面应用,必要时重新打开
提示给出复制命令停止前台 CLI 服务器,用复制命令(含serve--host等选项)重启
更新前保护会话开启 Settings → General → Continue threads after restarts,先更新旧服务器
更新失败重试一次 → 确认更新的是服务器机器 → 用精确版本重启命令行服务器
移动端商店常规更新;应用内可后台下载、离开应用时自动安装,Later排队
自包含构建升级宿主机上t3 update(可加--channel--yes--allow-downgrade

一句话总结:先看提示指向哪台机器,再按其服务器运行形态(后台服务 / 桌面应用 / 前台 CLI)选择对应动作;保持客户端打开直到重连确认,更新失败时优先检查"是否更新对了机器"。更底层的服务生命周期管理,可继续阅读 background services 与 server updates 内部机制。

【免费下载链接】t3code项目地址: https://gitcode.com/GitHub_Trending/t3/t3code

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询