From d769d3cbb7c32cc4f1a4ff32cf5b30af96ea9f34 Mon Sep 17 00:00:00 2001 From: Hypatia May Date: Thu, 6 Aug 2026 13:46:55 +0800 Subject: [PATCH] feat(subagent): let ancestors interrupt descendants MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit interrupt_agent(agent_id) passes the calling agent as the ancestor authority for ctx.subagents.interrupt(); the service verifies live registry identity and recorded lineage, so a direct child or deeper descendant stops with the same generic parameter while send_message keeps its exact-direct-parent authority. Discovery: list_agents gains an optional scope. descendants walks the new SubagentService.listDescendants() — one lineage trace flattened in stable pre-order across ordinary and one-shot intermediates, each entry carrying its verified parentId and depth — and every status now comes from the live Agent registry (running/idle/complete). Refs #1535 --- ...subagent-catalog-and-list-agents.i18n.yaml | 4 +- ...urable-subagent-catalog-and-list-agents.md | 8 +- ...ble-subagent-catalog-and-list-agents.zh.md | 8 +- ...6-continuable-subagent-interrupt.i18n.yaml | 4 +- ...26-08-06-continuable-subagent-interrupt.md | 6 +- ...08-06-continuable-subagent-interrupt.zh.md | 6 +- apps/web/tests/shipped-composition.e2e.ts | 1 + docs/cordis-catalog/services.md | 19 +- docs/core-data-structures/subagent.i18n.yaml | 4 +- docs/core-data-structures/subagent.md | 23 +- docs/core-data-structures/subagent.zh.md | 23 +- .../system-prompt.expected.md | 21 +- .../tool-schemas.expected.json | 31 ++- .../both-mode-turn/tool-schemas.expected.json | 31 ++- .../code-mode-turn/system-prompt.expected.md | 21 +- .../lsp-definition/tool-schemas.expected.json | 31 ++- .../pty-tools/tool-schemas.expected.json | 31 ++- .../tool-schemas.expected.json | 31 ++- .../tool-schemas.1.expected.json | 31 ++- .../tool-schemas.1.expected.json | 31 ++- .../tool-schemas.1.expected.json | 31 ++- .../text-turn/tool-schemas.expected.json | 31 ++- .../web-fetch/tool-schemas.expected.json | 31 ++- .../cordis/tool-cordis/src/api-catalog.ts | 8 + .../core/tools/tests/gen-tool-catalog.spec.ts | 3 +- packages/subagent/subagent/README.i18n.yaml | 4 +- packages/subagent/subagent/README.md | 5 +- packages/subagent/subagent/README.zh.md | 7 +- packages/subagent/subagent/src/index.ts | 31 ++- .../subagent/subagent/src/list-children.ts | 159 ++++++++++++-- .../subagent/tests/list-children.spec.ts | 194 +++++++++++++++++ .../tool-subagent-control/README.i18n.yaml | 4 +- .../subagent/tool-subagent-control/README.md | 28 ++- .../tool-subagent-control/README.zh.md | 28 ++- .../tool-subagent-control/src/index.ts | 56 ++++- .../tool-subagent-control/src/list-agents.ts | 124 ++++++++--- .../tests/list-agents.spec.ts | 165 +++++++++++++- .../tests/tool-subagent-control.spec.ts | 202 +++++++++++++++++- scripts/gen-cordis-catalog.ts | 1 + scripts/gen-tool-catalog.ts | 5 +- scripts/type-equiv.manifest.json | 5 + 41 files changed, 1325 insertions(+), 162 deletions(-) diff --git a/.agents/notes/implemented/feature/2026-07-22-durable-subagent-catalog-and-list-agents.i18n.yaml b/.agents/notes/implemented/feature/2026-07-22-durable-subagent-catalog-and-list-agents.i18n.yaml index 2acc3dd5b5..c525cc8f43 100644 --- a/.agents/notes/implemented/feature/2026-07-22-durable-subagent-catalog-and-list-agents.i18n.yaml +++ b/.agents/notes/implemented/feature/2026-07-22-durable-subagent-catalog-and-list-agents.i18n.yaml @@ -2,5 +2,5 @@ # side as of the last confirmed-consistent state. Both languages carry equal authority; # after editing either side, bring the other along and re-record with: # pnpm run verify-translation-pairing --write .agents/notes/implemented/feature/2026-07-22-durable-subagent-catalog-and-list-agents.md -2026-07-22-durable-subagent-catalog-and-list-agents.md: b96d6e1dd36c58af67c8e93e62515672790ad009 -2026-07-22-durable-subagent-catalog-and-list-agents.zh.md: 856bac615db84bfe2898ec0838094c6bc29f77b2 +2026-07-22-durable-subagent-catalog-and-list-agents.md: 8337a926238bf7fc4395896fcd4ca180c9c1ac1c +2026-07-22-durable-subagent-catalog-and-list-agents.zh.md: bcf2895a9a69c8cff949788c78158bfccd198c5c diff --git a/.agents/notes/implemented/feature/2026-07-22-durable-subagent-catalog-and-list-agents.md b/.agents/notes/implemented/feature/2026-07-22-durable-subagent-catalog-and-list-agents.md index b96d6e1dd3..8337a92623 100644 --- a/.agents/notes/implemented/feature/2026-07-22-durable-subagent-catalog-and-list-agents.md +++ b/.agents/notes/implemented/feature/2026-07-22-durable-subagent-catalog-and-list-agents.md @@ -23,7 +23,7 @@ Parent-to-child enumeration is a service capability with consumer-specific proje - report corpus activity separately as `running` or `inactive`, without implying completion or resumability; - return every resulting child in stable `createdAt` ascending, child-id ascending order. -Every ordinary local start receives a `one-shot` descriptor with an optional caller-owned display label, while the continuation manager persists a labeled `continuable` descriptor containing its additional reconstruction fields. The model-facing delegation tool already owns a short `description` and supplies it for one-shot display; lower-level callers such as workflows need not invent presentation metadata. The model-facing `list_agents` adapter filters the service result to continuable children and maps `inactive` to its existing `complete` presentation; a UI can consume both modes and choose an id-based fallback for unlabeled one-shot history. Descriptor persistence, by-id lookup, direct-parent authorization, and provider-independent cold resume remain owned by the implemented Activation contract. Listing consumes those facts but cannot weaken them or invent a second descriptor representation. +Every ordinary local start receives a `one-shot` descriptor with an optional caller-owned display label, while the continuation manager persists a labeled `continuable` descriptor containing its additional reconstruction fields. The model-facing delegation tool already owns a short `description` and supplies it for one-shot display; lower-level callers such as workflows need not invent presentation metadata. The model-facing `list_agents` adapter filters the service result to continuable children and refines status through the live Agent registry (`running`/`idle`/`complete`); a UI can consume both modes and choose an id-based fallback for unlabeled one-shot history. Descriptor persistence, by-id lookup, direct-parent authorization, and provider-independent cold resume remain owned by the implemented Activation contract. Listing consumes those facts but cannot weaken them or invent a second descriptor representation. ### Enumeration decision @@ -52,7 +52,7 @@ If measured scale later requires an index, that index is derived state: session A valid descriptor produces one child entry, a per-child inspection failure produces one diagnostic entry, and a candidate without a descriptor produces no entry. `mode` is durable creation policy; `activity` is a process-local corpus snapshot. Activity is neither `AgentStatus`, the manager's internal Activation state, nor a durable outcome, and the result does not expose the internal `createdAt` sorting key. Exact Activation states and durable outcomes such as successful completion, failure, cancellation, and stop reason require a separate durable activation record and are outside this feature. -The model-facing `list_agents` tool takes no arguments, derives `parentSessionId` from the current execution Agent, and is a thin adapter in `@deepseek-ai/dsh-tool-subagent-control`. It keeps diagnostics, drops `one-shot` child entries, maps a continuable child's `running` activity to `running` and `inactive` activity to `complete`, then renders ` [] —