- Replaced external watchdog timers with per-request SDK timeouts for first-event budget across OpenAI, Anthropic, and Azure providers.
- Keyed Python shared kernels by (sessionId, cwd) to prevent cross-directory state bleed.
- Deduplicated concurrent cold-start session acquisition for JS and Python executors.
- Moved `isOpenAIResponsesProgressEvent` to shared module and scoped display output routing per run for interleaved async cells.
- 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.
- 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.
- 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.
Adds the three regression tests the PR body claimed but #1389 had not actually shipped:
- $-prefixed identifier resolution: asserts resolveSymbolColumn("$store")
on a line with bar$store + $store returns the standalone column (16),
not the substring inside the compound identifier (7).
- create→edit ordering on the same URI: the motivating LSP §3.16.2 case
("Extract to new file" code actions emitting [CreateFile, TextDocumentEdit]
for the same URI). Pre-fix this threw ENOENT.
- Folder-delete subtree flush: mirror of the existing folder-rename test
for the delete arm — child-file edits must land before the parent folder
goes away.
Also adds a CHANGELOG sentence noting that when a WorkspaceEdit supplies
both `changes` and `documentChanges`, the new code uses documentChanges
exclusively per LSP §3.16.2 (previously the two were merged).
- BARE_IDENTIFIER_RE accepts $-prefixed names ($store, $count, RxJS/Svelte/
Angular). Word-boundary check now fires on those names, so searches no
longer return the offset inside a compound identifier like bar$store.
- applyWorkspaceEdit walks documentChanges in declared order, flushing
per-URI text edits immediately before any subsequent resource op for the
same URI. Folder rename/delete ops flush every pending URI under the
affected subtree. Rename ops also flush pending edits queued against
renameOp.newUri (and descendants) before fs.rename runs.
- Legacy changes-map-only WorkspaceEdit payloads are unchanged.
Refactor:
- session.ts: extract mapDebugpyMissingModule helper; replace the duplicated
inline check in launch/attach catch blocks. Add jsdoc on DapStartRequestFailure.settled
documenting per-call ownership and how throwPreferredDapStartError consumes it.
- path-utils.ts: replace the no-op keepOpaqueResourceUri branch with an
OPAQUE_RESOURCE_SCHEMES Set so the structure carries the intent. Functionally
equivalent; new opaque schemes become a one-line Set change.
Tests:
- dap-launch-failures: cover the debugpy stderr -> 'pip install debugpy'
rewrite for launch and attach, plus a negative case (non-debugpy adapter
with the substring in stderr is left untouched).
- dap-launch-failures: model the delayed-launch-failure case the new
settled-race in throwPreferredDapStartError defends against. FakeDapClient
gains optional launchErrorDelayMs/attachErrorDelayMs.
- dap-launch-failures (DebugTool): assert adapter:'debugpy' early-throw
surfaces 'python not found in PATH' on both launch and attach when
selectLaunchAdapter/selectAttachAdapter return null, and the unspecified-adapter
path still falls back to the generic 'No debugger adapter' error.
- find.ts: export validateFindPathInputs and pin the new backslash-escape
semantics (\, no longer trips the comma-joined heuristic) plus the
existing brace-expansion and rejection paths.
- patch.ts: cover the post-write verification error message. The user-facing
ToolError must contain the caller-supplied relative path and not the
absolute resolvedPath (which still lives in the structured context for
log correlation).
- split-internal-url-sel: reword two mcp:// test comments that described a
'peeler refuses' guard that doesn't exist; rename the tests to reflect the
actual opaque-scheme rule.
- browser tool's existing-tab re-nav defaults to waitUntil: 'load' (matching
new-tab path); identical acquireTab() calls no longer hang on dev servers
- patch tool error path uses caller-supplied relative path; absolute
resolvedPath stays in structured context only ($HOME no longer leaks to TUI)
- splitInternalUrlSel keeps mcp:// resource URIs opaque even when they end in
':raw' or '/:1-50' (McpProtocolHandler matches by verbatim URI)
- find tool: timeout signal honored by onMatch; partial results sorted by
mtime desc; backslash-escaped commas skipped in path-list validation
- DAP throwPreferredDapStartError waits up to 50ms for the underlying
launch/attach error instead of one microtask
- debug tool surfaces 'python missing' and 'pip install debugpy' diagnostics
separately when adapter: 'debugpy' is requested
- 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.
- 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.
- 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.
- Centralized OAuth access lifecycle in `AuthStorage`, returning identity metadata and new access-result types.
- Added 60-second skew and strict expiry checks, returning undefined/throws for stale or expired OAuth credentials.
- Removed provider-local token refresh flows from Gemini, Gemini CLI, Antigravity, Kimi, and related OAuth helpers.
- Migrated web-search providers from `AgentStorage` to `AuthStorage` session-aware lookup with `authStorage`/`sessionId`/`signal` flow.
- Replaced `findAnthropicAuth`/DB auth lookup with `buildAnthropicAuthConfig` and explicit base-url override/env fallback ordering.
- Added OpenAI Codex and Gemini web search provider options with updated setup/auth descriptions.
- Updated Codex OAuth flow to refresh near-expiry tokens during web_search and persist the refreshed credentials.
- Plumbed AgentStorage through search orchestrator, scrapers, and fetch paths so providers share session credentials.
- Refactored web provider and credential helpers to accept caller-provided AgentStorage and resolve keys synchronously.
The report_finding tool's priority is exposed as a string enum
("P0"-"P3") for ergonomics, but the reviewer agent and every
custom review agent declare priority as `type: number` in their
JTD output schema. The cast at executor.ts:1473 lied about the
runtime shape, so the auto-injected `findings[].priority` flowed
through as strings and every yield with at least one finding was
rejected with `findings.0.priority: expected number, received string`,
forcing the run into the schema_violation exit path.
Added `toReviewFinding(details)` in tools/review.ts that maps the
priority enum to its numeric ordinal via the existing PRIORITY_INFO
table and use it at the boundary in executor.ts. Render paths still
see the original `ReportFindingDetails` shape (string priority)
through normalizeReportFindings, so display formatting is unaffected.
Fixes#1350
Loaded marketplace lspServers metadata from Claude plugin caches and embedded it for OMP marketplace installs so config-only plugins register without package code.
Fixes#1352
The JTD-to-JSON-Schema converter post-processed convertSchema's
output with normalizeMixedSchemaNode, which walked back into the
emitted JSON Schema looking for nested JTD forms. Inside a
properties block, user-defined property names whose keys happened
to collide with JTD keywords ('ref', 'elements', 'values',
'optionalProperties', 'discriminator') were misclassified as JTD
forms and re-rewritten - corrupting properties like { ref: { type:
'string' } } into { $ref: '#/$defs/[object Object]' } and breaking
the built-in explore agent's output validator with
schema_violation: files.0.ref: must not be present.
convertSchema is already fully recursive and emits pure JSON Schema,
so the post-walk is both unnecessary and unsafe. Drop it.
Fixes#1345
- Changed hashline format to canonical `§` section headers and `"`/`"`/`≔` operations across grammar, parser, and docs.
- Reworked range and op parsing so single anchors are valid, legacy `-`/`-=` ops error, and empty `≔` payloads now delete ranges.
- Removed legacy `HL_EDIT_SEP`, `$HSEP$`, and `hsep` plumbing, adopting raw payload lines.
- Updated execution, input, renderer, and streaming flows to use `HL_FILE_PREFIX` and `HL_OP_CHARS` helpers.
- Updated session-stats parsing to `§`/`≔`/`"`/`"` format, patch envelopes, and bumped parser versions.
- Removed the hashline-separator benchmark script and its PI_HL_SEP job orchestration.
Appended the stealth iframe to documentElement when document.head is not available during new-document evaluation.
Added regression coverage for the null-head bootstrap path.
Fixes#1267
Adds a shared classifyProviderHttpError helper that maps the well-known
failure shapes (status 401/402/403 and bodies matching credits / quota
/ insufficient) into compact SearchProviderError messages so the
orchestrator advances to the next provider instead of bailing.
Wired into every HTTP-talking provider (codex, exa, gemini, anthropic,
brave, jina, kimi, perplexity, searxng, synthetic, tavily, zai) and the
two wrapped-error providers (kagi via KagiApiError, parallel via
ParallelApiError). The orchestrator now collects per-provider failures
and emits a joined summary ("exa: 403 forbidden; codex: credits
exhausted; ...") when the whole chain fails.
Test updates: web-search-{exa,tavily,kagi} message expectations now
assert the compact "<id>: <status> <reason>" form.
- Added splitInternalUrlSel to iteratively peel internal-URL selector chunks while preserving unsupported schemes like mcp://.
- Updated ReadTool to use the internal splitter before routing so selector parsing is handled via parseSel.
- Added unit tests covering malformed selectors, namespaced skill hosts, and unchanged behavior for non-URLs or unsupported schemes.
- Added capParseErrors in shared render utilities and updated ast_grep and ast_edit to return capped parseErrors plus parseErrorsTotal.
- Threaded the preserved totals into parse-error formatting and renderer output so labels and overflow counts report the full number of issues.
- Added an ast_grep test asserting parse errors are capped at PARSE_ERRORS_LIMIT while parseErrorsTotal retains the original count.
- Set GIT_CONFIG_* and GIT_TERMINAL_PROMPT environment variables to prevent test interference from user gitconfig, LFS filters, signing, and credential helpers.
- Enhanced git error messages to include stdout when stderr is empty, providing better diagnostics for test failures.
- Replaced symlink-resolving pathIsWithin with lexical path containment check to prevent test isolation bypass via symlinked extensions.
- Added `providerRetryWait` and `retryWait` hooks to stream/usage options so tests bypass real scheduler delays.
- Parameterized GitHub Copilot poll intervals and Copilot model retry base delay for fast test execution.
- Replaced `Bun.sleep`/`setTimeout` polling loops with `AbortSignal` event listeners in agent session tests.
- Consolidated auth-gateway E2E helpers into a shared `test/helpers` module, eliminating duplicated `checkGatewayAvailable` implementations.
- Migrated credential-disabled tests from SQLite-backed stores to an in-memory store, removing temp-dir lifecycle overhead.
- Added `dev.autoqa.consent` setting and single-flight popup handler wired through `InteractiveMode`.
- Added `flushGrievances` to batch-POST unpushed rows to `dev.autoqaPush.endpoint` with cooldown and single-flight deduplication.
- Added `omp grievances push` subcommand with TTY progress bar for manual draining.
- Migrated shared DB logic to `openAutoQaDb` (with `pushed` column migration) exported from `report-tool-issue`.
- Extracted `description` from type-array and nullable branches so it lives on the wrapper, not duplicated onto each variant.
- Replaced inline enum-type inference with `inferStrictPrimitiveTypeFromEnumOrConst`, covering both `enum` and `const` in sanitize and enforce paths.
- Mixed-primitive enums and non-primitive consts now fall back to non-strict instead of producing a typeless schema that OpenAI rejects on the wire.
- Moved sanitizeSchemaForStrictMode, enforceStrictSchema, and tryEnforceStrictSchema into normalize.ts.
- Moved sanitizeSchemaForOpenAIResponses/rewriteOneOfToAnyOf into normalize.ts alongside other normalizers.
- Removed strict-mode.ts and its public re-export; adapt.ts now only exposes NO_STRICT and adaptSchemaForStrict.
- Dropped StringEnum helper from strict-mode.ts (already removed from public API).
- Removed the legacy `parseEvalInput` parser module and `eval.lark`, eliminating `*** Cell` stream parsing.
- Replaced eval tool arguments from single `input` strings to ordered `cells` arrays in tool calls and schema.
- Updated execution to resolve language explicitly, map `py` to `python`, and apply timeout/reset defaults.
- Removed backend sniffing and `ABORT_WARNING` suffix handling, then updated docs and tests to the new JSON cells format.
- Implemented a unified normalization flow by switching Google/CCA handling to normalizeSchemaForGoogle/CCA.
- Added normalize.ts with recursive node normalization, nullable-union checks, and combiner collapsing.
- Removed sanitize-google.ts and normalize-cca.ts, replacing them with normalize exports in schema indexes.
- Added spill-to-description utilities with spill/paren modes and `$defs` exclusion for unsupported fields.
- Updated MCP bridge and schema tests to use normalizeSchemaFor* APIs with expanded compatibility checks.
- Documented normalization behavior changes and breaking rename in constraints and package changelog files.
ConPTY's ClosePseudoConsole can deadlock when it tries to flush output
to a pipe that nobody is reading (microsoft/terminal#1810). This caused
the PTY Promise to never resolve on Windows, making bash commands with
pty:true hang indefinitely.
Root cause: portable-pty's drop(master) calls ClosePseudoConsole
synchronously. If ConPTY's internal render thread is blocked writing to
a full/undrained output pipe, ClosePseudoConsole waits forever.
Fix (three parts):
1. Rust (pty.rs): Reordered teardown to follow Microsoft's recommended
shutdown sequence:
- Drop writer first (close ConPTY input pipe)
- Drain reader thread with 500ms timeout (consume output pipe)
- Drop master in a background thread with recv_timeout(2s):
* Clean case: ClosePseudoConsole completes, thread reclaimed
* Hung case: timeout expires, main thread returns anyway
- Replace child.wait() with try_wait() polling on Windows
(WaitForSingleObject can also hang in ConPTY)
2. TypeScript (bash-pty-selection.ts): Remove the Windows blanket
disable that prevented PTY from ever being used on Windows.
3. Tests: Updated to verify PTY works on Windows with UI context.
Replaces the blanket PTY disable on Windows (PR #1105) with a targeted fix:
- TypeScript: PI_FORCE_PTY env var allows explicit Windows PTY opt-in.
PTY is still disabled by default on Windows to prevent hangs, but power
users who need interactive workflows can override.
- Rust: Adds ct.heartbeat() checks during PTY setup (openpty, spawn, reader
creation) so the existing timeout mechanism works even during setup.
- Rust (Windows): Wraps openpty() in a 5-second startup timeout thread.
If ConPTY hangs during pseudo-console creation, the Promise rejects with
a clear error instead of hanging forever.
Fixes#1103#1106
- Preserved object schemas with explicit `additionalProperties` settings by avoiding strict coercion to false.
- Probed schema strictness before sanitization and set `tool.strict` false for non-strict schemas.
- Set `tool.strict` false for `null`, `true`, and unconstrained `outputSchema` fallbacks.
- Documented the fix in Unreleased changelog entries for both `ai` and `coding-agent` packages.
- Added regression tests covering loose `additionalProperties` and yield strictness behavior across tools.
- Adopted draft-2020-12 tuple validation with `prefixItems`, rejecting array-valued `items`.
- Expanded strict-mode handling to recurse `prefixItems` entries and infer `array` when tuple prefixes exist.
- Normalized Anthropic schemas through `prefixItems`, keeping supported tuple constraints and dropping unsupported fields.
- Updated coding-agent schema metadata and tests to draft-2020-12 `$schema` targets, including MCP/theme fixtures.
- Added `trimTrailingWhitespace()` to strip trailing spaces/tabs and keep the original line when none exist.
YieldTool's unresolved-ref fallback now skips literal-value positions such as const, enum, default, and examples when looking for unresolved schema refs. Valid schemas containing data literals like { "": "literal" } no longer degrade to the loose schema and still reject invalid yield payloads.
dereferenceJsonSchema leaves $ref strings in place when references are unresolvable (external URLs, missing definitions, certain cycles). The new yield-parameters builder now walks the resolved schema for any remaining $ref strings before installing validation; if any are found, it throws so the existing catch branch swaps in looseRecordSchema and disables strict validation. Previously YieldTool installed a validator that rejected every success payload with an unresolved-reference error.
- Replaced fromTypeBox conversion with a JSON-schema validator flow in ai tool handling and execution paths.
- Added recursive schema validation and expanded TypeBox checks for refs, enums, uniqueItems, and constraint keywords.
- Sanitized Azure/CCA tool schemas by dropping unsupported fields and rewriting oneOf tool branches as anyOf.
- Tightened argument and model-config validation, preserving unknown tool fields and adding apiKey plus compatibility flags.