- Removes `model` field from task item/schema, TaskParams, and TaskItem types.
- Removes model selector validation, formatting, and approval display logic.
- Updates task tool priority docs to reflect that model is no longer per-call overridable.
- Updates eval agent() helper docs and prompt templates to remove model parameter.
- Updates tests to reflect removal of model override capability.
estimateTokens now charges for serialized anthropicServerTool blocks so context maintenance sees the server-tool payload replayed on the wire; excluded from the compaction floor like other encrypted reasoning.
- Add `resolveFallbackTool` callback to `AgentOptions` and `AgentLoopConfig` that resolves tool calls not found in the advertised set.
- Use the callback as a third lookup step after `name` and `customWireName` match, enabling side transports like `xd://` device mounts.
- Add test coverage verifying the fallback resolves known devices and preserves "not found" errors for unknown names.
- Wire the coding agent's device registry as `resolveFallbackTool` in both `createAgentSession` and `streamAgentSession` paths.
Persisted native server-tool calls and web-search results in assistant content, replayed them only to the issuing Anthropic provider, and retained Umans gateway filtering.
Fixes#6495
- Add `CodexAttestationProvider` hook and `getCodexAttestationHeader` resolver that gates on ChatGPT-OAuth credentials.
- Integrate attestation into WebSocket transport, SSE event stream, and OpenAI compaction requests.
- Wire `setCodexAttestationProvider(generateCodexAttestation)` in model-registry init for OAuth sessions.
Both compaction serializers reproduced prior assistant reasoning as text
bound for a Claude target, tripping Anthropic's reasoning_extraction
refusal and wedging Fable 5 sessions:
- context-full: serializeConversation rendered thinking verbatim inside
<thinking> tags via the anthropic dialect renderer. Now drops thinking
blocks when the summary target dialect is anthropic; other dialects
(e.g. Harmony) keep native reasoning.
- snapcompact: emitted ¶think sections baked into replayed archive
frames. Added an includeThinking serialize option (default true) and
wired the agent session to disable it for Anthropic-dialect models.
Fixes#6093
After an OpenAI remote compaction, prepareCompaction decided whether to
keep the provider-native replay boundary or re-expand its originals by
asking whether *any* compaction candidate (every role model plus the
largest-context available model) shared the payload's provider. In a
multi-role setup where a role such as modelRoles.smol stays on OpenAI,
the check passed forever, so a session switched to a non-OpenAI active
model kept a placeholder-only summary and never recovered the compacted
span for the rest of the session.
Judge reusability against the active model — the one that assembles the
request context every turn — instead of the candidate set. When the
active model cannot replay the payload, re-expand the originals into a
portable local summary, matching the self-healing already present for
single-provider migrations.
Fixes#6343
A steer queued on a session with an empty transcript was undeliverable:
Agent.continue() threw "No messages to continue from" before dequeuing any
steering message, so the RPC idle-drain re-armed continue() on every microtask
(gated only on hasQueuedMessages(), which never cleared) — an unbounded
allocation loop that OOM-killed the process.
continue() now consumes a queued steer/follow-up as the opening turn when the
transcript is empty, mirroring the assistant-tail branch. The queue drains, the
re-arm's hasQueuedMessages() gate goes false, and the loop terminates.
Fixes#6344
- An eval-worktree cherry-pick swept 16 packages/*/node_modules symlinks into the index; 'node_modules/' with a trailing slash only matches directories, so symlinked installs bypassed the ignore. Dropped the slash and removed the tracked links.
Aligns the shim's runtime safeParse/__validator with the wire/tool-call
path, so legacy draft-07 documents (tuple items) accept the same values
validateToolArguments does. Adds a regression test.
The Promise.withResolvers signal resolved inside the scripted model
response fires before the loop can possibly dispatch the tool, so the
parked-state assertions passed even with parking disabled (verified by
simulation: 20/20 green with waitUntilResumed stubbed out). Resolve the
readiness signal from a test-local wrap of agentPauseGate.waitUntilResumed
instead: deterministic (no wall-clock race with the cold yieldIfDue
timer), immune to sibling restoreAllMocks (manual patch, restored in
finally), and a non-parking regression now hangs the await and fails
the test.
A stream that stalls or aborts mid-tool-call ends the assistant turn with
stopReason error/aborted, then appends a synthetic tool_result per un-run
tool call to keep the provider's tool_use/tool_result pairing intact. That
placeholder trailed the failed turn, so AgentSession.retry() — which only
inspected the last message and required role assistant — short-circuited to
false and /retry printed 'Nothing to retry'.
retry() now walks back over trailing synthetic tool results (details
__synthetic true) before the assistant + stopReason check, stripping both
the placeholders and the failed turn. Only synthetic results are skipped, so
a turn whose tools actually ran stays non-retryable. Adds an exported
isSyntheticToolResultMessage guard in agent-loop.ts.
Fixes#6056
Three-piece architecture so subagents inherit async.enabled and
bash.autoBackground.enabled instead of having both force-disabled:
- Owner-routed delivery: AsyncJobManager gains registerDeliverySink /
waitForOwnerJobs; every AgentSession registers a sink for its own agent
id, so background job results inject into the owning agent's run.
Owned deliveries with no live sink dead-letter (result retained on the
job row) instead of misrouting into the first top-level session.
- Quiescence barrier: a subagent's final yield with owner jobs still
running/undelivered is a scheduling pause, not completion. The run
driver notifies the model once (hub wait/cancel), settles owner work,
and folds results in as async-result follow-ups; teardown cancels and
awaits surviving jobs before isolation worktree capture/cleanup.
- Steering soft channel: queued steering no longer hard-aborts
non-interruptible tools; it aborts interruptible waits and raises a
cooperative ToolCallContext.steeringSignal. The mid-batch watch runs
for every batch, and auto-backgroundable bash backgrounds itself on
steer so incoming messages inject promptly with no work lost.
Resolved tool interruptibility from each call's raw arguments so mixed-operation tools can keep side-effecting calls non-interruptible.
Restricted the unified hub to interrupt passive waits and followed logs while preserving start, send, and lifecycle operation results.
Fixes#5995