feat(subagent): activation-based continuable subagents (source)

Replace the Task-backed continuation manager with one durable Session plus at
most one process-local Activation — a residency epoch for a reconstructed child
Agent, not a request, result, cancellation, or Task boundary. The manager owns
activation admission, authority, the live ownership graph, cold resume, and
child-first disposal; the Agent inbox is the only turn FIFO.

- startContinuable() is async and returns { childId, messageId } at inbox
  acceptance; followup() takes a SubagentAuthority and returns AgentMessageId.
- SubagentProvider.resume?(), SubagentProviderResumeRequest, SubagentRun.steer?(),
  SubagentProviderStartRequest and SubagentContinuation are deleted;
  prepareContinuable?() is the continuable-creation capability.
- Cold resume calls ctx.agents.resume() from the manager through a private
  activation-owner scope, never dispatching through a provider.
- Extract shared child composition, descriptor seeding, depth accounting, and
  one-shot run settlement so the manager and one-shot driver keep one home
  per fact.

Tests and docs follow in subsequent commits.
This commit is contained in:
Dudu-0223
2026-07-30 13:26:13 +08:00
committed by Tianyi Cui
parent dabd50e067
commit 26a117f842
15 changed files with 1721 additions and 868 deletions

View File

@@ -9,12 +9,12 @@
import type { Context } from 'cordis'
import z from 'schemastery'
import type {
ContinuableCreateSpec,
SubagentCapabilities,
SubagentProvider,
SubagentProviderResumeRequest,
SubagentProviderStartRequest,
SubagentStartRequest,
} from '@deepseek-ai/dsh-subagent'
import { resumeInProcessRun, startInProcessRun } from '@deepseek-ai/dsh-subagent-inprocess'
import { startInProcessRun } from '@deepseek-ai/dsh-subagent-inprocess'
export const name = 'subagent-spawn'
// `tools` is deliberately not injected: the child factory already provides it during setup,
@@ -45,17 +45,17 @@ class SpawnProvider implements SubagentProvider {
constructor(readonly name: string) {}
start(request: SubagentProviderStartRequest) {
start(request: SubagentStartRequest) {
// Fresh child: no seed. The shared driver mints ids, stamps cwd/lineage/
// depth, drives the one-shot (including the structured capture when the
// request carries an outputSchema), and maps the result.
return startInProcessRun(request, {})
}
resume(request: SubagentProviderResumeRequest) {
// Cold resume reconstructs the persisted child from its own transcript
// under the live parent scope; the shared driver drives the follow-up turn.
return resumeInProcessRun(request)
prepareContinuable(): Promise<ContinuableCreateSpec> {
// A spawned child starts fresh, so it contributes no seed; the continuation
// manager owns every later operation on it.
return Promise.resolve({})
}
}