You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
We run Magic Context with pi-web, which hosts multiple independent AgentSessions inside one Next.js Node process. Current Magic Context partially assumes "one Pi process = one primary session", which breaks the second and later sessions.
We have a working compatibility layer on top of v0.38.1 and would like to propose upstreaming its core: a small public Host Adapter API in packages/pi-plugin, so external embedded hosts can declare their hosting model instead of forking the plugin. This is related to #247 (closed) and overlaps in goal with the open PR #350 — we'd like to coordinate rather than compete.
Observed failures with stock Magic Context in stock pi-web
Reproduced against unmodified @cortexkit/pi-magic-context inside an unmodified production build of pi-web:
Historian/subagent spawning derives the Pi entry from process.argv[1], which in pi-web is the Next.js server entry, not a Pi CLI.
Spawned children then fail with unknown option '--print'.
Session cwd can resolve to the Next.js server directory instead of the actual project directory.
Net effect: tags/drops still run in session 1, but historian failure means no compartments are ever published and pending drops never complete.
Controlled comparison: with stock MC, session 1 gets the full ctx_* tool set and session 2 gets none. With our compat layer, both sessions register ctx_search / ctx_memory / ctx_note / ctx_expand / ctx_reduce, and both sessions' JSONL files land under the correct project cwd.
Proposal: a public MagicContextPiHostAdapter contract
Instead of encoding every host's quirks inside the plugin, let the host describe itself:
Runtime claims are managed by MC core, keyed by the adapter's runtimeKey (the ExtensionAPI instance), replacing the process-global "second init is a no-op" latch for primary sessions. The claim registry lives on globalThis via Symbol.for, so it survives jiti moduleCache: false re-imports. In-process hidden children keep the existing lean/no-op path via MAGIC_CONTEXT_PI_SUBAGENT=1.
Adapter loading is explicit: MAGIC_CONTEXT_PI_HOST_ADAPTER env var, or a plain Pi extension that registers only the adapter factory (no tools). A Next.js entry auto-detects as embedded-multi-session; MAGIC_CONTEXT_PI_HOST_MODE overrides.
Scope discipline: no changes to project-identity semantics, sessionId is never used as a memory key, no core storage/schema changes, OpenCode plugin untouched, and no global mutation of process.argv / process.cwd() / PATH.
Subagent launches accept a host-provided invocation (command = real execPath/Pi binary, prefixArgs = real CLI entry, cwd = parent session's project dir) instead of reusing process.argv[1].
Implementation status (working branch, rebased on v0.38.1)
Split as packages/pi-plugin/src/host-adapter/ (public API + loader + runtime registry) plus a separate, out-of-treepi-web-adapter package. For upstreaming we would scope the PR to the host-adapter API layer only; the pi-web-specific glue package stays external.
packages/pi-plugin: 808 tests passing + typecheck clean on the v0.38.1 base; new loader/adapter tests included.
Real-subprocess smoke test: with process.argv[1] pointing at a fake Next.js entry, PiSubagentRunner still spawns the resolved Pi CLI and the child receives --print --mode json --no-session and returns agent_end successfully.
Dreamer timers are ref-counted per runtime claim, so closing one web session does not tear down a sibling session's project timer.
Full end-to-end historian publish chain against a real model is the remaining validation item on our side.
If the direction is acceptable, we'll prepare a PR scoped to packages/pi-plugin/src/host-adapter/ (+ tests + PARITY.md notes), keeping the external adapter package out of the monorepo.
Happy to share the working branch or a diff of the API layer.
Summary
We run Magic Context with pi-web, which hosts multiple independent
AgentSessions inside one Next.js Node process. Current Magic Context partially assumes "one Pi process = one primary session", which breaks the second and later sessions.We have a working compatibility layer on top of v0.38.1 and would like to propose upstreaming its core: a small public Host Adapter API in
packages/pi-plugin, so external embedded hosts can declare their hosting model instead of forking the plugin. This is related to #247 (closed) and overlaps in goal with the open PR #350 — we'd like to coordinate rather than compete.Observed failures with stock Magic Context in stock pi-web
Reproduced against unmodified
@cortexkit/pi-magic-contextinside an unmodified production build of pi-web:process.argv[1], which in pi-web is the Next.js server entry, not a Pi CLI.unknown option '--print'.cwdcan resolve to the Next.js server directory instead of the actual project directory.Controlled comparison: with stock MC, session 1 gets the full
ctx_*tool set and session 2 gets none. With our compat layer, both sessions registerctx_search/ctx_memory/ctx_note/ctx_expand/ctx_reduce, and both sessions' JSONL files land under the correct project cwd.Proposal: a public
MagicContextPiHostAdaptercontractInstead of encoding every host's quirks inside the plugin, let the host describe itself:
Design points:
runtimeKey(theExtensionAPIinstance), replacing the process-global "second init is a no-op" latch for primary sessions. The claim registry lives onglobalThisviaSymbol.for, so it survives jitimoduleCache: falsere-imports. In-process hidden children keep the existing lean/no-op path viaMAGIC_CONTEXT_PI_SUBAGENT=1.MAGIC_CONTEXT_PI_HOST_ADAPTERenv var, or a plain Pi extension that registers only the adapter factory (no tools). A Next.js entry auto-detects asembedded-multi-session;MAGIC_CONTEXT_PI_HOST_MODEoverrides.sessionIdis never used as a memory key, no core storage/schema changes, OpenCode plugin untouched, and no global mutation ofprocess.argv/process.cwd()/PATH.command= real execPath/Pi binary,prefixArgs= real CLI entry,cwd= parent session's project dir) instead of reusingprocess.argv[1].Implementation status (working branch, rebased on v0.38.1)
packages/pi-plugin/src/host-adapter/(public API + loader + runtime registry) plus a separate, out-of-treepi-web-adapterpackage. For upstreaming we would scope the PR to thehost-adapterAPI layer only; the pi-web-specific glue package stays external.packages/pi-plugin: 808 tests passing + typecheck clean on the v0.38.1 base; new loader/adapter tests included.process.argv[1]pointing at a fake Next.js entry,PiSubagentRunnerstill spawns the resolved Pi CLI and the child receives--print --mode json --no-sessionand returnsagent_endsuccessfully.Relationship to #247 and #350
packages/pi-plugin. Our proposal is complementary rather than mutually exclusive: fix(pi-plugin): support pi-web multi-session and RPC hosts #350 fixes which calls initialize; a Host Adapter API fixes how hosts declare their runtime topology (cwd resolution, CLI resolution, lifecycle ownership). We're happy to port our API on top of fix(pi-plugin): support pi-web multi-session and RPC hosts #350's internals if that lands first, or to split the work along that boundary.Asks
packages/pi-plugin?packages/pi-plugin/src/host-adapter/(+ tests + PARITY.md notes), keeping the external adapter package out of the monorepo.Happy to share the working branch or a diff of the API layer.