- 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.
- Added canonical `pi.zod` schema API exports and removed TypeBox package exports/imports.
- Migrated Tool schema typing from TypeBox to shared `TSchema`/Zod flow with legacy TypeBox compatibility.
- Updated AI provider adapters and MCP/agent builders to convert tool params through `toolWireSchema()`.
- Reworked schema validation from AJV to Zod-safe parsing with `fromTypeBox`, `toolWireSchema`, and meta schema checks.
- Added a `resolveSearchRepoScope` helper that uses an explicit `repo` when provided, skips defaulting when a query already contains a repo/org/user/owner scope qualifier, and otherwise resolves the current checkout via `resolveDefaultRepoMemoized`.
- Updated `search_issues`, `search_prs`, `search_code`, and `search_commits` to use the resolver before composing API queries, defaulting `repo` when omitted but silently falling back to an unscoped search on resolution failure.
- Documented the new search-repo defaulting rules in tool prompts, user docs, and the package changelog.
- Added stripOutputNotice to output-meta to remove appended truncation notices when output metadata is available.
- Updated bash, eval, browser, read, and ssh renderers to strip the notice before display so the styled warning line is not duplicated.
- Left fallback behavior unchanged so outputs without a notice continue through unchanged.
- Updated `formatBashFixupNotice` to wrap the stripped-pattern warning in a `<system-warning>` wrapper.
- Reworded the notice to clarify output is already truncated and stderr is merged into stdout.
- Extended the Bash interceptor test to verify the warning tag appears for head/tail stripping.
- Added top-level parsing and segment splitting to apply bash fixups only on safe command chunks.
- Replaced `stripTrailingHeadTail` usage with `applyBashFixups` and array-based notice formatting.
- Fixed terminal `| head`/`| tail` and redundant `2>&1` stripping while preserving command semantics.
- Updated fixup tests for cross-command cases and removed superseded head-tail-only test coverage.
Drop trailing `| head [args]` / `| tail [args]` pipes that exist purely
to limit output — the harness already truncates bash output and exposes
the full result via the bash-original artifact, so these pipes only
hide content from the agent.
Conservative gates (any failing leaves the command verbatim):
- single-line only; multi-line scripts may legitimately end pipelines
with head/tail to bound a generator or loop body
- whitelisted limit-only args (-nN, -n N, -cN, -N, -q, -v, --lines[=N],
--bytes[=N], --quiet, --verbose); rejects -f/-F/+N/filenames so
`tail -f`, `tail -n +2` etc. stay intact
- regex anchored at end of command; any downstream operator (`&&`,
`||`, `;`, `&`, `>`, `|`, `` ` ``, `$(…)`, `)`) blocks the match, so
`just build 2>&1 | tail -3 && just up && …` is untouched
- refuses to reduce the command to an empty string
- pipe boundary uses `[ \t]*`, not `\s*`, so a `|` on a continuation
line cannot be swallowed
Consolidates the existing `timeoutClampNotice` and the new strip notice
into a single `pendingNotices: string[]` array threaded through every
execute branch (async, auto-background, ACP terminal, local exec).
New setting `bash.stripTrailingHeadTail` (default `true`).
- Added GoalRuntime with wall-clock and token accounting, budget steering, and lifecycle operations (create, pause, resume, drop, complete).
- Exposed goal tool as a hidden agent tool, activated only when goal mode is enabled.
- Integrated goal continuation loop in InteractiveMode with auto-submit between turns.
- Added status line segment and theme icons for goal mode state.
- Removed ExitPlanModeTool and deleted exit-plan-mode docs/tests, dropping the old approval contract outputs.
- Replaced plan-mode approval flow from exit_plan_mode to resolve across session, SDK, controllers, and discovery.
- Added standing resolve handler accessors and updated resolve routing for queued or standing approval handlers.
- Added PlanApprovalDetails and enforced normalized, validated approval titles with readable plan-file requirements.
- Extended resolve schema and invocation signatures with optional extra metadata and reason trimming behavior updates.
- Updated plan and resolve prompts and changelog guidance to require resolve action, reason, and extra.title for apply/discard.
- Updated parseHashlineInputPreviewHeader to strip all leading "@" markers before resolving the preview path, matching existing parser behavior.
- Added a regression test in edit renderer tests confirming both canonical "@@" and longer "@" runs render as clean file paths without extra "@" characters in titles.
- Updated conflict URI parsing to accept `path:conflict://N` and record the removed prefix in `recoveredPrefix`.
- Updated write conflict handling to resolve single or wildcard IDs through shared helpers and append a recovery note when a malformed prefix was stripped.
- Added regression tests for recovered prefixes and end-to-end write-path recovery and documented the change in the changelog.
- Removed export leakage by demoting many helper and const symbols to module-local scope.
- Renamed underscore-prefixed internals and cache fields, then updated related references and `satisfies never` checks.
- Deleted obsolete logic branches and helpers, including harmony-stream interruption flow and unused benchmark runtime helpers.
- Updated Biome config and manifests by broadening lint coverage and removing an unused `@napi-rs/cli` dev dependency.
- Adjusted tests and utilities to use renamed test helpers and remove redundant private test-only helpers/locals.
- Restored formatDimensionNote bracket form '[Image: original WxH, displayed at WxH. Multiply coordinates by S to map to original image.]' that tests assert. The Bun 1.3.14 refactor regressed it to a less informative 'Image resized from …' line.
- Broadened bash-sixel-render multi-line styling assertion to accept both truecolor (38;2;) and 256-color (38;5;) SGR runs so CI runners with TERM=dumb don't fail. The contract being tested — every line carries its own SGR — is independent of color depth.
Keep the active page stealth setup synchronous, but make the broader CDP target UA override sweep selective and best-effort. Non-page or ephemeral Chrome targets can otherwise block worker initialization long enough for browser.open to hit the tool timeout before the tab worker sends ready.
Fixes#1053
Forward worker error and messageerror events while acquireTab waits for the initial ready/init-failed response. This prevents async worker module-load or early startup failures from being reported only as a generic tab worker init timeout.
- Added a new formatBashCommandLines helper that syntax-highlighted each command line and applied the dim prefix only to the first line.
- Updated the shell renderer to emit command output as line-based entries instead of a single dimmed string.
- Extended the bash renderer test to verify multi-line commands keep ANSI styling on every rendered line.
- Changed multi-file search paging to skip whole files and page results in file windows.
- Added per-file match caps, round-robin file selection, and new file-limit truncation reporting.
- Replaced match/result limit metadata with fileLimitReached and perFileLimitReached.
- Lowered read.defaultLimit default to 300 with 1 lead and 3 trailing context lines.
- Replaced the search skip test with file-pagination coverage and added per-file cap tests.
- Added session-stats analytics tooling to classify searches, detect repeats, and render relevance plots.
- Removed one-shot eviction in openDb(), preventing cache rows from being purged before settings load.
- Moved hard-TTL enforcement to getOrFetchView() sweepIfDue() so configured retention applies per lookup.
- Extended github-cache tests to verify row persistence across reopen and expiry under stricter hardTtl.
- Fixed `issue://owner/diff` and `pr://owner/diff` parsing so they resolve to issue and PR list outputs.
- Fixed `pr` short-form parsing by requiring `scheme==='pr'` and a numeric host before `diff` matching.
- Fixed PR unified-diff parsing to decode quoted header paths and count `----`/`++++` hunk lines as one deletion/addition.
- Fixed `read` error rendering to emit status blocks with cleaned, range-aware, tab-normalized lines.
- Stopped `github-cache` from chmod-ing existing parent directories, preserving pre-existing permission modes.
- Added issue:// and pr:// URL handlers for single lookups and list queries with query filters.
- Added a SQLite-backed GitHub cache with soft/hard TTLs, stale hits, and background stale refresh.
- Removed issue_view and pr_view tool operations, inputs, and docs, requiring reads via issue:// and pr:// URLs.
- Added github-cache and issue-pr-protocol tests with temporary cache DB setup and OMP_GITHUB_CACHE_DB teardown.
- Switched issue and PR search handlers to `gh api /search/issues` with `is:issue`/`is:pr` queries.
- Added REST search response models and mapped issue/code/commit/repo payloads to normalized results.
- Updated code, commit, and repo search parsing to read `{items}` envelopes and convert snake_case fields.
- Fixed merged-PR output state by deriving it from `pull_request.merged_at` in test fixtures.
- Added `:conflicts` and `read conflict://<N>`/`read conflict://<N>/<scope>` support and rejected wildcard conflict reads.
- Added bulk conflict resolution via `write({ path: "conflict://*", ... })` across files with per-file grouping.
- Expanded conflict detection to scan files up to 10MB, track insertion-ordered history, and report full `X of Y` summaries.
- Reworked `spliceConflict` to match marker blocks by content, fixing shifted or stale block splicing.
- Added coverage for wildcard parsing, scoped reads, prepended-line splices, relocation, and warning assertions in detect/integration tests.
- Added `ConflictScope` parsing for `conflict://<N>/<scope>` with `ours`, `theirs`, and `base` validation.
- Added `read` support for full and scoped conflict URIs, rendering regions via `#readConflictRegion` with preserved formatting metadata.
- Added conflict-count and error handling in read results, including `Conflict #N not found` responses.
- Added `write`-path rejection for scoped conflict URIs, returning `ToolError` before lookup to enforce read-only behavior.
- Added unit and integration tests for scope parsing, conflict rendering, and read/write conflict error scenarios.
- Added conflictCount metadata and warning badge output to read results for files with unresolved conflicts.
- Added conflict detection parsing with strict marker matching and session-scoped conflict IDs.
- Added write-path conflict resolution for `conflict://N` using token expansion and marker validation before splicing.
- Added unit and integration tests for conflict scanning, history lifecycle, URI validation, and workflows.
External plugins, extensions, and downstream wrappers (notably the upstream
`@mariozechner/pi-coding-agent` AgentSession routed through the legacy-pi-compat
shim) call `modelRegistry.hasConfiguredAuth(model)` before launching a subagent
to short-circuit when no API key is configured. Our `ModelRegistry` did not
expose that method, so the direct agent-launch path threw
`this._modelRegistry.hasConfiguredAuth is not a function` and exited with 0
tokens, 0 tool uses, ~100ms runtime — well before any model conversation began.
The `task` tool path bypassed the preflight and worked, masking the missing
API.
Add a thin `hasConfiguredAuth(model)` wrapper that returns true for keyless
providers and providers with stored auth, matching upstream semantics. Add a
focused regression test asserting the method exists and distinguishes
configured vs. unconfigured providers.
Fixes#993.
- Added optional since/until/dateField parameters to issue, PR, commit, and repo search tools.
- Added parsing for relative and ISO date bounds and built inclusive/exclusive/range search qualifiers.
- Allowed issue/PR/commit/repo searches to proceed with only date ranges and no query string.
- Mapped tool-specific date fields (commits, repos) and rejected since/until for code search validation.
- Updated search tool docs and tests for date filter formats, mappings, and unsupported-code-search behavior.