refactor(subagent): drop the agentType lifecycle field
Address review: `agentType` was a Claude-Code concept (`subagent_type`) that does not fit our own subagent seam — nothing in the harness interprets it, and its only consumer was the CC-dialect hook bridge. Rather than let a foreign concept sit on the core seam, remove it: - `SubagentStartRequest`, `SubagentRunInfo`, `SubagentRunEndInfo`: drop the `agentType` field; the `subagent/start`/`subagent/end` payloads now carry `provider`/`id` (+ end `stopReason`/`lastAssistantMessage`) only. - `dsh-tool-subagent`: drop `Config.agentType` and its request plumbing. - Tests: keep the lastAssistantMessage / clone-containment / reject-path coverage (rewritten to not assert agentType); delete the two tool-subagent tests that only exercised agentType forwarding (dead behavior). - Docs: retitle + rewrite the subagent-observe-enrich RFC to the one shipped enrichment (lastAssistantMessage), with a note on why agentType was dropped; update rfc/README index title, both subagent READMEs, and the core-data-structures/subagent.md type-equiv block + prose; regenerate catalog. The CC bridge (PR-F) will feed Claude Code's own default matcher value "general-purpose" for its SubagentStart/Stop agent_type matcher instead.
This commit is contained in:
@@ -20,9 +20,9 @@
|
||||
* semantics are deferred to a future redesign that unifies long-running-tool
|
||||
* handling across subagents and bash.
|
||||
*
|
||||
* The `subagent/start` / `subagent/end` lifecycle events carry an enriched but
|
||||
* OBSERVE-ONLY payload (`agentType`, and on end `lastAssistantMessage`) — see
|
||||
* `docs/rfc/implemented/feature/2026-06-30-subagent-observe-enrich.md`.
|
||||
* The `subagent/start` / `subagent/end` lifecycle events carry an OBSERVE-ONLY
|
||||
* payload; `subagent/end` additionally carries the child's `lastAssistantMessage`
|
||||
* — see `docs/rfc/implemented/feature/2026-06-30-subagent-observe-enrich.md`.
|
||||
* FIXME(subagent-continuation): a control-flow `subagent/end` (an awaited
|
||||
* waterfall returning a stop/continue decision, like the other interception
|
||||
* seams) would require reshaping this emit into a waterfall, awaiting listeners
|
||||
@@ -82,13 +82,6 @@ export interface SubagentRunInfo {
|
||||
provider: string
|
||||
/** The child agent's id. */
|
||||
id: AgentId
|
||||
/**
|
||||
* The caller's subagent-kind label, carried verbatim from
|
||||
* {@link SubagentStartRequest.agentType} (Claude Code's `subagent_type`).
|
||||
* Absent when the caller did not supply one. An observer (a hooks bridge,
|
||||
* a UI) reports or matches on it; the seam never interprets it.
|
||||
*/
|
||||
agentType?: string
|
||||
}
|
||||
|
||||
/** Outcome detail for a settled subagent run (the `subagent/end` payload). */
|
||||
@@ -97,8 +90,6 @@ export interface SubagentRunEndInfo {
|
||||
provider: string
|
||||
/** The child agent's id. */
|
||||
id: AgentId
|
||||
/** The caller's subagent-kind label (see {@link SubagentRunInfo.agentType}). */
|
||||
agentType?: string
|
||||
/** The terminal stop reason. */
|
||||
stopReason: SubagentResult['stopReason']
|
||||
/**
|
||||
@@ -187,10 +178,7 @@ export class SubagentService extends Service {
|
||||
// acceptable. `ctx.emit` halts the dispatch on the first throw, so a single
|
||||
// surrounding try/catch is not enough — each listener is invoked and
|
||||
// contained individually.
|
||||
// Carry the caller's subagent-kind label verbatim onto both lifecycle events
|
||||
// (absent when not supplied — the spread omits the key for exactOptionalPropertyTypes).
|
||||
const agentType = request.agentType !== undefined ? { agentType: request.agentType } : {}
|
||||
this.emitLifecycle('subagent/start', { provider: name, id: run.id, ...agentType })
|
||||
this.emitLifecycle('subagent/start', { provider: name, id: run.id })
|
||||
// Emit `subagent/end` when the run settles. The result promise does not
|
||||
// reject on a child-level failure (it resolves with stopReason 'error'),
|
||||
// so a rejection here is an infrastructure fault — surface its stop reason
|
||||
@@ -220,9 +208,9 @@ export class SubagentService extends Service {
|
||||
} catch (error: unknown) {
|
||||
this.ctx.logger.warn(`subagent: could not clone ${name} output for subagent/end: ${String(error)}`)
|
||||
}
|
||||
this.emitLifecycle('subagent/end', { provider: name, id: run.id, ...agentType, stopReason: result.stopReason, ...lastAssistantMessage !== undefined ? { lastAssistantMessage } : {} })
|
||||
this.emitLifecycle('subagent/end', { provider: name, id: run.id, stopReason: result.stopReason, ...lastAssistantMessage !== undefined ? { lastAssistantMessage } : {} })
|
||||
},
|
||||
() => { this.emitLifecycle('subagent/end', { provider: name, id: run.id, ...agentType, stopReason: 'error' }) },
|
||||
() => { this.emitLifecycle('subagent/end', { provider: name, id: run.id, stopReason: 'error' }) },
|
||||
)
|
||||
return run
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user