fix(subagent): close stacked catalog integration gaps

This commit is contained in:
Dudu-0223
2026-07-30 22:46:33 +08:00
committed by Tianyi Cui
parent a967f5174a
commit 8b0a7a5d8d
16 changed files with 102 additions and 53 deletions

View File

@@ -10,6 +10,7 @@
import type { Context } from 'cordis'
import type { SessionId } from '@deepseek-ai/dsh-session'
import type { SessionQueryService, SessionRecord } from '@deepseek-ai/dsh-session-query'
import type SubagentService from './index.ts'
import { SubagentError } from './error.ts'
import { foldSubagentDescriptor } from './descriptor.ts'
@@ -67,10 +68,11 @@ export type SubagentListEntry =
/**
* Interpret one parent's direct session descendants as session-backed subagents
* without loading or resuming an Agent.
* @see {@link SubagentService.listChildren} for the public cancellation and
* failure contract.
* @param ctx - context carrying the optional session-query service.
* @param parentSessionId - parent session whose direct children are listed.
* @param signal - caller-owned cancellation forwarded where supported and
* observed around every query await.
* @param signal - caller-owned cancellation.
* @returns children and per-child diagnostics in stable trace order.
* @throws {@link SubagentError} when session query is unavailable or
* the caller cancels the scan.
@@ -79,7 +81,7 @@ export async function listChildren(
ctx: Context,
parentSessionId: SessionId,
signal?: AbortSignal,
): Promise<SubagentListEntry[]> {
): ReturnType<SubagentService['listChildren']> {
const query = ctx.get('sessionQuery')
if (query === undefined) {
throw new SubagentError(

View File

@@ -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 packages/subagent/tool-subagent-control/README.md
README.md: 78621701cd4fe8ac9ad8b3f0985271ee6e2a7e8c
README.zh.md: f6ed8144dcfc8df8f2e6edad89c4d42b641d666e
README.md: 5babd9a34fd63b0152543eca4467cd3afa3ff927
README.zh.md: bfeede644e7ffdd8ba5b01b2b62c2974937133df

View File

@@ -2,7 +2,7 @@
English | [中文](README.zh.md)
The optional, globally named `send_message` and `list_agents` tools are thin adapters over `ctx.subagents`. Provider-bound `@deepseek-ai/dsh-tool-subagent` instances register distinct delegation tools per transport; this separately loaded package registers shared control tools once, so multiple delegation tools never register duplicate global controls. The root plugin registers `send_message` and requires only `subagents`; the separately loadable `./list-agents` plugin registers `list_agents` and additionally requires `sessionQuery` at load. A deployment without session query keeps `send_message` and omits the list tool. Neither tool's presence determines whether a delegation tool starts continuable work.
The optional, globally named `send_message` and `list_agents` tools are thin adapters over `ctx.subagents`. Provider-bound `@deepseek-ai/dsh-tool-subagent` instances register distinct delegation tools per transport; this separately loaded package registers shared control tools once, so multiple delegation tools never register duplicate global controls. The root plugin registers `send_message` and requires only `subagents`; the separately loadable `./list-agents` plugin registers `list_agents`, declares `sessionQuery` as a load-time dependency, and remains inactive until that service is available. A deployment without session query keeps `send_message` and omits the list tool. Neither tool's presence determines whether a delegation tool starts continuable work.
The tool performs no lifecycle routing — residency and cold resume belong to the subagent service. It passes `exec.agent` as the exact live parent that authorizes delivery and attributes every message as durable provenance `{ kind: 'coordinator', senderSessionId: parent.id }`, which the service retains but never treats as authority. Every message becomes the subagent's next FIFO turn through `Agent.followup()`: if the child is still working, the message waits until its current turn finishes, so it cannot redirect work already underway. The tool forwards its execution signal, which owns admission only until inbox acceptance; once the child accepts the message the accepted turn cannot be cancelled through this tool. The child does not reply to the sender — its transcript by that id is the source of what it did. A delivery failure becomes an errored tool result stating the message was not delivered.

View File

@@ -2,7 +2,7 @@
[English](README.md) | 中文
可选的全局具名 `send_message``list_agents` 工具是 `ctx.subagents` 之上的轻量适配器。绑定提供方的 `@deepseek-ai/dsh-tool-subagent` 实例会为每种传输注册不同的委派工具;这个单独加载的包只注册一次共享控制工具,因此多个委派工具绝不会重复注册全局控制工具。根插件注册 `send_message`,且只要求 `subagents`;可单独加载的 `./list-agents` 插件注册 `list_agents`并在加载时额外要求 `sessionQuery`。没有会话查询服务的部署可保留 `send_message` 并省略列表工具。是否加载这些工具不会决定委派工具是否启动可继续工作。
可选的全局具名 `send_message``list_agents` 工具是 `ctx.subagents` 之上的轻量适配器。绑定提供方的 `@deepseek-ai/dsh-tool-subagent` 实例会为每种传输注册不同的委派工具;这个单独加载的包只注册一次共享控制工具,因此多个委派工具绝不会重复注册全局控制工具。根插件注册 `send_message`,且只要求 `subagents`;可单独加载的 `./list-agents` 插件注册 `list_agents` `sessionQuery` 声明为加载时依赖,并在该服务可用前保持未激活状态。没有会话查询服务的部署可保留 `send_message` 并省略列表工具。是否加载这些工具不会决定委派工具是否启动可继续工作。
本工具不执行生命周期路由——驻留与冷恢复归 subagent 服务所有。它将 `exec.agent` 作为授权投递的准确实时父级传入,并把每条消息的来源标记为持久化来源 `{ kind: 'coordinator', senderSessionId: parent.id }`;服务会保留该来源,但绝不将其视为权限。每条消息都会通过 `Agent.followup()` 成为子 agent智能体的下一个 FIFO 轮次:如果子 agent 仍在工作,该消息会等待其当前轮次结束,因此无法重定向已经在进行的工作。本工具会转发其执行信号,该信号只在 inbox 接受之前掌管准入;一旦子 agent 接受消息,已接受的轮次便无法再通过本工具取消。子 agent 不会回复发送方——通过该 id 查看其 transcript 即是其所做工作的来源。投递失败会变为出错的工具结果,并明确说明消息未送达。

View File

@@ -4,7 +4,7 @@
* separately loadable from the
* root `send_message` plugin because it additionally requires the session
* query service — a deployment may use `send_message` without loading session
* query, and this plugin catches that misconfiguration at load.
* query, and this plugin remains inactive until that service is available.
* @module @deepseek-ai/dsh-tool-subagent-control/list-agents
*/