- Added local CONNECT proxy with TLS interception to capture Claude API traffic.
- Drives Claude Code via headless PTY/xterm and extracts the first /v1/messages exchange.
- Added `claude:trace` npm script and CLI with JSON/text output modes.
- Added integration test using a fake Claude script against a local TLS server.
- Derived Anthropic and session metadata `device_id` from `getInstallId()` deterministically.
- Added CLAUDE bootstrap identity lookup and merged fallback into token exchange/refresh.
- Recovered `accountId` and `email` during token exchange/refresh when token payloads lacked them.
- Enforced bootstrap failures for non-OK responses and invalid JSON payloads.
ExaProvider.isAvailable() and searchExa() now consult AuthStorage so Exa credentials configured through the broker/credential store work alongside EXA_API_KEY, matching the other API-key search providers.
Refs #1695
- Passed ANTHROPIC_SEARCH_BASE_URL through to Anthropic web search calls that use authStorage fallback credentials instead of only applying it with ANTHROPIC_SEARCH_API_KEY.
- Added regression coverage asserting fallback Anthropic credentials use the search-specific base URL.
- Updated the environment and web_search docs to reflect the actual credential and base URL resolution order.
Fixes#1694
The Anthropic web search path built request headers via buildAnthropicSearchHeaders, which never threaded model headers through buildAnthropicHeaders, so ANTHROPIC_CUSTOM_HEADERS was dropped from every web-search request regardless of mode. The streaming path's resolveAnthropicCustomHeaders also gated on isFoundryEnabled(), so users with a corporate ANTHROPIC_BASE_URL + ANTHROPIC_CUSTOM_HEADERS (e.g. X-Gateway-Key) got 401s on web_search unless they set CLAUDE_CODE_USE_FOUNDRY=true.
Loosen the resolver to also apply when ANTHROPIC_BASE_URL points to a non-Anthropic host, export the baseUrl-keyed variant, and have buildAnthropicSearchHeaders pass the resolved custom headers as modelHeaders so search and streaming paths behave identically. Stock api.anthropic.com (no Foundry) still omits the headers.
Fixes#1693
- Expanded the existing entries in docs/environment-variables.md so the override-semantics ('search-only, isolates from main ANTHROPIC_API_KEY / ANTHROPIC_BASE_URL / FOUNDRY_BASE_URL') are spelled out, and added a usage note for enterprise-gateway split routing.
- Surfaced the search-only env vars (ANTHROPIC_SEARCH_API_KEY / ANTHROPIC_SEARCH_BASE_URL / ANTHROPIC_SEARCH_MODEL) in the Anthropic provider section of docs/tools/web_search.md, where users were already looking.
- Added ANTHROPIC_SEARCH_BASE_URL alongside ANTHROPIC_SEARCH_API_KEY in 'omp --help' so the pair shows up together in the CLI env-var summary.
Fixes#1694
Post-extension session-model retry now covers the case where the initial restore failed entirely (e.g. saved default unavailable, last active role supplied by an extension) and the settings default filled in the active model. Also recomputes thinking-level from full precedence against the reclaimed model so a fallback model's defaultLevel does not become sticky.\n\nFixes #1649
Initial startup resume runs before extension providers register, so a role model supplied by an extension fell back to the saved default. Retry the preferred session-model candidates once provider registrations are processed and re-resolve thinking level for the new model.\n\nFixes #1649
Treat temporary model_change roles as non-restorable when resuming sessions so context-promotion and retry-fallback models do not override the saved default.\n\nFixes #1649
Try the last active role model first, then the saved default model when the role model cannot be restored during session switching or startup resume.\n\nFixes #1649
Use the last model_change role when resuming an existing session instead of always restoring models.default. Covered both /resume switchSession and startup continue paths.\n\nFixes #1649
Address review of the in-place loader: the directory-subtree filter had two
regressions vs the old mirror.
- It only rewrote files under the entry's package root, so a `dist/`
entry importing `../../shared/helper.ts` (or a symlink-escaping sibling)
left that module's legacy `@(scope)/pi-*` / `@sinclair/typebox` imports
un-rewritten.
- `findExtensionRoot` walked up to the nearest package.json, which for an
ad-hoc extension under a project (e.g. `/repo/.omp/extensions/foo.ts`)
resolved to the project root — so the permanent onLoad hook would then
rewrite unrelated project/host source imported later.
Replace the directory filter with a precise scope: pre-walk the entry's
relative-import graph (static + dynamic `./`/`../` specifiers), collect each
module's realpath, and build the onLoad filter as an exact-path alternation
of just those modules. This matches exactly the set the old mirror tracked
(minus the copy): it covers `../src`/symlinked siblings and never touches
the host, other extensions, node_modules deps, or unrelated project files.
Adds a regression test that a non-imported sibling stays outside the rewrite
scope, and renames the ../src test to reflect graph-following.
Legacy Pi extensions were mirrored module-by-module into a flat temp dir
(`omp-legacy-pi-file/entry-<hash>/`) with imports rewritten to absolute
URLs. Running from that temp root made `import.meta.url`/`__dirname`
resolve to the mirror, so `readFileSync(join(__dirname, "ui.html"))`-style
asset loads ENOENT'd — e.g. @plannotator/pi-extension's HTML never loaded
and it auto-approved plans (#1674). The standing remedy (#1675) copied
~30MB of .html/.css per startup with a fragile extension whitelist.
Bun's runtime plugins don't fire onResolve for transitive imports, which
is why the mirror pre-resolved everything. But onLoad does fire
transitively for file-namespace modules matching its filter, and a real
file import keeps import.meta.url pointing at the source. So:
- Load the extension entry in place via `import(pathToFileURL(real))`;
realpath first so the path matches what Bun hands onLoad (macOS
/var->/private/var, bun link/pnpm symlinks).
- Register one Bun.plugin() onLoad per extension *package root* (nearest
package.json), filtered to that root's .js/.ts but excluding any
node_modules segment, that rewrites only `@(scope)/pi-*` and the bare
`@sinclair/typebox` specifier to absolute bundled/shim URLs.
- Everything else — relative siblings (incl. ../src), the extension's own
node_modules deps (CJS/ESM), and bundled assets — resolves natively.
Removes the flat mirror, the temp-dir writes, the asset-copy problem, and
the now-dead `omp-legacy-pi-file:` namespace machinery. import.meta.url is
the real source file, so assets resolve exactly as under the original Pi
runtime. Adds an in-place load regression test covering asset reads,
submodule .css siblings, node_modules-excluded native deps, and
package-root-scoped ../src rewrites.
Fixes#1674.
- Added `expectSleepNear` to allow ±100ms variance on sleep duration checks.
- Updated `--thinking` test value from `"extended"` to `Effort.XHigh` enum constant.
- Converted existing local paths to Windows paths via `wslpath -w` before opening.
- Used `wslview` directly in WSL environments, bypassing `xdg-open`'s broken file-handler translation.
- Fell back to `xdg-open` for URLs or when `wslview` is unavailable.
- Added unit tests covering WSL file, URL, and fallback scenarios.
Replace the sunset V0 Search API with V1 (POST /api/v1/search) under the
existing `kagi` provider id instead of shipping a parallel `kagi-v1`
provider. Credentials still resolve through the shared AuthStorage broker
(Bearer token, KAGI_API_KEY, /login kagi), and recency now maps to a
UTC-deterministic filters.after date.
- Merge V1 client into src/web/kagi.ts (categorized result buckets, direct
answer, related/adjacent questions)
- Keep classifyProviderHttpError mapping for auth/quota signals
- Drop the kagi-v1 entries from the provider registry, order, type union,
and settings schema
- Consolidate tests into web-search-kagi.test.ts
omp resolves the update target by querying https://registry.npmjs.org/ directly, but `bun install -g pkg@<version>` would then consult bun's on-disk manifest snapshot AND honour the user's npm-mirror configuration (corporate proxy, Taobao, …). Either source can lag the upstream registry by minutes-to-hours, in which case bun rejects the version with `No version matching "X" found for specifier "@oh-my-pi/pi-coding-agent" (but package exists)` even though the registry omp just queried is serving it.
The bun install step now runs with both `--no-cache` (skip the manifest snapshot) and `--registry=https://registry.npmjs.org/` (pin the official catalog regardless of bunfig/.npmrc) so the install observes the same registry state the version check used. The registry URL is centralised in an `NPM_REGISTRY` constant shared by `getLatestRelease` and `buildBunInstallArgs`.
Fixes#1686
- Changed `AgentOutputManager` to use requested names verbatim, adding `-2`/`-3` suffixes only on repeats (e.g. `Anna`, `Anna-2`).
- Renamed main agent id from `0-Main` to `Main`; nested ids now use dot notation without numeric prefix (e.g. `Parent.Child`).
- Updated task widget to render dotted hierarchy as `Parent>Child` breadcrumb without leading index.
- Resume scan now tracks seen names instead of a counter to avoid clobbering prior outputs.
- Removed the `concurrency` argument from `parallel()` and `pipeline()` in both JS and Python runtimes.
- Added `__concurrency__` bridge to resolve the pool ceiling live from `task.maxConcurrency` (default 32; 0 = unbounded).
- Eval fan-outs now run as wide as a `task` tool batch instead of being capped at 16.
- Encouraged staging helpers, datasets, and clients once, then fanning out subagents that call them directly.
- Clarified that re-importing, re-fetching, or serializing across the task boundary is unnecessary.
- Updated the role contract to allow direct trivial edits while reserving substantial work for subagents.
- Reinforced that parallel work must be fanned out broadly and that one-off task dispatches are disallowed.
- Clarified that subagents make edits only, while the orchestrator runs verification for changed files.
- Tracked the latest in-flight preview diff recompute in ToolExecutionComponent and exposed it through a new whenPreviewSettled method.
- Updated component paths that trigger preview recomputation to retain the returned promise instead of fire-and-forget calls.
- Updated the streaming preview height test to await settled diff recomputation before assertions, eliminating requestRender race-based flakes.
- Added `Settings.reloadForCwd` to mutate the live instance in place, so `/move` and cross-project resume pick up the destination project's `.claude/settings.yml` and path-scoped `enabledModels`/`disabledProviders`.
- Wired `reloadForCwd` into `applyCwdChange` (interactive mode) and the `--resume` startup path so settings always follow the active working directory.
- Added tests covering path-scoped re-resolution, no-op on same directory, and disk-backed project layer load/drop.
- Enabled resume picker to preload sessions and toggle folder/all scope with Tab.
- Enabled resume flow to fall back to all-project sessions and switch cwd on resume.
- Added centralized applyCwdChange to refresh caches, commands, and UI after cwd updates.
- Updated session restoration to adopt restored session cwd and sessionDir when present.
- Added ROW_COUNT_PROBE_CAP to limit rows scanned when counting tables, preventing JS thread freezes on large databases.
- Used sqlite_stat1 estimates for tables exceeding the cap; exact counts only for provably small tables.
- Introduced TableRowCount type with exact/estimate/atLeast variants reflected in rendered output.
- Fixed `session_id` never being created or populated; every history row had `NULL` for session.
- Added schema migration (`ALTER TABLE history ADD COLUMN session_id`) for pre-existing databases.
- Wired interactive mode to call `setSessionResolver(...)` so prompts are stamped with the active session at submission time.
- Re-enabled session ranking in `--resume` and in-session pickers via `matchingSessionIds()`, merging fuzzy and prompt-history signals.