AWS documents prompt caching for Nova Micro/Lite/Pro under their in-region
model IDs as well; the allowlist covered only the us. geo profiles (Premier
already had both forms). Regional/provisioned-throughput configs using base
IDs now emit the documented default-5m checkpoints.
The queue-level dispatch of issue events had no test at all; a revert of
the reopened mapping in WorkerPool._dispatch would silently reintroduce
the routing gap #5891 fixes. Mirrors the existing PR-review dispatch
test convention.
Streamed PCM kept for the nonzero-exit replay is now dropped once the
utterance exceeds 60s (~5.8 MB at 24 kHz mono f32): the recovered failure
is a short clip that fits the pipe buffer before a broken backend dies,
while replaying a long already-played utterance would duplicate audio and
unbounded retention would defeat streaming for long input.
Codex P2 on #6403: sendRequest rejected with only the server's error
message; a server answering rust-analyzer/reloadWorkspace with code
-32601 but nonstandard text (e.g. "Unknown request") would fail
isMethodNotFoundError and turn lsp reload into a hard error instead of
falling back to the generic reload. Include the code in the rejection
message so the existing -32601 substring check matches. Adds a
regression test with a -32601/"Unknown request" response.
Bash treats \" inside a backtick substitution nested in double quotes as
a quote delimiter for the inner command; the generic backslash-skip made
isInsideShellQuote report such quoted literals as unquoted, wrongly
expanding internal URLs inside them (Codex P2 review finding).
Callback flows now bind 127.0.0.1 for localhost; macOS lets a
specific-address bind coexist with the blocker's 0.0.0.0 wildcard bind, so
the fallback path never triggered. Contest the same interface.
An error redirect carrying the expected state nonce comes from the genuine
authorization flow (e.g. the user denied the consent screen); leaving it
unsettled stalled loopback logins for the full 5-minute timeout. Reject the
callback promise for those, while still ignoring forgeable errors without
the expected state (#4106).
A single hung/slow poll now aborts with TimeoutError after 30s; without
this, that one timeout escaped #waitForSmitheryCliApiKey and dropped the
browser login to the manual API-key fallback instead of retrying until
the 5-minute deadline. Catch isTimeoutError in the poll loop and
continue; export SmitheryCliPollResponse to type the retried response.
- Removed the logic that forced a minimum context window of 372k for GPT-5.6 SKUs when upstream actively reported lower values.
- Updated Codex discovery to treat 372k as a fallback only when upstream omits the context window.
Fixes#6371
- Convert the hub tool renderer to a lazy getter to prevent initialization-order temporal dead zone issues.
- Add session move support to the fake ACP builtin session runtime.
parseBlobRef sliced the blob:sha256: suffix and returned it unvalidated;
get/getSync then fed it into path.join(this.dir, hash), so a crafted ref
like blob:sha256:../../../etc/passwd escaped the blob directory and read
arbitrary files into resolved image history (base64, raw UTF-8, and the ACP
sync path).
Reject any suffix that is not a canonical 64-char lowercase hex hash in
parseBlobRef, the single choke point for every resolution entry point. Reuse
the shared BLOB_HASH_RE in gc-cli instead of its duplicate HASH_RE.
Fixes#4088
#ensureDir checked #initialized then set it across an await
#scanExistingIds() gap, so two concurrent first-use save/allocatePath
callers both re-seeded #nextId=maxId+1 and allocateId() handed both the
same id — silently overwriting the first artifact (same toolType) or
making artifact:// resolution ambiguous (different toolTypes).
Memoize the initial scan as a single in-flight #initPromise so all
concurrent callers share one initialization and receive distinct ids.
Fixes#4091
MCP OAuth endpoint discovery ran metadata, well-known, and recursive
authorization-server fetches with no AbortSignal, and the Smithery
browser-login poll received a never-aborting signal. An endpoint that
accepts the TCP connection but never responds stalled /mcp add,
/mcp reauth, the add wizard, or /mcp smithery-login indefinitely; the
5-minute login/poll deadlines run only after discovery resolves or
between polls, so a hung fetch never reached them.
- discoverOAuthEndpoints and fetchResourceMetadataScopes gain an optional
signal and wrap every fetch in withTimeoutSignal(DISCOVERY_FETCH_TIMEOUT_MS,
opts?.signal), threaded through the recursive authorization_servers call.
- pollSmitheryCliAuthSession wraps its fetch in
withTimeoutSignal(SMITHERY_POLL_TIMEOUT_MS, signal) so a hung poll aborts
and the loop reaches its 5-minute deadline.
Fixes#4103
Every exported read-modify-write on mcp.json (add/update/remove server, disabled/force-enabled lists) now runs under a per-file withFileLock, so overlapping in-process or cross-process mutations no longer lose updates. writeMCPConfigFile writes to a pid+uuid temp file instead of a shared ${filePath}.tmp, so concurrent writers cannot rename each other's temp out from under them (ENOENT / clobber).
Fixes#4104
Kept the callback promise pending after malformed, denied, or state-mismatched requests so a legitimate browser redirect can still complete login.
Bound localhost callback servers explicitly to 127.0.0.1 instead of Bun's all-interface default.
Fixes#4106
`omp say` for a short single-segment clip printed `spoke` but produced no
sound on hosts where the first streaming backend (bundled ffmpeg without a
pulse/alsa output device) spawns then exits nonzero. The single pipe write
succeeds into the OS buffer before the backend dies, so the drain's
broken-pipe replay never fires, and `player.end()` sets `#inputClosed`
before the exit lands, so the early-exit handler short-circuits and never
advances to paplay/aplay. The end-of-stream cleanup awaited the exit but
ignored its code.
StreamingAudioPlayer now retains the utterance PCM and, when the streaming
backend exits nonzero, replays it through per-file playback so short clips
still reach the speakers. Added injectable backend/file-playback seams and a
regression test exercising the nonzero-exit, clean-exit, and no-backend
paths.
Fixes#5875
Status presenters (showWarning/showError/showStatus and extension/tool
error presenters) baked theme.fg() into Text at construction, so a
warning shown while the auto-theme default guess was dark kept the
dark-mode color after async appearance detection switched the active
theme to light — dark-catppuccin Mocha yellow on the light Latte
background (1.12:1 contrast, effectively invisible).
Add Text.setStyleFn(), a foreground styler evaluated at render time, and
route the transient status presenters through it. Because the coding
agent invalidates status components on onThemeChange, a theme swap now
re-shapes them against the live theme instead of replaying the palette
active when they were constructed.
Fixes#6337
isInsideShellQuote opened an expansion context for $() command
substitution but never tracked legacy backtick substitution, so an
unquoted skill:// (or other supported scheme) nested directly inside a
backtick pair within double quotes kept the outer quote active and was
left literal. Treat an unescaped backtick as an expansion-context
boundary on the same substitution stack, restoring the outer quote when
the pair closes, matching $() behavior including nesting in either
order. Single-quoted and escaped-backtick text stay literal.
Fixes#5645
The finalized-issue boilerplate promises "reopen and I'll triage again from
scratch," but github_events.route() dropped issues.reopened to the ignored
skip branch (only opened/closed handled), while pull_request.reopened was
already routed. A user following the instruction got silence.
Route issues.reopened like issues.opened (submitter-attributable triage_issue,
same per-user rate budget) and dispatch it in queue._dispatch(). triage_issue
now tears down a stale finalized workspace (merged/closed/abandoned) before
re-provisioning, mirroring the maintainer directive-reopen teardown so the
re-triage branches afresh from default instead of a merged/deleted branch.
Fixes#5891
- Shared unique workspace suffix resolution between read and direct edit modes.
- Preserved create destinations and ambiguous-path failures while resolving existing update targets.
- Added direct replace, patch, and apply_patch regression coverage.
Fixes#6359
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
The browser tool's open action only passed the requested timeout to acquireTab; acquireBrowser ran under the caller signal alone, so CDP discovery/connect could run through its own fixed 5s/30s waits past the requested deadline. A freshly-created browser also sat in the registry at refCount 0 during worker/surface acquisition: the worker-abort branch released it only on tempHold (never on the fresh refCount-0 case), orphaning the handle, and two different-name opens sharing one refCount-0 browser let a single failure dispose it out from under the survivor.
Compose one open deadline from the caller signal and params.timeout and thread it through both acquireBrowser and acquireTab; caller cancellation stays ToolAbortError, the requested timeout becomes a timeout ToolError. Hold one explicit registry lease across tab acquisition, released exactly once on the mutually-exclusive success/rollback paths, and make the worker-abort browser release mirror the error paths' refCount-0 check.
Fixes#6365
Tracked retained Python kernel generations and shared one replacement promise per dead generation. Reset and disposal now invalidate and drain replacement work before allowing a new session to take ownership.
Added deterministic fake-kernel coverage for concurrent callers, cancellation, reset, owner/global disposal, and independent cwd keys.
Fixes#6367
- discarding a Settings instance (test reset, re-init) now disarms its
debounced save timers and refuses chained background writes, so a
dropped instance can never race a successor's file locks
- resetSettingsForTest sweeps a weak registry of ALL constructed
instances, covering isolated (non-singleton) instances too
- fixes deterministic cross-file failure of the model-role replay test
when settings-reload-cwd ran first in the same process
reloadServer caught every error from both fallback mechanisms in bare
catch blocks, so a caller cancel or tool timeout was swallowed and fell
through to `proc.kill(); return "Restarted"` -- reporting a successful
restart while killing the server with no replacement.
- Propagate ToolAbortError/timeout from both the rust-analyzer request
and the didChangeConfiguration notification fallback.
- Gate the fallback on genuine method-not-found via isMethodNotFoundError
instead of any error.
- Replace the blind proc.kill with shutdownClientInstance: remove the
client from the registry by identity and await confirmed process exit,
surfacing a truthful teardown error when the process outlives the kill.
Fixes#6369
- Consolidated Jujutsu (jj) integration logic into a centralized utility module with working-copy and status handling.
- Removed deprecated jj-info helper modules and their corresponding test files.
- Updated status line component and associated tests to consume the new centralized jj utility API.
- Added comprehensive test coverage for working-copy label parsing, status summary mapping, and repository root resolution.