Skip to content

核心类:Project / Thread / Turn

最新版代码里,最核心的三个对象不是按平台拆分,而是按协作主轴拆分:

  • Project 负责聚合根和项目级配置
  • Thread 负责一次持续协作会话
  • Turn 负责线程中的单次执行

这三个对象共同构成系统的最小稳定骨架。

Project Thread Turn 关系图占位图

Placeholder:在这里插入 Project / Thread / Turn 关系图,建议额外标出 UserThreadBindingRuntimeConfig

三者关系

1. Project

Project 在代码里的落点主要是两种投影:

类型位置作用
ProjectConfigservices/admin-api/src/admin-state.ts持久化项目配置,是真正的项目聚合根
ProjectContextRecordservices/orchestrator/src/project-resolver.tsorchestrator 视角下的项目上下文投影

Project 的职责

职责说明
聚合根thread / turn / snapshot / user-thread-binding 最终都归属到 projectId
平台绑定chatId 只是 Project 的 1:1 平台绑定
运行时默认配置保存 cwddefaultBranchsandboxapprovalPolicy 等项目级配置
路由起点所有 IM 入口先做 chatId -> projectId 解引用

Project 的关键字段

字段说明
idprojectId,系统内部主键
chatIdIM 平台绑定,不是 thread/turn 的真实持久化主键
cwd项目工作目录
defaultBranch默认分支
sandboxsandbox 策略
approvalPolicy审批策略
status项目启用状态

Project 的不变式

  • Project 是聚合根,不能用 chatId 直接替代 projectId
  • 线程历史不跟随群聊迁移;重新绑群时只更新 Project 与 Chat 的绑定
  • orchestrator 进入领域逻辑前,必须先经 ProjectResolver.findProjectByChatId(chatId)

2. Thread

Thread 在代码中由 ThreadRecord 表示,定义位于 services/orchestrator/src/thread-state/thread-registry.ts

Thread 的职责

职责说明
协作主轴表示一个持续存在的分支/会话/任务线
绑定后端身份保存 BackendIdentity,决定该线程走哪个 backend
绑定后端会话句柄threadId 是后端分配的 opaque handle
承接 turn 序列一个 thread 下会持续生成多个 turn

Thread 的关键字段

字段说明
projectId所属项目
threadName项目内逻辑线程名
threadId后端线程 ID / 会话 ID
backend不可拆分的 BackendIdentity

Thread 的不变式

  • ThreadRecord.backend 是线程后端身份的唯一真实来源
  • backend 信息必须原子传递,不能拆成 model + transport + backendName
  • 线程创建后 backend 身份不可修改
  • UserThreadBinding 只能指向 thread,不能复制 backend 元数据

3. Turn

Turn 在代码中由 TurnRecord 表示,定义位于 services/orchestrator/src/turn-state/turn-record.ts

Turn 的职责

职责说明
单次执行单元表示用户发起的一次 agent 执行
串联流式状态承接运行中、待审批、完成、失败等状态变化
记录执行结果保存 diff、token usage、最后一条 agent 消息、完成时间等
提供审计基础是 snapshot、审批、恢复、历史查询的主索引之一

Turn 的关键字段

字段说明
projectId所属项目
threadName / threadId所属线程
turnId本次执行 ID
statusrunning / awaiting_approval / completed / accepted / reverted / interrupted / failed
cwd本次执行工作目录
approvalRequired是否进入审批
filesChanged / diffSummary变更摘要
tokenUsagetoken 消耗
createdAt / updatedAt / completedAt生命周期时间点

Turn 的不变式

  • Turn 永远挂在 Thread 之下,不直接挂在 Chat 之下
  • turn 查询、恢复、快照都应以 projectId 为持久化归属
  • turn 状态推进通过 orchestrator 和事件管线完成,不能绕过主路径直接写平台层

核心数据流

text
IM Event
  -> chatId
  -> ProjectResolver.findProjectByChatId(chatId)
  -> projectId
  -> ThreadRegistry.get(projectId, threadName)
  -> ThreadRecord.backend / ThreadRecord.threadId
  -> 创建或恢复 TurnRecord
  -> backend 执行与事件回写
ts
const project = projectResolver.findProjectByChatId(chatId);
const thread = threadRegistry.get(project.id, threadName);

为什么这三个对象最核心

对象没有它会发生什么
Project无法确定聚合根,chatId 会重新污染持久化主键
Thread无法稳定绑定 backend 身份和会话恢复
Turn无法承载单次执行、审批状态和历史审计

与其他对象的关系

对象与三大核心类的关系
BackendIdentityThread 的不可变后端身份值对象
UserThreadBinding用户维度的 thread 指针,不属于核心聚合根
RuntimeConfig每个 turn 执行前临时组装,来源于 Project + Thread
UnifiedAgentEventTurn 执行中在 Path B 上传播的统一事件模型