feat(subagent): carry model routing through DSH SDK

This commit is contained in:
pku-xht
2026-08-24 21:38:28 +08:00
parent b44a139ab7
commit 1044db218d
54 changed files with 638 additions and 137 deletions
@@ -1,17 +1,37 @@
import type { Context } from '@deepseek-ai/cordis'
import type { GenerateOptions, StreamChunk } from '@deepseek-ai/dsh-llm'
import { LlmAdapter } from '@deepseek-ai/dsh-llm'
import type { GenerateOptions, LlmResolvedModelInfo, StreamChunk } from '@deepseek-ai/dsh-llm'
import { LlmAdapter, ReasoningEffortId } from '@deepseek-ai/dsh-llm'
/**
* Scripted model for the CHILD runtime: answers every request with its own
* process cwd, so the driving e2e can prove the parent session's workspace
* reached the child process across the SDK wire. `options` carries the
* request; the reply depends only on process state.
* Scripted model for the CHILD runtime: rejects any route drift, then reports
* its effective route and process cwd so the driving evidence observes both
* SDK initialization inputs and the inherited workspace.
*/
class CwdEchoAdapter extends LlmAdapter {
class RouteEchoAdapter extends LlmAdapter {
override resolveModel(provider: string, model: string): Promise<LlmResolvedModelInfo> {
return Promise.resolve({
provider,
id: model,
name: model,
reasoning: {
efforts: [{ id: ReasoningEffortId('max'), name: 'Maximum' }],
},
})
}
async * stream(options: GenerateOptions): AsyncIterable<StreamChunk> {
void options
const reply = `child cwd: ${process.cwd()}`
if (options.provider !== 'mock'
|| options.model !== 'mock-routed'
|| options.reasoningEffort !== 'max'
|| options.maxTokens !== 777) {
throw new Error(`unexpected child route: ${JSON.stringify({
provider: options.provider,
model: options.model,
reasoningEffort: options.reasoningEffort,
maxTokens: options.maxTokens,
})}`)
}
const reply = `child route: mock/mock-routed/max/777; cwd: ${process.cwd()}`
yield { type: 'block-start', index: 0, blockType: 'text' }
yield { type: 'text-delta', index: 0, text: reply }
yield { type: 'block-end', index: 0, block: { type: 'text', text: reply } }
@@ -28,5 +48,5 @@ export const inject = ['llm']
* @param ctx - the plugin context supplying `ctx.llm`.
*/
export function apply(ctx: Context): void {
ctx.llm.registerAdapter(['mock'], new CwdEchoAdapter())
ctx.llm.registerAdapter(['mock'], new RouteEchoAdapter())
}
@@ -1,7 +1,7 @@
# Test-only composition: the SDK subagent backend on the real Loader/app path.
# The scripted model delegates once; the child — a COMPLETE second harness
# runtime speaking stdio JSON-RPC — echoes its process cwd, so parent-session
# cwd inheritance is asserted keylessly end to end across the SDK wire.
# The scripted model selects a child route; the child — a COMPLETE second
# harness runtime speaking stdio JSON-RPC — echoes the effective route and cwd,
# so dynamic routing and parent-session cwd inheritance are asserted keylessly.
# `cwd` is deliberately omitted — the inheritance branch under test. The child
# profile patch and isolated Harness home are machine-absolute, supplied by
# the driving e2e.
@@ -19,8 +19,10 @@
profile: sdk
patches: !!js JSON.parse(process.env.DSH_TEST_CHILD_PATCHES ?? '[]')
dshHome: !!js process.env.DSH_TEST_CHILD_HOME
provider: mock
model: mock-echo
# These defaults are intentionally unavailable in the child composition;
# the model-selected route must replace them before initialize.
provider: unavailable-default
model: unavailable-default
env:
DSH_TELEMETRY_DISABLED: '1'
@@ -29,6 +31,8 @@
config:
provider: dsh-sdk
toolName: subagent
agentOptions:
maxTokens: 777
# The SDK backend advertises no depthLimit: the child harness owns its own
# recursion budget, so the local numeric default cannot apply here.
maxDepth: 'provider-managed'
@@ -1,6 +1,6 @@
import type { Context } from '@deepseek-ai/cordis'
import type { GenerateOptions, StreamChunk } from '@deepseek-ai/dsh-llm'
import { CallId, LlmAdapter } from '@deepseek-ai/dsh-llm'
import type { GenerateOptions, LlmResolvedModelInfo, StreamChunk } from '@deepseek-ai/dsh-llm'
import { CallId, LlmAdapter, ReasoningEffortId } from '@deepseek-ai/dsh-llm'
/**
* Test adapter for the `mock-delegate` model: the first request calls the
@@ -9,6 +9,17 @@ import { CallId, LlmAdapter } from '@deepseek-ai/dsh-llm'
* cwd echo) reaches the parent session log for the driving e2e to assert.
*/
class MockDelegatingAdapter extends LlmAdapter {
override resolveModel(provider: string, model: string): Promise<LlmResolvedModelInfo> {
return Promise.resolve({
provider,
id: model,
name: model,
reasoning: {
efforts: [{ id: ReasoningEffortId('max'), name: 'Maximum' }],
},
})
}
async * stream(options: GenerateOptions): AsyncIterable<StreamChunk> {
const toolResultText = options.messages.at(-1)?.content
.filter(block => block.type === 'tool-result')
@@ -18,7 +29,13 @@ class MockDelegatingAdapter extends LlmAdapter {
.join('') ?? ''
if (toolResultText.length === 0) {
const args = JSON.stringify({ description: 'cwd probe', prompt: 'report your workspace' })
const args = JSON.stringify({
description: 'route probe',
prompt: 'report your route and workspace',
provider: 'mock',
model: 'mock-routed',
reasoning_effort: 'max',
})
yield { type: 'block-start', index: 0, blockType: 'tool-call' }
yield { type: 'tool-call-delta', index: 0, id: CallId('call-delegate'), name: 'subagent', argumentsDelta: args }
yield { type: 'block-end', index: 0, block: { type: 'tool-call', id: CallId('call-delegate'), name: 'subagent', arguments: args } }
@@ -0,0 +1,51 @@
# JSON-RPC snapshot root: a deterministic parent model selects a route for a
# separate SDK child runtime. Both runtimes persist their own request headers.
- id: sdk-jsonrpc-server
name: '@deepseek-ai/dsh-sdk-jsonrpc-server'
- id: mock-llm
name: './mock-delegating-llm.ts'
- id: subagent
name: '@deepseek-ai/dsh-subagent'
- id: subagent-dsh-sdk
name: '@deepseek-ai/dsh-subagent-dsh-sdk'
config:
profile: sdk
patches: !!js JSON.parse(process.env.DSH_TEST_CHILD_PATCHES ?? '[]')
dshHome: !!js process.env.DSH_TEST_CHILD_HOME
provider: unavailable-default
model: unavailable-default
env:
DSH_TELEMETRY_DISABLED: '1'
- id: tool-subagent
name: '@deepseek-ai/dsh-tool-subagent'
config:
provider: dsh-sdk
toolName: subagent
enableRunInBackground: false
agentOptions:
maxTokens: 777
maxDepth: 'provider-managed'
- id: agent-spine
name: '@deepseek-ai/dsh-agent-spine-demo'
config:
persona: 'Test SDK subagent dynamic routing.'
workspaceContext: false
skills:
enabled: false
toolBash:
enableRunInBackground: false
toolJobs: false
- id: sessions
name: '@deepseek-ai/dsh-session-persistence-jsonl'
config:
root: !!js process.env.DSH_SESSION_ROOT
compression: none
- id: session-checkpoints
name: '@deepseek-ai/dsh-session-checkpoint-policy'
@@ -106,7 +106,13 @@ describe('Python SDK dsh profile keyless smoke', () => {
jsonrpc: '2.0',
id: 1,
method: 'initialize',
params: { cwd: root, provider: 'deepseek-official', model: 'deepseek-v4-pro', maxTokens: 1234 },
params: {
cwd: root,
provider: 'deepseek-official',
model: 'deepseek-v4-pro',
reasoningEffort: 'max',
maxTokens: 1234,
},
})}\n`)
const initialized = await waitForLine(lines, value => value.id === 1, () => stderr)
expect(initialized).toMatchObject({
@@ -145,6 +151,7 @@ describe('Python SDK dsh profile keyless smoke', () => {
},
})
const tools = modelRequests[0]?.tools as { function?: { name?: string } }[]
expect(modelRequests[0]?.reasoning_effort).toBe('max')
expect(modelRequests[0]?.max_tokens).toBe(1234)
expect(tools.map(tool => tool.function?.name)).toContain('list_subagent_models')
@@ -45,6 +45,10 @@ const replayPlugin = fileURLToPath(new URL(
: '../../../packages/test-support/llm-replay/src/index.ts',
import.meta.url,
))
const dshSdkFixtureDir = join(testsDir, 'fixtures', 'subagent', 'subagent-dsh-sdk')
const dshSdkSnapshotConfig = join(dshSdkFixtureDir, 'snapshot.cordis.yml')
const dshSdkChildConfig = join(dshSdkFixtureDir, 'child.cordis.yml')
const dshSdkChildMockPath = join(dshSdkFixtureDir, 'child-mock-llm.ts')
const MINIMAL_SYSTEM_PROMPT = 'You are the environment-selected minimal software engineer.'
const MINIMAL_BASH_DESCRIPTION = `Run commands in a bash shell
@@ -71,7 +75,7 @@ interface SdkScenario {
prompt: string
/** Fixed SDK session id, so fixtures and replay binding stay stable. */
sessionId: string
/** How many child sessions the turn persists (subagent scenarios). */
/** How many additional session logs the scenario persists. */
children: number
/** Optional scenario-specific live and replay compositions. */
configs?: { live: string; replay: string }
@@ -79,6 +83,14 @@ interface SdkScenario {
additionalPatches?: { live: readonly string[]; replay: readonly string[] }
/** Environment overrides passed to the runtime subprocess. */
environment?: Readonly<Record<string, string>>
/** SDK initialization route for the root runtime. */
sdkRoute?: { provider: string; model: string }
/** Separate DSH SDK child process and the route its persisted request must prove. */
dshSdkChild?: {
config: string
sessionRoot: string
expectedRoute: Readonly<Record<string, unknown>>
}
/** Cwd-relative files whose final contents are part of the scenario contract. */
expectedFiles?: Readonly<Record<string, string>>
/** Assembled model-facing tool names and required argument keys. */
@@ -111,6 +123,24 @@ const SCENARIOS: SdkScenario[] = [
sessionId: 'sdk-snapshot-subagent',
children: 1,
},
{
name: 'subagent-dsh-sdk-dynamic-route',
prompt: 'Delegate once using the requested child route.',
sessionId: 'sdk-snapshot-dsh-sdk',
children: 1,
configs: { live: dshSdkSnapshotConfig, replay: dshSdkSnapshotConfig },
sdkRoute: { provider: 'mock', model: 'mock-delegate' },
dshSdkChild: {
config: dshSdkChildConfig,
sessionRoot: '.child-dsh/sessions',
expectedRoute: {
provider: 'mock',
model: 'mock-routed',
reasoningEffort: 'max',
maxTokens: 777,
},
},
},
{
name: 'persistent-tools',
prompt: 'Prove that bash state persists. Then create {{cwd}}/note.txt with a tab-indented line, view it, replace that literal tab-indented line, and make the persistent shell exit with code 9.',
@@ -193,6 +223,17 @@ function assembledSystem(log: PersistedLog): string {
return system
}
function assembledRequestConfig(log: PersistedLog): Record<string, unknown> {
const event = log.content.trimEnd().split('\n')
.map(line => JSON.parse(line) as { type?: string; data?: { header?: { config?: unknown } } })
.find(candidate => candidate.type === 'request/header')
const config = event?.data?.header?.config
if (typeof config !== 'object' || config === null || Array.isArray(config)) {
throw new Error('session log has no request/header config')
}
return config as Record<string, unknown>
}
function assembledRuntimeContexts(log: PersistedLog): string[] {
return log.content.trimEnd().split('\n').flatMap((line) => {
const event = JSON.parse(line) as {
@@ -300,6 +341,18 @@ async function runScenario(scenario: SdkScenario): Promise<{
? scenario.additionalPatches?.live ?? []
: scenario.additionalPatches?.replay ?? []
const [parentFixture, ...childFixtures] = replayFixtures
let childEnvironment: Record<string, string> = {}
if (scenario.dshSdkChild !== undefined) {
const childHome = join(cwd, '.child-dsh')
const childPatch = join(childHome, 'child.cordis.yml')
await mkdir(childHome, { recursive: true })
await writeFile(childPatch, (await readFile(scenario.dshSdkChild.config, 'utf8'))
.replace("'./child-mock-llm.ts'", JSON.stringify(pathToFileURL(dshSdkChildMockPath).href)))
childEnvironment = {
DSH_TEST_CHILD_PATCHES: JSON.stringify([childPatch]),
DSH_TEST_CHILD_HOME: childHome,
}
}
const env: Record<string, string> = {
...Object.fromEntries(Object.entries(process.env).filter(([, value]) => value !== undefined)) as Record<string, string>,
DSH_SNAPSHOT: mode,
@@ -310,6 +363,7 @@ async function runScenario(scenario: SdkScenario): Promise<{
...childFixtures.length > 0 ? { DSH_SNAPSHOT_CHILD_FILES: childFixtures.join(delimiter) } : {},
},
...scenario.environment,
...childEnvironment,
}
const harness = new DeepSeekHarness({
@@ -324,8 +378,8 @@ async function runScenario(scenario: SdkScenario): Promise<{
env,
requestTimeoutMs: 110_000,
cwd,
provider: 'deepseek-official',
model: 'deepseek-v4-flash',
provider: scenario.sdkRoute?.provider ?? 'deepseek-official',
model: scenario.sdkRoute?.model ?? 'deepseek-v4-flash',
})
try {
const notifications: HarnessNotification[] = []
@@ -334,7 +388,12 @@ async function runScenario(scenario: SdkScenario): Promise<{
onNotification: (notification) => { notifications.push(notification) },
})
await harness.close()
const logs = await persistedLogs(sessionsRoot)
const logs = (await Promise.all([
persistedLogs(sessionsRoot),
...(scenario.dshSdkChild === undefined
? []
: [persistedLogs(join(cwd, scenario.dshSdkChild.sessionRoot))]),
])).flat()
const observedFiles = Object.fromEntries(await Promise.all(
Object.keys(scenario.expectedFiles ?? {}).map(async (path): Promise<[string, string | MissingFile]> => [
path,
@@ -350,6 +409,10 @@ async function runScenario(scenario: SdkScenario): Promise<{
/** Order logs parent-first, children by creation time (fixture layout order). */
function orderLogs(logs: PersistedLog[], scenario: SdkScenario): PersistedLog[] {
if (scenario.dshSdkChild !== undefined) {
expect(logs).toHaveLength(scenario.children + 1)
return logs
}
const parents = logs.filter(log => typeof log.header.parentSession !== 'string')
const children = logs.filter(log => typeof log.header.parentSession === 'string')
.sort((left, right) => Number(left.header.createdAt) - Number(right.header.createdAt))
@@ -480,7 +543,12 @@ describe('TypeScript SDK snapshots over the jsonrpc runtime', () => {
for (const clause of scenario.runtimeContext.includes) expect(system).not.toContain(clause)
}
}
if (scenario.children > 0) {
if (scenario.dshSdkChild !== undefined) {
const child = ordered[1]
if (child === undefined) throw new Error(`${scenario.name} has no child session log`)
expect(assembledRequestConfig(child)).toEqual(scenario.dshSdkChild.expectedRoute)
}
if (scenario.children > 0 && scenario.dshSdkChild === undefined) {
expect(notifications.some(n => n.method === 'subagent.started')).toBe(true)
expect(notifications.some(n => n.method === 'subagent.finished')).toBe(true)
}
@@ -0,0 +1,28 @@
{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"agent/inbox/spliced","seq":0,"time":0,"data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Delegate once using the requested child route."}],"source":{"kind":"user"},"role":"user","id":"{{sessionId}}"}]}}}}
{"method":"session.status","params":{"sessionId":"{{sessionId}}","status":"running"}}
{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"turn/start","seq":1,"time":0,"data":{"turn":1}}}}
{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"agent/inbox/spliced","seq":2,"time":0,"data":{"target":"next-turn","start":0,"removedCount":1,"inserted":[]}}}}
{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"step/start","seq":3,"time":0,"data":{"turn":1,"step":1}}}}
{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"user/message","seq":4,"time":0,"data":{"content":[{"type":"text","text":"Delegate once using the requested child route."}],"source":{"kind":"user"},"role":"user","id":"{{sessionId}}"},"surfaceOp":"append"}}}
{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"session/title","seq":5,"time":0,"data":{"title":"Delegate once using the requested","messageSeqs":[4],"source":{"kind":"fallback"}}}}}
{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"request/header","seq":6,"time":0,"data":{"header":{"config":{"provider":"mock","model":"mock-delegate"},"system":"{{system}}","tools":"{{tools}}"},"reason":"initial"}}}}
{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"request/context","seq":7,"time":0,"data":{"provider":"mock","model":"mock-delegate"}}}}
{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/chunk","seq":8,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}}}}}
{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/chunk","seq":9,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":0,"id":"call-delegate","name":"subagent","argumentsDelta":"{\"description\":\"route probe\",\"prompt\":\"report your route and workspace\",\"provider\":\"mock\",\"model\":\"mock-routed\",\"reasoning_effort\":\"max\"}"}}}}}
{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/chunk","seq":10,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call-delegate","name":"subagent","arguments":"{\"description\":\"route probe\",\"prompt\":\"report your route and workspace\",\"provider\":\"mock\",\"model\":\"mock-routed\",\"reasoning_effort\":\"max\"}"}}}}}}
{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/chunk","seq":11,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}}}}}
{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/chunk","seq":12,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}}}}
{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/message","seq":13,"time":0,"data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"tool-call","id":"call-delegate","name":"subagent","arguments":"{\"description\":\"route probe\",\"prompt\":\"report your route and workspace\",\"provider\":\"mock\",\"model\":\"mock-routed\",\"reasoning_effort\":\"max\"}"}],"source":{"kind":"model","provider":"mock","model":"mock-delegate"},"id":"{{sessionId}}"},"usage":{"inputTokens":10,"outputTokens":5}},"sourceEventSeqs":[8,9,10,11,12],"surfaceOp":"append"}}}
{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"tool/call","seq":14,"time":0,"data":{"turn":1,"step":1,"callId":"call-delegate","name":"subagent","arguments":"{\"description\":\"route probe\",\"prompt\":\"report your route and workspace\",\"provider\":\"mock\",\"model\":\"mock-routed\",\"reasoning_effort\":\"max\"}"}}}}
{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"tool/result","seq":15,"time":0,"data":{"turn":1,"step":1,"message":{"source":{"kind":"tool","callId":"call-delegate"},"content":[{"type":"tool-result","toolCallId":"call-delegate","content":[{"type":"text","text":"child route: mock/mock-routed/max/777; cwd: {{cwd}}"}],"isError":false}],"role":"user","id":"{{sessionId}}"}},"sourceEventSeqs":[14],"surfaceOp":"append"}}}
{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"step/end","seq":16,"time":0,"data":{"turn":1,"step":1}}}}
{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"step/start","seq":17,"time":0,"data":{"turn":1,"step":2}}}}
{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/chunk","seq":18,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"block-start","index":0,"blockType":"text"}}}}}
{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/chunk","seq":19,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"text-delta","index":0,"text":"child reported:\nchild route: mock/mock-routed/max/777; cwd: {{cwd}}"}}}}}
{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/chunk","seq":20,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"child reported:\nchild route: mock/mock-routed/max/777; cwd: {{cwd}}"}}}}}}
{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/chunk","seq":21,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":167}}}}}}
{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/chunk","seq":22,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"finish","reason":{"kind":"stop"}}}}}}
{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"assistant/message","seq":23,"time":0,"data":{"turn":1,"step":2,"message":{"role":"assistant","content":[{"type":"text","text":"child reported:\nchild route: mock/mock-routed/max/777; cwd: {{cwd}}"}],"source":{"kind":"model","provider":"mock","model":"mock-delegate"},"id":"{{sessionId}}"},"usage":{"inputTokens":10,"outputTokens":167}},"sourceEventSeqs":[18,19,20,21,22],"surfaceOp":"append"}}}
{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"step/end","seq":24,"time":0,"data":{"turn":1,"step":2}}}}
{"method":"session.event","params":{"sessionId":"{{sessionId}}","event":{"type":"turn/end","seq":25,"time":0,"data":{"turn":1,"reason":{"kind":"completed"}}}}}
{"method":"session.status","params":{"sessionId":"{{sessionId}}","status":"idle"}}
@@ -0,0 +1 @@
{"sessionId":"{{sessionId}}","finalResponse":"child reported:\nchild route: mock/mock-routed/max/777; cwd: {{cwd}}"}
@@ -0,0 +1,17 @@
{"type":"session","version":0,"id":"session-d9caef61eced4f94a2d4f6265020896e","createdAt":1787254273406,"cwd":"{{cwd}}","delegationDepth":0}
{"type":"agent/inbox/spliced","seq":0,"time":1787254273407,"data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"report your route and workspace"}],"source":{"kind":"user"},"role":"user","id":"18ece5d3-8dc4-4841-bc67-3287b1eb8ab2"}]}}
{"type":"turn/start","seq":1,"time":1787254273408,"data":{"turn":1}}
{"type":"agent/inbox/spliced","seq":2,"time":1787254273408,"data":{"target":"next-turn","start":0,"removedCount":1,"inserted":[]}}
{"type":"step/start","seq":3,"time":1787254273432,"data":{"turn":1,"step":1}}
{"type":"user/message","seq":4,"time":1787254273432,"data":{"content":[{"type":"text","text":"report your route and workspace"}],"source":{"kind":"user"},"role":"user","id":"18ece5d3-8dc4-4841-bc67-3287b1eb8ab2"},"surfaceOp":"append"}
{"type":"session/title","seq":5,"time":1787254273433,"data":{"title":"report your route and workspace","messageSeqs":[4],"source":{"kind":"fallback"}}}
{"type":"request/header","seq":6,"time":1787254273433,"data":{"header":{"config":{"provider":"mock","model":"mock-routed","reasoningEffort":"max","maxTokens":777},"system":"{{system}}","tools":"{{tools}}"},"reason":"initial"}}
{"type":"request/context","seq":7,"time":1787254273433,"data":{"provider":"mock","model":"mock-routed"}}
{"type":"assistant/chunk","seq":8,"time":1787254273438,"data":{"turn":1,"step":1,"chunk":{"type":"block-start","index":0,"blockType":"text"}}}
{"type":"assistant/chunk","seq":9,"time":1787254273438,"data":{"turn":1,"step":1,"chunk":{"type":"text-delta","index":0,"text":"child route: mock/mock-routed/max/777; cwd: {{cwd}}"}}}
{"type":"assistant/chunk","seq":10,"time":1787254273438,"data":{"turn":1,"step":1,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"child route: mock/mock-routed/max/777; cwd: {{cwd}}"}}}}
{"type":"assistant/chunk","seq":11,"time":1787254273438,"data":{"turn":1,"step":1,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":151}}}}
{"type":"assistant/chunk","seq":12,"time":1787254273438,"data":{"turn":1,"step":1,"chunk":{"type":"finish","reason":{"kind":"stop"}}}}
{"type":"assistant/message","seq":13,"time":1787254273438,"data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"text","text":"child route: mock/mock-routed/max/777; cwd: {{cwd}}"}],"source":{"kind":"model","provider":"mock","model":"mock-routed"},"id":"0f6dd3aa-2d48-4c64-9130-4812a99e1e31"},"usage":{"inputTokens":3,"outputTokens":151}},"sourceEventSeqs":[8,9,10,11,12],"surfaceOp":"append"}
{"type":"step/end","seq":14,"time":1787254273438,"data":{"turn":1,"step":1}}
{"type":"turn/end","seq":15,"time":1787254273438,"data":{"turn":1,"reason":{"kind":"completed"}}}
@@ -0,0 +1,27 @@
{"type":"session","version":0,"id":"sdk-snapshot-dsh-sdk","createdAt":1787254272178,"cwd":"{{cwd}}","delegationDepth":0}
{"type":"agent/inbox/spliced","seq":0,"time":1787254272180,"data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Delegate once using the requested child route."}],"source":{"kind":"user"},"role":"user","id":"7f17592a-8a93-4bb4-851c-f5e942372b06"}]}}
{"type":"turn/start","seq":1,"time":1787254272180,"data":{"turn":1}}
{"type":"agent/inbox/spliced","seq":2,"time":1787254272180,"data":{"target":"next-turn","start":0,"removedCount":1,"inserted":[]}}
{"type":"step/start","seq":3,"time":1787254272210,"data":{"turn":1,"step":1}}
{"type":"user/message","seq":4,"time":1787254272210,"data":{"content":[{"type":"text","text":"Delegate once using the requested child route."}],"source":{"kind":"user"},"role":"user","id":"7f17592a-8a93-4bb4-851c-f5e942372b06"},"surfaceOp":"append"}
{"type":"session/title","seq":5,"time":1787254272211,"data":{"title":"Delegate once using the requested","messageSeqs":[4],"source":{"kind":"fallback"}}}
{"type":"request/header","seq":6,"time":1787254272211,"data":{"header":{"config":{"provider":"mock","model":"mock-delegate"},"system":"{{system}}","tools":"{{tools}}"},"reason":"initial"}}
{"type":"request/context","seq":7,"time":1787254272211,"data":{"provider":"mock","model":"mock-delegate"}}
{"type":"assistant/chunk","seq":8,"time":1787254272214,"data":{"turn":1,"step":1,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}}}
{"type":"assistant/chunk","seq":9,"time":1787254272215,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":0,"id":"call-delegate","name":"subagent","argumentsDelta":"{\"description\":\"route probe\",\"prompt\":\"report your route and workspace\",\"provider\":\"mock\",\"model\":\"mock-routed\",\"reasoning_effort\":\"max\"}"}}}
{"type":"assistant/chunk","seq":10,"time":1787254272215,"data":{"turn":1,"step":1,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"call-delegate","name":"subagent","arguments":"{\"description\":\"route probe\",\"prompt\":\"report your route and workspace\",\"provider\":\"mock\",\"model\":\"mock-routed\",\"reasoning_effort\":\"max\"}"}}}}
{"type":"assistant/chunk","seq":11,"time":1787254272215,"data":{"turn":1,"step":1,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}}}
{"type":"assistant/chunk","seq":12,"time":1787254272215,"data":{"turn":1,"step":1,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}}
{"type":"assistant/message","seq":13,"time":1787254272215,"data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"tool-call","id":"call-delegate","name":"subagent","arguments":"{\"description\":\"route probe\",\"prompt\":\"report your route and workspace\",\"provider\":\"mock\",\"model\":\"mock-routed\",\"reasoning_effort\":\"max\"}"}],"source":{"kind":"model","provider":"mock","model":"mock-delegate"},"id":"09f8526a-e0ff-493f-8f43-b7f6b5558541"},"usage":{"inputTokens":10,"outputTokens":5}},"sourceEventSeqs":[8,9,10,11,12],"surfaceOp":"append"}
{"type":"tool/call","seq":14,"time":1787254272215,"data":{"turn":1,"step":1,"callId":"call-delegate","name":"subagent","arguments":"{\"description\":\"route probe\",\"prompt\":\"report your route and workspace\",\"provider\":\"mock\",\"model\":\"mock-routed\",\"reasoning_effort\":\"max\"}"}}
{"type":"tool/result","seq":15,"time":1787254273451,"data":{"turn":1,"step":1,"message":{"source":{"kind":"tool","callId":"call-delegate"},"content":[{"type":"tool-result","toolCallId":"call-delegate","content":[{"type":"text","text":"child route: mock/mock-routed/max/777; cwd: {{cwd}}"}],"isError":false}],"role":"user","id":"321d12a1-7801-4614-b800-c8c7ff267f52"}},"sourceEventSeqs":[14],"surfaceOp":"append"}
{"type":"step/end","seq":16,"time":1787254273451,"data":{"turn":1,"step":1}}
{"type":"step/start","seq":17,"time":1787254273455,"data":{"turn":1,"step":2}}
{"type":"assistant/chunk","seq":18,"time":1787254273459,"data":{"turn":1,"step":2,"chunk":{"type":"block-start","index":0,"blockType":"text"}}}
{"type":"assistant/chunk","seq":19,"time":1787254273460,"data":{"turn":1,"step":2,"chunk":{"type":"text-delta","index":0,"text":"child reported:\nchild route: mock/mock-routed/max/777; cwd: {{cwd}}"}}}
{"type":"assistant/chunk","seq":20,"time":1787254273460,"data":{"turn":1,"step":2,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"child reported:\nchild route: mock/mock-routed/max/777; cwd: {{cwd}}"}}}}
{"type":"assistant/chunk","seq":21,"time":1787254273460,"data":{"turn":1,"step":2,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":167}}}}
{"type":"assistant/chunk","seq":22,"time":1787254273460,"data":{"turn":1,"step":2,"chunk":{"type":"finish","reason":{"kind":"stop"}}}}
{"type":"assistant/message","seq":23,"time":1787254273460,"data":{"turn":1,"step":2,"message":{"role":"assistant","content":[{"type":"text","text":"child reported:\nchild route: mock/mock-routed/max/777; cwd: {{cwd}}"}],"source":{"kind":"model","provider":"mock","model":"mock-delegate"},"id":"373cadb7-313d-44e7-a31a-ec0a675e0255"},"usage":{"inputTokens":10,"outputTokens":167}},"sourceEventSeqs":[18,19,20,21,22],"surfaceOp":"append"}
{"type":"step/end","seq":24,"time":1787254273460,"data":{"turn":1,"step":2}}
{"type":"turn/end","seq":25,"time":1787254273460,"data":{"turn":1,"reason":{"kind":"completed"}}}