docs: tighten prose audit after master retarget
This commit is contained in:
@@ -1,34 +1,6 @@
|
||||
/**
|
||||
* The model-facing `subagent` tool: delegate a task to a child agent and return
|
||||
* its final output. Pure schema + lifecycle shaping — every transport concern
|
||||
* lives behind the `ctx.subagents` provider registry
|
||||
* (`@deepseek-ai/dsh-subagent`), so an in-process, ACP, or future A2A backend
|
||||
* swaps in without touching what the model sees.
|
||||
*
|
||||
* Provider selection is config, not model-facing: this plugin is bound to
|
||||
* EXACTLY ONE provider name (`Config.provider`). To expose more than one
|
||||
* transport, load the plugin more than once, each bound to a different provider
|
||||
* — there is no provider/type parameter in the model-facing schema. The model
|
||||
* sees only `{ description, prompt }`.
|
||||
*
|
||||
* The tool DESCRIPTION is derived from the bound provider's conversation-history
|
||||
* descriptor ({@link providerWording}): a fresh-conversation provider (spawn,
|
||||
* ACP) gets the standalone-prompt wording, while a seeded-conversation provider
|
||||
* (fork) tells the model the child already sees the conversation's completed
|
||||
* turns. This descriptor says nothing about Cordis scope, services, tools, or
|
||||
* authority. The tool MIRRORS the
|
||||
* provider's lifecycle via `subagent/provider-added`/`-removed` — it registers
|
||||
* when the provider is (or becomes) available and unregisters when the
|
||||
* provider goes away — so no load-order requirement exists and an HMR reload
|
||||
* of the backend re-derives the wording from the fresh provider.
|
||||
*
|
||||
* Collection is SYNCHRONOUS this cut: `execute` starts a run and awaits
|
||||
* `run.result` inside a `try/finally` that always disposes the run, so the
|
||||
* owned child agent/session is torn down on every path (success, error, abort)
|
||||
* and never leaks as a live idle child. A non-`completed` stop reason maps to an
|
||||
* `isError` tool result (by throwing) rather than returning partial output as
|
||||
* success.
|
||||
*
|
||||
* Provider-bound model tool that delegates to one child agent, awaits its
|
||||
* result, and always disposes the run. Provider lifecycle controls registration.
|
||||
* @module @deepseek-ai/dsh-tool-subagent
|
||||
*/
|
||||
|
||||
@@ -105,16 +77,7 @@ export const Config: z<Config> = z.object({
|
||||
model: z.string(),
|
||||
}).default(undefined as unknown as { model: string }),
|
||||
persona: z.string(),
|
||||
// A schemastery object materializes {} (with [] for nested arrays) when the
|
||||
// key is omitted — for toolFilter that would mean an EMPTY ALLOW-LIST, i.e.
|
||||
// deny-everything, silently. Force the omitted key to stay absent (the same
|
||||
// shape discipline as SystemPrompt's toolOrder); the cast is needed because
|
||||
// .default() expects the object type.
|
||||
// The NESTED arrays get the same treatment as the object itself: a partial
|
||||
// filter ({deny: […]}) must not materialize allow: [] beside it — an empty
|
||||
// allow-list means deny-EVERYTHING, so the materialized default would turn
|
||||
// a deny-one config into deny-all. An EXPLICIT allow: [] (grant-only
|
||||
// children) survives, since only the omitted key defaults to undefined.
|
||||
// Preserve omitted filters and nested lists; an empty allow-list means deny all.
|
||||
toolFilter: z.object({
|
||||
allow: z.array(z.string()).default(undefined as unknown as string[]),
|
||||
deny: z.array(z.string()).default(undefined as unknown as string[]),
|
||||
|
||||
Reference in New Issue
Block a user