管理 Session

创建、打开、列表、归档和永久清理 Session

agent.sessions 是本地 Session 集合入口。Session 在创建时可以选择一个 Workspace 作为初始目录,之后可以在会话中切换。

创建与打开

const created = await agent.sessions.create({
  workspace,
});

const task_session = await agent.sessions.create({
  workspace,
  origin: { type: "task", task_id: "daily-report" },
});

const existing = await agent.sessions.get("session-id-from-list", "work");
const existing_task = await agent.sessions.get(task_session.id, "task");

create() 始终由 SDK 内部生成 Session ID。恢复已有 Session 时,从 list() 或其他持久化引用 取得 ID,再调用 get(session_id, origin_type = "work")。origin.type 可以是任意 非空字符串,并可携带额外 JSON 元数据;get() 只读取指定分区,不会扫描其他来源。

Workspace 是会话的当前目录,不是会话身份。它是 Session 的持久化配置字段,与 model 同属 set():

const session = await agent.sessions.create({ workspace: repo_a });

await session.set({ workspace: repo_b });   // 带旧消息换到另一个仓库,session_id 不变
await session.set({ workspace: null });     // 脱离项目上下文

落盘的是 workspace_id,实例由宿主持有;恢复时由宿主解析实例并通过 get(..., { workspace }) 注入。 get() 传入的 Workspace 与持久化值不同时也不会报错,而是成为该会话新的当前目录:

const reopened = await agent.sessions.get(session.id, "work", { workspace: repo_c });

切换目录不迁移已有消息、附件与工具结果;它们属于发生时的目录。正在执行的 Turn 沿用旧目录, 从下一个 Step 检查点起生效。没有 Workspace 的 Session 是合法的:它没有文件工具与 Shell, 但纯模型对话仍然可用。

Agent 自己的会话

Agent 自己就是一条 Session,用 agent.session() 取用,它的 session_id 等于 Agent 的 id,角色为 origin.type = "agent"。它不会出现在默认的 work 分区列表里。详见 Agent 会话。

监听新会话

本地宿主可通过 agent.sessions.on_created() 监听新会话,包括 session_start 创建的 work 会话和首次创建的 Agent 主会话:

const unsubscribe_created = agent.sessions.on_created(async (session) => {
  session.subscribe((mutation) => publish_mutation(session.id, mutation));
  publish_session(await session.get_info());
});

// 宿主退出或替换 Agent 时释放订阅。
unsubscribe_created();

通知在会话初始化完成后触发,SDK 等待监听器完成再返回创建结果,因此宿主可以在首次 prompt() 前建立消息和运行态订阅。恢复已有会话不会触发;监听器失败会记录日志,不会撤销已持久化的会话。它是进程内通知,初始目录仍需通过 list() 加载。

Desktop 会把新建的 work 会话自动加入 Works 中对应的 Workspace,并接收后续标题、消息和执行状态更新。

列表与搜索

const page = await agent.sessions.list({
  origin_type: "work",
  limit: 30,
  query: "repo",
});

for (const item of page.items) {
  render_session_row(item);
}

if (page.has_more) {
  const next_page = await agent.sessions.list({
    limit: 30,
    cursor: page.next_cursor,
    query: "repo",
    origin_type: "work",
  });
}

list() 默认只查询 work 分区;查询其他来源时传入 origin_type。列表项是轻量摘要,不包含完整 Message。常用字段为 session_id、origin、title、preview_text、message_count、model_label、updated_at 与 executing。cursor 是透明游标,只能原样传回 SDK。

query 用于轻量包含匹配,适合侧边栏筛选;不要把它当作全文检索语法。

归档与清理

await agent.sessions.archive({ id: "repo-analysis", origin_type: "task" });

const archived_page = await agent.sessions.archived({ origin_type: "task", limit: 30 });

const removed = await agent.sessions.clean_archive();
console.log(removed.removed_session_ids);

归档会把 Session 从活跃列表移走,但不会立即永久删除。正在执行的 Session 不能归档,先等待 Turn 完成或调用 stop()。

clean_archive() 会永久删除所有已归档 Session,适合明确的“清空回收站”操作;UI 必须在调用前要求用户确认。

本地维护还可以使用 remove(session_id, origin_type = "work") 永久删除一个活跃 Session 的 Agent 数据,或使用 clear_messages(session_id, origin_type = "work") 只清空消息。Power 自有数据不会被隐式删除;需要同时清理领域数据时,应调用对应 Power。

UI 建议

  1. 列表页只用 list() 的摘要数据。
  2. 用户选中后调用 get(),再加载 messages()。
  3. 对 executing: true 的条目显示运行状态;不要仅根据最后更新时间猜测。
  4. 归档成功后从当前活跃列表移除该项,并重新读取归档列表。

Session 列表的标题可能为空。展示层应回退到 session_id 或产品定义的占位标题。