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.
- 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.
`ref` is a JTD-reserved keyword (RFC 8927) used by the schema-reference
form, so the JTD-to-JSON-Schema converter on releases prior to 15.3.2
silently dropped it from the generated JSON Schema and required it at
the same time. Every explore-agent invocation then failed validation
with `schema_violation: files.0.ref: must not be present`.
The converter side was hardened in #1345 (shipped in 15.3.2). This
rename is defense-in-depth at the prompt level: the explore agent's
output contract no longer relies on the converter recognising a
user-named property that collides with a JTD keyword, and the field
name now matches what it actually carries.
Fixes#1379
- 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.
- Updated `terminate_new_descendants` to require the `Sync` marker on its hash-set hasher.
- This tightened async helper bounds without changing its termination-wave logic.
Anthropic silently switched adaptive-thinking's display default to
"omitted" starting with Claude Opus 4.7, so the Bedrock provider
stopped surfacing any reasoning content — observed in the wild as
silent streams and timeouts on long reasoning runs.
Mirrors the existing direct-Anthropic behavior in this repo:
- For adaptive-thinking models that accept the field (Opus 4.7+),
emit { type: "adaptive", display: "summarized" } by default.
- For older adaptive-thinking models (Opus 4.6, Sonnet 4.6+) that
reject the field, keep emitting just { type: "adaptive" }.
- For budget-based Claude models, always set display.
- Expose BedrockOptions.thinkingDisplay ("summarized" | "omitted")
so callers can opt out, and wire hideThinkingSummary into the
bedrock-converse-stream case in stream.ts.
Fixes#1373
Quarantined persistent session keys only while the native cancellation promise remains unsettled, so healthy cleanup restores persistent mode and stalled cleanup cannot accumulate live shell instances.
Added coverage for both stalled and settled native cleanup paths.
Fixes#1347
Queued extension-delivered user messages when deliverAs is set and waited for session_start extension message sends before prompting subagents.
Fixes#1343
Stopped marking persistent bash sessions as permanently broken when the JavaScript abort or timeout race wins.
Stopped the Rust descendant kill-wave helper once no cancellation targets remain so later commands are not swept into old cancels.
Fixes#1347
- Restructured the auth-broker `openSnapshotStream` tests to be top-level cases under the describe suite.
- Added a stream parser test asserting pure ": keepalive" lines are not included in subsequent SSE event raw output.
- AuthBrokerClient now checked the response Content-Type and rejected non-SSE responses before parsing.
- It required the first parsed SSE event to be a snapshot and treated ended or truncated streams as errors.
- Added coverage for non-SSE and missing-initial-snapshot streams, and reset raw SSE state for empty events.
- Updated nested task-rendering tests to use parent-qualified IDs for completed child task results.
- Updated in-flight nested snapshot expectations to verify parent-aware `Parent>Subtask` labeling.
- Documented the live nested task rendering behavior in the package changelog.
- Added `/v1/snapshot/stream` SSE support and discriminated `snapshot`/`entry`/`removed` event payload contracts.
- Added `openSnapshotStream()` with abort handling, unsupported-stream errors, and filtered SSE payload parsing.
- Added `streamSnapshots` as default-true in remote store with SSE-first background syncing and 404-based fallback.
- Added per-credential generation tracking and `streamKeepaliveMs` tuning for long-lived SSE connections.
- Captured `tool_execution_update` snapshots for `task` calls into in-flight progress state for live nested rendering.
- Cleared in-flight task snapshots at task start and completion to prevent stale nested progress from persisting.
- Updated progress rendering to combine completed and in-flight task details through a dedicated nested task tree view.
Added Rust-side descendant termination on shell cancellation paths so aborts and timeouts escalate to SIGKILL even if brush cleanup stalls.
Covered SIGTERM-ignoring shell workloads in native tests.
Fixes#1347
- Added a per-credential in-flight refresh map in AuthStorage and returned existing promises for concurrent OAuth refreshes.
- Updated OAuth API-key retrieval to share refreshes and persist refreshed candidate credentials.
- Added tests covering preflight persistence across multiple credentials and ensuring concurrent refreshes coalesced to one call.
- Normalized reviewer-bot matching by stripping a trailing `[bot]` suffix when resolving configured bot logins.
- Fetched PR thread history for followup comments without directives and carried it through task execution.
- Updated followup prompt rendering to include prior conversation context for handle_comment tasks.
- OAuth refresh handling updated the candidate credential and replaced the stored entry at its index.
- OAuth refresh race tests were updated to unregister the test provider during teardown.
When a previous turn's providerPayload snapshot lands in the input array
via the `dt: false` splice, any earlier `function_call` items get
wiped while the matching `function_call_output` from a later toolResult
remains. Locally-rejected tool calls (argument-validation failure, hook
reject, aborted turn before the call streamed) hit the same pattern: a
toolResult lands without a `function_call` ever being persisted.
For non-Azure/non-Copilot providers (`strictResponsesPairing=false`)
the orphan output shipped to the wire, and the Responses API responded
with `400 No tool call found for function call output with call_id …`.
Sessions in that state were unrecoverable until restart.
Add a final-pass guard, `repairOrphanResponsesToolOutputs`, that scans
the assembled input for orphan `function_call_output` /
`custom_tool_call_output` items and folds each into an assistant
`message` text note carrying the call_id and (truncated) output. This
preserves the payload the model needs to recover while keeping the
request grammatically valid. Mirrors the existing behavior in the
`openai-codex` provider's `request-transformer.ts`.
Fixes#1351
- Updated markCredentialSuspect to apply the credential entry returned from refreshCredential and throw when the broker returns a non-OAuth credential.
- Added #applyCredentialEntry to replace or append a credential in the in-memory snapshot for immediate state updates.
- Added a test covering suspect-credential refresh snapshot updates and token refresh invocation.
Raced bash execution against the JavaScript abort signal and timeout so the tool returns even when native shell cleanup does not settle.
Added regression coverage for native cleanup stalls on ESC abort and timeout.
Fixes#1347
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
- Extended `invalidateCredentialMatching` to accept session-scoped options and clear cached session credentials before blocking the matched credential.
- Updated the OAuth auth-error retry flow to pass `agent.sessionId` through credential invalidation.
- Added a regression test ensuring invalidating a session-sticky OAuth key rotates to the next active credential.
- Moved issue classification updates to run only after branch rename succeeds, preventing partial labeling or DB writes when rename fails.
- Adjusted workspace ownership normalization to chown workspaces to the active slot or, when slotless, to the current euid/egid, then apply shared permissions.
- Added tests for classify_issue rename-failure rollback and chown_workspace normalization in non-slot mode.
- Added `checkCredentials()` with result types/options for per-credential tri-state health checks.
- Added `/v1/credentials/check` endpoint via `handleCredentialsCheck` returning `{ generatedAt, credentials }`.
- Added `omp auth-gateway check` flow with provider grouping, `--json` output, and exit status 1 on failures.
- Added command examples, changelog updates, and tests for expired OAuth refresh, null/missing config, and ordering edge cases.
parse_issue_ref now accepts owner/repo#NN or a github issue url (with or without scheme, www., trailing slash, query, fragment). The dashboard trigger, CLI, and replay endpoint pick this up automatically; UI hints updated to match.
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
Documented that keybinding remaps live in ~/.omp/agent/keybindings.json and use namespaced action IDs. Added the keybindings reference page to the embedded docs set.
Fixes#1353