分叉 Session

从完整历史或指定 Message 创建可独立继续执行的新 Session

session.fork() 从当前 Session 的历史创建一个独立的新 Session。分叉后的后续输入、模型执行、工具状态与审批都彼此隔离。

const full_branch = await session.fork();

const branch_at_message = await session.fork({
  message_id: "assistant:repo-analysis:abc",
});

也可以直接传入 message_id 字符串:

const branch = await session.fork("assistant:repo-analysis:abc");

原地替换历史

传入 replace: true 会直接截断当前 Session 的历史并返回当前实例,保留 Session ID、配置及保留消息的身份,不创建分支、不归档,也不写入操作记录。

await session.fork({
  message_id: "user:question:abc",
  include_message: false,
  replace: true,
});
await session.prompt({ query: "修改后的问题" });

include_message 默认 true;设为 false 时同时移除锚点消息。后续历史会被永久删除,关联的上下文摘要也同步清理。未指定 message_id 时历史保持原样。Session 正在执行或有排队命令时拒绝替换。

订阅方会收到 variant: "session"、type: "truncate" 的同步事件,通过 through_sequence 移除后续消息;该事件不应显示为时间线操作记录。本地与远程 Session 均支持此参数。

历史边界

调用复制范围
fork()当前可见历史的完整状态
fork({ message_id })从开头复制到该 Message,包含该 Message
fork({ message_id, include_message: false })从开头复制到该 Message 之前

分叉点是顶层 Message,不是 Assistant 内的 part_id。如果需要在工具调用前后试验不同方向,先在 messages() 中找到对应 Assistant Message 的 message_id。

来源与顺序

复制进新 Session 的 Message 保留新的 Session 身份和新的线性顺序,同时可携带 origin,记录来源的 session_id、message_id 与 turn_id。这使分叉可追溯,但分叉后两个 Session 不共享可变状态。

分叉成功后,新 Session 时间线末尾会记录一条 history-fork Action,说明这段历史的来源。源 Session 不会留下任何分叉记录。

不要把分叉理解为“两个窗口共同编辑一份历史”。源 Session 的后续 Message 不会自动出现到分叉中,分叉的后续 Message 也不会回写源 Session。

适合的场景

  • 在保留主线结论的前提下比较两种实现方案。
  • 从某一条用户输入重新提问,避免后续上下文干扰。
  • 为长任务建立实验支线,而不污染主会话。

分叉后按普通 Session 使用:加载 messages()、建立 subscribe(),然后调用 prompt()。不需要复制 Mutation,也不应该复制源 Session 的 pending approval。