@mxalbert/context-mode 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +33 -0
- package/.claude-plugin/plugin.json +31 -0
- package/.codex-plugin/hooks.json +65 -0
- package/.codex-plugin/mcp.json +13 -0
- package/.codex-plugin/plugin.json +31 -0
- package/.openclaw-plugin/index.ts +12 -0
- package/.openclaw-plugin/openclaw.plugin.json +38 -0
- package/.openclaw-plugin/package.json +28 -0
- package/LICENSE +94 -0
- package/README.md +1619 -0
- package/bin/statusline.mjs +378 -0
- package/build/adapters/antigravity/index.d.ts +51 -0
- package/build/adapters/antigravity/index.js +169 -0
- package/build/adapters/antigravity-cli/index.d.ts +51 -0
- package/build/adapters/antigravity-cli/index.js +342 -0
- package/build/adapters/base.d.ts +92 -0
- package/build/adapters/base.js +135 -0
- package/build/adapters/claude-code/config.d.ts +8 -0
- package/build/adapters/claude-code/config.js +8 -0
- package/build/adapters/claude-code/hooks.d.ts +106 -0
- package/build/adapters/claude-code/hooks.js +183 -0
- package/build/adapters/claude-code/index.d.ts +80 -0
- package/build/adapters/claude-code/index.js +569 -0
- package/build/adapters/claude-code-base.d.ts +49 -0
- package/build/adapters/claude-code-base.js +113 -0
- package/build/adapters/client-map.d.ts +10 -0
- package/build/adapters/client-map.js +42 -0
- package/build/adapters/codex/config.d.ts +8 -0
- package/build/adapters/codex/config.js +8 -0
- package/build/adapters/codex/hooks.d.ts +55 -0
- package/build/adapters/codex/hooks.js +64 -0
- package/build/adapters/codex/index.d.ts +87 -0
- package/build/adapters/codex/index.js +995 -0
- package/build/adapters/codex/paths.d.ts +1 -0
- package/build/adapters/codex/paths.js +12 -0
- package/build/adapters/codex/usage.d.ts +107 -0
- package/build/adapters/codex/usage.js +227 -0
- package/build/adapters/copilot-base.d.ts +94 -0
- package/build/adapters/copilot-base.js +297 -0
- package/build/adapters/copilot-cli/hooks.d.ts +33 -0
- package/build/adapters/copilot-cli/hooks.js +64 -0
- package/build/adapters/copilot-cli/index.d.ts +48 -0
- package/build/adapters/copilot-cli/index.js +341 -0
- package/build/adapters/cursor/config.d.ts +4 -0
- package/build/adapters/cursor/config.js +4 -0
- package/build/adapters/cursor/hooks.d.ts +55 -0
- package/build/adapters/cursor/hooks.js +82 -0
- package/build/adapters/cursor/index.d.ts +64 -0
- package/build/adapters/cursor/index.js +517 -0
- package/build/adapters/detect.d.ts +136 -0
- package/build/adapters/detect.js +623 -0
- package/build/adapters/gemini-cli/config.d.ts +8 -0
- package/build/adapters/gemini-cli/config.js +8 -0
- package/build/adapters/gemini-cli/hooks.d.ts +83 -0
- package/build/adapters/gemini-cli/hooks.js +115 -0
- package/build/adapters/gemini-cli/index.d.ts +80 -0
- package/build/adapters/gemini-cli/index.js +483 -0
- package/build/adapters/jetbrains-copilot/config.d.ts +8 -0
- package/build/adapters/jetbrains-copilot/config.js +8 -0
- package/build/adapters/jetbrains-copilot/hooks.d.ts +59 -0
- package/build/adapters/jetbrains-copilot/hooks.js +87 -0
- package/build/adapters/jetbrains-copilot/index.d.ts +31 -0
- package/build/adapters/jetbrains-copilot/index.js +131 -0
- package/build/adapters/kimi/config.d.ts +8 -0
- package/build/adapters/kimi/config.js +8 -0
- package/build/adapters/kimi/hooks.d.ts +28 -0
- package/build/adapters/kimi/hooks.js +34 -0
- package/build/adapters/kimi/index.d.ts +66 -0
- package/build/adapters/kimi/index.js +537 -0
- package/build/adapters/kimi/paths.d.ts +21 -0
- package/build/adapters/kimi/paths.js +52 -0
- package/build/adapters/kimi/usage.d.ts +82 -0
- package/build/adapters/kimi/usage.js +217 -0
- package/build/adapters/kiro/hooks.d.ts +61 -0
- package/build/adapters/kiro/hooks.js +94 -0
- package/build/adapters/kiro/index.d.ts +61 -0
- package/build/adapters/kiro/index.js +301 -0
- package/build/adapters/omp/index.d.ts +65 -0
- package/build/adapters/omp/index.js +182 -0
- package/build/adapters/omp/plugin.d.ts +81 -0
- package/build/adapters/omp/plugin.js +331 -0
- package/build/adapters/omp/usage.d.ts +49 -0
- package/build/adapters/omp/usage.js +110 -0
- package/build/adapters/openclaw/config.d.ts +8 -0
- package/build/adapters/openclaw/config.js +8 -0
- package/build/adapters/openclaw/hooks.d.ts +50 -0
- package/build/adapters/openclaw/hooks.js +61 -0
- package/build/adapters/openclaw/index.d.ts +74 -0
- package/build/adapters/openclaw/index.js +439 -0
- package/build/adapters/openclaw/mcp-tools.d.ts +54 -0
- package/build/adapters/openclaw/mcp-tools.js +207 -0
- package/build/adapters/openclaw/plugin.d.ts +141 -0
- package/build/adapters/openclaw/plugin.js +818 -0
- package/build/adapters/openclaw/session-db.d.ts +55 -0
- package/build/adapters/openclaw/session-db.js +88 -0
- package/build/adapters/openclaw/usage.d.ts +34 -0
- package/build/adapters/openclaw/usage.js +52 -0
- package/build/adapters/openclaw/workspace-router.d.ts +29 -0
- package/build/adapters/openclaw/workspace-router.js +64 -0
- package/build/adapters/opencode/config.d.ts +8 -0
- package/build/adapters/opencode/config.js +8 -0
- package/build/adapters/opencode/hooks.d.ts +38 -0
- package/build/adapters/opencode/hooks.js +50 -0
- package/build/adapters/opencode/index.d.ts +144 -0
- package/build/adapters/opencode/index.js +638 -0
- package/build/adapters/opencode/plugin.d.ts +249 -0
- package/build/adapters/opencode/plugin.js +1536 -0
- package/build/adapters/opencode/v2.d.ts +117 -0
- package/build/adapters/opencode/v2.js +224 -0
- package/build/adapters/opencode/zod3tov4.d.ts +1 -0
- package/build/adapters/opencode/zod3tov4.js +132 -0
- package/build/adapters/pi/extension.d.ts +81 -0
- package/build/adapters/pi/extension.js +861 -0
- package/build/adapters/pi/index.d.ts +57 -0
- package/build/adapters/pi/index.js +173 -0
- package/build/adapters/pi/mcp-bridge.d.ts +268 -0
- package/build/adapters/pi/mcp-bridge.js +894 -0
- package/build/adapters/qwen-code/hooks.d.ts +26 -0
- package/build/adapters/qwen-code/hooks.js +29 -0
- package/build/adapters/qwen-code/index.d.ts +40 -0
- package/build/adapters/qwen-code/index.js +361 -0
- package/build/adapters/qwen-code/usage.d.ts +90 -0
- package/build/adapters/qwen-code/usage.js +222 -0
- package/build/adapters/types.d.ts +360 -0
- package/build/adapters/types.js +118 -0
- package/build/adapters/vscode-copilot/config.d.ts +8 -0
- package/build/adapters/vscode-copilot/config.js +8 -0
- package/build/adapters/vscode-copilot/hooks.d.ts +71 -0
- package/build/adapters/vscode-copilot/hooks.js +98 -0
- package/build/adapters/vscode-copilot/index.d.ts +32 -0
- package/build/adapters/vscode-copilot/index.js +222 -0
- package/build/adapters/zed/index.d.ts +40 -0
- package/build/adapters/zed/index.js +163 -0
- package/build/cli.d.ts +34 -0
- package/build/cli.js +1828 -0
- package/build/db-base.d.ts +250 -0
- package/build/db-base.js +756 -0
- package/build/executor.d.ts +72 -0
- package/build/executor.js +678 -0
- package/build/exit-classify.d.ts +19 -0
- package/build/exit-classify.js +12 -0
- package/build/fetch/blocks.d.ts +145 -0
- package/build/fetch/blocks.js +244 -0
- package/build/fetch/extract.d.ts +68 -0
- package/build/fetch/extract.js +123 -0
- package/build/fetch/page-store.d.ts +66 -0
- package/build/fetch/page-store.js +174 -0
- package/build/fetch-cache.d.ts +13 -0
- package/build/fetch-cache.js +15 -0
- package/build/lifecycle.d.ts +124 -0
- package/build/lifecycle.js +278 -0
- package/build/package-identity.d.ts +26 -0
- package/build/package-identity.js +28 -0
- package/build/runPool.d.ts +36 -0
- package/build/runPool.js +51 -0
- package/build/runtime.d.ts +71 -0
- package/build/runtime.js +659 -0
- package/build/search/auto-memory.d.ts +47 -0
- package/build/search/auto-memory.js +170 -0
- package/build/search/ctx-search-schema.d.ts +90 -0
- package/build/search/ctx-search-schema.js +135 -0
- package/build/search/flood-guard.d.ts +57 -0
- package/build/search/flood-guard.js +80 -0
- package/build/search/unified.d.ts +56 -0
- package/build/search/unified.js +104 -0
- package/build/security.d.ts +206 -0
- package/build/security.js +780 -0
- package/build/server.d.ts +240 -0
- package/build/server.js +5034 -0
- package/build/session/analytics.d.ts +773 -0
- package/build/session/analytics.js +2420 -0
- package/build/session/db.d.ts +468 -0
- package/build/session/db.js +1330 -0
- package/build/session/error-classifier.d.ts +87 -0
- package/build/session/error-classifier.js +303 -0
- package/build/session/event-emit.d.ts +48 -0
- package/build/session/event-emit.js +101 -0
- package/build/session/extract.d.ts +333 -0
- package/build/session/extract.js +2688 -0
- package/build/session/model-prices.json +429 -0
- package/build/session/persist-tool-calls.d.ts +54 -0
- package/build/session/persist-tool-calls.js +105 -0
- package/build/session/pricing.d.ts +64 -0
- package/build/session/pricing.js +151 -0
- package/build/session/project-attribution.d.ts +73 -0
- package/build/session/project-attribution.js +245 -0
- package/build/session/purge.d.ts +138 -0
- package/build/session/purge.js +240 -0
- package/build/session/retrieval-marker.d.ts +39 -0
- package/build/session/retrieval-marker.js +65 -0
- package/build/session/snapshot.d.ts +46 -0
- package/build/session/snapshot.js +532 -0
- package/build/store-directory.d.ts +56 -0
- package/build/store-directory.js +254 -0
- package/build/store.d.ts +147 -0
- package/build/store.js +1714 -0
- package/build/truncate.d.ts +57 -0
- package/build/truncate.js +142 -0
- package/build/types.d.ts +117 -0
- package/build/types.js +20 -0
- package/build/util/claude-config.d.ts +32 -0
- package/build/util/claude-config.js +84 -0
- package/build/util/hook-config.d.ts +27 -0
- package/build/util/hook-config.js +76 -0
- package/build/util/jsonc.d.ts +14 -0
- package/build/util/jsonc.js +104 -0
- package/build/util/plugin-cache-integrity.d.ts +51 -0
- package/build/util/plugin-cache-integrity.js +146 -0
- package/build/util/project-dir.d.ts +149 -0
- package/build/util/project-dir.js +340 -0
- package/build/util/sibling-mcp.d.ts +79 -0
- package/build/util/sibling-mcp.js +181 -0
- package/cli.bundle.mjs +1495 -0
- package/configs/antigravity/GEMINI.md +68 -0
- package/configs/antigravity/mcp_config.json +7 -0
- package/configs/antigravity-cli/hooks/hooks.json +37 -0
- package/configs/antigravity-cli/hooks.json +37 -0
- package/configs/antigravity-cli/mcp_config.json +10 -0
- package/configs/antigravity-cli/plugin.json +14 -0
- package/configs/antigravity-cli/rules/context-mode.md +77 -0
- package/configs/antigravity-cli/skills/context-mode/SKILL.md +77 -0
- package/configs/claude-code/CLAUDE.md +91 -0
- package/configs/codex/AGENTS.md +99 -0
- package/configs/codex/config.toml +8 -0
- package/configs/codex/hooks.json +47 -0
- package/configs/copilot-cli/.github/plugin/plugin.json +23 -0
- package/configs/copilot-cli/.mcp.json +12 -0
- package/configs/copilot-cli/README.md +47 -0
- package/configs/copilot-cli/hooks.json +41 -0
- package/configs/copilot-cli/skills/context-mode/SKILL.md +38 -0
- package/configs/cursor/context-mode.mdc +76 -0
- package/configs/cursor/hooks.json +21 -0
- package/configs/cursor/mcp.json +7 -0
- package/configs/gemini-cli/GEMINI.md +88 -0
- package/configs/gemini-cli/mcp.json +7 -0
- package/configs/gemini-cli/settings.json +60 -0
- package/configs/jetbrains-copilot/copilot-instructions.md +80 -0
- package/configs/jetbrains-copilot/hooks.json +16 -0
- package/configs/jetbrains-copilot/mcp.json +7 -0
- package/configs/kilo/AGENTS.md +84 -0
- package/configs/kilo/kilo.json +6 -0
- package/configs/kimi/hooks.json +54 -0
- package/configs/kiro/KIRO.md +84 -0
- package/configs/kiro/agent.json +18 -0
- package/configs/kiro/mcp.json +7 -0
- package/configs/omp/SYSTEM.md +85 -0
- package/configs/omp/mcp.json +7 -0
- package/configs/openclaw/AGENTS.md +87 -0
- package/configs/openclaw/openclaw.json +13 -0
- package/configs/opencode/AGENTS.md +84 -0
- package/configs/opencode/opencode.json +6 -0
- package/configs/pi/AGENTS.md +3 -0
- package/configs/qwen-code/QWEN.md +91 -0
- package/configs/vscode-copilot/copilot-instructions.md +80 -0
- package/configs/vscode-copilot/hooks.json +16 -0
- package/configs/vscode-copilot/mcp.json +7 -0
- package/configs/zed/AGENTS.md +68 -0
- package/hooks/antigravity-cli/payload.mjs +98 -0
- package/hooks/antigravity-cli/posttooluse.mjs +138 -0
- package/hooks/antigravity-cli/pretooluse.mjs +78 -0
- package/hooks/antigravity-cli/stop.mjs +58 -0
- package/hooks/auto-injection.mjs +102 -0
- package/hooks/cache-heal-utils.mjs +379 -0
- package/hooks/codex/platform.mjs +1 -0
- package/hooks/codex/posttooluse.mjs +66 -0
- package/hooks/codex/precompact.mjs +70 -0
- package/hooks/codex/pretooluse.mjs +42 -0
- package/hooks/codex/sessionstart.mjs +121 -0
- package/hooks/codex/stop.mjs +138 -0
- package/hooks/codex/userpromptsubmit.mjs +75 -0
- package/hooks/copilot-cli/posttooluse.mjs +79 -0
- package/hooks/copilot-cli/precompact.mjs +66 -0
- package/hooks/copilot-cli/pretooluse.mjs +41 -0
- package/hooks/copilot-cli/sessionstart.mjs +121 -0
- package/hooks/copilot-cli/stop.mjs +59 -0
- package/hooks/copilot-cli/userpromptsubmit.mjs +77 -0
- package/hooks/core/codex-caps.mjs +112 -0
- package/hooks/core/formatters.mjs +356 -0
- package/hooks/core/mcp-ready.mjs +109 -0
- package/hooks/core/platform-detect.mjs +49 -0
- package/hooks/core/routing.mjs +1050 -0
- package/hooks/core/stdin.mjs +90 -0
- package/hooks/core/tool-naming.mjs +57 -0
- package/hooks/cursor/afteragentresponse.mjs +74 -0
- package/hooks/cursor/hooks.json +31 -0
- package/hooks/cursor/posttooluse.mjs +72 -0
- package/hooks/cursor/pretooluse.mjs +26 -0
- package/hooks/cursor/sessionstart.mjs +97 -0
- package/hooks/cursor/stop.mjs +48 -0
- package/hooks/ensure-deps.mjs +254 -0
- package/hooks/formatters/claude-code.mjs +113 -0
- package/hooks/formatters/cursor.mjs +37 -0
- package/hooks/formatters/gemini-cli.mjs +55 -0
- package/hooks/formatters/vscode-copilot.mjs +55 -0
- package/hooks/gemini-cli/aftermodel.mjs +70 -0
- package/hooks/gemini-cli/aftertool.mjs +61 -0
- package/hooks/gemini-cli/beforeagent.mjs +99 -0
- package/hooks/gemini-cli/beforetool.mjs +27 -0
- package/hooks/gemini-cli/precompress.mjs +55 -0
- package/hooks/gemini-cli/sessionstart.mjs +137 -0
- package/hooks/heal-partial-install.mjs +712 -0
- package/hooks/hooks.json +143 -0
- package/hooks/jetbrains-copilot/posttooluse.mjs +61 -0
- package/hooks/jetbrains-copilot/precompact.mjs +55 -0
- package/hooks/jetbrains-copilot/pretooluse.mjs +27 -0
- package/hooks/jetbrains-copilot/sessionstart.mjs +124 -0
- package/hooks/kimi/platform.mjs +1 -0
- package/hooks/kimi/posttooluse.mjs +72 -0
- package/hooks/kimi/precompact.mjs +80 -0
- package/hooks/kimi/pretooluse.mjs +42 -0
- package/hooks/kimi/sessionend.mjs +61 -0
- package/hooks/kimi/sessionstart.mjs +113 -0
- package/hooks/kimi/stop.mjs +132 -0
- package/hooks/kimi/userpromptsubmit.mjs +90 -0
- package/hooks/kiro/agentspawn.mjs +97 -0
- package/hooks/kiro/posttooluse.mjs +51 -0
- package/hooks/kiro/pretooluse.mjs +64 -0
- package/hooks/kiro/userpromptsubmit.mjs +88 -0
- package/hooks/normalize-hooks.mjs +323 -0
- package/hooks/platform-bridge.mjs +340 -0
- package/hooks/posttooluse.mjs +225 -0
- package/hooks/precompact.mjs +100 -0
- package/hooks/pretooluse.mjs +227 -0
- package/hooks/qwen-code/platform.mjs +1 -0
- package/hooks/qwen-code/stop.mjs +168 -0
- package/hooks/routing-block.mjs +105 -0
- package/hooks/run-hook.mjs +95 -0
- package/hooks/security.bundle.mjs +2 -0
- package/hooks/session-attribution.bundle.mjs +1 -0
- package/hooks/session-db.bundle.mjs +145 -0
- package/hooks/session-directive.mjs +520 -0
- package/hooks/session-extract.bundle.mjs +3 -0
- package/hooks/session-helpers.mjs +428 -0
- package/hooks/session-loaders.mjs +448 -0
- package/hooks/session-snapshot.bundle.mjs +32 -0
- package/hooks/sessionstart.mjs +464 -0
- package/hooks/stop.mjs +82 -0
- package/hooks/suppress-stderr.mjs +25 -0
- package/hooks/userpromptsubmit.mjs +108 -0
- package/hooks/vscode-copilot/posttooluse.mjs +61 -0
- package/hooks/vscode-copilot/precompact.mjs +55 -0
- package/hooks/vscode-copilot/pretooluse.mjs +27 -0
- package/hooks/vscode-copilot/sessionstart.mjs +129 -0
- package/openclaw.plugin.json +38 -0
- package/package.json +132 -0
- package/scripts/heal-better-sqlite3.mjs +430 -0
- package/scripts/heal-installed-plugins.mjs +635 -0
- package/scripts/plugin-cache-integrity.mjs +248 -0
- package/scripts/postinstall.mjs +397 -0
- package/server.bundle.mjs +1421 -0
- package/server.js +5 -0
- package/skills/.ignore +7 -0
- package/skills/context-mode/SKILL.md +300 -0
- package/skills/context-mode/references/anti-patterns.md +283 -0
- package/skills/context-mode/references/patterns-javascript.md +298 -0
- package/skills/context-mode/references/patterns-python.md +304 -0
- package/skills/context-mode/references/patterns-shell.md +277 -0
- package/skills/ctx-doctor/SKILL.md +22 -0
- package/skills/ctx-index/SKILL.md +46 -0
- package/skills/ctx-insight/SKILL.md +24 -0
- package/skills/ctx-purge/SKILL.md +49 -0
- package/skills/ctx-search/SKILL.md +35 -0
- package/skills/ctx-stats/SKILL.md +26 -0
- package/skills/ctx-upgrade/SKILL.md +31 -0
- package/start.mjs +616 -0
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* adapters/pi — Pi coding agent platform adapter.
|
|
3
|
+
*
|
|
4
|
+
* Implements HookAdapter for Pi's MCP-only paradigm at the adapter layer.
|
|
5
|
+
*
|
|
6
|
+
* Pi hook specifics:
|
|
7
|
+
* - NO JSON-stdio hooks. Pi exposes a JS-callback runtime API
|
|
8
|
+
* (`pi.on("session_start", fn)`, `pi.on("tool_call", fn)`, …) which is
|
|
9
|
+
* wired DIRECTLY by `src/adapters/pi/extension.ts`. The HookAdapter
|
|
10
|
+
* contract here intentionally reports `mcp-only` and all-false
|
|
11
|
+
* capabilities so harness paths that walk the JSON-stdio matrix do not
|
|
12
|
+
* try to register stdio hooks for Pi.
|
|
13
|
+
* - Config root: ~/.pi/
|
|
14
|
+
* - Settings: ~/.pi/settings.json (kept lightweight — Pi does not
|
|
15
|
+
* prescribe a canonical settings file, but several internal tools
|
|
16
|
+
* write one; using settings.json keeps parity with Claude Code).
|
|
17
|
+
* - Session dir: ~/.pi/context-mode/sessions/ (parallel to ~/.claude/,
|
|
18
|
+
* ~/.omp/) — this is the data-isolation contract from issue #473.
|
|
19
|
+
* - Instruction file: AGENTS.md (per configs/pi/AGENTS.md).
|
|
20
|
+
*
|
|
21
|
+
* Why a dedicated adapter is mandatory:
|
|
22
|
+
* Before this adapter existed, `getAdapter("pi")` fell through to the
|
|
23
|
+
* `default` arm of the switch in `src/adapters/detect.ts` and returned a
|
|
24
|
+
* ClaudeCodeAdapter. Pi sessions therefore wrote DBs and event logs into
|
|
25
|
+
* `~/.claude/context-mode/sessions/`, contaminating Claude Code state and
|
|
26
|
+
* silently leaking Pi user data into the wrong storage root (issue #473
|
|
27
|
+
* follow-up). The OMP adapter fixed the same class of bug for OMP; this
|
|
28
|
+
* adapter closes the gap for Pi.
|
|
29
|
+
*/
|
|
30
|
+
import { BaseAdapter } from "../base.js";
|
|
31
|
+
import type { HookAdapter, HookParadigm, PlatformCapabilities, DiagnosticResult, PreToolUseEvent, PostToolUseEvent, PreCompactEvent, SessionStartEvent, PreToolUseResponse, PostToolUseResponse, PreCompactResponse, SessionStartResponse, HookRegistration } from "../types.js";
|
|
32
|
+
export declare class PiAdapter extends BaseAdapter implements HookAdapter {
|
|
33
|
+
constructor();
|
|
34
|
+
readonly name = "Pi";
|
|
35
|
+
readonly paradigm: HookParadigm;
|
|
36
|
+
readonly capabilities: PlatformCapabilities;
|
|
37
|
+
parsePreToolUseInput(_raw: unknown): PreToolUseEvent;
|
|
38
|
+
parsePostToolUseInput(_raw: unknown): PostToolUseEvent;
|
|
39
|
+
parsePreCompactInput(_raw: unknown): PreCompactEvent;
|
|
40
|
+
parseSessionStartInput(_raw: unknown): SessionStartEvent;
|
|
41
|
+
formatPreToolUseResponse(_response: PreToolUseResponse): unknown;
|
|
42
|
+
formatPostToolUseResponse(_response: PostToolUseResponse): unknown;
|
|
43
|
+
formatPreCompactResponse(_response: PreCompactResponse): unknown;
|
|
44
|
+
formatSessionStartResponse(_response: SessionStartResponse): unknown;
|
|
45
|
+
getSettingsPath(): string;
|
|
46
|
+
getInstructionFiles(): string[];
|
|
47
|
+
generateHookConfig(_pluginRoot: string): HookRegistration;
|
|
48
|
+
readSettings(): Record<string, unknown> | null;
|
|
49
|
+
writeSettings(settings: Record<string, unknown>): void;
|
|
50
|
+
validateHooks(_pluginRoot: string): DiagnosticResult[];
|
|
51
|
+
checkPluginRegistration(): DiagnosticResult;
|
|
52
|
+
getInstalledVersion(): string;
|
|
53
|
+
configureAllHooks(_pluginRoot: string): string[];
|
|
54
|
+
setHookPermissions(_pluginRoot: string): string[];
|
|
55
|
+
updatePluginRegistry(_pluginRoot: string, _version: string): void;
|
|
56
|
+
getRoutingInstructions(): string;
|
|
57
|
+
}
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* adapters/pi — Pi coding agent platform adapter.
|
|
3
|
+
*
|
|
4
|
+
* Implements HookAdapter for Pi's MCP-only paradigm at the adapter layer.
|
|
5
|
+
*
|
|
6
|
+
* Pi hook specifics:
|
|
7
|
+
* - NO JSON-stdio hooks. Pi exposes a JS-callback runtime API
|
|
8
|
+
* (`pi.on("session_start", fn)`, `pi.on("tool_call", fn)`, …) which is
|
|
9
|
+
* wired DIRECTLY by `src/adapters/pi/extension.ts`. The HookAdapter
|
|
10
|
+
* contract here intentionally reports `mcp-only` and all-false
|
|
11
|
+
* capabilities so harness paths that walk the JSON-stdio matrix do not
|
|
12
|
+
* try to register stdio hooks for Pi.
|
|
13
|
+
* - Config root: ~/.pi/
|
|
14
|
+
* - Settings: ~/.pi/settings.json (kept lightweight — Pi does not
|
|
15
|
+
* prescribe a canonical settings file, but several internal tools
|
|
16
|
+
* write one; using settings.json keeps parity with Claude Code).
|
|
17
|
+
* - Session dir: ~/.pi/context-mode/sessions/ (parallel to ~/.claude/,
|
|
18
|
+
* ~/.omp/) — this is the data-isolation contract from issue #473.
|
|
19
|
+
* - Instruction file: AGENTS.md (per configs/pi/AGENTS.md).
|
|
20
|
+
*
|
|
21
|
+
* Why a dedicated adapter is mandatory:
|
|
22
|
+
* Before this adapter existed, `getAdapter("pi")` fell through to the
|
|
23
|
+
* `default` arm of the switch in `src/adapters/detect.ts` and returned a
|
|
24
|
+
* ClaudeCodeAdapter. Pi sessions therefore wrote DBs and event logs into
|
|
25
|
+
* `~/.claude/context-mode/sessions/`, contaminating Claude Code state and
|
|
26
|
+
* silently leaking Pi user data into the wrong storage root (issue #473
|
|
27
|
+
* follow-up). The OMP adapter fixed the same class of bug for OMP; this
|
|
28
|
+
* adapter closes the gap for Pi.
|
|
29
|
+
*/
|
|
30
|
+
import { readFileSync, writeFileSync, mkdirSync, } from "node:fs";
|
|
31
|
+
import { resolve, dirname } from "node:path";
|
|
32
|
+
import { homedir } from "node:os";
|
|
33
|
+
import { BaseAdapter } from "../base.js";
|
|
34
|
+
// ─────────────────────────────────────────────────────────
|
|
35
|
+
// Adapter implementation
|
|
36
|
+
// ─────────────────────────────────────────────────────────
|
|
37
|
+
export class PiAdapter extends BaseAdapter {
|
|
38
|
+
constructor() {
|
|
39
|
+
super([".pi"]);
|
|
40
|
+
}
|
|
41
|
+
name = "Pi";
|
|
42
|
+
paradigm = "mcp-only";
|
|
43
|
+
capabilities = {
|
|
44
|
+
preToolUse: false,
|
|
45
|
+
postToolUse: false,
|
|
46
|
+
preCompact: false,
|
|
47
|
+
sessionStart: false,
|
|
48
|
+
canModifyArgs: false,
|
|
49
|
+
canModifyOutput: false,
|
|
50
|
+
canInjectSessionContext: false,
|
|
51
|
+
};
|
|
52
|
+
// ── Input parsing ──────────────────────────────────────
|
|
53
|
+
// Pi does not feed the adapter via JSON-stdio. These methods exist to
|
|
54
|
+
// satisfy the HookAdapter contract and throw if the harness mistakenly
|
|
55
|
+
// routes a JSON-stdio event through the adapter.
|
|
56
|
+
parsePreToolUseInput(_raw) {
|
|
57
|
+
throw new Error("Pi does not support JSON-stdio hooks (wired via extension.ts)");
|
|
58
|
+
}
|
|
59
|
+
parsePostToolUseInput(_raw) {
|
|
60
|
+
throw new Error("Pi does not support JSON-stdio hooks (wired via extension.ts)");
|
|
61
|
+
}
|
|
62
|
+
parsePreCompactInput(_raw) {
|
|
63
|
+
throw new Error("Pi does not support JSON-stdio hooks (wired via extension.ts)");
|
|
64
|
+
}
|
|
65
|
+
parseSessionStartInput(_raw) {
|
|
66
|
+
throw new Error("Pi does not support JSON-stdio hooks (wired via extension.ts)");
|
|
67
|
+
}
|
|
68
|
+
// ── Response formatting ────────────────────────────────
|
|
69
|
+
// No JSON-stdio path — return undefined to satisfy the contract.
|
|
70
|
+
formatPreToolUseResponse(_response) {
|
|
71
|
+
return undefined;
|
|
72
|
+
}
|
|
73
|
+
formatPostToolUseResponse(_response) {
|
|
74
|
+
return undefined;
|
|
75
|
+
}
|
|
76
|
+
formatPreCompactResponse(_response) {
|
|
77
|
+
return undefined;
|
|
78
|
+
}
|
|
79
|
+
formatSessionStartResponse(_response) {
|
|
80
|
+
return undefined;
|
|
81
|
+
}
|
|
82
|
+
// ── Configuration ──────────────────────────────────────
|
|
83
|
+
getSettingsPath() {
|
|
84
|
+
return resolve(homedir(), ".pi", "settings.json");
|
|
85
|
+
}
|
|
86
|
+
getInstructionFiles() {
|
|
87
|
+
return ["AGENTS.md"];
|
|
88
|
+
}
|
|
89
|
+
generateHookConfig(_pluginRoot) {
|
|
90
|
+
return {};
|
|
91
|
+
}
|
|
92
|
+
readSettings() {
|
|
93
|
+
try {
|
|
94
|
+
const raw = readFileSync(this.getSettingsPath(), "utf-8");
|
|
95
|
+
return JSON.parse(raw);
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
writeSettings(settings) {
|
|
102
|
+
const settingsPath = this.getSettingsPath();
|
|
103
|
+
mkdirSync(dirname(settingsPath), { recursive: true });
|
|
104
|
+
writeFileSync(settingsPath, JSON.stringify(settings, null, 2), "utf-8");
|
|
105
|
+
}
|
|
106
|
+
// ── Diagnostics (doctor) ─────────────────────────────────
|
|
107
|
+
validateHooks(_pluginRoot) {
|
|
108
|
+
return [
|
|
109
|
+
{
|
|
110
|
+
check: "Hook support",
|
|
111
|
+
status: "pass",
|
|
112
|
+
message: "Pi hooks are wired via the context-mode Pi extension " +
|
|
113
|
+
"(~/.pi/extensions/context-mode/), not via JSON-stdio.",
|
|
114
|
+
},
|
|
115
|
+
];
|
|
116
|
+
}
|
|
117
|
+
checkPluginRegistration() {
|
|
118
|
+
// Pi registers extensions by directory presence; the version-sync
|
|
119
|
+
// script writes ~/.pi/extensions/context-mode/package.json. We treat
|
|
120
|
+
// that file as the registration signal.
|
|
121
|
+
const pkgPath = resolve(homedir(), ".pi", "extensions", "context-mode", "package.json");
|
|
122
|
+
try {
|
|
123
|
+
const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
|
|
124
|
+
if (pkg?.name === "context-mode") {
|
|
125
|
+
return {
|
|
126
|
+
check: "Pi extension registration",
|
|
127
|
+
status: "pass",
|
|
128
|
+
message: `context-mode extension installed at ${pkgPath}`,
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
return {
|
|
132
|
+
check: "Pi extension registration",
|
|
133
|
+
status: "warn",
|
|
134
|
+
message: `Unexpected package at ${pkgPath}`,
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
catch {
|
|
138
|
+
return {
|
|
139
|
+
check: "Pi extension registration",
|
|
140
|
+
status: "fail",
|
|
141
|
+
message: `context-mode not found at ${pkgPath}`,
|
|
142
|
+
fix: "Run: context-mode upgrade",
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
getInstalledVersion() {
|
|
147
|
+
try {
|
|
148
|
+
const pkgPath = resolve(homedir(), ".pi", "extensions", "context-mode", "package.json");
|
|
149
|
+
const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
|
|
150
|
+
return pkg.version ?? "unknown";
|
|
151
|
+
}
|
|
152
|
+
catch {
|
|
153
|
+
return "not installed";
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
// ── Upgrade ────────────────────────────────────────────
|
|
157
|
+
// Pi does NOT use settings.json hook entries. The extension is the
|
|
158
|
+
// integration point — there is nothing for the harness to register
|
|
159
|
+
// beyond copying the extension into ~/.pi/extensions/context-mode/.
|
|
160
|
+
configureAllHooks(_pluginRoot) {
|
|
161
|
+
return [];
|
|
162
|
+
}
|
|
163
|
+
setHookPermissions(_pluginRoot) {
|
|
164
|
+
return [];
|
|
165
|
+
}
|
|
166
|
+
updatePluginRegistry(_pluginRoot, _version) {
|
|
167
|
+
// Pi extension version is managed by scripts/version-sync.mjs writing
|
|
168
|
+
// to ~/.pi/extensions/context-mode/package.json. No-op here.
|
|
169
|
+
}
|
|
170
|
+
getRoutingInstructions() {
|
|
171
|
+
return "# context-mode\n\nUse context-mode MCP tools (ctx_execute, ctx_execute_file, ctx_batch_execute, ctx_fetch_and_index, ctx_search) instead of inline shell/HTTP calls for data-heavy operations.";
|
|
172
|
+
}
|
|
173
|
+
}
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP-stdio bridge for the Pi Coding Agent extension.
|
|
3
|
+
*
|
|
4
|
+
* Pi 0.73.x has no native MCP support — its README is explicit:
|
|
5
|
+
* > "No MCP. Build CLI tools with READMEs (see Skills), or build an
|
|
6
|
+
* > extension that adds MCP support."
|
|
7
|
+
*
|
|
8
|
+
* Without this bridge, the routing block tells the LLM to call
|
|
9
|
+
* `ctx_execute`, `ctx_search`, etc. — but those tools never enter Pi's
|
|
10
|
+
* tool list, so the LLM cannot reach them. context-mode then becomes a
|
|
11
|
+
* pure cost on Pi (~2.5K tokens of system-prompt overhead with 0
|
|
12
|
+
* actual ctx_* calls). Reported in mksglu/context-mode#426.
|
|
13
|
+
*
|
|
14
|
+
* The bridge spawns `server.bundle.mjs` as a long-lived child via stdio
|
|
15
|
+
* JSON-RPC, performs the MCP handshake, calls `tools/list` once, and
|
|
16
|
+
* registers each returned tool through `pi.registerTool({ … })`. Each
|
|
17
|
+
* tool's `execute()` forwards into the child via `tools/call` — same
|
|
18
|
+
* code path Claude Code, Gemini CLI, and the other adapters use, so
|
|
19
|
+
* Pi behavior matches the rest of the platform suite.
|
|
20
|
+
*
|
|
21
|
+
* No external dependencies — pure node:child_process + JSON line frames.
|
|
22
|
+
*/
|
|
23
|
+
export interface ResolveDeps {
|
|
24
|
+
detect?: () => {
|
|
25
|
+
javascript: string | null;
|
|
26
|
+
};
|
|
27
|
+
which?: (cmd: string) => string | null;
|
|
28
|
+
execPath?: string;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Resolve a JS runtime safe to spawn the MCP server with.
|
|
32
|
+
*
|
|
33
|
+
* Returns `null` when no real runtime is reachable (caller must skip
|
|
34
|
+
* the bridge gracefully — see bootstrapMCPTools). Pi-named binaries are
|
|
35
|
+
* explicitly rejected at every step to prevent the #516 fork bomb.
|
|
36
|
+
*/
|
|
37
|
+
export declare function resolveJsRuntimeForBridge(deps?: ResolveDeps): string | null;
|
|
38
|
+
export interface MCPTool {
|
|
39
|
+
name: string;
|
|
40
|
+
description?: string;
|
|
41
|
+
inputSchema?: Record<string, unknown>;
|
|
42
|
+
}
|
|
43
|
+
export interface MCPCallResult {
|
|
44
|
+
content?: Array<{
|
|
45
|
+
type?: string;
|
|
46
|
+
text?: string;
|
|
47
|
+
}>;
|
|
48
|
+
isError?: boolean;
|
|
49
|
+
}
|
|
50
|
+
export declare class PiTextComponent {
|
|
51
|
+
private text;
|
|
52
|
+
constructor(text?: string);
|
|
53
|
+
setText(text: string): void;
|
|
54
|
+
invalidate(): void;
|
|
55
|
+
render(width: number): string[];
|
|
56
|
+
}
|
|
57
|
+
export declare function truncateAnsiLine(line: string, maxWidth: number): string;
|
|
58
|
+
interface PiRenderTheme {
|
|
59
|
+
bold(text: string): string;
|
|
60
|
+
fg(color: string, text: string): string;
|
|
61
|
+
}
|
|
62
|
+
interface PiRenderContext {
|
|
63
|
+
lastComponent?: unknown;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Minimal stdio JSON-RPC client targeting the context-mode MCP server.
|
|
67
|
+
*
|
|
68
|
+
* Implementation notes:
|
|
69
|
+
* - One outstanding ID per request; results matched by `id` from the
|
|
70
|
+
* returned envelope. Notifications (no id) are sent fire-and-forget.
|
|
71
|
+
* - Buffer is split on `\n` because the MCP server writes one
|
|
72
|
+
* newline-delimited JSON message per `console.log` / `stdout.write`
|
|
73
|
+
* invocation — this is the standard MCP stdio transport framing.
|
|
74
|
+
* - On child exit / error, every in-flight request is rejected so
|
|
75
|
+
* callers do not hang forever.
|
|
76
|
+
*/
|
|
77
|
+
export declare class MCPStdioClient {
|
|
78
|
+
private readonly serverScript;
|
|
79
|
+
private readonly env;
|
|
80
|
+
private readonly runtimeOverride;
|
|
81
|
+
/**
|
|
82
|
+
* TUI-safe sink for the child's forwarded stderr (#868). Defaults to a
|
|
83
|
+
* no-op so direct callers (skippedBridge, tests) never leak to the
|
|
84
|
+
* terminal; bootstrapMCPTools wires this to the Pi host's file logger.
|
|
85
|
+
*/
|
|
86
|
+
private readonly diag;
|
|
87
|
+
private child;
|
|
88
|
+
private requestId;
|
|
89
|
+
private readonly pending;
|
|
90
|
+
private buffer;
|
|
91
|
+
private initialized;
|
|
92
|
+
private exited;
|
|
93
|
+
/**
|
|
94
|
+
* In-flight respawn promise — set while {@link respawn} runs so
|
|
95
|
+
* concurrent callers awaiting `request()` after an idle exit observe
|
|
96
|
+
* the SAME respawn, not N parallel ones. Without this guard, two
|
|
97
|
+
* simultaneous `callTool` calls would each see `this.exited === true`,
|
|
98
|
+
* each fire their own `respawn()`, and the loser leaks an orphaned
|
|
99
|
+
* child process the GC cannot reach (no `.kill()` reference).
|
|
100
|
+
*/
|
|
101
|
+
private respawnPromise;
|
|
102
|
+
/**
|
|
103
|
+
* Live env passed to the spawned child — exposed (read-only intent)
|
|
104
|
+
* so tests can pin the fork-bomb-prevention env counter (#516)
|
|
105
|
+
* without needing to attach a process-tree probe.
|
|
106
|
+
*/
|
|
107
|
+
_spawnEnv: NodeJS.ProcessEnv | null;
|
|
108
|
+
constructor(serverScript: string, env?: NodeJS.ProcessEnv, runtimeOverride?: string | null,
|
|
109
|
+
/**
|
|
110
|
+
* TUI-safe sink for the child's forwarded stderr (#868). Defaults to a
|
|
111
|
+
* no-op so direct callers (skippedBridge, tests) never leak to the
|
|
112
|
+
* terminal; bootstrapMCPTools wires this to the Pi host's file logger.
|
|
113
|
+
*/
|
|
114
|
+
diag?: BridgeDiag);
|
|
115
|
+
/** Spawn the MCP child. Idempotent. */
|
|
116
|
+
start(): void;
|
|
117
|
+
private onExit;
|
|
118
|
+
private onData;
|
|
119
|
+
request<T = unknown>(method: string, params: unknown, timeoutMs?: number): Promise<T>;
|
|
120
|
+
private writeFrame;
|
|
121
|
+
notify(method: string, params: unknown): void;
|
|
122
|
+
initialize(): Promise<void>;
|
|
123
|
+
listTools(): Promise<MCPTool[]>;
|
|
124
|
+
callTool(name: string, args: unknown): Promise<MCPCallResult>;
|
|
125
|
+
/**
|
|
126
|
+
* Respawn the MCP child after an exit (clean shutdown or crash).
|
|
127
|
+
* Resets state so a fresh `start()` + `initialize()` cycle runs, then
|
|
128
|
+
* the caller's pending request flows through the new child.
|
|
129
|
+
*
|
|
130
|
+
* Single-flight — concurrent callers share one in-flight respawn via
|
|
131
|
+
* {@link respawnPromise}. Internal — only entered via {@link request}.
|
|
132
|
+
*
|
|
133
|
+
* Sequencing pinned (do not reorder without updating the regression
|
|
134
|
+
* test in tests/adapters/pi-mcp-bridge.test.ts):
|
|
135
|
+
* 1. `this.child = null` — drop stale handle
|
|
136
|
+
* 2. `this.buffer = ""` — discard leftover bytes from old child
|
|
137
|
+
* 3. `this.exited = false` — must precede `start()` + `initialize()`,
|
|
138
|
+
* because `request("initialize", …)`
|
|
139
|
+
* inside `initialize()` re-checks this
|
|
140
|
+
* flag and would otherwise re-enter
|
|
141
|
+
* respawn in an infinite loop
|
|
142
|
+
* 4. `this.initialized = false`
|
|
143
|
+
* 5. `this.start()`
|
|
144
|
+
* 6. `await this.initialize()` — flows through `request()` recursively
|
|
145
|
+
*/
|
|
146
|
+
private respawn;
|
|
147
|
+
shutdown(): void;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Subset of the Pi ExtensionAPI we touch. Typed structurally so we don't
|
|
151
|
+
* pull `@earendil-works/pi-coding-agent` as a build dependency — keeps
|
|
152
|
+
* the bundle size unchanged and matches the existing pi-extension.ts
|
|
153
|
+
* style (which also types `pi` as `any`).
|
|
154
|
+
*/
|
|
155
|
+
export interface PiToolRegistration {
|
|
156
|
+
name: string;
|
|
157
|
+
label: string;
|
|
158
|
+
description: string;
|
|
159
|
+
parameters: unknown;
|
|
160
|
+
renderCall?: (args: unknown, theme: PiRenderTheme, context: PiRenderContext) => unknown;
|
|
161
|
+
renderResult?: (result: MCPCallResult, options: {
|
|
162
|
+
expanded: boolean;
|
|
163
|
+
isPartial: boolean;
|
|
164
|
+
}, theme: PiRenderTheme, context: PiRenderContext) => unknown;
|
|
165
|
+
execute: (toolCallId: string, params: Record<string, unknown>) => Promise<{
|
|
166
|
+
content: Array<{
|
|
167
|
+
type: "text";
|
|
168
|
+
text: string;
|
|
169
|
+
}>;
|
|
170
|
+
details: Record<string, unknown>;
|
|
171
|
+
isError?: boolean;
|
|
172
|
+
}>;
|
|
173
|
+
}
|
|
174
|
+
export interface PiLikeAPI {
|
|
175
|
+
registerTool: (tool: PiToolRegistration) => void;
|
|
176
|
+
/**
|
|
177
|
+
* Pi's rotating file logger (`~/.omp/logs/`). Pi runs a raw-mode TUI that
|
|
178
|
+
* owns the terminal, so an in-process extension MUST NOT write to
|
|
179
|
+
* process.stdout/stderr — any console write is rendered straight into the
|
|
180
|
+
* editor input box and blocks typing (#868, confirmed against
|
|
181
|
+
* oh-my-pi tui/terminal.ts raw-mode + docs/skills/authoring-extensions.md:
|
|
182
|
+
* "nothing is written to the console, which would corrupt the TUI"). All
|
|
183
|
+
* bridge diagnostics route here instead. Optional: absent in tests / minimal
|
|
184
|
+
* hosts, in which case diagnostics are dropped — we NEVER fall back to the
|
|
185
|
+
* terminal.
|
|
186
|
+
*/
|
|
187
|
+
logger?: {
|
|
188
|
+
debug?: (message: string, context?: Record<string, unknown>) => void;
|
|
189
|
+
info?: (message: string, context?: Record<string, unknown>) => void;
|
|
190
|
+
warn?: (message: string, context?: Record<string, unknown>) => void;
|
|
191
|
+
error?: (message: string, context?: Record<string, unknown>) => void;
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
/** TUI-safe diagnostics sink: routes to Pi's file logger, never the terminal. */
|
|
195
|
+
export type BridgeDiag = (line: string, level?: "warn" | "debug") => void;
|
|
196
|
+
/**
|
|
197
|
+
* Build a {@link BridgeDiag} bound to a Pi host's file logger (#868). Writing to
|
|
198
|
+
* process.stderr from inside Pi's raw-mode TUI corrupts the editor, so every
|
|
199
|
+
* bridge diagnostic — the forwarded MCP child stderr included — goes to
|
|
200
|
+
* `pi.logger` instead. When no logger is reachable (tests, non-Pi hosts) the
|
|
201
|
+
* line is dropped; we never touch the terminal as a fallback.
|
|
202
|
+
*/
|
|
203
|
+
export declare function makeBridgeDiag(pi: PiLikeAPI | null | undefined): BridgeDiag;
|
|
204
|
+
/**
|
|
205
|
+
* Split a chunk of forwarded child output into lines without a regex (the repo
|
|
206
|
+
* forbids regex in source). Trailing `\r` is stripped so CRLF traces stay clean
|
|
207
|
+
* in the log; the final partial line (no trailing newline) is preserved.
|
|
208
|
+
*/
|
|
209
|
+
export declare function splitDiagLines(text: string): string[];
|
|
210
|
+
/**
|
|
211
|
+
* #868: is this the FOREGROUND interactive Pi session (vs a subagent / print /
|
|
212
|
+
* RPC session)? Pi passes an ExtensionContext as the 2nd arg to
|
|
213
|
+
* `before_agent_start`; `ctx.hasUI === true` only for the interactive session
|
|
214
|
+
* with a real UI attached (refs oh-my-pi runner.ts:330-331), while subagents
|
|
215
|
+
* are provably `hasUI: false` (refs executor.ts:2052). Fail-safe: treat anything
|
|
216
|
+
* that is NOT an explicit `hasUI === false` as foreground, so an
|
|
217
|
+
* ambiguous/absent ctx keeps the session's bridge ALIVE rather than risking the
|
|
218
|
+
* #868 idle-drop. Mis-classifying an abandoned non-interactive child as
|
|
219
|
+
* foreground only costs one lingering child until parent-death/ session_shutdown
|
|
220
|
+
* reaps it; the opposite error re-drops the user's tools mid-session.
|
|
221
|
+
*/
|
|
222
|
+
export declare function isForegroundSession(ctx: unknown): boolean;
|
|
223
|
+
/**
|
|
224
|
+
* #868: derive the bridge child's spawn env for a session kind. The FOREGROUND
|
|
225
|
+
* interactive session's child must never be idle-reaped — a multi-minute human
|
|
226
|
+
* pause should not drop its ctx_* tools — so we disable the #854 reaper for it
|
|
227
|
+
* via `CONTEXT_MODE_BRIDGE_IDLE_MS=0` (lifecycle.ts honors 0 → reaper not armed).
|
|
228
|
+
* Sub-context / non-interactive children keep the default reaper so abandoned
|
|
229
|
+
* children still can't accumulate (#854). The foreground child is still reaped
|
|
230
|
+
* on actual parent death by the ppid/signal watchdog (#311/#388) — only the
|
|
231
|
+
* idle-time path is disabled. Pure; does not mutate the input env.
|
|
232
|
+
*/
|
|
233
|
+
export declare function foregroundBridgeEnv(baseEnv: NodeJS.ProcessEnv, foreground: boolean): NodeJS.ProcessEnv;
|
|
234
|
+
/** Result of bootstrapping the bridge. */
|
|
235
|
+
export interface BridgeHandle {
|
|
236
|
+
/** Names of tools registered with Pi (for diagnostics / tests). */
|
|
237
|
+
tools: string[];
|
|
238
|
+
/** Idempotent shutdown — terminates the MCP child. */
|
|
239
|
+
shutdown: () => void;
|
|
240
|
+
/** Underlying client, exposed for tests / advanced callers. */
|
|
241
|
+
client: MCPStdioClient;
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Spawn the MCP server and register each of its tools with Pi via
|
|
245
|
+
* `pi.registerTool()`. The same JSON Schema returned by `tools/list` is
|
|
246
|
+
* passed straight through as `parameters` — TypeBox emits JSON-Schema
|
|
247
|
+
* compatible objects, so any Pi runtime that validates JSON Schema
|
|
248
|
+
* accepts this shape (verified against pi 0.73.x).
|
|
249
|
+
*
|
|
250
|
+
* Errors during MCP `tools/call` are translated to a `throw` from the
|
|
251
|
+
* `execute()` callback — Pi's contract is "throw to mark the tool call
|
|
252
|
+
* failed", which lets the LLM see and adapt.
|
|
253
|
+
*/
|
|
254
|
+
export interface BootstrapOptions {
|
|
255
|
+
env?: NodeJS.ProcessEnv;
|
|
256
|
+
/** DI hook for tests: override the runtime resolver entirely. */
|
|
257
|
+
_resolveJsRuntime?: () => string | null;
|
|
258
|
+
/**
|
|
259
|
+
* #868: true for the foreground interactive Pi session → spawn the child with
|
|
260
|
+
* the #854 idle reaper DISABLED so a human pause never drops its tools.
|
|
261
|
+
* Defaults to false (keep the reaper) for any non-foreground / unspecified
|
|
262
|
+
* caller; the pi extension resolves this from `ctx.hasUI` via
|
|
263
|
+
* {@link isForegroundSession}.
|
|
264
|
+
*/
|
|
265
|
+
foreground?: boolean;
|
|
266
|
+
}
|
|
267
|
+
export declare function bootstrapMCPTools(pi: PiLikeAPI, serverScript: string, options?: BootstrapOptions): Promise<BridgeHandle>;
|
|
268
|
+
export {};
|