Redirected legacy pi-ai utils/oauth subpaths through the compatibility loader so background workers load the relocated OAuth registry modules.\n\nFixes #2566
The package-root override branch of `resolveCanonicalPiSpecifier` returned
the bunfs override path without checking the target was actually present,
so when `bun --compile` quietly dropped one of the extra entrypoints
(observed on macOS arm64 release binaries), the static rewrite emitted a
`file://` URL to a missing module. The #1216 fallback only fired on the
throwing `getResolvedSpecifier` path, so the override never threw and the
rewrite committed the bad URL — extensions silently failed to load.
Each override target is now checked with `fs.existsSync` at module init.
Missing entries are dropped from `LEGACY_PI_PACKAGE_ROOT_OVERRIDES` so
`resolveCanonicalPiSpecifier` falls through to `getResolvedSpecifier`,
which throws under bunfs and triggers the existing rewrite catch — Bun
then resolves the canonical `@oh-my-pi/pi-*` specifier from the
extension's own `node_modules`.
Fixes#2168
- Derived descriptors, default-model map, env keys, login list, and refresh dispatch from one ProviderDefinition per provider.
- Disabled OpenAI Codex stream obfuscation and interrupted whitespace-only tool-call argument deltas.
- Derived auth-broker callback ports and paste-code login set from the registry.
- Aligned handoff, reminder, and system-prompt expectations with shortened copy.
- Added HTTP transport test for required initialize failures.
- Guarded SSE startup timeout against stale connection races.
- Grouped `isRepository`, `workspaceRoot`, and `clearWorkspaceRootCache` under a `repo` namespace (`repo.is`, `repo.root`, `repo.clearRootCache`).
- Promoted `diff` to a named export with a `changedFiles` sub-method via `Object.assign`.
- Added `ensureAvailable` check and `nameOnly` support to `diff`.
- Updated callers and tests to use the new API surface.
- Replaced `jj workspace root` subprocess call with a local `.jj/repo/store` directory traversal, eliminating process spawning overhead.
- Added LRU cache for resolved workspace roots to avoid redundant filesystem walks.
- Renamed internal `runCommand` helpers to `git`/`jj` for clarity.
- Replaced git subprocess setup in review test with mocked `git.status` and `git.diff` calls.
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.
Bun 1.3 compiled modules report the bunfs mount root from import.meta.dir, not their source-layout module directory. The prior helper walked four directories above that value and escaped the embedded root.
Append packages to the compiled bunfs root, while keeping a guarded suffix path for future module-specific import.meta.dir semantics. Update regression tests to pin the compiled-root behavior observed by a bun build --compile probe.
Fixes#1514
External extensions importing @oh-my-pi/pi-* values (e.g. AssistantMessageEventStream from @oh-my-pi/pi-ai) failed on Windows compiled binaries with "Cannot find package $bunfs\\root\\packages\\...". Shim paths in LEGACY_PI_PACKAGE_ROOT_OVERRIDES were built from a hardcoded POSIX literal "/$bunfs/root/packages"; Win32 normalised the leading slash to a backslash and the path never resolved against the real bunfs mount (<drive>:\\~BUN\\root\\...).
Derive the bunfs package root by walking four directories up from import.meta.dir (which oven-sh/bun#15766 confirms returns the platform-native bunfs path inside the binary). All override targets now go through path.join, so separators stay native on Windows, Linux, and macOS.
Fixes#1514
- Mocked the Vertex stream E2E test to override the home directory and clear GOOGLE_APPLICATION_CREDENTIALS so token resolution uses metadata credentials instead of local ADC files.
- Updated wafer and model-registry test expectations to match current model metadata values (Qwen3.7 Max and claude-opus-4-8).
Limited bunfs package-root overrides to compiled-binary mode so non-compiled installs (monorepo, source-link, node_modules) keep resolving legacy pi roots through Bun's package resolver instead of a hardcoded source-tree path.
Refs #1474
Retried original legacy specifiers after canonical peer fallback fails so direct plugin imports with only legacy-scoped peer dependencies continue to load.
Added bundled root overrides for legacy pi package imports in compiled binaries and corrected fallback resolution to use canonical @oh-my-pi specifiers.
Fixes#1474
Plannotator-class legacy extensions still import `Type` from
`@(scope)/pi-ai` (e.g. `@earendil-works/pi-ai` rewritten to
`@oh-my-pi/pi-ai`). pi-ai 15.1.0 removed the root `Type` runtime
export, so extension load crashed with `Export named 'Type' not found`
even though the `@sinclair/typebox` Zod-backed shim still ships in the
coding agent.
Routed bare `@oh-my-pi/pi-ai` root specifiers — used by both the
mirrored-source rewriter and the Bun.plugin onResolve hook — through a
new sibling shim that re-exports the canonical pi-ai surface plus the
`Type` runtime from the existing TypeBox shim. Subpath imports such as
`@oh-my-pi/pi-ai/utils/oauth` continue to resolve directly against the
bundled pi-ai package.
Fixes#1437
Rewrites JSON-roundtripped Zod 4 schema objects that leak Zod internals as
JSON Schema keywords (e.g., `type:"enum"`, `enum:{...}`) into valid
JSON Schema 2020-12. This prevents validation failures when such schemas
are used as tool input schemas (e.g., from MCP servers).
Updates `isZodSchema` to reject deserialized Zod impostors that retain
`_zod` but lose their prototype.
Wires `toJSON` methods onto TypeBox shim schemas to ensure `JSON.stringify`
produces clean JSON Schema, preventing future leaks.
Fixes#1101
- Type.String({ format, minLength, maxLength, pattern }) no longer drops the length/pattern constraints when a format selects a Zod format-specific schema (z.email, z.url, z.uuid, …). The instanceof z.ZodString guard never matched those subclasses; constraints are now applied via the shared _ZodString base so all format variants honor them.
- Type.Object without explicit additionalProperties now installs .loose() (matching TypeBox's preserve-extras default) instead of stripping unknown keys. additionalProperties: false continues to install .strict(); a schema value installs .catchall(schemaToZod(schema)).
- Added a dedicated `@sinclair/typebox` specifier remap path and routed bare legacy imports to the in-repo shim during extension rewriting and module resolution.
- Added resolve hooks for both `file` and legacy-file namespaces so legacy extensions load the shim consistently at runtime.
- Replaced fromTypeBox conversion with a JSON-schema validator flow in ai tool handling and execution paths.
- Added recursive schema validation and expanded TypeBox checks for refs, enums, uniqueItems, and constraint keywords.
- Sanitized Azure/CCA tool schemas by dropping unsupported fields and rewriting oneOf tool branches as anyOf.
- Tightened argument and model-config validation, preserving unknown tool fields and adding apiKey plus compatibility flags.
- Added canonical `pi.zod` schema API exports and removed TypeBox package exports/imports.
- Migrated Tool schema typing from TypeBox to shared `TSchema`/Zod flow with legacy TypeBox compatibility.
- Updated AI provider adapters and MCP/agent builders to convert tool params through `toolWireSchema()`.
- Reworked schema validation from AJV to Zod-safe parsing with `fromTypeBox`, `toolWireSchema`, and meta schema checks.
- Consolidated all former gh_* tools into a single GithubTool that routes execution by a required op field.
- Replaced gh_* tool registrations and render dispatch with `github`, including renderer key and header updates.
- Removed deprecated gh-* tool prompt files and added a unified github.md prompt covering per-op inputs and outputs.
- Updated settings-schema and ci-green prompt guidance to reference the unified github tool and `run_watch` operation.
- Updated tests and tool imports to use `GithubTool`/`githubToolRenderer` with op-based payloads and assertions.
- Fixed PR checkout tool to resolve worktree paths to canonical form using fs.realpath().
- Refactored test mocks to use vi.spyOn for git module functions instead of inline implementations.
- Updated test setup to pass Settings.isolated() with edit.manageImports enabled to EditTool.
- Added afterEach hooks across test suites to restore mocks after each test execution.