git clone --depth 1 --single-branch only fetches the tip of the
requested branch, so any subsequent git checkout <sha> for a non-tip
commit fails with 'reference is not a tree'. The error was caught and
rethrown as 'shallow clone may not contain this commit', but the clone
arguments were never adjusted.
Drop --depth 1 (and --single-branch when no ref is requested) when the
caller supplies options.sha so the desired commit is present in the
local object store. The ref-only path remains shallow.
Fixes#1589
- Dropped `summarizeShakeRegions`, the shake-summary prompt, and related types.
- Removed `shake-summary` compaction strategy and `providers.shakeSummaryModel` setting.
- Migrated existing `shake-summary` configs to plain `shake` on load.
- Simplified `/shake` to `elide` and `images` modes only.
- Fixed Anthropic stream idle-timeout errors incorrectly triggering provider retries after streaming had begun.
- Fixed darwin-x64 `bun build --compile` failure by guarding `onnxruntime-node` preload behind a `process.platform === "win32"` literal for dead-code elimination.
- Added `prefill` and `stop` parameters to the tiny-model worker's `complete` message type to pin output format without biasing content.
- Defaulted the test createAgentSession input to an empty object before spreading.
- Computed workspaceTree from the normalized options, preserving the cwd fallback behavior.
- Added `!streamedReplayUnsafeContent` guard to `canRetryProviderFailure` to avoid replaying unsafe content on retry.
- Updated test fixtures to supply a required `workspaceTree` parameter via a shared `emptyWorkspaceTree` helper.
- Updated toggleToolOutputExpansion to pass allowUnknownViewportMutation when requesting render.
- Added a test that verifies tool output toggling sets expansion state and calls requestRender with the new flag.
- Documented the Ctrl+O POSIX tool-result expansion scrollback fix in the changelog.
- Added a post-dispatch refresh hook to recompute foreground tool render mode after key turn/tool events.
- Computed whether any non-background pending tool is active and toggled eager native scrollback rebuild accordingly.
- Added a regression test confirming eager rebuild is enabled while foreground tools are pending and disabled when none remain.
- Added a system prompt instruction to never re-audit applied edits.
- Added guidance to avoid routine `git status` and `git diff` checks, with exceptions for explicit requests and selective repo operations.
- Replaced the streaming edit diff rendering strategy with a fixed-height trailing window so partial re-diff streams stayed anchored and stopped oscillating.
- Updated streaming preview tests to assert the window remained saturated without trailing blank padding across chunked updates and still produced a real diff after finalization.
- Tuned TUI viewport repaint heuristics for pure appends and multiplexer sessions, and adjusted render-stress handling for preserved tmux scrollback.
- Preserved hidden tmux overlays in live viewport while keeping native scrollback intact during forced renders.
- Adjusted forced-render handling so pure appends preserve full scrollback and return viewport repaint on equal-size diffs.
- Capped streaming edit diff previews to a fixed trailing window and reported hidden hunk counts.
- Updated tmux and regression tests to validate hidden overlays, nativeText frame sources, and scrollback retention.
- Removed stream preview height tracking and simplified tool call rendering to always invalidate the content box.
- Changed eval timeout behavior from hard wall-clock deadlines to per-cell inactivity budgets in all executors.
- Added IdleTimeout watchdog support, including bumps on status/tool activity and timer cleanup after execution.
- Updated executor option plumbing to replace deadlineMs with idleTimeoutMs and emit inactivity timeout annotations.
- Added IdleTimeout and shared-executor tests and updated prompt/repl docs for the new timeout contract.
- Added markdown prose tests to verify maskNonProse preserves plain prose and masks fenced/tilde blocks.
- Added keyword-in-prose tests that enforced lowercase token matching and ignored code spans, fences, XML, and comments.
- Added highlight-mode tests ensuring only prose keywords are ANSI-highlighted and inline/fenced/XML regions stay unmodified.
- Added workflow/orchestrate assertions that uppercase or path-like forms remain unchanged while lowercase token boundaries are handled correctly.
- Replaced composed keyword decorators in `CustomEditor.decorateText` with `highlightMagicKeywords`.
- Adjusted `UserMessageComponent` rendering to use `highlightMagicKeywords` with `keywordReset` for consistent foreground.
- Added `highlightMagicKeywords(text: string, resetTo?: string): string` and chained ultrathink, orchestrate, workflow glow.
- Updated ultrathink, orchestrate, and workflow matching to lowercase whitespace-delimited patterns with prose-only checks.
- Added `maskNonProse` and `keywordInProse` to skip fenced/inline code and HTML/XML segments while highlighting keywords.
- Added `KeywordHighlighter` with optional `resetTo`, and updated gradient highlighting to use masked match slicing.
- Added overlayRebuild intent, refactored forced-frame prep around base lines, and added frame dump support.
- Updated forced-render prep to preserve forced flags, allow unknown viewport mutation, and clear scrollback on resize.
- Introduced #syncChildOrder for child attach/reorder and skipped duplicate checks when after.atBottom was false.
- Added streaming-preview test scaffolding with VirtualTerminal, settleTerminal draining, and normalized row helpers.
- Added optional `onStatus` callback wiring across eval backends and JS/Python executors for live status streams.
- Added collectDisplay-based forwarding so `emitStatus` and `onDisplay` route status outputs consistently.
- Expanded agent status payloads with preview/model/token-cost context and kept completion updates single-pass.
- Added status upsert and render adjustments in `tools/eval.ts` to coalesce agent events with progress stats.
- Added status/progress test coverage for running/completed agent events, final metric retention, and parallel placement.
- Updated CHANGELOG Unreleased notes to record live progress updates and completion-status metric fixes.
- Added +Nk/+Nm turn-budget parsing with whitespace-boundary matching, multipliers, and hard `!` indicator.
- Added per-turn budget lifecycle plus APIs (`getTurnBudget`, `recordEvalSubagentUsage`) and hard-cap checks in eval runs.
- Added hard budget observability in eval preludes and docs by exposing `budget.hard` and documenting ceiling modes.
- Fixed streaming preview stutter with max-row tracking and padding, with tests for preview height and budget parsing.
- Dropped `args` input from eval tool schema, JS/Python executors, and worker protocol.
- Removed per-call `args` injection from JS runtime and Python kernel/runner.
- Deleted related tests and updated docs to reflect removal.
- Replaced ad-hoc ANSI/VT stripping regexes with `stripVTControlCharacters` in status text handling and related tests.
- Updated status footer rendering to truncate using `truncateToWidth` and visible width after VT stripping.
- Extended tui cursor handling and rendering to strip markers from all lines and fit repaint/append-tail lines to width.
- Expanded deterministic render tests with overlay-aware assertions and recorded the truncation/cursor-marker behavior in changelogs.
- Added fuzzy token matching in agent-dashboard, state-manager, and tree-selector, replacing lowercased checks.
- Added search-query state and fuzzy-filter helpers to hook, oauth, and user-message selectors for query filtering.
- Updated filtered selectors to render match results, status lines, no-match text, and move selection within results.
- Added `overflowSearch` and filter state to `SelectList`, switching overflowing list matching to fuzzy checks.
- Configured `SelectList` input flow and fixed cancel so Escape/Ctrl+C closes lists when no matches exist.
- Updated changelogs and added tests for fuzzy-filter behavior in hook, oauth, user-message, and list selectors.
- Added `agent()` in JS/Python preludes to call host bridge and parse returned text when schema is set.
- Added JS `parallel()` and `pipeline()` with bounded `__pool()` pools and concurrency normalization.
- Added `runEvalAgent` bridge logic with argument parsing plus plan-mode, allowlist, depth, and artifacts checks.
- Added tool routing and tests documenting new `agent/parallel/pipeline` behavior, defaults, and validation failures.
- Stored mcpManager and localProtocolOptions on ToolSession so nested subagents inherit them without relying on process-global singletons.
- TaskTool now uses the session's localProtocolOptions and mcpManager when spawning sub-tasks, falling back to defaults if absent.
- Previously the slider started at the current cycle index, so execution would inherit whichever model drove planning.
- Now finds the `default` role in the cycle and anchors the slider there, falling back to `currentIndex` if no default exists.
- Explicit `executionModel` is set whenever the chosen tier differs from the restored cycle position, covering the case where the slider stays on `default` but planning ran on another model.
Follow-up to #1503. When an extension registered a flag whose name collides
with a value-taking built-in — e.g. plan-mode's boolean `--plan` vs the
built-in `--plan <plan-model>` selector — the extension-aware reparse still
took the built-in branch. `omp --extension plan-mode --plan "review the diff"`
consumed "review the diff" as the plan-model value, leaving parsed.messages
empty and overwriting result.plan with the prompt text. recoverFlagValue only
patched the extension flag value, not the corrupted parsed object that
applyExtensionFlags returns as initialArgs.
Fix at the source: parseArgs now checks the registered extension-flag set
BEFORE the built-in branches, so a registered flag is parsed with the
extension's semantics (boolean toggle / string value) and surfaces in
unknownFlags without consuming the following token or touching the built-in
field. This makes recoverFlagValue dead, so applyExtensionFlags is simplified
to read resolved values straight from unknownFlags.
Tests: parseArgs-level shadowing guard (boolean --plan keeps the message and
leaves result.plan unset); applyExtensionFlags message/built-in-field
preservation for colliding boolean (--plan) and string (--model) flags;
non-colliding flag-looking-value rule retained. Verified the new guards fail
without the shadowing fix.
- Dropped `onShowHotkeys` callback and its binding from `CustomEditor` and `InputController`.
- `?` now inserts a literal question mark regardless of editor state; use `/hotkeys` explicitly.
- Added regression test confirming `?` is treated as plain input when the editor is empty.
Two review fixes for the extension-flag/initial-prompt work:
1. @file ordering — `processFileArguments` runs `process.exit(1)` on a
missing/unreadable file. It had been moved after `createSession`, which
writes the terminal breadcrumb eagerly (SessionManager.create →
#newSessionSync), so `omp @missing.md "x"` left a junk session/breadcrumb
behind before exiting.
Resolve extension-registered CLI flags BEFORE creating the session: load the
session's extensions up front (new `loadSessionExtensions` helper, the single
source of createAgentSession's discovery-branch logic), build an
ExtensionFlagSink straight from the loaded extensions + runtime, re-parse
argv, then process @file args — all before any session exists. The loaded
result is handed back to createAgentSession via `preloadedExtensions` (now
checked before `disableExtensionDiscovery`, so it can't double-load) and the
same EventBus is shared, so no extra work. This keeps the P1#1 fix
(`--flag @value` is the flag's value, not a file) while failing fast with no
session side effects.
2. "Can we avoid the big list of names?" — removed the hand-maintained
`BUILTIN_FLAG_NAMES` set (and its stale "rejected at registration" doc).
`applyExtensionFlags` now always falls back to recovering a flag's value from
argv when parseArgs didn't surface it; the recovery scan mirrors parseArgs's
consumption rules (flag-looking space-form values stay their own flag) and is
a no-op for flags that were absent or already surfaced, so no list of
built-in names is needed.
Adds `ExtensionRunner.aggregateFlags` (static) so getFlags and the CLI's
pre-session sink share one implementation.
Tests: pre-session flag resolution via the exact main.ts sink pattern;
list-free recovery of an arbitrary colliding built-in (`--model`); and the
flag-looking-value rule. Verified typecheck + extension/runner/acp suites.
- Restricted `setModel` to persist settings only when `persist: true` is passed; all runtime switches (Ctrl+P, `--model`, `/model`, model picker temp selections) no longer overwrite `modelRoles.default`.
- Changed `cycleRoleModels` to accept a direction ("forward"/"backward") instead of a `temporary` flag; both directions now use `applyRoleModel` without persisting.
- Added `persist: true` exclusively to the model picker's "Set as default" action in `SelectorController`.
- Added test suite covering persistence behavior for `setModel`, `cycleRoleModels`, and `cycleModel`.
- Removed `ModelRegistry.create` and updated construction sites to use `new ModelRegistry` directly.
- Dropped the async `ConfigFile` migration warmup path and switched migration handling to the unified `#ensureMigrated` logic used by relocate and load flows.
- Adjusted model registry tests to instantiate `ModelRegistry` through the constructor.
- Defined `EmbeddingRow` and `EmbeddingOutput` in runtime options and exported them from core embeddings.
- Updated `EmbeddingProvider`, `MnemosyneEmbeddingProvider`, and `provider` runtime option types to return `EmbeddingOutput` instead of `unknown`.
- Refactored embedding result normalization to accept typed rows and sync/async batches and coerce them into validated `Float32Array` vectors.
- Updated each package's test script to run `bun test` with the `--parallel` flag.
- Updated the tui package test command to preserve its `test/*.test.ts` file filter while enabling parallel execution.
- Mocked `watchBranch` in LSP startup test to prevent real `fs.watch` from triggering Bun SIGTRAP in parallel workers.
- Moved `refreshBaseSystemPrompt` assertion inside the `await` block where it belongs.
Codex review on #1527 flagged that the documented forms
`git+https://github.com/user/repo` and `git@github.com:user/repo` still
fell through to the npm install path. `git+https` was rejected by the
package-name validator; scp-style `git@…` passed the validator but then
resolved `actualName` via `extractPackageName` to `git` (everything before
the `@`), causing the post-install package.json lookup to fail at
`node_modules/git/package.json`.
- `parseGitUrl`: strip leading `git+` (forwarded to bun/git as-is) and
extend the protocol gate to also accept scp-like `git@host:user/repo`.
The scp form is unambiguous — no local path starts with `git@` — and
matches what `git clone` itself takes.
- `isGitSpec` now returns true for both forms, routing them through the
snapshot/diff path in `PluginManager.install` so the real package name
is discovered correctly.
- Tests: flip the two cases that asserted rejection, add ref and
`git+ssh` coverage. Verified end-to-end:
`PluginManager.install('git+https://github.com/oldschoola/omp-insights')`
installs `@oldschoola/omp-insights@1.2.3`.
Extends `omp plugin install` to accept git sources alongside npm specs and
marketplace refs. Bun's installer already understands git URLs; the blocker
was `PluginManager.install`'s strict npm-name validator and the assumption
that the actual package name could be derived from the spec.
- `git-url.ts`: `parseGitUrl` now recognizes npm-style namespaced shorthand
(`github:user/repo`, `gitlab:`, `bitbucket:`, `codeberg:`, `sourcehut:` /
`srht:`), with optional `#ref` and `.git` suffix. Exposes `isGitSpec` as
`parseGitUrl(s) !== null`. Existing protocol-URL and `git:` shorthand paths
are untouched.
- `manager.ts`: `install()` branches on `isGitSpec`. Git specs go through a
separate `validateGitSpec` (shell-metachar rejection only — `/`, `:`, `@`,
`#`, `+` are legal) and the real package name is discovered by snapshotting
`plugins/package.json` deps before `bun install` and diffing afterwards.
Falls back to value-match on force-reinstall where the key already exists.
- Help text in `plugin-cli` documents the new sources and adds a github:
example.
Smoke tested end-to-end on Windows with both forms against the test repo:
PluginManager.install('github:oldschoola/omp-insights')
PluginManager.install('https://github.com/oldschoola/omp-insights')
both resolve `@oldschoola/omp-insights@1.2.3` and write a correct lock entry.
Shell-injection probe (`github:foo/bar; rm -rf /`) is rejected.
F6: defer the JSON -> YAML migration out of ConfigFile's constructor and
add an async path so the boot sequence stops blocking the event loop on
sync I/O. New ConfigFile.tryLoadAsync/loadAsync/loadOrDefaultAsync/
getMtimeMsAsync and static ConfigFile.warmup. The migration is now
idempotent (per-process cache) so relocate() does not re-run it.
ModelRegistry.create(authStorage, modelsPath?) is a new async factory
that runs the warmup before the sync constructor's bundled-model load.
Production call sites (main.ts, sdk.ts, task/executor.ts, commit
pipelines, SDK example) all switched. Sync new ModelRegistry(...)
constructor is still supported for tests.
F2: rewrite MemorySessionStorage's mirror as { chunks: string[]; byteLen;
mtimeMs } so writeLineSync appends a single chunk in O(1) instead of
read-modify-writing the entire file (which was O(N) per append, O(N^2)
per session). statSync now reports true UTF-8 byte length instead of
character count. readTextPrefix walks chunks until the byte budget is
exhausted instead of materialising the full mirror.
Also rolls in per-package CHANGELOG entries for F1-F8.
F3 (agent): mutate state.messages and state.pendingToolCalls in place on
appendMessage/popMessage/clearMessages/reset/tool_execution_start/_end
instead of allocating a fresh array/Set on every transition. Subscribers
that capture state.messages by reference now observe updates directly.
Public type signature unchanged.
F5 (ai): add parseStreamingJsonThrottled to utils/json-parse — a per-delta
wrapper around parseStreamingJson that skips the re-parse until the
buffer has grown by minGrowthBytes (default 256). Wired into every
provider's tool-call argument accumulator (anthropic, amazon-bedrock,
openai-completions, openai-codex-responses, openai-responses-shared) so
per-delta cost becomes O(N) in total buffer length instead of O(N²).
Every provider's toolcall_end still runs a final unthrottled parse, so
the published block.arguments is unchanged.
F8 (coding-agent): drop the per-delta structuredClone of streaming tool
arguments in ToolExecutionComponent.updateArgs. event-controller.ts and
ui-helpers.ts already spread their input into a fresh object on each
delta, so cloning here was dead work on the rendering hot path. Added a
reference-equality short-circuit so repeat calls with the same args
object skip the preview-diff and display refresh.