Skip to content

Add Pi package compatibility layer#811

Open
HabibPro1999 wants to merge 15 commits intocan1357:mainfrom
HabibPro1999:feat/pi-package-compat
Open

Add Pi package compatibility layer#811
HabibPro1999 wants to merge 15 commits intocan1357:mainfrom
HabibPro1999:feat/pi-package-compat

Conversation

@HabibPro1999
Copy link
Copy Markdown
Contributor

What

Adds a Pi compatibility layer for OMP plugin packages:

  • New omp pi command group for doctor, install, shim, and path bridge planning/creation
  • Pi source parsing for npm:, git:, GitHub URL, and local package specs
  • package.json.pi and conventional Pi resource normalization for extensions, skills, prompts, and themes
  • Scoped import shims for @mariozechner/* and typebox package names
  • Scoped pi CLI shim and safe .pi bridge modes for legacy packages
  • Static Pi compatibility doctor with known profiles for @tmustier/pi-agent-teams, pi-teams, and pi-messenger

Why

Allows OMP to install, diagnose, and load upstream Pi-style packages without renaming OMP globally or writing to a real ~/.pi by default.

Fixes #433.

Testing

  • bun run check
  • bun --cwd=packages/coding-agent test test/plugin-command.test.ts test/plugin-extensions-discovery.test.ts test/pi-compat.test.ts
  • bun packages/coding-agent/src/cli.ts pi doctor npm:pi-teams@0.9.14 --json
  • Local sandbox test using isolated HOME=/tmp/omp-pi-compat-sandbox/home with a fake Pi plugin covering package.json.pi, @mariozechner/* import aliases, pi subprocess detection, ~/.pi detection, resource discovery, shim creation, and symlink bridge dry-run/create

  • bun check passes
  • Tested locally
  • CHANGELOG updated (if user-facing)

Add source parsing, manifest normalization, known profiles, doctor reports, import aliases, CLI shim generation, and safe legacy path bridge helpers.

Export the new pi-compat API from the coding-agent package for integration points and tests.
Add omp pi commands and --compat-pi plugin install/doctor flows for npm, git, and local Pi package sources.

Resolve Pi skills, prompts, and themes from plugins, and activate scoped shims/env before extension and tool loading.
Exercise Pi source parsing, manifest normalization, resource resolution, shim generation, path bridge safety, known profiles, and local doctor classification.
Describe tiers, install grammar, resource support, scoped shims, bridge modes, doctor output, and known package profiles.

Refs can1357#433.
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 25044de15e

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +206 to +209
return execCommand(command, args, options?.cwd ?? this.cwd, {
...options,
env: buildPiCompatEnv({ baseEnv: process.env }),
});
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Preserve caller-provided env in extension exec

ConcreteExtensionAPI.exec now unconditionally sets env from buildPiCompatEnv({ baseEnv: process.env }), which discards options.env from the caller. Any extension that relies on per-invocation env overrides (for example API tokens, feature flags, or PATH changes) will silently lose those values after this change and execute commands with the wrong environment. Merge options.env into the base env (or layer it after building compat env) to keep the existing exec contract.

Useful? React with 👍 / 👎.

Comment on lines 278 to 282
if (options.compatPi) {
await activatePiCompatEnvironment({ packageName: source.packageNameHint, bridgeMode: "profile" });
}

if (options.dryRun) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Skip Pi compat activation during dry-run installs

The compat setup runs before the dry-run guard, so install(..., { compatPi: true, dryRun: true }) still performs side effects. activatePiCompatEnvironment() writes shim/home files and mutates process.env, which violates the --dry-run expectation of previewing changes without applying them. This affects pi install --dry-run and plugin install --compat-pi --dry-run flows; the activation should happen only after the dry-run early return.

Useful? React with 👍 / 👎.

Resolve shim targets to the installed OMP runtime instead of relying on plugin-local node_modules resolution.

Expand Pi extension directory manifest entries to concrete index files, and add compatibility shims for common legacy exports used by tested Pi packages.
@HabibPro1999 HabibPro1999 force-pushed the feat/pi-package-compat branch from 2e93f9d to 06d1705 Compare April 27, 2026 05:18
@HabibPro1999
Copy link
Copy Markdown
Contributor Author

Sandbox follow-up on real Pi packages after the compatibility fixes:

Package Install Doctor/resources Extension load
pi-agents@0.2.0 pass 1 extension pass
@tmustier/pi-agent-teams@0.5.4 pass 1 extension, 1 skill pass
pi-subagents@0.19.1 pass 1 extension, 1 skill, 1 prompt pass
pi-messenger@0.14.1 pass 1 extension, 1 skill pass
pi-web-access@0.10.6 pass 1 extension, 1 skill pass
pi-mcp-adapter@2.5.1 pass 1 extension pass

This surfaced and fixed two compatibility gaps before merge:

  • Pi manifest extension directories such as ./extensions and ./src now expand to loadable index.ts entry points.
  • Import shims now resolve to the installed OMP runtime via absolute module URLs, and include missing peer/core compatibility shims used by these packages.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 06d1705d0b

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +58 to +64

function isLocalSource(spec: string): boolean {
return (
spec.startsWith("./") ||
spec.startsWith("../") ||
spec.startsWith("/") ||
spec.startsWith("~/") ||
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Handle Windows drive paths as local install sources

parsePiInstallSource() only treats ./, ../, /, ~/, ., .., and file: as local sources, so Windows drive-letter paths like C:/plugins/foo are classified as npm specs. In PluginManager.install(), that path then goes through npm package-name validation and fails, which blocks local plugin installs on Windows for plugin install/pi install. Add drive-letter path detection (and corresponding safe handling) in the local-source check.

Useful? React with 👍 / 👎.

Comment on lines +17 to +18
const skillPath = path.join(skillDir, "SKILL.md");
const content = await readFile(skillPath);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Support direct SKILL.md paths in plugin skill discovery

Skill resource paths are always treated as directories, and loadDirectSkill() unconditionally appends SKILL.md. If a plugin manifest provides a direct skill-file entry (for example skills: ["skills/my-skill/SKILL.md"]), discovery looks for <that-file>/SKILL.md and drops the skill. Add a file-path branch (similar to prompt loading) so direct skill-file entries are loaded correctly.

Useful? React with 👍 / 👎.

Preserve per-call extension exec env, keep compat setup out of dry-run installs, treat Windows drive paths as local sources, and load direct SKILL.md plugin resources.
@HabibPro1999
Copy link
Copy Markdown
Contributor Author

Addressed the latest Codex review feedback in 459f825:

  • Preserved caller-provided options.env in extension exec() while still layering the Pi compatibility environment.
  • Moved Pi compatibility activation after the dry-run return so pi/plugin install --dry-run --compat-pi does not create shims/home or mutate process.env.
  • Treated Windows drive-letter paths like C:/plugins/foo as local install sources.
  • Loaded direct plugin skill-file manifest entries such as skills/foo/SKILL.md instead of assuming every skill entry is a directory.

Verification:

  • bun --cwd=packages/coding-agent test test/plugin-command.test.ts test/plugin-extensions-discovery.test.ts test/pi-compat.test.ts — 15 pass
  • bun run check:ts — pass
  • bun run check:rs — pass

Keep the user-facing Pi compatibility note under the mutable Unreleased section per repository changelog rules.
@HabibPro1999
Copy link
Copy Markdown
Contributor Author

Contribution-guideline audit complete. I found one changelog placement issue after the rebase: the Pi compatibility entry had landed under released 14.5.3 instead of [Unreleased]. Fixed in 085ba0b and re-ran bun run check:ts successfully. Other checked repo rules/templates are satisfied: PR body includes What/Why/Testing and checkboxes, no generated native artifacts are tracked, review fixes are pushed, and prior targeted tests + Rust check remain passing.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 085ba0b0d3

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

const runtime = new ExtensionRuntime();
if (paths.length > 0) {
await ensurePiCompatImportShims();
await activatePiCompatEnvironment({ bridgeMode: "env" });
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Preserve selected Pi bridge mode during extension activation

loadExtensions unconditionally calls activatePiCompatEnvironment({ bridgeMode: "env" }), which overwrites any preselected OMP_PI_COMPAT_BRIDGE mode and forces all extension subprocesses back to env-only bridging. This breaks Tier 3 compatibility scenarios (e.g., child-home) because the shim only rewrites HOME when the mode remains child-home, so packages with hardcoded ~/.pi paths can still touch the real home directory. The same forced mode is also present in custom-tools/loader.ts, so both extension and tool execution paths ignore the user/profile-selected bridge mode.

Useful? React with 👍 / 👎.

@HabibPro1999
Copy link
Copy Markdown
Contributor Author

Addressed the latest bridge-mode review in 5527d5c.

loadExtensions() and loadCustomTools() now activate Pi compatibility without forcing bridgeMode: "env", so a preselected OMP_PI_COMPAT_BRIDGE value such as child-home is preserved through extension/tool loading.

Added regression coverage for both extension and custom-tool loading paths.

Verification:

  • bun --cwd=packages/coding-agent test test/pi-compat.test.ts — 14 pass
  • bun run check:ts — pass

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5527d5c120

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

// Run npm install
const proc = Bun.spawn(["bun", "install", spec.packageName], {
if (options.compatPi) {
await activatePiCompatEnvironment({ packageName: source.packageNameHint, bridgeMode: "profile" });
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Strip version from profile package name before activation

PluginManager.install() forwards source.packageNameHint directly into activatePiCompatEnvironment(), but npm-style specs keep the version suffix (for example @tmustier/pi-agent-teams@0.5.4). Profile lookup is exact-name based, so version-pinned installs miss their compatibility profile and skip profile env injection (such as PI_TEAMS_ROOT_DIR), which undermines the documented --compat-pi install path.

Useful? React with 👍 / 👎.

Comment on lines +59 to +60
if (mode === "child-home") {
env.HOME = getPiCompatHomeDir();
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Propagate Windows home vars in child-home bridge mode

In buildPiCompatEnv(), child-home mode only sets HOME, so Windows subprocesses that resolve the home directory via USERPROFILE/HOMEDRIVE/HOMEPATH still point at the real user profile. Under OMP_PI_COMPAT_BRIDGE=child-home, this leaves %USERPROFILE%\.pi unisolated and defeats the bridge for Windows plugin processes.

Useful? React with 👍 / 👎.

@HabibPro1999
Copy link
Copy Markdown
Contributor Author

Addressed the latest two Codex comments in 94c7c26:

  • child-home bridge mode now overrides Windows home env (USERPROFILE, HOMEDRIVE, HOMEPATH) in addition to HOME, so Windows child processes do not keep resolving %USERPROFILE%\\.pi to the real profile.
  • Pi npm source parsing now strips version suffixes from packageNameHint, so version-pinned installs like npm:@tmustier/pi-agent-teams@0.5.4 still match exact compatibility profiles and receive profile env such as PI_TEAMS_ROOT_DIR.

Added regression coverage for both cases.

Verification:

  • bun --cwd=packages/coding-agent test test/pi-compat.test.ts — 16 pass
  • bun --cwd=packages/coding-agent test test/plugin-command.test.ts test/plugin-extensions-discovery.test.ts test/pi-compat.test.ts — 19 pass
  • bun run check:ts — pass

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 94c7c26e6b

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +64 to +65
if (!manifest[key]?.length && conventional[key]?.length) {
manifest[key] = conventional[key];
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Respect explicit empty Pi resource arrays

applyConventionalFallbacks() currently treats an explicit empty array the same as a missing key because it checks !manifest[key]?.length. That means a plugin that intentionally sets pi.skills: [] (or prompts/themes/extensions) will still get those directories auto-added if they exist on disk, enabling resources the manifest explicitly disabled. This changes capability loading behavior unexpectedly; fallback should run only when the key is absent, not when it is present-but-empty.

Useful? React with 👍 / 👎.

Comment on lines +15 to +16
const valueToCheck = isWindowsDrivePath(spec) ? spec.replace(/\\/g, "/") : spec;
if (SHELL_METACHARS.test(valueToCheck)) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Accept Windows relative paths in Pi source parsing

Windows-style relative local specs (for example .\plugin or ..\plugin) are rejected as unsafe because backslashes are only normalized for drive-letter paths before the metacharacter check. In parsePiInstallSource(), this throws Invalid characters in package source before local-path resolution, so local Pi installs on Windows require non-native path rewriting. Treat Windows relative separators as local path syntax before applying the shell-metacharacter denylist.

Useful? React with 👍 / 👎.

@HabibPro1999
Copy link
Copy Markdown
Contributor Author

Addressed the latest Codex comments in c2c0f83:

  • Windows relative local specs such as .\\plugin, ..\\plugin, and ~\\plugin now pass Pi source parsing and resolve as local paths instead of being rejected by the shell-metacharacter denylist.
  • Conventional Pi resource fallback now only fills absent manifest keys. Explicit empty arrays like pi.skills: [] are respected and no longer auto-enable matching on-disk directories.

Added regression coverage for both cases.

Verification:

  • bun --cwd=packages/coding-agent test test/pi-compat.test.ts — 17 pass
  • bun --cwd=packages/coding-agent test test/plugin-command.test.ts test/plugin-extensions-discovery.test.ts test/pi-compat.test.ts — 20 pass
  • bun run check:ts — pass

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c2c0f83342

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

const runtime = new ExtensionRuntime();
if (paths.length > 0) {
await ensurePiCompatImportShims();
await activatePiCompatEnvironment();
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Apply profile env with package context during extension load

loadExtensions enables Pi compatibility by calling activatePiCompatEnvironment() without a package name, so profile mode cannot inject package-specific variables from getPiCompatProfileEnv (for example PI_TEAMS_ROOT_DIR for @tmustier/pi-agent-teams). In a normal runtime (separate from install), extensions that rely on profile-provided env can start without those variables, so --compat-pi profile behavior silently degrades for affected packages.

Useful? React with 👍 / 👎.

Comment on lines +202 to +205
const changed = Object.entries(deps).filter(([name, version]) => previousDeps[name] !== version);
if (changed.length === 1) return changed[0][0];
if (fallbackName) {
const actualName = extractPackageName(fallbackName);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Handle unchanged dependency maps when resolving installed name

#resolveInstalledPackageName() assumes either exactly one dependency entry changed or that fallbackName maps directly to node_modules/<name>. For git installs where repo basename differs from package.json.name, reinstalling the same spec leaves dependencies unchanged (changed.length === 0) and the fallback lookup misses, causing a throw even though the package is already installed. This breaks idempotent plugin install git:... flows for those repositories.

Useful? React with 👍 / 👎.

@HabibPro1999
Copy link
Copy Markdown
Contributor Author

Checked the latest Codex comments for conflicts/loops: they are new edge cases on top of the existing compatibility work, not contradictory with the prior fixes.

Addressed both in 70fdd5f:

  • Reinstall/idempotent git installs now resolve an already-installed dependency by matching the dependency spec when the dependency map is unchanged, instead of relying only on changed entries or repo-basename fallback.
  • Plugin extension loading now preserves package context derived from the plugin node_modules path, applies package profile env before loading that extension, and carries the same package context into extension exec() env construction.

Added regression coverage for profile env during plugin extension load.

Verification:

  • bun --cwd=packages/coding-agent test test/pi-compat.test.ts — 18 pass
  • bun --cwd=packages/coding-agent test test/plugin-command.test.ts test/plugin-extensions-discovery.test.ts test/pi-compat.test.ts — 21 pass
  • bun run check:ts — pass

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 70fdd5fe02

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +357 to +359
if (paths.length > 0) {
await ensurePiCompatImportShims();
await activatePiCompatEnvironment();
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Make Pi compat bootstrap non-fatal in extension loading

loadExtensions now unconditionally runs Pi compat setup before loading any module, but both helpers perform filesystem writes under the OMP config directory and can throw on read-only or restricted environments. Because these awaits are not guarded, one shim/home setup failure aborts loadExtensions() and prevents all extensions (including non-Pi extensions) from loading instead of returning per-extension errors. This should be best-effort or limited to paths that actually need Pi compatibility.

Useful? React with 👍 / 👎.

Comment on lines +175 to +177
if (pathsWithSources.length > 0) {
await ensurePiCompatImportShims();
await activatePiCompatEnvironment();
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Avoid failing all tool loads on Pi shim bootstrap errors

loadCustomTools now blocks on Pi shim/environment setup whenever any tool path exists, and those setup calls can throw if ~/.omp is not writable. Since this happens before tool modules are loaded and without error isolation, a bootstrap failure prevents every custom tool (including ordinary non-Pi tools) from loading. Handle setup failures as warnings or restrict this path to Pi-compat tool sources so unrelated tools still work.

Useful? React with 👍 / 👎.

# Conflicts:
#	packages/coding-agent/CHANGELOG.md
@HabibPro1999
Copy link
Copy Markdown
Contributor Author

Merged latest origin/main into the PR branch and resolved the changelog conflict in 87fc6d7.

GitHub now reports:

  • mergeable: MERGEABLE
  • mergeStateStatus: UNSTABLE
  • no status checks listed

Verification:

  • bun --cwd=packages/coding-agent test test/pi-compat.test.ts — 18 pass
  • bun --cwd=packages/coding-agent test test/plugin-command.test.ts test/plugin-extensions-discovery.test.ts test/pi-compat.test.ts — 21 pass

Note: I also tried bun run check:ts after merging main; it currently fails on formatting/import-order issues introduced by latest origin/main files unrelated to this PR (for example line-hash.ts, extensions/types.ts, tools/renderers.ts, and search tool tests). I left those upstream files untouched to keep this PR scoped.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 87fc6d7f1c

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +151 to +154
{
name: "typebox",
files: {
"index.ts": typeboxShimContent(),
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve existing typebox package when writing Pi shims

ensurePiCompatImportShims() always rewrites node_modules/typebox because this shim entry lacks skipIfPackageExists, unlike the adjacent @sinclair/typebox shim. In any environment where a plugin installs a real typebox dependency, loading extensions/tools will silently replace that package with the compat shim and can break runtime imports or behavior for that plugin.

Useful? React with 👍 / 👎.

@joshmac007
Copy link
Copy Markdown

Fantastic idea! I've been missing being able to use the Pi extensions since moving over to OMP.

@HabibPro1999
Copy link
Copy Markdown
Contributor Author

@can1357 can you review this please

# Conflicts:
#	docs/plugin-manager-installer-plumbing.md
#	packages/coding-agent/CHANGELOG.md
@HabibPro1999
Copy link
Copy Markdown
Contributor Author

Resolved the merge conflicts with latest main and pushed the updated feat/pi-package-compat branch.

Conflicts resolved:

  • docs/plugin-manager-installer-plumbing.md — kept both the upstream extension-loader documentation and the Pi compatibility additions.
  • packages/coding-agent/CHANGELOG.md — kept both the Pi compatibility entry and the upstream after_provider_response changelog entry.

Local verification before pushing:

  • no unmerged files
  • no conflict markers
  • git diff --check HEAD^1..HEAD passes

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 08536910b6

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines 113 to 116
} else if (arg === "-l" || arg === "--local") {
} else if (arg === "--compat-pi") {
result.flags.compatPi = true;
result.flags.local = true;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Parse --local and --compat-pi as independent flags

The new flag parsing block leaves the -l/--local branch empty and sets result.flags.local = true under --compat-pi, so consumers of parsePluginArgs can no longer request local mode with -l alone while --compat-pi now unexpectedly forces local scope. In contexts that still use this parser, that changes which plugin registry is targeted (project-local vs user/global) and can run install/doctor operations against the wrong location.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 01fcdd7: -l/--local now sets flags.local = true, while --compat-pi only sets flags.compatPi = true.

Also added regression coverage for --local, -l, --compat-pi, and combined --local --compat-pi parsing.

Verification:

  • bunx biome check packages/coding-agent/src/cli/plugin-cli.ts packages/coding-agent/test/plugin-command.test.ts — pass
  • git diff --check — pass

Note: local bun --cwd=packages/coding-agent test test/plugin-command.test.ts is blocked in this fresh checkout because the native addon is not built, and local native build cannot run because cargo is not installed on this machine.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 01fcdd7d5a

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

) {
if (pathsWithSources.length > 0) {
await ensurePiCompatImportShims();
await activatePiCompatEnvironment();
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Pass package name when activating Pi compat for tools

loadCustomTools enables Pi compatibility globally but never passes a package context, so profile-specific env injection is skipped for plugin tools. buildPiCompatEnv only applies profile vars via getPiCompatProfileEnv(options.packageName), which means tools from profiled packages (for example @tmustier/pi-agent-teams) can load/execute without required vars like PI_TEAMS_ROOT_DIR, breaking runtime behavior that depends on profile mode.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 7e61ca2: plugin custom tools now derive their installed package name from the managed plugin node_modules path, activate Pi compat with that packageName before importing the tool module, and use a per-plugin CustomToolAPI whose exec() env includes package profile vars.

Added regression coverage using an @tmustier/pi-agent-teams plugin tool to verify both load-time process.env.PI_TEAMS_ROOT_DIR and api.exec() child env receive the profile value.

Verification:

  • bunx biome check packages/coding-agent/src/extensibility/custom-tools/loader.ts packages/coding-agent/test/pi-compat.test.ts — pass
  • bun --cwd=packages/coding-agent run check:types — pass
  • git diff --check — pass

Note: local bun --cwd=packages/coding-agent test test/pi-compat.test.ts is still blocked in this checkout by missing pi_natives.darwin-arm64.node; building it locally is blocked because cargo is not installed. GitHub CI should run the full test job.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7e61ca2361

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +59 to +60
for (const [key, value] of Object.entries(env)) {
process.env[key] = value;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Avoid leaking profile env across compatibility activations

activatePiCompatEnvironment() mutates process.env by only assigning keys from the newly built compat env, but it never removes profile-specific variables from previous activations. If a profiled package (for example one that sets PI_TEAMS_ROOT_DIR) is activated first, then a different package is loaded afterward, stale profile vars remain in the global process environment and can be inherited by later extension/tool subprocesses, causing them to run with the wrong package context.

Useful? React with 👍 / 👎.

Comment on lines 220 to +224
exec(command: string, args: string[], options?: ExecOptions) {
return execCommand(command, args, options?.cwd ?? this.cwd, options);
return execCommand(command, args, options?.cwd ?? this.cwd, {
...options,
env: buildPiCompatEnv({ baseEnv: { ...process.env, ...options?.env }, packageName: this.packageName }),
});
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Restrict Pi-compat exec env injection to Pi plugin extensions

ConcreteExtensionAPI.exec() now always wraps subprocesses with buildPiCompatEnv(...), even when the extension is not from a Pi-compatible plugin (packageName is undefined). This changes subprocess semantics for all extensions by prepending the Pi shim path and setting Pi compatibility vars, so non-Pi/user extensions can unexpectedly resolve pi to the shim and observe compatibility-only env state they never requested.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

About extension and plugin && compatibility with pi-mono

2 participants