- Updated hashline parser tests to use inline payload syntax (e.g., `tagvpayload` instead of `tagv\npl(payload)`).
- Removed deprecated test cases for bare-blank-line and explicit-blank-payload syntax.
- Removed deprecated MCP-specific type aliases and functions from tool-discovery module, consolidating to unified generic tool discovery API.
- Migrated session and SDK code to use generic filterBySource() and collectDiscoverableTools() instead of MCP-specific variants.
- Removed deprecated interface members including hasQueuedMessages(), FocusPane, AcpBuiltinCommandRuntime, and legacy settings methods.
- Updated test suites to use renamed generic discovery methods and removed back-compat test coverage for legacy MCP shapes.
- Added `cwd` and `env` optional parameters to kernel execution API for runtime working directory and environment variable control.
- Implemented runtime environment setup in Python runner with `_apply_request_runtime()` to apply cwd and env from request before code execution.
- Enhanced SIGINT handler management with `active_executions` counter and `_begin_exec_sigint()` / `_end_exec_sigint()` functions to prevent state mutation during concurrent execution.
- Changed `SearchRenderArgs.paths` parameter type from `string[]` to `string | string[]` to accept single string paths.
- Added comprehensive test coverage for kernel cwd updates, timeout interruption safety, and SystemExit handling in shared executor sessions.
- Updated type signature to show `paths` accepts `string | string[]` instead of only arrays.
- Clarified that single string paths are wrapped into a one-element list before resolution.
- Improved prompt instructions to explicitly show both string and array usage patterns.
- Restored per-provider stream watchdog with idle and first-event timeout support, progress-event filtering, and per-provider timeout overrides via `getStreamIdleTimeoutMs()` and `getStreamFirstEventTimeoutMs()`.
- Fixed silent multi-hour hangs on Codex WebSocket and z.ai/GLM-via-OpenRouter subagent runs by filtering keepalive frames from idle watchdog resets.
- Added `isOpenAICompletionsProgressChunk` export and progress-event filtering to multiple providers (Anthropic, OpenAI Responses/Completions, Azure OpenAI, Codex) to prevent keepalive frames from resetting idle timeouts.
- Un-deprecated `StreamOptions.streamIdleTimeoutMs` and wired it into all built-in providers and lazy stream forwarder with environment variable fallback support.
- Removed per-session run queues from JS and Python backends, allowing async cells on the same session id to interleave.
- Introduced `getEvalSessionId` on ToolSession so subagents spawned via `task` inherit the parent's executor id and share JS VM and Python kernel state.
- Switched JS runtime state from module-level fields to AsyncLocalStorage so concurrent runs route output and tool calls to their own context.
- Changed Python runner to an asyncio event loop with per-request tasks and ContextVar-based run id tracking for concurrent execution.
- Added mtime-based module cache eviction to preserve singleton state across re-imports of unchanged local files.
- Replaced per-line hash anchors with file-level hash validation in hashline format, changing anchor syntax from LINE+HASH to bare LINE numbers.
- Simplified hashline line separator from pipe (|) to colon (:) and replaced replace operator (->) with colon, added delete operator (!) for explicit line deletion.
- Implemented file-read snapshot caching with multi-snapshot ring buffer per path and file-hash-based recovery to detect and recover from stale edits.
- Refactored hashline grammar, parser, and execution to support file-level hash binding, anchor-scoped validation, and structural bracket warnings for delete operations.
- Updated documentation and test fixtures to reflect new hashline syntax with file hashes, colon separators, and delete operator throughout.
- Deleted the `packages/ai/src/utils/h2-fetch.ts` HTTP/2 retry wrapper and removed its public export from `packages/ai/src/index.ts`.
- Removed the `installH2Fetch` import and invocation from `packages/coding-agent/src/cli.ts`, so the CLI no longer patches `fetch` for HTTP/2 negotiation.
- Updated `packages/coding-agent/CHANGELOG.md` to align the vim-mode removal notes with the code changes.
- Removed vim edit mode and automatically map existing vim configurations to hashline mode.
- Deleted VimTool class, VimEngine implementation, and all vim-specific editing logic (2409 lines).
- Removed vim mode from EditMode union type, edit tool strategies, and configuration schemas.
- Deleted vim parser, command handler, buffer manager, and renderer modules.
- Updated documentation and tests to remove vim mode references and add deprecation mapping.
- Added a `console.table` helper in the JS prelude that forwards calls to the runtime `__omp_table__` hook.
- Implemented `__omp_table__` in the runtime to render tables through `node:console.Console` and emit text via `onText`.
- Added tests verifying `console.table` produced formatted table output and respected the optional columns filter.
- Handled successful `main()` resolution by calling `process.exit(0)`.
- Preserved existing benchmark failure handling by logging the error and exiting with status 1.
Ignored the agent auth sentinel when selecting Bedrock bearer auth so AWS credential sources still use SigV4.
Added regression coverage for sentinel forwarding with AWS_BEARER_TOKEN_BEDROCK and static AWS credentials.
Fixes#1399
- Updated OpenAI completions compatibility to set `supportsDeveloperRole` only for OpenAI and Azure hosts.
- Added regression tests for host-specific `supportsDeveloperRole` defaults across OpenAI, Azure, and alternative providers.
- Added a Moonshot regression test confirming reasoning message conversion emits the system role.
Bedrock now sends AWS_BEARER_TOKEN_BEDROCK as Authorization: Bearer before resolving SigV4 credentials, so failing profile credential_process hooks cannot block bearer-token requests.
Added regression coverage for a default profile credential_process failure with AWS_BEARER_TOKEN_BEDROCK set.
Fixes#1399
- Updated Moonshot login validation to use a `models-endpoint` check instead of `chat-completions`.
- Changed the Moonshot key verification target to `https://api.moonshot.ai/v1/models` to avoid model-specific chat parameter validation failures.
- Added helpers to synthesize RawSseEvent records for inbound, outbound, and malformed Codex WebSocket traffic.
- Passed onSseEvent through websocket transport and stream setup so frames are forwarded to the raw-SSE debug pipeline during streaming.
- Added a stream test that verifies outbound and inbound websocket frames are emitted with SSE-style raw lines for the debug viewer.
- Updated hashline markers to `¶` headers and `^/v/->` operators across constants, prompts, docs, and tests.
- Reworked hashline grammar and parser to support `ANCHOR<SIGIL>[INLINE_PAYLOAD]` with optional inline bodies and `A-B` ranges.
- Changed range and marker syntax from `..`/`"` to `-` and suffix `^/v/->` forms like `7v` and `A->`.
- Aligned `sameLineRange()` output and BOF/EOF handling so `|TEXT` remains cosmetic and payload now follows the op line.
- Centralized op-line detection by replacing local regex helpers with `isHashlineOpLineText` for payload terminator and bad-op checks.
- Adjusted `#emitViewportRepaint` to use `viewportTop + height - 1` as the cursor target row instead of clamping to `lines.length - 1`.
- This kept `#cursorControlSequence` row-delta math consistent with the hardware cursor after blank padding rows, preventing the IME cursor from staying stuck at the viewport bottom on height-grow resizes.
- Added a regression test and terminal cursor accessor to verify the focused `CURSOR_MARKER` row remains active after terminal expansion.
- Expanded transient error matching for Bun HTTP2StreamReset, RefusedStream, and EnhanceYourCalm.
- Dropped thinking-only/error/aborted turns without text/toolCall, reset aborted tool-call map, and stored timestamps.
- Updated TUI render planning to track scrollback high-water and suppress suffix-scroll artifacts in non-multiplexer sessions.
- Added regression tests and changelog notes for Bun HTTP/2 retry handling, thinking-only filtering, and scrollback regressions.
- Added a custom JSON replacer that unwraps `Error` instances in logger output, preserving name, message, stack, cause, and enumerable fields.
- Updated uncaught-exception and unhandled-rejection logging paths to pass only `{ err }`, relying on the logger serializer for full error details.
- Extended transient socket-close matching to detect HTTP2 stream reset/refused/calm errors and added regression tests for logger error serialization behavior.
- Added shared timeout helpers in `sdk-stream-timeout` and removed duplicated inline stream timeout logic.
- Replaced inline provider timeout math with `resolveSdkTimeoutMs` and shared request-option builders.
- Added Codex websocket first-event and idle timeout settings via env-backed options.
- Updated Codex stream polling to apply per-phase time limits, return timeout errors, and fallback to SSE.
- Expanded `abortable-iterator` tests for preflight, in-flight, and leak cases around abort handling.
- Updated `streamFirstEventTimeoutMs` docs to document provider support and deprecated `streamIdleTimeoutMs`.
- Deleted the `ValidationVerdict` type and `evaluateOutputAgainstSchema` API from the output schema validator.
- Updated `yield.ts` to bind `buildOutputValidator`'s error directly to `schemaError` during validator setup.
- Removed the obsolete evaluator tests and adjusted validation success fixture to match the raw summary input shape.
Mapped streamFirstEventTimeoutMs onto OpenAI Responses request timeout options so explicit caller deadlines are not ignored after removing provider-stream watchdogs.
Fixes#1392
Checked provider abort signals at the start of each iteration so aborts fired between yielded stream events cannot be missed before the next iterator wait is armed.
Fixes#1392
Removed OMP-owned first-event and idle watchdogs from provider stream consumption while preserving caller abort handling. Updated provider stream tests to assert slow/silent streams wait for provider output or caller abort instead of surfacing watchdog errors.
Fixes#1392
- Unified output schema construction and validation by adding buildOutputValidator and using it in YieldTool and task executor.
- Added MAX_SCHEMA_RETRIES so YieldTool now retries schema failures three times with hints before overriding.
- Updated failure handling to use shared summarizeValidationFailure and formatters for required-field reporting.
- Added tests for output-schema-validator and YieldTool covering malformed schemas and nested-array retry edge cases.
Terminals clamp the hardware cursor to the visible viewport on resize, but TUI committed cursor rows from the prior geometry. Subsequent relative cursor moves (diff/shrink/append-tail) then wrote to wrong rows, producing duplicate or shifted content on screen. Clamp `prevHardwareCursorRow` to `prevViewportTop + height - 1` in each emitter that uses relative cursor math, and add a regression for height + content storms.
Fixes#1295
Centralizing OAuth refresh in AuthStorage (e6893515) introduced five
follow-on bugs surfaced by an audit of the commit; this fixes all of
them and updates the tests that relied on the old refresh seam.
1. packages/ai/src/auth-storage.ts (#tryOAuthCredential):
For built-in providers the path went directly to `getOAuthApiKey`
with the (possibly still-expired) selection.credential when the
pre-refresh at line 2587 caught a transient error. `getOAuthApiKey`
then threw the "expired … must be refreshed via AuthStorage"
precondition error, which the disable classifier matched against
`/expired.*refresh/` and soft-disabled the row. A single network
blip during refresh could permanently kill a still-valid Anthropic /
OpenAI / Gemini-CLI / Copilot credential. Built-in providers now
route through the broker-aware single-flighted
`#refreshOAuthCredential` first, so transient failures surface as
network errors (5-min temp block) instead of definitive auth
failures.
2. packages/ai/src/auth-storage.ts (#fetchUsageUncached):
The usage refresh check only fired once `Date.now() >= expiresAt`,
missing the 60-second skew that `getApiKey` honors. A token
expiring inside the skew window was posted to the usage endpoint
and 401'd mid-flight, briefly hiding quota in the UI. Aligned with
`OAUTH_REFRESH_SKEW_MS`.
3. packages/coding-agent/src/web/search/index.ts (webSearchCustomTool):
The CustomTool counterpart of WebSearchTool dropped sessionId so
SDK callers that opted into `web_search` via toolNames lost
per-session credential stickiness — multi-account users saw the
provider round-robin between searches in the same session. Threads
`ctx.sessionManager.getSessionId()` through to `executeSearch`.
4. packages/coding-agent/src/web/search/providers/perplexity.ts
(findOAuthToken):
`authStorage.getApiKey("perplexity")` returns runtime/config
overrides, stored api_key credentials, OAuth bearers, and env keys.
Filtering only env keys meant a config-pinned `pplx-…` API key was
POSTed to `www.perplexity.ai/rest/sse/perplexity_ask` (the OAuth
endpoint) instead of falling through to
`api.perplexity.ai/chat/completions`, producing 401s. Switched to
`getOAuthAccess` so only true OAuth bearers reach the OAuth
branch; api_key credentials/overrides correctly fall through.
5. packages/ai/scripts/generate-models.ts:
`getOAuthApiKey` was being called directly with possibly-expired
credentials. The new contract throws on expired, the broad catch
swallowed it, and the build silently fell back to bundled models
instead of refreshing. Both helpers now route through
AuthStorage's `getApiKey` / `getOAuthAccess`, which trigger the
full broker-aware refresh pipeline.
Test updates:
- auth-storage-credential-disabled-event.test.ts,
sdk-credential-disabled-bridge.test.ts: the `failOAuthRefresh`
helper used to spy on `getOAuthApiKey` to inject invalid_grant.
With refresh now happening before that helper, the spy never fired.
Switched to spying on `refreshOAuthToken` so the simulated failure
reaches the disable classifier.
- auth-storage-rotation.test.ts: stub `refreshOAuthToken` so the test
doesn't hit a real OAuth endpoint when the seeded credential lands
inside the 60s skew window.
- Handled the case where Anthropic sends a refusal/sensitive stop_reason but omits stop_details, previously falling through to a generic "unknown error."
- Added human-readable fallback messages per stop_reason type (refusal, sensitive, or raw value).
- Added test covering the null stop_details refusal scenario.
- Added optional per-provider fallback parameters to stream timeout helper functions so callers can widen default watchdog values safely.
- Threaded provider-specific lazy stream limits into stream creation and set Google Gemini CLI to a 300000ms first-event fallback by default.
- Added tests covering fallback defaults, env precedence, and global-default behavior for both idle and first-event timeouts.
Split `#doRender` into a planner plus one emitter per intent: `initial`, `sessionReplace`, `historyRebuild`, `viewportRepaint` (optionally prefixed with an append-to-scrollback), `shrink`, `diff`, `noop`. Cursor, viewport, and scrollback state now flow through a single `#commit` checkpoint at the end of every emitter.
Fixes#1295
Combined task.enableLsp with the parent session enableLsp gate before spawning subagents, so --no-lsp remains authoritative even when subagent LSP is enabled in settings.
Fixes#1385
Added task.enableLsp (boolean, default false) and routed both regular and isolated subagent dispatch through it. Keeps subagents cheap by default while letting users opt in to LSP-aware delegation. Updated regression tests to cover the default-off, opt-in, plan-mode, and isolated paths.
Fixes#1385
Subagents now inherit the parent session's enableLsp value, so a top-level --no-lsp invocation propagates into spawned tasks instead of falling back to the executor's default of true.
Fixes#1385
Removed the hardcoded subagent LSP disable flag so executor defaults and user settings control LSP availability. Passed the effective plan-mode agent definition into both regular and isolated subagent dispatch so plan-mode tool restrictions apply consistently.
Fixes#1385
- packages/ai/test/issue-957-repro.test.ts now tests:
- refreshKimiToken applies the 5-minute server-side skew (Kimi-specific)
- AuthStorage refreshes kimi-code credentials inside its 60s skew window
- packages/ai/test/anthropic-stream-timeout.test.ts: raise the
streamFirstEventTimeoutMs from 10ms to 5000ms so slow CI scheduling
cannot fire the first-event watchdog before the mocked events arrive.
The test still exercises the (1ms) idle path it was written for.
fix(web): allow Parallel extract via PARALLEL_API_KEY env var without storage
The fetch tool and YouTube scraper previously gated the Parallel extract
branch behind `storage && findParallelApiKey(storage)`. With no
AgentStorage the env key was never consulted, so callers that ran
without a per-session storage (e.g. ReadTool sessions in unit tests, and
in practice any caller that has only an env API key) silently fell back
to raw-html / no-ytdlp paths.
- findCredential/findParallelApiKey now accept null or undefined storage
and rely solely on the env-first path when no storage is supplied.
- searchWithParallel/extractWithParallel mirror the same nullable shape.
- Drop the redundant `storage && ` guards in fetch.ts and youtube.ts;
the inner findParallelApiKey call already returns null when no
credential is available.
Clear the viewport on the initial TUI paint so stale shell rows are not left onscreen. When a width change affects offscreen transcript rows, clear terminal history and replay the resized transcript so historical components do not remain in the old geometry.
Fixes#1295
When offscreen transcript changes require a viewport repaint in the same frame as appended output, emit the appended tail first so terminal history advances before repainting the visible rows.
Fixes#1295