Commit Graph

93 Commits

Author SHA1 Message Date
can1357 3aea0bfb38 Merge PR #2714: fix(plugins): resolve directory extension manifest entries one level deep
Resolve directory extension manifest entries one level deep with manifest-first precedence (issue #2713). Supersedes #2723.
2026-06-16 14:53:39 +02:00
roboomp 4c336543d5 fix(cli): preserved linked plugin doctor state
Taught plugin doctor to treat lockfile-only plugins with node_modules entries as installed instead of orphaned.

Added coverage for plugin doctor --fix after linking a local plugin without package dependencies.

Fixes #2742
2026-06-16 05:17:24 +00:00
roboomp 7244e21b73 fix(cli): listed linked local plugins
Included lockfile-only linked plugins when building plugin list output so local symlink installs are visible after successful link operations.

Added regression coverage for plugin link followed by plugin list --json.

Fixes #2742
2026-06-16 05:02:20 +00:00
Asaf Mahlev b740faf6ce fix(plugins): resolve directory extension manifest entries one level deep
Installed pi packages declare their entry as `pi.extensions: ["./extensions"]` with the real module at `extensions/<name>/index.ts`, but the plugin manifest resolver only matched a file or a directory containing a direct index.{ts,js,mjs,cjs}. A directory whose entry sits one level below resolved to null, so `omp plugin install` rejected it ("declared extension entry not found on disk") and runtime load silently skipped it.

For the extensions key, resolveManifestEntryFiles now resolves a directory like OMP's configured-directory (-e) scanner: the directory's own package.json omp/pi extensions (authoritative -- a declared-but-missing entry is reported, not replaced by a decoy index), then a direct index.{ts,js,mjs,cjs}, then a one-level scan where each child directory is itself resolved manifest-first plus direct *.{ts,js,mjs,cjs} files. The directory expansion is gated to the extensions key; tools/hooks/commands keep direct-index resolution so a directory entry like `tools: "."` is unaffected.

Adds CHANGELOG Unreleased entry and regression tests for subdir-index, nested-manifest-over-index, missing-declared-entry, and key-aware (tools vs extensions) resolution. Verified: omp plugin install @zosmaai/pi-llm-wiki registers all 14 wiki_* tools; pi-mcp-adapter loads.
2026-06-16 03:01:07 +03:00
can1357 39d819e8b9 Merge PR #2237: fix(coding-agent): handle legacy plugin config settings 2026-06-15 19:46:15 +02:00
can1357 15184332b8 Merge PR #1173: feat(marketplace): prefer .omp-plugin/marketplace.json catalog path 2026-06-15 19:46:14 +02:00
can1357 9e18d3fbb0 Merge branch 'main' into farm/a4aed75b/npm-plugin-load-deps 2026-06-14 18:13:29 +02:00
jiwangyihao c47718a6b5 fix(coding-agent): derive bundled self root from dist path 2026-06-14 17:24:07 +02:00
roboomp fed5e43f45 fix(coding-agent): remapped legacy oauth imports
Redirected legacy pi-ai utils/oauth subpaths through the compatibility loader so background workers load the relocated OAuth registry modules.\n\nFixes #2566
2026-06-14 12:56:05 +00:00
roboomp 54922241d9 fix(cli): restored git plugin upgrades by repo identity
Matched installed git dependencies by parsed host and repo path instead of the new ref so failed ref upgrades restore the prior package tree.
2026-06-11 16:46:41 +00:00
roboomp bfbbbb02af fix(cli): rejected plugins declaring missing extension entries
Surfaced manifest entries that resolve to nothing on disk at install time instead of silently skipping them through resolvePluginExtensionPaths.
2026-06-11 16:42:27 +00:00
roboomp dd5936701e fix(cli): restored plugin tree after invalid reinstall
Backed up existing npm plugin package trees before reinstall validation so failed extension loads restore the previous working package contents.
2026-06-11 16:39:39 +00:00
roboomp 9842ad8494 fix(cli): rejected unloadable npm plugin installs
Validated npm plugin extension entry points before recording installs and rolled back fresh installs that cannot resolve their extension imports.

Fixes #2312
2026-06-11 16:32:27 +00:00
roboomp 9347f8f4a4 fix(coding-agent): handled legacy plugin config settings
Normalized persisted plugin runtime config before manager and loader callers use it, so older lockfiles without a settings object can still accept plugin config writes.

Added a regression test covering setting a plugin option against a legacy lockfile.

Fixes #2236
2026-06-10 06:57:32 +00:00
can1357 dc5c93462f feat: rerouted worker subprocesses through the bundled CLI host entrypoint
- Rerouted sync, tab, js-eval, and tiny workers to re-enter CLI modes via `__omp_*` selectors.
- Adjusted `cli.ts` startup to dispatch worker entrypoints before parsing and exit 1 on uncaught errors.
- Bundled CLI as `dist/cli.js` in prepack, switching `omp` binary and published files.
- Removed explicit Bun `--compile` worker entrypoints from build/release scripts in favor of host-entry dispatch.
- Added `declareWorkerHostEntry()` and `workerHostEntry()` environment helpers and `PI_COMPILED` binary detection.
2026-06-10 03:57:31 +02:00
roboomp 4a6362192d fix(legacy-pi-compat): validated package-root override targets before rewrite
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
2026-06-09 06:33:53 +00:00
can1357 31b6f0bf31 refactor(ai): consolidated provider config into single-source registry
- 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.
2026-06-08 18:48:43 +02:00
can1357 bda3102451 ux(coding-agent): updated status glyphs and fixed extension model discovery refresh
- Added status.done and tool.* symbols to theme mappings and presets.
- Replaced generic success glyphs with contextual +/-, tool icons, and warnings.
- Mapped tool/task/job completions to status.done or status.enabled with icon overrides.
- Triggered runtime provider refresh after extension registration and warned on failure.
2026-06-08 18:28:15 +02:00
can1357 e5e93ff762 feat(packages/coding-agent): enabled setup-version-gated startup flow
- Deferred setup wizard import until setup was forced or version stale.
- Dynamically loaded ACP, RPC, and print mode runners only when used.
- Added a marketplace auto-update scheduler with off-mode early exit and non-blocking errors.
- Added setup-version assertions to keep CURRENT_SETUP_VERSION aligned with scenes.
2026-06-06 22:58:33 +02:00
can1357 8a5b99a967 feat(coding-agent): enabled anonymous Perplexity fallback and updated web-search checks
- Added anonymous Perplexity authentication mode for unauthenticated web searches.
- Switched web-search setup checks to use `isExplicitlyAvailable` and removed key enforcement in doctor.
- Updated Perplexity OAuth flow to reuse auth handling for all non-key searches and anonymous responses.
- Updated CLI and provider option help text to mark the Perplexity key optional with fallback.
2026-06-06 19:42:16 +02:00
roboomp c4fa93e460 fix(plugins): preserved null package import exclusions
Kept explicit null package imports as exclusions so exact entries and active conditions do not fall through to wildcard or fallback targets.\n\nFixes #1889
2026-06-05 07:59:28 +00:00
roboomp 994ae513f5 fix(plugins): skipped non-source package import targets
Returned null from resolveSourceModuleFile when a package imports alias points at a JSON, WASM, or other non-code asset so the on-load rewrite hook no longer claims it and forces it through the JS loader. Bun resolves these targets natively. Added a regression where #schema maps to a .json file imported with a JSON type assertion.\n\nFixes #1889
2026-06-04 21:54:33 +00:00
roboomp 251d9152fc fix(plugins): honored package import condition order
Selected conditional package import targets by package.json object order for supported Bun runtime conditions, including node, instead of probing a fixed precedence list. Added a regression where node precedes import and must be selected for a plugin-local #src/* import.\n\nFixes #1889
2026-06-04 21:51:26 +00:00
roboomp 6e47ae8150 fix(plugins): matched side-effect imports in compat rewrite
Extended the legacy Pi, TypeBox, package-import alias, and extension graph regexes to recognise the bare \"import \\"specifier\\";\" shape so side-effect-only loads such as \"import \\"#src/register\\";\" walk into the source graph and get their legacy @(scope)/pi-* imports rewritten. Added a regression that loads a plugin with a side-effect alias import whose target contains a legacy scope import.\n\nFixes #1889
2026-06-04 21:49:06 +00:00
roboomp b2c6b7becf fix(plugins): loaded package import extensions
Resolved plugin-local package import aliases while loading extension source graphs so legacy Pi plugins with TypeScript source imports like #src/* register correctly under OMP. Added a regression covering legacy scope rewrites through a package import module.\n\nFixes #1889
2026-06-04 21:42:52 +00:00
David Marshall 2c27d2df15 Merge remote-tracking branch 'origin/main' into feat/marketplace-omp-plugin-path
# Conflicts:
#	docs/marketplace.md
2026-06-03 12:50:46 -05:00
can1357 ab935e992c fix(legacy-pi-compat): scope rewrite hook to the import graph, not a dir
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.
2026-06-02 09:15:44 +02:00
can1357 c5e3698f45 fix(legacy-pi-compat): load extensions in place instead of mirroring
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.
2026-06-02 09:15:44 +02:00
can1357 9f547d8e4f refactor(mnemosyne/core): typed embedding provider outputs and tightened normalization
- 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.
2026-05-31 05:32:28 +02:00
can1357 495c570ed4 fix(coding-agent): normalize hosted plugin git shorthands
Addresses review feedback on #1527.
2026-05-31 04:47:39 +02:00
oldschoola 84a50e8921 fix(coding-agent): classify git+ and unprefixed scp specs as git
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`.
2026-05-31 04:46:08 +02:00
oldschoola 22e564a85d feat(coding-agent): accept GitHub/git URLs in plugin install
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.
2026-05-31 04:46:08 +02:00
roboomp 2780f5dec6 fix(coding-agent): kept legacy-pi paths under compiled bunfs root
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
2026-05-29 19:44:36 +00:00
roboomp 9e35b784d8 fix(coding-agent): derived legacy-pi compat bunfs root from import.meta.dir for windows
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
2026-05-29 19:39:50 +00:00
roboomp 4d108c1951 fix(plugins): enumerate linked plugins for sub-discovery
PluginManager.link symlinks the package into <plugins>/node_modules
and records it in omp-plugins.lock.json, but never writes to
<plugins>/package.json#dependencies. getEnabledPlugins iterated only
the dependency map, so the documented `omp install ./local-extension`
workflow (delegated to plugin link) succeeded but its sibling skills/,
hooks/, tools/, etc. stayed invisible after install.

Iterate the union of package.json#dependencies and
omp-plugins.lock.json#plugins so symlinked-only packages surface
alongside npm/marketplace installs. Lockfile entries whose
node_modules tree has since been deleted (stale link) are skipped
silently. Linked-only setups with no <plugins>/package.json at all
now work too.

Per-PR review feedback: https://github.com/can1357/oh-my-pi/pull/1498
2026-05-29 06:34:10 +00:00
roboomp bdce9cf068 feat(discovery): scan installed plugin packages for sub-discovery
Marketplace and `omp plugin link` installs write to
`<plugins>/node_modules/` rather than to `extensions:` in settings,
so the original PR still missed their sibling skills/, hooks/,
tools/, commands/, rules/, prompts/, .mcp.json sub-trees. Wire
listOmpExtensionRoots to enumerate getEnabledPlugins(cwd, { home })
in addition to CLI-injected and settings-driven roots.

Adds an optional { home } parameter to getEnabledPlugins so the
discovery loader can pass through LoadContext.home for tempdir-rooted
tests. The getPluginsNodeModules/getPluginsPackageJson/
getPluginsLockfile helpers gain the same optional home overload so
they mirror getPluginsDir.

Per-PR review feedback: https://github.com/can1357/oh-my-pi/pull/1498
2026-05-29 06:28:33 +00:00
can1357 625c8b1992 test(ai): updated tests for model metadata and auth token fallback
- 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).
2026-05-29 06:56:29 +02:00
roboomp 437b6524cd fix(cli): restored package resolver for non-compiled pi root remaps
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
2026-05-29 06:42:47 +02:00
roboomp 349fb51ddb fix(cli): preserved legacy peer fallback for subpaths
Retried original legacy specifiers after canonical peer fallback fails so direct plugin imports with only legacy-scoped peer dependencies continue to load.
2026-05-29 06:42:46 +02:00
roboomp 564b6d0f22 fix(cli): routed legacy pi-coding-agent imports through a sibling shim
Listing the coding-agent's own ./src/index.ts as a bun --compile extra entrypoint silently breaks the CLI binary startup. Added a dedicated legacy-pi-coding-agent-shim.ts that re-exports the canonical barrel, registered the shim instead of the package index, and updated the compat resolver to point pi-coding-agent at the shim path.
2026-05-29 06:42:46 +02:00
roboomp 82008e4f38 fix(cli): restored legacy pi package root remaps
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
2026-05-29 06:42:46 +02:00
David Marshall 587f68a899 feat(marketplace): prefer .omp-plugin/marketplace.json catalog path
Adds .omp-plugin/marketplace.json as the preferred catalog location for omp
marketplaces. fetchMarketplace now searches .omp-plugin/marketplace.json
first and falls back to .claude-plugin/marketplace.json so existing
Claude Code-compatible marketplaces keep loading.

Docs and authoring skill updated to reflect the new preferred path.

Co-Authored-By: omp <noreply@oh-my-pi.dev>
2026-05-28 22:03:19 -05:00
roboomp 802e3f3e63 fix(extensibility): resolved compat shims to bunfs entry paths in compiled binaries
Reviewer caught that the new `legacy-pi-ai-shim.ts` is only referenced
via a computed string path, so Bun's `--compile` static analyzer cannot
trace it into bunfs. The same gap existed for the pre-existing
`typebox.ts` shim — `path.resolve(import.meta.dir, "../typebox.ts")`
collapses to `/$bunfs/typebox.ts` in compiled mode (where
`import.meta.dir` is `/$bunfs/root`), which does not exist in bunfs.
Legacy plugins importing bare `@sinclair/typebox` or `@(scope)/pi-ai`
therefore hit "Cannot find module" in release builds.

- Branch `TYPEBOX_SHIM_PATH` and `LEGACY_PI_AI_SHIM_PATH` on
  `isCompiledBinary()`: in compiled mode they point at the
  `--root`-relative bunfs entry path with a `.js` extension
  (`/$bunfs/root/packages/coding-agent/src/extensibility/<file>.js`);
  in dev they keep the `path.resolve(import.meta.dir, "../<file>.ts")`
  source path so tests still resolve against the workspace tree.
- List both shims as additional `--compile` entrypoints in
  `scripts/build-binary.ts` so Bun actually emits them into bunfs at the
  paths the runtime expects.

Verified with a focused `bun build --compile` probe: `Bun.resolveSync`
returns the expected bunfs path for both shims when they are listed as
entries, and fails when they are not. Dev-mode test suite unchanged
(17 pass / 0 fail across the four legacy-pi compat test files).
2026-05-27 12:34:27 +00:00
roboomp 6f7da0769b fix(extensibility): redirected legacy pi-ai root imports through Type-compat shim
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
2026-05-27 12:14:57 +00:00
Can Bölük a40864c5b2 Merge branch 'main' into farm/ccf5d9fd/csharp-lsp-plugin-doesn-t-work-with-omp- 2026-05-25 20:37:30 +03:00
roboomp 24b249219e fix(lsp): supported config-only marketplace servers
Loaded marketplace lspServers metadata from Claude plugin caches and embedded it for OMP marketplace installs so config-only plugins register without package code.

Fixes #1352
2026-05-25 17:34:32 +00:00
roboomp a2032850e5 fix(legacy-pi-compat): fall back to peer deps when resolveSync fails in binary mode
In a compiled binary, Bun.resolveSync(spec, import.meta.dir) throws
'Cannot find module' because import.meta.dir is inside /$bunfs/root
and the virtual FS exposes no node_modules tree at runtime.

Previously this throw propagated through rewriteLegacyPiImports ->
rewriteLegacyPiImportsForRuntime -> mirrorLegacyPiFile ->
loadLegacyPiModule -> loadExtension, which swallowed it as 'Failed to
load extension' and silently dropped any plugin whose files imported
@mariozechner/pi-ai (or any @mariozechner/pi-* whose bundled
counterpart isn't reachable via resolveSync in the binary).

Fix: wrap the resolution call in rewriteLegacyPiImports in a try/catch
and return the original match on failure. rewriteBareImportsForLegacyExtension
runs immediately afterwards in every call path and already resolves bare
specifiers against the importer's real filesystem directory, so it picks
up @mariozechner/pi-ai from the plugin's installed peer deps instead.

Apply the same fallback to resolveLegacyPiSpecifier (the Bun plugin
shim's onResolve handler) for tool/hook files loaded directly via Bun's
import system rather than through loadLegacyPiModule.

Fixes #1215
2026-05-25 12:22:57 +02:00
can1357 8dc9125b0b fix(coding-agent): stabilize extension and hyperlink tests 2026-05-21 17:35:04 +09:00
can1357 43ed173e2e fix(coding-agent/extensibility): added remap for bare @sinclair/typebox imports to shim
- 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.
2026-05-15 15:26:44 +02:00
oldschoola 69043d3071 fix(extensibility): treat Windows drive-letter paths as filesystem in legacy-pi mirror
isUrlLikeSpecifier matched Windows absolute paths (e.g. `C:\foo`) because the URL-scheme regex `^[A-Za-z][A-Za-z\d+.-]*:` happily eats a single drive letter. When a legacy plugin extension imported a bare-specifier dep from its own `node_modules`, rewriteBareImportsForLegacyExtension resolved it to an absolute path, then toRewrittenImportSpecifier short-circuited pathToFileURL and embedded the raw Windows path into the mirrored TS source.

The TS string-literal parser then ate \n, \U, \y and friends, producing nonsense package specifiers like `C:Usersjames.ompagentextensionssupipowers\node_modulesyamldistindex.js` that Bun rejected with `Cannot find package …`. Net effect: every legacy extension that pulls in any node_modules dep failed to load on Windows.

Fix: reject `^[A-Za-z]:[\\/]` in isUrlLikeSpecifier before the URL-scheme test so drive-letter paths flow through pathToFileURL and reach the mirror as proper `file:///C:/...` URLs.
2026-05-15 02:44:49 -07:00