feat(tools): live dispatch lifecycle + native-contract parallel sub-calls in Code Mode

The bridge replaces its serialization queue with a pool that reuses the
native concurrency contract: submissions classify through
registry.executionMode (fail-closed isConcurrencySafe), start strictly in
submission order, overlap up to the validated maxParallelSubCalls config
(default 10; 1 restores serial), and exclusive calls drain the pool, run
alone, and bar later calls. Each started sub-call logs a
tool/code-dispatch-start event at pool entry; the existing
tool/code-dispatch settles the pair (started ⇔ settles exactly once;
abandoned queued calls log neither). SDK prompt guidance now states the
true Promise.all contract — re-recorded across every code/both-mode
snapshot (plus the stale cordis-dynamic-toolchain fixture gaining the
required description arg).

Client: CodeSubCall widens to RunningToolCall | ToolResultNode — starts
land the running shape (rows wear the native running ring), settles
replace in place preserving start order, callTime pairs to the start
time. Fixture emits start/settle pairs; jsdom pins the running sub-row;
runtime specs pin in-place settlement and out-of-order completion.
This commit is contained in:
Tianyi Cui
2026-07-26 06:02:36 +08:00
parent 526651cb88
commit 8a79679489
34 changed files with 1921 additions and 1673 deletions

View File

@@ -144,30 +144,22 @@ function buildAlphaLog(): SessionEvent[] {
data: { turn, step: 0, content: [{ type: 'tool-call', id: callId, name: 'run_code', arguments: args } as ContentBlock], provenance: { provider: 'fixture', model: 'fx-1' } },
})
push({ type: 'tool/call', data: { turn, step: 0, callId, name: 'run_code', arguments: args } })
push({
type: 'tool/code-dispatch',
data: {
parentCallId: callId, subCallId: `${callId}:code:1`, name: 'bash',
arguments: { command: 'ls notes', description: 'List notes' },
isError: false, content: [{ type: 'text', text: 'demo.txt\nnew-demo.txt' }],
},
})
push({
type: 'tool/code-dispatch',
data: {
parentCallId: callId, subCallId: `${callId}:code:2`, name: 'read',
arguments: { path: 'notes/demo.txt' },
isError: false, content: [{ type: 'text', text: 'hello fixture\n' }],
},
})
push({
type: 'tool/code-dispatch',
data: {
parentCallId: callId, subCallId: `${callId}:code:3`, name: 'read',
arguments: { path: 'notes/missing.txt' },
isError: true, content: [{ type: 'text', text: 'Error: ENOENT: notes/missing.txt not found' }],
},
})
const dispatchPair = (n: number, name: string, dispatchArgs: Record<string, unknown>, resultText: string, isError = false): void => {
push({
type: 'tool/code-dispatch-start',
data: { parentCallId: callId, subCallId: `${callId}:code:${n}`, name, arguments: dispatchArgs },
})
push({
type: 'tool/code-dispatch',
data: {
parentCallId: callId, subCallId: `${callId}:code:${n}`, name,
arguments: dispatchArgs, isError, content: [{ type: 'text', text: resultText }],
},
})
}
dispatchPair(1, 'bash', { command: 'ls notes', description: 'List notes' }, 'demo.txt\nnew-demo.txt')
dispatchPair(2, 'read', { path: 'notes/demo.txt' }, 'hello fixture\n')
dispatchPair(3, 'read', { path: 'notes/missing.txt' }, 'Error: ENOENT: notes/missing.txt not found', true)
push({
type: 'tool/result', surfaceOp: 'append',
data: { turn, step: 0, callId, content: text('{"listing":"demo.txt\\nnew-demo.txt","demo":"hello fixture\\n"}'), isError: false },