- Updated getApiKey signatures to accept a Model and return ApiKey or ApiKeyResolver.
- Updated stream key handling to resolve credentials per model and use seedApiKeyResolver for retries.
- Added antigravityEndpointMode setting with auto/production/sandbox endpoint selection.
- Added 429/5xx endpoint failover for Gemini stream, usage, search, and image calls.
OpenRouter previously omitted `max_tokens` entirely (except for specific models) to prevent unintended provider filtering when a model's catalog default `maxTokens` exceeded an upstream's actual capacity. This could lead to incorrect routing if a model had a high catalog cap but individual providers under OpenRouter did not.
- Read tool result details now include optional per-line number arrays so displayed content can retain original line mappings.
- Read tool group and renderer now forward code start-line and line-number metadata into code-cell rendering.
- Code cell rendering now draws aligned line-number gutters and pads hidden-line hints to keep gutter alignment.
Merge displayed bridge-backed range and multi-range read lines into the existing hashline snapshot provenance so INS.POST anchors pass visible-line validation after ACP reads.
Fixes#2773
- Sanitized artifact filenames by normalizing tool names before composing spill paths.
- Applied `wrapToolWithMetaNotice` to custom tool adapters and RPC-host tools in agent-session setup.
- Wrapped SDK-registered extension/custom tools with the same meta-notice adapter during session creation.
- Removed render_mermaid from tool discovery, task definitions, and registries.
- Removed renderMermaid setting and prompt/docs references tied to the deleted tool.
- Added maxWidth and theme color options to Mermaid ASCII resolution in markdown flow.
- Re-rendered Mermaid ASCII in both directions and clipped output to available width.
- Added a list-mode flag to job rendering and used it to keep background job listing behavior distinct.
- Filtered non-partial poll call results to exclude running jobs and return no output when only running jobs remain.
- Added tests covering partial rendering, poll-based filtering, and list/cancel paths for the updated preview behavior.
Re-throw ToolAbortError from soft-expired issue and PR synchronous refreshes instead of falling back to stale cached content.
Cover the abort path in github-cache tests.
Fixes#2684
Refresh soft-expired issue and PR view cache rows synchronously before returning content, while keeping PR diff rows on stale-first refresh semantics.
Add stale fallback warnings when a live refresh fails and cover the cache/protocol behavior in tests.
Fixes#2684
Restricted MSYS and WSL drive alias normalization to forward-slash roots so native Windows root-relative paths like \d\logs stay on the current drive.
Fixes#2634
Mapped MSYS and WSL drive aliases before bash cwd validation and brush filesystem resolution so cd, stat-style tests, and tool cwd handling agree on Windows.
Fixes#2634
- Added `WorkerInbox` and `installWorkerInbox(port)` to queue worker messages before bind.
- Added `consumeWorkerInbox()` to replay buffered messages and clear one active inbox.
- Added buffered inbox consumption in JS and tab worker transports before direct message handlers.
- Normalized worker selector arguments to the `__omp_worker_*` naming across workers and tests.
- Added an `interruptible` field to AgentTool and documented when it is honored.
- Updated immediate-mode tool execution to poll steering during in-flight interruptible calls and abort them when steering is queued.
- Marked the coding `job` tool as interruptible and added tests covering mid-wait aborts versus boundary-only steering drain.
- Updated `init` handling to build a single-phase list from `items` when `list` is absent, using `phase` if provided or defaulting to `Tasks`.
- Kept the existing init validation behavior by emitting `Missing list for init operation` only when neither `list` nor `items` was supplied.
- Added tests for flattened init forms, including implicit phase defaulting, explicit phase use, and the missing-input error case.
- Added model-to-syntax mapping in catalog with preferred tool-call syntax API.
- Added `ToolExample` typing and `ToolCallSyntax` exports across tool/grammar interfaces.
- Added syntax-aware tool example rendering through provider-specific grammar invocations.
- Added `exampleSyntax` context flow and example metadata so rendered prompts include examples.
- Added a `truncateFrom` option to `TreeListOptions` supporting `start` and `end` modes, defaulting to `end`.
- Updated `renderTreeList` to compute candidate items and summary placement based on truncation direction.
- Set the todo list renderer to use start-side truncation so collapsed todo output shows the tail entries first.
- Tracked seen-line provenance in snapshots and propagated it from read/search/ast-grep rows.
- Rejected hashline edits on unseen lines before patching, throwing unseen-line errors.
- Rejected single-line block anchors in strict mode and dropped them in unresolved lenient mode.
- Trimmed one-sided keeper-echo duplicates during multi-line replacements with warning output.
- agent-loop: raise repetition-detection floor to 180 chars and clear thinking
replay anchors when collapsing a detected loop.
- providers/google: ignore empty text parts, retain terminal thoughtSignatures,
and stop function-call signatures clobbering the prior block.
- autolearn: capture goal-mode at the turn boundary; harden managed-skill writes
against hard-links/symlinks (O_NOFOLLOW + nlink); refuse minting managed skills
whose name an authored skill already claims.
- eager tasks: thread agentKind through the session so a custom top-level agentId
still gets always-mode delegation; split Eager Tasks prompt into hard vs soft.
- title-generator: race the online title model against a local tiny-model fallback.
- eager-todo: keep the soft reminder aligned with the todo init schema.
- mcp/stdio: keep close() detaching the read loop instead of awaiting it.
- stream loop: fix collapsing and tool-call thought-signature handling.
- Added unified `omp setup speech` flow with JSON/check modes and model picker.
- Added local STT pipeline with sherpa workers, recorder/download flow, and streaming inference.
- Added local TTS pipeline with `omp say`, backend selection, and streaming vocalization.
- Replaced legacy speech settings with unified `speech`/`speechgen` configuration keys.
Unwrap bracketed [path#TAG] headers at the top of WriteTool.execute() so internal-URL detection, plan-mode guard, plan path resolution, and ACP bridge routing all see the same filesystem target. Without this, ['/data/workspaces/can1357__oh-my-pi__2472/.omp-session/2026-06-13T20-19-47-341Z_019ec2a3-fc0d-7000-b1e6-25831d3c3ec5/local/scratch.md' slipped past isInternalUrlPath() and was bridged to the editor instead of staying on disk as a session-local artifact.\n\nFixes #2472
- learn (mnemopi): `rememberScoped` returns undefined when the retain failed
(closed DB / disk error). The tool ignored it and reported "Lesson stored"
(and could still mint a skill), silently losing the lesson. Mirror
`mnemopiBackend.save` and fail loudly when no id is returned.
- manage_skill: enforce the action/field contract in the schema via a cross-field
refine (create/update require description+body; delete needs only name) instead
of relying solely on a runtime throw in execute. Kept as a refine, not a
discriminated union, so the wire schema stays a single root object — both
strict structured-output mode and the Anthropic tool-schema builder require
that.
Addresses review threads on PR #2542 (threads 19, 14).
The `manage_skill`/`learn` force-include and `isToolAllowed` gates only
checked `autolearn.enabled`, not session depth. A subagent created with an
explicit `tools:[...]` whitelist (which runs `approvalMode: "yolo"`) would
silently gain write-capable tools that can mutate `~/.omp/agent/managed-skills`.
The auto-learn controller only runs for top-level sessions, so gate both the
force-include and `isToolAllowed` for `manage_skill`/`learn` to `taskDepth === 0`.
Also tidies the gating test file: drop a module-level `Bun.env` mutation that
was never restored (the test runner skips the Python preflight already) and a
no-op `afterEach` homedir spy in a block that never mocks homedir. Adds a
subagent-exclusion test.
Addresses review threads on PR #2542 (threads 2, 3, 8, 16).
- Added a smart poll-wait mode to AsyncJobManager with per-owner escalation ladder logic and a reset timer for idle pauses.
- Updated job polling to use the adaptive wait when `async.pollWaitDuration` is `smart` and to record poll completion timing for subsequent waits.
- Expanded async job settings and tests so `smart` is the default option and escalation, reset, and owner isolation behavior are covered.
The `learn` tool previously required a `hindsight`/`mnemopi` backend. It now
also works when `memory.backend` is `local` (the file-based rollout backend):
lessons append to a `learned.md` under the project's memory root, kept separate
from the consolidation artifacts so a consolidation pass never clobbers them,
and are injected into future sessions alongside the memory summary.
- memories: `saveLearnedLesson` (newest-first, deduped, count- and per-field
size-capped, secret-redacted, injection-neutralized) with per-path write
serialization; `buildMemoryToolDeveloperInstructions` reads `learned.md` and
shares one injection budget with the summary; `redactSecrets` extended with
GitHub/npm/Slack/Google token prefixes.
- local backend: implements `save()`; status reports `writable: true`.
- learn tool: `local` execute branch; `createIf`/`isToolAllowed`/auto-include
and the standing guidance extended to `local`; local saves tier as a `write`
approval.
- read-path prompt: renders the learned-lessons block when present.
- Lessons are injection-neutralized and secret-redacted on BOTH write and read
(they render unescaped into the system prompt).
Also moves the auto-learn CHANGELOG entry out of the released [15.12.6] section
(a cherry-pick artifact) back under [Unreleased] and notes the local backend.
Tests: local storage (format, dedup, cap, redaction incl. provider/delimiter-
split tokens, concurrency), read-back (with/without summary, off-gating, raw
hand-edited file), tool gating + write-approval tiering.
Add a default-off "auto-learn" loop. When `autolearn.enabled` is set, after the
agent stops a session controller nudges it to capture reusable lessons: durable
facts go to long-term memory and repeatable procedures become "managed skills" —
SKILL.md files written to an isolated ~/.omp/agent/managed-skills directory that is
discovered and surfaced like authored skills but never overwrites them.
Two tools back this:
- `manage_skill` — create/update/delete managed skills.
- `learn` — record a lesson, optionally minting/enhancing a managed skill in the
same call (requires a hindsight/mnemopi memory backend).
The nudge is passive by default (a hidden reminder rides the next turn);
`autolearn.autoContinue` instead auto-runs one capture turn at stop, and
`autolearn.minToolCalls` (default 5) gates trivial turns. Plan/goal-mode turns and
subagents are never nudged, and the controller re-checks the live setting at fire
time so a mid-session opt-out takes effect.
Isolation & precedence: managed skills are a separate lowest-priority discovery
provider, so an authored skill of the same name wins across every provider and
custom directory regardless of third-party toggles; a disabled higher-priority
authored skill can never hide a managed one, and managed never masks an enabled
authored skill. Managed names and descriptions are sanitized on both write and
read (control/format chars, angle brackets, and Markdown fences) before they render
into the system prompt, and the SKILL.md byte cap is enforced on the final
serialized file.
Default off → zero footprint when disabled.
- Added session-domain modules and exports for session-entries, context, listing, loader, and migrations.
- Changed persistence to async append writes plus writeTextAtomic, removing sync line APIs.
- Added compaction-aware session context rebuild with dangling tool-call cleanup.
- Added resumable session resolution with status inference, id/stem/suffix matching, and backup recovery.
Add a display-only `activity` field to AgentRef plus `setActivity`, fed
from the subagent progress chokepoint with a short gist of the agent's
latest intent (or current tool). Render it in the `irc list` output, the
subagent peer roster, and the TUI peer card, beside the role-derived
display name. setActivity emits no event — the roster reads on demand —
so the per-tool-call rate stays off the registry listener path. Peers
with no activity render without a dangling clause.
Refs #2470
Op: extend
When a spawner with remaining depth capacity spawns generic role-less
workers (a task/quick_task spawn without a `role`, or the same agent
cloned >=2x all without roles), TaskTool.execute appends a non-blocking
advisory steering it toward tailored specialists. Gated on DepthCapacity
so a leaf at max recursion is never nudged; the task-tool depth gate is
extracted into a shared `canSpawnAtDepth` helper reused by both the tool
gate and the advisory.
Refs #2469
Op: extend
- Added a reusable notice constant for executable write operations.
- Appended the executable notice to write-result output whenever a file was made executable.
- Extended gateway stream control to pass abort signals and onCancel into encodeStream.
- Added optional cancellation control parameters to provider encodeStream handlers.
- Stopped provider stream loops on cancellation and suppressed SSE completion/error output after abort.
- Added a regression test verifying reader.cancel triggers onCancel and aborts upstream request.
- Added cmux browser mode options and resolved mode selection from env and app flags.
- Added cmux tab operations for navigation, JS execution, observations, and screenshots.
- Added CMUX socket client messaging with auth, timeouts, and ordered request dispatch.
- Updated browser docs and examples to describe cmux behavior, selectors, and API limits.
- Added getActiveModel support to session/tool interfaces for propagating active model objects.
- Added model capability helpers to flag WebP-unfriendly Ollama backends for image resize options.
- Updated image normalization and loading to auto-disable/reencode WebP when model constraints require it.
Concurrent omp --session restores after an unclean shutdown crashed
in SqliteAuthCredentialStore.#initializeSchema() with
SQLITE_BUSY_RECOVERY because the multi-statement schema run installed
PRAGMA busy_timeout=5000 AFTER PRAGMA journal_mode=WAL, the first
lock-taking statement during WAL recovery. Bun's default busy_timeout
is 0, so the lock conflict surfaces immediately.
- packages/ai/src/auth-storage.ts: hoisted PRAGMA busy_timeout to a
standalone first statement, dropped it from the multi-statement
schema run, wrapped SqliteAuthCredentialStore.open() in a 4-attempt
exponential-backoff retry loop on the SQLITE_BUSY family, and the
exhausted-retry error now includes the DB path. Exported
isSqliteBusyError(err) (matches code prefix 'SQLITE_BUSY').
- packages/coding-agent/src/session/agent-storage.ts: same hoist and
the existing retry loop now uses isSqliteBusyError so
SQLITE_BUSY_RECOVERY / _SNAPSHOT / _TIMEOUT also trigger backoff.
- Hoisted busy_timeout before journal_mode=WAL in every other shared
SQLite open path: history-storage, autoresearch/storage,
memories/storage, github-cache, report-tool-issue (auto-QA),
catalog/model-cache; stats/db.ts now sets busy_timeout at all.
- packages/ai/test/auth-storage-sqlite-busy.test.ts pins the contract:
isSqliteBusyError matches every BUSY extended code (rejects
SQLITE_LOCKED, non-errors, strings); open() leaves the connection in
WAL mode (proves busy_timeout ran before journal_mode); open() retries
through synthetic SQLITE_BUSY_RECOVERY; non-BUSY errors (SQLITE_CORRUPT)
short-circuit; exhausted retries throw an error mentioning the DB path
with exactly 3 sleeps for a 4-attempt budget.
Fixes#2421
Format multi-line, tab-indented AST patterns by collapsing whitespace
to single spaces, preventing them from distorting the single-line status
description in the UI.