- The broker heals its store synchronously while serving /v1/usage, but the
remote client snapshot only converges via the background long-poll; the
assertion raced that poll and flaked on slow CI runners.
- Pull one explicit snapshot after fetchUsageReports, matching the sibling
same-deadline re-upsert test.
Provider ids (ZenMux mirrors) and explicit compat.signingEndpoint spec
overrides on opaque proxies now qualify alongside URL-recognized signing
routes; stale-official compat and the Vertex/Copilot header exclusions
are preserved (#6717).
- Excluded effective github-copilot URLs from the interleaved beta path so custom-provider and rerouted Copilot hosts don't send the rejected header.
- Covered a custom provider on a Copilot host omitting the beta.
Fixes#6717
- Classified known signing proxies from the resolved request URL instead of materialized model compat.
- Excluded Vertex rawPredict by URL regardless of provider id.
- Covered canonical-model reroutes and custom-provider Vertex routes.
Fixes#6717
- Sent the interleaved-thinking beta for adaptive models on recognized non-official signing endpoints.
- Covered signing and non-signing proxy header behavior.
- Documented the replay failure fix in the AI changelog.
Fixes#6717
- Stopped dropping /usage limits[] entries with is_active: false. Anthropic marks only the currently binding limit active (an account pinned at a 100% Fable cap reports its 77% shared weekly row as inactive), so is_active signals severity, not bucket existence; filtering on it rendered real utilization as "not reported". Exhaustion gating unchanged: tier rows still hard-block only at confirmed 100% with a future reset.
- Moved the Claude Code fingerprint constants into the leaf module providers/claude-code-fingerprint (star re-exported from providers/anthropic, import paths unchanged). Fixes the providers/anthropic -> stream -> registry -> registry/oauth/anthropic init cycle that TDZ-crashed on claudeCodeVersion whenever providers/anthropic was the first module loaded, which blocked the covering test file.
- PR #6513 strips status from sanitized replay items, which made buildResponsesDeltaInput's strict prefix compare treat raw response output items as history mutations and break previous_response_id chaining on every websocket continuation.
- Prefix identity now ignores the status field on both sides; regression covered by the existing openai-codex-stream websocket delta tests.
Reset text replay metadata whenever the projector enters a new source block, including unsigned terminal-only blocks.
Covered a signed terminal text block followed by an unsigned block to prevent invalid signature carryover.
Fixes#6703
Two defects flagged by review on the final head, both in the new drain/settle
machinery:
- drainInFlightDispatches looped on Promise.all unconditionally. Exec handlers
have no cancellation contract (the bridge calls tool.execute with no signal),
so a hung or long-running tool held the terminal error hostage after Ctrl+C.
The drain now returns once the signal aborts; late results were discarded
after agent_end regardless.
- A host todoSync callback that throws (session persistence on disk failure)
skipped both the paired result and toolcall_end, stranding the live card and
leaving the resolved block to be stripped from rebuilt transcripts. The
callback is now caught and the call settles as a failure carrying the thrown
message.
Both regression tests fail without their fix (the first by hanging the stream).
The entries were appended inside the released 17.1.3 section under a
duplicate '### Fixed' heading, retroactively mutating published release
history while leaving Unreleased empty.
Retained complete native web-search call/result pairs through leaked-thinking projection at their original source anchors.
Kept opaque server-tool blocks atomic during persistence, stripped them on reparent, and covered custom continuations plus compaction retention.
Fixes#6703
describeExecResult treated every `success` oneof variant as a
successful call, but MCP encodes application-level tool failures inside
that variant as McpSuccess.is_error (agent.proto:2058), mirroring the
MCP spec. A handler using the TResult-only form that returned such a
result therefore reached Cursor as a failed tool while the rebuilt
transcript recorded success - the same inconsistency the previous fix
closed for the error/rejected variants.
The success branch now inspects is_error and, when set, flattens the
payload content into the transcript body instead of the generic
placeholder. Image items carry no text, so an all-image failure falls
back to a generic message. McpSuccess is the only *Success message in
agent.proto with an is_error field, so no other shape needs this.
Two P2 findings on the exec-handler path.
1. The success path waits for in-flight exec dispatches before pushing
done, but the catch path did not. When the HTTP/2 completion rejects
while a handler decoded from the last chunk is still running, the
Agent finalizes the synthesized call from the terminal error and
clears its Cursor result buffer; the handler then lands its real
result after agent_end and it is discarded at the next run - even
though the tool may already have performed side effects. The barrier
is now a shared helper and inFlightDispatches is hoisted out of the
try so both exits drain it.
2. resolveExecHandler always synthesized "Tool produced no transcript
result" with isError: false for the TResult-only handler form. A
rejected or error protocol result therefore reached Cursor as a
failure while the rebuilt transcript recorded the same call as
successful. Every exec result is a proto oneof whose only non-failure
variant is success, so describeExecResult() derives the state from
the variant and reuses its own error/reason text - the same string
the server received.