feat(subagent): name subagents in their creator catalog

Models coordinate subagents through send_message, interrupt_agent, list_agents,
and Team task owners, but every one of those addressed a member by a
36-character Session id. Each new child now has a name, unique among its
creator's children, recorded as a field of the subagent/catalog entry the
creator already appends (payload version 3).

The Session id stays the only execution identity for routing, authorization,
persistence, task ownership, and navigation. A name is a model-facing
reference: 1-32 lower-case letters, digits, or hyphens starting with a letter,
never `lead`, so a UUID never parses as one. Omission selects the first free
`agent-N`; an explicit duplicate or invalid name fails before startup. The
creator reserves the name synchronously at admission and releases it when the
catalog entry commits or startup fails, so no second write, rollback protocol,
or optional naming service exists.

The root is `lead`, and a descendant's full name is its path from the root
without a `lead/` prefix, such as `reviewer/checker`. Sibling-unique segments
make full names tree-unique without a root registry, and cold resume rebuilds
a member's path from the catalogs along its creation chain. A member below an
unnamed historical creator keeps its Session id as its name. resolveName()
reads only the catalogs along the path and grants no authority.

Tools, runtime-authored text, and the Web client consume names: delegation
takes an optional name and returns { kind, subagentId, name }; send_message and
interrupt_agent take `agent`; list_agents rows carry name, status, and
description; Team task results report the owner's name while storage keeps
ownerId; identity runtime context, message framing, and settlement notices use
full names. Recorded sessions, CLI and Web expectations, the Python runtime
snapshots, bilingual docs, an upgrade guide, and an Agent Note follow.
This commit is contained in:
Dudu-0223
2026-11-02 14:58:32 +08:00
parent a2119d6184
commit ff563d07e0
581 changed files with 4677 additions and 2745 deletions
@@ -15,11 +15,11 @@
en: 62284bd7dd804188
zh: b3a8dfebffc01bdb
/agent-note-adjacent-agents-share-one-steer-send-message-operation/decision/complete-removal-and-reintroduction-condition:
en: 8c6d355d91ec83d2
zh: fcc74d1e6ef477bf
en: 8cd78e21602f17f0
zh: 3843fea07e9b93a3
/agent-note-adjacent-agents-share-one-steer-send-message-operation/alternatives-considered:
en: 7386e88e7051dce7
zh: dcea5b9e30374be3
/agent-note-adjacent-agents-share-one-steer-send-message-operation/consequences:
en: 9c23dd6ace029ec3
zh: f08ef3f142534843
en: 22a3af4c51aee23e
zh: 9d59315313d0f761
@@ -40,7 +40,7 @@ The globally registered model tool is direction-neutral and has one fixed schema
```ts
interface SendMessageInput {
readonly agent_id: string
readonly agent: string
readonly message: string
}
```
@@ -53,7 +53,7 @@ Human browser prompts are not model-authored Agent messages. The remote prompt p
### Complete removal and reintroduction condition
The standalone `@deepseek-ai/dsh-tool-subagent-report` package, `report` schema, `tool:report` prompt section, `reportDelivery` configuration, report-specific message source, catalog entries, composition rows, and supported-behavior snapshots are absent. The unified tool gives up the recipient-free child shortcut and the old ability for a structural return tool to survive an explicit child allow-list. Those capabilities return only if a concrete use case requires semantics that a tree member’s `agent_id` and fixed Steer cannot express; reintroducing them requires a distinct model operation and prefix-cost evidence, not an alias over `sendMessage()`.
The standalone `@deepseek-ai/dsh-tool-subagent-report` package, `report` schema, `tool:report` prompt section, `reportDelivery` configuration, report-specific message source, catalog entries, composition rows, and supported-behavior snapshots are absent. The unified tool gives up the recipient-free child shortcut and the old ability for a structural return tool to survive an explicit child allow-list. Those capabilities return only if a concrete use case requires semantics that a tree member’s `agent` reference and fixed Steer cannot express; reintroducing them requires a distinct model operation and prefix-cost evidence, not an alias over `sendMessage()`.
## Alternatives considered
@@ -71,7 +71,7 @@ The standalone `@deepseek-ai/dsh-tool-subagent-report` package, `report` schema,
## Consequences
- Model consumers expose one `send_message({ agent_id, message })` definition to parents and children, with no model-selected Queue versus Steer parameter.
- Model consumers expose one `send_message({ agent, message })` definition to parents and children, with no model-selected Queue versus Steer parameter.
- The continuation manager remains the sole owner of tree authorization, residency, cold resume, waking admission, and teardown races.
- Accepted messages may extend a running target's current turn; messages waiting together share next-step FIFO ordering.
- Caller cancellation owns work only until inbox acceptance and does not retract an accepted message or dispose the target.
@@ -40,7 +40,7 @@ interface AgentMessageSource {
```ts
interface SendMessageInput {
readonly agent_id: string
readonly agent: string
readonly message: string
}
```
@@ -53,7 +53,7 @@ parent 与 child 以相同注册表顺序继承相同定义。标准定义携带
### 完整移除与重新引入条件
独立的 `@deepseek-ai/dsh-tool-subagent-report` 包、`report` schema、`tool:report` 提示词 section、`reportDelivery` 配置、report 专属消息来源、目录项、组合行和受支持行为快照均已不存在。统一工具放弃了无需接收方的 child 快捷方式,也放弃了让结构性返回工具绕过显式 child allow-list 的旧能力。只有具体用例需要树成员的 `agent_id` 与固定 Steer 无法表达的语义时,这些能力才会重新出现;重新引入需要独立的模型操作与前缀成本证据,而非 `sendMessage()` 之上的别名。
独立的 `@deepseek-ai/dsh-tool-subagent-report` 包、`report` schema、`tool:report` 提示词 section、`reportDelivery` 配置、report 专属消息来源、目录项、组合行和受支持行为快照均已不存在。统一工具放弃了无需接收方的 child 快捷方式,也放弃了让结构性返回工具绕过显式 child allow-list 的旧能力。只有具体用例需要树成员的 `agent` 引用与固定 Steer 无法表达的语义时,这些能力才会重新出现;重新引入需要独立的模型操作与前缀成本证据,而非 `sendMessage()` 之上的别名。
## 考虑过的替代方案
@@ -71,7 +71,7 @@ parent 与 child 以相同注册表顺序继承相同定义。标准定义携带
## 后果
- 模型 Consumer 向 parent 与 child 公开一个 `send_message({ agent_id, message })` 定义,不提供模型选择的 Queue 与 Steer 参数。
- 模型 Consumer 向 parent 与 child 公开一个 `send_message({ agent, message })` 定义,不提供模型选择的 Queue 与 Steer 参数。
- 继续执行管理器仍是整树授权、驻留、冷恢复、唤醒准入与拆卸竞态的唯一所有者。
- 被接受的消息可以延长运行中目标的当前轮次;一起等待的消息共享 next-step FIFO 顺序。
- 调用方取消只在 inbox 接受前掌管工作,不会撤回已接受消息或 dispose(资源释放)目标。
@@ -9,8 +9,8 @@
en: 5a991fec31578cea
zh: 13b75aa36eb22907
/agent-note-parent-owned-subagent-catalog-events/decision:
en: 4319c502038ab34d
zh: b11825ff9d744822
en: d2290d8e70d42054
zh: 64a2d1d0915f6c3e
/agent-note-parent-owned-subagent-catalog-events/alternatives-considered:
en: 7a3d4b9f69c243d8
zh: 82b03d16ccc94dd2
@@ -14,7 +14,7 @@ The child descriptor remains necessary for recovery and composition, but it cann
The shared activation entry point, external execution ownership, and caller-versus-parent result delivery are governed by [Unified subagent activations](../simplification/2026-09-17-unified-subagent-activations.md). This record retains the independent rationale described below.
The parent Session's required `subagent/catalog` events are the persistent authority for direct-child discovery. Every local child enters the catalog independently of its result recipient; external children enter only with parent delivery. Workflow membership records describe execution progress and do not replace local Session discovery. Each event contains `childId`, `childCreatedAt`, mode, and the mode-discriminated label. Local children use `continuable`; external executions use `external` and cannot be opened as local Sessions. Historical `one-shot` and `unknown` entries remain readable. Invalid own facts, including unsupported payload versions, reject projection restoration because silently dropping a required fact would return an incomplete catalog.
The parent Session's required `subagent/catalog` events are the persistent authority for direct-child discovery. Every local child enters the catalog independently of its result recipient; external children enter only with parent delivery. Workflow membership records describe execution progress and do not replace local Session discovery. Each event contains `childId`, `childCreatedAt`, mode, the mode-discriminated label, and, from payload v3, the child's [name](2026-11-02-subagent-catalog-names.md). Local children use `continuable`; external executions use `external` and cannot be opened as local Sessions. Historical `one-shot` and `unknown` entries remain readable. Invalid own facts, including unsupported payload versions, reject projection restoration because silently dropping a required fact would return an incomplete catalog.
Creation publishes only successful facts. A local activation admits the initial prompt before appending its catalog event. An external activation appends its event after provider startup and before returning the receipt. Failed admission or publication releases the unpublished execution; there is no compensating catalog event or rollback protocol.
@@ -22,7 +22,7 @@ The child header and `subagent/descriptor` remain authoritative for recovery and
The registered `subagentCatalog` projection materializes the parent facts. It delegates storage, append, iteration, and checkpoint validation to [`dsh-chunked-list`](../../../../packages/util/chunked-list/README.md), which stores facts in a persistent stack of 64-entry chunks, so an append copies at most the head chunk in bounded O(1) work. Materialization visits chunks from oldest to newest and preserves parent catalog event order in O(D) time for D facts. Concurrent creation is ordered by successful catalog append, independent of child timestamps and ids. A projection checkpoint clones the state once in O(D); projection-cache writes remain asynchronous and use the existing mandatory creation, turn-end, and disposal points.
The utility owns chunk layout and its shared capacity constant; the catalog owns event validation, fork filtering, and row conversion. Catalog projection state version 6 accepts external membership, so the projection registry rebuilds incompatible caches from Session events. Payload v0 and v1 remain unchanged; v2 records external executions.
The utility owns chunk layout and its shared capacity constant; the catalog owns event validation, fork filtering, and row conversion. Catalog projection state version 7 accepts external membership and child names, so the projection registry rebuilds incompatible caches from Session events. Payload v0 and v1 remain unchanged; v2 records external executions; v3 adds names to continuable and external entries.
Fork isolation uses the exact `Session.inheritedEventCount` supplied to projection initialization. The fold ignores `subagent/catalog` events below that offset. The state stores the inherited offset but not each event seq because acceptance is decided during folding.
@@ -14,7 +14,7 @@ child descriptor 对恢复与 composition 仍然必要,但它不能作为 disc
共享 activation 入口、外部执行所有权,以及调用方与父级之间的结果投递选择由[统一 subagent activation](../simplification/2026-09-17-unified-subagent-activations.zh.md) 决策拥有。本记录保留下述独立理由。
父级 Session 的必读 `subagent/catalog` 事件是发现直接子级的持久化权威。每个本地子级都会进入目录,与结果接收方无关;外部子级仅在 parent 投递时进入目录。工作流成员记录描述执行进度,不替代本地 Session 发现。每个事件包含 `childId`、`childCreatedAt`、mode 与按 mode 区分的 label。本地子级使用 `continuable`;外部执行使用 `external`,不能作为本地 Session 打开。历史 `one-shot` 与 `unknown` 条目仍可读取。无效的自身事实(包括不支持的载荷版本)会使投影恢复失败,因为静默丢弃必读事实将返回不完整的 catalog。
父级 Session 的必读 `subagent/catalog` 事件是发现直接子级的持久化权威。每个本地子级都会进入目录,与结果接收方无关;外部子级仅在 parent 投递时进入目录。工作流成员记录描述执行进度,不替代本地 Session 发现。每个事件包含 `childId`、`childCreatedAt`、mode、按 mode 区分的 label,以及从载荷 v3 起的子级[名称](2026-11-02-subagent-catalog-names.zh.md)。本地子级使用 `continuable`;外部执行使用 `external`,不能作为本地 Session 打开。历史 `one-shot` 与 `unknown` 条目仍可读取。无效的自身事实(包括不支持的载荷版本)会使投影恢复失败,因为静默丢弃必读事实将返回不完整的 catalog。
创建只发布成功事实。本地 activation 先接纳初始提示词,再追加 catalog 事件。外部 activation 在提供方启动后、返回回执前追加事件。准入或发布失败会释放未发布的执行;不存在补偿 catalog 事件或回滚协议。
@@ -22,7 +22,7 @@ child header 与 `subagent/descriptor` 继续拥有恢复与 composition 权威
注册的 `subagentCatalog` projection 物化 parent fact。它将存储、追加、迭代和检查点校验交给 [`dsh-chunked-list`](../../../../packages/util/chunked-list/README.zh.md),后者以每块 64 项的持久 stack 保存事实,因此 append 最多复制 head chunk,以有界 O(1) 工作完成。materialization 从旧到新访问 chunk,对 D 条事实以 O(D) 时间保留父目录事件顺序。并发创建按目录成功追加的顺序排列,与 child 时间戳和 id 无关。projection checkpoint 以 O(D) 克隆 state;projection-cache 继续异步写入,并使用既有创建、turn-end 与 disposal 强制点。
工具库拥有 chunk 布局与共享容量常量;catalog 拥有事件校验、fork 过滤和行转换。catalog 投影状态版本 6 接受外部成员,因此投影注册表会从 Session 事件重建不兼容缓存。载荷 v0 与 v1 保持不变;v2 记录外部执行。
工具库拥有 chunk 布局与共享容量常量;catalog 拥有事件校验、fork 过滤和行转换。catalog 投影状态版本 7 接受外部成员和子级名称,因此投影注册表会从 Session 事件重建不兼容缓存。载荷 v0 与 v1 保持不变;v2 记录外部执行;v3 为可继续和外部条目增加名称。
fork 隔离使用 projection 初始化时提供的精确 `Session.inheritedEventCount`。fold 忽略该 offset 之前的 `subagent/catalog` 事件。state 保存 inherited offset,但不保存每条 event seq,因为接受判定已在 fold 时完成。
@@ -3,8 +3,8 @@
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-10-13-team-identity-runtime-context.md
/agent-note-subagent-identity-in-required-runtime-context:
en: ce8f378b6e7b57fa
zh: 26bd0415b4dba94a
en: 3da6e33c5dc2c917
zh: 9c8d4542cda63fc4
/agent-note-subagent-identity-in-required-runtime-context/problem:
en: f944254565541454
zh: 27fa9f67c671dec7
@@ -4,6 +4,8 @@ Status: implemented
English | [中文](2026-10-13-team-identity-runtime-context.zh.md)
[Catalog names](2026-11-02-subagent-catalog-names.md) supersede the Session-id identity text below: agents see their own, direct parent, and root names. The runtime-context retention decision remains active.
## Problem
A teammate identity embedded in its initial task depends on ordinary history retention. Compaction can remove it, and an ordinary fork from that teammate can retain the old role even though the fork is an independent Lead. Identity must reflect the current subagent tree while keeping shared system instructions uniform.
@@ -4,6 +4,8 @@ Status: implemented
[English](2026-10-13-team-identity-runtime-context.md) | 中文
[目录名称](2026-11-02-subagent-catalog-names.zh.md)取代下文以 Session id 表述身份的文本:agent 看到自身、直接父级和根的名称。runtime context 保留决策仍然有效。
## Problem
嵌入初始任务的 teammate 身份依赖普通历史保留。压缩可能移除它;从 teammate 创建的普通 fork 即使已成为独立 Lead,也可能保留旧角色。身份必须反映当前 subagent 树,同时保持共享系统指令一致。
@@ -3,8 +3,8 @@
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-10-15-agent-teams-as-subagents.md
/agent-note-agent-teams-teammates-are-subagents:
en: 51e2fc51a6e1622a
zh: 7e09ea6292e5921d
en: f49f9e7ef588e612
zh: 7da804056221af51
/agent-note-agent-teams-teammates-are-subagents/problem:
en: ca2848e3bbc3a009
zh: 0551e32ff6d187d0
@@ -4,7 +4,7 @@ Status: implemented
English | [中文](2026-10-15-agent-teams-as-subagents.zh.md)
The adjacency and parent-lifetime restrictions are superseded by [tree-wide communication](2026-10-16-tree-wide-agent-communication.md). [Task-board inbox coordination](2026-10-19-team-task-board-inbox.md) supersedes the separate roster and Team-owned wait; the single subagent identity decision remains active.
The adjacency and parent-lifetime restrictions are superseded by [tree-wide communication](2026-10-16-tree-wide-agent-communication.md). [Task-board inbox coordination](2026-10-19-team-task-board-inbox.md) supersedes the separate roster and Team-owned wait; the single subagent identity decision remains active. [Catalog names](2026-11-02-subagent-catalog-names.md) supersede the statement that creation accepts no member name and the rejection of unique names below.
## Problem
@@ -4,7 +4,7 @@ Status: implemented
[English](2026-10-15-agent-teams-as-subagents.md) | 中文
邻接和父级生命周期限制由[整树通信](2026-10-16-tree-wide-agent-communication.zh.md)取代。[任务板收件箱协调](2026-10-19-team-task-board-inbox.zh.md)取代独立名册和 Team 所有的等待;单一 subagent 身份决策仍有效。
邻接和父级生命周期限制由[整树通信](2026-10-16-tree-wide-agent-communication.zh.md)取代。[任务板收件箱协调](2026-10-19-team-task-board-inbox.zh.md)取代独立名册和 Team 所有的等待;单一 subagent 身份决策仍有效。[目录名称](2026-11-02-subagent-catalog-names.zh.md)取代下文“创建不接收成员名称”的表述及对唯一名称的否决。
## Problem
@@ -9,8 +9,8 @@
en: c583c3cdb894e417
zh: 6edc0354b79f4f26
/agent-note-communication-follows-the-subagent-tree/decision:
en: da35a75e069fa1e4
zh: 7edf62ad66ab04ec
en: 767b4b4dfd84f72e
zh: 36617ec0dab777ee
/agent-note-communication-follows-the-subagent-tree/alternatives-considered:
en: 470f9cf8c3e32af9
zh: 73bbe29767c5d02a
@@ -10,13 +10,13 @@ A Team shares one task board across the root's entire subagent tree. Restricting
## Decision
`list_agents` starts at the caller's live root and lists that root and all reachable continuable descendants, including the caller. Parent ids and depth remain relative to the root. The existing parent catalogs remain authoritative; no Team directory is stored separately.
`list_agents` starts at the caller's live root and lists that root and all reachable continuable descendants, including the caller. Full names remain relative to the root. The existing parent catalogs remain authoritative; no Team directory is stored separately.
`send_message` accepts another root or continuable member of the same tree. The sender must be the exact live root or a resident continuable subagent. Cross-branch delivery verifies the target descriptor and creation catalogs, then restores only the target under the Team root. Final inbox admission rechecks the sender and root. Cancellation or rejection before acceptance releases the new target instance; accepted input follows normal Agent persistence.
The existing Agent registry records runtime ownership by the Team root. Creation parent ids and catalogs preserve ancestry for discovery and interrupt authority. A member finishing or being released affects only its own instance; Team-root shutdown joins all startup and cleanup. This removes ancestor restoration, parent retention, and recursive disposal without adding a Team runtime registry. Saved target presets and permission events supply restoration configuration.
This supersedes the adjacency, discovery, and parent-lifetime restrictions in [adjacent messaging](2026-08-27-adjacent-agent-steer-messaging.md) and [subagent teammates](2026-10-15-agent-teams-as-subagents.md). Their shared inbox, scheduling, attribution, and Team reuse decisions remain active. Members use Session ids for addressing; ordinary Session forks lead independent Teams.
This supersedes the adjacency, discovery, and parent-lifetime restrictions in [adjacent messaging](2026-08-27-adjacent-agent-steer-messaging.md) and [subagent teammates](2026-10-15-agent-teams-as-subagents.md). Their shared inbox, scheduling, attribution, and Team reuse decisions remain active. Members address one another by the names that [catalog names](2026-11-02-subagent-catalog-names.md) define, or by Session id; ordinary Session forks lead independent Teams.
## Alternatives considered
@@ -10,13 +10,13 @@ Status: implemented
## Decision
`list_agents` 从调用方的在线根开始,列出该根与所有可达的可继续后代,包括调用方。父级 id 和深度始终相对根计算。现有父级目录仍是权威来源;不单独存储 Team 目录。
`list_agents` 从调用方的在线根开始,列出该根与所有可达的可继续后代,包括调用方。完整名称始终相对根计算。现有父级目录仍是权威来源;不单独存储 Team 目录。
`send_message` 接受同一棵树中的其他根或可继续成员。发送者必须是确切在线根或驻留的可继续子代理。跨分支投递验证目标描述符和创建目录后,仅在 Team 根下恢复目标。最终收件箱准入重新检查发送者与根。接受前的取消或拒绝释放新建目标实例;已接受输入遵循普通 Agent 持久化。
现有 Agent 注册表记录 Team 根对运行时实例的所有权。创建父级 id 和目录保留用于发现及中断授权的祖先关系。成员完成或释放只影响自身实例;关闭 Team 根会等待全部启动和清理。这删除了祖先恢复、父级保留和递归释放,无需增加 Team 运行时注册表。目标保存的 preset 和权限事件提供恢复配置。
本决策替代[相邻消息](2026-08-27-adjacent-agent-steer-messaging.zh.md)与[子代理队友](2026-10-15-agent-teams-as-subagents.zh.md)中的邻接、发现及父子生命周期限制。它们的共享收件箱、调度、发送者归属和 Team 复用决策仍有效。成员使用 Session id 寻址;普通 Session 分叉领导独立 Team。
本决策替代[相邻消息](2026-08-27-adjacent-agent-steer-messaging.zh.md)与[子代理队友](2026-10-15-agent-teams-as-subagents.zh.md)中的邻接、发现及父子生命周期限制。它们的共享收件箱、调度、发送者归属和 Team 复用决策仍有效。成员使用[目录名称](2026-11-02-subagent-catalog-names.zh.md)定义的名称或 Session id 互相寻址;普通 Session 分叉领导独立 Team。
## Alternatives considered
@@ -9,8 +9,8 @@
en: ac391b569d2bc7e9
zh: a95f613aa2b330b8
/agent-note-subagent-tools-own-communication-guidance/decision:
en: 52fb33963bedfe07
zh: 75fe66d80f47323f
en: d83310e85ffcb3cf
zh: eb1f069948399d93
/agent-note-subagent-tools-own-communication-guidance/alternatives-considered:
en: c55d44c6414e0c4c
zh: 9fa2ab31843e259b
@@ -10,7 +10,7 @@ The continuation manager inspected a Symbol on the standard messaging tool befor
## Decision
`tool-subagent-control` owns messaging instructions and parent addressing. Its logged runtime context gives delegated children their direct creator’s id from the Session header, explains when to send findings, and states that sending does not finish a turn. The context is emitted only for delegated children when the plugin’s own tool definition is admitted in the current scope and step; roots and ordinary Session forks receive none. Communication guidance follows inherited history without changing the shared system prompt or tool schema.
`tool-subagent-control` owns messaging instructions and parent addressing. Its logged runtime context gives delegated children their direct creator’s name from `ctx.subagents.namesOf()`, explains when to send findings, and states that sending does not finish a turn. The context is emitted only for delegated children when the plugin’s own tool definition is admitted in the current scope and step; roots and ordinary Session forks receive none. Communication guidance follows inherited history without changing the shared system prompt or tool schema.
The manager owns result delivery. Local activations with `delivery: 'parent'` receive automatic-result guidance even without messaging tools; caller-owned activations receive no parent-delivery promise. Settlement timing, recipients, output, and suppression of closing text after a final message to the parent remain unchanged. Tool visibility grants no messaging authority.
@@ -10,7 +10,7 @@ Status: implemented
## 决策
`tool-subagent-control` 拥有通信说明和父级寻址。持久记录的运行时上下文从 Session header 读取委派子级的直接创建者 id,说明何时发送发现,并指出发送不会结束轮次。仅当本插件的工具定义在当前作用域和 step 中可用时,才向委派子级提供上下文;根代理和普通 Session fork 不接收。通信指导位于继承历史之后,不改变共享系统提示词或工具 schema。
`tool-subagent-control` 拥有通信说明和父级寻址。持久记录的运行时上下文通过 `ctx.subagents.namesOf()` 提供委派子级的直接创建者名称,说明何时发送发现,并指出发送不会结束轮次。仅当本插件的工具定义在当前作用域和 step 中可用时,才向委派子级提供上下文;根代理和普通 Session fork 不接收。通信指导位于继承历史之后,不改变共享系统提示词或工具 schema。
管理器拥有结果交付。采用 `delivery: 'parent'` 的本地 activation 即使没有通信工具,也会收到自动结果交付指导;调用方拥有的 activation 不会收到父级交付承诺。结算时序、接收方、输出,以及最后向父级发送消息后省略结束文本的规则保持不变。工具可见性不授予通信权限。
@@ -0,0 +1,22 @@
# Bilingual-pair consistency record for 2026-11-02-subagent-catalog-names.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-11-02-subagent-catalog-names.md
/agent-note-subagent-names-live-in-the-creator-s-catalog:
en: 987d2272bb47fe75
zh: 54e701ecbaa60457
/agent-note-subagent-names-live-in-the-creator-s-catalog/problem:
en: d4798e7bbbd5d49d
zh: b388470cf1ff33ac
/agent-note-subagent-names-live-in-the-creator-s-catalog/decision:
en: ff9771851b64b1ca
zh: a032e7f14207d8bd
/agent-note-subagent-names-live-in-the-creator-s-catalog/alternatives-considered:
en: 14b564fd848248da
zh: 5f65c05bbe22d581
/agent-note-subagent-names-live-in-the-creator-s-catalog/consequences:
en: adddb4d296db5c44
zh: ed8c6559c53fc6f2
/agent-note-subagent-names-live-in-the-creator-s-catalog/testing:
en: a7963eadbfe52c21
zh: 10bfc9fb28f6ae73
@@ -0,0 +1,45 @@
# Agent Note: Subagent names live in the creator's catalog
Status: implemented
English | [中文](2026-11-02-subagent-catalog-names.zh.md)
## Problem
Models coordinate subagents through `send_message`, `interrupt_agent`, `list_agents`, and Team task owners. Those tools addressed every member by a 36-character Session id. Models copy such ids poorly: they cannot recall which id belongs to which task, they mistype ids, and every listing, receipt, notice, and identity statement spends tokens on them. Descriptions explain responsibilities but repeat and cannot address a member. Models need short, readable references that survive restarts and resolve to exactly one member, without a second execution identity.
## Decision
The Session id remains the only execution identity for routing, authorization, persistence, task ownership, and navigation. A name is a model-facing reference to it.
Each new child has a name that is unique among its creator's children. The name is a field of the `subagent/catalog` entry that the creator already appends when it creates the child, using catalog payload version 3. Local and parent-delivered external creation write it; caller-delivered external runs enter no catalog and take no name. A name is 1–32 lower-case letters, digits, or hyphens starting with a letter, and is never `lead`. A 36-character UUID therefore never parses as a name. Omission selects the first free `agent-N`. An explicit name already held by a sibling fails with `DUPLICATE_AGENT_NAME`, and an invalid name fails with `INVALID_AGENT_NAME`.
The creator reserves the name synchronously at admission, before startup awaits anything. The reservation lives in process memory beside the creator's committed catalog names and is released when the catalog entry commits or startup fails. No other write records the name.
The root is always `lead`. A descendant's full name is the slash-separated path of names from the root without a `lead/` prefix, such as `reviewer/checker`. Sibling-unique segments make full names unique in the tree. A child whose catalog entry predates names, and every descendant below it, keeps its Session id as its name.
`ctx.subagents.resolveName()` returns the Session id for `lead` or a full name by reading only the catalogs along the path; any other text is returned unchanged as a Session id. Tools resolve before they call messaging, interruption, or Team assignment, and those operations authorize the resulting Session id. Resolution grants no authority. Runtime-authored text names agents by full name, while durable attribution such as `senderSessionId` and Team `ownerId` keeps Session ids. The [subagent runtime](../../../../packages/subagent/subagent/README.md#agent-names) owns the API contract and the [upgrade guide](../../../../docs/upgrade-guide/v0.2.2-alpha.2/subagent-names/guide.md) owns caller migration.
This supersedes the rejection of "unique names as sibling-routing opt-in" and the statement that creation accepts no member name in [subagent teammates](2026-10-15-agent-teams-as-subagents.md), and the Session-id identity text in [required runtime-context identity](2026-10-13-team-identity-runtime-context.md). Their single-identity, Team, and runtime-context retention decisions remain active.
## Alternatives considered
**Optional naming plugin with a root-Session binding event.** A separate plugin would record a name-to-Session binding in the root Session after the child starts. That adds a second write that can fail independently after startup succeeds, so a started child can lack its binding, and binding after start can report errors for children that are already running. The presentation plugin would then own cancellation of a lifecycle it does not control, would rewrite runtime-authored messages that name agents, and would still change model-visible schemas when it is absent, because the core tools must accept and render either form. Recording the name in the creator's existing catalog fact needs no second write, no rollback protocol, and no optional service.
**Flat names unique across the tree.** A tree-wide flat namespace needs one registry at the root that every creation must consult and update, including creations by descendants whose root may be cold. Sibling-unique segments joined into paths are unique without a root registry, and each creator checks only its own catalog.
**Recyclable names.** Releasing a name when its child settles would let a later sibling take it. A model that still remembers the earlier child would then message or interrupt a different agent. A name stays taken for as long as the catalog entry exists.
**Automatic suffixes on conflict.** Turning a duplicate `reviewer` into `reviewer-2` would let creation succeed, but the model would believe it holds a name that the runtime never assigned. A duplicate fails so that the model chooses a name it knows.
## Consequences
Catalog payload version 3 is a same-format addition: `SESSION_FORMAT_VERSION` is unchanged, current readers accept versions 0 through 3, and releases that predate names reject version 3 loudly. The `subagentCatalog` projection state version is 7, so caches rebuild from Session events. The [persistence acknowledgement](../../../../docs/persistence-changes/2026-11-02-subagent-catalog-names.md) records the type change.
Tool schemas grow by one optional `name` parameter on each delegation tool, and `send_message` and `interrupt_agent` rename `agent_id` to `agent`. These schema changes invalidate cached request prefixes once after upgrading. Identity runtime context, receipts, settlement notices, agent messages, and listing rows become shorter for shallow trees, while full names lengthen with nesting depth. `list_agents` drops parent ids and depth because a full name encodes both.
Names cannot be renamed or recycled. Historical children have no names, and no migration assigns them. Name reservations are process-local, as is subagent residency. Tools still accept Session ids, so recorded Session ids and members below unnamed creators remain addressable.
## Testing
Runtime tests cover requested and default names, duplicate and invalid names rejected before startup, reservation across concurrent startup and release after failed startup, nested paths and `namesOf`, resolution of names, unknown text, and Session ids without granting authority, cold restoration of a member's path from the catalogs along its creation chain, and Session-id addressing below an unnamed historical creator. Catalog tests restore version-3 names beside unnamed historical entries, and the V4 format reader admits native version-3 catalog facts. Control-tool and Team-tool tests cover name-addressed messaging, listing rows, owner names, and historical owners shown by Session id. Recorded sessions pin the tool schemas, identity runtime context, receipts, listing rows, and Team policy text.
@@ -0,0 +1,45 @@
# Agent Note: Subagent 名称记录在创建者目录中
Status: implemented
[English](2026-11-02-subagent-catalog-names.md) | 中文
## Problem
模型通过 `send_message`、`interrupt_agent`、`list_agents` 和 Team 任务所有者协调 subagent(子智能体)。这些工具曾以 36 字符的 Session id 寻址每个成员。模型难以准确复制这类 id:记不清哪个 id 对应哪个任务,会输错 id,而且每次列表、回执、通知和身份声明都要为其消耗 token。描述能说明职责,但可以重复,无法寻址成员。模型需要简短、可读、跨重启有效且只解析到唯一成员的引用,同时不引入第二种执行身份。
## Decision
Session id 仍是路由、授权、持久化、任务归属和导航使用的唯一执行身份。名称是指向它的面向模型的引用。
每个新子级都有一个名称,在其创建者的子级之间唯一。名称是创建者在创建子级时本就会追加的 `subagent/catalog` 条目中的一个字段,使用第 3 版目录载荷。本地创建和父级投递的外部创建写入名称;调用方投递的外部执行不进入目录,也没有名称。名称由 1–32 个小写字母、数字或连字符组成,以字母开头,且绝不能是 `lead`。因此 36 字符的 UUID 永远不会被解析为名称。省略时选择第一个空闲的 `agent-N`。显式请求同级已持有的名称会以 `DUPLICATE_AGENT_NAME` 失败,无效名称以 `INVALID_AGENT_NAME` 失败。
创建者在准入时、启动等待任何操作之前同步预留名称。预留保存在进程内存中,与创建者已提交的目录名称并列,并在目录条目提交或启动失败时释放。没有其他写入记录该名称。
根的名称始终为 `lead`。后代的完整名称是从根开始、以斜杠分隔的名称路径,不带 `lead/` 前缀,例如 `reviewer/checker`。同级唯一的各段使完整名称在整棵树中唯一。目录条目早于名称机制的子级及其下所有后代继续以 Session id 作为名称。
`ctx.subagents.resolveName()` 只读取路径上的目录,为 `lead` 或完整名称返回 Session id;其他文本原样作为 Session id 返回。工具先解析名称,再调用消息、中断或 Team 分配,由这些操作对解析出的 Session id 授权。解析本身不授予权限。运行时撰写的文本以完整名称指称 agent,而 `senderSessionId` 和 Team `ownerId` 等持久归属仍保留 Session id。[subagent 运行时](../../../../packages/subagent/subagent/README.zh.md#agent-names)定义 API 约定,[升级指南](../../../../docs/upgrade-guide/v0.2.2-alpha.2/subagent-names/guide.zh.md)负责调用方迁移。
本决策取代 [Agent Teams 队友是子代理](2026-10-15-agent-teams-as-subagents.zh.md)中对“以唯一名称选择性启用同级路由”的否决以及“创建不接收成员名称”的表述,并取代[必需运行时身份](2026-10-13-team-identity-runtime-context.zh.md)中以 Session id 表述身份的文本。它们的单一身份、Team 和运行时上下文保留决策仍然有效。
## Alternatives considered
**带根 Session 绑定事件的可选命名插件。** 独立插件会在子级启动后,在根 Session 中记录名称到 Session 的绑定。这会增加第二次写入,且可能在启动成功后单独失败,导致已启动的子级缺少绑定;启动后再绑定还可能为已在运行的子级报告错误。展示用插件因此要负责取消一个不受它控制的生命周期,要改写指称 agent 的运行时消息;而且即使插件不存在,面向模型的 schema 仍会改变,因为核心工具必须接受并渲染两种形式。把名称记录在创建者已有的目录事实中,不需要第二次写入、回滚协议或可选服务。
**全树唯一的扁平名称。** 全树扁平命名空间需要根上的一个注册表,每次创建都要查询并更新它,包括根可能处于冷状态时由后代发起的创建。同级唯一的各段连接成路径后无需根注册表即可唯一,每个创建者只检查自己的目录。
**可回收名称。** 子级结算后释放名称会让之后的同级取得该名称。仍记得先前子级的模型会因此向另一个 agent 发消息或发出中断。只要目录条目存在,名称就保持占用。
**冲突时自动加后缀。** 把重复的 `reviewer` 改为 `reviewer-2` 能让创建成功,但模型会以为自己持有一个运行时从未分配的名称。重复名称直接失败,模型才会选择一个自己知道的名称。
## Consequences
第 3 版目录载荷是同格式增量:`SESSION_FORMAT_VERSION` 不变,当前读取器接受第 0 至第 3 版,早于名称机制的发布会明确拒绝第 3 版。`subagentCatalog` 投影状态版本为 7,因此缓存会从 Session 事件重建。[持久化确认记录](../../../../docs/persistence-changes/2026-11-02-subagent-catalog-names.zh.md)记录了该类型变更。
每个委派工具的 schema 增加一个可选 `name` 参数,`send_message` 和 `interrupt_agent` 把 `agent_id` 改名为 `agent`。这些 schema 变更会在升级后使缓存的请求前缀失效一次。对浅层树而言,身份运行时上下文、回执、结算通知、agent 消息和列表行都变短,完整名称则随嵌套深度变长。`list_agents` 不再携带父级 id 和深度,因为完整名称已包含这两项信息。
名称不能修改或回收。历史子级没有名称,也没有迁移为其分配名称。名称预留与 subagent 驻留一样仅限进程内。工具仍接受 Session id,因此已记录的 Session id 和无名创建者下的成员仍可寻址。
## Testing
运行时测试覆盖请求名称与默认名称、启动前拒绝重复和无效名称、并发启动期间的预留和启动失败后的释放、嵌套路径与 `namesOf`、在不授予权限的前提下解析名称、未知文本和 Session id、从创建链上的目录冷恢复成员路径,以及无名历史创建者之下以 Session id 寻址。目录测试在无名历史条目旁恢复第 3 版名称,V4 格式读取器接纳原生第 3 版目录事实。控制工具和 Team 工具测试覆盖按名称发消息、列表行、所有者名称,以及以 Session id 显示的历史所有者。录制会话固定工具 schema、身份运行时上下文、回执、列表行和 Team 策略文本。
@@ -8,7 +8,7 @@
{"type":"step/start","data":{"turn":1,"step":1}}
{"type":"system/message","data":{"turn":1,"step":1,"message":{"role":"system","content":[{"type":"text","text":"{{system}}"}],"source":{"kind":"system-prompt"},"id":"{{sessionId}}"}},"surfaceOp":"append"}
{"type":"user/message","data":{"content":[{"type":"text","text":"Create a durable two-round goal for the ACP snapshot, inspect it, then report readiness."}],"source":{"kind":"user"},"role":"user","id":"{{sessionId}}"},"surfaceOp":"append"}
{"type":"user/message","data":{"content":[{"type":"text","text":"Current runtime context. This snapshot supersedes earlier runtime-context snapshots.\n\nCurrent working directory: \"{{cwd}}\".\n\nCurrent DSH file policy: danger-full-access. The DSH file sandbox does not restrict file modifications by available operations.\n\nApproval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`).\n\nYou are the root agent. Your agent id is \"{{sessionId}}\".\n\nTo message other agents, use send_message({ agent_id: \"<agent-id>\", message: \"...\" }).\nUse list_agents({}) to find your collaborator agents and their ids."}],"source":{"kind":"runtime-context","form":"snapshot","sections":[{"name":"working-directory:current","text":"Current working directory: \"{{cwd}}\"."},{"name":"sandbox:policy","text":"Current DSH file policy: danger-full-access. The DSH file sandbox does not restrict file modifications by available operations."},{"name":"approval:policy","text":"Approval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`)."},{"name":"subagent:identity","text":"You are the root agent. Your agent id is \"{{sessionId}}\".\n\nTo message other agents, use send_message({ agent_id: \"<agent-id>\", message: \"...\" }).\nUse list_agents({}) to find your collaborator agents and their ids."}]},"role":"user","id":"{{sessionId}}"},"surfaceOp":"append"}
{"type":"user/message","data":{"content":[{"type":"text","text":"Current runtime context. This snapshot supersedes earlier runtime-context snapshots.\n\nCurrent working directory: \"{{cwd}}\".\n\nCurrent DSH file policy: danger-full-access. The DSH file sandbox does not restrict file modifications by available operations.\n\nApproval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`).\n\nYou are the root agent. Your name is \"lead\".\n\nTo message other agents, use send_message({ agent: \"<agent-name>\", message: \"...\" }).\nUse list_agents({}) to find your collaborator agents and their names."}],"source":{"kind":"runtime-context","form":"snapshot","sections":[{"name":"working-directory:current","text":"Current working directory: \"{{cwd}}\"."},{"name":"sandbox:policy","text":"Current DSH file policy: danger-full-access. The DSH file sandbox does not restrict file modifications by available operations."},{"name":"approval:policy","text":"Approval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`)."},{"name":"subagent:identity","text":"You are the root agent. Your name is \"lead\".\n\nTo message other agents, use send_message({ agent: \"<agent-name>\", message: \"...\" }).\nUse list_agents({}) to find your collaborator agents and their names."}]},"role":"user","id":"{{sessionId}}"},"surfaceOp":"append"}
{"type":"request/header","data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash"},"tools":"{{tools}}"},"reason":"initial"}}
{"type":"request/context","data":{"provider":"deepseek-official","model":"deepseek-v4-flash"}}
{"type":"session/title","data":{"title":"Create a durable two-round goal","messageSeqs":[8],"source":{"kind":"fallback"}}}
@@ -8,7 +8,7 @@
{"type":"step/start","data":{"turn":1,"step":1}}
{"type":"system/message","data":{"turn":1,"step":1,"message":{"role":"system","content":[{"type":"text","text":"{{system}}"}],"source":{"kind":"system-prompt"},"id":"{{sessionId}}"}},"surfaceOp":"append"}
{"type":"user/message","data":{"content":[{"type":"text","text":"Create a durable goal for the wrap-up snapshot, then report readiness."}],"source":{"kind":"user"},"role":"user","id":"{{sessionId}}"},"surfaceOp":"append"}
{"type":"user/message","data":{"content":[{"type":"text","text":"Current runtime context. This snapshot supersedes earlier runtime-context snapshots.\n\nCurrent working directory: \"{{cwd}}\".\n\nCurrent DSH file policy: danger-full-access. The DSH file sandbox does not restrict file modifications by available operations.\n\nApproval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`).\n\nYou are the root agent. Your agent id is \"{{sessionId}}\".\n\nTo message other agents, use send_message({ agent_id: \"<agent-id>\", message: \"...\" }).\nUse list_agents({}) to find your collaborator agents and their ids."}],"source":{"kind":"runtime-context","form":"snapshot","sections":[{"name":"working-directory:current","text":"Current working directory: \"{{cwd}}\"."},{"name":"sandbox:policy","text":"Current DSH file policy: danger-full-access. The DSH file sandbox does not restrict file modifications by available operations."},{"name":"approval:policy","text":"Approval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`)."},{"name":"subagent:identity","text":"You are the root agent. Your agent id is \"{{sessionId}}\".\n\nTo message other agents, use send_message({ agent_id: \"<agent-id>\", message: \"...\" }).\nUse list_agents({}) to find your collaborator agents and their ids."}]},"role":"user","id":"{{sessionId}}"},"surfaceOp":"append"}
{"type":"user/message","data":{"content":[{"type":"text","text":"Current runtime context. This snapshot supersedes earlier runtime-context snapshots.\n\nCurrent working directory: \"{{cwd}}\".\n\nCurrent DSH file policy: danger-full-access. The DSH file sandbox does not restrict file modifications by available operations.\n\nApproval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`).\n\nYou are the root agent. Your name is \"lead\".\n\nTo message other agents, use send_message({ agent: \"<agent-name>\", message: \"...\" }).\nUse list_agents({}) to find your collaborator agents and their names."}],"source":{"kind":"runtime-context","form":"snapshot","sections":[{"name":"working-directory:current","text":"Current working directory: \"{{cwd}}\"."},{"name":"sandbox:policy","text":"Current DSH file policy: danger-full-access. The DSH file sandbox does not restrict file modifications by available operations."},{"name":"approval:policy","text":"Approval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`)."},{"name":"subagent:identity","text":"You are the root agent. Your name is \"lead\".\n\nTo message other agents, use send_message({ agent: \"<agent-name>\", message: \"...\" }).\nUse list_agents({}) to find your collaborator agents and their names."}]},"role":"user","id":"{{sessionId}}"},"surfaceOp":"append"}
{"type":"request/header","data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash"},"tools":"{{tools}}"},"reason":"initial"}}
{"type":"request/context","data":{"provider":"deepseek-official","model":"deepseek-v4-flash"}}
{"type":"session/title","data":{"title":"Create a durable goal for","messageSeqs":[8],"source":{"kind":"fallback"}}}
@@ -140,13 +140,13 @@ it('pins Messages Files offload and inline fallback in assembled requests', asyn
const fileImage = { type: 'image', source: { type: 'file', file_id: 'file-api-snapshot-1' } }
const offloadedImage = `[image omitted to fit request image limits; ${attachmentId}.${normalizedAccess}]`
const imageHandle = `Image ${attachmentId}; request preview 1x1px.${normalizedAccess}`
const runtimeContext = (cwd: string, sessionId: string): string => 'Current runtime context. This snapshot supersedes earlier runtime-context snapshots.\n\n'
const runtimeContext = (cwd: string): string => 'Current runtime context. This snapshot supersedes earlier runtime-context snapshots.\n\n'
+ `Current working directory: ${JSON.stringify(cwd)}.\n\n`
+ 'Current DSH file policy: danger-full-access. The DSH file sandbox does not restrict file modifications by available operations.\n\n'
+ 'Approval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`).\n\n'
+ `You are the root agent. Your agent id is ${JSON.stringify(sessionId)}.\n\n`
+ 'To message other agents, use send_message({ agent_id: "<agent-id>", message: "..." }).\n'
+ 'Use list_agents({}) to find your collaborator agents and their ids.'
+ 'You are the root agent. Your name is "lead".\n\n'
+ 'To message other agents, use send_message({ agent: "<agent-name>", message: "..." }).\n'
+ 'Use list_agents({}) to find your collaborator agents and their names.'
const messages = requests[0]?.messages as { content?: unknown }[] | undefined
const offloaded = messages?.find(message => JSON.stringify(message.content).includes('[image omitted'))
expect(offloaded?.content).toEqual([
@@ -156,7 +156,7 @@ it('pins Messages Files offload and inline fallback in assembled requests', asyn
{ type: 'text', text: imageHandle },
fileImage,
{ type: 'text', text: ', then use read_image on red.png and reply with DONE.' },
{ type: 'text', text: runtimeContext(result.cwd, result.sessionId) },
{ type: 'text', text: runtimeContext(result.cwd) },
])
const followup = requests[1]?.messages as Array<{ role: string; content: Array<Record<string, unknown>> }>
@@ -208,7 +208,7 @@ it('pins Messages Files offload and inline fallback in assembled requests', asyn
{ type: 'text', text: `Image ${attachmentId}; request preview 1x1px.${fallbackAccess}` },
{ type: 'image', source: { type: 'base64', media_type: 'image/png', data: image } },
{ type: 'text', text: ', then use read_image on red.png and reply with DONE.' },
{ type: 'text', text: runtimeContext(fallback.cwd, fallback.sessionId) },
{ type: 'text', text: runtimeContext(fallback.cwd) },
])
} finally {
await new Promise<void>(resolve => server.close(() => { resolve() }))
@@ -4,7 +4,7 @@
{"type":"session_event","sessionId":"{{sessionId}}","event":{"type":"step/start","seq":6,"time":0,"data":{"turn":1,"step":1}}}
{"type":"session_event","sessionId":"{{sessionId}}","event":{"type":"system/message","seq":7,"time":0,"data":{"turn":1,"step":1,"message":{"role":"system","content":[{"type":"text","text":"{{system}}"}],"source":{"kind":"system-prompt"},"id":"{{sessionId}}"}},"surfaceOp":"append"}}
{"type":"session_event","sessionId":"{{sessionId}}","event":{"type":"user/message","seq":8,"time":0,"data":{"content":[{"type":"text","text":"Probe strict-schema fillers against missing-goal revision 1, then create a durable goal to finish the snapshot proof and inspect it."}],"source":{"kind":"user"},"role":"user","id":"{{sessionId}}"},"surfaceOp":"append"}}
{"type":"session_event","sessionId":"{{sessionId}}","event":{"type":"user/message","seq":9,"time":0,"data":{"content":[{"type":"text","text":"Current runtime context. This snapshot supersedes earlier runtime-context snapshots.\n\nCurrent working directory: \"{{cwd}}\".\n\nCurrent DSH file policy: workspace-write. Any available operation enforced by the DSH file sandbox may modify files under the session workspace: \"{{cwd}}\". Some platform temporary areas may also be writable.\n\nApproval prompts are enabled in this session: operations that require approval may ask through the configured answerers; without an available answerer, the request fails closed.\n\nYou are the root agent. Your agent id is \"{{sessionId}}\".\n\nTo message other agents, use send_message({ agent_id: \"<agent-id>\", message: \"...\" }).\nUse list_agents({}) to find your collaborator agents and their ids."}],"source":{"kind":"runtime-context","form":"snapshot","sections":[{"name":"working-directory:current","text":"Current working directory: \"{{cwd}}\"."},{"name":"sandbox:policy","text":"Current DSH file policy: workspace-write. Any available operation enforced by the DSH file sandbox may modify files under the session workspace: \"{{cwd}}\". Some platform temporary areas may also be writable."},{"name":"approval:policy","text":"Approval prompts are enabled in this session: operations that require approval may ask through the configured answerers; without an available answerer, the request fails closed."},{"name":"subagent:identity","text":"You are the root agent. Your agent id is \"{{sessionId}}\".\n\nTo message other agents, use send_message({ agent_id: \"<agent-id>\", message: \"...\" }).\nUse list_agents({}) to find your collaborator agents and their ids."}]},"role":"user","id":"{{sessionId}}"},"surfaceOp":"append"}}
{"type":"session_event","sessionId":"{{sessionId}}","event":{"type":"user/message","seq":9,"time":0,"data":{"content":[{"type":"text","text":"Current runtime context. This snapshot supersedes earlier runtime-context snapshots.\n\nCurrent working directory: \"{{cwd}}\".\n\nCurrent DSH file policy: workspace-write. Any available operation enforced by the DSH file sandbox may modify files under the session workspace: \"{{cwd}}\". Some platform temporary areas may also be writable.\n\nApproval prompts are enabled in this session: operations that require approval may ask through the configured answerers; without an available answerer, the request fails closed.\n\nYou are the root agent. Your name is \"lead\".\n\nTo message other agents, use send_message({ agent: \"<agent-name>\", message: \"...\" }).\nUse list_agents({}) to find your collaborator agents and their names."}],"source":{"kind":"runtime-context","form":"snapshot","sections":[{"name":"working-directory:current","text":"Current working directory: \"{{cwd}}\"."},{"name":"sandbox:policy","text":"Current DSH file policy: workspace-write. Any available operation enforced by the DSH file sandbox may modify files under the session workspace: \"{{cwd}}\". Some platform temporary areas may also be writable."},{"name":"approval:policy","text":"Approval prompts are enabled in this session: operations that require approval may ask through the configured answerers; without an available answerer, the request fails closed."},{"name":"subagent:identity","text":"You are the root agent. Your name is \"lead\".\n\nTo message other agents, use send_message({ agent: \"<agent-name>\", message: \"...\" }).\nUse list_agents({}) to find your collaborator agents and their names."}]},"role":"user","id":"{{sessionId}}"},"surfaceOp":"append"}}
{"type":"session_event","sessionId":"{{sessionId}}","event":{"type":"request/header","seq":10,"time":0,"data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash"},"tools":"{{tools}}"},"reason":"initial"}}}
{"type":"session_event","sessionId":"{{sessionId}}","event":{"type":"request/context","seq":11,"time":0,"data":{"provider":"deepseek-official","model":"deepseek-v4-flash"}}}
{"type":"session_event","sessionId":"{{sessionId}}","event":{"type":"session/title","seq":12,"time":0,"data":{"title":"Probe strict-schema fillers against miss","messageSeqs":[8],"source":{"kind":"fallback"}}}}
@@ -8,7 +8,7 @@
{"type":"step/start","data":{"turn":1,"step":1}}
{"type":"system/message","data":{"turn":1,"step":1,"message":{"role":"system","content":[{"type":"text","text":"{{system}}"}],"source":{"kind":"system-prompt"},"id":"{{sessionId}}"}},"surfaceOp":"append"}
{"type":"user/message","data":{"content":[{"type":"text","text":"Prove the product headless profile path with one real tool round trip."}],"source":{"kind":"user"},"role":"user","id":"{{sessionId}}"},"surfaceOp":"append"}
{"type":"user/message","data":{"content":[{"type":"text","text":"Current runtime context. This snapshot supersedes earlier runtime-context snapshots.\n\nCurrent working directory: \"{{cwd}}\".\n\nCurrent DSH file policy: danger-full-access. The DSH file sandbox does not restrict file modifications by available operations.\n\nApproval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`).\n\nYou are the root agent. Your agent id is \"{{sessionId}}\".\n\nTo message other agents, use send_message({ agent_id: \"<agent-id>\", message: \"...\" }).\nUse list_agents({}) to find your collaborator agents and their ids."}],"source":{"kind":"runtime-context","form":"snapshot","sections":[{"name":"working-directory:current","text":"Current working directory: \"{{cwd}}\"."},{"name":"sandbox:policy","text":"Current DSH file policy: danger-full-access. The DSH file sandbox does not restrict file modifications by available operations."},{"name":"approval:policy","text":"Approval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`)."},{"name":"subagent:identity","text":"You are the root agent. Your agent id is \"{{sessionId}}\".\n\nTo message other agents, use send_message({ agent_id: \"<agent-id>\", message: \"...\" }).\nUse list_agents({}) to find your collaborator agents and their ids."}]},"role":"user","id":"{{sessionId}}"},"surfaceOp":"append"}
{"type":"user/message","data":{"content":[{"type":"text","text":"Current runtime context. This snapshot supersedes earlier runtime-context snapshots.\n\nCurrent working directory: \"{{cwd}}\".\n\nCurrent DSH file policy: danger-full-access. The DSH file sandbox does not restrict file modifications by available operations.\n\nApproval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`).\n\nYou are the root agent. Your name is \"lead\".\n\nTo message other agents, use send_message({ agent: \"<agent-name>\", message: \"...\" }).\nUse list_agents({}) to find your collaborator agents and their names."}],"source":{"kind":"runtime-context","form":"snapshot","sections":[{"name":"working-directory:current","text":"Current working directory: \"{{cwd}}\"."},{"name":"sandbox:policy","text":"Current DSH file policy: danger-full-access. The DSH file sandbox does not restrict file modifications by available operations."},{"name":"approval:policy","text":"Approval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`)."},{"name":"subagent:identity","text":"You are the root agent. Your name is \"lead\".\n\nTo message other agents, use send_message({ agent: \"<agent-name>\", message: \"...\" }).\nUse list_agents({}) to find your collaborator agents and their names."}]},"role":"user","id":"{{sessionId}}"},"surfaceOp":"append"}
{"type":"request/header","data":{"header":{"config":{"provider":"cli-mock","model":"cli-mock","reasoningEffort":"high"},"adapterDefaults":{"reasoningEffort":true},"tools":"{{tools}}"},"reason":"initial"}}
{"type":"request/context","data":{"provider":"cli-mock","model":"cli-mock"}}
{"type":"session/title","data":{"title":"Prove the product headless profile","messageSeqs":[8],"source":{"kind":"fallback"}}}
@@ -4,7 +4,7 @@
{"type":"session_event","sessionId":"{{sessionId}}","event":{"type":"step/start","seq":6,"time":0,"data":{"turn":1,"step":1}}}
{"type":"session_event","sessionId":"{{sessionId}}","event":{"type":"system/message","seq":7,"time":0,"data":{"turn":1,"step":1,"message":{"role":"system","content":[{"type":"text","text":"{{system}}"}],"source":{"kind":"system-prompt"},"id":"{{sessionId}}"}},"surfaceOp":"append"}}
{"type":"session_event","sessionId":"{{sessionId}}","event":{"type":"user/message","seq":8,"time":0,"data":{"content":[{"type":"text","text":"say pong"}],"source":{"kind":"user"},"role":"user","id":"{{sessionId}}"},"surfaceOp":"append"}}
{"type":"session_event","sessionId":"{{sessionId}}","event":{"type":"user/message","seq":9,"time":0,"data":{"content":[{"type":"text","text":"Current runtime context. This snapshot supersedes earlier runtime-context snapshots.\n\nCurrent working directory: \"{{cwd}}\".\n\nCurrent DSH file policy: workspace-write. Any available operation enforced by the DSH file sandbox may modify files under the session workspace: \"{{cwd}}\". Some platform temporary areas may also be writable.\n\nApproval prompts are enabled in this session: operations that require approval may ask through the configured answerers; without an available answerer, the request fails closed.\n\nYou are the root agent. Your agent id is \"{{sessionId}}\".\n\nTo message other agents, use send_message({ agent_id: \"<agent-id>\", message: \"...\" }).\nUse list_agents({}) to find your collaborator agents and their ids."}],"source":{"kind":"runtime-context","form":"snapshot","sections":[{"name":"working-directory:current","text":"Current working directory: \"{{cwd}}\"."},{"name":"sandbox:policy","text":"Current DSH file policy: workspace-write. Any available operation enforced by the DSH file sandbox may modify files under the session workspace: \"{{cwd}}\". Some platform temporary areas may also be writable."},{"name":"approval:policy","text":"Approval prompts are enabled in this session: operations that require approval may ask through the configured answerers; without an available answerer, the request fails closed."},{"name":"subagent:identity","text":"You are the root agent. Your agent id is \"{{sessionId}}\".\n\nTo message other agents, use send_message({ agent_id: \"<agent-id>\", message: \"...\" }).\nUse list_agents({}) to find your collaborator agents and their ids."}]},"role":"user","id":"{{sessionId}}"},"surfaceOp":"append"}}
{"type":"session_event","sessionId":"{{sessionId}}","event":{"type":"user/message","seq":9,"time":0,"data":{"content":[{"type":"text","text":"Current runtime context. This snapshot supersedes earlier runtime-context snapshots.\n\nCurrent working directory: \"{{cwd}}\".\n\nCurrent DSH file policy: workspace-write. Any available operation enforced by the DSH file sandbox may modify files under the session workspace: \"{{cwd}}\". Some platform temporary areas may also be writable.\n\nApproval prompts are enabled in this session: operations that require approval may ask through the configured answerers; without an available answerer, the request fails closed.\n\nYou are the root agent. Your name is \"lead\".\n\nTo message other agents, use send_message({ agent: \"<agent-name>\", message: \"...\" }).\nUse list_agents({}) to find your collaborator agents and their names."}],"source":{"kind":"runtime-context","form":"snapshot","sections":[{"name":"working-directory:current","text":"Current working directory: \"{{cwd}}\"."},{"name":"sandbox:policy","text":"Current DSH file policy: workspace-write. Any available operation enforced by the DSH file sandbox may modify files under the session workspace: \"{{cwd}}\". Some platform temporary areas may also be writable."},{"name":"approval:policy","text":"Approval prompts are enabled in this session: operations that require approval may ask through the configured answerers; without an available answerer, the request fails closed."},{"name":"subagent:identity","text":"You are the root agent. Your name is \"lead\".\n\nTo message other agents, use send_message({ agent: \"<agent-name>\", message: \"...\" }).\nUse list_agents({}) to find your collaborator agents and their names."}]},"role":"user","id":"{{sessionId}}"},"surfaceOp":"append"}}
{"type":"session_event","sessionId":"{{sessionId}}","event":{"type":"request/header","seq":10,"time":0,"data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash","maxTokens":256000,"reasoningEffort":"high"},"adapterDefaults":{"reasoningEffort":true,"maxTokens":true},"tools":"{{tools}}"},"reason":"initial"}}}
{"type":"session_event","sessionId":"{{sessionId}}","event":{"type":"request/context","seq":11,"time":0,"data":{"provider":"deepseek-official","model":"deepseek-v4-flash","contextWindow":1000000}}}
{"type":"session_event","sessionId":"{{sessionId}}","event":{"type":"session/title","seq":12,"time":0,"data":{"title":"say pong","messageSeqs":[8],"source":{"kind":"fallback"}}}}
@@ -4,7 +4,7 @@
{"type":"session_event","sessionId":"{{sessionId}}","event":{"type":"step/start","seq":6,"time":0,"data":{"turn":1,"step":1}}}
{"type":"session_event","sessionId":"{{sessionId}}","event":{"type":"system/message","seq":7,"time":0,"data":{"turn":1,"step":1,"message":{"role":"system","content":[{"type":"text","text":"{{system}}"}],"source":{"kind":"system-prompt"},"id":"{{sessionId}}"}},"surfaceOp":"append"}}
{"type":"session_event","sessionId":"{{sessionId}}","event":{"type":"user/message","seq":8,"time":0,"data":{"content":[{"type":"text","text":"say pong"}],"source":{"kind":"user"},"role":"user","id":"{{sessionId}}"},"surfaceOp":"append"}}
{"type":"session_event","sessionId":"{{sessionId}}","event":{"type":"user/message","seq":9,"time":0,"data":{"content":[{"type":"text","text":"Current runtime context. This snapshot supersedes earlier runtime-context snapshots.\n\nCurrent working directory: \"{{cwd}}\".\n\nCurrent DSH file policy: workspace-write. Any available operation enforced by the DSH file sandbox may modify files under the session workspace: \"{{cwd}}\". Some platform temporary areas may also be writable.\n\nApproval prompts are enabled in this session: operations that require approval may ask through the configured answerers; without an available answerer, the request fails closed.\n\nYou are the root agent. Your agent id is \"{{sessionId}}\".\n\nTo message other agents, use send_message({ agent_id: \"<agent-id>\", message: \"...\" }).\nUse list_agents({}) to find your collaborator agents and their ids."}],"source":{"kind":"runtime-context","form":"snapshot","sections":[{"name":"working-directory:current","text":"Current working directory: \"{{cwd}}\"."},{"name":"sandbox:policy","text":"Current DSH file policy: workspace-write. Any available operation enforced by the DSH file sandbox may modify files under the session workspace: \"{{cwd}}\". Some platform temporary areas may also be writable."},{"name":"approval:policy","text":"Approval prompts are enabled in this session: operations that require approval may ask through the configured answerers; without an available answerer, the request fails closed."},{"name":"subagent:identity","text":"You are the root agent. Your agent id is \"{{sessionId}}\".\n\nTo message other agents, use send_message({ agent_id: \"<agent-id>\", message: \"...\" }).\nUse list_agents({}) to find your collaborator agents and their ids."}]},"role":"user","id":"{{sessionId}}"},"surfaceOp":"append"}}
{"type":"session_event","sessionId":"{{sessionId}}","event":{"type":"user/message","seq":9,"time":0,"data":{"content":[{"type":"text","text":"Current runtime context. This snapshot supersedes earlier runtime-context snapshots.\n\nCurrent working directory: \"{{cwd}}\".\n\nCurrent DSH file policy: workspace-write. Any available operation enforced by the DSH file sandbox may modify files under the session workspace: \"{{cwd}}\". Some platform temporary areas may also be writable.\n\nApproval prompts are enabled in this session: operations that require approval may ask through the configured answerers; without an available answerer, the request fails closed.\n\nYou are the root agent. Your name is \"lead\".\n\nTo message other agents, use send_message({ agent: \"<agent-name>\", message: \"...\" }).\nUse list_agents({}) to find your collaborator agents and their names."}],"source":{"kind":"runtime-context","form":"snapshot","sections":[{"name":"working-directory:current","text":"Current working directory: \"{{cwd}}\"."},{"name":"sandbox:policy","text":"Current DSH file policy: workspace-write. Any available operation enforced by the DSH file sandbox may modify files under the session workspace: \"{{cwd}}\". Some platform temporary areas may also be writable."},{"name":"approval:policy","text":"Approval prompts are enabled in this session: operations that require approval may ask through the configured answerers; without an available answerer, the request fails closed."},{"name":"subagent:identity","text":"You are the root agent. Your name is \"lead\".\n\nTo message other agents, use send_message({ agent: \"<agent-name>\", message: \"...\" }).\nUse list_agents({}) to find your collaborator agents and their names."}]},"role":"user","id":"{{sessionId}}"},"surfaceOp":"append"}}
{"type":"session_event","sessionId":"{{sessionId}}","event":{"type":"request/header","seq":10,"time":0,"data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash","maxTokens":256000,"reasoningEffort":"high"},"adapterDefaults":{"reasoningEffort":true,"maxTokens":true},"tools":"{{tools}}"},"reason":"initial"}}}
{"type":"session_event","sessionId":"{{sessionId}}","event":{"type":"request/context","seq":11,"time":0,"data":{"provider":"deepseek-official","model":"deepseek-v4-flash","contextWindow":1000000}}}
{"type":"session_event","sessionId":"{{sessionId}}","event":{"type":"session/title","seq":12,"time":0,"data":{"title":"say pong","messageSeqs":[8],"source":{"kind":"fallback"}}}}
@@ -4,7 +4,7 @@
{"type":"session_event","sessionId":"{{sessionId}}","event":{"type":"step/start","seq":6,"time":0,"data":{"turn":1,"step":1}}}
{"type":"session_event","sessionId":"{{sessionId}}","event":{"type":"system/message","seq":7,"time":0,"data":{"turn":1,"step":1,"message":{"role":"system","content":[{"type":"text","text":"{{system}}"}],"source":{"kind":"system-prompt"},"id":"{{sessionId}}"}},"surfaceOp":"append"}}
{"type":"session_event","sessionId":"{{sessionId}}","event":{"type":"user/message","seq":8,"time":0,"data":{"content":[{"type":"text","text":"retry the transient provider failure"}],"source":{"kind":"user"},"role":"user","id":"{{sessionId}}"},"surfaceOp":"append"}}
{"type":"session_event","sessionId":"{{sessionId}}","event":{"type":"user/message","seq":9,"time":0,"data":{"content":[{"type":"text","text":"Current runtime context. This snapshot supersedes earlier runtime-context snapshots.\n\nCurrent working directory: \"{{cwd}}\".\n\nCurrent DSH file policy: workspace-write. Any available operation enforced by the DSH file sandbox may modify files under the session workspace: \"{{cwd}}\". Some platform temporary areas may also be writable.\n\nApproval prompts are enabled in this session: operations that require approval may ask through the configured answerers; without an available answerer, the request fails closed.\n\nYou are the root agent. Your agent id is \"{{sessionId}}\".\n\nTo message other agents, use send_message({ agent_id: \"<agent-id>\", message: \"...\" }).\nUse list_agents({}) to find your collaborator agents and their ids."}],"source":{"kind":"runtime-context","form":"snapshot","sections":[{"name":"working-directory:current","text":"Current working directory: \"{{cwd}}\"."},{"name":"sandbox:policy","text":"Current DSH file policy: workspace-write. Any available operation enforced by the DSH file sandbox may modify files under the session workspace: \"{{cwd}}\". Some platform temporary areas may also be writable."},{"name":"approval:policy","text":"Approval prompts are enabled in this session: operations that require approval may ask through the configured answerers; without an available answerer, the request fails closed."},{"name":"subagent:identity","text":"You are the root agent. Your agent id is \"{{sessionId}}\".\n\nTo message other agents, use send_message({ agent_id: \"<agent-id>\", message: \"...\" }).\nUse list_agents({}) to find your collaborator agents and their ids."}]},"role":"user","id":"{{sessionId}}"},"surfaceOp":"append"}}
{"type":"session_event","sessionId":"{{sessionId}}","event":{"type":"user/message","seq":9,"time":0,"data":{"content":[{"type":"text","text":"Current runtime context. This snapshot supersedes earlier runtime-context snapshots.\n\nCurrent working directory: \"{{cwd}}\".\n\nCurrent DSH file policy: workspace-write. Any available operation enforced by the DSH file sandbox may modify files under the session workspace: \"{{cwd}}\". Some platform temporary areas may also be writable.\n\nApproval prompts are enabled in this session: operations that require approval may ask through the configured answerers; without an available answerer, the request fails closed.\n\nYou are the root agent. Your name is \"lead\".\n\nTo message other agents, use send_message({ agent: \"<agent-name>\", message: \"...\" }).\nUse list_agents({}) to find your collaborator agents and their names."}],"source":{"kind":"runtime-context","form":"snapshot","sections":[{"name":"working-directory:current","text":"Current working directory: \"{{cwd}}\"."},{"name":"sandbox:policy","text":"Current DSH file policy: workspace-write. Any available operation enforced by the DSH file sandbox may modify files under the session workspace: \"{{cwd}}\". Some platform temporary areas may also be writable."},{"name":"approval:policy","text":"Approval prompts are enabled in this session: operations that require approval may ask through the configured answerers; without an available answerer, the request fails closed."},{"name":"subagent:identity","text":"You are the root agent. Your name is \"lead\".\n\nTo message other agents, use send_message({ agent: \"<agent-name>\", message: \"...\" }).\nUse list_agents({}) to find your collaborator agents and their names."}]},"role":"user","id":"{{sessionId}}"},"surfaceOp":"append"}}
{"type":"session_event","sessionId":"{{sessionId}}","event":{"type":"request/header","seq":10,"time":0,"data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash"},"tools":"{{tools}}"},"reason":"initial"}}}
{"type":"session_event","sessionId":"{{sessionId}}","event":{"type":"request/context","seq":11,"time":0,"data":{"provider":"deepseek-official","model":"deepseek-v4-flash"}}}
{"type":"session_event","sessionId":"{{sessionId}}","event":{"type":"session/title","seq":12,"time":0,"data":{"title":"retry the transient provider failure","messageSeqs":[8],"source":{"kind":"fallback"}}}}
@@ -18,7 +18,7 @@
{"type":"step/start","data":{"turn":2,"step":1}}
{"type":"system/message","data":{"turn":2,"step":1,"message":{"role":"system","content":[{"type":"text","text":"{{system}}"}],"source":{"kind":"system-prompt"},"id":"{{sessionId}}"}},"sourceEventSeqs":[2],"surfaceOp":{"op":"replace","startSeq":2,"endSeq":2}}
{"type":"user/message","data":{"content":[{"type":"text","text":"Continue safely from the interrupted operation."}],"source":{"kind":"user"},"role":"user","id":"{{sessionId}}"},"surfaceOp":"append"}
{"type":"user/message","data":{"content":[{"type":"text","text":"Current runtime context. This snapshot supersedes earlier runtime-context snapshots.\n\nCurrent working directory: \"{{cwd}}\".\n\nCurrent DSH file policy: workspace-write. Any available operation enforced by the DSH file sandbox may modify files under the session workspace: \"{{cwd}}\". Some platform temporary areas may also be writable.\n\nApproval prompts are enabled in this session: operations that require approval may ask through the configured answerers; without an available answerer, the request fails closed.\n\nYou are the root agent. Your agent id is \"{{sessionId}}\".\n\nTo message other agents, use send_message({ agent_id: \"<agent-id>\", message: \"...\" }).\nUse list_agents({}) to find your collaborator agents and their ids."}],"source":{"kind":"runtime-context","form":"snapshot","sections":[{"name":"working-directory:current","text":"Current working directory: \"{{cwd}}\"."},{"name":"sandbox:policy","text":"Current DSH file policy: workspace-write. Any available operation enforced by the DSH file sandbox may modify files under the session workspace: \"{{cwd}}\". Some platform temporary areas may also be writable."},{"name":"approval:policy","text":"Approval prompts are enabled in this session: operations that require approval may ask through the configured answerers; without an available answerer, the request fails closed."},{"name":"subagent:identity","text":"You are the root agent. Your agent id is \"{{sessionId}}\".\n\nTo message other agents, use send_message({ agent_id: \"<agent-id>\", message: \"...\" }).\nUse list_agents({}) to find your collaborator agents and their ids."}]},"role":"user","id":"{{sessionId}}"},"surfaceOp":"append"}
{"type":"user/message","data":{"content":[{"type":"text","text":"Current runtime context. This snapshot supersedes earlier runtime-context snapshots.\n\nCurrent working directory: \"{{cwd}}\".\n\nCurrent DSH file policy: workspace-write. Any available operation enforced by the DSH file sandbox may modify files under the session workspace: \"{{cwd}}\". Some platform temporary areas may also be writable.\n\nApproval prompts are enabled in this session: operations that require approval may ask through the configured answerers; without an available answerer, the request fails closed.\n\nYou are the root agent. Your name is \"lead\".\n\nTo message other agents, use send_message({ agent: \"<agent-name>\", message: \"...\" }).\nUse list_agents({}) to find your collaborator agents and their names."}],"source":{"kind":"runtime-context","form":"snapshot","sections":[{"name":"working-directory:current","text":"Current working directory: \"{{cwd}}\"."},{"name":"sandbox:policy","text":"Current DSH file policy: workspace-write. Any available operation enforced by the DSH file sandbox may modify files under the session workspace: \"{{cwd}}\". Some platform temporary areas may also be writable."},{"name":"approval:policy","text":"Approval prompts are enabled in this session: operations that require approval may ask through the configured answerers; without an available answerer, the request fails closed."},{"name":"subagent:identity","text":"You are the root agent. Your name is \"lead\".\n\nTo message other agents, use send_message({ agent: \"<agent-name>\", message: \"...\" }).\nUse list_agents({}) to find your collaborator agents and their names."}]},"role":"user","id":"{{sessionId}}"},"surfaceOp":"append"}
{"type":"request/header","data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash"},"tools":"{{tools}}"},"reason":"initial","startsSeries":true}}
{"type":"request/context","data":{"provider":"deepseek-official","model":"deepseek-v4-flash"}}
{"type":"session/title","data":{"title":"Perform one side-effecting remote mutati","messageSeqs":[3],"source":{"kind":"fallback"}}}
@@ -16,13 +16,13 @@
{"type":"step/start","data":{"turn":2,"step":1}}
{"type":"system/message","data":{"turn":2,"step":1,"message":{"role":"system","content":[{"type":"text","text":"{{system}}"}],"source":{"kind":"system-prompt"},"id":"{{sessionId}}"}},"sourceEventSeqs":[2],"surfaceOp":{"op":"replace","startSeq":2,"endSeq":2}}
{"type":"user/message","data":{"content":[{"type":"text","text":"Call list_agents once and report what it shows."}],"source":{"kind":"user"},"role":"user","id":"{{sessionId}}"},"surfaceOp":"append"}
{"type":"user/message","data":{"content":[{"type":"text","text":"Current runtime context. This snapshot supersedes earlier runtime-context snapshots.\n\nCurrent working directory: \"{{cwd}}\".\n\nCurrent DSH file policy: workspace-write. Any available operation enforced by the DSH file sandbox may modify files under the session workspace: \"{{cwd}}\". Some platform temporary areas may also be writable.\n\nApproval prompts are enabled in this session: operations that require approval may ask through the configured answerers; without an available answerer, the request fails closed.\n\nYou are the root agent. Your agent id is \"{{sessionId}}\".\n\nTo message other agents, use send_message({ agent_id: \"<agent-id>\", message: \"...\" }).\nUse list_agents({}) to find your collaborator agents and their ids."}],"source":{"kind":"runtime-context","form":"snapshot","sections":[{"name":"working-directory:current","text":"Current working directory: \"{{cwd}}\"."},{"name":"sandbox:policy","text":"Current DSH file policy: workspace-write. Any available operation enforced by the DSH file sandbox may modify files under the session workspace: \"{{cwd}}\". Some platform temporary areas may also be writable."},{"name":"approval:policy","text":"Approval prompts are enabled in this session: operations that require approval may ask through the configured answerers; without an available answerer, the request fails closed."},{"name":"subagent:identity","text":"You are the root agent. Your agent id is \"{{sessionId}}\".\n\nTo message other agents, use send_message({ agent_id: \"<agent-id>\", message: \"...\" }).\nUse list_agents({}) to find your collaborator agents and their ids."}]},"role":"user","id":"{{sessionId}}"},"surfaceOp":"append"}
{"type":"user/message","data":{"content":[{"type":"text","text":"Current runtime context. This snapshot supersedes earlier runtime-context snapshots.\n\nCurrent working directory: \"{{cwd}}\".\n\nCurrent DSH file policy: workspace-write. Any available operation enforced by the DSH file sandbox may modify files under the session workspace: \"{{cwd}}\". Some platform temporary areas may also be writable.\n\nApproval prompts are enabled in this session: operations that require approval may ask through the configured answerers; without an available answerer, the request fails closed.\n\nYou are the root agent. Your name is \"lead\".\n\nTo message other agents, use send_message({ agent: \"<agent-name>\", message: \"...\" }).\nUse list_agents({}) to find your collaborator agents and their names."}],"source":{"kind":"runtime-context","form":"snapshot","sections":[{"name":"working-directory:current","text":"Current working directory: \"{{cwd}}\"."},{"name":"sandbox:policy","text":"Current DSH file policy: workspace-write. Any available operation enforced by the DSH file sandbox may modify files under the session workspace: \"{{cwd}}\". Some platform temporary areas may also be writable."},{"name":"approval:policy","text":"Approval prompts are enabled in this session: operations that require approval may ask through the configured answerers; without an available answerer, the request fails closed."},{"name":"subagent:identity","text":"You are the root agent. Your name is \"lead\".\n\nTo message other agents, use send_message({ agent: \"<agent-name>\", message: \"...\" }).\nUse list_agents({}) to find your collaborator agents and their names."}]},"role":"user","id":"{{sessionId}}"},"surfaceOp":"append"}
{"type":"request/header","data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash"},"tools":"{{tools}}"},"reason":"initial","startsSeries":true}}
{"type":"request/context","data":{"provider":"deepseek-official","model":"deepseek-v4-flash"}}
{"type":"session/title","data":{"title":"Start a background job.","messageSeqs":[3],"source":{"kind":"fallback"}}}
{"type":"assistant/message","data":{"turn":2,"step":1,"message":{"role":"assistant","content":[{"type":"tool-call","id":"list-once","name":"list_agents","arguments":"{}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{sessionId}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":0,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":0,"index":0,"dt":[],"id":"list-once","name":"list_agents","args":["{}"]},{"type":"chunk","time":0,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"list-once","name":"list_agents","arguments":"{}"}}},{"type":"chunk","time":0,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":0,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"}
{"type":"tool/call","data":{"turn":2,"step":1,"callId":"list-once","name":"list_agents","arguments":"{}"}}
{"type":"tool/result","data":{"turn":2,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"list-once"},"toolCallId":"list-once","content":[{"type":"text","text":"{{sessionId}} [running] — root agent\n{{sessionId}} [inactive] parent={{sessionId}} depth=1 — descriptorless child"}],"isError":false,"id":"{{sessionId}}"}},"sourceEventSeqs":[22],"surfaceOp":"append"}
{"type":"tool/result","data":{"turn":2,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"list-once"},"toolCallId":"list-once","content":[{"type":"text","text":"lead [running] — root agent\n{{sessionId}} [inactive] — descriptorless child"}],"isError":false,"id":"{{sessionId}}"}},"sourceEventSeqs":[22],"surfaceOp":"append"}
{"type":"step/end","data":{"turn":2,"step":1}}
{"type":"step/start","data":{"turn":2,"step":2}}
{"type":"assistant/message","data":{"turn":2,"step":2,"message":{"role":"assistant","content":[{"type":"text","text":"The catalogued subagent is ready. PARENT_DONE"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{sessionId}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":0,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"text-chunks","time0":0,"index":0,"dt":[],"texts":["The catalogued subagent is ready. PARENT_DONE"]},{"type":"chunk","time":0,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"The catalogued subagent is ready. PARENT_DONE"}}},{"type":"chunk","time":0,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":0,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"}
@@ -8,7 +8,7 @@
{"type":"step/start","data":{"turn":1,"step":1}}
{"type":"system/message","data":{"turn":1,"step":1,"message":{"role":"system","content":[{"type":"text","text":"{{system}}"}],"source":{"kind":"system-prompt"},"id":"{{sessionId}}"}},"surfaceOp":"append"}
{"type":"user/message","data":{"content":[{"type":"text","text":"Use the write tool exactly once with file_path set to exactly the relative path inherited.txt and content escaped. If the write is denied, reply with the single word CHILD_DENIED and the denial marker line; do not retry and do not request escalation. If it succeeds, reply CHILD_WROTE."},{"type":"text","text":"Your final answer is delivered automatically if your parent is still online. Include the result and relevant evidence in that answer; the parent does not receive your full transcript, tool output, or reasoning. If your last action is a message to your parent, the completion notice omits your final answer; include the result and relevant evidence in that message."}],"source":{"kind":"user"},"role":"user","id":"{{sessionId}}"},"surfaceOp":"append"}
{"type":"user/message","data":{"content":[{"type":"text","text":"Current runtime context. This snapshot supersedes earlier runtime-context snapshots.\n\nCurrent working directory: \"{{cwd}}\".\n\nCurrent DSH file policy: read-only. Any available operation enforced by the DSH file sandbox cannot modify files in the standing mode. Do not refuse a required modification from this policy alone: try an available tool normally and follow any denial and escalation guidance it returns.\n\nApproval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`).\n\nYou are a subagent delegated by agent \"{{sessionId}}\".\nYour agent id is \"{{sessionId}}\".\nThe root agent of your collaboration tree is \"{{sessionId}}\".\n\nTo message other agents, use send_message({ agent_id: \"<agent-id>\", message: \"...\" }).\nUse list_agents({}) to find your collaborator agents and their ids.\n\nDelegation depth for `subagent`: current 1, maximum 1, remaining levels 0. Do not call `subagent` at this depth; carry out the work directly.\n\nDelegation depth for `subagent_fork`: current 1, maximum 1, remaining levels 0. Do not call `subagent_fork` at this depth; carry out the work directly.\n\nYou are a delegated subagent: your permission scope was fixed when you were started and cannot be widened from inside this session — operations that require approval are rejected automatically. When the task needs access beyond that scope, do not retry the denied operation; state the limitation in your reply so the delegating agent can handle it."}],"source":{"kind":"runtime-context","form":"snapshot","sections":[{"name":"working-directory:current","text":"Current working directory: \"{{cwd}}\"."},{"name":"sandbox:policy","text":"Current DSH file policy: read-only. Any available operation enforced by the DSH file sandbox cannot modify files in the standing mode. Do not refuse a required modification from this policy alone: try an available tool normally and follow any denial and escalation guidance it returns."},{"name":"approval:policy","text":"Approval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`)."},{"name":"subagent:identity","text":"You are a subagent delegated by agent \"{{sessionId}}\".\nYour agent id is \"{{sessionId}}\".\nThe root agent of your collaboration tree is \"{{sessionId}}\".\n\nTo message other agents, use send_message({ agent_id: \"<agent-id>\", message: \"...\" }).\nUse list_agents({}) to find your collaborator agents and their ids."},{"name":"tool:subagent:depth","text":"Delegation depth for `subagent`: current 1, maximum 1, remaining levels 0. Do not call `subagent` at this depth; carry out the work directly."},{"name":"tool:subagent_fork:depth","text":"Delegation depth for `subagent_fork`: current 1, maximum 1, remaining levels 0. Do not call `subagent_fork` at this depth; carry out the work directly."},{"name":"subagent:delegation","text":"You are a delegated subagent: your permission scope was fixed when you were started and cannot be widened from inside this session — operations that require approval are rejected automatically. When the task needs access beyond that scope, do not retry the denied operation; state the limitation in your reply so the delegating agent can handle it."}]},"role":"user","id":"{{sessionId}}"},"surfaceOp":"append"}
{"type":"user/message","data":{"content":[{"type":"text","text":"Current runtime context. This snapshot supersedes earlier runtime-context snapshots.\n\nCurrent working directory: \"{{cwd}}\".\n\nCurrent DSH file policy: read-only. Any available operation enforced by the DSH file sandbox cannot modify files in the standing mode. Do not refuse a required modification from this policy alone: try an available tool normally and follow any denial and escalation guidance it returns.\n\nApproval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`).\n\nYou are a subagent delegated by agent \"lead\".\nYour name is \"agent-1\".\nThe root agent of your collaboration tree is \"lead\".\n\nTo message other agents, use send_message({ agent: \"<agent-name>\", message: \"...\" }).\nUse list_agents({}) to find your collaborator agents and their names.\n\nDelegation depth for `subagent`: current 1, maximum 1, remaining levels 0. Do not call `subagent` at this depth; carry out the work directly.\n\nDelegation depth for `subagent_fork`: current 1, maximum 1, remaining levels 0. Do not call `subagent_fork` at this depth; carry out the work directly.\n\nYou are a delegated subagent: your permission scope was fixed when you were started and cannot be widened from inside this session — operations that require approval are rejected automatically. When the task needs access beyond that scope, do not retry the denied operation; state the limitation in your reply so the delegating agent can handle it."}],"source":{"kind":"runtime-context","form":"snapshot","sections":[{"name":"working-directory:current","text":"Current working directory: \"{{cwd}}\"."},{"name":"sandbox:policy","text":"Current DSH file policy: read-only. Any available operation enforced by the DSH file sandbox cannot modify files in the standing mode. Do not refuse a required modification from this policy alone: try an available tool normally and follow any denial and escalation guidance it returns."},{"name":"approval:policy","text":"Approval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`)."},{"name":"subagent:identity","text":"You are a subagent delegated by agent \"lead\".\nYour name is \"agent-1\".\nThe root agent of your collaboration tree is \"lead\".\n\nTo message other agents, use send_message({ agent: \"<agent-name>\", message: \"...\" }).\nUse list_agents({}) to find your collaborator agents and their names."},{"name":"tool:subagent:depth","text":"Delegation depth for `subagent`: current 1, maximum 1, remaining levels 0. Do not call `subagent` at this depth; carry out the work directly."},{"name":"tool:subagent_fork:depth","text":"Delegation depth for `subagent_fork`: current 1, maximum 1, remaining levels 0. Do not call `subagent_fork` at this depth; carry out the work directly."},{"name":"subagent:delegation","text":"You are a delegated subagent: your permission scope was fixed when you were started and cannot be widened from inside this session — operations that require approval are rejected automatically. When the task needs access beyond that scope, do not retry the denied operation; state the limitation in your reply so the delegating agent can handle it."}]},"role":"user","id":"{{sessionId}}"},"surfaceOp":"append"}
{"type":"request/header","data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash","reasoningEffort":"low"},"tools":"{{tools}}"},"reason":"initial"}}
{"type":"request/context","data":{"provider":"deepseek-official","model":"deepseek-v4-flash"}}
{"type":"session/title","data":{"title":"Use the write tool exactly","messageSeqs":[8],"source":{"kind":"fallback"}}}
@@ -16,20 +16,20 @@
{"type":"step/start","data":{"turn":2,"step":1}}
{"type":"system/message","data":{"turn":2,"step":1,"message":{"role":"system","content":[{"type":"text","text":"{{system}}"}],"source":{"kind":"system-prompt"},"id":"{{sessionId}}"}},"sourceEventSeqs":[2],"surfaceOp":{"op":"replace","startSeq":2,"endSeq":2}}
{"type":"user/message","data":{"content":[{"type":"text","text":"Delegate the write probe to a subagent."}],"source":{"kind":"user"},"role":"user","id":"{{sessionId}}"},"surfaceOp":"append"}
{"type":"user/message","data":{"content":[{"type":"text","text":"Current runtime context. This snapshot supersedes earlier runtime-context snapshots.\n\nCurrent working directory: \"{{cwd}}\".\n\nCurrent DSH file policy: read-only. Any available operation enforced by the DSH file sandbox cannot modify files in the standing mode. Do not refuse a required modification from this policy alone: try an available tool normally and follow any denial and escalation guidance it returns.\n\nApproval prompts are enabled in this session: operations that require approval may ask through the configured answerers; without an available answerer, the request fails closed.\n\nYou are the root agent. Your agent id is \"{{sessionId}}\".\n\nTo message other agents, use send_message({ agent_id: \"<agent-id>\", message: \"...\" }).\nUse list_agents({}) to find your collaborator agents and their ids."}],"source":{"kind":"runtime-context","form":"snapshot","sections":[{"name":"working-directory:current","text":"Current working directory: \"{{cwd}}\"."},{"name":"sandbox:policy","text":"Current DSH file policy: read-only. Any available operation enforced by the DSH file sandbox cannot modify files in the standing mode. Do not refuse a required modification from this policy alone: try an available tool normally and follow any denial and escalation guidance it returns."},{"name":"approval:policy","text":"Approval prompts are enabled in this session: operations that require approval may ask through the configured answerers; without an available answerer, the request fails closed."},{"name":"subagent:identity","text":"You are the root agent. Your agent id is \"{{sessionId}}\".\n\nTo message other agents, use send_message({ agent_id: \"<agent-id>\", message: \"...\" }).\nUse list_agents({}) to find your collaborator agents and their ids."}]},"role":"user","id":"{{sessionId}}"},"surfaceOp":"append"}
{"type":"user/message","data":{"content":[{"type":"text","text":"Current runtime context. This snapshot supersedes earlier runtime-context snapshots.\n\nCurrent working directory: \"{{cwd}}\".\n\nCurrent DSH file policy: read-only. Any available operation enforced by the DSH file sandbox cannot modify files in the standing mode. Do not refuse a required modification from this policy alone: try an available tool normally and follow any denial and escalation guidance it returns.\n\nApproval prompts are enabled in this session: operations that require approval may ask through the configured answerers; without an available answerer, the request fails closed.\n\nYou are the root agent. Your name is \"lead\".\n\nTo message other agents, use send_message({ agent: \"<agent-name>\", message: \"...\" }).\nUse list_agents({}) to find your collaborator agents and their names."}],"source":{"kind":"runtime-context","form":"snapshot","sections":[{"name":"working-directory:current","text":"Current working directory: \"{{cwd}}\"."},{"name":"sandbox:policy","text":"Current DSH file policy: read-only. Any available operation enforced by the DSH file sandbox cannot modify files in the standing mode. Do not refuse a required modification from this policy alone: try an available tool normally and follow any denial and escalation guidance it returns."},{"name":"approval:policy","text":"Approval prompts are enabled in this session: operations that require approval may ask through the configured answerers; without an available answerer, the request fails closed."},{"name":"subagent:identity","text":"You are the root agent. Your name is \"lead\".\n\nTo message other agents, use send_message({ agent: \"<agent-name>\", message: \"...\" }).\nUse list_agents({}) to find your collaborator agents and their names."}]},"role":"user","id":"{{sessionId}}"},"surfaceOp":"append"}
{"type":"request/header","data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash","reasoningEffort":"low"},"tools":["apply_patch","bash","create_goal","edit","get_goal","glob","grep","interrupt_agent","job_kill","job_list","job_output","list_agents","read","read_image","send_message","skill","subagent","subagent_fork","todo_write","update_goal","wait_agent","web_fetch","web_search","workflow","working_directory","write"]},"reason":"resume","startsSeries":true}}
{"type":"developer/message","data":{"turn":2,"step":1,"message":{"source":{"kind":"tool-registry"},"content":[{"type":"tool-addition","toolName":"apply_patch"},{"type":"tool-addition","toolName":"bash"},{"type":"tool-addition","toolName":"create_goal"},{"type":"tool-addition","toolName":"edit"},{"type":"tool-addition","toolName":"get_goal"},{"type":"tool-addition","toolName":"glob"},{"type":"tool-addition","toolName":"grep"},{"type":"tool-addition","toolName":"interrupt_agent"},{"type":"tool-addition","toolName":"job_kill"},{"type":"tool-addition","toolName":"job_list"},{"type":"tool-addition","toolName":"job_output"},{"type":"tool-addition","toolName":"list_agents"},{"type":"tool-addition","toolName":"read"},{"type":"tool-addition","toolName":"read_image"},{"type":"tool-addition","toolName":"send_message"},{"type":"tool-addition","toolName":"skill"},{"type":"tool-addition","toolName":"subagent"},{"type":"tool-addition","toolName":"subagent_fork"},{"type":"tool-addition","toolName":"todo_write"},{"type":"tool-addition","toolName":"update_goal"},{"type":"tool-addition","toolName":"wait_agent"},{"type":"tool-addition","toolName":"web_fetch"},{"type":"tool-addition","toolName":"web_search"},{"type":"tool-addition","toolName":"workflow"},{"type":"tool-addition","toolName":"working_directory"},{"type":"tool-addition","toolName":"write"}],"role":"developer","id":"{{sessionId}}"},"headerSeq":18},"surfaceOp":"append"}
{"type":"request/context","data":{"provider":"deepseek-official","model":"deepseek-v4-flash"}}
{"type":"session/title","data":{"title":"Tighten this session to read-only.","messageSeqs":[3],"source":{"kind":"fallback"}}}
{"type":"assistant/message","data":{"turn":2,"step":1,"message":{"role":"assistant","content":[{"type":"tool-call","id":"delegate-write","name":"subagent","arguments":"{\"description\": \"Delegated write probe\", \"prompt\": \"Use the write tool exactly once with file_path set to exactly the relative path inherited.txt and content escaped. If the write is denied, reply with the single word CHILD_DENIED and the denial marker line; do not retry and do not request escalation. If it succeeds, reply CHILD_WROTE.\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{sessionId}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":0,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":0,"index":0,"dt":[],"id":"delegate-write","name":"subagent","args":["{\"description\": \"Delegated write probe\", \"prompt\": \"Use the write tool exactly once with file_path set to exactly the relative path inherited.txt and content escaped. If the write is denied, reply with the single word CHILD_DENIED and the denial marker line; do not retry and do not request escalation. If it succeeds, reply CHILD_WROTE.\"}"]},{"type":"chunk","time":0,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"delegate-write","name":"subagent","arguments":"{\"description\": \"Delegated write probe\", \"prompt\": \"Use the write tool exactly once with file_path set to exactly the relative path inherited.txt and content escaped. If the write is denied, reply with the single word CHILD_DENIED and the denial marker line; do not retry and do not request escalation. If it succeeds, reply CHILD_WROTE.\"}"}}},{"type":"chunk","time":0,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":0,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"}
{"type":"tool/call","data":{"turn":2,"step":1,"callId":"delegate-write","name":"subagent","arguments":"{\"description\": \"Delegated write probe\", \"prompt\": \"Use the write tool exactly once with file_path set to exactly the relative path inherited.txt and content escaped. If the write is denied, reply with the single word CHILD_DENIED and the denial marker line; do not retry and do not request escalation. If it succeeds, reply CHILD_WROTE.\"}"}}
{"type":"subagent/catalog","data":{"version":0,"childId":"{{sessionId}}","childCreatedAt":0,"mode":"continuable","label":"Delegated write probe"}}
{"type":"agent/inbox/spliced","data":{"target":"next-step","start":0,"inserted":[{"content":[{"type":"text","text":"Background subagent {{sessionId}} finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"CHILD_DENIED [sandbox: file access denied under read-only mode]"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent {{sessionId}} finished and will do no further work unless you send it more.","stopReason":"completed","senderSessionId":"{{sessionId}}"},"role":"user","id":"{{sessionId}}"}]}}
{"type":"tool/result","data":{"turn":2,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"delegate-write"},"toolCallId":"delegate-write","content":[{"type":"text","text":"started subagent {{sessionId}}"}],"isError":false,"id":"{{sessionId}}"},"meta":{"kind":"activation","subagentId":"{{sessionId}}"}},"sourceEventSeqs":[23],"surfaceOp":"append"}
{"type":"subagent/catalog","data":{"version":3,"childId":"{{sessionId}}","childCreatedAt":0,"mode":"continuable","label":"Delegated write probe","name":"agent-1"}}
{"type":"agent/inbox/spliced","data":{"target":"next-step","start":0,"inserted":[{"content":[{"type":"text","text":"Background subagent agent-1 finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"CHILD_DENIED [sandbox: file access denied under read-only mode]"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent agent-1 finished and will do no further work unless you send it more.","stopReason":"completed","senderSessionId":"{{sessionId}}"},"role":"user","id":"{{sessionId}}"}]}}
{"type":"tool/result","data":{"turn":2,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"delegate-write"},"toolCallId":"delegate-write","content":[{"type":"text","text":"started subagent agent-1"}],"isError":false,"id":"{{sessionId}}"},"meta":{"kind":"activation","subagentId":"{{sessionId}}","name":"agent-1"}},"sourceEventSeqs":[23],"surfaceOp":"append"}
{"type":"step/end","data":{"turn":2,"step":1}}
{"type":"agent/inbox/spliced","data":{"target":"next-step","start":0,"removedCount":1,"inserted":[]}}
{"type":"step/start","data":{"turn":2,"step":2}}
{"type":"user/message","data":{"content":[{"type":"text","text":"Background subagent {{sessionId}} finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"CHILD_DENIED [sandbox: file access denied under read-only mode]"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent {{sessionId}} finished and will do no further work unless you send it more.","stopReason":"completed","senderSessionId":"{{sessionId}}"},"role":"user","id":"{{sessionId}}"},"surfaceOp":"append"}
{"type":"user/message","data":{"content":[{"type":"text","text":"Background subagent agent-1 finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"CHILD_DENIED [sandbox: file access denied under read-only mode]"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent agent-1 finished and will do no further work unless you send it more.","stopReason":"completed","senderSessionId":"{{sessionId}}"},"role":"user","id":"{{sessionId}}"},"surfaceOp":"append"}
{"type":"assistant/message","data":{"turn":2,"step":2,"message":{"role":"assistant","content":[{"type":"text","text":"The delegated child was denied by the sandbox. PARENT_DONE"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{sessionId}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":0,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"text-chunks","time0":0,"index":0,"dt":[],"texts":["The delegated child was denied by the sandbox. PARENT_DONE"]},{"type":"chunk","time":0,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"The delegated child was denied by the sandbox. PARENT_DONE"}}},{"type":"chunk","time":0,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":0,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"}
{"type":"step/end","data":{"turn":2,"step":2}}
{"type":"turn/end","data":{"turn":2,"reason":{"kind":"completed"}}}
@@ -8,7 +8,7 @@
{"type":"step/start","data":{"turn":1,"step":1}}
{"type":"system/message","data":{"turn":1,"step":1,"message":{"role":"system","content":[{"type":"text","text":"{{system}}"}],"source":{"kind":"system-prompt"},"id":"{{sessionId}}"}},"surfaceOp":"append"}
{"type":"user/message","data":{"content":[{"type":"text","text":"Reply with exactly CHILD_RESULT and nothing else. Do not call send_message."},{"type":"text","text":"Your final answer is delivered automatically if your parent is still online. Include the result and relevant evidence in that answer; the parent does not receive your full transcript, tool output, or reasoning. If your last action is a message to your parent, the completion notice omits your final answer; include the result and relevant evidence in that message."}],"source":{"kind":"user"},"role":"user","id":"{{sessionId}}"},"surfaceOp":"append"}
{"type":"user/message","data":{"content":[{"type":"text","text":"Current runtime context. This snapshot supersedes earlier runtime-context snapshots.\n\nCurrent working directory: \"{{cwd}}\".\n\nCurrent DSH file policy: workspace-write. Any available operation enforced by the DSH file sandbox may modify files under the session workspace: \"{{cwd}}\". Some platform temporary areas may also be writable.\n\nApproval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`).\n\nYou are a subagent delegated by agent \"{{sessionId}}\".\nYour agent id is \"{{sessionId}}\".\nThe root agent of your collaboration tree is \"{{sessionId}}\".\n\nTo message other agents, use send_message({ agent_id: \"<agent-id>\", message: \"...\" }).\nUse list_agents({}) to find your collaborator agents and their ids.\n\nDelegation depth for `subagent`: current 1, maximum 1, remaining levels 0. Do not call `subagent` at this depth; carry out the work directly.\n\nDelegation depth for `subagent_fork`: current 1, maximum 1, remaining levels 0. Do not call `subagent_fork` at this depth; carry out the work directly.\n\nYou are a delegated subagent: your permission scope was fixed when you were started and cannot be widened from inside this session — operations that require approval are rejected automatically. When the task needs access beyond that scope, do not retry the denied operation; state the limitation in your reply so the delegating agent can handle it."}],"source":{"kind":"runtime-context","form":"snapshot","sections":[{"name":"working-directory:current","text":"Current working directory: \"{{cwd}}\"."},{"name":"sandbox:policy","text":"Current DSH file policy: workspace-write. Any available operation enforced by the DSH file sandbox may modify files under the session workspace: \"{{cwd}}\". Some platform temporary areas may also be writable."},{"name":"approval:policy","text":"Approval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`)."},{"name":"subagent:identity","text":"You are a subagent delegated by agent \"{{sessionId}}\".\nYour agent id is \"{{sessionId}}\".\nThe root agent of your collaboration tree is \"{{sessionId}}\".\n\nTo message other agents, use send_message({ agent_id: \"<agent-id>\", message: \"...\" }).\nUse list_agents({}) to find your collaborator agents and their ids."},{"name":"tool:subagent:depth","text":"Delegation depth for `subagent`: current 1, maximum 1, remaining levels 0. Do not call `subagent` at this depth; carry out the work directly."},{"name":"tool:subagent_fork:depth","text":"Delegation depth for `subagent_fork`: current 1, maximum 1, remaining levels 0. Do not call `subagent_fork` at this depth; carry out the work directly."},{"name":"subagent:delegation","text":"You are a delegated subagent: your permission scope was fixed when you were started and cannot be widened from inside this session — operations that require approval are rejected automatically. When the task needs access beyond that scope, do not retry the denied operation; state the limitation in your reply so the delegating agent can handle it."}]},"role":"user","id":"{{sessionId}}"},"surfaceOp":"append"}
{"type":"user/message","data":{"content":[{"type":"text","text":"Current runtime context. This snapshot supersedes earlier runtime-context snapshots.\n\nCurrent working directory: \"{{cwd}}\".\n\nCurrent DSH file policy: workspace-write. Any available operation enforced by the DSH file sandbox may modify files under the session workspace: \"{{cwd}}\". Some platform temporary areas may also be writable.\n\nApproval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`).\n\nYou are a subagent delegated by agent \"lead\".\nYour name is \"agent-1\".\nThe root agent of your collaboration tree is \"lead\".\n\nTo message other agents, use send_message({ agent: \"<agent-name>\", message: \"...\" }).\nUse list_agents({}) to find your collaborator agents and their names.\n\nDelegation depth for `subagent`: current 1, maximum 1, remaining levels 0. Do not call `subagent` at this depth; carry out the work directly.\n\nDelegation depth for `subagent_fork`: current 1, maximum 1, remaining levels 0. Do not call `subagent_fork` at this depth; carry out the work directly.\n\nYou are a delegated subagent: your permission scope was fixed when you were started and cannot be widened from inside this session — operations that require approval are rejected automatically. When the task needs access beyond that scope, do not retry the denied operation; state the limitation in your reply so the delegating agent can handle it."}],"source":{"kind":"runtime-context","form":"snapshot","sections":[{"name":"working-directory:current","text":"Current working directory: \"{{cwd}}\"."},{"name":"sandbox:policy","text":"Current DSH file policy: workspace-write. Any available operation enforced by the DSH file sandbox may modify files under the session workspace: \"{{cwd}}\". Some platform temporary areas may also be writable."},{"name":"approval:policy","text":"Approval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`)."},{"name":"subagent:identity","text":"You are a subagent delegated by agent \"lead\".\nYour name is \"agent-1\".\nThe root agent of your collaboration tree is \"lead\".\n\nTo message other agents, use send_message({ agent: \"<agent-name>\", message: \"...\" }).\nUse list_agents({}) to find your collaborator agents and their names."},{"name":"tool:subagent:depth","text":"Delegation depth for `subagent`: current 1, maximum 1, remaining levels 0. Do not call `subagent` at this depth; carry out the work directly."},{"name":"tool:subagent_fork:depth","text":"Delegation depth for `subagent_fork`: current 1, maximum 1, remaining levels 0. Do not call `subagent_fork` at this depth; carry out the work directly."},{"name":"subagent:delegation","text":"You are a delegated subagent: your permission scope was fixed when you were started and cannot be widened from inside this session — operations that require approval are rejected automatically. When the task needs access beyond that scope, do not retry the denied operation; state the limitation in your reply so the delegating agent can handle it."}]},"role":"user","id":"{{sessionId}}"},"surfaceOp":"append"}
{"type":"request/header","data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash"},"tools":"{{tools}}"},"reason":"initial"}}
{"type":"request/context","data":{"provider":"deepseek-official","model":"deepseek-v4-flash"}}
{"type":"session/title","data":{"title":"Reply with exactly CHILD_RESULT and","messageSeqs":[8],"source":{"kind":"fallback"}}}
@@ -4,7 +4,7 @@
{"type":"session_event","sessionId":"{{sessionId}}","event":{"type":"step/start","seq":6,"time":0,"data":{"turn":1,"step":1}}}
{"type":"session_event","sessionId":"{{sessionId}}","event":{"type":"system/message","seq":7,"time":0,"data":{"turn":1,"step":1,"message":{"role":"system","content":[{"type":"text","text":"{{system}}"}],"source":{"kind":"system-prompt"},"id":"{{sessionId}}"}},"surfaceOp":"append"}}
{"type":"session_event","sessionId":"{{sessionId}}","event":{"type":"user/message","seq":8,"time":0,"data":{"content":[{"type":"text","text":"Start one continuable subagent and acknowledge its completion notice. Do not call list_agents or send_message."}],"source":{"kind":"user"},"role":"user","id":"{{sessionId}}"},"surfaceOp":"append"}}
{"type":"session_event","sessionId":"{{sessionId}}","event":{"type":"user/message","seq":9,"time":0,"data":{"content":[{"type":"text","text":"Current runtime context. This snapshot supersedes earlier runtime-context snapshots.\n\nCurrent working directory: \"{{cwd}}\".\n\nCurrent DSH file policy: workspace-write. Any available operation enforced by the DSH file sandbox may modify files under the session workspace: \"{{cwd}}\". Some platform temporary areas may also be writable.\n\nApproval prompts are enabled in this session: operations that require approval may ask through the configured answerers; without an available answerer, the request fails closed.\n\nYou are the root agent. Your agent id is \"{{sessionId}}\".\n\nTo message other agents, use send_message({ agent_id: \"<agent-id>\", message: \"...\" }).\nUse list_agents({}) to find your collaborator agents and their ids."}],"source":{"kind":"runtime-context","form":"snapshot","sections":[{"name":"working-directory:current","text":"Current working directory: \"{{cwd}}\"."},{"name":"sandbox:policy","text":"Current DSH file policy: workspace-write. Any available operation enforced by the DSH file sandbox may modify files under the session workspace: \"{{cwd}}\". Some platform temporary areas may also be writable."},{"name":"approval:policy","text":"Approval prompts are enabled in this session: operations that require approval may ask through the configured answerers; without an available answerer, the request fails closed."},{"name":"subagent:identity","text":"You are the root agent. Your agent id is \"{{sessionId}}\".\n\nTo message other agents, use send_message({ agent_id: \"<agent-id>\", message: \"...\" }).\nUse list_agents({}) to find your collaborator agents and their ids."}]},"role":"user","id":"{{sessionId}}"},"surfaceOp":"append"}}
{"type":"session_event","sessionId":"{{sessionId}}","event":{"type":"user/message","seq":9,"time":0,"data":{"content":[{"type":"text","text":"Current runtime context. This snapshot supersedes earlier runtime-context snapshots.\n\nCurrent working directory: \"{{cwd}}\".\n\nCurrent DSH file policy: workspace-write. Any available operation enforced by the DSH file sandbox may modify files under the session workspace: \"{{cwd}}\". Some platform temporary areas may also be writable.\n\nApproval prompts are enabled in this session: operations that require approval may ask through the configured answerers; without an available answerer, the request fails closed.\n\nYou are the root agent. Your name is \"lead\".\n\nTo message other agents, use send_message({ agent: \"<agent-name>\", message: \"...\" }).\nUse list_agents({}) to find your collaborator agents and their names."}],"source":{"kind":"runtime-context","form":"snapshot","sections":[{"name":"working-directory:current","text":"Current working directory: \"{{cwd}}\"."},{"name":"sandbox:policy","text":"Current DSH file policy: workspace-write. Any available operation enforced by the DSH file sandbox may modify files under the session workspace: \"{{cwd}}\". Some platform temporary areas may also be writable."},{"name":"approval:policy","text":"Approval prompts are enabled in this session: operations that require approval may ask through the configured answerers; without an available answerer, the request fails closed."},{"name":"subagent:identity","text":"You are the root agent. Your name is \"lead\".\n\nTo message other agents, use send_message({ agent: \"<agent-name>\", message: \"...\" }).\nUse list_agents({}) to find your collaborator agents and their names."}]},"role":"user","id":"{{sessionId}}"},"surfaceOp":"append"}}
{"type":"session_event","sessionId":"{{sessionId}}","event":{"type":"request/header","seq":10,"time":0,"data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash"},"tools":"{{tools}}"},"reason":"initial"}}}
{"type":"session_event","sessionId":"{{sessionId}}","event":{"type":"request/context","seq":11,"time":0,"data":{"provider":"deepseek-official","model":"deepseek-v4-flash"}}}
{"type":"session_event","sessionId":"{{sessionId}}","event":{"type":"session/title","seq":12,"time":0,"data":{"title":"Start one continuable subagent and","messageSeqs":[8],"source":{"kind":"fallback"}}}}
@@ -12,16 +12,16 @@
{"type":"session_event","sessionId":"{{sessionId}}","event":{"type":"assistant/message","seq":14,"time":0,"data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"tool-call","id":"start-child","name":"subagent","arguments":"{\"description\":\"Return child result\",\"prompt\":\"Reply with exactly CHILD_RESULT and nothing else. Do not call send_message.\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{sessionId}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":0,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":0,"index":0,"dt":[],"id":"start-child","name":"subagent","args":["{\"description\":\"Return child result\",\"prompt\":\"Reply with exactly CHILD_RESULT and nothing else. Do not call send_message.\"}"]},{"type":"chunk","time":0,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"start-child","name":"subagent","arguments":"{\"description\":\"Return child result\",\"prompt\":\"Reply with exactly CHILD_RESULT and nothing else. Do not call send_message.\"}"}}},{"type":"chunk","time":0,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":0,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"}}
{"type":"session_event","sessionId":"{{sessionId}}","event":{"type":"tool/call","seq":15,"time":0,"data":{"turn":1,"step":1,"callId":"start-child","name":"subagent","arguments":"{\"description\":\"Return child result\",\"prompt\":\"Reply with exactly CHILD_RESULT and nothing else. Do not call send_message.\"}"}}}
{"type":"session_event","sessionId":"{{sessionId}}","event":{"type":"session/title","seq":16,"time":0,"data":{"title":"Subagent settlement","messageSeqs":[8],"source":{"kind":"provider","provider":"session-title-first-prompt-llm","model":{"provider":"deepseek-official","model":"deepseek-v4-flash"}}}}}
{"type":"session_event","sessionId":"{{sessionId}}","event":{"type":"subagent/catalog","seq":17,"time":0,"data":{"version":0,"childId":"{{sessionId}}","childCreatedAt":0,"mode":"continuable","label":"Return child result"}}}
{"type":"session_event","sessionId":"{{sessionId}}","event":{"type":"tool/result","seq":18,"time":0,"data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"start-child"},"toolCallId":"start-child","content":[{"type":"text","text":"started subagent {{sessionId}}"}],"isError":false,"id":"{{sessionId}}"},"meta":{"kind":"activation","subagentId":"{{sessionId}}"}},"sourceEventSeqs":[15],"surfaceOp":"append"}}
{"type":"session_event","sessionId":"{{sessionId}}","event":{"type":"subagent/catalog","seq":17,"time":0,"data":{"version":3,"childId":"{{sessionId}}","childCreatedAt":0,"mode":"continuable","label":"Return child result","name":"agent-1"}}}
{"type":"session_event","sessionId":"{{sessionId}}","event":{"type":"tool/result","seq":18,"time":0,"data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"start-child"},"toolCallId":"start-child","content":[{"type":"text","text":"started subagent agent-1"}],"isError":false,"id":"{{sessionId}}"},"meta":{"kind":"activation","subagentId":"{{sessionId}}","name":"agent-1"}},"sourceEventSeqs":[15],"surfaceOp":"append"}}
{"type":"session_event","sessionId":"{{sessionId}}","event":{"type":"step/end","seq":19,"time":0,"data":{"turn":1,"step":1}}}
{"type":"session_event","sessionId":"{{sessionId}}","event":{"type":"agent/inbox/spliced","seq":20,"time":0,"data":{"target":"next-step","start":0,"inserted":[{"content":[{"type":"text","text":"Background subagent {{sessionId}} finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"CHILD_RESULT"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent {{sessionId}} finished and will do no further work unless you send it more.","stopReason":"completed","senderSessionId":"{{sessionId}}"},"role":"user","id":"{{sessionId}}"}]}}}
{"type":"session_event","sessionId":"{{sessionId}}","event":{"type":"agent/inbox/spliced","seq":20,"time":0,"data":{"target":"next-step","start":0,"inserted":[{"content":[{"type":"text","text":"Background subagent agent-1 finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"CHILD_RESULT"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent agent-1 finished and will do no further work unless you send it more.","stopReason":"completed","senderSessionId":"{{sessionId}}"},"role":"user","id":"{{sessionId}}"}]}}}
{"type":"session_event","sessionId":"{{sessionId}}","event":{"type":"step/start","seq":21,"time":0,"data":{"turn":1,"step":2}}}
{"type":"session_event","sessionId":"{{sessionId}}","event":{"type":"assistant/message","seq":22,"time":0,"data":{"turn":1,"step":2,"message":{"role":"assistant","content":[{"type":"text","text":"STARTED"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{sessionId}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":0,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"text-chunks","time0":0,"index":0,"dt":[],"texts":["STARTED"]},{"type":"chunk","time":0,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"STARTED"}}},{"type":"chunk","time":0,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":0,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"}}
{"type":"session_event","sessionId":"{{sessionId}}","event":{"type":"step/end","seq":23,"time":0,"data":{"turn":1,"step":2}}}
{"type":"session_event","sessionId":"{{sessionId}}","event":{"type":"agent/inbox/spliced","seq":24,"time":0,"data":{"target":"next-step","start":0,"removedCount":1,"inserted":[]}}}
{"type":"session_event","sessionId":"{{sessionId}}","event":{"type":"step/start","seq":25,"time":0,"data":{"turn":1,"step":3}}}
{"type":"session_event","sessionId":"{{sessionId}}","event":{"type":"user/message","seq":26,"time":0,"data":{"content":[{"type":"text","text":"Background subagent {{sessionId}} finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"CHILD_RESULT"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent {{sessionId}} finished and will do no further work unless you send it more.","stopReason":"completed","senderSessionId":"{{sessionId}}"},"role":"user","id":"{{sessionId}}"},"surfaceOp":"append"}}
{"type":"session_event","sessionId":"{{sessionId}}","event":{"type":"user/message","seq":26,"time":0,"data":{"content":[{"type":"text","text":"Background subagent agent-1 finished and will do no further work unless you send it more."},{"type":"text","text":"Its closing message:"},{"type":"text","text":"CHILD_RESULT"}],"source":{"kind":"subagent-settled","form":"notice","summary":"Background subagent agent-1 finished and will do no further work unless you send it more.","stopReason":"completed","senderSessionId":"{{sessionId}}"},"role":"user","id":"{{sessionId}}"},"surfaceOp":"append"}}
{"type":"session_event","sessionId":"{{sessionId}}","event":{"type":"assistant/message","seq":27,"time":0,"data":{"turn":1,"step":3,"message":{"role":"assistant","content":[{"type":"text","text":"PARENT_RECEIVED_SETTLEMENT_NOTICE"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{sessionId}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":0,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"text-chunks","time0":0,"index":0,"dt":[],"texts":["PARENT_RECEIVED_SETTLEMENT_NOTICE"]},{"type":"chunk","time":0,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"PARENT_RECEIVED_SETTLEMENT_NOTICE"}}},{"type":"chunk","time":0,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":0,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"}}
{"type":"session_event","sessionId":"{{sessionId}}","event":{"type":"step/end","seq":28,"time":0,"data":{"turn":1,"step":3}}}
{"type":"session_event","sessionId":"{{sessionId}}","event":{"type":"turn/end","seq":29,"time":0,"data":{"turn":1,"reason":{"kind":"completed"}}}}
@@ -17,7 +17,7 @@
{"type":"system/message","data":{"turn":2,"step":1,"message":{"role":"system","content":[{"type":"text","text":"{{system}}"}],"source":{"kind":"system-prompt"},"id":"{{sessionId}}"}},"sourceEventSeqs":[2],"surfaceOp":{"op":"replace","startSeq":2,"endSeq":2}}
{"type":"user/message","data":{"content":[{"type":"text","text":"Acknowledge the current workspace instruction."}],"source":{"kind":"user"},"role":"user","id":"{{sessionId}}"},"surfaceOp":"append"}
{"type":"user/message","data":{"content":[{"type":"text","text":"<system-reminder>\nUpdated instructions from: AGENTS.md\n\nThis file changed after it was loaded. Use the following content instead of the previously loaded instructions from this file.\n\nNew workspace instruction after offline edit.\n\n</system-reminder>"}],"source":{"kind":"agent-instructions","form":"instructions","changes":[{"action":"replace","scope":".\u0000AGENTS.md","path":"AGENTS.md","digest":"d8375b516f158718bd3463bc8eb7ed42c011b29f"}]},"role":"user","id":"{{sessionId}}"},"surfaceOp":"append"}
{"type":"user/message","data":{"content":[{"type":"text","text":"Current runtime context. This snapshot supersedes earlier runtime-context snapshots.\n\nCurrent working directory: \"{{cwd}}\".\n\nCurrent DSH file policy: workspace-write. Any available operation enforced by the DSH file sandbox may modify files under the session workspace: \"{{cwd}}\". Some platform temporary areas may also be writable.\n\nApproval prompts are enabled in this session: operations that require approval may ask through the configured answerers; without an available answerer, the request fails closed.\n\nYou are the root agent. Your agent id is \"{{sessionId}}\".\n\nTo message other agents, use send_message({ agent_id: \"<agent-id>\", message: \"...\" }).\nUse list_agents({}) to find your collaborator agents and their ids."}],"source":{"kind":"runtime-context","form":"snapshot","sections":[{"name":"working-directory:current","text":"Current working directory: \"{{cwd}}\"."},{"name":"sandbox:policy","text":"Current DSH file policy: workspace-write. Any available operation enforced by the DSH file sandbox may modify files under the session workspace: \"{{cwd}}\". Some platform temporary areas may also be writable."},{"name":"approval:policy","text":"Approval prompts are enabled in this session: operations that require approval may ask through the configured answerers; without an available answerer, the request fails closed."},{"name":"subagent:identity","text":"You are the root agent. Your agent id is \"{{sessionId}}\".\n\nTo message other agents, use send_message({ agent_id: \"<agent-id>\", message: \"...\" }).\nUse list_agents({}) to find your collaborator agents and their ids."}]},"role":"user","id":"{{sessionId}}"},"surfaceOp":"append"}
{"type":"user/message","data":{"content":[{"type":"text","text":"Current runtime context. This snapshot supersedes earlier runtime-context snapshots.\n\nCurrent working directory: \"{{cwd}}\".\n\nCurrent DSH file policy: workspace-write. Any available operation enforced by the DSH file sandbox may modify files under the session workspace: \"{{cwd}}\". Some platform temporary areas may also be writable.\n\nApproval prompts are enabled in this session: operations that require approval may ask through the configured answerers; without an available answerer, the request fails closed.\n\nYou are the root agent. Your name is \"lead\".\n\nTo message other agents, use send_message({ agent: \"<agent-name>\", message: \"...\" }).\nUse list_agents({}) to find your collaborator agents and their names."}],"source":{"kind":"runtime-context","form":"snapshot","sections":[{"name":"working-directory:current","text":"Current working directory: \"{{cwd}}\"."},{"name":"sandbox:policy","text":"Current DSH file policy: workspace-write. Any available operation enforced by the DSH file sandbox may modify files under the session workspace: \"{{cwd}}\". Some platform temporary areas may also be writable."},{"name":"approval:policy","text":"Approval prompts are enabled in this session: operations that require approval may ask through the configured answerers; without an available answerer, the request fails closed."},{"name":"subagent:identity","text":"You are the root agent. Your name is \"lead\".\n\nTo message other agents, use send_message({ agent: \"<agent-name>\", message: \"...\" }).\nUse list_agents({}) to find your collaborator agents and their names."}]},"role":"user","id":"{{sessionId}}"},"surfaceOp":"append"}
{"type":"request/header","data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash"},"tools":"{{tools}}"},"reason":"initial","startsSeries":true}}
{"type":"request/context","data":{"provider":"deepseek-official","model":"deepseek-v4-flash"}}
{"type":"session/title","data":{"title":"Remember the workspace instruction.","messageSeqs":[3],"source":{"kind":"fallback"}}}
@@ -17,7 +17,7 @@
{"type":"system/message","data":{"turn":2,"step":1,"message":{"role":"system","content":[{"type":"text","text":"{{system}}"}],"source":{"kind":"system-prompt"},"id":"{{sessionId}}"}},"sourceEventSeqs":[2],"surfaceOp":{"op":"replace","startSeq":2,"endSeq":2}}
{"type":"user/message","data":{"content":[{"type":"text","text":"Acknowledge the current workspace instruction."}],"source":{"kind":"user"},"role":"user","id":"{{sessionId}}"},"surfaceOp":"append"}
{"type":"user/message","data":{"content":[{"type":"text","text":"<system-reminder>\nThis complete workspace instruction baseline replaces all earlier workspace instruction baselines. The following workspace instructions may be relevant to your work. Use them as guidance when applicable. More specific instructions take precedence over broader ones. They do not override system, developer, or direct user instructions.\n\nInstructions from: AGENTS.md\n\nCurrent AGENTS rule.\n\n\nInstructions from: CLAUDE.md\n\nCurrent CLAUDE rule.\n\n</system-reminder>"}],"source":{"kind":"agent-instructions","form":"instructions","baseline":true,"baselineIdentity":"{\"projectRoot\":\"\",\"projectRootMarkers\":[\".git\"],\"maxBytes\":65536,\"maxSourceBytes\":1048576,\"instructionFileCandidates\":[\"AGENTS.md\",\"CLAUDE.md\"],\"localInstructionFileCandidates\":[\"AGENTS.local.md\",\"CLAUDE.local.md\"]}","changes":[{"action":"set","scope":".\u0000AGENTS.md","path":"AGENTS.md","digest":"7f53d2327837129750aef117f9754a001c46cf68"},{"action":"set","scope":".\u0000CLAUDE.md","path":"CLAUDE.md","digest":"5b1e9e3fd759eee6b43ceff899e47fb10c64701a"}]},"role":"user","id":"{{sessionId}}"},"surfaceOp":"append"}
{"type":"user/message","data":{"content":[{"type":"text","text":"Current runtime context. This snapshot supersedes earlier runtime-context snapshots.\n\nCurrent working directory: \"{{cwd}}\".\n\nCurrent DSH file policy: workspace-write. Any available operation enforced by the DSH file sandbox may modify files under the session workspace: \"{{cwd}}\". Some platform temporary areas may also be writable.\n\nApproval prompts are enabled in this session: operations that require approval may ask through the configured answerers; without an available answerer, the request fails closed.\n\nYou are the root agent. Your agent id is \"{{sessionId}}\".\n\nTo message other agents, use send_message({ agent_id: \"<agent-id>\", message: \"...\" }).\nUse list_agents({}) to find your collaborator agents and their ids."}],"source":{"kind":"runtime-context","form":"snapshot","sections":[{"name":"working-directory:current","text":"Current working directory: \"{{cwd}}\"."},{"name":"sandbox:policy","text":"Current DSH file policy: workspace-write. Any available operation enforced by the DSH file sandbox may modify files under the session workspace: \"{{cwd}}\". Some platform temporary areas may also be writable."},{"name":"approval:policy","text":"Approval prompts are enabled in this session: operations that require approval may ask through the configured answerers; without an available answerer, the request fails closed."},{"name":"subagent:identity","text":"You are the root agent. Your agent id is \"{{sessionId}}\".\n\nTo message other agents, use send_message({ agent_id: \"<agent-id>\", message: \"...\" }).\nUse list_agents({}) to find your collaborator agents and their ids."}]},"role":"user","id":"{{sessionId}}"},"surfaceOp":"append"}
{"type":"user/message","data":{"content":[{"type":"text","text":"Current runtime context. This snapshot supersedes earlier runtime-context snapshots.\n\nCurrent working directory: \"{{cwd}}\".\n\nCurrent DSH file policy: workspace-write. Any available operation enforced by the DSH file sandbox may modify files under the session workspace: \"{{cwd}}\". Some platform temporary areas may also be writable.\n\nApproval prompts are enabled in this session: operations that require approval may ask through the configured answerers; without an available answerer, the request fails closed.\n\nYou are the root agent. Your name is \"lead\".\n\nTo message other agents, use send_message({ agent: \"<agent-name>\", message: \"...\" }).\nUse list_agents({}) to find your collaborator agents and their names."}],"source":{"kind":"runtime-context","form":"snapshot","sections":[{"name":"working-directory:current","text":"Current working directory: \"{{cwd}}\"."},{"name":"sandbox:policy","text":"Current DSH file policy: workspace-write. Any available operation enforced by the DSH file sandbox may modify files under the session workspace: \"{{cwd}}\". Some platform temporary areas may also be writable."},{"name":"approval:policy","text":"Approval prompts are enabled in this session: operations that require approval may ask through the configured answerers; without an available answerer, the request fails closed."},{"name":"subagent:identity","text":"You are the root agent. Your name is \"lead\".\n\nTo message other agents, use send_message({ agent: \"<agent-name>\", message: \"...\" }).\nUse list_agents({}) to find your collaborator agents and their names."}]},"role":"user","id":"{{sessionId}}"},"surfaceOp":"append"}
{"type":"request/header","data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash"},"tools":"{{tools}}"},"reason":"initial","startsSeries":true}}
{"type":"request/context","data":{"provider":"deepseek-official","model":"deepseek-v4-flash"}}
{"type":"session/title","data":{"title":"Remember the workspace instruction.","messageSeqs":[3],"source":{"kind":"fallback"}}}
@@ -87,7 +87,7 @@ function researcher(messages) {
if (!names.includes('send_message')) {
return toolChunks([
{ name: 'team_task_update', args: { task_id: 'task-1', expected_revision: 2, action: 'complete' } },
{ name: 'send_message', args: { agent_id: sibling, message: 'Research complete: use the deterministic finding.' } },
{ name: 'send_message', args: { agent: sibling, message: 'Research complete: use the deterministic finding.' } },
])
}
return textChunks('Research teammate complete.')
@@ -134,7 +134,7 @@ function implementer(messages, parentId) {
if (!names.includes('send_message')) {
return toolChunks([
{ name: 'team_task_update', args: { task_id: 'task-2', expected_revision: 2, action: 'complete' } },
{ name: 'send_message', args: { agent_id: parentId, message: 'Implementation complete and verified.' } },
{ name: 'send_message', args: { agent: parentId, message: 'Implementation complete and verified.' } },
])
}
return textChunks('Implementation teammate complete.')
@@ -203,7 +203,7 @@ class TeamFixtureAdapter extends LlmAdapter {
if (workflowChild) chunks = textChunks('Fresh workflow child complete.')
else if (task?.startsWith('RESEARCHER_MARK:')) chunks = researcher(options.messages)
else if (task?.startsWith('IMPLEMENTER_MARK:')) chunks = implementer(options.messages, parentId)
else if (role?.startsWith('You are the root agent. Your agent id is')) chunks = lead(options.messages)
else if (role?.startsWith('You are the root agent. Your name is')) chunks = lead(options.messages)
else throw new Error('Team runtime context is missing a recognized identity')
for (const chunk of chunks) {
options.signal?.throwIfAborted()
@@ -1254,18 +1254,18 @@ describe('headless stream-json snapshots', () => {
"checkedAgents": true,
"deliveredMessages": 0,
"identities": [
"You are a subagent delegated by agent "<lead>".
Your agent id is "<self>".
The root agent of your collaboration tree is "<lead>".
"You are a subagent delegated by agent "lead".
Your name is "agent-2".
The root agent of your collaboration tree is "lead".
To message other agents, use send_message({ agent_id: "<agent-id>", message: "..." }).
Use list_agents({}) to find your collaborator agents and their ids.",
"You are a subagent delegated by agent "<lead>".
Your agent id is "<self>".
The root agent of your collaboration tree is "<lead>".
To message other agents, use send_message({ agent: "<agent-name>", message: "..." }).
Use list_agents({}) to find your collaborator agents and their names.",
"You are a subagent delegated by agent "lead".
Your name is "agent-3".
The root agent of your collaboration tree is "lead".
To message other agents, use send_message({ agent_id: "<agent-id>", message: "..." }).
Use list_agents({}) to find your collaborator agents and their ids.",
To message other agents, use send_message({ agent: "<agent-name>", message: "..." }).
Use list_agents({}) to find your collaborator agents and their names.",
],
"queuedMessages": 0,
"sessions": 4,
@@ -132,8 +132,8 @@ describe('parent-owned cold child catalog snapshot', () => {
if (parent === undefined) throw new Error('missing persisted parent log')
// Discovery reads child catalogs without requiring activation descriptors.
expect(parent).toContain(`${childId} [inactive] parent=${parentId} depth=1 — descriptorless child`)
expect(parent).not.toContain('[diagnostic: corrupt]')
expect(parent).toContain(`${childId} [inactive] — descriptorless child`)
expect(parent).not.toContain(`${childId} [corrupt]`)
const context: NormalizeContext = { sessionIds: [parentId, childId], cwd }
const normalizedParent = normalizeSessionSnapshot(parent, context)
+2 -2
View File
@@ -420,7 +420,7 @@ describe('web e2e: agent teamwork panel', () => {
taskId: task.id, expectedRevision: task.revision, action: 'claim',
})
await row.getByRole('img', { name: 'In progress', exact: true }).waitFor()
await row.locator('[data-team-task-owner]').filter({ hasText: agent.id }).waitFor()
await row.locator('[data-team-task-owner]').filter({ hasText: 'Owner: lead' }).waitFor()
await action.getByRole('heading', { name: 'Shared tasks 1 in progress', exact: true }).waitFor()
expect(await action.getByRole('button', { name: /^(New task|Edit|Complete|Reopen|Delete)$/u }).count()).toBe(0)
expect(await action.locator('input, select, textarea').count()).toBe(0)
@@ -762,7 +762,7 @@ describe('web e2e: agent teamwork panel', () => {
expect(await row.getAttribute('data-expanded')).toBe('false')
expect(await row.locator('[data-team-task-details]').count()).toBe(0)
expect(await board.locator('[data-team-task-details]').count()).toBe(1)
expect(await emptyRow.locator('[data-team-task-owner]').textContent()).toBe(`Owner: ${agent.id}`)
expect(await emptyRow.locator('[data-team-task-owner]').textContent()).toBe('Owner: lead')
expect(await emptyRow.locator('[data-team-task-details] p:not([data-team-task-owner])').textContent()).toBe(completed.description)
expect(await emptyRow.locator('dl, dt, dd').count()).toBe(0)
expect(await emptyRow.locator('[data-team-task-details]').textContent()).not.toContain(completed.id)
@@ -1,8 +1,8 @@
- dialog "Subagent sessions":
- tree "Subagent sessions":
- treeitem "event-sourcing researcher {{uuid}} · continuable · not running 15.7K tok · {{duration}}" [level=1]:
- treeitem "event-sourcing researcher agent-1 · continuable · not running 15.7K tok · {{duration}}" [level=1]:
- button "Expand event-sourcing researcher descendants"
- text: event-sourcing researcher {{uuid}} 15.7K tok {{duration}}
- text: event-sourcing researcher agent-1 15.7K tok {{duration}}
- treeitem "event-sourcing reviewer recorded-one-shot · one-shot · completed 0 tok · {{duration}}" [level=1]:
- text: event-sourcing reviewer recorded-one-shot 0 tok ~6mo 12d
- button "Open event-sourcing reviewer in sidebar"
@@ -2,37 +2,37 @@
- text: Subagent run completed
- time: {{clock}}
- paragraph: This notification triggered this response.
- text: Background subagent notice-result-child finished and will do no further work unless you send it more.Its closing message:## Research result The original child reply stays available.
- text: Background subagent agent-1 finished and will do no further work unless you send it more.Its closing message:## Research result The original child reply stays available.
- button "Subagent run stopped {{clock}}" [expanded]:
- text: Subagent run stopped
- time: {{clock}}
- paragraph: This notification triggered this response.
- text: Background subagent notice-result-child was stopped before it finished.Its closing message:## Research result The original child reply stays available.
- text: Background subagent agent-1 was stopped before it finished.Its closing message:## Research result The original child reply stays available.
- button "Subagent run failed {{clock}}" [expanded]:
- text: Subagent run failed
- time: {{clock}}
- paragraph: This notification triggered this response.
- text: Background subagent notice-result-child failed before it finished.Its closing message:## Research result The original child reply stays available.
- text: Background subagent agent-1 failed before it finished.Its closing message:## Research result The original child reply stays available.
- button "Subagent reached the token limit {{clock}}" [expanded]:
- text: Subagent reached the token limit
- time: {{clock}}
- paragraph: This notification triggered this response.
- text: Background subagent notice-result-child ran out of room before it finished.Its closing message:## Research result The original child reply stays available.
- text: Background subagent agent-1 ran out of room before it finished.Its closing message:## Research result The original child reply stays available.
- button "Subagent declined the task {{clock}}" [expanded]:
- text: Subagent declined the task
- time: {{clock}}
- paragraph: This notification triggered this response.
- text: Background subagent notice-result-child declined the task.Its closing message:## Research result The original child reply stays available.
- text: Background subagent agent-1 declined the task.Its closing message:## Research result The original child reply stays available.
- button "Subagent run completed {{clock}}" [expanded]:
- text: Subagent run completed
- time: {{clock}}
- paragraph: This notification triggered this response.
- text: Background subagent notice-result-child finished and will do no further work unless you send it more.It left no closing message.
- text: Background subagent agent-1 finished and will do no further work unless you send it more.It left no closing message.
- button "Subtask status updated {{clock}}" [expanded]:
- text: Subtask status updated
@@ -2,37 +2,37 @@
- text: 子智能体已完成任务
- time: {{clock}}
- paragraph: 这条通知触发了本轮回复。
- text: Background subagent notice-result-child finished and will do no further work unless you send it more.Its closing message:## Research result The original child reply stays available.
- text: Background subagent agent-1 finished and will do no further work unless you send it more.Its closing message:## Research result The original child reply stays available.
- button "子智能体任务已停止 {{clock}}" [expanded]:
- text: 子智能体任务已停止
- time: {{clock}}
- paragraph: 这条通知触发了本轮回复。
- text: Background subagent notice-result-child was stopped before it finished.Its closing message:## Research result The original child reply stays available.
- text: Background subagent agent-1 was stopped before it finished.Its closing message:## Research result The original child reply stays available.
- button "子智能体执行失败 {{clock}}" [expanded]:
- text: 子智能体执行失败
- time: {{clock}}
- paragraph: 这条通知触发了本轮回复。
- text: Background subagent notice-result-child failed before it finished.Its closing message:## Research result The original child reply stays available.
- text: Background subagent agent-1 failed before it finished.Its closing message:## Research result The original child reply stays available.
- button "子智能体已达 token 上限 {{clock}}" [expanded]:
- text: 子智能体已达 token 上限
- time: {{clock}}
- paragraph: 这条通知触发了本轮回复。
- text: Background subagent notice-result-child ran out of room before it finished.Its closing message:## Research result The original child reply stays available.
- text: Background subagent agent-1 ran out of room before it finished.Its closing message:## Research result The original child reply stays available.
- button "子智能体拒绝执行 {{clock}}" [expanded]:
- text: 子智能体拒绝执行
- time: {{clock}}
- paragraph: 这条通知触发了本轮回复。
- text: Background subagent notice-result-child declined the task.Its closing message:## Research result The original child reply stays available.
- text: Background subagent agent-1 declined the task.Its closing message:## Research result The original child reply stays available.
- button "子智能体已完成任务 {{clock}}" [expanded]:
- text: 子智能体已完成任务
- time: {{clock}}
- paragraph: 这条通知触发了本轮回复。
- text: Background subagent notice-result-child finished and will do no further work unless you send it more.It left no closing message.
- text: Background subagent agent-1 finished and will do no further work unless you send it more.It left no closing message.
- button "子任务状态更新 {{clock}}" [expanded]:
- text: 子任务状态更新
@@ -161,7 +161,7 @@ describe.skipIf(MODE === 'record')('web snapshot: Official native subagent bundl
if (notice?.data.source.kind !== 'subagent-settled') throw new Error('Native completion was not delivered to the parent')
expect(notice.data.source.senderSessionId).toBe(catalog[0]?.childId)
expect(notice.data.content).toContainEqual({ type: 'text', text: RESPONSE })
expect(dispatches[0]?.content).toEqual([{ type: 'text', text: `started subagent ${notice.data.source.senderSessionId}` }])
expect(dispatches[0]?.content).toEqual([{ type: 'text', text: 'started subagent agent-1' }])
expect(events.filter(event => event.type === 'turn/end')).toHaveLength(2)
expect(server.requests).toHaveLength(1)
expect(server.requests[0]?.body).toMatchObject({ model: 'fixture-model' })
+1 -1
View File
@@ -305,7 +305,7 @@ class ShippedChildAutoAdapter extends LlmAdapter {
throw new Error('continuable child id was not observed before parent adjustment')
}
return toolChunks('parent-adjust', 'send_message', {
agent_id: this.continuableChildId,
agent: this.continuableChildId,
message: [
AUTO_CHILD_ADJUSTED,
`Replace the earlier no-deletion restriction: permanently delete exactly ${this.continuableDeletePath}.`,
@@ -11,4 +11,4 @@
- img "In progress"
- text: Agent task
- paragraph: Created by the root agent
- paragraph: "Owner: session-{{uuid}}"
- paragraph: "Owner: lead"
+9 -7
View File
@@ -39,6 +39,8 @@ const MIGRATING_CHILD_EXPECTED = fileURLToPath(new URL(
))
const MODE = webSnapshotMode()
const LABEL = 'event-sourcing researcher'
/** The live child's catalog name; it is the parent's first named child. */
const CHILD_NAME = 'agent-1'
const ONE_SHOT_LABEL = 'event-sourcing reviewer'
const NESTED_LABEL = 'example editor'
const CHILD_TITLE = 'Explain event sourcing in one'
@@ -398,7 +400,7 @@ describe('web e2e: persisted subagent conversation and human continuation', () =
}
})
it('shows complete descriptions and IDs without hover at desktop and touch widths', async () => {
it('shows complete descriptions and names without hover at desktop and touch widths', async () => {
onTestFailed(() => saveFailureShot(page, 'web-e2e-subagent-catalog-labels'))
const originalViewport = page.viewportSize()!
const originalUrl = page.url()
@@ -410,7 +412,7 @@ describe('web e2e: persisted subagent conversation and human continuation', () =
const panel = page.locator('[data-subagent-panel]')
const row = panel.getByRole('treeitem', { name: new RegExp(LABEL) })
const primary = row.getByText(LABEL, { exact: true })
const secondary = row.getByText(childId, { exact: true })
const secondary = row.getByText(CHILD_NAME, { exact: true })
const primaryBounds = await primary.boundingBox()
const secondaryBounds = await secondary.boundingBox()
expect(primaryBounds).not.toBeNull()
@@ -420,7 +422,7 @@ describe('web e2e: persisted subagent conversation and human continuation', () =
expect(await label.evaluate(element => element.scrollWidth <= element.clientWidth
&& element.scrollHeight <= element.clientHeight)).toBe(true)
}
expect(await row.getAttribute('aria-label')).toContain(`${LABEL} ${childId} `)
expect(await row.getAttribute('aria-label')).toContain(`${LABEL} ${CHILD_NAME} `)
expect(await row.getByRole('button', { name: /description/u }).count()).toBe(0)
expect(await row.getByRole('button', { name: `Expand ${LABEL} descendants`, exact: true }).count()).toBe(1)
expect(await row.getByRole('button', { name: `Open ${LABEL} in sidebar`, exact: true }).count()).toBe(1)
@@ -776,7 +778,7 @@ describe('web e2e: persisted subagent conversation and human continuation', () =
.getByRole('treeitem', { name: /Ask a research subagent to/ })
.click()
await page.getByRole('button', { name: '2 subagents' }).hover()
await page.getByRole('treeitem', { name: new RegExp(LABEL) }).getByText(childId, { exact: true }).click()
await page.getByRole('treeitem', { name: new RegExp(LABEL) }).getByText(CHILD_NAME, { exact: true }).click()
await page.getByRole('textbox', { name: 'Message or run a task, / commands, @ files or sessions' }).waitFor()
const forkResponse = page.waitForResponse(response =>
new URL(response.url()).pathname === '/api/session/fork')
@@ -805,7 +807,7 @@ describe('web e2e: persisted subagent conversation and human continuation', () =
const sessions = page.getByRole('tree', { name: 'Sessions' })
await sessions.getByRole('treeitem', { name: /Ask a research subagent to/ }).click()
await page.getByRole('button', { name: '2 subagents' }).hover()
await page.getByRole('treeitem', { name: new RegExp(LABEL) }).getByText(childId, { exact: true }).click()
await page.getByRole('treeitem', { name: new RegExp(LABEL) }).getByText(CHILD_NAME, { exact: true }).click()
await page.locator('[data-composer-input][contenteditable="true"]').first().waitFor()
expect(scaffold.ctx.agents.get(childId)).toBeUndefined()
@@ -822,7 +824,7 @@ describe('web e2e: persisted subagent conversation and human continuation', () =
await sessions.getByRole('treeitem', { name: /Ask a research subagent to/ }).click()
await page.getByRole('button', { name: '2 subagents' }).press('ArrowDown')
await page.getByRole('treeitem', { name: new RegExp(LABEL) }).getByText(childId, { exact: true }).click()
await page.getByRole('treeitem', { name: new RegExp(LABEL) }).getByText(CHILD_NAME, { exact: true }).click()
const input = page.locator('[data-composer-input][contenteditable="true"]').first()
await input.waitFor()
const promptResponse = page.waitForResponse(response =>
@@ -868,7 +870,7 @@ describe('web e2e: persisted subagent conversation and human continuation', () =
await page.getByRole('button', { name: `Expand ${LABEL} descendants`, exact: true }).click()
await page.getByRole('treeitem', { name: new RegExp(NESTED_LABEL) }).waitFor()
expect(await rootHeader.textContent()).toBe(progress)
await page.getByRole('treeitem', { name: new RegExp(LABEL) }).getByText(childId, { exact: true }).click()
await page.getByRole('treeitem', { name: new RegExp(LABEL) }).getByText(CHILD_NAME, { exact: true }).click()
const switcher = page.getByRole('button', { name: `Switch subagent: ${LABEL}`, exact: true })
await switcher.click()
const panel = page.locator('[data-subagent-panel]')
+2 -2
View File
@@ -63,13 +63,13 @@ describe.skipIf(MODE === 'record')('web e2e: subagent result notices', () => {
const childId = SessionId('notice-result-child')
const notices: { title: string; message: ReturnType<typeof createUserMessage> }[] = OUTCOMES.map(outcome => ({
title: outcome[locale],
message: createSettlementMessage(childId, {
message: createSettlementMessage(childId, 'agent-1', {
stopReason: outcome.reason, output: [{ type: 'text', text: OUTPUT }],
}),
}))
notices.push({
title: OUTCOMES[0][locale],
message: createSettlementMessage(childId, { stopReason: 'completed', output: [] }),
message: createSettlementMessage(childId, 'agent-1', { stopReason: 'completed', output: [] }),
})
notices.push({
title: locale === 'en' ? 'Subtask status updated' : '子任务状态更新',
+4 -4
View File
@@ -2223,7 +2223,7 @@ export type PiAiThinkingTokenBudgetField = NonNullable<OpenAICompletionsCompat['
- `inject`: `llm`
- `refs`: [`LlmModelBadge`](../packages/llm/llm/src/index.ts) · [`ModelModality`](../packages/llm/llm/src/index.ts) · [`RetryPolicyConfig`](../packages/llm/llm/src/index.ts) · [`SystemPromptUpdate`](../packages/llm/llm/src/index.ts) · [`ToolUpdate`](../packages/llm/llm/src/index.ts)
- `source`: [`packages/test-support/llm-replay/src/index.ts:1135`](../packages/test-support/llm-replay/src/index.ts)
- `source`: [`packages/test-support/llm-replay/src/index.ts:1115`](../packages/test-support/llm-replay/src/index.ts)
```ts config-catalog
/** Plugin config: the {@link ReplayConfig} inputs, each defaulting to its `DSH_SNAPSHOT_*` env var in `apply`. */
@@ -3545,7 +3545,7 @@ export type JournalMode = 'wal' | 'delete' | 'truncate' | 'persist'
- `inject`: `workingDirectory` · `sessionProjections`
- `refs`: `Volatile` (`@deepseek-ai/cordis`)
- `source`: [`packages/subagent/subagent/src/index.ts:181`](../packages/subagent/subagent/src/index.ts)
- `source`: [`packages/subagent/subagent/src/index.ts:186`](../packages/subagent/subagent/src/index.ts)
```ts config-catalog
/** Host configuration for continuable subagent capacity. */
@@ -3906,7 +3906,7 @@ export type TokenMeterConfig = Record<string, never>
## `@deepseek-ai/dsh-tool-agent-team`
- `inject`: `agentTeams` · `subagents` · `tools` · `systemPrompt`
- `source`: [`packages/team/tool-agent-team/src/index.ts:18`](../packages/team/tool-agent-team/src/index.ts)
- `source`: [`packages/team/tool-agent-team/src/index.ts:19`](../packages/team/tool-agent-team/src/index.ts)
```ts config-catalog
/** The Team tool plugin takes no configuration. */
@@ -4366,7 +4366,7 @@ export interface PresetSelectionConfig {
## `@deepseek-ai/dsh-tool-subagent-control`
- `inject`: `tools` · `subagents` · `agents` · `systemPrompt`
- `source`: [`packages/subagent/tool-subagent-control/src/index.ts:26`](../packages/subagent/tool-subagent-control/src/index.ts)
- `source`: [`packages/subagent/tool-subagent-control/src/index.ts:24`](../packages/subagent/tool-subagent-control/src/index.ts)
```ts config-catalog
/** Optional subagent control tools. */
+4 -4
View File
@@ -2225,7 +2225,7 @@ export type PiAiThinkingTokenBudgetField = NonNullable<OpenAICompletionsCompat['
- `inject`: `llm`
- `refs`: [`LlmModelBadge`](../packages/llm/llm/src/index.ts) · [`ModelModality`](../packages/llm/llm/src/index.ts) · [`RetryPolicyConfig`](../packages/llm/llm/src/index.ts) · [`SystemPromptUpdate`](../packages/llm/llm/src/index.ts) · [`ToolUpdate`](../packages/llm/llm/src/index.ts)
- `source`: [`packages/test-support/llm-replay/src/index.ts:1135`](../packages/test-support/llm-replay/src/index.ts)
- `source`: [`packages/test-support/llm-replay/src/index.ts:1115`](../packages/test-support/llm-replay/src/index.ts)
```ts config-catalog
/** Plugin config: the {@link ReplayConfig} inputs, each defaulting to its `DSH_SNAPSHOT_*` env var in `apply`. */
@@ -3547,7 +3547,7 @@ export type JournalMode = 'wal' | 'delete' | 'truncate' | 'persist'
- `inject`: `workingDirectory` · `sessionProjections`
- `refs`: `Volatile` (`@deepseek-ai/cordis`)
- `source`: [`packages/subagent/subagent/src/index.ts:181`](../packages/subagent/subagent/src/index.ts)
- `source`: [`packages/subagent/subagent/src/index.ts:186`](../packages/subagent/subagent/src/index.ts)
```ts config-catalog
/** Host configuration for continuable subagent capacity. */
@@ -3908,7 +3908,7 @@ export type TokenMeterConfig = Record<string, never>
## `@deepseek-ai/dsh-tool-agent-team`
- `inject`: `agentTeams` · `subagents` · `tools` · `systemPrompt`
- `source`: [`packages/team/tool-agent-team/src/index.ts:18`](../packages/team/tool-agent-team/src/index.ts)
- `source`: [`packages/team/tool-agent-team/src/index.ts:19`](../packages/team/tool-agent-team/src/index.ts)
```ts config-catalog
/** The Team tool plugin takes no configuration. */
@@ -4368,7 +4368,7 @@ export interface PresetSelectionConfig {
## `@deepseek-ai/dsh-tool-subagent-control`
- `inject`: `tools` · `subagents` · `agents` · `systemPrompt`
- `source`: [`packages/subagent/tool-subagent-control/src/index.ts:26`](../packages/subagent/tool-subagent-control/src/index.ts)
- `source`: [`packages/subagent/tool-subagent-control/src/index.ts:24`](../packages/subagent/tool-subagent-control/src/index.ts)
```ts config-catalog
/** Optional subagent control tools. */
+4 -4
View File
@@ -76,10 +76,10 @@ Application listeners are outside this package matrix. Desktop Host subscribes t
| `session/flush` | `parallel` | [`packages/core/session/src/index.ts:84`](../packages/core/session/src/index.ts) | [`session`](../packages/core/session) (`events.dispatch`) | [`session-persistence-jsonl`](../packages/session/session-persistence-jsonl), [`session-telemetry`](../packages/session/session-telemetry) |
| `settings/document-updated` | `emit` | [`packages/settings/settings/src/types.ts:75`](../packages/settings/settings/src/types.ts) | [`settings`](../packages/settings/settings) (`emit`) | `remotes` |
| `skills/change` | `emit` | [`packages/skill/skill/src/index.ts:296`](../packages/skill/skill/src/index.ts) | [`skill`](../packages/skill/skill) (`events.dispatch`) | - |
| `subagent/end` | `emit` | [`packages/subagent/subagent/src/index.ts:161`](../packages/subagent/subagent/src/index.ts) | [`subagent`](../packages/subagent/subagent) (`events.dispatch`) | [`hooks-claude-code`](../packages/experimental/hooks-claude-code), `server` |
| `subagent/provider-added` | `emit` | [`packages/subagent/subagent/src/index.ts:137`](../packages/subagent/subagent/src/index.ts) | [`subagent`](../packages/subagent/subagent) (`emit`) | [`tool-subagent`](../packages/subagent/tool-subagent) |
| `subagent/provider-removed` | `emit` | [`packages/subagent/subagent/src/index.ts:143`](../packages/subagent/subagent/src/index.ts) | [`subagent`](../packages/subagent/subagent) (`events.dispatch`) | [`tool-subagent`](../packages/subagent/tool-subagent) |
| `subagent/start` | `emit` | [`packages/subagent/subagent/src/index.ts:153`](../packages/subagent/subagent/src/index.ts) | [`subagent`](../packages/subagent/subagent) (`events.dispatch`) | [`hooks-claude-code`](../packages/experimental/hooks-claude-code) |
| `subagent/end` | `emit` | [`packages/subagent/subagent/src/index.ts:166`](../packages/subagent/subagent/src/index.ts) | [`subagent`](../packages/subagent/subagent) (`events.dispatch`) | [`hooks-claude-code`](../packages/experimental/hooks-claude-code), `server` |
| `subagent/provider-added` | `emit` | [`packages/subagent/subagent/src/index.ts:142`](../packages/subagent/subagent/src/index.ts) | [`subagent`](../packages/subagent/subagent) (`emit`) | [`tool-subagent`](../packages/subagent/tool-subagent) |
| `subagent/provider-removed` | `emit` | [`packages/subagent/subagent/src/index.ts:148`](../packages/subagent/subagent/src/index.ts) | [`subagent`](../packages/subagent/subagent) (`events.dispatch`) | [`tool-subagent`](../packages/subagent/tool-subagent) |
| `subagent/start` | `emit` | [`packages/subagent/subagent/src/index.ts:158`](../packages/subagent/subagent/src/index.ts) | [`subagent`](../packages/subagent/subagent) (`events.dispatch`) | [`hooks-claude-code`](../packages/experimental/hooks-claude-code) |
| `system-prompt/assemble` | `waterfall` | [`packages/core/system-prompt/src/index.ts:31`](../packages/core/system-prompt/src/index.ts) | [`system-prompt`](../packages/core/system-prompt) (`waterfall`) | `browser-use-runtime`, [`working-directory`](../packages/session/working-directory) |
| `system-prompt/change` | `emit` | [`packages/core/system-prompt/src/index.ts:37`](../packages/core/system-prompt/src/index.ts) | [`system-prompt`](../packages/core/system-prompt) (`emit`) | - |
| `tools/change` | `emit` | [`packages/core/tools/src/events.ts:56`](../packages/core/tools/src/events.ts) | [`agent-preset-registry`](../packages/preset/agent-preset-registry) (`emit`), [`tools`](../packages/core/tools) (`emit`) | `browser-use-runtime` |
+4 -4
View File
@@ -78,10 +78,10 @@
| `session/flush` | `parallel` | [`packages/core/session/src/index.ts:84`](../packages/core/session/src/index.ts) | [`session`](../packages/core/session) (`events.dispatch`) | [`session-persistence-jsonl`](../packages/session/session-persistence-jsonl), [`session-telemetry`](../packages/session/session-telemetry) |
| `settings/document-updated` | `emit` | [`packages/settings/settings/src/types.ts:75`](../packages/settings/settings/src/types.ts) | [`settings`](../packages/settings/settings) (`emit`) | `remotes` |
| `skills/change` | `emit` | [`packages/skill/skill/src/index.ts:296`](../packages/skill/skill/src/index.ts) | [`skill`](../packages/skill/skill) (`events.dispatch`) | - |
| `subagent/end` | `emit` | [`packages/subagent/subagent/src/index.ts:161`](../packages/subagent/subagent/src/index.ts) | [`subagent`](../packages/subagent/subagent) (`events.dispatch`) | [`hooks-claude-code`](../packages/experimental/hooks-claude-code), `server` |
| `subagent/provider-added` | `emit` | [`packages/subagent/subagent/src/index.ts:137`](../packages/subagent/subagent/src/index.ts) | [`subagent`](../packages/subagent/subagent) (`emit`) | [`tool-subagent`](../packages/subagent/tool-subagent) |
| `subagent/provider-removed` | `emit` | [`packages/subagent/subagent/src/index.ts:143`](../packages/subagent/subagent/src/index.ts) | [`subagent`](../packages/subagent/subagent) (`events.dispatch`) | [`tool-subagent`](../packages/subagent/tool-subagent) |
| `subagent/start` | `emit` | [`packages/subagent/subagent/src/index.ts:153`](../packages/subagent/subagent/src/index.ts) | [`subagent`](../packages/subagent/subagent) (`events.dispatch`) | [`hooks-claude-code`](../packages/experimental/hooks-claude-code) |
| `subagent/end` | `emit` | [`packages/subagent/subagent/src/index.ts:166`](../packages/subagent/subagent/src/index.ts) | [`subagent`](../packages/subagent/subagent) (`events.dispatch`) | [`hooks-claude-code`](../packages/experimental/hooks-claude-code), `server` |
| `subagent/provider-added` | `emit` | [`packages/subagent/subagent/src/index.ts:142`](../packages/subagent/subagent/src/index.ts) | [`subagent`](../packages/subagent/subagent) (`emit`) | [`tool-subagent`](../packages/subagent/tool-subagent) |
| `subagent/provider-removed` | `emit` | [`packages/subagent/subagent/src/index.ts:148`](../packages/subagent/subagent/src/index.ts) | [`subagent`](../packages/subagent/subagent) (`events.dispatch`) | [`tool-subagent`](../packages/subagent/tool-subagent) |
| `subagent/start` | `emit` | [`packages/subagent/subagent/src/index.ts:158`](../packages/subagent/subagent/src/index.ts) | [`subagent`](../packages/subagent/subagent) (`events.dispatch`) | [`hooks-claude-code`](../packages/experimental/hooks-claude-code) |
| `system-prompt/assemble` | `waterfall` | [`packages/core/system-prompt/src/index.ts:31`](../packages/core/system-prompt/src/index.ts) | [`system-prompt`](../packages/core/system-prompt) (`waterfall`) | `browser-use-runtime`, [`working-directory`](../packages/session/working-directory) |
| `system-prompt/change` | `emit` | [`packages/core/system-prompt/src/index.ts:37`](../packages/core/system-prompt/src/index.ts) | [`system-prompt`](../packages/core/system-prompt) (`emit`) | - |
| `tools/change` | `emit` | [`packages/core/tools/src/events.ts:56`](../packages/core/tools/src/events.ts) | [`agent-preset-registry`](../packages/preset/agent-preset-registry) (`emit`), [`tools`](../packages/core/tools) (`emit`) | `browser-use-runtime` |
+30 -21
View File
@@ -9,8 +9,8 @@
en: 1387c4505dde2faf
zh: 48570fa1c13d6910
/session-persistence-event-catalog/persistence-type-fingerprints:
en: d334560286daab57
zh: ddece2494dd2131c
en: 18fad247b1c849db
zh: 5cf48ae5db4615d7
/session-persistence-event-catalog/event-envelope:
en: 56414ffd00cdc32a
zh: 6dc11eb013e95e41
@@ -207,8 +207,8 @@
en: 9630752e97ddbfbc
zh: 9630752e97ddbfbc
/session-persistence-event-catalog/events/subagent/subagent-catalog-log-only:
en: e6ce4b5a98ff2f52
zh: 9a8e112754679aef
en: cc33ef2805abbfdd
zh: d35696cb06672d6d
/session-persistence-event-catalog/events/subagent/subagent-descriptor-log-only:
en: f5d53639dc5afdfc
zh: 8c553e7397d08832
@@ -963,8 +963,11 @@
en: 6884d3e0e7f31048
zh: 6884d3e0e7f31048
/session-persistence-event-catalog/resolved-persistence-types/2:
en: d462b9a5e0855776
zh: d462b9a5e0855776
en: ca872ec805526f3d
zh: ca872ec805526f3d
/session-persistence-event-catalog/resolved-persistence-types/3:
en: 27a98df839b87cc8
zh: 27a98df839b87cc8
/session-persistence-event-catalog/resolved-persistence-types/4:
en: 9ec6b8bd755f3e33
zh: 9ec6b8bd755f3e33
@@ -1239,11 +1242,11 @@
en: ecc15ebadb77afdf
zh: 97ac27d6a4175f6f
/session-persistence-event-catalog/resolved-persistence-types/streamchunk:
en: 76ef1d6de369c7b5
zh: e033b6bbaa455e87
en: 747e384b3176e0cb
zh: defbff408ea7c97c
/session-persistence-event-catalog/resolved-persistence-types/subagentcatalogevent:
en: 725539dcd5c335ed
zh: 5ca08d3667f84ff9
en: 8a56ae8e701509b3
zh: caef4f0223f65470
/session-persistence-event-catalog/resolved-persistence-types/subagentdescriptordata:
en: 2b9c68682eec6f78
zh: 8ef5e64326c1eae6
@@ -1446,21 +1449,27 @@
en: de1d59e9edd58a7d
zh: 0e29b8e80db664dc
/session-persistence-event-catalog/resolved-persistence-types/childcreatedat-childid-label-mode:
en: 2ef977cb4a83bb0a
zh: 893fded259888650
en: c3690b3beea61c52
zh: 7a788be5921e8d8f
/session-persistence-event-catalog/resolved-persistence-types/childcreatedat-childid-label-mode~2:
en: 2af7543c81f83558
zh: a96b05e9c12d0e7b
/session-persistence-event-catalog/resolved-persistence-types/childcreatedat-childid-label-mode~3:
en: 669e284c656449c7
zh: e40ac8cb904bd983
/session-persistence-event-catalog/resolved-persistence-types/childcreatedat-childid-label-mode~3:
/session-persistence-event-catalog/resolved-persistence-types/childcreatedat-childid-label-mode~4:
en: 1dc667423caefb33
zh: bd38fa2473673d14
/session-persistence-event-catalog/resolved-persistence-types/childcreatedat-childid-label-mode~4:
en: dc8738014c719f4e
zh: c773fd60c0090231
/session-persistence-event-catalog/resolved-persistence-types/childcreatedat-childid-label-mode~5:
en: 9599091956b57334
zh: 54dbf4a35ec3ed35
/session-persistence-event-catalog/resolved-persistence-types/childcreatedat-childid-label-mode~6:
en: b1cdfd349b457908
zh: d5d75fb74a5cefc8
/session-persistence-event-catalog/resolved-persistence-types/childcreatedat-childid-label-mode~7:
en: 43cf5cd666b591a0
zh: 7c7a3011f8681f12
/session-persistence-event-catalog/resolved-persistence-types/childcreatedat-childid-label-mode~6:
/session-persistence-event-catalog/resolved-persistence-types/childcreatedat-childid-label-mode~8:
en: a1f188c9058cf621
zh: eb43c0f045fb9afb
/session-persistence-event-catalog/resolved-persistence-types/code-name-reason:
@@ -2106,11 +2115,11 @@
en: 7fc233c4a569dae2
zh: bc2b3fed4a397c00
/session-persistence-event-catalog/resolved-persistence-types/type-step-start:
en: bb27281e17bb5e4f
zh: b53e3fc8d916118b
en: 6ba6d118d44365e2
zh: 846ea149908f0e04
/session-persistence-event-catalog/resolved-persistence-types/type-subagent-catalog:
en: 0f697ddcde1625dd
zh: 0dd87d2e108c5312
en: b5dfa07e0b8d9f6a
zh: e93efb23da447ade
/session-persistence-event-catalog/resolved-persistence-types/type-subagent-descriptor:
en: 2adab4361a5b558d
zh: 7f2a8da669f9e117
+49 -9
View File
@@ -61,7 +61,7 @@ The [format references](persistence-changes/historical-formats/README.md) cover
| `event:session/title-llm-request` | event | `d95c624eddecdacf1ee74356196c09d2f3fcd625714be5e852a6b643fa12a7ca` | [`{ type: "session/title-llm-request" }`](#persistence-type-sha256-d95c624eddecdacf1ee74356196c09d2f3fcd625714be5e852a6b643fa12a7ca) |
| `event:step/end` | event | `e0a787e6ec76c7c94fecbc501b489164ab0293db05bc947914077ad01e674f05` | [`{ type: "step/end" }`](#persistence-type-sha256-e0a787e6ec76c7c94fecbc501b489164ab0293db05bc947914077ad01e674f05) |
| `event:step/start` | event | `4513e088d43e6c68425be30451b9f961cc264fe7318ca62681c41d4d78615986` | [`{ type: "step/start" }`](#persistence-type-sha256-4513e088d43e6c68425be30451b9f961cc264fe7318ca62681c41d4d78615986) |
| `event:subagent/catalog` | event | `53750b9abf61efb7992b0aadc3e247ec927449c63266df28230fd1139f5590ac` | [`{ type: "subagent/catalog" }`](#persistence-type-sha256-53750b9abf61efb7992b0aadc3e247ec927449c63266df28230fd1139f5590ac) |
| `event:subagent/catalog` | event | `d49164d37eab0f0f70fa787c65d887abbea869c010ccb103d717fab3519c3a41` | [`{ type: "subagent/catalog" }`](#persistence-type-sha256-d49164d37eab0f0f70fa787c65d887abbea869c010ccb103d717fab3519c3a41) |
| `event:subagent/descriptor` | event | `b79ada42962cad0190a9d465805260567621fa3a4abd757eb31e6016b52d5ab5` | [`{ type: "subagent/descriptor" }`](#persistence-type-sha256-b79ada42962cad0190a9d465805260567621fa3a4abd757eb31e6016b52d5ab5) |
| `event:subagent/model-selection-policy` | event | `a6567ccb2e530606b775371eb4fa31468d72084339968e8b0440a516a23b39dc` | [`{ type: "subagent/model-selection-policy" }`](#persistence-type-sha256-a6567ccb2e530606b775371eb4fa31468d72084339968e8b0440a516a23b39dc) |
| `event:system/message` | event | `69081694be231d56fd9580ba14645fd5e35373202605d5c5c841a9435b5fa3b1` | [`{ type: "system/message" }`](#persistence-type-sha256-69081694be231d56fd9580ba14645fd5e35373202605d5c5c841a9435b5fa3b1) |
@@ -938,7 +938,7 @@ Source: [`packages/core/session/src/types.ts:305`](../packages/core/session/src/
'subagent/catalog': SubagentCatalogEvent
```
Source: [`packages/subagent/subagent/src/catalog.ts:44`](../packages/subagent/subagent/src/catalog.ts)
Source: [`packages/subagent/subagent/src/catalog.ts:52`](../packages/subagent/subagent/src/catalog.ts)
<a id="subagentdescriptor--log-only"></a>
@@ -3102,6 +3102,14 @@ SHA-256: `a0f906856fc06f1c6f2083eb970e5a657a82b1a84c06c095445e5d6d161cda80`
`2`
<a id="persistence-type-sha256-137ac60e26bcb192210d9a32a704b73b0924ed34019323defa1b787be95bd45e"></a>
### `3`
SHA-256: `137ac60e26bcb192210d9a32a704b73b0924ed34019323defa1b787be95bd45e`
`3`
<a id="persistence-type-sha256-af6e173f7be819bcd0a5c8d77918649c10ce761d8a184ff472f2e01ce64eb2e0"></a>
### `4`
@@ -4873,7 +4881,7 @@ One of:
- [`{ type: "finish" }`](#persistence-type-sha256-a2b49331716ba0a7078b026d145306a70eae64b7313c3e6204bd931e75ec3bb1)
- [`{ type: "usage" }`](#persistence-type-sha256-f1a96afe7503ac1817de769cd0ba13d9b80111c7034c50106b3344ecc14cc515)
<a id="persistence-type-sha256-f731ffe80810b0289b3e694d8f40af6f01865c02a622ee457be90ca808b66e87"></a>
<a id="persistence-type-sha256-058fc9a6b4fbd5d43437c3a64170002070dfc98e18d87de294b564ae446ca8ae"></a>
<a id="persistence-type-packagessubagentsubagentsrccatalogtssubagentcatalogevent"></a>
@@ -4881,18 +4889,20 @@ One of:
### `SubagentCatalogEvent`
SHA-256: `f731ffe80810b0289b3e694d8f40af6f01865c02a622ee457be90ca808b66e87`
SHA-256: `058fc9a6b4fbd5d43437c3a64170002070dfc98e18d87de294b564ae446ca8ae`
Sources: [`packages/subagent/subagent/src/catalog.ts:28`](../packages/subagent/subagent/src/catalog.ts)
Sources: [`packages/subagent/subagent/src/catalog.ts:32`](../packages/subagent/subagent/src/catalog.ts)
One of:
- [`{ childCreatedAt, childId, label, mode, … }`](#persistence-type-sha256-8faed5b52ab2d2df40b94a926d0f0faa75280bddcc4b17b6bdd9c8bfed7c34b5)
- [`{ childCreatedAt, childId, label, mode, … }`](#persistence-type-sha256-0e10d7c096b47e61defe372a5fc8bd37d835199410eac44367f95c45082498bd)
- [`{ childCreatedAt, childId, label, mode, … }`](#persistence-type-sha256-e2ad8f5bcd813f268ffef1b10a12d7ddd2b8ced8b9b6d0275b3f6b7ed094a187)
- [`{ childCreatedAt, childId, label?, mode, … }`](#persistence-type-sha256-a43327a1739c3fa477f32981071fef7d8ba6ae5f32a84fd70f547b2eee59e93e)
- [`{ childCreatedAt, childId, label?, mode, … }`](#persistence-type-sha256-cbbe8377ee744964537dbafd83607219e58ba79a13f6db0d0645c7ad3d5e8a09)
- [`{ childCreatedAt, childId, label?, mode, … }`](#persistence-type-sha256-5d542ac7bdf13310c46e1a884dec9fb18ad8c6e153cff207e639cd7bf9d7e694)
- [`{ childCreatedAt, childId, label?, mode, … }`](#persistence-type-sha256-b6896938660a1dfe4ddd100fb3164d9f8fa57feeabfe37441a80106c9942697a)
- [`{ childCreatedAt, childId, label?, mode, … }`](#persistence-type-sha256-a0f25b5aeeebf2bf1542ce67726b095e3b139a39c71861d57e827f12dea1f499)
- [`{ childCreatedAt, childId, label, mode, … }`](#persistence-type-sha256-0e10d7c096b47e61defe372a5fc8bd37d835199410eac44367f95c45082498bd)
<a id="persistence-type-sha256-86d1d0e9cfebb240421187e3dc37fb71cc38a1501885cf32f8f9adef7b0a2bde"></a>
@@ -5984,6 +5994,21 @@ SHA-256: `0e10d7c096b47e61defe372a5fc8bd37d835199410eac44367f95c45082498bd`
| `mode` | required | `"continuable"` |
| `version` | required | `0` |
<a id="persistence-type-sha256-8faed5b52ab2d2df40b94a926d0f0faa75280bddcc4b17b6bdd9c8bfed7c34b5"></a>
### `{ childCreatedAt, childId, label, mode, … }`
SHA-256: `8faed5b52ab2d2df40b94a926d0f0faa75280bddcc4b17b6bdd9c8bfed7c34b5`
| Property | Presence | Type |
|---|---|---|
| `childCreatedAt` | required | `number` |
| `childId` | required | `string` |
| `label` | required | `string` |
| `mode` | required | `"continuable"` |
| `name` | required | `string` |
| `version` | required | `3` |
<a id="persistence-type-sha256-e2ad8f5bcd813f268ffef1b10a12d7ddd2b8ced8b9b6d0275b3f6b7ed094a187"></a>
### `{ childCreatedAt, childId, label, mode, … }`
@@ -6026,6 +6051,21 @@ SHA-256: `a0f25b5aeeebf2bf1542ce67726b095e3b139a39c71861d57e827f12dea1f499`
| `mode` | required | `"unknown"` |
| `version` | required | `1` |
<a id="persistence-type-sha256-a43327a1739c3fa477f32981071fef7d8ba6ae5f32a84fd70f547b2eee59e93e"></a>
### `{ childCreatedAt, childId, label?, mode, … }`
SHA-256: `a43327a1739c3fa477f32981071fef7d8ba6ae5f32a84fd70f547b2eee59e93e`
| Property | Presence | Type |
|---|---|---|
| `childCreatedAt` | required | `number` |
| `childId` | required | `string` |
| `label` | optional | `string` |
| `mode` | required | `"external"` |
| `name` | required | `string` |
| `version` | required | `3` |
<a id="persistence-type-sha256-b6896938660a1dfe4ddd100fb3164d9f8fa57feeabfe37441a80106c9942697a"></a>
### `{ childCreatedAt, childId, label?, mode, … }`
@@ -8857,17 +8897,17 @@ SHA-256: `4513e088d43e6c68425be30451b9f961cc264fe7318ca62681c41d4d78615986`
| `time` | required | `number` |
| `type` | required | `"step/start"` |
<a id="persistence-type-sha256-53750b9abf61efb7992b0aadc3e247ec927449c63266df28230fd1139f5590ac"></a>
<a id="persistence-type-sha256-d49164d37eab0f0f70fa787c65d887abbea869c010ccb103d717fab3519c3a41"></a>
<a id="persistence-type-eventsubagentcatalog"></a>
### `{ type: "subagent/catalog" }`
SHA-256: `53750b9abf61efb7992b0aadc3e247ec927449c63266df28230fd1139f5590ac`
SHA-256: `d49164d37eab0f0f70fa787c65d887abbea869c010ccb103d717fab3519c3a41`
| Property | Presence | Type |
|---|---|---|
| `data` | required | [`SubagentCatalogEvent`](#persistence-type-sha256-f731ffe80810b0289b3e694d8f40af6f01865c02a622ee457be90ca808b66e87) |
| `data` | required | [`SubagentCatalogEvent`](#persistence-type-sha256-058fc9a6b4fbd5d43437c3a64170002070dfc98e18d87de294b564ae446ca8ae) |
| `ignorable` | optional | `true` |
| `seq` | required | `number` |
| `time` | required | `number` |
+49 -9
View File
@@ -63,7 +63,7 @@
| `event:session/title-llm-request` | event | `d95c624eddecdacf1ee74356196c09d2f3fcd625714be5e852a6b643fa12a7ca` | [`{ type: "session/title-llm-request" }`](#persistence-type-sha256-d95c624eddecdacf1ee74356196c09d2f3fcd625714be5e852a6b643fa12a7ca) |
| `event:step/end` | event | `e0a787e6ec76c7c94fecbc501b489164ab0293db05bc947914077ad01e674f05` | [`{ type: "step/end" }`](#persistence-type-sha256-e0a787e6ec76c7c94fecbc501b489164ab0293db05bc947914077ad01e674f05) |
| `event:step/start` | event | `4513e088d43e6c68425be30451b9f961cc264fe7318ca62681c41d4d78615986` | [`{ type: "step/start" }`](#persistence-type-sha256-4513e088d43e6c68425be30451b9f961cc264fe7318ca62681c41d4d78615986) |
| `event:subagent/catalog` | event | `53750b9abf61efb7992b0aadc3e247ec927449c63266df28230fd1139f5590ac` | [`{ type: "subagent/catalog" }`](#persistence-type-sha256-53750b9abf61efb7992b0aadc3e247ec927449c63266df28230fd1139f5590ac) |
| `event:subagent/catalog` | event | `d49164d37eab0f0f70fa787c65d887abbea869c010ccb103d717fab3519c3a41` | [`{ type: "subagent/catalog" }`](#persistence-type-sha256-d49164d37eab0f0f70fa787c65d887abbea869c010ccb103d717fab3519c3a41) |
| `event:subagent/descriptor` | event | `b79ada42962cad0190a9d465805260567621fa3a4abd757eb31e6016b52d5ab5` | [`{ type: "subagent/descriptor" }`](#persistence-type-sha256-b79ada42962cad0190a9d465805260567621fa3a4abd757eb31e6016b52d5ab5) |
| `event:subagent/model-selection-policy` | event | `a6567ccb2e530606b775371eb4fa31468d72084339968e8b0440a516a23b39dc` | [`{ type: "subagent/model-selection-policy" }`](#persistence-type-sha256-a6567ccb2e530606b775371eb4fa31468d72084339968e8b0440a516a23b39dc) |
| `event:system/message` | event | `69081694be231d56fd9580ba14645fd5e35373202605d5c5c841a9435b5fa3b1` | [`{ type: "system/message" }`](#persistence-type-sha256-69081694be231d56fd9580ba14645fd5e35373202605d5c5c841a9435b5fa3b1) |
@@ -940,7 +940,7 @@ export type SessionEvent<T extends SessionEventType = SessionEventType> = {
'subagent/catalog': SubagentCatalogEvent
```
来源:[`packages/subagent/subagent/src/catalog.ts:44`](../packages/subagent/subagent/src/catalog.ts)
来源:[`packages/subagent/subagent/src/catalog.ts:52`](../packages/subagent/subagent/src/catalog.ts)
<a id="subagentdescriptor--log-only"></a>
@@ -3104,6 +3104,14 @@ SHA-256: `a0f906856fc06f1c6f2083eb970e5a657a82b1a84c06c095445e5d6d161cda80`
`2`
<a id="persistence-type-sha256-137ac60e26bcb192210d9a32a704b73b0924ed34019323defa1b787be95bd45e"></a>
### `3`
SHA-256: `137ac60e26bcb192210d9a32a704b73b0924ed34019323defa1b787be95bd45e`
`3`
<a id="persistence-type-sha256-af6e173f7be819bcd0a5c8d77918649c10ce761d8a184ff472f2e01ce64eb2e0"></a>
### `4`
@@ -4875,7 +4883,7 @@ SHA-256: `47e9095591ae36e7c39ee62553097772f2bfa16304536a72dbbc3f691f605180`
- [`{ type: "finish" }`](#persistence-type-sha256-a2b49331716ba0a7078b026d145306a70eae64b7313c3e6204bd931e75ec3bb1)
- [`{ type: "usage" }`](#persistence-type-sha256-f1a96afe7503ac1817de769cd0ba13d9b80111c7034c50106b3344ecc14cc515)
<a id="persistence-type-sha256-f731ffe80810b0289b3e694d8f40af6f01865c02a622ee457be90ca808b66e87"></a>
<a id="persistence-type-sha256-058fc9a6b4fbd5d43437c3a64170002070dfc98e18d87de294b564ae446ca8ae"></a>
<a id="persistence-type-packagessubagentsubagentsrccatalogtssubagentcatalogevent"></a>
@@ -4883,18 +4891,20 @@ SHA-256: `47e9095591ae36e7c39ee62553097772f2bfa16304536a72dbbc3f691f605180`
### `SubagentCatalogEvent`
SHA-256: `f731ffe80810b0289b3e694d8f40af6f01865c02a622ee457be90ca808b66e87`
SHA-256: `058fc9a6b4fbd5d43437c3a64170002070dfc98e18d87de294b564ae446ca8ae`
来源:[`packages/subagent/subagent/src/catalog.ts:28`](../packages/subagent/subagent/src/catalog.ts)
来源:[`packages/subagent/subagent/src/catalog.ts:32`](../packages/subagent/subagent/src/catalog.ts)
以下类型之一:
- [`{ childCreatedAt, childId, label, mode, … }`](#persistence-type-sha256-8faed5b52ab2d2df40b94a926d0f0faa75280bddcc4b17b6bdd9c8bfed7c34b5)
- [`{ childCreatedAt, childId, label, mode, … }`](#persistence-type-sha256-0e10d7c096b47e61defe372a5fc8bd37d835199410eac44367f95c45082498bd)
- [`{ childCreatedAt, childId, label, mode, … }`](#persistence-type-sha256-e2ad8f5bcd813f268ffef1b10a12d7ddd2b8ced8b9b6d0275b3f6b7ed094a187)
- [`{ childCreatedAt, childId, label?, mode, … }`](#persistence-type-sha256-a43327a1739c3fa477f32981071fef7d8ba6ae5f32a84fd70f547b2eee59e93e)
- [`{ childCreatedAt, childId, label?, mode, … }`](#persistence-type-sha256-cbbe8377ee744964537dbafd83607219e58ba79a13f6db0d0645c7ad3d5e8a09)
- [`{ childCreatedAt, childId, label?, mode, … }`](#persistence-type-sha256-5d542ac7bdf13310c46e1a884dec9fb18ad8c6e153cff207e639cd7bf9d7e694)
- [`{ childCreatedAt, childId, label?, mode, … }`](#persistence-type-sha256-b6896938660a1dfe4ddd100fb3164d9f8fa57feeabfe37441a80106c9942697a)
- [`{ childCreatedAt, childId, label?, mode, … }`](#persistence-type-sha256-a0f25b5aeeebf2bf1542ce67726b095e3b139a39c71861d57e827f12dea1f499)
- [`{ childCreatedAt, childId, label, mode, … }`](#persistence-type-sha256-0e10d7c096b47e61defe372a5fc8bd37d835199410eac44367f95c45082498bd)
<a id="persistence-type-sha256-86d1d0e9cfebb240421187e3dc37fb71cc38a1501885cf32f8f9adef7b0a2bde"></a>
@@ -5986,6 +5996,21 @@ SHA-256: `0e10d7c096b47e61defe372a5fc8bd37d835199410eac44367f95c45082498bd`
| `mode` | 必需 | `"continuable"` |
| `version` | 必需 | `0` |
<a id="persistence-type-sha256-8faed5b52ab2d2df40b94a926d0f0faa75280bddcc4b17b6bdd9c8bfed7c34b5"></a>
### `{ childCreatedAt, childId, label, mode, … }`
SHA-256: `8faed5b52ab2d2df40b94a926d0f0faa75280bddcc4b17b6bdd9c8bfed7c34b5`
| 属性 | 存在性 | 类型 |
|---|---|---|
| `childCreatedAt` | 必需 | `number` |
| `childId` | 必需 | `string` |
| `label` | 必需 | `string` |
| `mode` | 必需 | `"continuable"` |
| `name` | 必需 | `string` |
| `version` | 必需 | `3` |
<a id="persistence-type-sha256-e2ad8f5bcd813f268ffef1b10a12d7ddd2b8ced8b9b6d0275b3f6b7ed094a187"></a>
### `{ childCreatedAt, childId, label, mode, … }`
@@ -6028,6 +6053,21 @@ SHA-256: `a0f25b5aeeebf2bf1542ce67726b095e3b139a39c71861d57e827f12dea1f499`
| `mode` | 必需 | `"unknown"` |
| `version` | 必需 | `1` |
<a id="persistence-type-sha256-a43327a1739c3fa477f32981071fef7d8ba6ae5f32a84fd70f547b2eee59e93e"></a>
### `{ childCreatedAt, childId, label?, mode, … }`
SHA-256: `a43327a1739c3fa477f32981071fef7d8ba6ae5f32a84fd70f547b2eee59e93e`
| 属性 | 存在性 | 类型 |
|---|---|---|
| `childCreatedAt` | 必需 | `number` |
| `childId` | 必需 | `string` |
| `label` | 可选 | `string` |
| `mode` | 必需 | `"external"` |
| `name` | 必需 | `string` |
| `version` | 必需 | `3` |
<a id="persistence-type-sha256-b6896938660a1dfe4ddd100fb3164d9f8fa57feeabfe37441a80106c9942697a"></a>
### `{ childCreatedAt, childId, label?, mode, … }`
@@ -8859,17 +8899,17 @@ SHA-256: `4513e088d43e6c68425be30451b9f961cc264fe7318ca62681c41d4d78615986`
| `time` | 必需 | `number` |
| `type` | 必需 | `"step/start"` |
<a id="persistence-type-sha256-53750b9abf61efb7992b0aadc3e247ec927449c63266df28230fd1139f5590ac"></a>
<a id="persistence-type-sha256-d49164d37eab0f0f70fa787c65d887abbea869c010ccb103d717fab3519c3a41"></a>
<a id="persistence-type-eventsubagentcatalog"></a>
### `{ type: "subagent/catalog" }`
SHA-256: `53750b9abf61efb7992b0aadc3e247ec927449c63266df28230fd1139f5590ac`
SHA-256: `d49164d37eab0f0f70fa787c65d887abbea869c010ccb103d717fab3519c3a41`
| 属性 | 存在性 | 类型 |
|---|---|---|
| `data` | 必需 | [`SubagentCatalogEvent`](#persistence-type-sha256-f731ffe80810b0289b3e694d8f40af6f01865c02a622ee457be90ca808b66e87) |
| `data` | 必需 | [`SubagentCatalogEvent`](#persistence-type-sha256-058fc9a6b4fbd5d43437c3a64170002070dfc98e18d87de294b564ae446ca8ae) |
| `ignorable` | 可选 | `true` |
| `seq` | 必需 | `number` |
| `time` | 必需 | `number` |
@@ -0,0 +1,28 @@
# Bilingual-pair consistency record for 2026-11-02-subagent-catalog-names.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write docs/persistence-changes/2026-11-02-subagent-catalog-names.md
/:
en: 3d5a424ae7d7e46b
zh: c22a8e4a62d8cc1a
/2026-11-02-subagent-catalog-names:
en: d60db721936ec588
zh: 9271248e40f283c5
/2026-11-02-subagent-catalog-names/summary:
en: af5f42653bb5d143
zh: 4441c72b0ab5d2b8
/2026-11-02-subagent-catalog-names/table-of-contents:
en: 6cf314a069ceb451
zh: 9adff678e9ecab3b
/2026-11-02-subagent-catalog-names/declaration:
en: 6907136f28e48c90
zh: 02f8298485f3d8e7
/2026-11-02-subagent-catalog-names/compatibility:
en: 201ca563853eb66b
zh: c7d7457a9a4a33b7
/2026-11-02-subagent-catalog-names/verification:
en: cf8533363c2d36f7
zh: 75de24564998ca27
/2026-11-02-subagent-catalog-names/dev-note:
en: b75c8458928b72b9
zh: 003ba4e17b4b5269
@@ -0,0 +1,48 @@
---
description: "Records a persistence type transition and its compatibility acknowledgement."
kind: persistence-change
---
# 2026-11-02-subagent-catalog-names
English | [中文](2026-11-02-subagent-catalog-names.zh.md)
## Summary
Adds version 3 of the parent-owned subagent/catalog payload, which records each continuable or parent-delivered external child's name, unique among its creator's children.
## Table of Contents
- [Declaration](#declaration)
- [Compatibility](#compatibility)
- [Verification](#verification)
- [Dev Note](#dev-note)
<a id="declaration"></a>
## Declaration
```yaml persistence-change
schemaVersion: 1
id: 2026-11-02-subagent-catalog-names
baseline: false
changes:
- root: "event:subagent/catalog"
previous: "2026-09-19-external-subagent-catalog"
after: "d49164d37eab0f0f70fa787c65d887abbea869c010ccb103d717fab3519c3a41"
decision: same-version
```
<a id="compatibility"></a>
## Compatibility
Version 0, 1, and 2 payloads keep their schemas and meaning; current readers restore them as unnamed children addressed by Session id. New local and parent-delivered external creation writes version 3. Earlier releases reject the unknown payload version during native V4 admission and catalog projection restoration instead of misreading the entry, so a parent Session that recorded a named child fails loudly rather than losing a child.
<a id="verification"></a>
## Verification
pnpm exec vitest run packages/subagent/subagent/tests: 495 tests passed, including named catalog restoration, invalid version-3 facts, sibling-unique reservation, cold resume path recovery, and external parent-delivered names. pnpm exec vitest run packages/session/session-format-v3-to-v4/tests: 397 tests passed, including native version-3 admission and rejection.
<a id="dev-note"></a>
## Dev Note
None.
@@ -0,0 +1,31 @@
{
"formatVersion": 2,
"roots": [
{"key":"event:subagent/catalog","kind":"event","event":"subagent/catalog","surface":false,"digest":"d49164d37eab0f0f70fa787c65d887abbea869c010ccb103d717fab3519c3a41"}
],
"types": [],
"nodes": {
"058fc9a6b4fbd5d4": {"kind":"union","types":["0e10d7c096b47e61","5d542ac7bdf13310","8faed5b52ab2d2df","a0f25b5aeeebf2bf","a43327a1739c3fa4","b6896938660a1dfe","cbbe8377ee744964","e2ad8f5bcd813f26"]},
"05a2796621b1ee6c": {"kind":"literal","value":"unknown"},
"0657d3ca5ac4e7bf": {"kind":"primitive","type":"number"},
"0e10d7c096b47e61": {"kind":"object","properties":[{"name":"childCreatedAt","type":"0657d3ca5ac4e7bf","optional":false},{"name":"childId","type":"4cd48f3e5108bd6e","optional":false},{"name":"label","type":"4cd48f3e5108bd6e","optional":false},{"name":"mode","type":"e5d3828df1ec3e2a","optional":false},{"name":"version","type":"93d38436347f67c9","optional":false}],"indices":[]},
"137ac60e26bcb192": {"kind":"literal","value":3},
"44c8c77aa9aa100b": {"kind":"literal","value":"subagent/catalog"},
"4cd48f3e5108bd6e": {"kind":"primitive","type":"string"},
"5d542ac7bdf13310": {"kind":"object","properties":[{"name":"childCreatedAt","type":"0657d3ca5ac4e7bf","optional":false},{"name":"childId","type":"4cd48f3e5108bd6e","optional":false},{"name":"label","type":"4cd48f3e5108bd6e","optional":true},{"name":"mode","type":"d28765f87d6b6ab4","optional":false},{"name":"version","type":"93d38436347f67c9","optional":false}],"indices":[]},
"8faed5b52ab2d2df": {"kind":"object","properties":[{"name":"childCreatedAt","type":"0657d3ca5ac4e7bf","optional":false},{"name":"childId","type":"4cd48f3e5108bd6e","optional":false},{"name":"label","type":"4cd48f3e5108bd6e","optional":false},{"name":"mode","type":"e5d3828df1ec3e2a","optional":false},{"name":"name","type":"4cd48f3e5108bd6e","optional":false},{"name":"version","type":"137ac60e26bcb192","optional":false}],"indices":[]},
"93d38436347f67c9": {"kind":"literal","value":0},
"a0f25b5aeeebf2bf": {"kind":"object","properties":[{"name":"childCreatedAt","type":"0657d3ca5ac4e7bf","optional":false},{"name":"childId","type":"4cd48f3e5108bd6e","optional":false},{"name":"label","type":"4cd48f3e5108bd6e","optional":true},{"name":"mode","type":"05a2796621b1ee6c","optional":false},{"name":"version","type":"f88f1b7b6bb733f6","optional":false}],"indices":[]},
"a0f906856fc06f1c": {"kind":"literal","value":2},
"a43327a1739c3fa4": {"kind":"object","properties":[{"name":"childCreatedAt","type":"0657d3ca5ac4e7bf","optional":false},{"name":"childId","type":"4cd48f3e5108bd6e","optional":false},{"name":"label","type":"4cd48f3e5108bd6e","optional":true},{"name":"mode","type":"fc351843b8ecbd05","optional":false},{"name":"name","type":"4cd48f3e5108bd6e","optional":false},{"name":"version","type":"137ac60e26bcb192","optional":false}],"indices":[]},
"b6896938660a1dfe": {"kind":"object","properties":[{"name":"childCreatedAt","type":"0657d3ca5ac4e7bf","optional":false},{"name":"childId","type":"4cd48f3e5108bd6e","optional":false},{"name":"label","type":"4cd48f3e5108bd6e","optional":true},{"name":"mode","type":"d28765f87d6b6ab4","optional":false},{"name":"version","type":"f88f1b7b6bb733f6","optional":false}],"indices":[]},
"cbbe8377ee744964": {"kind":"object","properties":[{"name":"childCreatedAt","type":"0657d3ca5ac4e7bf","optional":false},{"name":"childId","type":"4cd48f3e5108bd6e","optional":false},{"name":"label","type":"4cd48f3e5108bd6e","optional":true},{"name":"mode","type":"fc351843b8ecbd05","optional":false},{"name":"version","type":"a0f906856fc06f1c","optional":false}],"indices":[]},
"d28765f87d6b6ab4": {"kind":"literal","value":"one-shot"},
"d49164d37eab0f0f": {"kind":"object","properties":[{"name":"data","type":"058fc9a6b4fbd5d4","optional":false},{"name":"ignorable","type":"dacf3d5f3e4ff619","optional":true},{"name":"seq","type":"0657d3ca5ac4e7bf","optional":false},{"name":"time","type":"0657d3ca5ac4e7bf","optional":false},{"name":"type","type":"44c8c77aa9aa100b","optional":false}],"indices":[]},
"dacf3d5f3e4ff619": {"kind":"literal","value":true},
"e2ad8f5bcd813f26": {"kind":"object","properties":[{"name":"childCreatedAt","type":"0657d3ca5ac4e7bf","optional":false},{"name":"childId","type":"4cd48f3e5108bd6e","optional":false},{"name":"label","type":"4cd48f3e5108bd6e","optional":false},{"name":"mode","type":"e5d3828df1ec3e2a","optional":false},{"name":"version","type":"f88f1b7b6bb733f6","optional":false}],"indices":[]},
"e5d3828df1ec3e2a": {"kind":"literal","value":"continuable"},
"f88f1b7b6bb733f6": {"kind":"literal","value":1},
"fc351843b8ecbd05": {"kind":"literal","value":"external"}
}
}
@@ -0,0 +1,48 @@
---
description: "记录持久化类型更改及其兼容性确认。"
kind: persistence-change
---
# 2026-11-02-subagent-catalog-names
[English](2026-11-02-subagent-catalog-names.md) | 中文
## 概述
为父 Session 拥有的 subagent/catalog 载荷增加 version 3,记录每个 continuable 子代理或父级交付的 external 子代理在其创建者子代理中唯一的名称。
## 目录
- [声明](#declaration)
- [兼容性](#compatibility)
- [验证](#verification)
- [开发备注](#dev-note)
<a id="declaration"></a>
## 声明
```yaml persistence-change
schemaVersion: 1
id: 2026-11-02-subagent-catalog-names
baseline: false
changes:
- root: "event:subagent/catalog"
previous: "2026-09-19-external-subagent-catalog"
after: "d49164d37eab0f0f70fa787c65d887abbea869c010ccb103d717fab3519c3a41"
decision: same-version
```
<a id="compatibility"></a>
## 兼容性
version 0、1、2 载荷的 schema 和含义保持不变;当前读取方将其恢复为按 Session id 寻址的无名子代理。新的本地创建和父级交付的 external 创建写入 version 3。较早版本在原生 V4 准入和目录投影恢复时拒绝未知载荷版本,而不会误读条目,因此记录了具名子代理的父 Session 会明确失败,而不是丢失子代理。
<a id="verification"></a>
## 验证
pnpm exec vitest run packages/subagent/subagent/tests:495 个测试通过,覆盖具名目录恢复、无效 version 3 事实、同级唯一预留、冷恢复路径还原以及父级交付 external 子代理的名称。pnpm exec vitest run packages/session/session-format-v3-to-v4/tests:397 个测试通过,覆盖原生 version 3 准入与拒绝。
<a id="dev-note"></a>
## 开发备注
无。
@@ -15,8 +15,8 @@
en: 14c57f30e676f6e3
zh: b1a0ccf26fab3727
/session-persistence-formats/format-references:
en: a660985fd2941e51
zh: 0d4aed6be93be922
en: 77ac7919d6cac2e4
zh: 1ecb8a42e6d2a0fd
/session-persistence-formats/scope-and-evidence:
en: b220062139ddac1e
zh: 7c4c0efe05dafa9c
@@ -32,7 +32,7 @@ The index is generated from validated snapshots and the current writer constant.
| 1 | PR #3349 | [V1](v1.md) | [JSON](v1.schema.json) | 54 / 415 |
| 2 | `dsh-v0.1.3-alpha.2` | [V2](v2.md) | [JSON](v2.schema.json) | 56 / 435 |
| 3 | PR #4320 | [V3](v3.md) | [JSON](v3.schema.json) | 60 / 467 |
| 4 | Current checkout | [Current catalog](../../persistence-catalog.md) | [JSON](../../persistence-schema.json) | 66 / 631 |
| 4 | Current checkout | [Current catalog](../../persistence-catalog.md) | [JSON](../../persistence-schema.json) | 66 / 634 |
<!-- persistence-format-index:end -->
@@ -32,7 +32,7 @@ description: "查找从 V0 到工作区写入器版本的每个 Session 格式
| 1 | PR #3349 | [V1](v1.zh.md) | [JSON](v1.schema.json) | 54 / 415 |
| 2 | `dsh-v0.1.3-alpha.2` | [V2](v2.zh.md) | [JSON](v2.schema.json) | 56 / 435 |
| 3 | PR #4320 | [V3](v3.zh.md) | [JSON](v3.schema.json) | 60 / 467 |
| 4 | 当前工作树 | [当前目录](../../persistence-catalog.zh.md) | [JSON](../../persistence-schema.json) | 66 / 631 |
| 4 | 当前工作树 | [当前目录](../../persistence-catalog.zh.md) | [JSON](../../persistence-schema.json) | 66 / 634 |
<!-- persistence-format-index:end -->
+11 -5
View File
@@ -43,7 +43,7 @@
{"key":"event:session/title-llm-request","kind":"event","event":"session/title-llm-request","surface":false,"digest":"d95c624eddecdacf1ee74356196c09d2f3fcd625714be5e852a6b643fa12a7ca"},
{"key":"event:step/end","kind":"event","event":"step/end","surface":false,"digest":"e0a787e6ec76c7c94fecbc501b489164ab0293db05bc947914077ad01e674f05"},
{"key":"event:step/start","kind":"event","event":"step/start","surface":false,"digest":"4513e088d43e6c68425be30451b9f961cc264fe7318ca62681c41d4d78615986"},
{"key":"event:subagent/catalog","kind":"event","event":"subagent/catalog","surface":false,"digest":"53750b9abf61efb7992b0aadc3e247ec927449c63266df28230fd1139f5590ac"},
{"key":"event:subagent/catalog","kind":"event","event":"subagent/catalog","surface":false,"digest":"d49164d37eab0f0f70fa787c65d887abbea869c010ccb103d717fab3519c3a41"},
{"key":"event:subagent/descriptor","kind":"event","event":"subagent/descriptor","surface":false,"digest":"b79ada42962cad0190a9d465805260567621fa3a4abd757eb31e6016b52d5ab5"},
{"key":"event:subagent/model-selection-policy","kind":"event","event":"subagent/model-selection-policy","surface":false,"digest":"a6567ccb2e530606b775371eb4fa31468d72084339968e8b0440a516a23b39dc"},
{"key":"event:system/message","kind":"event","event":"system/message","surface":true,"digest":"69081694be231d56fd9580ba14645fd5e35373202605d5c5c841a9435b5fa3b1"},
@@ -77,6 +77,7 @@
{"digest":"02b2c23f2d94b028c9588a8faace3fce1217405db346da3389368b495457bf79","names":[],"sources":["packages/extensions/cordis-host-runner/src/index.ts:14"]},
{"digest":"0341d4c3dfcd53253cdc1e789d9130d3cd848b6f8b0706bf92f313a68b39ff23","names":[],"sources":[]},
{"digest":"05205074b24d8340cfd7995f6cb64779c7f1241490954700115601e264178877","names":[],"sources":[]},
{"digest":"058fc9a6b4fbd5d43437c3a64170002070dfc98e18d87de294b564ae446ca8ae","names":["packages/subagent/subagent/src/catalog.ts#SubagentCatalogEvent"],"sources":["packages/subagent/subagent/src/catalog.ts:32"]},
{"digest":"05a2796621b1ee6c03ef7abe560b25116bb4da4d592312117242a78415a32b04","names":[],"sources":[]},
{"digest":"05d2ae1e0c7f8770f83f9a09047afb39a335d8ac986df3193659aa1e581472cf","names":["packages/interaction/user-approval/src/index.ts#ApprovalPolicy"],"sources":["packages/interaction/user-approval/src/index.ts:68"]},
{"digest":"0657d3ca5ac4e7bf79b00bcf860b1c7159d01a9da137497221ec2f1776e365f7","names":["packages/core/session/src/types.ts#SessionSeq"],"sources":["packages/core/session/src/types.ts:33"]},
@@ -113,6 +114,7 @@
{"digest":"12a0cfa619ac4a5fc6c3e8e359c8dae15769edc61497a575935c78d5842f8e42","names":[],"sources":[]},
{"digest":"12d5808fac1996b9b3c2afa806e03022252ba2d7b88f835862ae1896591f60c7","names":["packages/llm/llm/src/types.ts#ImageBlock"],"sources":["packages/llm/llm/src/types.ts:86"]},
{"digest":"1379f0b72275994d20f1ddca2d60a96ab16ec80397ca9f1af21bdc67ba5c269c","names":[],"sources":[]},
{"digest":"137ac60e26bcb192210d9a32a704b73b0924ed34019323defa1b787be95bd45e","names":[],"sources":[]},
{"digest":"13d3d180f977bf78081d487ffa0ecb75857349bcab29a5a3fb48189fca2a6176","names":[],"sources":[]},
{"digest":"14230f9b8b5797bb7e8c621fa636531cfbde2ffba1ef5f1fd058216ff21952a0","names":[],"sources":[]},
{"digest":"142c37d302aa22a0a57915b5255939d3ca91c1811ca13fddcf84cf76ea00758a","names":[],"sources":[]},
@@ -271,7 +273,6 @@
{"digest":"52c6113cb0e53f345324bf84f01928bea5d5df57ee80bc0dd65407b8bc5a3734","names":[],"sources":[]},
{"digest":"5302e763151277614b97e77f00e3b326694c6c1247b916a20503c344dc970777","names":[],"sources":["packages/core/session/src/types.ts:383"]},
{"digest":"530da6c0267813bb4511af72883cc518834e624e3b3220a7062955fd57a788a6","names":["packages/core/session/src/types.ts#RequestHeaderReason"],"sources":["packages/core/session/src/types.ts:279"]},
{"digest":"53750b9abf61efb7992b0aadc3e247ec927449c63266df28230fd1139f5590ac","names":[],"sources":[]},
{"digest":"53cf1704ae0709c7678bcf070c83c619fc48ca1b5c173b74cfa8702f22a8e492","names":[],"sources":[]},
{"digest":"54f9276a1617d7c12594722c89cfe864bcbe4517e9a6f9c98bab14f199a135e0","names":[],"sources":["packages/core/session/src/types.ts:363"]},
{"digest":"557e148d30b79ee48645850832b30c717d7c3b64641deb5d6133b8b4e91ee0b8","names":[],"sources":[]},
@@ -423,6 +424,7 @@
{"digest":"8e8e91646a5cae3fc78f7532a0013ff2088ae47077642c2edd507a508209b8af","names":["packages/schedule/schedule/src/types.ts#OneShotScheduleDispatchChange"],"sources":["packages/schedule/schedule/src/types.ts:213"]},
{"digest":"8f324cea3916c0517261e88167def8efb3a9994c1135e23d40ed9fd48f8c7bd4","names":[],"sources":[]},
{"digest":"8f6d609794bf5afc01d7ccf3e03811d32f4b8047f58a2c9a98db0154c2ad7cb9","names":[],"sources":[]},
{"digest":"8faed5b52ab2d2df40b94a926d0f0faa75280bddcc4b17b6bdd9c8bfed7c34b5","names":[],"sources":[]},
{"digest":"8fcb0b44a575e998665c053643d1ab04c82f39253ebd190ac0c975b78e40b543","names":[],"sources":["packages/core/tools/src/index.ts:28"]},
{"digest":"904bf499d98be4a3a5f836fcac533b6c4899569b018071e6604e1d32657d00fd","names":[],"sources":[]},
{"digest":"920d87e22b7409bcc7224f8b1dc7f5101c33574c75627c65baab12b85cc96e75","names":[],"sources":[]},
@@ -474,6 +476,7 @@
{"digest":"a3c6f1ea38e9a61d7a9706057ba65aabe02dfe6d9dd90d4736aa62325d874531","names":[],"sources":[]},
{"digest":"a3edd1efd1fef21b72c55e213c8a8b24196b091abde2b89db52be0b2aaae3cfa","names":[],"sources":[]},
{"digest":"a40d12070f6f4a124f32fb3cc86e7857554702e32f0eda3080a25c4b9ac9b18c","names":[],"sources":["packages/team/agent-team/src/types.ts:175"]},
{"digest":"a43327a1739c3fa477f32981071fef7d8ba6ae5f32a84fd70f547b2eee59e93e","names":[],"sources":[]},
{"digest":"a4afec59b75aad5d13ef82d6931f35cc2d98918503916cf069355b77c5e42302","names":[],"sources":["packages/api/session-controller/src/types.ts:397"]},
{"digest":"a6567ccb2e530606b775371eb4fa31468d72084339968e8b0440a516a23b39dc","names":[],"sources":[]},
{"digest":"a6b41f5bede8094d7bf635be5d69b1bd7a25e006ca9cf9415bceb9322f1a7feb","names":["packages/experimental/hook-protocol/src/types.ts#HookDialect"],"sources":["packages/experimental/hook-protocol/src/types.ts:48"]},
@@ -586,6 +589,7 @@
{"digest":"cffcdc19881ab61ec0a9ce18743996f7ac44ac8889f34dfac36ae745574aa22f","names":["packages/goal/goal/src/domain.ts#GoalClearChangeMeta"],"sources":["packages/goal/goal/src/domain.ts:35"]},
{"digest":"d0fbb0ca1bbba059830826f33f801da1aced35a2504376d61e020bdfec8d50c0","names":[],"sources":[]},
{"digest":"d28765f87d6b6ab408e0b2f3e7e297791b004b806d8e302c49903ebae815feb2","names":[],"sources":[]},
{"digest":"d49164d37eab0f0f70fa787c65d887abbea869c010ccb103d717fab3519c3a41","names":[],"sources":[]},
{"digest":"d4b739491689cc6bb13d07ffac1a32239875abda364c0d5edd8f74faf5e9c00d","names":[],"sources":["packages/llm/llm/src/types.ts:501"]},
{"digest":"d4c799e3d51cae1040362ba4968efc484739e14416c9c1df20c2f108b4ef2eb5","names":[],"sources":[]},
{"digest":"d4e4d575abeb4b72d616dc65c17ac0eaa943cc135609395044c38d5afcb10e31","names":[],"sources":[]},
@@ -680,7 +684,6 @@
{"digest":"f6afe41e3926f422fe849debe90819fddd739f0f59e20be9c71018b9554a7f09","names":[],"sources":[]},
{"digest":"f6cb462f808309e315fea634f1ed86268b8346bbcee6774d9097ca6eed7ac1f8","names":[],"sources":[]},
{"digest":"f7283223aacdc39b0adca728c8cbd4c090a20006a6fecec74421c30e943b489c","names":[],"sources":[]},
{"digest":"f731ffe80810b0289b3e694d8f40af6f01865c02a622ee457be90ca808b66e87","names":["packages/subagent/subagent/src/catalog.ts#SubagentCatalogEvent"],"sources":["packages/subagent/subagent/src/catalog.ts:28"]},
{"digest":"f789af5ab844827eb5a4f357c0afae1eeed108c6c22d8ca1a56e586b349a7c85","names":[],"sources":[]},
{"digest":"f88f1b7b6bb733f685f5fb6a8744a5db9199fa53c90463ea1a33bad51153671d","names":[],"sources":[]},
{"digest":"f90eb4ab2d3897bc20c521a038e3119d581f791ec974b1a0004f63a8ab9e232d","names":[],"sources":["packages/core/session/src/types.ts:294","packages/deliverables/workspace-changes/src/types.ts:106"]},
@@ -710,6 +713,7 @@
"02b2c23f2d94b028": {"kind":"object","properties":[{"name":"kind","type":"c5687b1313206a6f","optional":false}],"indices":[]},
"0341d4c3dfcd5325": {"kind":"literal","value":"product-interaction"},
"05205074b24d8340": {"kind":"literal","value":"action-cards"},
"058fc9a6b4fbd5d4": {"kind":"union","types":["0e10d7c096b47e61","5d542ac7bdf13310","8faed5b52ab2d2df","a0f25b5aeeebf2bf","a43327a1739c3fa4","b6896938660a1dfe","cbbe8377ee744964","e2ad8f5bcd813f26"]},
"05a2796621b1ee6c": {"kind":"literal","value":"unknown"},
"05d2ae1e0c7f8770": {"kind":"union","types":["1571525adc95a24e","9e07693fd7cd9bab"]},
"0657d3ca5ac4e7bf": {"kind":"primitive","type":"number"},
@@ -746,6 +750,7 @@
"12a0cfa619ac4a5f": {"kind":"literal","value":"read-only"},
"12d5808fac1996b9": {"kind":"object","properties":[{"name":"attachment","type":"b0b0eb1b16490f6b","optional":false},{"name":"offloaded","type":"dacf3d5f3e4ff619","optional":true},{"name":"type","type":"fb8b6a2e53cb9cf4","optional":false}],"indices":[]},
"1379f0b72275994d": {"kind":"literal","value":"developer/message"},
"137ac60e26bcb192": {"kind":"literal","value":3},
"13d3d180f977bf78": {"kind":"object","properties":[{"name":"data","type":"1528539c63db8b23","optional":false},{"name":"ignorable","type":"dacf3d5f3e4ff619","optional":true},{"name":"seq","type":"0657d3ca5ac4e7bf","optional":false},{"name":"time","type":"0657d3ca5ac4e7bf","optional":false},{"name":"type","type":"1a2718b00937b236","optional":false}],"indices":[]},
"14230f9b8b5797bb": {"kind":"literal","value":"chunk"},
"142c37d302aa22a0": {"kind":"literal","value":"always"},
@@ -904,7 +909,6 @@
"52c6113cb0e53f34": {"kind":"object","properties":[{"name":"form","type":"6f9e00383836275e","optional":false},{"name":"kind","type":"9ac52f0f84fec2eb","optional":false},{"name":"sections","type":"c748fb42c80a1200","optional":false}],"indices":[]},
"5302e76315127761": {"kind":"object","properties":[{"name":"error","type":"a81059ca06999da1","optional":true},{"name":"message","type":"4b259f7f8f0a44ad","optional":false},{"name":"meta","type":"c592ce75aab73fca","optional":true},{"name":"step","type":"0657d3ca5ac4e7bf","optional":false},{"name":"turn","type":"0657d3ca5ac4e7bf","optional":false}],"indices":[]},
"530da6c0267813bb": {"kind":"union","types":["34d1ab5c5df37818","4f507598cf476214","e7ce49f12953583f","f789af5ab844827e"]},
"53750b9abf61efb7": {"kind":"object","properties":[{"name":"data","type":"f731ffe80810b028","optional":false},{"name":"ignorable","type":"dacf3d5f3e4ff619","optional":true},{"name":"seq","type":"0657d3ca5ac4e7bf","optional":false},{"name":"time","type":"0657d3ca5ac4e7bf","optional":false},{"name":"type","type":"44c8c77aa9aa100b","optional":false}],"indices":[]},
"53cf1704ae0709c7": {"kind":"object","properties":[{"name":"form","type":"fee1caf8ab6a65c1","optional":false},{"name":"kind","type":"99e7e7d7fed55ae6","optional":false}],"indices":[]},
"54f9276a1617d7c1": {"kind":"object","properties":[{"name":"step","type":"0657d3ca5ac4e7bf","optional":false},{"name":"stream","type":"84bbfdce7d2eab5b","optional":false},{"name":"turn","type":"0657d3ca5ac4e7bf","optional":false}],"indices":[]},
"557e148d30b79ee4": {"kind":"literal","value":"agent-preset/selected"},
@@ -1056,6 +1060,7 @@
"8e8e91646a5cae3f": {"kind":"object","properties":[{"name":"id","type":"4cd48f3e5108bd6e","optional":false},{"name":"operation","type":"26c879bdd130e8b8","optional":false},{"name":"version","type":"f88f1b7b6bb733f6","optional":false}],"indices":[]},
"8f324cea3916c051": {"kind":"object","properties":[{"name":"form","type":"16d0507cb94b4cfc","optional":false},{"name":"kind","type":"2f3f201c8846e19c","optional":false}],"indices":[]},
"8f6d609794bf5afc": {"kind":"tuple","elements":[{"type":"4e88776858652856","optional":false,"rest":false}]},
"8faed5b52ab2d2df": {"kind":"object","properties":[{"name":"childCreatedAt","type":"0657d3ca5ac4e7bf","optional":false},{"name":"childId","type":"4cd48f3e5108bd6e","optional":false},{"name":"label","type":"4cd48f3e5108bd6e","optional":false},{"name":"mode","type":"e5d3828df1ec3e2a","optional":false},{"name":"name","type":"4cd48f3e5108bd6e","optional":false},{"name":"version","type":"137ac60e26bcb192","optional":false}],"indices":[]},
"8fcb0b44a575e998": {"kind":"object","properties":[{"name":"kind","type":"a720757f704a2512","optional":false}],"indices":[]},
"904bf499d98be4a3": {"kind":"union","types":["7382c4fc95fe8c5d","b765ee31033cea46","f6cb462f808309e3"]},
"920d87e22b7409bc": {"kind":"object","properties":[{"name":"data","type":"c2a13242efc3bea4","optional":false},{"name":"ignorable","type":"dacf3d5f3e4ff619","optional":true},{"name":"seq","type":"0657d3ca5ac4e7bf","optional":false},{"name":"time","type":"0657d3ca5ac4e7bf","optional":false},{"name":"type","type":"d8a476d2c6fd30df","optional":false}],"indices":[]},
@@ -1107,6 +1112,7 @@
"a3c6f1ea38e9a61d": {"kind":"object","properties":[{"name":"form","type":"e8de0f457fed5b9f","optional":false},{"name":"kind","type":"9ac52f0f84fec2eb","optional":false},{"name":"summary","type":"4cd48f3e5108bd6e","optional":false}],"indices":[]},
"a3edd1efd1fef21b": {"kind":"literal","value":"workspace-write"},
"a40d12070f6f4a12": {"kind":"object","properties":[{"name":"task","type":"51edec100659da3a","optional":false},{"name":"teamId","type":"4cd48f3e5108bd6e","optional":false},{"name":"version","type":"a0f906856fc06f1c","optional":false}],"indices":[]},
"a43327a1739c3fa4": {"kind":"object","properties":[{"name":"childCreatedAt","type":"0657d3ca5ac4e7bf","optional":false},{"name":"childId","type":"4cd48f3e5108bd6e","optional":false},{"name":"label","type":"4cd48f3e5108bd6e","optional":true},{"name":"mode","type":"fc351843b8ecbd05","optional":false},{"name":"name","type":"4cd48f3e5108bd6e","optional":false},{"name":"version","type":"137ac60e26bcb192","optional":false}],"indices":[]},
"a4afec59b75aad5d": {"kind":"object","properties":[{"name":"clientTimeZone","type":"4cd48f3e5108bd6e","optional":true},{"name":"kind","type":"68f44f59e91c4139","optional":false},{"name":"principal","type":"824a4aad44a54e24","optional":true},{"name":"rpcId","type":"4cd48f3e5108bd6e","optional":false}],"indices":[]},
"a6567ccb2e530606": {"kind":"object","properties":[{"name":"data","type":"0d47a8f3d847243c","optional":false},{"name":"ignorable","type":"dacf3d5f3e4ff619","optional":true},{"name":"seq","type":"0657d3ca5ac4e7bf","optional":false},{"name":"time","type":"0657d3ca5ac4e7bf","optional":false},{"name":"type","type":"0a8a062bc9c3c0d9","optional":false}],"indices":[]},
"a6b41f5bede8094d": {"kind":"union","types":["15495614ccfa9cbd","aff60ef947c18b01"]},
@@ -1219,6 +1225,7 @@
"cffcdc19881ab61e": {"kind":"object","properties":[{"name":"cleared","type":"0b6d718c693fdf7f","optional":false},{"name":"clearedAt","type":"0657d3ca5ac4e7bf","optional":false},{"name":"kind","type":"237c004c73b6b288","optional":false},{"name":"operation","type":"e7e154d47d5fbc53","optional":false},{"name":"version","type":"f88f1b7b6bb733f6","optional":false}],"indices":[]},
"d0fbb0ca1bbba059": {"kind":"literal","value":"delete"},
"d28765f87d6b6ab4": {"kind":"literal","value":"one-shot"},
"d49164d37eab0f0f": {"kind":"object","properties":[{"name":"data","type":"058fc9a6b4fbd5d4","optional":false},{"name":"ignorable","type":"dacf3d5f3e4ff619","optional":true},{"name":"seq","type":"0657d3ca5ac4e7bf","optional":false},{"name":"time","type":"0657d3ca5ac4e7bf","optional":false},{"name":"type","type":"44c8c77aa9aa100b","optional":false}],"indices":[]},
"d4b739491689cc6b": {"kind":"object","properties":[{"name":"block","type":"8064c03c87c357fd","optional":false},{"name":"index","type":"0657d3ca5ac4e7bf","optional":false},{"name":"type","type":"eefbea819caeeea9","optional":false}],"indices":[]},
"d4c799e3d51cae10": {"kind":"literal","value":"working-directory/change"},
"d4e4d575abeb4b72": {"kind":"literal","value":"canceled"},
@@ -1313,7 +1320,6 @@
"f6afe41e3926f422": {"kind":"object","properties":[{"name":"form","type":"fee1caf8ab6a65c1","optional":false},{"name":"kind","type":"8067b0d232c350f1","optional":false}],"indices":[]},
"f6cb462f808309e3": {"kind":"literal","value":"replace"},
"f7283223aacdc39b": {"kind":"object","properties":[{"name":"kind","type":"9ac52f0f84fec2eb","optional":false}],"indices":[]},
"f731ffe80810b028": {"kind":"union","types":["0e10d7c096b47e61","5d542ac7bdf13310","a0f25b5aeeebf2bf","b6896938660a1dfe","cbbe8377ee744964","e2ad8f5bcd813f26"]},
"f789af5ab844827e": {"kind":"literal","value":"change"},
"f88f1b7b6bb733f6": {"kind":"literal","value":1},
"f90eb4ab2d3897bc": {"kind":"object","properties":[{"name":"turn","type":"0657d3ca5ac4e7bf","optional":false}],"indices":[]},
+2 -2
View File
@@ -15,8 +15,8 @@
en: c70f0fd199fc7db5
zh: c6b77cb5a5cfd1c2
/agent-teams/web-projection:
en: 059d4e5d6a9ddc71
zh: cb3fd92096144e19
en: af4ffca1efab0f56
zh: 1f53c9c258cc5a75
/agent-teams/replay:
en: 448d32856f87b067
zh: 7fafd96314c7e2c5
+1 -1
View File
@@ -77,7 +77,7 @@ interface TeamTaskSnapshot {
`agentTeam.enabled` exposes the root Session’s saved selection. New Sessions default to false; `team/mode` records explicit selections. Historical tasks imply enabled until an explicit selection. Only the root can call `setEnabled`; descendants share that mode. The Web menu calls the same method through `remote.agentTeams.setEnabled`, with the root Session id resolved to its live Agent by the Gateway. Mode writes take effect before awaiting persistence. Tools resolve availability at step preparation; prompt providers read the selection when evaluated. Task mutations check the current mode when their queued operation starts; admitted mutations may finish. Mode changes do not end inbox waits. A failed flush leaves the appended selection active; retrying the same selection flushes it without a duplicate event.
The root Session publishes non-deleted task views through `SessionProjectionMap.agentTeam`. `failure` reports a rejected persisted task or mode record beside the last valid state. Historical roster and mailbox records are not projected. The task panel identifies every owner by its Session id.
The root Session publishes non-deleted task views through `SessionProjectionMap.agentTeam`. `failure` reports a rejected persisted task or mode record beside the last valid state. Historical roster and mailbox records are not projected. Views identify every owner by its Session id; the task panel and task tools display the owner's agent name, or the Session id when the owner has no name.
```ts type-equiv
/** Runtime-enriched task view returned to tools and hosts. */
+1 -1
View File
@@ -77,7 +77,7 @@ interface TeamTaskSnapshot {
`agentTeam.enabled` 提供根 Session 保存的选择。新 Session 默认为 false;`team/mode` 记录显式选择。历史任务在显式选择前视为开启。仅根可调用 `setEnabled`;后代共享该模式。Web 菜单通过 `remote.agentTeams.setEnabled` 调用同一方法,Gateway 将根 Session id 解析为其存活 Agent。模式写入先立即生效,再等待刷盘。工具在步骤准备时确定可用性;提示词提供方在求值时读取选择。任务修改在排队操作开始时检查当前模式;已获准的修改可继续完成。模式变更不会结束收件箱等待。刷盘失败时已追加的选择仍然生效;重试相同选择会再次刷盘,不重复追加事件。
根 Session 通过 `SessionProjectionMap.agentTeam` 发布未删除任务视图。`failure` 在最后有效状态旁报告被拒绝的持久化任务或模式记录。历史名册与邮箱记录不参与投影。任务面板以 Session id 标识每个负责人。
根 Session 通过 `SessionProjectionMap.agentTeam` 发布未删除任务视图。`failure` 在最后有效状态旁报告被拒绝的持久化任务或模式记录。历史名册与邮箱记录不参与投影。视图以 Session id 标识每个负责人;任务面板和任务工具显示负责人的 agent 名称,负责人没有名称时显示其 Session id。
```ts type-equiv
/** Runtime-enriched task view returned to tools and hosts. */
+5 -2
View File
@@ -11,6 +11,9 @@
/subagents/local-children-and-activations:
en: 6f87231d18d82916
zh: 9f064b23058f8766
/subagents/agent-names:
en: 50a0b5505111af2c
zh: e4f4172ca212771d
/subagents/messages-and-interruption:
en: 9befacb931520842
zh: c214b4fffa779b06
@@ -24,5 +27,5 @@
en: 226ba8094a8cf96c
zh: 719678662905d1eb
/subagents/durable-enumeration-listdescendants-and-catalog-entries:
en: 8000138f84fd15fa
zh: 32fa91d3aebd3d01
en: 992acbcc3ac77e30
zh: 83b9dd42ade734ab
+51 -1
View File
@@ -33,6 +33,12 @@ interface SubagentActivationSpec extends Omit<SubagentStartRequest, 'label' | 's
readonly provider: string
/** Short task label retained in cataloged child membership. */
readonly label: string
/**
* Requested name, unique among the parent's children: 1–32 lower-case
* letters, digits, or hyphens starting with a letter, other than `lead`.
* Omission selects the first free `agent-N`.
*/
readonly name?: string
/** Optional reserved identity for a local child; external backends allocate their own ids. */
readonly childId?: SessionId
/** Cancellation before publication; callers own later cancellation through dispose. */
@@ -47,6 +53,11 @@ interface SubagentActivationSpec extends Omit<SubagentStartRequest, 'label' | 's
interface SubagentActivation {
/** Stable identity of the child. */
readonly childId: SessionId
/**
* Model-facing name: slash-separated names from the root when every creator
* below the root is named, otherwise the child Session id.
*/
readonly name: string
/** Accepted inbox message, when the backend has a local inbox. */
readonly messageId?: MessageId
/**
@@ -168,6 +179,20 @@ interface ContinuableCreateSpec {
}
```
## Agent names
Session ids remain the only execution identity for routing, authorization, persistence, and task ownership; names are model-facing references. `SubagentActivation.name` is the child's full name, and `listDescendants()` rows carry it as `path` when every link from the root is named. `namesOf(agent)` reports the names of a live member and its direct creator; the root is `lead`. `resolveName(caller, name, signal)` returns the Session id for `lead` or a full name and returns any other text unchanged as a Session id. Callers authorize the result; resolution grants no authority. The [package README](../../packages/subagent/subagent/README.md#agent-names) defines the name rule, defaults, failures, and catalog persistence.
```ts type-equiv
/** Model-facing names of one live tree member and its direct creator. */
interface SubagentMemberNames {
/** `lead` for the root, the slash-separated path for a named descendant, otherwise the Session id. */
readonly self: string
/** The direct creator's name by the same rule; absent for the root. */
readonly parent?: string
}
```
## Messages and interruption
`sendMessage` requires the exact live sender and a target Session id in the same root tree. Root and continuable members can message across branches; admission revalidates the sender and root. Running targets receive Steer; only an absent target cold-resumes, while its creation ancestors may remain offline. External executions reject follow-ups. Local and external executions report final text, structured output, diagnostics, and status to their direct creator only while it is online; caller delivery suppresses those notices. `drainDescendants` awaits whole-tree teardown; an activation receipt’s `dispose()` releases only that execution.
@@ -377,7 +402,7 @@ The model-facing `list_agents` adapter reports current activity as `running` or
Direct-child entries are available as `observation.projections?.values.subagentCatalog` through `ctx.sessionQuery.observeSession(parentSessionId, { signal })`; callers release the observation with `using`. Entries follow parent event order without reading child logs or enumerating the Session corpus. Query failures propagate; a missing catalog projection means discovery is unavailable. Browser rows derive membership from the shared projection store and add activity from Session status; the control stream pushes complete catalog updates. `listDescendants()` recursively reads those catalogs and derives `hasChildren` from each child catalog. [The parent-catalog Agent Note](../../.agents/notes/implemented/architecture/2026-09-01-parent-owned-subagent-catalog.md) owns creation, fork isolation, ordering, and persistence costs.
`SubagentRuntime.listDescendants(rootSessionId)` recursively calls the same catalog reader in stable pre-order, preserving each parent's event order. External entries are leaves without local Sessions. One-shot and unknown-mode entries remain traversal nodes; unknown modes produce `unsupported` diagnostics. An unreadable child catalog produces `corrupt` or `unavailable` and stops only that branch. Root read failures, missing services or projections, and cancellation reject the listing. Each reachable catalog is observed once and released before the next read; repeated ids and cycles are skipped. Sessions absent from reachable catalogs are not discovered, including ordinary Session forks and any subagents below those forks. Each row carries its catalog parent and root-relative depth:
`SubagentRuntime.listDescendants(rootSessionId)` recursively calls the same catalog reader in stable pre-order, preserving each parent's event order. External entries are leaves without local Sessions. One-shot and unknown-mode entries remain traversal nodes; unknown modes produce `unsupported` diagnostics. An unreadable child catalog produces `corrupt` or `unavailable` and stops only that branch. Root read failures, missing services or projections, and cancellation reject the listing. Each reachable catalog is observed once and released before the next read; repeated ids and cycles are skipped. Sessions absent from reachable catalogs are not discovered, including ordinary Session forks and any subagents below those forks. Each row carries its catalog parent, root-relative depth, and, when every link from the root is named, its full name as `path`:
```ts type-equiv
/** One catalog descendant with its direct parent and edge distance from the requested root. */
@@ -386,6 +411,8 @@ type SubagentDescendantListEntry = SubagentListEntry & {
readonly parentId: SessionId
/** Edge distance from the requested root; direct children are `1`. */
readonly depth: number
/** Slash-separated names from the requested root; absent when this child or an ancestor below the root has no name. */
readonly path?: string
}
```
@@ -443,6 +470,29 @@ startActivation(spec: SubagentActivationSpec): Promise<SubagentActivation>
*/
rootOf(caller: Agent): Agent
/**
* Report the model-facing names of a live tree member and its direct creator.
* The root is `lead`; a descendant is the slash-separated path of names from
* the root, or its Session id when it or a creator below the root has no name.
* @param agent - exact live root or resident tree member.
* @returns the member's name and, for a descendant, its creator's name.
* @throws when the caller or its runtime owner is unavailable.
*/
namesOf(agent: Agent): SubagentMemberNames
/**
* Resolve a model-supplied agent reference within the caller's tree. `lead`
* selects the root; a slash-separated path is looked up through the catalogs
* along it; any other text is returned as a Session id. Resolution grants no
* authority: messaging, interruption, and assignment authorize the result.
* @param caller - exact live Agent whose tree root anchors the lookup.
* @param name - `lead`, a full name from the root, or a Session id.
* @param signal - cancellation forwarded to each catalog read.
* @returns the referenced Session id.
* @throws when the caller's root is unavailable or a catalog along the path cannot be read.
*/
async resolveName(caller: Agent, name: string, signal: AbortSignal): Promise<SessionId>
/**
* Join progressing subagent tree work for its root. Idle members with parked input
* stay resident without delaying host completion. Ordinary members return false.
+51 -1
View File
@@ -33,6 +33,12 @@ interface SubagentActivationSpec extends Omit<SubagentStartRequest, 'label' | 's
readonly provider: string
/** Short task label retained in cataloged child membership. */
readonly label: string
/**
* Requested name, unique among the parent's children: 1–32 lower-case
* letters, digits, or hyphens starting with a letter, other than `lead`.
* Omission selects the first free `agent-N`.
*/
readonly name?: string
/** Optional reserved identity for a local child; external backends allocate their own ids. */
readonly childId?: SessionId
/** Cancellation before publication; callers own later cancellation through dispose. */
@@ -47,6 +53,11 @@ interface SubagentActivationSpec extends Omit<SubagentStartRequest, 'label' | 's
interface SubagentActivation {
/** Stable identity of the child. */
readonly childId: SessionId
/**
* Model-facing name: slash-separated names from the root when every creator
* below the root is named, otherwise the child Session id.
*/
readonly name: string
/** Accepted inbox message, when the backend has a local inbox. */
readonly messageId?: MessageId
/**
@@ -168,6 +179,20 @@ interface ContinuableCreateSpec {
}
```
## Agent 名称
Session id 仍是路由、授权、持久化和任务归属使用的唯一执行身份;名称是面向模型的引用。`SubagentActivation.name` 是子级的完整名称;当从根开始的每一级都有名称时,`listDescendants()` 的行以 `path` 携带该名称。`namesOf(agent)` 报告在线成员及其直接创建者的名称;根的名称为 `lead`。`resolveName(caller, name, signal)` 为 `lead` 或完整名称返回对应 Session id,其他文本原样作为 Session id 返回。调用方授权解析结果;解析本身不授予权限。[包 README](../../packages/subagent/subagent/README.zh.md#agent-names) 定义名称规则、默认值、失败和目录持久化。
```ts type-equiv
/** Model-facing names of one live tree member and its direct creator. */
interface SubagentMemberNames {
/** `lead` for the root, the slash-separated path for a named descendant, otherwise the Session id. */
readonly self: string
/** The direct creator's name by the same rule; absent for the root. */
readonly parent?: string
}
```
## 消息与中断
`sendMessage` 要求确切在线发送方和同一根树中的目标 Session id。根和可继续成员可跨分支发消息;接纳时重新校验发送方和根。运行中目标接收 Steer;只冷恢复不在线的目标,其创建祖先可以保持离线。外部执行拒绝后续输入。本地和外部执行仅向仍在线的直接创建者报告最终文本、结构化输出、诊断和状态;caller 投递抑制这些通知。`drainDescendants` 等待整棵树释放;activation 回执的 `dispose()` 仅释放那一次执行。
@@ -377,7 +402,7 @@ interface SubagentProvider {
通过 `ctx.sessionQuery.observeSession(parentSessionId, { signal })`,可从 `observation.projections?.values.subagentCatalog` 获取直接子级条目;调用方使用 `using` 释放观察对象。条目遵循父会话事件顺序,不读取子级日志,也不枚举 Session 语料库。查询失败直接传播;缺少目录投影意味着发现功能不可用。浏览器条目从共享 projection store 派生成员关系,并从 Session 状态补充活动状态;control stream 推送完整目录更新。`listDescendants()` 递归读取这些目录,并从每个子级目录推导 `hasChildren`。[父目录 Agent Note](../../.agents/notes/implemented/architecture/2026-09-01-parent-owned-subagent-catalog.zh.md) 说明创建、fork 隔离、排序和持久化成本。
`SubagentRuntime.listDescendants(rootSessionId)` 以稳定前序递归调用同一目录读取函数,保留每个父级的事件顺序。外部条目是没有本地 Session 的叶节点。一次性和未知模式条目仍是遍历节点;未知模式产生 `unsupported` 诊断。无法读取的子级目录产生 `corrupt` 或 `unavailable`,只停止该分支。根读取失败、服务或投影缺失、取消会使整个查询失败。每个可达目录只观察一次,并在下一次读取前释放;重复 id 和循环引用会被跳过。可达目录中不存在的 Session 不会被发现,包括普通 Session fork 及其下的子 agent。每行携带目录中的父级和相对根的深度:
`SubagentRuntime.listDescendants(rootSessionId)` 以稳定前序递归调用同一目录读取函数,保留每个父级的事件顺序。外部条目是没有本地 Session 的叶节点。一次性和未知模式条目仍是遍历节点;未知模式产生 `unsupported` 诊断。无法读取的子级目录产生 `corrupt` 或 `unavailable`,只停止该分支。根读取失败、服务或投影缺失、取消会使整个查询失败。每个可达目录只观察一次,并在下一次读取前释放;重复 id 和循环引用会被跳过。可达目录中不存在的 Session 不会被发现,包括普通 Session fork 及其下的子 agent。每行携带目录中的父级、相对根的深度;当从根开始的每一级都有名称时,还以 `path` 携带完整名称:
```ts type-equiv
/** One catalog descendant with its direct parent and edge distance from the requested root. */
@@ -386,6 +411,8 @@ type SubagentDescendantListEntry = SubagentListEntry & {
readonly parentId: SessionId
/** Edge distance from the requested root; direct children are `1`. */
readonly depth: number
/** Slash-separated names from the requested root; absent when this child or an ancestor below the root has no name. */
readonly path?: string
}
```
@@ -445,6 +472,29 @@ startActivation(spec: SubagentActivationSpec): Promise<SubagentActivation>
*/
rootOf(caller: Agent): Agent
/**
* Report the model-facing names of a live tree member and its direct creator.
* The root is `lead`; a descendant is the slash-separated path of names from
* the root, or its Session id when it or a creator below the root has no name.
* @param agent - exact live root or resident tree member.
* @returns the member's name and, for a descendant, its creator's name.
* @throws when the caller or its runtime owner is unavailable.
*/
namesOf(agent: Agent): SubagentMemberNames
/**
* Resolve a model-supplied agent reference within the caller's tree. `lead`
* selects the root; a slash-separated path is looked up through the catalogs
* along it; any other text is returned as a Session id. Resolution grants no
* authority: messaging, interruption, and assignment authorize the result.
* @param caller - exact live Agent whose tree root anchors the lookup.
* @param name - `lead`, a full name from the root, or a Session id.
* @param signal - cancellation forwarded to each catalog read.
* @returns the referenced Session id.
* @throws when the caller's root is unavailable or a catalog along the path cannot be read.
*/
async resolveName(caller: Agent, name: string, signal: AbortSignal): Promise<SessionId>
/**
* Join progressing subagent tree work for its root. Idle members with parked input
* stay resident without delaying host completion. Ordinary members return false.
+9 -9
View File
@@ -9,8 +9,8 @@
en: 6cc2cd9ced70bb09
zh: 1c0e6cb4ba2ed637
/tool-schema-catalog/tool-package-map:
en: 6e8419f195bc96a1
zh: 564c4f04420d329a
en: b208722c649460ba
zh: 8f8224ad1158f34b
/tool-schema-catalog/deepseek-ai-dsh-plugin-manager:
en: e0143916bb634762
zh: e0143916bb634762
@@ -240,8 +240,8 @@
en: 8daafae6faf7898e
zh: 8daafae6faf7898e
/tool-schema-catalog/deepseek-ai-dsh-experimental-tool-subagent-oar/subagent-oar:
en: 6283c3023d6ea436
zh: 9c018b8c12a3f1e7
en: 4936c61a65f8cdb2
zh: 5a1bfbb9738a62a9
/tool-schema-catalog/deepseek-ai-dsh-tool-subagent:
en: 841abe0dd5913ea7
zh: 841abe0dd5913ea7
@@ -249,17 +249,17 @@
en: 207228068bc61885
zh: 36e9344ee1af8869
/tool-schema-catalog/deepseek-ai-dsh-tool-subagent/subagent:
en: 430672da3c1a6ca6
zh: bd3a9ab4089f9dbb
en: 9912eeda5bc40b43
zh: 0cb70f9a0d923bee
/tool-schema-catalog/deepseek-ai-dsh-tool-subagent-control:
en: ab82e130c3413f04
zh: ab82e130c3413f04
/tool-schema-catalog/deepseek-ai-dsh-tool-subagent-control/interrupt-agent:
en: a622b15cc2598d51
zh: 48e1b05956d63e26
zh: ece4b2af6a11c49c
/tool-schema-catalog/deepseek-ai-dsh-tool-subagent-control/list-agents:
en: a56168133c21c6a0
zh: f9df1c0fe49fa225
en: fddccad0b31e7fbc
zh: fbaf63fa019c4df7
/tool-schema-catalog/deepseek-ai-dsh-tool-subagent-control/send-message:
en: b53326fedeab850d
zh: ecb75b6ce31da009
+21 -13
View File
@@ -40,7 +40,7 @@ This table connects model-visible tool names to the plugin package and service s
| `@deepseek-ai/dsh-tool-skill` | `skill` | `ctx.workingDirectory`, `ctx.tools`, `ctx.agents`, `ctx.skills` | `tool/call`, `tool/result`, `user/message replacement catalogs via agent.inject()` | - | - |
| `@deepseek-ai/dsh-tool-session-query` | `session_event_read`, `session_event_search`, `session_event_trace`, `session_search`, `session_trace` | `ctx.tools`, `ctx.systemPrompt`, `ctx.sessionQuery`, `ctx.agents`, `a calling Agent for workspace authority` | `tool/call`, `tool/result` | - | The five read-only tools hide provider cursors and authorize every result from the immutable calling agent session. The package is opt-in; compositions that need enforced deadlines or bounded inline output also mount the generic timeout or spill policies. |
| `@deepseek-ai/dsh-experimental-tool-subagent-oar` | `subagent_oar` | `ctx.tools`, `ctx.subagents` | `tool/call`, `tool/result`, `parent subagent catalog and completion notices` | - | The subagent_oar tool selects among configured aliases for external providers. This catalog shows Codex and Claude Code aliases; each deployment chooses its providers. Native model and permission settings belong to the selected provider configuration. |
| `@deepseek-ai/dsh-tool-subagent` | `list_subagent_models`, `subagent` | `ctx.tools`, `ctx.subagents`, `ctx.systemPrompt`, `ctx.sessionProjections`, `ctx.llm for model discovery and selected-route validation` | `tool/call`, `tool/result`, `child session events through the chosen provider` | `subagent`, `subagent_fork` | The load-time `toolName` selects the delegation name (default `subagent`); `modelSelection` adds optional route fields. `modelDiscovery` defaults off and registers shared discovery on one instance per scope. Web and Desktop presets enable spawn discovery and route fields and leave `subagent_fork` route fields disabled. The Host settings service records authorization for each new top-level Session; child Sessions inherit it. Without a recorded policy, discovery and explicit selection permit only the current parent route. Every delegation returns a child id promptly; local children accept follow-ups, while external backends report their single execution automatically. |
| `@deepseek-ai/dsh-tool-subagent` | `list_subagent_models`, `subagent` | `ctx.tools`, `ctx.subagents`, `ctx.systemPrompt`, `ctx.sessionProjections`, `ctx.llm for model discovery and selected-route validation` | `tool/call`, `tool/result`, `child session events through the chosen provider` | `subagent`, `subagent_fork` | The load-time `toolName` selects the delegation name (default `subagent`); `modelSelection` adds optional route fields. `modelDiscovery` defaults off and registers shared discovery on one instance per scope. Web and Desktop presets enable spawn discovery and route fields and leave `subagent_fork` route fields disabled. The Host settings service records authorization for each new top-level Session; child Sessions inherit it. Without a recorded policy, discovery and explicit selection permit only the current parent route. Every delegation returns the child's name promptly; local children accept follow-ups, while external backends report their single execution automatically. |
| `@deepseek-ai/dsh-tool-subagent-control` | `interrupt_agent`, `list_agents`, `send_message`, `wait_agent` | `ctx.tools`, `ctx.subagents`, `ctx.agents` | `tool/call`, `tool/result`, `child session events through ctx.subagents` | - | The shared control tools discover and contact agents in the subagent tree, interrupt owned descendants, and wait for input in the caller’s inbox. Provider-bound `tool-subagent` instances supply delegation tools. |
| `@deepseek-ai/dsh-tool-jobs` | `job_kill`, `job_list`, `job_output` | `ctx.tools`, `ctx.jobs`, `ctx.systemPrompt` | `tool/call`, `tool/result`, `user/message via agent.inject() for background completion notices` | - | The kind-agnostic background-job controller: background bash commands and PTY sends are read, listed, and killed through the same three tools. Loading the plugin attaches the controller that arms producers' `ctx.jobs.start()`. |
| `@deepseek-ai/dsh-tool-agent-team` | `team_task_create`, `team_task_get`, `team_task_list`, `team_task_update` | `ctx.tools`, `ctx.systemPrompt`, `ctx.agentTeams`, `ctx.subagents`, `an exact live Team member Agent` | `tool/call`, `team/task`, `tool/result` | - | Four task-board tools share the subagent tree’s root Session. Enabling Team mode on the root Session adds task-board guidance alongside standard subagent delegation and control tools. Standard subagent controls provide required identity independently of Team mode. |
@@ -1994,7 +1994,7 @@ The five read-only tools hide provider cursors and authorize every result from t
### `subagent_oar`
Delegate a self-contained task to a configured external agent. Choose its runtime for each call. The child works in its own context and does not see this conversation. This tool returns a child id; a later completion notice includes its final answer. The child does not accept follow-up messages. Start independent tasks together and continue useful work while they run. When only waiting for their results remains, end your turn instead of polling.
Delegate a self-contained task to a configured external agent. Choose its runtime for each call. The child works in its own context and does not see this conversation. This tool returns the child's name; a later completion notice includes its final answer. The child does not accept follow-up messages. Start independent tasks together and continue useful work while they run. When only waiting for their results remains, end your turn instead of polling.
```json
{
@@ -2012,6 +2012,10 @@ Delegate a self-contained task to a configured external agent. Choose its runtim
"type": "string",
"description": "A short description of the delegated task, for display."
},
"name": {
"type": "string",
"description": "Optional short name for the subagent, unique among the subagents you create: lower-case letters, digits, and hyphens, starting with a letter, at most 32 characters. Omitted names default to agent-1, agent-2, and so on."
},
"prompt": {
"type": "string",
"description": "The complete, self-contained task. Include all context the external agent needs."
@@ -2061,7 +2065,7 @@ Source: [`packages/subagent/tool-subagent/src/list-models.ts`](../packages/subag
### `subagent`
Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its id. If you are still online when it finishes, the runtime automatically delivers its completion notice. The notice includes the final answer unless the child sent you a message just before finishing. Use `send_message` to steer it while running or continue its conversation after it finishes.
Delegate a self-contained task to a subagent (a separate agent that works in its own context) to offload focused, independent work — research, a scoped implementation, an analysis — so it does not consume this conversation's context. The subagent returns its result, not its intermediate steps. This tool starts an independently managed subagent and immediately returns its name. If you are still online when it finishes, the runtime automatically delivers its completion notice. The notice includes the final answer unless the child sent you a message just before finishing. Use `send_message` to steer it while running or continue its conversation after it finishes.
```json
{
@@ -2075,6 +2079,10 @@ Delegate a self-contained task to a subagent (a separate agent that works in its
"type": "string",
"description": "A short (3-5 word) description of the delegated task, for display. Use the language of the user's current request."
},
"name": {
"type": "string",
"description": "Optional short name for the subagent, unique among the subagents you create: lower-case letters, digits, and hyphens, starting with a letter, at most 32 characters. Omitted names default to agent-1, agent-2, and so on."
},
"prompt": {
"type": "string",
"description": "The complete, self-contained task for the subagent. It does not share this conversation's context, so include everything it needs."
@@ -2089,7 +2097,7 @@ Delegate a self-contained task to a subagent (a separate agent that works in its
Source: [`packages/subagent/tool-subagent/src/index.ts`](../packages/subagent/tool-subagent/src/index.ts)
The load-time `toolName` selects the delegation name (default `subagent`); `modelSelection` adds optional route fields. `modelDiscovery` defaults off and registers shared discovery on one instance per scope. Web and Desktop presets enable spawn discovery and route fields and leave `subagent_fork` route fields disabled. The Host settings service records authorization for each new top-level Session; child Sessions inherit it. Without a recorded policy, discovery and explicit selection permit only the current parent route. Every delegation returns a child id promptly; local children accept follow-ups, while external backends report their single execution automatically.
The load-time `toolName` selects the delegation name (default `subagent`); `modelSelection` adds optional route fields. `modelDiscovery` defaults off and registers shared discovery on one instance per scope. Web and Desktop presets enable spawn discovery and route fields and leave `subagent_fork` route fields disabled. The Host settings service records authorization for each new top-level Session; child Sessions inherit it. Without a recorded policy, discovery and explicit selection permit only the current parent route. Every delegation returns the child's name promptly; local children accept follow-ups, while external backends report their single execution automatically.
<a id="deepseek-aidsh-tool-subagent-control"></a>
@@ -2103,13 +2111,13 @@ Ask a subagent to stop its current work. This call returns without waiting for i
{
"type": "object",
"properties": {
"agent_id": {
"agent": {
"type": "string",
"description": "The id of an agent created under you: your direct child or a deeper descendant."
"description": "The name of an agent created under you: your direct child or a deeper descendant."
}
},
"required": [
"agent_id"
"agent"
]
}
```
@@ -2118,7 +2126,7 @@ Source: [`packages/subagent/tool-subagent-control/src/index.ts`](../packages/sub
### `list_agents`
List your entire subagent tree: the root agent and all reachable continuable descendants, including yourself. Rows carry ids, descriptions, and status; descendant rows carry parent ids and depth from the root. You can message any other agent in the subagent tree listed as running or inactive. running means it is working; inactive means no turn is executing; it does not indicate task completion, success, or failure. While you remain active, you will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.
List your entire subagent tree: the root agent and all reachable continuable descendants, including yourself. Rows carry names, descriptions, and status. A descendant's name is its path from the root, such as reviewer/checker. You can message any other agent in the subagent tree listed as running or inactive. running means it is working; inactive means no turn is executing; it does not indicate task completion, success, or failure. While you remain active, you will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.
```json
{
@@ -2137,9 +2145,9 @@ Send a message to an agent. A working agent receives it at its next step; an idl
{
"type": "object",
"properties": {
"agent_id": {
"agent": {
"type": "string",
"description": "The agent id of another member of your subagent tree, as shown by list_agents."
"description": "The name of another agent in your subagent tree, as shown by list_agents."
},
"message": {
"type": "string",
@@ -2147,7 +2155,7 @@ Send a message to an agent. A working agent receives it at its next step; an idl
}
},
"required": [
"agent_id",
"agent",
"message"
]
}
@@ -2332,7 +2340,7 @@ List shared tasks, including readiness, owner, revision, blockers, and write-sco
},
"owner": {
"type": "string",
"description": "Optional exact ownerId filter; use unowned for tasks without an owner."
"description": "Optional owner agent name filter; use unowned for tasks without an owner."
},
"ready": {
"type": "boolean",
@@ -2406,7 +2414,7 @@ Compare-and-set a shared task action using the latest revision from team_task_ge
},
"owner": {
"type": "string",
"description": "Agent id of the root or any continuable descendant for root-only reassign; omit to unassign."
"description": "Agent name of the root or any continuable descendant for root-only reassign; omit to unassign."
}
},
"required": [
+22 -14
View File
@@ -44,7 +44,7 @@
| `@deepseek-ai/dsh-tool-skill` | `skill` | `ctx.workingDirectory`、`ctx.tools`、`ctx.agents`、`ctx.skills` | `tool/call`、`tool/result`、`user/message replacement catalogs via agent.inject()` | - | - |
| `@deepseek-ai/dsh-tool-session-query` | `session_event_read`、`session_event_search`、`session_event_trace`、`session_search`、`session_trace` | `ctx.tools`、`ctx.systemPrompt`、`ctx.sessionQuery`、`a calling Agent for workspace authority` | `tool/call`、`tool/result` | - | 这 5 个只读工具会隐藏提供方游标,并根据不可变的调用 agent 会话为每个结果授权。该包需要选择启用;需要强制截止时间或限制行内输出的组合还会挂载通用超时或 spill 策略。 |
| `@deepseek-ai/dsh-experimental-tool-subagent-oar` | `subagent_oar` | `ctx.tools`, `ctx.subagents` | `tool/call`, `tool/result`, `parent subagent catalog and completion notices` | - | subagent_oar 工具在为外部提供方配置的别名之间选择。本目录展示 Codex 和 Claude Code 别名;每个部署自行选择提供方。原生模型和权限设置由所选提供方的配置决定。 |
| `@deepseek-ai/dsh-tool-subagent` | `list_subagent_models`、`subagent` | `ctx.tools`、`ctx.subagents`、`ctx.systemPrompt`、`ctx.sessionProjections`、`用于模型发现和所选路由校验的 ctx.llm` | `tool/call`、`tool/result`、`child session events through the chosen provider` | `subagent`、`subagent_fork` | 加载时的 `toolName` 选择委派名称(默认为 `subagent`);`modelSelection` 增加可选路由字段。`modelDiscovery` 默认关闭,每个作用域由一个实例注册共享发现工具。Web 与 Desktop preset 启用 spawn 发现和路由字段,并为 `subagent_fork` 保持路由字段关闭。Host 设置服务为每个新顶层 Session 记录授权;子 Session 继承该授权。没有已记录策略时,发现和显式选择只允许当前父级路由。每次委派都会立即返回子代理 id;本地子代理接受后续消息,外部后端自动汇报单次执行结果。 |
| `@deepseek-ai/dsh-tool-subagent` | `list_subagent_models`、`subagent` | `ctx.tools`、`ctx.subagents`、`ctx.systemPrompt`、`ctx.sessionProjections`、`用于模型发现和所选路由校验的 ctx.llm` | `tool/call`、`tool/result`、`child session events through the chosen provider` | `subagent`、`subagent_fork` | 加载时的 `toolName` 选择委派名称(默认为 `subagent`);`modelSelection` 增加可选路由字段。`modelDiscovery` 默认关闭,每个作用域由一个实例注册共享发现工具。Web 与 Desktop preset 启用 spawn 发现和路由字段,并为 `subagent_fork` 保持路由字段关闭。Host 设置服务为每个新顶层 Session 记录授权;子 Session 继承该授权。没有已记录策略时,发现和显式选择只允许当前父级路由。每次委派都会立即返回子代理的名称;本地子代理接受后续消息,外部后端自动汇报单次执行结果。 |
| `@deepseek-ai/dsh-tool-subagent-control` | `interrupt_agent`、`list_agents`、`send_message`、`wait_agent` | `ctx.tools`、`ctx.subagents`、`ctx.agents` | `tool/call`、`tool/result`、`child session events through ctx.subagents` | - | 共享控制工具发现并联系 subagent 树中的 Agent,中断有权控制的后代,并等待调用者收件箱中的输入。绑定提供方的 `tool-subagent` 实例提供委派工具。 |
| `@deepseek-ai/dsh-tool-jobs` | `job_kill`、`job_list`、`job_output` | `ctx.tools`、`ctx.jobs`、`ctx.systemPrompt` | `tool/call`、`tool/result`、`user/message via agent.inject() for background completion notices` | - | 与任务种类无关的后台任务控制器:后台 bash 命令与 PTY 发送 都通过相同的 3 个工具读取、列出和终止。加载该插件会挂接控制器,从而启用生产方的 `ctx.jobs.start()`。 |
| `@deepseek-ai/dsh-tool-agent-team` | `team_task_create`, `team_task_get`, `team_task_list`, `team_task_update` | `ctx.tools`, `ctx.systemPrompt`, `ctx.agentTeams`, `ctx.subagents`, `an exact live Team member Agent` | `tool/call`, `team/task`, `tool/result` | - | 四个任务板工具共享 subagent 树的根 Session。在根 Session 开启 Team 模式,会在标准 subagent 委派和控制工具之外增加任务板指导。标准 subagent 控制工具提供必需身份,不受 Team 模式影响。 |
@@ -2000,7 +2000,7 @@ lsp 工具将提供方选择和语言服务器子进程置于 ctx.lsp 之后,
### `subagent_oar`
将上下文完整的任务委派给已配置的外部 agent。每次调用选择一个运行时。subagent 在独立上下文中工作,无法看到当前对话。工具返回子级 id,后续完成通知包含其最终回答。subagent 不接受后续消息。并发启动相互独立的任务,并在其运行期间继续其他有用工作。只剩等待结果时结束当前轮次,不要轮询。
将上下文完整的任务委派给已配置的外部 agent。每次调用选择一个运行时。subagent 在独立上下文中工作,无法看到当前对话。工具返回子级的名称,后续完成通知包含其最终回答。subagent 不接受后续消息。并发启动相互独立的任务,并在其运行期间继续其他有用工作。只剩等待结果时结束当前轮次,不要轮询。
```json
{
@@ -2018,6 +2018,10 @@ lsp 工具将提供方选择和语言服务器子进程置于 ctx.lsp 之后,
"type": "string",
"description": "A short description of the delegated task, for display."
},
"name": {
"type": "string",
"description": "Optional short name for the subagent, unique among the subagents you create: lower-case letters, digits, and hyphens, starting with a letter, at most 32 characters. Omitted names default to agent-1, agent-2, and so on."
},
"prompt": {
"type": "string",
"description": "The complete, self-contained task. Include all context the external agent needs."
@@ -2067,7 +2071,7 @@ subagent_oar 工具在为外部提供方配置的别名之间选择。本目录
### `subagent`
将一项自包含任务委派给 subagent(在自身上下文中工作的独立 agent),用它卸载聚焦且独立的工作,例如研究、限定范围的实现或分析,以免消耗当前对话的上下文。subagent 会返回结果,但不会返回中间步骤。此工具启动独立管理的 subagent 并立即返回其 id。如果它结束时你仍在线,运行时会自动递送其完成通知。通知包含最终回答,除非子任务在结束前刚给你发过消息。你可以使用 `send_message` 在运行时引导它,或在结束后继续对话。
将一项自包含任务委派给 subagent(在自身上下文中工作的独立 agent),用它卸载聚焦且独立的工作,例如研究、限定范围的实现或分析,以免消耗当前对话的上下文。subagent 会返回结果,但不会返回中间步骤。此工具启动独立管理的 subagent 并立即返回其名称。如果它结束时你仍在线,运行时会自动递送其完成通知。通知包含最终回答,除非子任务在结束前刚给你发过消息。你可以使用 `send_message` 在运行时引导它,或在结束后继续对话。
```json
{
@@ -2081,6 +2085,10 @@ subagent_oar 工具在为外部提供方配置的别名之间选择。本目录
"type": "string",
"description": "A short (3-5 word) description of the delegated task, for display. Use the language of the user's current request."
},
"name": {
"type": "string",
"description": "Optional short name for the subagent, unique among the subagents you create: lower-case letters, digits, and hyphens, starting with a letter, at most 32 characters. Omitted names default to agent-1, agent-2, and so on."
},
"prompt": {
"type": "string",
"description": "The complete, self-contained task for the subagent. It does not share this conversation's context, so include everything it needs."
@@ -2095,7 +2103,7 @@ subagent_oar 工具在为外部提供方配置的别名之间选择。本目录
来源:[`packages/subagent/tool-subagent/src/index.ts`](../packages/subagent/tool-subagent/src/index.ts)
加载时的 `toolName` 选择委派名称(默认为 `subagent`);`modelSelection` 增加可选路由字段。`modelDiscovery` 默认关闭,每个作用域由一个实例注册共享发现工具。Web 与 Desktop preset 启用 spawn 发现和路由字段,并为 `subagent_fork` 保持路由字段关闭。Host 设置服务为每个新顶层 Session 记录授权;子 Session 继承该授权。没有已记录策略时,发现和显式选择只允许当前父级路由。每次委派都会立即返回子代理 id;本地子代理接受后续消息,外部后端自动汇报单次执行结果。
加载时的 `toolName` 选择委派名称(默认为 `subagent`);`modelSelection` 增加可选路由字段。`modelDiscovery` 默认关闭,每个作用域由一个实例注册共享发现工具。Web 与 Desktop preset 启用 spawn 发现和路由字段,并为 `subagent_fork` 保持路由字段关闭。Host 设置服务为每个新顶层 Session 记录授权;子 Session 继承该授权。没有已记录策略时,发现和显式选择只允许当前父级路由。每次委派都会立即返回子代理的名称;本地子代理接受后续消息,外部后端自动汇报单次执行结果。
<a id="deepseek-aidsh-tool-subagent-control"></a>
@@ -2103,19 +2111,19 @@ subagent_oar 工具在为外部提供方配置的别名之间选择。本目录
### `interrupt_agent`
根据 agent id 请求取消后台 agent 的当前轮次。目标可以是你的直接子级,也可以是在你下方创建的更深层 agent。对于本地 agent,只有当前轮次会停止:已经排队发给该 agent 的消息会一直搁置到后续的 send_message;它启动的 agent 会继续运行;该 agent 本身仍可接受后续操作。外部执行会永久停止,无法接收后续消息。停止请求被接受后,此调用立即返回,因此目标可能还会短暂运行;中断一个已经完成的 agent 是可接受的空操作。
请求 subagent 停止当前工作。此调用不等待其停止即返回。之后可以用 send_message 继续本地 subagent 的对话。外部执行会永久停止,无法接收后续消息。它启动的 subagent 会继续运行。
```json
{
"type": "object",
"properties": {
"agent_id": {
"agent": {
"type": "string",
"description": "The id of an agent created under you: your direct child or a deeper descendant."
"description": "The name of an agent created under you: your direct child or a deeper descendant."
}
},
"required": [
"agent_id"
"agent"
]
}
```
@@ -2124,7 +2132,7 @@ subagent_oar 工具在为外部提供方配置的别名之间选择。本目录
### `list_agents`
列出整棵 subagent 树:根代理和所有可达的可继续后代,包括调用方自身。行包含 id、描述和状态;后代行包含父级 id 和相对根的深度。可以向树中列为 running 或 inactive 的任意其他代理发送消息。running 表示正在工作;inactive 表示当前没有轮次在执行,不表示任务完成、成功或失败。自身仍在线时,直属子代理结束会收到通知,无需反复查询其状态。使用 send_message 继续对话。
列出整棵 subagent 树:根代理和所有可达的可继续后代,包括调用方自身。行包含名称、描述和状态。后代的名称是其相对根的路径,例如 reviewer/checker。可以向树中列为 running 或 inactive 的任意其他代理发送消息。running 表示正在工作;inactive 表示当前没有轮次在执行,不表示任务完成、成功或失败。自身仍在线时,直属子代理结束会收到通知,无需反复查询其状态。使用 send_message 继续对话。
```json
{
@@ -2143,9 +2151,9 @@ subagent_oar 工具在为外部提供方配置的别名之间选择。本目录
{
"type": "object",
"properties": {
"agent_id": {
"agent": {
"type": "string",
"description": "The agent id of another member of your subagent tree, as shown by list_agents."
"description": "The name of another agent in your subagent tree, as shown by list_agents."
},
"message": {
"type": "string",
@@ -2153,7 +2161,7 @@ subagent_oar 工具在为外部提供方配置的别名之间选择。本目录
}
},
"required": [
"agent_id",
"agent",
"message"
]
}
@@ -2338,7 +2346,7 @@ subagent_oar 工具在为外部提供方配置的别名之间选择。本目录
},
"owner": {
"type": "string",
"description": "Optional exact ownerId filter; use unowned for tasks without an owner."
"description": "Optional owner agent name filter; use unowned for tasks without an owner."
},
"ready": {
"type": "boolean",
@@ -2412,7 +2420,7 @@ subagent_oar 工具在为外部提供方配置的别名之间选择。本目录
},
"owner": {
"type": "string",
"description": "Agent id of the root or any continuable descendant for root-only reassign; omit to unassign."
"description": "Agent name of the root or any continuable descendant for root-only reassign; omit to unassign."
}
},
"required": [
@@ -0,0 +1,16 @@
# Bilingual-pair consistency record for guide.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write docs/upgrade-guide/v0.2.2-alpha.2/subagent-names/guide.md
/:
en: 9d10fcdf4af74152
zh: 1e932a7fe192df48
/subagent-tools-address-agents-by-name:
en: ae90ad0e4999f3e2
zh: 312d85156ab6c77d
/subagent-tools-address-agents-by-name/change:
en: a08e4e84f7e3a99c
zh: 29f4b80788a9cbc5
/subagent-tools-address-agents-by-name/migration:
en: 360eb6737d05896c
zh: 1689cd23cf2000bd
@@ -0,0 +1,29 @@
---
kind: upgrade-guide
description: "Subagent control and Team task tools address agents by name, list_agents rows change, and subagent catalogs write payload version 3."
---
# Subagent tools address agents by name
English | [中文](guide.zh.md)
## Change
Each new subagent has a name that is unique among its creator's children and recorded in the creator's `subagent/catalog` entry. The root is `lead`; a descendant's full name is its path from the root, such as `reviewer/checker`. The [subagent runtime](../../../../packages/subagent/subagent/README.md#agent-names) defines the name rule. Children created before upgrading keep their Session ids as names. These changes affect scripts, Code-mode (PTC) programs, SDK callers, and recorded transcripts that call or parse these tools, and code that reads catalogs or constructs activations:
- `send_message({ agent_id, message })` becomes `send_message({ agent, message })`, and `interrupt_agent({ agent_id })` becomes `interrupt_agent({ agent })`. `agent` accepts a name or a Session id. A call that still passes `agent_id` fails argument validation.
- `subagent`, `subagent_fork`, and `subagent_oar` accept an optional `name`. They return `started subagent <name>`, and their result is `{ kind: 'activation', subagentId, name }`.
- `list_agents` returns `{ name, status, description? }` rows instead of rows with `kind`, `id`, `label`, `parent`, `depth`, and `reason`. Unreadable branches report `corrupt`, `unsupported`, or `unavailable` as `status`. Text rows read `<name> [<status>] — <description>`.
- Team task results replace `ownerId` with `owner`, the owner's name. `team_task_list` and `team_task_update` accept a name as `owner`.
- Local and parent-delivered external creation write `subagent/catalog` payload version 3. Releases before this one reject catalogs that contain it, so they cannot open Sessions that create subagents after upgrading. See the [persistence acknowledgement](../../../persistence-changes/2026-11-02-subagent-catalog-names.md).
- `SubagentActivation` has a required `name` field, and `SubagentActivationSpec` accepts an optional `name`.
## Migration
1. In scripts, PTC programs, and SDK calls, rename the `agent_id` argument of `send_message` and `interrupt_agent` to `agent`. Pass the name that `list_agents` or the start receipt reports; a saved Session id still works.
2. Update parsers of `list_agents` output to read `name`, `status`, and `description`. Derive a member's creator from its name: the text before the last `/`, or `lead` for a name without `/`. Children created before upgrading appear under their Session ids.
3. Update Team task consumers to read `owner` instead of `ownerId`. Host code that calls `ctx.agentTeams` still reads `ownerId`.
4. Update recorded transcripts or fixtures that contain `agent_id` arguments, `started subagent <Session id>` receipts, identity runtime context text, or the earlier `list_agents` rows.
5. In code that constructs `SubagentActivation` values, such as test doubles, add `name`. Code that reads catalog rows can read the optional `name` field.
6. Upgrade every process that opens the same Session store before creating subagents. Older releases cannot open Sessions that contain catalog payload version 3.
7. To confirm the change, start a subagent with `name: "reviewer"` and check that the receipt reads `started subagent reviewer`, that `list_agents` lists `reviewer`, and that `send_message({ agent: "reviewer", message })` succeeds.
@@ -0,0 +1,29 @@
---
kind: upgrade-guide
description: "Subagent 控制工具和 Team 任务工具按名称寻址 agent,list_agents 行格式改变,subagent 目录写入第 3 版载荷。"
---
# Subagent 工具按名称寻址 agent
[English](guide.md) | 中文
## 变更
每个新 subagent(子智能体)都有一个名称,在其创建者的子级之间唯一,并记录在创建者的 `subagent/catalog` 条目中。根的名称为 `lead`;后代的完整名称是其相对根的路径,例如 `reviewer/checker`。[subagent 运行时](../../../../packages/subagent/subagent/README.zh.md#agent-names)定义名称规则。升级前创建的子级继续以 Session id 作为名称。以下变更影响调用或解析这些工具的脚本、Code 模式(PTC)程序、SDK 调用方和录制的 transcript(文本记录),以及读取目录或构造 activation 的代码:
- `send_message({ agent_id, message })` 改为 `send_message({ agent, message })`,`interrupt_agent({ agent_id })` 改为 `interrupt_agent({ agent })`。`agent` 接受名称或 Session id。仍传入 `agent_id` 的调用无法通过参数校验。
- `subagent`、`subagent_fork` 和 `subagent_oar` 接受可选的 `name`。它们返回 `started subagent <name>`,结果为 `{ kind: 'activation', subagentId, name }`。
- `list_agents` 返回 `{ name, status, description? }` 行,取代含 `kind`、`id`、`label`、`parent`、`depth` 和 `reason` 的行。不可读分支以 `status` 报告 `corrupt`、`unsupported` 或 `unavailable`。文本行格式为 `<name> [<status>] — <description>`。
- Team 任务结果以 `owner`(所有者名称)取代 `ownerId`。`team_task_list` 和 `team_task_update` 的 `owner` 接受名称。
- 本地创建和父级投递的外部创建写入第 3 版 `subagent/catalog` 载荷。本版本之前的发布会拒绝包含该载荷的目录,因此无法打开升级后创建过 subagent 的 Session。参见[持久化确认记录](../../../persistence-changes/2026-11-02-subagent-catalog-names.zh.md)。
- `SubagentActivation` 新增必需字段 `name`,`SubagentActivationSpec` 接受可选的 `name`。
## 迁移
1. 在脚本、PTC 程序和 SDK 调用中,将 `send_message` 和 `interrupt_agent` 的 `agent_id` 参数改名为 `agent`。传入 `list_agents` 或启动回执报告的名称;已保存的 Session id 仍可使用。
2. 更新 `list_agents` 输出的解析器,读取 `name`、`status` 和 `description`。从名称推导成员的创建者:最后一个 `/` 之前的文本;名称不含 `/` 时为 `lead`。升级前创建的子级以 Session id 列出。
3. 更新 Team 任务消费方,读取 `owner` 而非 `ownerId`。调用 `ctx.agentTeams` 的 host 代码仍读取 `ownerId`。
4. 更新包含 `agent_id` 参数、`started subagent <Session id>` 回执、身份运行时上下文文本或旧 `list_agents` 行的录制 transcript 或 fixture。
5. 在构造 `SubagentActivation` 值的代码(例如测试替身)中添加 `name`。读取目录行的代码可读取可选的 `name` 字段。
6. 在创建 subagent 之前,升级所有打开同一 Session 存储的进程。旧版本无法打开包含第 3 版目录载荷的 Session。
7. 验证迁移:以 `name: "reviewer"` 启动一个 subagent,确认回执为 `started subagent reviewer`,`list_agents` 列出 `reviewer`,且 `send_message({ agent: "reviewer", message })` 成功。
+2 -2
View File
@@ -21,8 +21,8 @@
en: 0f971f7ac7c09139
zh: ceb866da681c709c
/deepseek-ai-dsh-base/use-this-package/what-you-get:
en: 94430c891006526d
zh: 94ba771960ec6f71
en: ab2fb279cdd726c5
zh: ae84c61bddc00ddf
/deepseek-ai-dsh-base/use-this-package/shell-tools-per-platform:
en: 2dce12f82d6ee955
zh: d4599eb899a3cd88
+1 -1
View File
@@ -49,7 +49,7 @@ Run `dsh --profile my-profile "your task"` and you get a working agent with mode
Out of the box, every profile built on this core provides: a DeepSeek model connection (the provider and model are configurable, and you can enable extra providers from your settings), the full tool set — file editing, shell commands, web search, HTTP(S) fetch, subagents, task and goal tracking — durable sessions that survive restarts, and the default permission policy that confines file writes to your workspace and asks before risky actions. Web fetch runs without per-call approval and can reach loopback and private-network hosts. Feedback stays in the Session log. [OTel session upload](../../session/session-telemetry-otel/README.md) defaults to `FEEDBACK_ONLY` for all users, including `deepseek-official`: new text feedback, message ratings, edits, and withdrawals release the complete canonical prefix through that event, including context. Later records wait for the next explicit feedback; sending an authorized batch needs no further interaction or model call. `DISABLED` prevents OTel capture. The default-on [DeepSeek session-log contributor](../../session/session-log-deepseek/README.md) remains a separate request path.
Both `subagent` and `subagent_fork` create managed children and return a child id immediately. Use `send_message` to steer active children or continue their conversations after completion. [Delegation-tool behavior](../../subagent/tool-subagent/README.md) describes result delivery and backend capabilities.
Both `subagent` and `subagent_fork` create managed children and return the child's name immediately. Use `send_message` to steer active children or continue their conversations after completion. [Delegation-tool behavior](../../subagent/tool-subagent/README.md) describes result delivery and backend capabilities.
The bundle also mounts [Agent Teams](../../team/agent-team/README.md) and its task tools. Team mode defaults off per root Session; the root conversation’s **Use Agent Teams** menu switch enables collaboration for that tree without changing the profile.
+1 -1
View File
@@ -49,7 +49,7 @@ kind: "package-bundle"
开箱即用,基于本核心构建的每个 profile 都提供:DeepSeek 模型连接(提供方与模型可配置,你还可以在设置中启用额外提供方)、完整工具集——文件编辑、shell 命令、web 搜索、HTTP(S) 抓取、subagent、任务与目标跟踪——可跨重启存活的持久会话,以及默认权限策略:把文件写入限制在工作区内,危险操作前征询许可。Web 抓取无需逐次审批,并且可以访问 loopback 与内网主机。反馈保存在会话日志中。[OTel 会话上传](../../session/session-telemetry-otel/README.zh.md)对所有用户默认使用 `FEEDBACK_ONLY`,包括 `deepseek-official`:新的文本反馈、消息评分、编辑与撤回会释放截至该事件的完整规范会话日志前缀,包含上下文。后续记录等待下一次显式反馈;发送已授权批次无需进一步交互或模型调用。`DISABLED` 阻止 OTel 捕获。默认开启的 [DeepSeek 会话日志贡献器](../../session/session-log-deepseek/README.zh.md)仍是独立的请求路径。
`subagent` 与 `subagent_fork` 都创建受管理的子任务,并立即返回 child id。使用 `send_message` 可引导活跃子任务,或在完成后继续其对话。[委派工具行为](../../subagent/tool-subagent/README.zh.md)说明了结果交付和后端能力。
`subagent` 与 `subagent_fork` 都创建受管理的子任务,并立即返回子任务名称。使用 `send_message` 可引导活跃子任务,或在完成后继续其对话。[委派工具行为](../../subagent/tool-subagent/README.zh.md)说明了结果交付和后端能力。
此 bundle 还挂载 [Agent Teams](../../team/agent-team/README.zh.md) 及其任务工具。每个根 Session 的 Team 模式默认关闭;根会话菜单中的**使用智能体团队**开关为当前树开启协作,无需修改 profile。
@@ -18,8 +18,8 @@
en: d502ab38773eef34
zh: e1f9c4edbc74c38f
/deepseek-ai-dsh-client-ui-agent-team/use-this-package/inspect-the-task-board:
en: 7e88fb00a3abd230
zh: 08efcf80afecb0c0
en: d3d67c28bd2379ff
zh: f0057ab13a554a25
/deepseek-ai-dsh-client-ui-agent-team/understand-the-implementation:
en: 9b0b6a8505a9ebbf
zh: beb5d89f80463b3e
+1 -1
View File
@@ -37,7 +37,7 @@ The [Web bundle](../../bundle/web-app/README.md) loads this package by default.
Ready pending tasks use idle, blocked pending tasks use warning, in-progress tasks use ongoing, and completed tasks use done.
The noncollapsible Shared tasks header uses a Checklist icon and completed, in-progress, and pending counts, with zero counts omitted and wording and separators matching the input task list. Compact read-only rows show the subject, status, and a chevron, with 13px primary titles and hover geometry aligned to subagent rows; expanded details use 12px text. Task rows use 7px vertical padding, 6px horizontal padding, and 7px gaps to align their clickable content with subagent rows. All task details start closed; opening one closes the previous task. Details show only the full description when present, followed by a single-line owner label and Session id in the same color with a 4px gap. Long owner ids are ellipsized and reveal their full text in a tooltip only when clipped. Task-text and owner tooltips appear after 500ms of hover. Every owner is identified by its Session id. The shared menu is 360px wide with 6px outer padding, constrained to fit the viewport. Shared tasks have a 4px top margin rather than a divider. Both section headers keep a 7px icon/title gap and an additional 4px before their counts. Only the menu scrolls; task lists and details have no nested scrolling. Agents mutate tasks through tools; the panel provides no mutation controls. A projection failure appears separately above any retained tasks and remains visible when no tasks exist.
The noncollapsible Shared tasks header uses a Checklist icon and completed, in-progress, and pending counts, with zero counts omitted and wording and separators matching the input task list. Compact read-only rows show the subject, status, and a chevron, with 13px primary titles and hover geometry aligned to subagent rows; expanded details use 12px text. Task rows use 7px vertical padding, 6px horizontal padding, and 7px gaps to align their clickable content with subagent rows. All task details start closed; opening one closes the previous task. Details show only the full description when present, followed by a single-line owner label and owner name in the same color with a 4px gap. Long owner names are ellipsized and reveal their full text in a tooltip only when clipped. Task-text and owner tooltips appear after 500ms of hover. Owners use the names agent tools report: `lead` for the root conversation, and for a descendant the names from loaded subagent catalogs joined by `/` below the root, such as `reviewer/checker`. An owner keeps its Session id when its catalog path is not loaded or includes an entry recorded without a name. The shared menu is 360px wide with 6px outer padding, constrained to fit the viewport. Shared tasks have a 4px top margin rather than a divider. Both section headers keep a 7px icon/title gap and an additional 4px before their counts. Only the menu scrolls; task lists and details have no nested scrolling. Agents mutate tasks through tools; the panel provides no mutation controls. A projection failure appears separately above any retained tasks and remains visible when no tasks exist.
-----
+1 -1
View File
@@ -37,7 +37,7 @@ Chat 隐藏历史 `/team on` 和 `/team off` 记录中尚未完成或执行成
可开始的 pending 任务使用 idle 灰点,被依赖阻塞的 pending 任务使用 warning 橙点,in-progress 任务使用 ongoing loading,completed 任务使用 done 绿点。
不可折叠的“共享任务”标题使用 Checklist 图标,并显示已完成、进行中和待处理数量;省略零值,文案和分隔符与输入区任务列表一致。紧凑只读行显示主题、状态和展开箭头,13px 主标题与悬停区域对齐子智能体行;展开详情使用 12px 文字。任务行使用 7px 垂直内边距、6px 水平内边距和 7px 间距,使可点击内容与 subagent 行对齐。所有任务详情初始关闭,打开一项会关闭上一项。详情仅显示完整描述(如有),下方以单行显示负责人标签和 Session id,两者使用相同颜色,间距为 4px。过长的负责人 id以省略号截断,仅在被截断时通过工具提示显示完整内容。任务文字和负责人的工具提示在悬停 500ms 后显示。每个负责人均通过其 Session id 标识。共享菜单宽度为 360px,外层内边距为 6px,并受视口可用宽度约束。共享任务上方保留 4px 外边距,不显示分隔线。两个区域标题均保留 7px 图标与文字间距,并在统计数量前额外留出 4px。仅菜单本身滚动,任务列表与详情不单独滚动。Agent 通过工具修改任务;面板不提供修改控件。投影失败以独立警告显示在保留的任务上方,即使没有任务也保持可见。
不可折叠的“共享任务”标题使用 Checklist 图标,并显示已完成、进行中和待处理数量;省略零值,文案和分隔符与输入区任务列表一致。紧凑只读行显示主题、状态和展开箭头,13px 主标题与悬停区域对齐子智能体行;展开详情使用 12px 文字。任务行使用 7px 垂直内边距、6px 水平内边距和 7px 间距,使可点击内容与 subagent 行对齐。所有任务详情初始关闭,打开一项会关闭上一项。详情仅显示完整描述(如有),下方以单行显示负责人标签和负责人名称,两者使用相同颜色,间距为 4px。过长的负责人名称以省略号截断,仅在被截断时通过工具提示显示完整内容。任务文字和负责人的工具提示在悬停 500ms 后显示。负责人使用智能体工具报告的名称:根会话为 `lead`,后代为已加载 subagent 目录中根以下各级名称以 `/` 连接的路径,例如 `reviewer/checker`。目录路径未加载或包含没有名称的历史目录项时,负责人保留其 Session id。共享菜单宽度为 360px,外层内边距为 6px,并受视口可用宽度约束。共享任务上方保留 4px 外边距,不显示分隔线。两个区域标题均保留 7px 图标与文字间距,并在统计数量前额外留出 4px。仅菜单本身滚动,任务列表与详情不单独滚动。Agent 通过工具修改任务;面板不提供修改控件。投影失败以独立警告显示在保留的任务上方,即使没有任务也保持可见。
-----
@@ -10,6 +10,7 @@ import type { PropsLocale, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots
import type {} from '@deepseek-ai/dsh-client-ui-subagent/client'
import type {} from '@deepseek-ai/dsh-client-ui-conversation/client'
import { NS, type TeamKey } from './locales.ts'
import { ownerName } from './owner-name.ts'
import css from './TeamBoard.module.css'
/** Full props of the task board below the shared subagent catalog. */
@@ -37,13 +38,16 @@ function progressLabel(tasks: readonly VisibleTask[], t: TeamBoardProps['t']): s
].join('\u2002·\u2002')
}
function TaskRow({ task, rootId, expanded, onToggle, t }: Pick<TeamBoardProps, 't'> & {
function TaskRow({ task, rootId, expanded, onToggle, useSessions, t }: Pick<TeamBoardProps, 'useSessions' | 't'> & {
task: VisibleTask
rootId: SessionId
expanded: boolean
onToggle: () => void
}) {
const owner = task.ownerId ?? t('unowned')
const named = useSessions(state => !expanded || task.ownerId === undefined
? undefined
: ownerName(state.projectionsBySession, rootId, task.ownerId))
const owner = named ?? t('unowned')
const blocked = task.status === 'pending' && !task.ready
const detailsId = `team-task-${rootId}-${task.id}`
return (
@@ -103,6 +107,7 @@ export function TeamBoard({ sessionId, useProjection, useSessions, t }: TeamBoar
key={task.id} task={task} rootId={sessionId}
expanded={expandedTaskId === task.id}
onToggle={() => { setExpandedTaskId(current => current === task.id ? null : task.id) }}
useSessions={useSessions}
t={t}
/>
))}
@@ -0,0 +1,34 @@
/** Model-facing agent name of a Team task owner, derived from loaded subagent catalogs. */
import type { SessionId } from '@deepseek-ai/dsh-session/types'
import type { SessionListState } from '@deepseek-ai/dsh-api-session-controller/client'
/** The root agent's fixed name, equal to `ROOT_AGENT_NAME` of the Host-only `@deepseek-ai/dsh-subagent` entry. */
const ROOT_AGENT_NAME = 'lead'
/**
* Name a task owner as agent tools name it.
* @param projections - Loaded projections by Session; each `subagentCatalog` lists that Session's direct children.
* @param rootId - Root Session of the subagent tree that owns the task board.
* @param ownerId - Session ID recorded as the task owner.
* @returns `lead` for the root; the slash-separated catalog names below the root, such as
* `reviewer/checker`, when every link to the owner is loaded and named; otherwise `ownerId`.
*/
export function ownerName(
projections: SessionListState['projectionsBySession'], rootId: SessionId, ownerId: SessionId,
): string {
if (ownerId === rootId) return ROOT_AGENT_NAME
// A Session listed by more than one loaded catalog is searched once, which also ends a cyclic listing.
const visited = new Set<SessionId>([rootId])
const search = (parentId: SessionId): string | undefined => {
for (const entry of projections[parentId]?.values.subagentCatalog ?? []) {
const name = entry.mode === 'continuable' || entry.mode === 'external' ? entry.name : undefined
if (name === undefined || visited.has(entry.id)) continue
if (entry.id === ownerId) return name
visited.add(entry.id)
const below = search(entry.id)
if (below !== undefined) return `${name}/${below}`
}
return undefined
}
return search(rootId) ?? ownerId
}
@@ -0,0 +1,61 @@
/** Team task owners use the agent names that agent tools report. */
import { describe, expect, it } from 'vitest'
import type { SessionId } from '@deepseek-ai/dsh-session/types'
import type { SessionListState, SessionProjectionMap } from '@deepseek-ai/dsh-api-session-controller/client'
import { ownerName } from '../src/client/owner-name.ts'
type Projections = SessionListState['projectionsBySession']
type SubagentCatalogEntry = SessionProjectionMap['subagentCatalog'][number]
const ROOT = 'root-id' as SessionId
const REVIEWER = 'reviewer-id' as SessionId
const CHECKER = 'checker-id' as SessionId
const HISTORICAL = 'historical-id' as SessionId
function catalogs(entries: Readonly<Record<SessionId, readonly SubagentCatalogEntry[]>>): Projections {
return Object.fromEntries(Object.entries(entries).map(([id, subagentCatalog]) => [
id, { state: 'ready', error: null, values: { subagentCatalog: [...subagentCatalog] } },
]))
}
const tree = catalogs({
[ROOT]: [
{ id: HISTORICAL, createdAt: 1, mode: 'continuable', label: 'Historical' },
{ id: 'one-shot-id' as SessionId, createdAt: 2, mode: 'one-shot' },
{ id: 'external-id' as SessionId, createdAt: 3, mode: 'external', name: 'outside' },
{ id: REVIEWER, createdAt: 4, mode: 'continuable', label: 'Review', name: 'reviewer' },
],
[REVIEWER]: [{ id: CHECKER, createdAt: 5, mode: 'continuable', label: 'Check', name: 'checker' }],
[HISTORICAL]: [{ id: 'below-historical-id' as SessionId, createdAt: 6, mode: 'continuable', label: 'Below', name: 'below' }],
})
describe('ownerName', () => {
it('names the root lead and descendants by their path below the root', () => {
expect(ownerName(tree, ROOT, ROOT)).toBe('lead')
expect(ownerName({}, ROOT, ROOT)).toBe('lead')
expect(ownerName(tree, ROOT, REVIEWER)).toBe('reviewer')
expect(ownerName(tree, ROOT, CHECKER)).toBe('reviewer/checker')
expect(ownerName(tree, ROOT, 'external-id' as SessionId)).toBe('outside')
})
it('keeps the Session ID when a link is unnamed, unloaded, or absent', () => {
expect(ownerName(tree, ROOT, HISTORICAL)).toBe(HISTORICAL)
expect(ownerName(tree, ROOT, 'below-historical-id' as SessionId)).toBe('below-historical-id')
expect(ownerName(tree, ROOT, 'one-shot-id' as SessionId)).toBe('one-shot-id')
expect(ownerName({ [ROOT]: tree[ROOT]! }, ROOT, CHECKER)).toBe(CHECKER)
expect(ownerName({ ...tree, [ROOT]: { state: 'loading', error: null, values: {} } }, ROOT, REVIEWER)).toBe(REVIEWER)
expect(ownerName(tree, ROOT, 'unknown-id' as SessionId)).toBe('unknown-id')
})
it('searches each Session once when catalogs list a member again', () => {
const repeated = catalogs({
[ROOT]: [
{ id: REVIEWER, createdAt: 1, mode: 'continuable', label: 'Review', name: 'reviewer' },
{ id: REVIEWER, createdAt: 2, mode: 'continuable', label: 'Review', name: 'again' },
],
[REVIEWER]: [{ id: ROOT, createdAt: 3, mode: 'continuable', label: 'Root', name: 'cycle' }],
})
expect(ownerName(repeated, ROOT, REVIEWER)).toBe('reviewer')
expect(ownerName(repeated, ROOT, CHECKER)).toBe(CHECKER)
})
})
@@ -141,8 +141,8 @@ describe('TeamBoard', () => {
const details = document.getElementById(first.getAttribute('aria-controls')!)!
const owner = details.querySelector('[data-team-task-owner]')!
expect(owner.tagName).toBe('P')
expect(owner.textContent).toBe(`${zh.owner}: ${SESSION}`)
expect(ownerValue()).toBe(SESSION)
expect(owner.textContent).toBe(`${zh.owner}: lead`)
expect(ownerValue()).toBe('lead')
const paragraphs = details.querySelectorAll('p')
expect(paragraphs).toHaveLength(2)
expect(paragraphs[0]?.textContent).toBe(description)
@@ -179,7 +179,7 @@ describe('TeamBoard', () => {
expect(row('Completed second').querySelector('[data-state="done"]')).toBeTruthy()
fireEvent.click(row('Completed second'))
expect(row('Completed second').getAttribute('aria-expanded')).toBe('true')
expect(ownerValue()).toBe(SESSION)
expect(ownerValue()).toBe('lead')
expect(screen.getByText(task.description)).toBeTruthy()
})
@@ -212,30 +212,44 @@ describe('TeamBoard', () => {
fireEvent.click(row())
expect(within(row()).getByRole('img', { name: zh['status.pending'] })).toBeTruthy()
expect(row().querySelector('[data-state="idle"]')).toBeTruthy()
expect(ownerValue()).toBe(SESSION)
expect(ownerValue()).toBe('lead')
expect(document.querySelector('[data-team-task-details]')?.children).toHaveLength(1)
expect(document.querySelector('[data-team-task-details] p:not([data-team-task-owner])')).toBeNull()
})
it('uses the owner id independently of catalog descriptions and Session titles', () => {
it('names the owner by its catalog path from the root, independently of descriptions and Session titles', () => {
const b = bench({
byId: { [SESSION]: summary(SESSION), [NESTED]: { ...summary(NESTED, 'Session title'), parentId: WORKER } },
projections: {
[SESSION]: { state: 'ready', error: null, values: {
agentTeam: { ...team, tasks: [{ ...task, ownerId: NESTED }] },
subagentCatalog: [{ id: WORKER, createdAt: 0, mode: 'continuable', label: 'Worker responsibility', name: 'worker' }],
} },
[WORKER]: { state: 'ready', error: null, values: {
subagentCatalog: [{ id: NESTED, createdAt: 0, mode: 'continuable', label: 'Catalog responsibility' }],
subagentCatalog: [{ id: NESTED, createdAt: 0, mode: 'continuable', label: 'Catalog responsibility', name: 'checker' }],
} },
},
})
render(<TeamBoard {...b.props} />)
fireEvent.click(row())
expect(ownerValue()).toBe(NESTED)
expect(ownerValue()).toBe('worker/checker')
setProjectionSnapshot(b.sessions, WORKER, { state: 'ready', error: null, values: {} })
act(() => { b.sessions.update((draft) => { draft.byId[NESTED] = { ...summary(NESTED), displayTitle: 'Display title' } }) })
expect(ownerValue()).toBe(NESTED)
setProjection(b.sessions, SESSION, { ...team, tasks: [{ ...task, ownerId: WORKER }] })
setProjectionSnapshot(b.sessions, SESSION, { state: 'ready', error: null, values: {
agentTeam: { ...team, tasks: [{ ...task, ownerId: WORKER }] },
subagentCatalog: [{ id: WORKER, createdAt: 0, mode: 'continuable', label: 'Worker responsibility', name: 'worker' }],
} })
expect(ownerValue()).toBe('worker')
})
it('uses the owner Session ID when its catalog entry has no name', () => {
const b = bench({ projections: { [SESSION]: { state: 'ready', error: null, values: {
agentTeam: { ...team, tasks: [{ ...task, ownerId: WORKER }] },
subagentCatalog: [{ id: WORKER, createdAt: 0, mode: 'continuable', label: 'Historical worker' }],
} } } })
render(<TeamBoard {...b.props} />)
fireEvent.click(row())
expect(ownerValue()).toBe(WORKER)
})
@@ -344,8 +358,8 @@ describe('TeamBoard', () => {
render(<TeamBoard {...b.props} t={makeTranslate(en)} />)
expect(screen.getByRole('heading').textContent).toBe(`${en.tasks}${makeTranslate(en)('progress.active', { count: 1 })}`)
fireEvent.click(row())
expect(ownerValue()).toBe(SESSION)
expect(document.querySelector('[data-team-task-owner]')?.textContent).toBe(`${en.owner}: ${SESSION}`)
expect(ownerValue()).toBe('lead')
expect(document.querySelector('[data-team-task-owner]')?.textContent).toBe(`${en.owner}: lead`)
expect(screen.queryByText(TASK_1)).toBeNull()
expect(screen.queryByText('Show more')).toBeNull()
expect(screen.queryByText('Show less')).toBeNull()
+4 -4
View File
@@ -15,11 +15,11 @@
en: d152484eb41ac6b4
zh: 09388d293f9be9cb
/deepseek-ai-dsh-client-ui-subagent/use-this-package:
en: d00a6c7ffced5dc7
zh: 616220bbdfdc70a6
en: cb12cbb59ca353f5
zh: d5f370d69f431513
/deepseek-ai-dsh-client-ui-subagent/use-this-package/browsing-the-tree:
en: 4ecdca030e42109d
zh: 406b08590ba8df83
en: 5ea28139189887e9
zh: f5a51f041c39b0fa
/deepseek-ai-dsh-client-ui-subagent/use-this-package/continuing-a-conversation:
en: e4ec261d3b122eb5
zh: 320bb2efc93dccdc
+2 -2
View File
@@ -25,7 +25,7 @@ Browse local subagent conversations and external tasks from the parent header. L
<a id="use-this-package"></a>
## Use this package
The session header uses the session title for ordinary breadcrumbs. Subagent breadcrumbs prefer the original creation description (`entry.label`), then the Session id. Ordinary and subagent breadcrumb titles both use 14px text with a 20px line height. When the session's direct catalog has entries or a read has failed, the descendant-count trigger renders after the preset label in the header actions band, with no breadcrumb separator. An absent or empty catalog hides the count trigger unless the root Session has an enabled, available Team board with shared tasks or a task-record error. Enabling Team mode alone does not show an empty entry. The trigger opens that direct catalog, uses the total count as its accessible name and the running count as its accessible description, and loads nested catalogs only when their rows expand. Select a local child at any depth to open that child's conversation with its exact `{parentSessionId, childSessionId, mode}` address, or use a noncurrent local row's trailing arrow to open the same address in the right Sidebar, preferring a separate pane when room permits.
The session header uses the session title for ordinary breadcrumbs. Subagent breadcrumbs prefer the original creation description (`entry.label`), then the agent name (`entry.name`), then the Session id. Ordinary and subagent breadcrumb titles both use 14px text with a 20px line height. When the session's direct catalog has entries or a read has failed, the descendant-count trigger renders after the preset label in the header actions band, with no breadcrumb separator. An absent or empty catalog hides the count trigger unless the root Session has an enabled, available Team board with shared tasks or a task-record error. Enabling Team mode alone does not show an empty entry. The trigger opens that direct catalog, uses the total count as its accessible name and the running count as its accessible description, and loads nested catalogs only when their rows expand. Select a local child at any depth to open that child's conversation with its exact `{parentSessionId, childSessionId, mode}` address, or use a noncurrent local row's trailing arrow to open the same address in the right Sidebar, preferring a separate pane when room permits.
This package registers the `dsh-resource://subagentchat/session/<child>?parent=<parent>&mode=<mode>` resource and builtin Sidebar tab type. The resource retains the child `SessionReference` directly from its address without refreshing the parent catalog, and releases the reference when the tab record closes. The tab renders the shared `conversation.content` Factory through `sidebar.chat.conversation`, fixes the local View to Chat, and omits the main Conversation header and width controls.
@@ -39,7 +39,7 @@ The wide root count trigger shows a 14px Users icon in its 14px slot when no chi
Count, owner, and sidebar-action tooltips appear after 500ms of hover. Hovering a text-visible trigger opens its catalog after 150ms; leaving both trigger and catalog closes it after 120ms. Clicking the descendant-count trigger opens and pins its catalog, or closes an already pinned catalog. The icon-only count trigger does not open on hover, including when a pending hover crosses into the narrow layout. Clicking toggles its pinned menu; ArrowDown opens and pins the menu and focuses its first row. Outside click or Escape dismisses a pinned menu. Clicking moves focus into the panel, where ArrowDown/Home enters the first tree row and ArrowUp/End enters the last; Escape returns focus when it was inside. Breadcrumb-title clicks navigate to the corresponding conversation.
Rows show the creation description, or an available Session title, above the Session id. Without either description, the row shows only its Session id. Local rows use compact 4px vertical padding; their clickable content uses 6px horizontal padding and 7px gaps, aligned with shared-task rows while retaining the tree's left offset. A decorative trailing check marks the current conversation and is not an action; other local rows retain the sidebar arrow. Primary titles use 13px text and secondary ids use 12px. All rows wrap descriptions and ids in full, including on touch screens. Running uses the shared ongoing loader, an inactive child whose latest closed turn completed normally uses the shared success dot, and other inactive children use the shared idle dot. Every row reserves the same 14px status column, centering smaller dots so titles align with the loader state. The text-visible header trigger vertically centers its activity glyph and count with a 4px gap. The trailing column stacks total durable provider usage above active-turn duration. Keyboard navigation works with ArrowRight/ArrowLeft to expand and collapse branches and ArrowUp/ArrowDown, Home, End, and Escape to navigate or close the tree. An unlabeled one-shot row falls back to its session id. A row is a known leaf only after its own catalog loads empty.
Rows show the creation description, or an available Session title, above the agent name, which is unique among its siblings. Entries recorded without a name show the Session id in its place. Without either description, the row shows only the name or Session id. Navigation, row identity, and Sidebar addresses always use the Session id. Local rows use compact 4px vertical padding; their clickable content uses 6px horizontal padding and 7px gaps, aligned with shared-task rows while retaining the tree's left offset. A decorative trailing check marks the current conversation and is not an action; other local rows retain the sidebar arrow. Primary titles use 13px text and secondary names use 12px. All rows wrap descriptions and names in full, including on touch screens. Running uses the shared ongoing loader, an inactive child whose latest closed turn completed normally uses the shared success dot, and other inactive children use the shared idle dot. Every row reserves the same 14px status column, centering smaller dots so titles align with the loader state. The text-visible header trigger vertically centers its activity glyph and count with a 4px gap. The trailing column stacks total durable provider usage above active-turn duration. Keyboard navigation works with ArrowRight/ArrowLeft to expand and collapse branches and ArrowUp/ArrowDown, Home, End, and Escape to navigate or close the tree. An unlabeled one-shot row falls back to its session id. A row is a known leaf only after its own catalog loads empty.
### Continuing a conversation
+2 -2
View File
@@ -25,7 +25,7 @@ kind: "package-reference"
<a id="use-this-package"></a>
## 使用本包
会话页头的普通面包屑使用会话标题。subagent 面包屑优先使用创建时的原始描述(`entry.label`),缺少时回退到 Session id。普通与 subagent 面包屑标题均使用 14px 文字和 20px 行高。当会话的直接目录有子项或读取失败时,后代数量触发器渲染在页头操作区中预设标签之后,不带任何面包屑分隔符。目录缺席或为空时隐藏数量触发器,除非根 Session 已开启且可用的 Team 任务板有共享任务或任务记录错误。仅开启 Team 模式不会显示空入口。触发器打开该直接目录,以总数作为无障碍名称、运行数作为无障碍描述,并且只在行展开时加载嵌套目录。选择任意深度,即可用该子会话的确切 `{parentSessionId, childSessionId, mode}` 地址打开其对话;也可以使用非当前本地行的行尾箭头在右侧 Sidebar 打开同一地址,并在空间允许时优先使用独立分栏。
会话页头的普通面包屑使用会话标题。subagent 面包屑优先使用创建时的原始描述(`entry.label`),其次使用智能体名称(`entry.name`),最后回退到 Session id。普通与 subagent 面包屑标题均使用 14px 文字和 20px 行高。当会话的直接目录有子项或读取失败时,后代数量触发器渲染在页头操作区中预设标签之后,不带任何面包屑分隔符。目录缺席或为空时隐藏数量触发器,除非根 Session 已开启且可用的 Team 任务板有共享任务或任务记录错误。仅开启 Team 模式不会显示空入口。触发器打开该直接目录,以总数作为无障碍名称、运行数作为无障碍描述,并且只在行展开时加载嵌套目录。选择任意深度,即可用该子会话的确切 `{parentSessionId, childSessionId, mode}` 地址打开其对话;也可以使用非当前本地行的行尾箭头在右侧 Sidebar 打开同一地址,并在空间允许时优先使用独立分栏。
本包注册 `dsh-resource://subagentchat/session/<child>?parent=<parent>&mode=<mode>` 资源与 builtin Sidebar tab 类型。资源直接根据地址保留 child 的 `SessionReference`,不刷新 parent 目录,并在 tab 记录关闭时释放 reference。tab 通过 `sidebar.chat.conversation` 渲染共享 `conversation.content` Factory,把局部 View 固定为 Chat,并省略主 Conversation 的 Header 与宽度控制。
@@ -39,7 +39,7 @@ kind: "package-reference"
数量、负责人及侧边栏操作的工具提示在悬停 500ms 后显示。悬停文字可见的触发器 150ms 后打开目录;指针离开触发器和目录后,经过 120ms 关闭。点击后代数量触发器会打开并固定目录,或关闭已固定的目录。纯图标数量触发器不会因悬停而打开,包括等待悬停打开期间切换到窄布局的情况。点击可切换固定菜单的开关状态;ArrowDown 会打开并固定菜单,并将焦点移至首行。点击外部或按 Escape 可关闭已固定的菜单。点击会将焦点移入面板,此时 ArrowDown/Home 进入首个树行,ArrowUp/End 进入最后一个树行;Escape 在焦点原本位于面板内时将其送回。点击面包屑标题会导航至对应会话。
目录行在 Session id 上方显示创建描述,缺少创建描述时使用可用的 Session title。两者均缺少时,该行仅显示 Session id。本地行使用紧凑的 4px 垂直内边距;可点击内容使用 6px 水平内边距和 7px 间距,与共享任务行对齐,同时保留树的左侧偏移。当前对话在行尾显示装饰性对勾,该对勾不是操作控件;其他本地行保留侧边栏箭头。主标题使用 13px 文字,次级 id 使用 12px。所有行均将描述与 id 换行完整展示,包括在触屏上。running 使用共享 ongoing loading,最近一个已结束轮次正常完成的 inactive child 使用共享 success 绿点,其他 inactive child 使用共享 idle 灰点。每行都为状态图标预留相同的 14px 列宽,并将较小的圆点居中,使 title 与 loading 状态对齐。文字可见的页头触发器会垂直居中活动图标与数量,并保留 4px 水平间距。尾随列在上行显示提供方的持久化 token 用量总计,在下行显示活跃轮次耗时。键盘导航:ArrowRight/ArrowLeft 展开和折叠分支;ArrowUp/ArrowDown、Home、End 与 Escape 用于导航或关闭树。没有 label 的 one-shot 行回退到其会话 id。只有一行自身的目录加载为空后,它才是已知叶子。
目录行在智能体名称上方显示创建描述,缺少创建描述时使用可用的 Session title;名称在同级子智能体中唯一。没有名称的历史目录项在相同位置显示 Session id。两者均缺少时,该行仅显示名称或 Session id。导航、行身份与 Sidebar 地址始终使用 Session id。本地行使用紧凑的 4px 垂直内边距;可点击内容使用 6px 水平内边距和 7px 间距,与共享任务行对齐,同时保留树的左侧偏移。当前对话在行尾显示装饰性对勾,该对勾不是操作控件;其他本地行保留侧边栏箭头。主标题使用 13px 文字,次级名称使用 12px。所有行均将描述与名称换行完整展示,包括在触屏上。running 使用共享 ongoing loading,最近一个已结束轮次正常完成的 inactive child 使用共享 success 绿点,其他 inactive child 使用共享 idle 灰点。每行都为状态图标预留相同的 14px 列宽,并将较小的圆点居中,使 title 与 loading 状态对齐。文字可见的页头触发器会垂直居中活动图标与数量,并保留 4px 水平间距。尾随列在上行显示提供方的持久化 token 用量总计,在下行显示活跃轮次耗时。键盘导航:ArrowRight/ArrowLeft 展开和折叠分支;ArrowUp/ArrowDown、Home、End 与 Escape 用于导航或关闭树。没有 label 的 one-shot 行回退到其会话 id。只有一行自身的目录加载为空后,它才是已知叶子。
### 续接对话
@@ -208,6 +208,11 @@ function isKnownLeaf(catalog: SubagentCatalogSnapshot | undefined): boolean {
return catalog?.state === 'ready' && catalog.entries.length === 0
}
/** The agent name unique among the row's siblings, or the Session ID for entries recorded without one. */
function entryName(entry: SubagentCatalogSnapshot['entries'][number]): string {
return entry.mode === 'continuable' || entry.mode === 'external' ? entry.name ?? entry.id : entry.id
}
/** Only a local child's last closed, normally completed turn receives the completed marker. */
function completedEntry(entry: SubagentCatalogSnapshot['entries'][number], summary: SessionSummary | undefined): boolean {
return entry.mode !== 'external' && entry.activity === 'inactive'
@@ -282,8 +287,9 @@ function CatalogRows({
|| (childCatalog.state === 'loading' && childCatalog.entries.length === 0)
const summary = summaries[entry.id]
const description = entry.label || summary?.title
const primaryLabel = description || entry.id
const secondaryLabel = description ? entry.id : undefined
const name = entryName(entry)
const primaryLabel = description || name
const secondaryLabel = description ? name : undefined
const mode = external ? t('mode.external') : entry.mode === 'unknown' ? t('mode.unknown')
: entry.mode === 'one-shot' ? t('mode.oneShot') : t('mode.continuable')
const completed = completedEntry(entry, summary)
@@ -533,7 +539,7 @@ function CatalogDropdown(props: CatalogDropdownProps) {
? undefined
: catalog?.entries.find(entry => entry.id === currentSessionId)
const switcherDisplayTitle = currentEntry !== undefined
? currentEntry.label || currentEntry.id
? currentEntry.label || entryName(currentEntry)
: displayTitle
const directChildren = catalog?.entries ?? []
const directCount = directChildren.length
@@ -316,6 +316,29 @@ describe('SubagentHeaderLineage', () => {
expect(row.getAttribute('aria-label')).toMatch(new RegExp(`^${CHILD}`))
})
it('shows agent names in place of Session ids while navigation keeps the Session id', () => {
const external = 'external-id' as SessionId
const input = props(catalog({
entries: [
{ id: CHILD, mode: 'continuable', label: 'Review the diff', name: 'reviewer', activity: 'running' },
{ id: GRANDCHILD, mode: 'continuable', label: '', name: 'checker', activity: 'inactive' },
{ id: external, mode: 'external', name: 'outside', activity: 'inactive' },
],
}), {}, { [CHILD]: { ...summary(CHILD, 1), running: true } })
render(<HeaderCatalog {...input} />)
fireEvent.click(screen.getByRole('button', { name: /\d+ 个子智能体$/ }))
const named = screen.getByRole('treeitem', { name: /^Review the diff reviewer/ })
expect(within(named).getByText('Review the diff').compareDocumentPosition(within(named).getByText('reviewer'))
& Node.DOCUMENT_POSITION_FOLLOWING).toBeTruthy()
expect(within(named).queryByText(CHILD)).toBeNull()
const undescribed = screen.getByRole('treeitem', { name: /^checker/ })
expect(within(undescribed).getAllByText('checker')).toHaveLength(1)
expect(within(undescribed).queryByText(GRANDCHILD)).toBeNull()
expect(screen.getByRole('treeitem', { name: /^outside/ }).getAttribute('aria-disabled')).toBe('true')
fireEvent.click(named)
expect(input.openChild).toHaveBeenCalledExactlyOnceWith({ parentSessionId: PARENT, childSessionId: CHILD, mode: 'continuable' })
})
it('hides an empty Team entry but keeps shared tasks and errors reachable without children', () => {
const input = props(catalog({ entries: [] }))
const initial = input.useSessions(state => state)
@@ -1606,6 +1629,19 @@ describe('SubagentHeaderLineage', () => {
expect(screen.getByRole('button', { name: `切换子智能体:${CHILD}` })).toBeTruthy()
})
it('names the breadcrumb by the agent name when the selected row has an empty description', () => {
const input = {
...props(catalog({ entries: [{ id: CHILD, mode: 'continuable', label: '', name: 'reviewer', activity: 'inactive' }] }), {}, {
[CHILD]: { ...summary(CHILD, 1), parentId: PARENT, origin: 'subagent' as const },
}),
sessionId: CHILD,
lineageSessionId: CHILD,
displayTitle: 'summary title',
}
render(<HeaderCatalog {...input} />)
expect(screen.getByRole('button', { name: '切换子智能体:reviewer' }).textContent).toBe('reviewer')
})
it('keeps an ancestor switcher muted and omits its descendant count and section heading', () => {
const input = {
...props(catalog({ team: sharedTeam }), {
+4 -4
View File
@@ -15,8 +15,8 @@
en: d152484eb41ac6b4
zh: 09388d293f9be9cb
/deepseek-ai-dsh-client-ui-tool/use-this-package:
en: 2419beff9bcd8139
zh: 5aafe9b168e571a5
en: 64c4c250bfe2898f
zh: fe99277a67dbd84a
/deepseek-ai-dsh-client-ui-tool/use-this-package/registering-a-business-tool-view:
en: e458aff61e634190
zh: 650e417f450b3edf
@@ -30,8 +30,8 @@
en: 672e63b2f92e689b
zh: ba950ecb480325a6
/deepseek-ai-dsh-client-ui-tool/understand-the-implementation/cards:
en: d2ac2f855da27aff
zh: 61d257d60971f259
en: 614a73a6652d3f76
zh: 0321bc0f72bdcc07
/deepseek-ai-dsh-client-ui-tool/understand-the-implementation/declared-optional-capabilities:
en: c1926deb4e5f3734
zh: c5845f465b94a459
+3 -3
View File
@@ -25,13 +25,13 @@ English | [中文](README.zh.md)
<a id="use-this-package"></a>
## Use this package
Tool calls appear in the conversation as cards: a root call tree with its nested subcalls, each atomic call rendered by its owning view. Every lifecycle state retains the tool's ordinary business glyph; failure and interruption remain explicit through the frozen call/result state, accessible status text, and failure summary. Users can open files or inspect calls through the Host callbacks. A collapsed `web_fetch` row links its http(s) URL, which opens in a new browser tab. Control receipts display the agent ID supplied by the recorded call. Text agent lists show the ID above a single-line description, with compact spacing and recorded status. Click the description to expand or collapse its full text; its accessible name follows the selected locale.
Tool calls appear in the conversation as cards: a root call tree with its nested subcalls, each atomic call rendered by its owning view. Every lifecycle state retains the tool's ordinary business glyph; failure and interruption remain explicit through the frozen call/result state, accessible status text, and failure summary. Users can open files or inspect calls through the Host callbacks. A collapsed `web_fetch` row links its http(s) URL, which opens in a new browser tab. Control receipts display the agent name supplied by the recorded call, or the agent ID in historical calls. Text agent lists show each agent name, or the historical ID, above a single-line description, with compact spacing and recorded status. Click the description to expand or collapse its full text; its accessible name follows the selected locale.
Settled foreground commands with a nonzero exit code, a terminating signal, or an explicit missing exit code keep their description in the ordinary gray text and show a neutral capsule with a red dot immediately after it. The capsule displays only the recorded code, signal, or localized missing-code status and stays on the same line; the description truncates with an ellipsis to reserve its space. Running, successful, and background calls omit it. Generic execution errors and stopped summaries retain their error and warning colors, including on hover.
Before dispatch, a named model call appears as one non-expandable row with its tool-owned icon and title. A generic row shows `Tool call · <tool name>`. Read/write/edit show an openable path once `file_path` closes and decodes without errors; write/edit show `NKB` after that path once content arrives, retaining it during execution and after success, before any diff totals. N rounds the decoded input's UTF-16 length up in units of 1024, summing old and new text for edit; it is not file bytes. Error and stopped rows omit the size and diff totals. Command rows show the streamed description. `tool/call` enables the existing call presentation; completing an argument block alone does not start execution.
`subagent` and `subagent_fork` creation rows stream the first line of `description`, retaining it during execution, after creation, and when expanded. After preparation, calls without a description fall back to the first nonempty `prompt` line; missing arguments leave only the tool title. Both tools and `list_subagent_models` use the existing Users icon; `subagent_fork` uses the distinct title “Fork subagent”. Creation receipts show the started state, the full `description` as the agent task description, the recorded agent Session id, and complete task instructions. Current receipts read `kind: activation` and `subagentId` from result metadata; only historical results without metadata use text parsing. Malformed metadata keeps the generic result view. Synchronous agent responses remain in the result body; errors retain their failure summary.
`subagent` and `subagent_fork` creation rows stream the first line of `description`, retaining it during execution, after creation, and when expanded. After preparation, calls without a description fall back to the first nonempty `prompt` line; missing arguments leave only the tool title. Both tools and `list_subagent_models` use the existing Users icon; `subagent_fork` uses the distinct title “Fork subagent”. Creation receipts show the started state, the full `description` as the agent task description, the recorded agent name when present, the agent Session id, and complete task instructions. Current receipts read `kind: activation`, `subagentId`, and optional `name` from result metadata; only historical results without metadata use text parsing. Malformed metadata keeps the generic result view. Synchronous agent responses remain in the result body; errors retain their failure summary.
File and URL toolview Slots obtain `useContextMenu` directly and supply bound `fileContextMenuProps` or `urlContextMenuProps` to `ToolRow`. File registrations inject a gesture-time path resolver for the originating Session’s working directory, falling back to its workspace root. `ToolCallTree` supplies an explicit file adapter to its plain `GenericToolCard` fallback, including nested calls. No Markdown provider is required. Mouse and keyboard gestures retain the captured path, line, URL, and Session without expanding the row or opening the file.
@@ -93,7 +93,7 @@ Chat diff cards keep nine rows before folding, enough for a file header, one rem
An Auto denial takes precedence over keyed specialized views. Its generic row preserves the call identity, omits raw arguments, and normalizes the stored reason only for display: trim surrounding whitespace and collapse line separators to spaces, with localized fallback for an empty result. Session and SDK error details keep the original reason.
Recorded tool details cover goal and schedule tools, Cordis inspection, workflow and Ralph reports, Session event/search/trace queries, agent and teammate controls, background jobs, persistent terminals, and LSP navigation. These expanded bodies read successful logged results, preserve generic input/output for failures or unsupported data, and keep Inspect available. Dates include the viewer's time zone, and statuses reflect the call result rather than current session state. Agent control receipts display the recorded target Session id. `wait_agent` shows a single waiting, ended, or timed-out header without a repeated summary; historical `noProgress` results keep their recorded explanation. Session traces preserve descendant indentation. LSP results open filesystem paths through the Host callback and display other URIs as text. The browser adapter consumes recorded producer text and JSON; Host service objects and presenter callbacks do not cross into the Client.
Recorded tool details cover goal and schedule tools, Cordis inspection, workflow and Ralph reports, Session event/search/trace queries, agent and teammate controls, background jobs, persistent terminals, and LSP navigation. These expanded bodies read successful logged results, preserve generic input/output for failures or unsupported data, and keep Inspect available. Dates include the viewer's time zone, and statuses reflect the call result rather than current session state. Agent control receipts display the recorded target agent name, or the Session id in historical calls. `wait_agent` shows a single waiting, ended, or timed-out header without a repeated summary; historical `noProgress` results keep their recorded explanation. Session traces preserve descendant indentation. LSP results open filesystem paths through the Host callback and display other URIs as text. The browser adapter consumes recorded producer text and JSON; Host service objects and presenter callbacks do not cross into the Client.
Expanded status dots and labels use static semantic colors. Receipt and job-output headers keep neutral text and omit the status while expanded. An interruption receipt confirms only that interruption was requested.
+3 -3
View File
@@ -25,13 +25,13 @@ kind: "package-reference"
<a id="use-this-package"></a>
## 使用本包
工具调用在对话中显示为卡片:一个根调用树带其嵌套子调用,每个原子调用由所属视图渲染。所有生命周期状态都保留工具的普通业务图标;失败与中断仍通过冻结调用/结果状态、无障碍状态文本和失败摘要明确表达。用户可通过宿主回调打开文件或检查调用。折叠的 `web_fetch` 行把其 http(s) URL 显示为链接,在新浏览器标签页中打开。控制工具回执显示记录的调用所提供的智能体 ID。文本形式的智能体列表以紧凑间距展示 ID、下方的单行描述及记录中的状态。点击描述可展开或收起全文;其无障碍名称使用当前语言。
工具调用在对话中显示为卡片:一个根调用树带其嵌套子调用,每个原子调用由所属视图渲染。所有生命周期状态都保留工具的普通业务图标;失败与中断仍通过冻结调用/结果状态、无障碍状态文本和失败摘要明确表达。用户可通过宿主回调打开文件或检查调用。折叠的 `web_fetch` 行把其 http(s) URL 显示为链接,在新浏览器标签页中打开。控制工具回执显示记录的调用所提供的智能体名称,历史调用则显示智能体 ID。文本形式的智能体列表以紧凑间距展示智能体名称(历史记录为 ID)、下方的单行描述及记录中的状态。点击描述可展开或收起全文;其无障碍名称使用当前语言。
已结束的前台命令若返回非零退出码、终止信号,或明确记录为无退出码,描述保持普通灰色,后面紧接带红点的中性胶囊。胶囊仅显示记录的退出码、信号或本地化的“未正常退出”状态,并保持在同一行;描述超出可用宽度时显示省略号,为胶囊预留空间。运行中、成功和后台调用不显示胶囊。通用执行错误与停止摘要仍保留错误色和警告色,悬停时也不改变。
派发前,模型已给出名称的调用显示为不可展开的一行,使用工具自己的图标与标题。通用行显示为 `工具调用 · <工具名>`。read/write/edit 在 `file_path` 闭合且解码无误后显示可打开的路径;write/edit 从内容到达起在该路径后显示 `NKB`,执行中和成功后仍保留,位于差异统计之前。N 按解码后输入的 UTF-16 长度除以 1024 向上取整,edit 合计新旧文本长度;它不是文件字节数。失败和停止的行省略大小与差异统计。命令行显示流入中的描述。`tool/call` 才启用既有调用展示;参数块结束本身不代表开始执行。
`subagent` 与 `subagent_fork` 的创建行逐步显示 `description` 的首行,执行中、创建完成后和展开时均保留。准备阶段结束后,缺少描述的调用回退到 `prompt` 的首个非空行;参数不可用时仅显示工具标题。两个工具与 `list_subagent_models` 均使用现有的 Users 图标;`subagent_fork` 使用独立标题“派生子智能体”。创建回执显示已启动状态、作为智能体任务描述的完整 `description`、记录的智能体 Session id,以及完整任务指令。当前回执从结果 metadata 读取 `kind: activation` 与 `subagentId`;仅缺少 metadata 的历史结果使用文本解析。metadata 无效时保留通用结果视图。同步返回的 agent 回复仍放在结果正文中;失败时保留错误摘要。
`subagent` 与 `subagent_fork` 的创建行逐步显示 `description` 的首行,执行中、创建完成后和展开时均保留。准备阶段结束后,缺少描述的调用回退到 `prompt` 的首个非空行;参数不可用时仅显示工具标题。两个工具与 `list_subagent_models` 均使用现有的 Users 图标;`subagent_fork` 使用独立标题“派生子智能体”。创建回执显示已启动状态、作为智能体任务描述的完整 `description`、记录的智能体名称(如有)、智能体 Session id,以及完整任务指令。当前回执从结果 metadata 读取 `kind: activation`、`subagentId` 与可选的 `name`;仅缺少 metadata 的历史结果使用文本解析。metadata 无效时保留通用结果视图。同步返回的 agent 回复仍放在结果正文中;失败时保留错误摘要。
文件和 URL 工具视图 Slot 直接获取 `useContextMenu`,向 `ToolRow` 提供已绑定的 `fileContextMenuProps` 或 `urlContextMenuProps`。文件注册注入在触发时读取原始 Session 工作目录的路径解析器,工作目录缺失时使用工作区根目录。`ToolCallTree` 向普通 `GenericToolCard` fallback 显式提供文件适配函数,包含嵌套调用。无需 Markdown Provider。鼠标和键盘手势保留捕获的路径、行号、URL 与 Session,不会展开工具行或打开文件。
@@ -93,7 +93,7 @@ Chat diff 卡片在折叠前保留九行,足以容纳文件标题、一对删
Auto 拒绝优先于按工具名选择的专门视图。其通用行保留调用身份、省略原始参数,并且只在显示时归一化存储的理由:去除首尾空白,把行分隔符折叠为空格,结果为空时使用本地化通用理由。Session 与 SDK 错误详情保留原始理由。
记录结果的工具详情覆盖目标和定时任务工具、Cordis 检查、workflow 与 Ralph 报告、Session 事件/搜索/轨迹查询、Agent 与 teammate 控制、后台作业、持久终端以及 LSP 导航。展开内容读取成功的记录结果,为失败或不支持的数据保留通用输入/输出,并保留 Inspect。日期包含查看者的时区,状态反映调用结果而非当前会话状态。Agent 控制回执显示记录的目标 Session id。`wait_agent` 的行标题仅显示等待中、已结束或已超时,不重复追加摘要;历史 `noProgress` 结果保留记录中的说明。Session 轨迹保留后代的缩进。LSP 结果通过 Host 回调打开文件系统路径,其他 URI 则显示为文本。浏览器适配器消费已记录的 producer 文本与 JSON;Host service 对象和 presenter 回调不会进入 Client。
记录结果的工具详情覆盖目标和定时任务工具、Cordis 检查、workflow 与 Ralph 报告、Session 事件/搜索/轨迹查询、Agent 与 teammate 控制、后台作业、持久终端以及 LSP 导航。展开内容读取成功的记录结果,为失败或不支持的数据保留通用输入/输出,并保留 Inspect。日期包含查看者的时区,状态反映调用结果而非当前会话状态。Agent 控制回执显示记录的目标智能体名称,历史调用则显示 Session id。`wait_agent` 的行标题仅显示等待中、已结束或已超时,不重复追加摘要;历史 `noProgress` 结果保留记录中的说明。Session 轨迹保留后代的缩进。LSP 结果通过 Host 回调打开文件系统路径,其他 URI 则显示为文本。浏览器适配器消费已记录的 producer 文本与 JSON;Host service 对象和 presenter 回调不会进入 Client。
展开后的状态圆点和文字使用静态语义色。操作回执和任务输出的标题保持中性色,展开时省略标题中的状态。中断回执仅确认已发出中断请求。
@@ -24,12 +24,13 @@ function agentList(text: string, json: unknown, t: DetailTranslate): ToolDetails
if (text === '(no subagents)') return detailList([], t('detail.agents.count', { count: 0 }), t)
const items: DetailItem[] = []
for (const line of text.split('\n')) {
// Historical rows name agents by Session ID and carry parent and depth.
const match = /^(\S+) \[([^\]]+)\](?: parent=\S+ depth=\d+)?(?: — (.*))?$/u.exec(line)
if (match === null) return null
const [, id, state, title] = match
if (id === undefined || state === undefined) return null
const [, agent, state, title] = match
if (agent === undefined || state === undefined) return null
items.push({
title: id, ...(title === undefined ? {} : { subtitle: title }),
title: agent, ...(title === undefined ? {} : { subtitle: title }),
badge: detailBadge(state, t),
fields: [],
})
@@ -99,6 +100,7 @@ function lspDetails(args: Record<string, unknown>, text: string, t: DetailTransl
* @param args - Recorded creation arguments, including description and full prompt.
* @param text - Single recorded text block; absent for other content layouts.
* @param meta - Tool-owned result metadata; only absent metadata permits legacy text parsing.
* Its `name` is the child's model-facing agent name and is absent from receipts recorded before agents had names.
* @param t - Conversation translator.
* @returns Started task details, a historical synchronous reply, or null for unsupported data.
*/
@@ -110,6 +112,8 @@ export function subagentDetails(
if (nonempty(description)) fields.push({ label: t('detail.field.agentDescription'), value: description })
if (meta !== undefined) {
if (!detailRecord(meta) || meta.kind !== 'activation' || !nonempty(meta.subagentId)) return null
if (meta.name !== undefined && !nonempty(meta.name)) return null
if (meta.name !== undefined) fields.push({ label: t('detail.field.agentName'), value: meta.name })
fields.push({ label: t('detail.field.id'), value: meta.subagentId })
} else {
if (text === undefined) return null
@@ -139,7 +143,8 @@ export function subagentDetails(
export function controlDetails(
name: string, args: Record<string, unknown>, text: string, json: unknown, t: DetailTranslate,
): ToolDetailsModel | null {
const target = arg(args, 'target') || arg(args, 'agent_id') || arg(args, 'sessionId') || arg(args, 'job_id')
// Historical `send_message` and `interrupt_agent` records name their target with `agent_id`.
const target = arg(args, 'target') || arg(args, 'agent') || arg(args, 'agent_id') || arg(args, 'sessionId') || arg(args, 'job_id')
switch (name) {
case 'list_agents': return agentList(text, json, t)
case 'job_list': return jobList(text, t)
@@ -66,7 +66,7 @@ export function detailBadge(status: string, t: DetailTranslate): NonNullable<Det
const FIELD_KEYS = {
id: 'detail.field.id', revision: 'detail.field.revision', platform: 'detail.field.platform',
provider: 'detail.field.provider', model: 'detail.field.model', role: 'detail.field.role',
context: 'detail.field.context', ownerId: 'detail.field.owner', ready: 'detail.field.ready',
context: 'detail.field.context', owner: 'detail.field.owner', ownerId: 'detail.field.owner', ready: 'detail.field.ready',
blockedBy: 'detail.field.dependencies', writeScopes: 'detail.field.writeScopes',
writeScopeWarnings: 'detail.field.warnings', diagnostics: 'detail.field.diagnostics',
methods: 'detail.field.methods', inputSchema: 'detail.field.inputSchema', outputSchema: 'detail.field.outputSchema',
@@ -65,12 +65,26 @@ describe('control detail adapters', () => {
})
it('uses producer wording for agent, job, terminal, and LSP lists', () => {
const agents = details('list_agents', 'a1 [running] — Build\na2 [ready] parent=a1 depth=1 — Review', { scope: 'descendants' })
expect(agents?.summary).toBe('2 agents')
const agents = details('list_agents', 'lead [running] — root agent\nreviewer/checker [inactive] — Check tests\nold-id [unavailable]')
expect(agents?.summary).toBe('3 agents')
expect(agents?.items).toEqual([
{ title: 'lead', subtitle: 'root agent', badge: { label: 'Running', tone: 'info' }, fields: [] },
{ title: 'reviewer/checker', subtitle: 'Check tests', badge: { label: 'Inactive', tone: 'warning' }, fields: [] },
{ title: 'old-id', badge: { label: 'unavailable', tone: 'neutral' }, fields: [] },
])
const historical = details('list_agents', 'a1 [running] — Build\na2 [ready] parent=a1 depth=1 — Review\na3 [diagnostic: corrupt] parent=a1 depth=1', { scope: 'descendants' })
expect(historical?.summary).toBe('3 agents')
expect(historical?.items).toEqual([
{ title: 'a1', subtitle: 'Build', badge: { label: 'Running', tone: 'info' }, fields: [] },
{ title: 'a2', subtitle: 'Review', badge: { label: 'Ready', tone: 'neutral' }, fields: [] },
{ title: 'a3', badge: { label: 'diagnostic: corrupt', tone: 'neutral' }, fields: [] },
])
const structured = details('list_agents', JSON.stringify([{ name: 'lead', status: 'running', description: 'root agent' }, { name: 'reviewer', status: 'inactive' }]))
expect(structured?.items).toEqual([
{ title: 'lead', description: 'root agent', badge: { label: 'Running', tone: 'info' }, fields: [] },
{ title: 'reviewer', badge: { label: 'Inactive', tone: 'warning' }, fields: [] },
])
expect(details('list_agents', 'reviewer running')).toBeNull()
expect(details('list_agents', '(no subagents)')?.empty).toBe('No results')
expect(details('job_list', 'j1 [bash] running — Build')?.items[0]?.fields).toContainEqual({ label: 'Type', value: 'bash' })
expect(details('job_list', '(no background jobs)')?.empty).toBe('No results')
@@ -103,20 +117,39 @@ describe('control detail adapters', () => {
it.each(['subagent', 'subagent_fork'])('%s renders persisted creation metadata independently of result wording', (name) => {
const args = { description: 'Review the changes', prompt: 'Read the diff and report defects.' }
const block = { ...output(name, 'Delegation accepted.', args), meta: { kind: 'activation', subagentId: 'child-1' } }
const block = { ...output(name, 'Delegation accepted.', args), meta: { kind: 'activation', subagentId: 'child-1', name: 'reviewer' } }
const model = detailsCardModel(block, t, 'en')
expect(model?.items[0]).toEqual({
title: 'Started',
fields: [{ label: 'Agent task description', value: args.description }, { label: 'ID', value: 'child-1' }],
fields: [
{ label: 'Agent task description', value: args.description },
{ label: 'Agent name', value: 'reviewer' },
{ label: 'ID', value: 'child-1' },
],
groups: [{ label: 'Task', items: [{ description: args.prompt, fields: [] }] }],
})
expect(detailsCardModel({ ...block, content: [] }, t, 'en')).toEqual(model)
expect(detailsCardModel({ ...block, isError: true }, t, 'en')).toBeNull()
expect(detailsCardModel(block, makeTranslate(zh, commonZh), 'zh-CN')?.items[0]?.fields)
.toEqual([{ label: '智能体任务描述', value: args.description }, { label: 'ID', value: 'child-1' }])
expect(detailsCardModel(block, makeTranslate(zh, commonZh), 'zh-CN')?.items[0]?.fields).toEqual([
{ label: '智能体任务描述', value: args.description },
{ label: '智能体名称', value: 'reviewer' },
{ label: 'ID', value: 'child-1' },
])
})
it.each([null, [], {}, { kind: 'other', subagentId: 'child-1' }, { kind: 'activation' }, { kind: 'activation', subagentId: 1 }, { kind: 'activation', subagentId: ' ' }])(
it('omits the name from metadata recorded before agents had names', () => {
const args = { description: 'Review the changes', prompt: 'Read the diff and report defects.' }
const block = { ...output('subagent', 'started subagent child-1', args), meta: { kind: 'activation', subagentId: 'child-1' } }
expect(detailsCardModel(block, t, 'en')?.items[0]?.fields).toEqual([
{ label: 'Agent task description', value: args.description }, { label: 'ID', value: 'child-1' },
])
})
it.each([
null, [], {}, { kind: 'other', subagentId: 'child-1' }, { kind: 'activation' }, { kind: 'activation', subagentId: 1 },
{ kind: 'activation', subagentId: ' ' }, { kind: 'activation', subagentId: 'child-1', name: 1 },
{ kind: 'activation', subagentId: 'child-1', name: ' ' },
])(
'keeps malformed metadata on the generic result path (%j)', (meta) => {
const block = { ...output('subagent', 'started subagent child-1'), meta }
expect(detailsCardModel(block, t, 'en')).toBeNull()
@@ -127,7 +160,10 @@ describe('control detail adapters', () => {
expect(details('spawn_teammate', '{"member":{"id":"a1","status":"running"}}', { name: 'A' })?.items[0]).toMatchObject({ title: 'a1', badge: { label: 'Running' } })
expect(details('team_task_create', '{"id":"task-1","subject":"Review","status":"pending"}')?.summary).toBe('Review')
expect(details('team_task_list', '{"tasks":[{"id":"task-1","subject":"Review"}],"nextCursor":3}')?.caption).toBe('More tasks available; next cursor is 3')
expect(details('send_message', '{"status":"queued"}', { agent_id: 'a1', message: 'hello' })?.items[0]?.badge?.label).toBe('Queued')
expect(details('team_task_get', '{"id":"task-1","subject":"Review","owner":"reviewer/checker"}')?.items[0]?.fields).toContainEqual({ label: 'Owner', value: 'reviewer/checker' })
expect(details('team_task_get', '{"id":"task-1","subject":"Review","ownerId":"child-1"}')?.items[0]?.fields).toContainEqual({ label: 'Owner', value: 'child-1' })
expect(details('send_message', '{"status":"queued"}', { agent: 'reviewer', message: 'hello' })?.items[0]).toMatchObject({ title: 'reviewer', badge: { label: 'Queued' } })
expect(details('send_message', 'message delivered to agent reviewer/checker', { agent: 'reviewer/checker', message: 'hello' })?.summary).toBe('reviewer/checker · Message delivered')
expect(details('send_message', 'message delivered to agent reviewer', { agent_id: 'reviewer', message: 'hello' })?.summary).toBe('reviewer · Message delivered')
expect(details('interrupt_agent', '{"previousStatus":"running"}', { agent_id: 'a1' })?.items[0]?.fields).toContainEqual({ label: 'Previous status', value: 'Running' })
expect(details('wait_agent', '{"timedOut":true}')?.summary).toBe('Wait timed out')
@@ -149,6 +185,7 @@ describe('control detail adapters', () => {
expect(details('unknown', 'x')).toBeNull()
expect(details('team_task_list', '{"tasks":[],"nextCursor":"bad"}')).toBeNull()
expect(details('terminal_read', 'bad', { sessionId: 'pty-1' })).toBeNull()
expect(details('interrupt_agent', 'interrupt requested for agent reviewer', { agent: 'reviewer' })?.summary).toBe('reviewer · Interrupt requested')
expect(details('interrupt_agent', 'interrupt requested for agent reviewer', { agent_id: 'reviewer' })?.summary).toContain('Interrupt')
expect(details('interrupt_agent', 'unexpected', { agent_id: 'a1' })).toBeNull()
expect(details('job_kill', 'unexpected', { job_id: 'j1' })).toBeNull()
@@ -153,17 +153,17 @@ describe('todosDetail', () => {
})
describe('DetailsRow', () => {
it('puts agent IDs first and lets a compact description expand and collapse', () => {
it('puts agent names first and lets a compact description expand and collapse', () => {
const description = 'Verify every construction bound. '.repeat(20)
const block = { ...result('list_agents', null), content: [{ type: 'text' as const, text: `tree-checker-id [running] parent=root-id depth=1 — ${description}` }] }
const block = { ...result('list_agents', null), content: [{ type: 'text' as const, text: `reviewer/checker [running] — ${description}` }] }
const model = detailsCardModel(block, t, 'en')!
render(<ToolDetails model={model} t={t} />)
const id = screen.getByText('tree-checker-id')
const toggle = screen.getByRole('button', { name: 'Expand description for tree-checker-id' })
expect(id.compareDocumentPosition(toggle) & Node.DOCUMENT_POSITION_FOLLOWING).toBeTruthy()
const name = screen.getByText('reviewer/checker')
const toggle = screen.getByRole('button', { name: 'Expand description for reviewer/checker' })
expect(name.compareDocumentPosition(toggle) & Node.DOCUMENT_POSITION_FOLLOWING).toBeTruthy()
expect(toggle.textContent).toBe(description)
fireEvent.click(toggle)
expect(screen.getByRole('button', { name: 'Collapse description for tree-checker-id' }).getAttribute('aria-expanded')).toBe('true')
expect(screen.getByRole('button', { name: 'Collapse description for reviewer/checker' }).getAttribute('aria-expanded')).toBe('true')
fireEvent.click(toggle)
expect(toggle.getAttribute('aria-expanded')).toBe('false')
})
@@ -73,7 +73,7 @@ it.each(['portable-bundle', 'foreign-nested-row'] as const)('validates and insta
await rename(join(spec.cwd!, 'index.js'), join(spec.cwd!, 'runtime.mjs'))
await symlink('./runtime.mjs', join(spec.cwd!, 'index.js'))
}
return { childId: spec.childId!, dispose: async () => {},
return { childId: spec.childId!, name: 'agent-1', dispose: async () => {},
result: Promise.resolve({ output: [], stopReason: 'completed', structured: { ready: true } }) }
} })
Object.assign(ctx.loader.builtins, { sessions: Sessions, projections: Projections, llm: Llm, prompt: SystemPrompt, tools: Tools,
@@ -9,8 +9,8 @@
en: 520d9dc51e2b0142
zh: 8f332776243107a9
/deepseek-ai-dsh-experimental-tool-subagent-oar/summary:
en: 8adbaf2511d2c47f
zh: 1495f6bdb84a30ea
en: eeb535e580132e01
zh: 918fc55ce2be9581
/deepseek-ai-dsh-experimental-tool-subagent-oar/table-of-contents:
en: d152484eb41ac6b4
zh: 8d1e20b826450ffe
@@ -21,11 +21,11 @@
en: 368805e5bcffeb0a
zh: 9340ff5074ada9e1
/deepseek-ai-dsh-experimental-tool-subagent-oar/use-this-package/minimal-configuration:
en: 5b2b33c1d0fae20a
zh: 26bff1e013e2bfcd
en: 2f456750c533e966
zh: 89ed99fcbb664475
/deepseek-ai-dsh-experimental-tool-subagent-oar/understand-the-implementation:
en: 3e8a9fffa9c5afd0
zh: 932b6d0b682208ba
en: 87b1d584ff51cc25
zh: bc3858dc2f3a8099
/deepseek-ai-dsh-experimental-tool-subagent-oar/further-exploration:
en: a796236202b695f5
zh: 8e76361f31517714
@@ -36,11 +36,11 @@
en: 8febbb031aa0452d
zh: da3f9011631652da
/deepseek-ai-dsh-experimental-tool-subagent-oar/model-experience/external-delegation-tool/what-the-model-sees:
en: 2e0f5274092f794b
zh: 83a14e5f7018717f
en: 7ec989dffbc0f65e
zh: fc734ea0a8801bab
/deepseek-ai-dsh-experimental-tool-subagent-oar/model-experience/external-delegation-tool/token-effect:
en: 60d7ffec7f4dc858
zh: 09f286978df6b4ec
en: 33d073eb994d2969
zh: 320f4a82aa665a46
/deepseek-ai-dsh-experimental-tool-subagent-oar/model-experience/external-delegation-tool/kv-cache-effect:
en: 7c1ac0b007b2f0ce
zh: 2332a07c6f8bcbdc

Some files were not shown because too many files have changed in this diff Show More