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.
- Added `is_implementation_authorizer` check requiring OWNER or allowlisted maintainer to authorize implementation work.
- Blocked `gh_push_branch` and `gh_open_pr` for unclassified/enhancement/proposal issues without explicit directive authorization.
- Auto-allowed bug and documentation issues without requiring a directive.
- Propagated `authorizes_impl` flag through events, server, tasks, and worker bindings.
- Added T co-signal requirement for tool_arg surface so legitimate edits carrying the marker are never hard-aborted.
- Extended detectHarmonyLeakInAssistantMessage with optional toolArgParseEnd resolver; agent loop omits it, keeping tool_arg inert.
- Updated tests to inject a boundary-at-0 helper for corpus cases and added T-gate unit tests.
- 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
- Added `review_pr` task that checks out PR head in a detached worktree, classifies rank/type/area, and posts a batched GitHub review as `event=COMMENT`.
- Added four new host tools: `fetch_pr`, `classify_pr`, `pr_review_comment`, and `submit_pr_review`; review tools self-gate on `review_mode`, push/open-PR tools refuse when `review_mode` is set.
- Added sqlite staging table `pr_review_comments` with `stage_review_comment`, `list_staged_review_comments`, and `clear_staged_review_comments` DAOs.
- Routed `pull_request.opened/reopened/ready_for_review` to `review_pr` and extended `pull_request.closed` cleanup to any tracked PR regardless of author.
- Added `terminalHasEagerEraseScrollbackRisk` to detect WezTerm, kitty, ghostty, and alacritty on POSIX, where xterm ED3 (`CSI 3 J`) can snap scrolled-up readers back to the tail during streaming.
- Kept direct user-input and checkpoint rebuilds unaffected by the deferral.
- Added regression tests covering the deferred and non-deferred paths (issue #1682).
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.