Skip to content

[pi-plugin] pi.subagent_extensions resolves non-path sources as relative paths #677

Closed

Description

@Shrub24

Short description

pi.subagent_extensions passes only npm: entries through unchanged and resolves every other relative entry against ~/.pi/agent. Pi's own loader treats seven prefixes as non-local sources. As a result, builtin:<name>, git:, github:, http(s): and ssh: entries reach the child as nonexistent files, and ~/ entries are resolved as relative paths.

What happened?

The allowlist becomes one --extension flag per entry. Only absolute paths and npm: entries are passed as given; everything else is resolved against the agent directory.

Example: pi.subagent_extensions = ["git:github.com/owner/repo"] becomes --extension <agent-dir>/git:github.com/owner/repo.

Source: packages/pi-plugin/src/subagent-runner.ts, resolveSubagentExtensionEntry (v0.49.0, around lines 599–603).

Expected

Pi's own rule. In @earendil-works/pi-coding-agent 1.1.0, dist/utils/paths.js treats these prefixes as non-local and passes them through unchanged:

npm:, git:, github:, http:, https:, ssh:, builtin:

Everything else is local. Pi also expands ~/ and converts file:// URLs. We should match that list and those two rules.

Affected

  • Stock Pi, through git:, github:, https:, ssh:, builtin:, ~/ and file: entries.
  • OMP, which shares this resolver.
  • Not OpenCode 1 or 2, which have no pi.subagent_extensions, and not the Rust module, which does not spawn Pi children.

builtin:<name> entries come from variants of Pi that compile extensions into their own binary. For example Pi-bolt, a downstream AOT compiled fork of Pi that I run, does this, and it is how I hit the bug. The fix does not depend on this: any builtin: name should reach the child unchanged, and the host decides how it resolves, as with the other keyed entries.

Native settings.json toggles do not apply to allowlisted children. That is intended.

Proposed change

Mirror Pi's prefix list in one constant, with a comment to keep it in step with Pi's isLocalPath(). Then: pass those prefixes through, expand ~/ and file://, keep absolute paths, and resolve anything else against the agent directory as today.

Tests: each prefix passes through; ~/x and file:///x are normalised; relative and absolute entries behave as before.

Reproduction

  1. Set pi.subagent_extensions = ["git:github.com/owner/repo"] in ~/.config/cortexkit/magic-context.jsonc.
  2. Trigger a historian or dreamer child.
  3. Child fails to load selected extension (evidenced in logs/request behaviour eg. in my case where it is a required provider extension - model not found)

Harness coverage

  • OpenCode 1 and 2: not applicable, no pi.subagent_extensions.
  • Pi: covered by the change.
  • OMP: covered by the change, shared resolver. Needs an explicit check.
  • Rust module: not applicable.

Environment

  • Magic Context: fork base v0.49.0; upstream master as of this report.
  • Pi: @earendil-works/pi-coding-agent 1.1.0 (also Pi-Bolt 0.8.5 for the builtin: case)
  • Platform: Linux x64, NixOS.
  • Client: Pi.

Diagnostics

Forthcoming (pending a clean env and latest upstream magic-context as I'm running a fork with it fixed atm)

Plugin version

0.49.0

OpenCode version

No response

Platform

Linux x64

Client

Pi

Log output (optional)

Activity

  1. magic-alfonso commented on Oct 13, 2026

    @magic-alfonso

    Thanks, confirmed. resolveSubagentExtensionEntry only treats npm: and absolute paths as given, so the other source prefixes become paths under the agent directory, and ~/ and file:// entries aren't expanded. The fix mirrors the host's own isLocalPath() rule in one place (checked separately for Oh My Pi), expands ~/ and file://, and keeps relative and absolute entries as they are today. It will be in the next release.

  2. magic-alfonso commented on Oct 13, 2026

    @magic-alfonso

    Fixed on master. The two hosts handle these entries differently, so the resolver now follows each one:

    • Pi: npm:, git:, github:, http:, https:, ssh: and builtin: entries pass through unchanged, matching Pi 1.1.0's isLocalPath(). ~/ and file:// are expanded; absolute paths stay as given; other relative entries still resolve against the agent directory.
    • Oh My Pi: its loader resolves every configured entry as a path (remote packages are installed separately with omp install), so only the existing npm: passthrough is kept there, and ~/ and file:// are expanded the way its resolvePath does.

    It will be in the next release.

  3. Shrub24 commented on Oct 13, 2026

    @Shrub24
    Author

    Beat me to it! Thanks :)

  4. magic-alfonso commented on Oct 14, 2026

    @magic-alfonso

    Fixed in 0.49.1. On Pi, pi.subagent_extensions now passes remote sources (git:, github:, https:, ssh:, builtin:) through unchanged instead of resolving them as relative paths, and handles ~/ and file:// the way Pi does. Oh My Pi loads entries as paths, so its behaviour is unchanged. Update with npx @cortexkit/magic-context@latest setup or by bumping the plugin version, then restart the host.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions