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

@@ -202,7 +202,6 @@ A long-running command started with `start()` is tracked as a `BashTask`. `BashT
```ts type-equiv
interface BashTask {
readonly id: BashTaskId
readonly command: string
status: BashTaskStatus
/** Exit code once finished (null = killed by signal / still running). */
exitCode: number | null

View File

@@ -137,7 +137,6 @@ type ToolGuard = (execution: Readonly<ToolExecution>) => string | undefined
```ts type-equiv
interface ToolExecutionResult {
callId: CallId
content: ContentBlock[]
isError: boolean
/**
@@ -167,6 +166,8 @@ interface ToolExecutionResult {
}
```
The result carries only the outcome. Call identity remains on the immutable `ToolExecution` that accompanies it through every hook and on the durable `tool/call` / `tool/result` session events, so wrappers cannot create a second, disagreeing identity.
The registry materializes and freezes the final accepted result immediately before `tools/result`. Its content, structured error, additional context, and presentation metadata must round-trip losslessly through JSON; an invalid outcome becomes a JSON-safe `isError` result, so the observed live outcome is safe for the later durable `tool/result` append.
Each interception waterfall returns a typed **Decision** (the idiom shared with the `agent/*` seams). `tools/pre-execute` listeners receive `(exec, next)` and return a `PreToolDecision`; `tools/execute` wrappers return a `ToolExecutionResult`; `tools/post-execute` listeners receive `(exec, result, next)` and return a `PostToolDecision`: