Merge remote-tracking branch 'origin/master' into worktree/provider-routed-llm-adapters

# Conflicts:
#	docs/event-producer-consumer.md
This commit is contained in:
Yichen Jiang
2026-07-15 13:30:40 +08:00
170 changed files with 1403 additions and 1067 deletions

View File

@@ -28,7 +28,7 @@
"@deepseek-ai/dsh-session-persistence": "^0.0.1",
"@deepseek-ai/dsh-system-prompt": "^0.0.1",
"@deepseek-ai/dsh-tools": "^0.0.1",
"cordis": "^4.0.0-rc.6"
"cordis": "^4.0.0-rc.7"
},
"dependencies": {
"schemastery": "^3.18.0"
@@ -43,6 +43,6 @@
"@deepseek-ai/dsh-session-persistence-jsonl": "workspace:^",
"@deepseek-ai/dsh-system-prompt": "workspace:^",
"@deepseek-ai/dsh-tools": "workspace:^",
"cordis": "^4.0.0-rc.6"
"cordis": "^4.0.0-rc.7"
}
}

View File

@@ -569,7 +569,8 @@ async function runStep(
})
session.append('tool/result', {
turn, step,
// Preserve transcript pairing even if a post-execute listener returns another id.
// Correlation comes from the immutable execution input; the result does
// not duplicate this authoritative transcript identity.
callId: call.id,
content: result.content,
isError: result.isError,

View File

@@ -1066,8 +1066,7 @@ describe('tool result call identity', () => {
// A post-execute listener transforms the result (accept-with-replacement).
// The loop must still record the tool/result under the model's authoritative
// call.id (the loop ignores result.callId — which the registry always sets to
// exec.callId anyway — and uses call.id, the model-transcript id).
// call.id, which is the immutable identity carried by the execution input.
ctx.on('tools/post-execute', (exec, _result) => {
expect(exec.callId).toBe(CallId('c1')) // the loop passed the real id in
return Promise.resolve({ kind: 'accept', content: [{ type: 'text', text: 'ok' }] })
@@ -1077,8 +1076,7 @@ describe('tool result call identity', () => {
send(agent, 'use tool')
await waitForIdle(ctx, agent)
// The logged tool/result.callId is the originating call.id, NOT the
// listener's wrong id.
// The logged tool/result.callId is the originating call.id.
const resultEvent = [...agent.session.events].find(e => e.type === 'tool/result')
expect(resultEvent?.type).toBe('tool/result')
if (resultEvent?.type === 'tool/result') {