@ken-jo/agent-connector 0.4.7 → 0.4.8
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/dist/{action-YCU53FNE.js → action-RWPRIZIC.js} +10 -10
- package/dist/{amazon-q-W574ZX35.js → amazon-q-5LJOB5L3.js} +6 -18
- package/dist/amazon-q-5LJOB5L3.js.map +1 -0
- package/dist/{amp-JPBQJJVM.js → amp-PU4LFSY6.js} +16 -48
- package/dist/amp-PU4LFSY6.js.map +1 -0
- package/dist/{antigravity-VK2Y3FGV.js → antigravity-DWW35HZO.js} +6 -5
- package/dist/{antigravity-cli-D4PCCUG2.js → antigravity-cli-VTQ6DNWL.js} +6 -5
- package/dist/{antigravity-cli-D4PCCUG2.js.map → antigravity-cli-VTQ6DNWL.js.map} +1 -1
- package/dist/{chunk-F5RX62T7.js → chunk-7QRUZAUG.js} +2 -2
- package/dist/{chunk-G5CQHVQG.js → chunk-7TVBFRVI.js} +12 -15
- package/dist/chunk-7TVBFRVI.js.map +1 -0
- package/dist/{chunk-CYOAH23F.js → chunk-A2T4Q7RM.js} +18 -18
- package/dist/{chunk-7ECYDK5T.js → chunk-CDVOBKSG.js} +4 -4
- package/dist/{chunk-DT6Y7XBI.js → chunk-CENEXP7K.js} +9 -38
- package/dist/chunk-CENEXP7K.js.map +1 -0
- package/dist/chunk-FBJQGRET.js +38 -0
- package/dist/chunk-FBJQGRET.js.map +1 -0
- package/dist/{chunk-WZA4CSGJ.js → chunk-H53QZQJI.js} +15 -2
- package/dist/chunk-H53QZQJI.js.map +1 -0
- package/dist/{chunk-MDNX7HTN.js → chunk-HOE2MN36.js} +2 -2
- package/dist/{chunk-7L6ITC4T.js → chunk-IEGR4TP3.js} +22 -6
- package/dist/chunk-IEGR4TP3.js.map +1 -0
- package/dist/{chunk-PFDUGDOA.js → chunk-KG6T3YNJ.js} +3 -3
- package/dist/{chunk-YQLQJZ7S.js → chunk-MOW2RKHX.js} +2 -2
- package/dist/{chunk-SDPIT4HW.js → chunk-NYR55UT7.js} +2 -2
- package/dist/{chunk-WFXWJITA.js → chunk-OZ5EXXQV.js} +2 -2
- package/dist/{chunk-I5MLE6S7.js → chunk-TO57WYBB.js} +15 -1
- package/dist/chunk-TO57WYBB.js.map +1 -0
- package/dist/chunk-UM5S7DKK.js +33 -0
- package/dist/chunk-UM5S7DKK.js.map +1 -0
- package/dist/{chunk-6RYPUR6O.js → chunk-VRKTVCYJ.js} +7 -7
- package/dist/{chunk-HAIMYUEY.js → chunk-WI6YSXOC.js} +3 -3
- package/dist/{chunk-2F5QH3D4.js → chunk-XQUUNAGC.js} +36 -36
- package/dist/{chunk-TZQBASI7.js → chunk-YS2NYJ6R.js} +13 -49
- package/dist/chunk-YS2NYJ6R.js.map +1 -0
- package/dist/{chunk-SPWFUHHK.js → chunk-YYISBXOM.js} +7 -7
- package/dist/{claude-code-ROSIILTM.js → claude-code-64X6RR2S.js} +15 -38
- package/dist/claude-code-64X6RR2S.js.map +1 -0
- package/dist/cli/sdk.js +4 -4
- package/dist/cli.js +1 -1
- package/dist/{cline-JUTO4V27.js → cline-T7ZDJYZQ.js} +15 -47
- package/dist/cline-T7ZDJYZQ.js.map +1 -0
- package/dist/{codebuff-2QUHL6HO.js → codebuff-PPPY3SJV.js} +9 -40
- package/dist/codebuff-PPPY3SJV.js.map +1 -0
- package/dist/{codex-YBBTIDD4.js → codex-EEVN43C2.js} +26 -62
- package/dist/codex-EEVN43C2.js.map +1 -0
- package/dist/{continue-W4TU4JSB.js → continue-VLLZO4PM.js} +9 -32
- package/dist/continue-VLLZO4PM.js.map +1 -0
- package/dist/{copilot-cli-Y74SOP5G.js → copilot-cli-A7G5WB4N.js} +15 -64
- package/dist/copilot-cli-A7G5WB4N.js.map +1 -0
- package/dist/{crush-GMEWLXK5.js → crush-AH24GDDB.js} +15 -42
- package/dist/crush-AH24GDDB.js.map +1 -0
- package/dist/{cursor-JBS4B3Q4.js → cursor-GJBSMXI6.js} +13 -51
- package/dist/cursor-GJBSMXI6.js.map +1 -0
- package/dist/{detect-2NIXILMZ.js → detect-YDCZNV4W.js} +4 -4
- package/dist/{doctor-QWJBWALA.js → doctor-DGC7P3P7.js} +13 -12
- package/dist/{doctor-QWJBWALA.js.map → doctor-DGC7P3P7.js.map} +1 -1
- package/dist/{droid-TJMTNCQE.js → droid-RBWCFKL3.js} +17 -40
- package/dist/droid-RBWCFKL3.js.map +1 -0
- package/dist/{gemini-cli-RAONGZRG.js → gemini-cli-CFPFEJEA.js} +15 -63
- package/dist/gemini-cli-CFPFEJEA.js.map +1 -0
- package/dist/{goose-G4KKM6YU.js → goose-UBJVQFUE.js} +18 -54
- package/dist/goose-UBJVQFUE.js.map +1 -0
- package/dist/{hermes-PJDTJE6F.js → hermes-6FXGXLNL.js} +14 -52
- package/dist/hermes-6FXGXLNL.js.map +1 -0
- package/dist/{hook-FDGIQPRC.js → hook-CDGSCASQ.js} +10 -10
- package/dist/index.js +2 -2
- package/dist/{install-TLG3QVP3.js → install-2D3UKEME.js} +13 -12
- package/dist/{install-TLG3QVP3.js.map → install-2D3UKEME.js.map} +1 -1
- package/dist/{jetbrains-copilot-DNXSLQE5.js → jetbrains-copilot-K26KMA3U.js} +10 -37
- package/dist/jetbrains-copilot-K26KMA3U.js.map +1 -0
- package/dist/{kilo-FERJ3X46.js → kilo-BKZJ26RM.js} +26 -90
- package/dist/kilo-BKZJ26RM.js.map +1 -0
- package/dist/{kilo-cli-TDCONH5G.js → kilo-cli-6UVWCXQD.js} +17 -48
- package/dist/kilo-cli-6UVWCXQD.js.map +1 -0
- package/dist/{kimi-RIRD4J5J.js → kimi-QALYPSRR.js} +10 -31
- package/dist/kimi-QALYPSRR.js.map +1 -0
- package/dist/{kiro-X7JVLAN7.js → kiro-J5J42I5Z.js} +10 -31
- package/dist/kiro-J5J42I5Z.js.map +1 -0
- package/dist/{leaderboard-MXGENYXN.js → leaderboard-VZQXNWTX.js} +2 -2
- package/dist/{mimo-code-RFLQ727H.js → mimo-code-BEE622P2.js} +22 -87
- package/dist/mimo-code-BEE622P2.js.map +1 -0
- package/dist/{mux-D77HBSBU.js → mux-5HTNKK4K.js} +9 -39
- package/dist/mux-5HTNKK4K.js.map +1 -0
- package/dist/{nemoclaw-LXUTMR56.js → nemoclaw-DNFIZFDF.js} +5 -5
- package/dist/{omp-CO7IXURG.js → omp-I3UTRBNP.js} +16 -48
- package/dist/omp-I3UTRBNP.js.map +1 -0
- package/dist/{openclaw-XWJLEW35.js → openclaw-QE2LMWIF.js} +5 -5
- package/dist/{opencode-QKZ5EIYU.js → opencode-ZFSUYJXI.js} +22 -88
- package/dist/opencode-ZFSUYJXI.js.map +1 -0
- package/dist/{package-IA56LSC3.js → package-BSCCMW4E.js} +8 -8
- package/dist/{pi-YGBXYWY5.js → pi-H2KBBDDJ.js} +4 -4
- package/dist/{qwen-code-E2MSEZK6.js → qwen-code-5LE34FNE.js} +10 -31
- package/dist/qwen-code-5LE34FNE.js.map +1 -0
- package/dist/{roo-code-AGGJ473T.js → roo-code-XH4GCYIS.js} +15 -52
- package/dist/roo-code-XH4GCYIS.js.map +1 -0
- package/dist/runtime/index.js +8 -8
- package/dist/sdk/index.js +3 -3
- package/dist/sdk/test.js +5 -5
- package/dist/{serve-RNUCK5F7.js → serve-MQNGPY2H.js} +10 -10
- package/dist/{status-JOX6RLJU.js → status-MRHVRDFY.js} +8 -7
- package/dist/{status-JOX6RLJU.js.map → status-MRHVRDFY.js.map} +1 -1
- package/dist/{statusline-ZVFI5DRT.js → statusline-IYWA75TR.js} +9 -9
- package/dist/{telemetry-3FN6HDVU.js → telemetry-IONIOMLC.js} +5 -5
- package/dist/{trae-6L226ZDU.js → trae-RVNRSV7X.js} +10 -39
- package/dist/trae-RVNRSV7X.js.map +1 -0
- package/dist/{uninstall-SCKZYB4J.js → uninstall-ESLSVCLE.js} +13 -12
- package/dist/{uninstall-SCKZYB4J.js.map → uninstall-ESLSVCLE.js.map} +1 -1
- package/dist/{upgrade-WU3KZWR4.js → upgrade-VICY5T64.js} +13 -12
- package/dist/{upgrade-WU3KZWR4.js.map → upgrade-VICY5T64.js.map} +1 -1
- package/dist/{usage-G72SF7JG.js → usage-TCUWV2YZ.js} +2 -2
- package/dist/{usage-event-DHSEBO5T.js → usage-event-CBZZP37Q.js} +9 -9
- package/dist/{vscode-copilot-6EOZDLXC.js → vscode-copilot-B2QBBHJW.js} +15 -65
- package/dist/vscode-copilot-B2QBBHJW.js.map +1 -0
- package/dist/{warp-N5YYN5BF.js → warp-5R54ST3N.js} +7 -19
- package/dist/warp-5R54ST3N.js.map +1 -0
- package/dist/{windsurf-4TGSJIVV.js → windsurf-L32UEOLY.js} +6 -18
- package/dist/windsurf-L32UEOLY.js.map +1 -0
- package/dist/{zed-6P2UFWXU.js → zed-FDJHJZKD.js} +11 -21
- package/dist/zed-FDJHJZKD.js.map +1 -0
- package/package.json +1 -1
- package/dist/amazon-q-W574ZX35.js.map +0 -1
- package/dist/amp-JPBQJJVM.js.map +0 -1
- package/dist/chunk-7L6ITC4T.js.map +0 -1
- package/dist/chunk-DT6Y7XBI.js.map +0 -1
- package/dist/chunk-G5CQHVQG.js.map +0 -1
- package/dist/chunk-I5MLE6S7.js.map +0 -1
- package/dist/chunk-TZQBASI7.js.map +0 -1
- package/dist/chunk-WZA4CSGJ.js.map +0 -1
- package/dist/claude-code-ROSIILTM.js.map +0 -1
- package/dist/cline-JUTO4V27.js.map +0 -1
- package/dist/codebuff-2QUHL6HO.js.map +0 -1
- package/dist/codex-YBBTIDD4.js.map +0 -1
- package/dist/continue-W4TU4JSB.js.map +0 -1
- package/dist/copilot-cli-Y74SOP5G.js.map +0 -1
- package/dist/crush-GMEWLXK5.js.map +0 -1
- package/dist/cursor-JBS4B3Q4.js.map +0 -1
- package/dist/droid-TJMTNCQE.js.map +0 -1
- package/dist/gemini-cli-RAONGZRG.js.map +0 -1
- package/dist/goose-G4KKM6YU.js.map +0 -1
- package/dist/hermes-PJDTJE6F.js.map +0 -1
- package/dist/jetbrains-copilot-DNXSLQE5.js.map +0 -1
- package/dist/kilo-FERJ3X46.js.map +0 -1
- package/dist/kilo-cli-TDCONH5G.js.map +0 -1
- package/dist/kimi-RIRD4J5J.js.map +0 -1
- package/dist/kiro-X7JVLAN7.js.map +0 -1
- package/dist/mimo-code-RFLQ727H.js.map +0 -1
- package/dist/mux-D77HBSBU.js.map +0 -1
- package/dist/omp-CO7IXURG.js.map +0 -1
- package/dist/opencode-QKZ5EIYU.js.map +0 -1
- package/dist/qwen-code-E2MSEZK6.js.map +0 -1
- package/dist/roo-code-AGGJ473T.js.map +0 -1
- package/dist/trae-6L226ZDU.js.map +0 -1
- package/dist/vscode-copilot-6EOZDLXC.js.map +0 -1
- package/dist/warp-N5YYN5BF.js.map +0 -1
- package/dist/windsurf-4TGSJIVV.js.map +0 -1
- package/dist/zed-6P2UFWXU.js.map +0 -1
- /package/dist/{action-YCU53FNE.js.map → action-RWPRIZIC.js.map} +0 -0
- /package/dist/{antigravity-VK2Y3FGV.js.map → antigravity-DWW35HZO.js.map} +0 -0
- /package/dist/{chunk-F5RX62T7.js.map → chunk-7QRUZAUG.js.map} +0 -0
- /package/dist/{chunk-CYOAH23F.js.map → chunk-A2T4Q7RM.js.map} +0 -0
- /package/dist/{chunk-7ECYDK5T.js.map → chunk-CDVOBKSG.js.map} +0 -0
- /package/dist/{chunk-MDNX7HTN.js.map → chunk-HOE2MN36.js.map} +0 -0
- /package/dist/{chunk-PFDUGDOA.js.map → chunk-KG6T3YNJ.js.map} +0 -0
- /package/dist/{chunk-YQLQJZ7S.js.map → chunk-MOW2RKHX.js.map} +0 -0
- /package/dist/{chunk-SDPIT4HW.js.map → chunk-NYR55UT7.js.map} +0 -0
- /package/dist/{chunk-WFXWJITA.js.map → chunk-OZ5EXXQV.js.map} +0 -0
- /package/dist/{chunk-6RYPUR6O.js.map → chunk-VRKTVCYJ.js.map} +0 -0
- /package/dist/{chunk-HAIMYUEY.js.map → chunk-WI6YSXOC.js.map} +0 -0
- /package/dist/{chunk-2F5QH3D4.js.map → chunk-XQUUNAGC.js.map} +0 -0
- /package/dist/{chunk-SPWFUHHK.js.map → chunk-YYISBXOM.js.map} +0 -0
- /package/dist/{detect-2NIXILMZ.js.map → detect-YDCZNV4W.js.map} +0 -0
- /package/dist/{hook-FDGIQPRC.js.map → hook-CDGSCASQ.js.map} +0 -0
- /package/dist/{leaderboard-MXGENYXN.js.map → leaderboard-VZQXNWTX.js.map} +0 -0
- /package/dist/{nemoclaw-LXUTMR56.js.map → nemoclaw-DNFIZFDF.js.map} +0 -0
- /package/dist/{openclaw-XWJLEW35.js.map → openclaw-QE2LMWIF.js.map} +0 -0
- /package/dist/{package-IA56LSC3.js.map → package-BSCCMW4E.js.map} +0 -0
- /package/dist/{pi-YGBXYWY5.js.map → pi-H2KBBDDJ.js.map} +0 -0
- /package/dist/{serve-RNUCK5F7.js.map → serve-MQNGPY2H.js.map} +0 -0
- /package/dist/{statusline-ZVFI5DRT.js.map → statusline-IYWA75TR.js.map} +0 -0
- /package/dist/{telemetry-3FN6HDVU.js.map → telemetry-IONIOMLC.js.map} +0 -0
- /package/dist/{usage-G72SF7JG.js.map → usage-TCUWV2YZ.js.map} +0 -0
- /package/dist/{usage-event-DHSEBO5T.js.map → usage-event-CBZZP37Q.js.map} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/adapters/omp/index.ts"],"sourcesContent":["/**\n * adapters/omp — Oh My Pi (OMP) platform adapter for agent-connector.\n *\n * OMP is a ts-plugin host with NATIVE MCP. The two surfaces are split:\n *\n * • MCP (native, real file) — OMP reads a real `mcp.json`:\n * user scope → <agentDir>/mcp.json (agentDir = ~/.omp/agent)\n * project scope → <projectDir>/.omp/mcp.json\n * JSON, root key \"mcpServers\", stdio entry { command, args, env } — the\n * portable field names. Verified against can1357/oh-my-pi\n * (packages/utils/src/dirs.ts getMCPConfigPath + docs/mcp-config.md). OMP\n * documents no native ${env:VAR} token, so env refs resolve to literals at\n * install time (resolveEnvRefsDeep).\n *\n * • Hooks (ts-plugin, in-process) — OMP loads EXTENSION PACKAGES. Its plugin\n * loader reads a package whose package.json carries an `omp` (or `pi`)\n * manifest field; the manifest's `extensions` array points at the plugin\n * module, whose DEFAULT export is a HookFactory `(pi) => void` that calls\n * `pi.on(event, handler)` (upstream loader.ts:75\n * `pluginPkg.omp || pluginPkg.pi`; hook factory types.ts:809). context-mode\n * proved this by dropping an extension under\n * `<agentDir>/extensions/<name>/{package.json,index.js}` whose index.js\n * default-exports the OMP plugin factory (src/setup.ts applyPlatformInstall\n * \"omp\"; src/adapters/omp/plugin.ts).\n *\n * Why we SYNTHESIZE instead of importing context-mode's plugin:\n * context-mode could load its own plugin module in-process because the handler\n * code shipped with the package. agent-connector cannot — the connector's hook\n * handlers are arbitrary developer code we must not import into OMP's runtime\n * (wrong cwd, wrong deps, version skew, the cache-heal bug class). So, exactly\n * like the OpenCode adapter, we generate a tiny self-contained ESM extension\n * that imports NOTHING from agent-connector: each `pi.on(...)` handler shells\n * out to the ONE stable home binary's universal entrypoint\n * (`<homeBin> hook omp <event> --connector <id>`) over child_process, feeds it\n * the OMP-shaped payload as JSON on stdin, and JSON.parses the normalized\n * HookResponse back from stdout. Fail-open: any bridge error → no-op. One\n * entrypoint, every paradigm.\n *\n * Event mapping (only events the connector declares are subscribed):\n * PreToolUse → pi.on(\"tool_call\", …) block via { block:true, reason }\n * (OMP tool_call cannot mutate args → canModifyArgs:false)\n * PostToolUse → pi.on(\"tool_result\", …) observe-only (no output rewrite hook)\n * SessionStart → pi.on(\"session_start\", …) (no context-injection surface)\n * PreCompact → pi.on(\"session_before_compact\", …) observe-only\n *\n * Distinct storage root from Pi: OMP lives under ~/.omp (NOT ~/.pi); the\n * PI_CODING_AGENT_DIR env var (the only OMP runtime dir override — OMP mirrors\n * any .env `OMP_*` keys to `PI_*` before process.env is read) takes precedence.\n */\n\nimport {\n chmodSync,\n existsSync,\n mkdirSync,\n readFileSync,\n rmSync,\n writeFileSync,\n} from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\n\nimport { BaseAdapter } from \"../base.js\";\nimport type {\n Adapter,\n GeneratedPluginFile,\n HookReply,\n InstallContext,\n NormalizedEvent,\n} from \"../spi.js\";\nimport type {\n ChangeRecord,\n DetectedPlatform,\n HealthCheck,\n HookEventName,\n HookParadigm,\n HookResponse,\n PlatformCapabilities,\n PlatformId,\n PostToolUseEvent,\n PreCompactEvent,\n PreToolUseEvent,\n ServerDef,\n SessionStartEvent,\n Transport,\n} from \"../../core/types.js\";\nimport { resolveEnvRefsDeep } from \"../../core/interpolate.js\";\nimport { renderBridgePrelude } from \"../../core/ts-plugin-bridge.js\";\nimport {\n buildWrappedStdio,\n} from \"../../core/spawn.js\";\n\nconst HOST: PlatformId = \"omp\";\nconst MCP_ROOT_KEY = \"mcpServers\";\n\n/**\n * Canonical → OMP event name map. A connector hook event is only subscribed by\n * the generated plugin when it appears here AND is declared by the connector.\n * Names verified against the proven context-mode OMP plugin (pi.on targets).\n */\nconst EVENT_TO_OMP: Partial<Record<HookEventName, string>> = {\n PreToolUse: \"tool_call\",\n PostToolUse: \"tool_result\",\n SessionStart: \"session_start\",\n PreCompact: \"session_before_compact\",\n};\n\n/** Raw payload the generated plugin posts to the universal hook entrypoint. */\ninterface OmpBridgePayload {\n toolName?: string;\n toolInput?: Record<string, unknown>;\n toolOutput?: string;\n isError?: boolean;\n sessionId?: string;\n projectDir?: string;\n}\n\n/** Native MCP server entry shapes OMP accepts under \"mcpServers\". */\ninterface OmpStdioServer {\n command: string;\n args?: string[];\n env?: Record<string, string>;\n}\ninterface OmpRemoteServer {\n type: \"http\" | \"sse\";\n url: string;\n headers?: Record<string, string>;\n}\n\nexport class OMPAdapter extends BaseAdapter implements Adapter {\n readonly id: PlatformId = HOST;\n readonly name = \"Oh My Pi (OMP)\";\n readonly paradigm: HookParadigm = \"ts-plugin\";\n\n readonly capabilities: PlatformCapabilities = {\n // Memory surface: AGENTS.md-first managed block via the BaseAdapter default\n // (memoryTargets: project <projectDir>/AGENTS.md; user scope where documented).\n supportsMemory: true,\n preToolUse: true,\n postToolUse: true,\n // session_before_compact is wired as an observe-only PreCompact surface.\n preCompact: true,\n sessionStart: true,\n sessionEnd: false,\n userPromptSubmit: false,\n stop: false,\n notification: false,\n // Newer events: OMP's agent_start/agent_end/turn_* hooks are the MAIN loop\n // (no subagent lifecycle events), there is no permission/approval surface,\n // and tool failure is merged into tool_result (isError) rather than a\n // dedicated event. None are wired, so permissionRequest /\n // postToolUseFailure / subagentStart / subagentStop stay unset — the\n // generated bridge never references them and install reports them as\n // \"unsupported here\".\n // OMP tool_call gates via { block, reason } only — it does not hand the\n // handler a mutable args object, so input rewrite is unsupported.\n canModifyArgs: false,\n // No tool_result output-rewrite surface upstream.\n canModifyOutput: false,\n // No session_start context-injection surface upstream.\n canInjectSessionContext: false,\n // OMP registers stdio and remote (streamable http + sse) MCP servers.\n transports: [\"stdio\", \"sse\", \"http\"],\n // Action surface: each declared action becomes a user-invokable slash\n // command registered INSIDE the generated plugin module (pi.registerCommand),\n // shelling out to the home-bin `action` verb. supportsActions → the\n // installActions/uninstallActions overrides below.\n supportsActions: true,\n // Native passthrough hooks: OMP's main-loop lifecycle events —\n // agent_start, agent_end, turn_start, turn_end — have NO canonical\n // HookEventName analog (verified in oh-my-pi shared-events.ts). A connector\n // reaches them by declaring platforms[\"omp\"].nativeHooks; the generated\n // plugin registers + bridges each declared native event verbatim\n // (buildPluginSource native loop), and the home-bin runtime dispatches it\n // host-generically via runNativeHook.\n supportsNativeHooks: true,\n };\n\n // ── Native paths ───────────────────────────────────────────────────────\n\n /**\n * Resolve the OMP agent dir, honoring the PI_CODING_AGENT_DIR override (the\n * only OMP runtime dir env), else ~/.omp/agent. This is the user-scope root.\n */\n private agentDir(): string {\n const override = process.env.PI_CODING_AGENT_DIR;\n return override && override !== \"\"\n ? override\n : join(homedir(), \".omp\", \"agent\");\n }\n\n getConfigDir(ctx: InstallContext): string {\n return ctx.scope === \"project\"\n ? join(ctx.projectDir, \".omp\")\n : this.agentDir();\n }\n\n /** Native MCP file: <agentDir>/mcp.json (user) or <projectDir>/.omp/mcp.json. */\n getServerConfigPath(ctx: InstallContext): string {\n return join(this.getConfigDir(ctx), \"mcp.json\");\n }\n\n /**\n * For this ts-plugin host the \"hook config path\" is the generated extension\n * entrypoint module (index.js). OMP loads the extension package by reading its\n * package.json manifest, so the package.json is written alongside (see\n * synthesizePlugin); this returns the entry module the manifest points at.\n */\n getHookConfigPath(ctx: InstallContext): string {\n return join(this.extensionDir(ctx), \"index.js\");\n }\n\n /** Extension package directory OMP loads the plugin from, per scope. */\n private extensionDir(ctx: InstallContext): string {\n const base =\n ctx.scope === \"project\"\n ? join(ctx.projectDir, \".omp\")\n : this.agentDir();\n return join(base, \"extensions\", ctx.connector.id);\n }\n\n // ── Detection ──────────────────────────────────────────────────────────\n\n detectInstalled(projectDir: string): DetectedPlatform {\n const userAgentDir = this.agentDir();\n const userConfig = join(userAgentDir, \"mcp.json\");\n const projectConfig = join(projectDir, \".omp\", \"mcp.json\");\n\n const userInstalled = existsSync(userAgentDir) || existsSync(userConfig);\n const projInstalled =\n existsSync(join(projectDir, \".omp\")) || existsSync(projectConfig);\n const installed = userInstalled || projInstalled;\n\n // Report the marker that actually matched.\n const scope = projInstalled && !userInstalled ? \"project\" : \"user\";\n const configPath = scope === \"project\" ? projectConfig : userConfig;\n\n return {\n id: this.id,\n name: this.name,\n installed,\n paradigm: this.paradigm,\n capabilities: this.capabilities,\n configPath,\n scope,\n reason: installed\n ? scope === \"project\"\n ? `found project OMP dir at ${join(projectDir, \".omp\")}`\n : `found OMP agent dir at ${userAgentDir}`\n : `no OMP agent dir at ${userAgentDir}`,\n confidence: installed ? \"high\" : \"low\",\n };\n }\n\n // ── MCP server install / uninstall (native mcp.json) ────────────────────\n\n installServer(ctx: InstallContext): ChangeRecord[] {\n const server = this.effectiveServer(ctx);\n const serverPath = this.getServerConfigPath(ctx);\n\n if (!server) {\n return [\n {\n platform: this.id,\n action: \"skip\",\n path: serverPath,\n detail: ctx.connector.server\n ? \"server registration disabled for omp\"\n : \"connector declares no MCP server\",\n },\n ];\n }\n\n const changes: ChangeRecord[] = [];\n // Honesty: OMP documents stdio/sse/http. A connector declaring another\n // transport (e.g. the non-spec \"ws\") is still rendered best-effort — the\n // remote branch coerces it to type:\"http\" (OMP rejects an unknown `type`) —\n // but the mismatch is REPORTED, never silently downgraded (same \"degradation\n // is never silent\" posture as the hook warn-skips).\n if (!this.capabilities.transports.includes(server.transport)) {\n changes.push({\n platform: this.id,\n action: \"warn\",\n path: serverPath,\n detail: `transport \"${server.transport}\" is not an OMP MCP transport (stdio/sse/http); registered best-effort as type:\"http\"`,\n });\n }\n\n const entry = this.renderServerEntry(ctx, server);\n changes.push(\n this.upsertServerInJson(\n serverPath,\n MCP_ROOT_KEY,\n ctx.connector.id,\n entry,\n ctx.dryRun,\n ),\n );\n return changes;\n }\n\n uninstallServer(ctx: InstallContext): ChangeRecord[] {\n const serverPath = this.getServerConfigPath(ctx);\n return [\n this.removeServerFromJson(\n serverPath,\n MCP_ROOT_KEY,\n ctx.connector.id,\n ctx.dryRun,\n ),\n ];\n }\n\n /** Resolve the per-platform server override into an effective ServerDef. */\n private effectiveServer(ctx: InstallContext): ServerDef | undefined {\n const override = ctx.connector.platforms[HOST]?.server;\n if (override === false) return undefined;\n const base = ctx.connector.server;\n if (!base) return undefined;\n return override && typeof override === \"object\"\n ? { ...base, ...override }\n : base;\n }\n\n /**\n * Render a normalized ServerDef into OMP's native \"mcpServers\" entry.\n *\n * stdio → { command, args, env } (portable field names; `type` omitted —\n * OMP defaults an entry with no `type` to stdio)\n * remote → { type: \"http\"|\"sse\", url, headers? } (`type` is REQUIRED for a\n * URL server — without it OMP would mis-parse the entry as stdio)\n *\n * Telemetry wrapping routes the real command through\n * `<homeBin> serve --connector <id> -- <command> <args...>`. OMP has no native\n * env interpolation token, so every ${env:VAR} ref resolves to a literal.\n */\n private renderServerEntry(\n ctx: InstallContext,\n server: ServerDef,\n ): OmpStdioServer | OmpRemoteServer {\n const transport: Transport = server.transport;\n\n if (transport === \"stdio\") {\n let command = server.command ?? \"\";\n let args = [...(server.args ?? [])];\n\n ({ command, args } = buildWrappedStdio(ctx, server, this.id, command, args));\n\n const entry: OmpStdioServer = {\n command: resolveEnvRefsDeep(command),\n };\n const resolvedArgs = resolveEnvRefsDeep(args).filter((s) => s !== \"\");\n if (resolvedArgs.length > 0) entry.args = resolvedArgs;\n const env = this.renderEnv(server.env);\n if (env) entry.env = env;\n return entry;\n }\n\n // remote (http / sse) — OMP registers a URL with an explicit `type`\n // discriminator. OMP defaults a type-less entry to stdio (docs/mcp-config.md\n // \"stdio is the default when type is omitted\"), so a URL server MUST carry\n // its type or it is mis-parsed as a command.\n const entry: OmpRemoteServer = {\n type: server.transport === \"sse\" ? \"sse\" : \"http\",\n url: resolveEnvRefsDeep(server.url ?? \"\"),\n };\n const headers = this.renderEnv(server.headers);\n if (headers) entry.headers = headers;\n return entry;\n }\n\n /** Resolve every ${env:VAR} ref to a literal (OMP has no native token). */\n private renderEnv(\n env: Record<string, string> | undefined,\n ): Record<string, string> | undefined {\n if (!env || Object.keys(env).length === 0) return undefined;\n return resolveEnvRefsDeep({ ...env });\n }\n\n // ── Hook install / uninstall (ts-plugin extension package) ──────────────\n\n installHooks(ctx: InstallContext): ChangeRecord[] {\n const entryPath = this.getHookConfigPath(ctx);\n\n // Native passthrough events are a sibling, omp-scoped declaration: `hooks:\n // false` disables only the CANONICAL events, and the generated native loop\n // reads platforms.omp.nativeHooks directly (independent of hookEvents). So\n // whenever native events exist the plugin must still be synthesized.\n const nativeEvents = Object.keys(\n ctx.connector.platforms[HOST]?.nativeHooks ?? {},\n );\n\n if (ctx.connector.platforms[HOST]?.hooks === false && nativeEvents.length === 0) {\n return [\n {\n platform: this.id,\n action: \"skip\",\n path: entryPath,\n detail: \"hooks disabled for omp\",\n },\n ];\n }\n // Empty-events gate: the plugin module is SHARED with the action surface, so\n // a connector with actions-but-no-hooks still needs it written — but that is\n // installActions' job. installHooks itself only writes when there ARE hooks,\n // so its skip detail stays honest about why (no hooks) while admitting the\n // plugin may still exist for actions. Native events are a third reason to\n // write it, so they suppress the skip too.\n if (ctx.connector.hookEvents.length === 0 && nativeEvents.length === 0) {\n return [\n {\n platform: this.id,\n action: \"skip\",\n path: entryPath,\n detail:\n this.actionTriggers(ctx).length > 0\n ? \"no hooks (plugin written for actions)\"\n : \"connector declares no hooks\",\n },\n ];\n }\n\n return this.ensurePlugin(ctx, (file) =>\n file.path.endsWith(\"package.json\")\n ? \"omp extension manifest\"\n : `omp plugin module (${this.hookDetail(ctx)})`,\n );\n }\n\n // ── Action install / uninstall (slash commands in the shared plugin) ────\n\n /**\n * Each declared action becomes a `pi.registerCommand(...)` inside the SAME\n * generated extension module (see buildPluginSource). So installActions just\n * ensures that shared module is on disk: when hooks already wrote the identical\n * bytes the content-compare yields \"skip\" (no double material write), and an\n * actions-only connector gets the plugin written here. Honors\n * platforms.omp.actions === false and the empty-actions skip.\n */\n override installActions(ctx: InstallContext): ChangeRecord[] {\n const entryPath = this.getHookConfigPath(ctx);\n if (ctx.connector.platforms[HOST]?.actions === false) {\n return [\n { platform: this.id, action: \"skip\", path: entryPath, detail: \"actions disabled for omp\" },\n ];\n }\n if (this.actionTriggers(ctx).length === 0) {\n return [\n { platform: this.id, action: \"skip\", path: entryPath, detail: \"connector declares no actions\" },\n ];\n }\n return this.ensurePlugin(ctx, (file) =>\n file.path.endsWith(\"package.json\")\n ? \"omp extension manifest\"\n : \"omp plugin module (action commands)\",\n );\n }\n\n /**\n * Actions live INSIDE the shared plugin module, which uninstallHooks removes\n * unconditionally (it runs last in the teardown pass). Removing it here too\n * would race uninstallHooks, so this is a single informational skip.\n */\n override uninstallActions(ctx: InstallContext): ChangeRecord[] {\n return [\n {\n platform: this.id,\n action: \"skip\",\n path: this.getHookConfigPath(ctx),\n detail: \"action commands are embedded in the plugin module; removed by uninstallHooks\",\n },\n ];\n }\n\n /**\n * Synthesize + content-compare-write the extension package (package.json +\n * index.js). Shared by installHooks and installActions: the generator is a pure\n * function of ctx, so whichever surface runs second sees byte-identical files\n * and reports \"skip\" — no double material write. `detailFor` flavors the\n * ChangeRecord detail per surface.\n */\n private ensurePlugin(\n ctx: InstallContext,\n detailFor: (file: GeneratedPluginFile) => string,\n ): ChangeRecord[] {\n const files = this.synthesizePlugin(ctx);\n const changes: ChangeRecord[] = [];\n\n for (const file of files) {\n const before = existsSync(file.path)\n ? this.safeRead(file.path)\n : undefined;\n let action: ChangeRecord[\"action\"];\n if (before === undefined) action = \"create\";\n else if (before === file.contents) action = \"skip\";\n else action = \"update\";\n\n if (action !== \"skip\" && !ctx.dryRun) {\n ensureDir(dirname(file.path));\n writeFileSync(file.path, file.contents, \"utf8\");\n chmodSync(file.path, file.executable ? 0o755 : 0o644);\n }\n\n changes.push({\n platform: this.id,\n action,\n path: file.path,\n detail: detailFor(file),\n });\n }\n\n return changes;\n }\n\n /**\n * Human-facing summary of which declared events the synthesized module ACTUALLY\n * wires. Only events present in EVENT_TO_OMP are mapped/wired; any declared\n * event with no OMP mapping (e.g. UserPromptSubmit) is reported separately as\n * \"unsupported here\" so the detail never overstates coverage.\n */\n private hookDetail(ctx: InstallContext): string {\n // `hooks: false` suppresses the canonical handlers (buildPluginSource), so\n // the detail must not claim them. Native events are still reported below.\n const canonicalOff = ctx.connector.platforms[HOST]?.hooks === false;\n const declared = canonicalOff ? [] : ctx.connector.hookEvents;\n const mapped = declared.filter((e) => EVENT_TO_OMP[e] !== undefined);\n const unsupported = declared.filter((e) => EVENT_TO_OMP[e] === undefined);\n const nativeEvents = Object.keys(\n ctx.connector.platforms[HOST]?.nativeHooks ?? {},\n );\n const parts = [mapped.join(\",\")].filter((p) => p !== \"\");\n if (nativeEvents.length > 0) {\n parts.push(`native: ${nativeEvents.join(\",\")}`);\n }\n const base = parts.join(\"; \");\n return unsupported.length > 0\n ? `${base}; unsupported here: ${unsupported.join(\",\")}`\n : base;\n }\n\n uninstallHooks(ctx: InstallContext): ChangeRecord[] {\n const entryPath = this.getHookConfigPath(ctx);\n const manifestPath = join(this.extensionDir(ctx), \"package.json\");\n const present = [entryPath, manifestPath].filter((p) => existsSync(p));\n\n if (present.length === 0) {\n return [\n {\n platform: this.id,\n action: \"skip\",\n path: entryPath,\n detail: \"no omp extension present\",\n },\n ];\n }\n\n const changes: ChangeRecord[] = [];\n for (const p of present) {\n if (!ctx.dryRun) rmSync(p, { force: true });\n changes.push({\n platform: this.id,\n action: \"remove\",\n path: p,\n detail: p.endsWith(\"package.json\")\n ? \"omp extension manifest\"\n : \"omp plugin module\",\n });\n }\n return changes;\n }\n\n // ── ts-plugin synthesis ────────────────────────────────────────────────\n\n /**\n * Build the OMP extension package: TWO files.\n *\n * 1. package.json — the manifest OMP's loader reads. It carries the `omp`\n * field (`pluginPkg.omp || pluginPkg.pi`) whose `extensions` array points\n * at the entry module, plus `type:\"module\"` and `main:\"index.js\"`.\n * 2. index.js — a self-contained ESM plugin that imports nothing from\n * agent-connector. Its default export is the OMP HookFactory `(pi)=>void`;\n * each declared event registers a `pi.on(...)` handler that bridges to the\n * home binary via execFileSync (fail-open) and applies the normalized\n * response.\n */\n synthesizePlugin(ctx: InstallContext): GeneratedPluginFile[] {\n const dir = this.extensionDir(ctx);\n return [\n {\n path: join(dir, \"package.json\"),\n contents: this.buildManifest(ctx),\n executable: false,\n },\n {\n path: join(dir, \"index.js\"),\n contents: this.buildPluginSource(ctx),\n executable: false,\n },\n ];\n }\n\n /** The extension package.json manifest OMP's plugin loader reads. */\n private buildManifest(ctx: InstallContext): string {\n const manifest = {\n name: ctx.connector.id,\n version: ctx.connector.version || \"0.0.0\",\n description: `${ctx.connector.displayName} OMP extension (generated by agent-connector)`,\n type: \"module\",\n main: \"index.js\",\n // pluginPkg.omp || pluginPkg.pi → manifest. extensions points at the entry.\n omp: {\n extensions: [\"./index.js\"],\n },\n };\n return `${JSON.stringify(manifest, null, 2)}\\n`;\n }\n\n /** Compose the generated plugin source with plain string concatenation. */\n private buildPluginSource(ctx: InstallContext): string {\n // `platforms.omp.hooks === false` disables only the CANONICAL events (the\n // native loop below reads platforms.omp.nativeHooks directly and is a\n // sibling, unaffected). When canonical hooks are off the module may still be\n // synthesized for native events and/or actions, so the canonical handler set\n // collapses to empty here rather than short-circuiting the whole plugin.\n const canonicalOff = ctx.connector.platforms[HOST]?.hooks === false;\n const events = canonicalOff\n ? []\n : ctx.connector.hookEvents.filter(\n (e): e is HookEventName => EVENT_TO_OMP[e] !== undefined,\n );\n const has = (e: HookEventName) => events.includes(e);\n\n const header = `/**\n * AUTO-GENERATED by agent-connector — DO NOT EDIT.\n *\n * Self-contained Oh My Pi (OMP) plugin extension for connector ${ctx.connector.id}.\n * It imports nothing from agent-connector: every hook invocation shells out to\n * the stable home binary's universal entrypoint and JSON-parses the normalized\n * response. Fail-open: any bridge error degrades to a no-op (never wedges OMP).\n *\n * OMP loads this module via the sibling package.json \"omp\" manifest field; the\n * default export is the HookFactory (pi) => void called once at load time.\n */\nimport { execFileSync, execSync } from \"node:child_process\";\n\n${renderBridgePrelude({\n homeBin: ctx.homeBinPath,\n connectorId: ctx.connector.id,\n hookSlug: \"omp\",\n payloadNoun: \"OMP\",\n failOpenComment: \"Fail-open — never break an OMP tool call / lifecycle event.\",\n})}\n\n// OMP exposes the project dir via PI_PROJECT_DIR (PI_*-prefixed only); fall\n// through to cwd. The plugin process is long-lived, so resolve once at load.\nconst PROJECT_DIR = process.env.PI_PROJECT_DIR || process.cwd();\n\n// Derive a stable session id from OMP's session manager when available\n// (ctx.sessionManager.getSessionFile()), else a wall-clock token. The id is\n// rebound on each session_start so multi-session reuse stays attributed.\nlet SESSION_ID = \"\";\nfunction deriveSessionId(ctx) {\n try {\n const f = ctx && ctx.sessionManager && typeof ctx.sessionManager.getSessionFile === \"function\"\n ? ctx.sessionManager.getSessionFile()\n : \"\";\n if (f && typeof f === \"string\") return f;\n } catch {\n // best effort\n }\n return \"omp-\" + Date.now();\n}\n`;\n\n const handlers: string[] = [];\n\n if (has(\"SessionStart\")) {\n handlers.push(` // SessionStart → rebind the session id and notify the connector.\n pi.on(\"session_start\", (_event, ctx) => {\n SESSION_ID = deriveSessionId(ctx);\n bridge(\"SessionStart\", { sessionId: SESSION_ID, projectDir: PROJECT_DIR });\n return undefined;\n });`);\n }\n\n if (has(\"PreToolUse\")) {\n handlers.push(` // PreToolUse → block via { block, reason }. OMP tool_call cannot mutate\n // args, so \"ask\" degrades to a block (the safe direction); \"modify\" degrades\n // to ALLOW (no-block), matching opencode/claude-code — only deny/ask block.\n pi.on(\"tool_call\", (event) => {\n const payload = {\n toolName: (event && event.toolName) || \"\",\n toolInput: (event && event.input) || {},\n sessionId: SESSION_ID,\n projectDir: PROJECT_DIR,\n };\n const res = bridge(\"PreToolUse\", payload);\n if (!res) return undefined;\n if (res.decision === \"deny\" || res.decision === \"ask\") {\n return { block: true, reason: res.reason || \"Blocked by ${ctx.connector.id}\" };\n }\n return undefined;\n });`);\n }\n\n if (has(\"PostToolUse\")) {\n handlers.push(` // PostToolUse → observe tool results (no output-rewrite surface upstream).\n pi.on(\"tool_result\", (event) => {\n const content = (event && Array.isArray(event.content)) ? event.content : [];\n const toolOutput = content\n .filter((c) => c && c.type === \"text\" && typeof c.text === \"string\")\n .map((c) => c.text)\n .join(\"\\\\n\");\n const payload = {\n toolName: (event && event.toolName) || \"\",\n toolInput: (event && event.input) || {},\n toolOutput,\n isError: !!(event && event.isError),\n sessionId: SESSION_ID,\n projectDir: PROJECT_DIR,\n };\n bridge(\"PostToolUse\", payload);\n return undefined;\n });`);\n }\n\n if (has(\"PreCompact\")) {\n handlers.push(` // PreCompact → notify before OMP compacts the context window.\n pi.on(\"session_before_compact\", () => {\n bridge(\"PreCompact\", { sessionId: SESSION_ID, projectDir: PROJECT_DIR });\n return undefined;\n });`);\n }\n\n // NATIVE passthrough events: OMP's main-loop lifecycle hooks (agent_start,\n // agent_end, turn_start, turn_end) have NO canonical analog, so they are not\n // in EVENT_TO_OMP. Each declared native event registers a pi.on(...) handler\n // that bridges the NATIVE event name verbatim to the home-bin → runNativeHook\n // dispatches it host-generically. Read straight off platforms.omp.nativeHooks\n // (independent of hookEvents), so they install even with hooks:false.\n const nativeEvents = Object.keys(\n ctx.connector.platforms[HOST]?.nativeHooks ?? {},\n );\n for (const ev of nativeEvents) {\n handlers.push(` // nativeHooks passthrough → ${ev}\n pi.on(${JSON.stringify(ev)}, (event) => {\n bridge(${JSON.stringify(ev)}, { sessionId: SESSION_ID, projectDir: PROJECT_DIR, raw: event });\n return undefined;\n });`);\n }\n\n // Action surface: one pi.registerCommand per declared action. The command\n // shells out to the home-bin `action` verb (host token literal \"omp\" — OMP\n // has no fork). Fail-open: a launcher error degrades to a no-op (never wedges\n // OMP). Both id AND description are JSON.stringify'd — descriptions are\n // free-form connector text, so a raw \" / backtick would break the module.\n const actionHandlers: string[] = [];\n for (const action of this.actionTriggers(ctx)) {\n const id = JSON.stringify(action.id);\n const description = JSON.stringify(action.description);\n actionHandlers.push(` // Action /${action.id} → run the home-bin action verb directly.\n pi.registerCommand(${id}, {\n description: ${description},\n handler: async (_args, _ctx) => {\n try {\n const args = [\"action\", \"omp\", ${id}, \"--connector\", CONNECTOR_ID];\n process.platform === \"win32\"\n ? execSync([HOME_BIN, ...args].map((a) => '\"' + a + '\"').join(\" \"), { stdio: \"inherit\" })\n : execFileSync(HOME_BIN, args, { stdio: \"inherit\" });\n } catch { /* fail-open */ }\n return undefined;\n },\n });`);\n }\n\n // When hook events are empty but actions exist, the factory body is just the\n // action registrations (still valid JS — an empty handlers[] yields \"\").\n const factory = `\nexport default function plugin(pi) {\n${[...handlers, ...actionHandlers].join(\"\\n\\n\")}\n}\n`;\n\n return header + factory;\n }\n\n // ── Runtime: parse OUR bridge payload → normalized event ───────────────\n\n /**\n * `raw` is the payload OUR generated plugin posts (NOT a host-native shape):\n * { toolName?, toolInput?, toolOutput?, isError?, sessionId?, projectDir? }\n * so this maps straight through.\n */\n parseEvent(event: HookEventName, raw: unknown): NormalizedEvent {\n const input = (raw ?? {}) as OmpBridgePayload;\n const base = {\n hostPlatform: HOST,\n connectorId: \"\",\n sessionId: typeof input.sessionId === \"string\" ? input.sessionId : \"\",\n raw,\n ...(typeof input.projectDir === \"string\"\n ? { projectDir: input.projectDir }\n : {}),\n } as const;\n\n switch (event) {\n case \"PreToolUse\": {\n const ev: PreToolUseEvent = {\n ...base,\n toolName: input.toolName ?? \"\",\n toolInput: input.toolInput ?? {},\n };\n return ev;\n }\n case \"PostToolUse\": {\n const ev: PostToolUseEvent = {\n ...base,\n toolName: input.toolName ?? \"\",\n toolInput: input.toolInput ?? {},\n ...(typeof input.toolOutput === \"string\"\n ? { toolOutput: input.toolOutput }\n : {}),\n ...(typeof input.isError === \"boolean\"\n ? { isError: input.isError }\n : {}),\n };\n return ev;\n }\n case \"PreCompact\": {\n const ev: PreCompactEvent = { ...base };\n return ev;\n }\n case \"SessionStart\": {\n const ev: SessionStartEvent = { ...base, source: \"startup\" };\n return ev;\n }\n default:\n // Other canonical events are not surfaced by OMP; treat as a\n // session-start-shaped no-op so the dispatcher fails open gracefully.\n return { ...base, source: \"startup\" } satisfies SessionStartEvent;\n }\n }\n\n // ── Runtime: normalized response → reply the generated bridge parses ───\n\n /**\n * Unlike json-stdio hosts (whose reply is the host's NATIVE control payload),\n * OUR generated bridge consumes this stdout directly. So the reply body is the\n * NORMALIZED HookResponse itself — the bridge JSON.parses it and maps decision\n * → OMP's { block, reason } for tool_call (and ignores it otherwise).\n */\n formatReply(_event: HookEventName, response: HookResponse): HookReply {\n return {\n exitCode: 0,\n stdout: JSON.stringify(response ?? { decision: \"allow\" }),\n };\n }\n\n // ── Diagnostics ────────────────────────────────────────────────────────\n\n override getHealthChecks(ctx: InstallContext): readonly HealthCheck[] {\n const serverPath = this.getServerConfigPath(ctx);\n const entryPath = this.getHookConfigPath(ctx);\n const manifestPath = join(this.extensionDir(ctx), \"package.json\");\n const connectorId = ctx.connector.id;\n // Actions are health-equivalent to hooks: both write the SAME extension\n // package, so an actions-only connector must still assert it is present.\n const hasHooks =\n ctx.connector.hookEvents.length > 0 || this.actionTriggers(ctx).length > 0;\n\n return [\n {\n name: `${this.name}: mcp.json present`,\n check: () =>\n existsSync(serverPath)\n ? { status: \"OK\", detail: serverPath }\n : { status: \"FAIL\", detail: `not found: ${serverPath}` },\n },\n {\n name: `${this.name}: ${MCP_ROOT_KEY}.${connectorId} registered`,\n check: () => {\n if (!ctx.connector.server) {\n return { status: \"OK\", detail: \"no MCP server declared\" };\n }\n const cfg = this.readJson<{ [k: string]: Record<string, unknown> }>(\n serverPath,\n );\n const bucket = cfg?.[MCP_ROOT_KEY];\n if (!cfg || !bucket) {\n return {\n status: \"FAIL\",\n detail: `no ${MCP_ROOT_KEY} in ${serverPath}`,\n };\n }\n return connectorId in bucket\n ? { status: \"OK\", detail: `${MCP_ROOT_KEY}.${connectorId} present` }\n : {\n status: \"FAIL\",\n detail: `no ${MCP_ROOT_KEY}.${connectorId} in ${serverPath}`,\n };\n },\n },\n {\n name: `${this.name}: extension package present`,\n check: () => {\n if (!hasHooks) return { status: \"OK\", detail: \"no hooks declared\" };\n if (!existsSync(manifestPath)) {\n return { status: \"FAIL\", detail: `not found: ${manifestPath}` };\n }\n return existsSync(entryPath)\n ? { status: \"OK\", detail: entryPath }\n : { status: \"FAIL\", detail: `not found: ${entryPath}` };\n },\n },\n ];\n }\n\n /** Read a file, returning undefined on any error (idempotency compare). */\n private safeRead(path: string): string | undefined {\n try {\n return readFileSync(path, \"utf8\");\n } catch {\n return undefined;\n }\n }\n}\n\n/** Create a directory (recursive) if it does not already exist. */\nfunction ensureDir(dir: string): void {\n if (!existsSync(dir)) mkdirSync(dir, { recursive: true });\n}\n\nexport const adapter = new OMPAdapter();\nexport default adapter;\n"],"mappings":"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","names":["entry"]}
|
|
@@ -3,11 +3,11 @@ import {
|
|
|
3
3
|
OpenClawAdapter,
|
|
4
4
|
adapter,
|
|
5
5
|
openclaw_default
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-CENEXP7K.js";
|
|
7
7
|
import "./chunk-DBQMX75U.js";
|
|
8
|
-
import "./chunk-
|
|
9
|
-
import "./chunk-
|
|
10
|
-
import "./chunk-
|
|
8
|
+
import "./chunk-KG6T3YNJ.js";
|
|
9
|
+
import "./chunk-IEGR4TP3.js";
|
|
10
|
+
import "./chunk-TO57WYBB.js";
|
|
11
11
|
import "./chunk-N6HH7K6P.js";
|
|
12
12
|
import "./chunk-TRQKHP7D.js";
|
|
13
13
|
export {
|
|
@@ -15,4 +15,4 @@ export {
|
|
|
15
15
|
adapter,
|
|
16
16
|
openclaw_default as default
|
|
17
17
|
};
|
|
18
|
-
//# sourceMappingURL=openclaw-
|
|
18
|
+
//# sourceMappingURL=openclaw-QE2LMWIF.js.map
|
|
@@ -1,15 +1,20 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
renderBridgePrelude
|
|
4
|
+
} from "./chunk-FBJQGRET.js";
|
|
2
5
|
import {
|
|
3
6
|
resolveEnvRefsDeep
|
|
4
7
|
} from "./chunk-DBQMX75U.js";
|
|
5
8
|
import {
|
|
6
9
|
BaseAdapter
|
|
7
|
-
} from "./chunk-
|
|
8
|
-
import
|
|
10
|
+
} from "./chunk-KG6T3YNJ.js";
|
|
11
|
+
import {
|
|
12
|
+
renderOpenCodeSubagentMd,
|
|
13
|
+
renderSkillMd
|
|
14
|
+
} from "./chunk-IEGR4TP3.js";
|
|
9
15
|
import {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
} from "./chunk-I5MLE6S7.js";
|
|
16
|
+
buildWrappedStdio
|
|
17
|
+
} from "./chunk-TO57WYBB.js";
|
|
13
18
|
import "./chunk-N6HH7K6P.js";
|
|
14
19
|
import "./chunk-TRQKHP7D.js";
|
|
15
20
|
|
|
@@ -217,18 +222,7 @@ var OpenCodeAdapter = class extends BaseAdapter {
|
|
|
217
222
|
if (transport === "stdio") {
|
|
218
223
|
let command = server.command ?? "";
|
|
219
224
|
let args = [...server.args ?? []];
|
|
220
|
-
|
|
221
|
-
const wrapped = buildServeWrapperCommand(
|
|
222
|
-
ctx.homeBinPath,
|
|
223
|
-
ctx.connector.id,
|
|
224
|
-
command,
|
|
225
|
-
args,
|
|
226
|
-
ctx.scope,
|
|
227
|
-
this.id
|
|
228
|
-
);
|
|
229
|
-
command = wrapped.command;
|
|
230
|
-
args = wrapped.args;
|
|
231
|
-
}
|
|
225
|
+
({ command, args } = buildWrappedStdio(ctx, server, this.id, command, args));
|
|
232
226
|
const commandArray = resolveEnvRefsDeep([command, ...args]).filter(
|
|
233
227
|
(s) => s !== ""
|
|
234
228
|
);
|
|
@@ -430,7 +424,7 @@ var OpenCodeAdapter = class extends BaseAdapter {
|
|
|
430
424
|
for (const skill of connector.skills) {
|
|
431
425
|
const dir = this.skillDir(ctx, skill.name);
|
|
432
426
|
changes.push(
|
|
433
|
-
this.writeContentFile(join(dir, "SKILL.md"),
|
|
427
|
+
this.writeContentFile(join(dir, "SKILL.md"), renderSkillMd(skill), ctx.dryRun)
|
|
434
428
|
);
|
|
435
429
|
for (const [rel, contents] of Object.entries(skill.resources ?? {})) {
|
|
436
430
|
const target = this.resolveWithin(dir, rel);
|
|
@@ -465,25 +459,6 @@ var OpenCodeAdapter = class extends BaseAdapter {
|
|
|
465
459
|
}
|
|
466
460
|
return changes;
|
|
467
461
|
}
|
|
468
|
-
/**
|
|
469
|
-
* Render a skill's SKILL.md (UNIFORM across platforms): frontmatter
|
|
470
|
-
* (name, description + optional model, allowed-tools, disable-model-invocation)
|
|
471
|
-
* + markdown body. Only the parent dir differs per platform.
|
|
472
|
-
*/
|
|
473
|
-
renderSkill(skill) {
|
|
474
|
-
const frontmatter = {
|
|
475
|
-
name: skill.name,
|
|
476
|
-
description: skill.description
|
|
477
|
-
};
|
|
478
|
-
if (skill.model !== void 0) frontmatter.model = skill.model;
|
|
479
|
-
const allow = skill.tools?.allow;
|
|
480
|
-
if (allow && allow.length > 0) frontmatter["allowed-tools"] = allow.join(", ");
|
|
481
|
-
if (skill.disableModelInvocation !== void 0) {
|
|
482
|
-
frontmatter["disable-model-invocation"] = skill.disableModelInvocation;
|
|
483
|
-
}
|
|
484
|
-
if (skill.extra) Object.assign(frontmatter, skill.extra);
|
|
485
|
-
return this.renderFrontmatterMd(frontmatter, skill.body);
|
|
486
|
-
}
|
|
487
462
|
// ── Subagents ───────────────────────────────────────────────────────────────
|
|
488
463
|
installSubagents(ctx) {
|
|
489
464
|
const { connector } = ctx;
|
|
@@ -496,7 +471,7 @@ var OpenCodeAdapter = class extends BaseAdapter {
|
|
|
496
471
|
return connector.subagents.map(
|
|
497
472
|
(agent) => this.writeContentFile(
|
|
498
473
|
this.subagentPath(ctx, agent.name),
|
|
499
|
-
|
|
474
|
+
renderOpenCodeSubagentMd(agent),
|
|
500
475
|
ctx.dryRun
|
|
501
476
|
)
|
|
502
477
|
);
|
|
@@ -510,25 +485,6 @@ var OpenCodeAdapter = class extends BaseAdapter {
|
|
|
510
485
|
(agent) => this.removeContentFile(this.subagentPath(ctx, agent.name), ctx.dryRun)
|
|
511
486
|
);
|
|
512
487
|
}
|
|
513
|
-
/**
|
|
514
|
-
* Render a subagent to md+frontmatter. OpenCode's shape is
|
|
515
|
-
* (description, mode:"subagent", model, permission) with the system prompt as
|
|
516
|
-
* the body. `name` is NOT a frontmatter field — it comes from the filename.
|
|
517
|
-
* `permission` is derived from the coarse `readonly` knob: a readonly agent
|
|
518
|
-
* gets a per-tool deny map (edit/bash) so it cannot mutate the workspace.
|
|
519
|
-
*/
|
|
520
|
-
renderSubagent(agent) {
|
|
521
|
-
const frontmatter = {
|
|
522
|
-
description: agent.description,
|
|
523
|
-
mode: "subagent"
|
|
524
|
-
};
|
|
525
|
-
if (agent.model !== void 0) frontmatter.model = agent.model;
|
|
526
|
-
if (agent.readonly === true) {
|
|
527
|
-
frontmatter.permission = { edit: "deny", bash: "deny" };
|
|
528
|
-
}
|
|
529
|
-
if (agent.extra) Object.assign(frontmatter, agent.extra);
|
|
530
|
-
return this.renderFrontmatterMd(frontmatter, agent.prompt);
|
|
531
|
-
}
|
|
532
488
|
// ── ts-plugin synthesis ────────────────────────────────────────────────
|
|
533
489
|
/**
|
|
534
490
|
* Build ONE self-contained ESM bridge module for OpenCode.
|
|
@@ -548,8 +504,6 @@ var OpenCodeAdapter = class extends BaseAdapter {
|
|
|
548
504
|
}
|
|
549
505
|
/** Compose the generated plugin source with plain string concatenation. */
|
|
550
506
|
buildPluginSource(ctx) {
|
|
551
|
-
const homeBin = JSON.stringify(ctx.homeBinPath);
|
|
552
|
-
const connectorId = JSON.stringify(ctx.connector.id);
|
|
553
507
|
const canonicalDisabled = ctx.connector.platforms[HOST]?.hooks === false;
|
|
554
508
|
const events = canonicalDisabled ? [] : ctx.connector.hookEvents.filter(
|
|
555
509
|
(e) => EVENT_TO_OPENCODE[e] !== void 0
|
|
@@ -565,34 +519,14 @@ var OpenCodeAdapter = class extends BaseAdapter {
|
|
|
565
519
|
*/
|
|
566
520
|
import { execFileSync, execSync } from "node:child_process";
|
|
567
521
|
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
*/
|
|
577
|
-
function bridge(event, payload) {
|
|
578
|
-
try {
|
|
579
|
-
// On Windows HOME_BIN is the agent-connector.cmd launcher: Node cannot
|
|
580
|
-
// execFile a batch file, and shell+args is deprecated (DEP0190), so run one
|
|
581
|
-
// quoted command line via a shell. POSIX keeps the direct execFile (no shell).
|
|
582
|
-
const args = ["hook", "opencode", event, "--connector", CONNECTOR_ID];
|
|
583
|
-
const opts = { input: JSON.stringify(payload), encoding: "utf8" };
|
|
584
|
-
const stdout =
|
|
585
|
-
process.platform === "win32"
|
|
586
|
-
? execSync([HOME_BIN, ...args].map((a) => '"' + a + '"').join(" "), opts)
|
|
587
|
-
: execFileSync(HOME_BIN, args, opts);
|
|
588
|
-
const text = (stdout || "").trim();
|
|
589
|
-
if (text === "") return { decision: "allow" };
|
|
590
|
-
return JSON.parse(text);
|
|
591
|
-
} catch {
|
|
592
|
-
// Fail-open \u2014 never wedge a tool call on a bridge error.
|
|
593
|
-
return null;
|
|
594
|
-
}
|
|
595
|
-
}
|
|
522
|
+
${renderBridgePrelude({
|
|
523
|
+
homeBin: ctx.homeBinPath,
|
|
524
|
+
connectorId: ctx.connector.id,
|
|
525
|
+
hookSlug: "opencode",
|
|
526
|
+
payloadNoun: "OpenCode",
|
|
527
|
+
eventDoc: " (PreToolUse|PostToolUse|SessionStart)",
|
|
528
|
+
failOpenComment: "Fail-open \u2014 never wedge a tool call on a bridge error."
|
|
529
|
+
})}
|
|
596
530
|
`;
|
|
597
531
|
const handlers = [];
|
|
598
532
|
if (has("PreToolUse")) {
|
|
@@ -837,4 +771,4 @@ export {
|
|
|
837
771
|
adapter,
|
|
838
772
|
opencode_default as default
|
|
839
773
|
};
|
|
840
|
-
//# sourceMappingURL=opencode-
|
|
774
|
+
//# sourceMappingURL=opencode-ZFSUYJXI.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/adapters/opencode/index.ts"],"sourcesContent":["/**\n * adapters/opencode — OpenCode (SST) platform adapter for agent-connector.\n *\n * OpenCode is the reference **ts-plugin** host: it has no JSON hook table.\n * Instead it auto-loads JS/TS modules from a plugin directory; each module\n * default-exports an async factory that returns an object keyed by OpenCode\n * event names (\"tool.execute.before\", \"tool.execute.after\", …). The factory\n * runs in-process inside OpenCode, mutates the args/output objects it is handed,\n * and throws to block a tool call.\n *\n * The novel part — why this PROVES the ts-plugin paradigm:\n * context-mode could load ITS OWN plugin module in-process because the handler\n * code shipped with the package. agent-connector cannot: the connector's hook\n * handlers are arbitrary developer code we must not import into OpenCode's\n * runtime (wrong cwd, wrong deps, version skew, the cache-heal bug class).\n * So instead of importing handlers, we synthesize a tiny, fully self-contained\n * bridge module that shells out to the ONE stable home binary\n * (`<homeBin> hook opencode <event> --connector <id>`) over child_process,\n * feeds it the OpenCode payload as JSON on stdin, and JSON.parses the\n * normalized HookResponse back from stdout. The same universal json-stdio\n * dispatcher every other host uses (runtime/hook-entrypoint) thus serves the\n * ts-plugin host too — one entrypoint, every paradigm.\n *\n * MCP registration:\n * - config file: opencode.json\n * user scope → ~/.config/opencode/opencode.json\n * project scope → <projectDir>/opencode.json\n * - root key: \"mcp\" (NOT \"mcpServers\").\n * - stdio server → { type: \"local\", command: [exe, ...args], environment }\n * (command is an ARRAY, env key is \"environment\").\n * - remote server → { type: \"remote\", url }.\n * OpenCode documents no native ${env:VAR} interpolation token, so env/url refs\n * are resolved to literals at install time (resolveEnvRefsDeep).\n *\n * Hooks (ts-plugin):\n * - synthesizePlugin(ctx) builds one self-contained ESM bridge module.\n * - installHooks(ctx) writes it into the OpenCode plugin dir\n * user scope → ~/.config/opencode/plugin/<id>.js\n * project scope → <projectDir>/.opencode/plugin/<id>.js\n * OpenCode auto-loads every file in the plugin dir, so writing the file is\n * sufficient — we do NOT also edit the opencode.json \"plugin\" array.\n *\n * Event mapping (only the events the connector declares are emitted):\n * PreToolUse → \"tool.execute.before\" (can mutate output.args; throw to deny)\n * PostToolUse → \"tool.execute.after\" (can mutate output.output)\n * SessionStart → \"experimental.chat.system.transform\" (no real SessionStart\n * hook upstream — #14808/#5409; this is the verified surrogate context-mode\n * uses; we inject additionalContext into output.system).\n * PermissionRequest → \"permission.ask\" (decision-capable gate; the handler\n * MUTATES output.status (\"ask\"|\"deny\"|\"allow\") rather than returning — like\n * tool.execute.before mutates output.args. Verified against\n * anomalyco/opencode packages/plugin/src/index.ts).\n *\n * Native passthrough hooks (supportsNativeHooks):\n * - Host-specific OpenCode plugin events with no normalized HookEventName\n * (chat.message, session.idle, permission.replied, command.execute.before,\n * shell.env, …) are reachable via platforms[\"opencode\"].nativeHooks. The\n * generated plugin emits a fire-and-forget bridge registration for each; the\n * home-bin's runNativeHook dispatches them host-generically.\n *\n * Capability degradations (documented, never thrown):\n * - For tool.execute.before OpenCode has no \"ask\" gate. A decision of \"ask\"\n * degrades to a block (throw with the reason) — the safe direction.\n * (permission.ask DOES have a real \"ask\" status, so PermissionRequest \"ask\"\n * is honored verbatim there.)\n */\n\nimport {\n chmodSync,\n existsSync,\n mkdirSync,\n readFileSync,\n rmSync,\n writeFileSync,\n} from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\n\nimport { BaseAdapter } from \"../base.js\";\nimport type {\n Adapter,\n GeneratedPluginFile,\n HookReply,\n InstallContext,\n MemoryTarget,\n NormalizedEvent,\n} from \"../spi.js\";\nimport type {\n ChangeRecord,\n CommandDef,\n DetectedPlatform,\n HealthCheck,\n HookEventName,\n HookParadigm,\n HookResponse,\n PermissionRequestEvent,\n PlatformCapabilities,\n PlatformId,\n PostToolUseEvent,\n PreToolUseEvent,\n ServerDef,\n SessionStartEvent,\n Transport,\n} from \"../../core/types.js\";\nimport { resolveEnvRefsDeep } from \"../../core/interpolate.js\";\nimport { renderBridgePrelude } from \"../../core/ts-plugin-bridge.js\";\nimport {\n buildWrappedStdio,\n} from \"../../core/spawn.js\";\nimport { renderOpenCodeSubagentMd, renderSkillMd } from \"../claude-code/render.js\";\n\nconst HOST: PlatformId = \"opencode\";\nconst MCP_ROOT_KEY = \"mcp\";\n\n/**\n * Canonical → OpenCode event name map. A connector hook event is only emitted\n * by the generated plugin when it appears here AND is declared by the connector.\n */\nconst EVENT_TO_OPENCODE: Partial<Record<HookEventName, string>> = {\n PreToolUse: \"tool.execute.before\",\n PostToolUse: \"tool.execute.after\",\n // OpenCode lacks a real SessionStart hook (#14808 / #5409). The verified\n // surrogate is experimental.chat.system.transform, which receives the system\n // prompt array; we inject additionalContext there.\n // TODO(opencode-upstream): when anomalyco/opencode ships a native\n // session.start / session.created hook (#14808 / #5409), remap SessionStart to\n // it and retire the experimental.chat.system.transform surrogate.\n SessionStart: \"experimental.chat.system.transform\",\n // OpenCode's decision-capable permission gate. The \"permission.ask\" plugin\n // hook MUTATES output.status (\"ask\"|\"deny\"|\"allow\") rather than returning a\n // value (mirrors tool.execute.before mutating output.args); verified against\n // anomalyco/opencode packages/plugin/src/index.ts.\n PermissionRequest: \"permission.ask\",\n};\n\n/** Raw payload the generated plugin posts to the universal hook entrypoint. */\ninterface OpenCodeBridgePayload {\n toolName?: string;\n toolInput?: Record<string, unknown>;\n toolOutput?: string;\n isError?: boolean;\n sessionId?: string;\n projectDir?: string;\n}\n\n/** Native MCP server entry shapes OpenCode accepts under the \"mcp\" key. */\ninterface OpenCodeLocalServer {\n type: \"local\";\n command: string[];\n environment?: Record<string, string>;\n enabled?: boolean;\n}\ninterface OpenCodeRemoteServer {\n type: \"remote\";\n url: string;\n enabled?: boolean;\n}\n\nexport class OpenCodeAdapter extends BaseAdapter implements Adapter {\n readonly id: PlatformId = HOST;\n readonly name = \"OpenCode\";\n readonly paradigm: HookParadigm = \"ts-plugin\";\n\n readonly capabilities: PlatformCapabilities = {\n // Memory surface: AGENTS.md-first managed block. memoryTargets below probes\n // project scope (CLAUDE.md is opencode's fallback ONLY when AGENTS.md is\n // absent — creating AGENTS.md beside it would shadow the user's rules).\n supportsMemory: true,\n preToolUse: true,\n postToolUse: true,\n // OpenCode's compaction hook is experimental and not wired here.\n preCompact: false,\n sessionStart: true,\n sessionEnd: false,\n userPromptSubmit: false,\n stop: false,\n notification: false,\n // Newer events: OpenCode HAS a decision-capable `permission.ask` plugin\n // hook upstream — now wired (PermissionRequest → permission.ask, which\n // mutates output.status). subagents run as child sessions (bus events only\n // — no dedicated lifecycle hook) and tool failure is merged into\n // tool.execute.after / session.error, so postToolUseFailure / subagentStart\n // / subagentStop stay unset — the generated bridge never references them and\n // install reports them as \"unsupported here\".\n permissionRequest: true,\n // tool.execute.before mutates output.args → input rewrite supported.\n canModifyArgs: true,\n // tool.execute.after mutates output.output → output rewrite supported.\n canModifyOutput: true,\n // injected via experimental.chat.system.transform at session start.\n canInjectSessionContext: true,\n transports: [\"stdio\", \"sse\", \"http\"],\n // Content surfaces: OpenCode authors all three natively under <ocDir>.\n supportsCommands: true,\n supportsSkills: true,\n supportsSubagents: true,\n // Native passthrough hooks: OpenCode's host-specific plugin events that have\n // NO normalized HookEventName (chat.message, session.idle, permission.replied,\n // command.execute.before, shell.env, …) are reachable by declaring\n // platforms[\"opencode\"].nativeHooks. The generated plugin emits a bridge\n // registration for each, and the home-bin's runNativeHook dispatches them\n // host-generically (raw payload → handler → verbatim reply).\n supportsNativeHooks: true,\n };\n\n // ── Detection ──────────────────────────────────────────────────────────\n\n detectInstalled(projectDir: string): DetectedPlatform {\n const userConfigDir = join(homedir(), \".config\", \"opencode\");\n const userConfig = join(userConfigDir, \"opencode.json\");\n const projectConfig = join(projectDir, \"opencode.json\");\n\n const userInstalled = existsSync(userConfigDir) || existsSync(userConfig);\n const projInstalled = existsSync(projectConfig);\n const installed = userInstalled || projInstalled;\n\n // Report the marker that actually matched so a project-only install isn't\n // misreported as a (non-existent) user install.\n const scope = projInstalled && !userInstalled ? \"project\" : \"user\";\n const configPath = scope === \"project\" ? projectConfig : userConfig;\n\n return {\n id: this.id,\n name: this.name,\n installed,\n paradigm: this.paradigm,\n capabilities: this.capabilities,\n configPath,\n scope,\n reason: installed\n ? scope === \"project\"\n ? `found project OpenCode config at ${projectConfig}`\n : `found OpenCode config under ${userConfigDir}`\n : `no OpenCode config at ${userConfigDir}`,\n confidence: installed ? \"high\" : \"low\",\n };\n }\n\n // ── Memory surface: AGENTS.md / CLAUDE.md-fallback probe (project) ──────\n // OpenCode reads project AGENTS.md, falling back to CLAUDE.md ONLY when no\n // AGENTS.md exists. If the user relies on that CLAUDE.md fallback, CREATING\n // AGENTS.md beside it would shadow their own rules — so the block goes into\n // the file opencode actually reads today; AGENTS.md is created only when\n // neither exists. User scope (~/.config/opencode/AGENTS.md) stays on the\n // BaseAdapter default.\n protected override memoryTargets(ctx: InstallContext): MemoryTarget[] {\n if (this.memoryOverride(ctx)?.path || ctx.scope !== \"project\") {\n return super.memoryTargets(ctx);\n }\n const agentsMd = join(ctx.projectDir, \"AGENTS.md\");\n if (existsSync(agentsMd)) {\n return [{ path: agentsMd, reason: \"AGENTS.md (opencode's primary project rules file)\" }];\n }\n const claudeMd = join(ctx.projectDir, \"CLAUDE.md\");\n if (existsSync(claudeMd)) {\n return [\n {\n path: claudeMd,\n reason:\n \"CLAUDE.md (opencode's fallback rules file — creating AGENTS.md would shadow it)\",\n },\n ];\n }\n return [{ path: agentsMd, reason: \"AGENTS.md standard (created; no opencode rules file yet)\" }];\n }\n\n // ── Native paths ───────────────────────────────────────────────────────\n\n getConfigDir(ctx: InstallContext): string {\n return ctx.scope === \"project\"\n ? ctx.projectDir\n : join(homedir(), \".config\", \"opencode\");\n }\n\n getServerConfigPath(ctx: InstallContext): string {\n return join(this.getConfigDir(ctx), \"opencode.json\");\n }\n\n /**\n * For ts-plugin hosts the \"hook config path\" is the generated plugin FILE.\n * OpenCode auto-loads every file in the plugin dir; writing this file IS the\n * registration.\n */\n getHookConfigPath(ctx: InstallContext): string {\n return join(this.pluginDir(ctx), this.pluginFileName(ctx));\n }\n\n /** Plugin directory OpenCode auto-loads modules from, per scope. */\n private pluginDir(ctx: InstallContext): string {\n return ctx.scope === \"project\"\n ? join(ctx.projectDir, \".opencode\", \"plugin\")\n : join(homedir(), \".config\", \"opencode\", \"plugin\");\n }\n\n /** Plugin module file name (one per connector, kebab-case id). */\n private pluginFileName(ctx: InstallContext): string {\n return `${ctx.connector.id}.js`;\n }\n\n // ── MCP server install / uninstall ─────────────────────────────────────\n\n installServer(ctx: InstallContext): ChangeRecord[] {\n const server = this.effectiveServer(ctx);\n const serverPath = this.getServerConfigPath(ctx);\n\n if (!server) {\n return [\n {\n platform: this.id,\n action: \"skip\",\n path: serverPath,\n detail: ctx.connector.server\n ? \"server registration disabled for opencode\"\n : \"connector declares no MCP server\",\n },\n ];\n }\n\n const entry = this.renderServerEntry(ctx, server);\n return [\n this.upsertServerInJson(\n serverPath,\n MCP_ROOT_KEY,\n ctx.connector.id,\n entry,\n ctx.dryRun,\n ),\n ];\n }\n\n uninstallServer(ctx: InstallContext): ChangeRecord[] {\n const serverPath = this.getServerConfigPath(ctx);\n return [\n this.removeServerFromJson(\n serverPath,\n MCP_ROOT_KEY,\n ctx.connector.id,\n ctx.dryRun,\n ),\n ];\n }\n\n /** Resolve the per-platform server override into an effective ServerDef. */\n private effectiveServer(ctx: InstallContext): ServerDef | undefined {\n const override = ctx.connector.platforms[HOST]?.server;\n if (override === false) return undefined;\n const base = ctx.connector.server;\n if (!base) return undefined;\n return override && typeof override === \"object\" ? { ...base, ...override } : base;\n }\n\n /**\n * Render a normalized ServerDef into OpenCode's native \"mcp\" entry.\n *\n * stdio → { type: \"local\", command: [exe, ...args], environment }\n * remote → { type: \"remote\", url }\n *\n * OpenCode flattens command+args into a single ARRAY. When telemetry wrapping\n * applies, the wrapper's command+args (which already include the real command\n * tail after `--`) become the head of that array.\n */\n private renderServerEntry(\n ctx: InstallContext,\n server: ServerDef,\n ): OpenCodeLocalServer | OpenCodeRemoteServer {\n const transport: Transport = server.transport;\n\n if (transport === \"stdio\") {\n let command = server.command ?? \"\";\n let args = [...(server.args ?? [])];\n\n // Transparent telemetry wrapping: route the real command through\n // `<homeBin> serve --connector <id> -- <command> <args...>`.\n ({ command, args } = buildWrappedStdio(ctx, server, this.id, command, args));\n\n // OpenCode has no native interpolation token → resolve to literals.\n const commandArray = resolveEnvRefsDeep([command, ...args]).filter(\n (s) => s !== \"\",\n );\n const entry: OpenCodeLocalServer = {\n type: \"local\",\n command: commandArray,\n };\n const environment = this.renderEnv(server.env);\n if (environment) entry.environment = environment;\n if (server.enabled === false) entry.enabled = false;\n return entry;\n }\n\n // sse / http / ws (any remote transport) — OpenCode registers a URL.\n const entry: OpenCodeRemoteServer = {\n type: \"remote\",\n url: resolveEnvRefsDeep(server.url ?? \"\"),\n };\n if (server.enabled === false) entry.enabled = false;\n return entry;\n }\n\n /**\n * Render env values. OpenCode documents no native interpolation token, so\n * resolve every ${env:VAR} reference to a literal at install time.\n */\n private renderEnv(\n env: Record<string, string> | undefined,\n ): Record<string, string> | undefined {\n if (!env || Object.keys(env).length === 0) return undefined;\n return resolveEnvRefsDeep({ ...env });\n }\n\n // ── Hook install / uninstall (ts-plugin) ───────────────────────────────\n\n installHooks(ctx: InstallContext): ChangeRecord[] {\n const pluginPath = this.getHookConfigPath(ctx);\n\n // `hooks: false` disables only the canonical (normalized) events; nativeHooks\n // is a sibling, opencode-scoped declaration on the same override.\n const canonicalDisabled = ctx.connector.platforms[HOST]?.hooks === false;\n const hasCanonical = !canonicalDisabled && ctx.connector.hookEvents.length > 0;\n const hasNative = this.nativeHookEvents(ctx).length > 0;\n\n if (!hasCanonical && !hasNative) {\n return [\n {\n platform: this.id,\n action: \"skip\",\n path: pluginPath,\n detail: canonicalDisabled\n ? \"hooks disabled for opencode\"\n : \"connector declares no hooks\",\n },\n ];\n }\n\n const files = this.synthesizePlugin(ctx);\n const changes: ChangeRecord[] = [];\n\n for (const file of files) {\n // Idempotent: compare existing contents before writing.\n const before = existsSync(file.path)\n ? this.safeRead(file.path)\n : undefined;\n let action: ChangeRecord[\"action\"];\n if (before === undefined) action = \"create\";\n else if (before === file.contents) action = \"skip\";\n else action = \"update\";\n\n if (action !== \"skip\" && !ctx.dryRun) {\n ensureDir(dirname(file.path));\n writeFileSync(file.path, file.contents, \"utf8\");\n // 0644 — readable plugin module; the executable bit is irrelevant for an\n // imported ESM module, but honor the SPI flag if a host ever needs it.\n chmodSync(file.path, file.executable ? 0o755 : 0o644);\n }\n\n changes.push({\n platform: this.id,\n action,\n path: file.path,\n detail: `opencode plugin module (${this.hookDetail(ctx)})`,\n });\n }\n\n return changes;\n }\n\n /**\n * Human-facing summary of which declared events the synthesized module ACTUALLY\n * wires. Only events present in EVENT_TO_OPENCODE are mapped/wired; any declared\n * event with no OpenCode mapping (e.g. UserPromptSubmit) is reported separately\n * as \"unsupported here\" so the detail never overstates coverage.\n */\n private hookDetail(ctx: InstallContext): string {\n const declared = ctx.connector.platforms[HOST]?.hooks === false\n ? []\n : ctx.connector.hookEvents;\n const mapped = declared.filter((e) => EVENT_TO_OPENCODE[e] !== undefined);\n const unsupported = declared.filter((e) => EVENT_TO_OPENCODE[e] === undefined);\n const native = this.nativeHookEvents(ctx);\n const parts: string[] = [];\n if (mapped.length > 0) parts.push(mapped.join(\",\"));\n if (native.length > 0) parts.push(`native: ${native.join(\",\")}`);\n const base = parts.join(\"; \") || \"no canonical hooks\";\n return unsupported.length > 0\n ? `${base}; unsupported here: ${unsupported.join(\",\")}`\n : base;\n }\n\n /**\n * OpenCode-native passthrough events declared on platforms[\"opencode\"]\n * .nativeHooks (host event names with no normalized HookEventName, e.g.\n * session.idle / chat.message). Emitted as generic bridge registrations and\n * dispatched host-generically by the home-bin's runNativeHook.\n */\n private nativeHookEvents(ctx: InstallContext): string[] {\n return Object.keys(ctx.connector.platforms[HOST]?.nativeHooks ?? {});\n }\n\n uninstallHooks(ctx: InstallContext): ChangeRecord[] {\n const pluginPath = this.getHookConfigPath(ctx);\n if (!existsSync(pluginPath)) {\n return [\n {\n platform: this.id,\n action: \"skip\",\n path: pluginPath,\n detail: \"no opencode plugin module present\",\n },\n ];\n }\n if (!ctx.dryRun) rmSync(pluginPath, { force: true });\n return [\n {\n platform: this.id,\n action: \"remove\",\n path: pluginPath,\n detail: \"opencode plugin module\",\n },\n ];\n }\n\n // ── Content surfaces: commands / skills / subagents ──────────────────────\n // CONTENT-ONLY: pure native-file writers under <ocDir>/{commands,skills,\n // agent}. No runtime dispatch, no home-bin pointer, no telemetry wrap. Each\n // method is idempotent (byte-identical → skip) via BaseAdapter.writeContentFile\n // and reversible via removeContentFile. Honors platforms[\"opencode\"]\n // per-surface false to skip.\n //\n // <ocDir> is NOT getConfigDir for project scope: opencode.json lives at the\n // project ROOT, but content surfaces are read from <projectDir>/.opencode/\n // (e.g. .opencode/skills/<name>/SKILL.md per opencode.ai/docs/skills) — the\n // 0.1.0 adapter wrote <projectDir>/skills, which OpenCode never reads.\n //\n // NOTE on dirs: commands live in commands/<name>.md and skills in\n // skills/<name>/SKILL.md, but subagents use the SINGULAR \"agent/\" dir\n // (agent/<name>.md) — the OpenCode loader/CLI historically uses singular\n // (anomalyco/opencode#14410); singular is the safe choice.\n\n private contentRootDir(ctx: InstallContext): string {\n return ctx.scope === \"project\"\n ? join(ctx.projectDir, \".opencode\")\n : this.getConfigDir(ctx);\n }\n private commandsDir(ctx: InstallContext): string {\n return join(this.contentRootDir(ctx), \"commands\");\n }\n private skillsDir(ctx: InstallContext): string {\n return join(this.contentRootDir(ctx), \"skills\");\n }\n private agentDir(ctx: InstallContext): string {\n return join(this.contentRootDir(ctx), \"agent\");\n }\n\n /** Native command file path: <ocDir>/commands/<name>.md. */\n private commandPath(ctx: InstallContext, name: string): string {\n return join(this.commandsDir(ctx), `${name}.md`);\n }\n /** Native skill dir: <ocDir>/skills/<name>. */\n private skillDir(ctx: InstallContext, name: string): string {\n return join(this.skillsDir(ctx), name);\n }\n /** Native subagent file path: <ocDir>/agent/<name>.md (SINGULAR dir). */\n private subagentPath(ctx: InstallContext, name: string): string {\n return join(this.agentDir(ctx), `${name}.md`);\n }\n\n // ── Commands ──────────────────────────────────────────────────────────────\n\n override installCommands(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n if (connector.platforms[HOST]?.commands === false) {\n return [{ platform: this.id, action: \"skip\", detail: \"commands disabled for opencode\" }];\n }\n if (connector.commands.length === 0) {\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no commands\" }];\n }\n return connector.commands.map((cmd) =>\n this.writeContentFile(\n this.commandPath(ctx, cmd.name),\n this.renderCommand(cmd),\n ctx.dryRun,\n ),\n );\n }\n\n override uninstallCommands(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n if (connector.commands.length === 0) {\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no commands\" }];\n }\n return connector.commands.map((cmd) =>\n this.removeContentFile(this.commandPath(ctx, cmd.name), ctx.dryRun),\n );\n }\n\n /** Render a command to md+frontmatter (description, agent, model, subtask). */\n private renderCommand(cmd: CommandDef): string {\n const frontmatter: Record<string, unknown> = {};\n if (cmd.description !== undefined) frontmatter.description = cmd.description;\n if (cmd.model !== undefined) frontmatter.model = cmd.model;\n if (cmd.subtask !== undefined) frontmatter.subtask = cmd.subtask;\n // `agent` is not a core CommandDef field; it arrives via `extra` (escape\n // hatch) and is merged last so a connector can pin a specific OpenCode agent.\n if (cmd.extra) Object.assign(frontmatter, cmd.extra);\n return this.renderFrontmatterMd(frontmatter, cmd.prompt);\n }\n\n // ── Skills ────────────────────────────────────────────────────────────────\n\n override installSkills(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n if (connector.platforms[HOST]?.skills === false) {\n return [{ platform: this.id, action: \"skip\", detail: \"skills disabled for opencode\" }];\n }\n if (connector.skills.length === 0) {\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no skills\" }];\n }\n const changes: ChangeRecord[] = [];\n for (const skill of connector.skills) {\n const dir = this.skillDir(ctx, skill.name);\n changes.push(\n this.writeContentFile(join(dir, \"SKILL.md\"), renderSkillMd(skill), ctx.dryRun),\n );\n // Bundle any resource files beside SKILL.md (relative path → contents).\n // Defense-in-depth: skip+warn on any key that escapes the skill dir\n // (config-time validation already rejects these, but never trust input).\n for (const [rel, contents] of Object.entries(skill.resources ?? {})) {\n const target = this.resolveWithin(dir, rel);\n if (target === null) {\n changes.push({\n platform: this.id,\n action: \"warn\",\n detail: `skill resource \"${rel}\" escapes the skill dir; skipped`,\n });\n continue;\n }\n changes.push(this.writeContentFile(target, contents, ctx.dryRun));\n }\n }\n return changes;\n }\n\n override uninstallSkills(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n if (connector.skills.length === 0) {\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no skills\" }];\n }\n const changes: ChangeRecord[] = [];\n for (const skill of connector.skills) {\n const dir = this.skillDir(ctx, skill.name);\n // Remove only the files we wrote (SKILL.md + declared resources), then the\n // skill dir itself when we own its full contents.\n changes.push(this.removeContentFile(join(dir, \"SKILL.md\"), ctx.dryRun));\n for (const rel of Object.keys(skill.resources ?? {})) {\n const target = this.resolveWithin(dir, rel);\n if (target === null) continue; // never delete outside the skill dir\n changes.push(this.removeContentFile(target, ctx.dryRun));\n }\n // Only remove the skill dir when WE own its full contents — never rm -rf a\n // dir that still holds user-added / sibling-tool / shared files.\n changes.push(this.removeDirIfEmpty(dir, ctx.dryRun));\n }\n return changes;\n }\n\n // ── Subagents ───────────────────────────────────────────────────────────────\n\n override installSubagents(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n if (connector.platforms[HOST]?.subagents === false) {\n return [{ platform: this.id, action: \"skip\", detail: \"subagents disabled for opencode\" }];\n }\n if (connector.subagents.length === 0) {\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no subagents\" }];\n }\n return connector.subagents.map((agent) =>\n this.writeContentFile(\n this.subagentPath(ctx, agent.name),\n renderOpenCodeSubagentMd(agent),\n ctx.dryRun,\n ),\n );\n }\n\n override uninstallSubagents(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n if (connector.subagents.length === 0) {\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no subagents\" }];\n }\n return connector.subagents.map((agent) =>\n this.removeContentFile(this.subagentPath(ctx, agent.name), ctx.dryRun),\n );\n }\n\n // ── ts-plugin synthesis ────────────────────────────────────────────────\n\n /**\n * Build ONE self-contained ESM bridge module for OpenCode.\n *\n * The module imports nothing from agent-connector. It embeds two constants\n * (the absolute home-bin path and the connector id) and a `bridge()` helper\n * that shells out to the universal hook entrypoint via execFileSync, feeding\n * the OpenCode payload on stdin and JSON.parsing the normalized HookResponse\n * back from stdout (fail-open: any error → null). Its default export is the\n * OpenCode plugin factory returning an object keyed only by the OpenCode event\n * names for the events this connector actually declares.\n */\n synthesizePlugin(ctx: InstallContext): GeneratedPluginFile[] {\n const path = this.getHookConfigPath(ctx);\n const contents = this.buildPluginSource(ctx);\n return [{ path, contents, executable: false }];\n }\n\n /** Compose the generated plugin source with plain string concatenation. */\n private buildPluginSource(ctx: InstallContext): string {\n // The OpenCode event keys this connector declares (and that we can map).\n // `hooks: false` disables the canonical events but leaves nativeHooks (a\n // sibling, opencode-scoped declaration) intact.\n const canonicalDisabled = ctx.connector.platforms[HOST]?.hooks === false;\n const events = canonicalDisabled\n ? []\n : ctx.connector.hookEvents.filter(\n (e): e is HookEventName => EVENT_TO_OPENCODE[e] !== undefined,\n );\n const has = (e: HookEventName) => events.includes(e);\n\n const header = `/**\n * AUTO-GENERATED by agent-connector — DO NOT EDIT.\n *\n * Self-contained OpenCode plugin bridge for connector ${ctx.connector.id}.\n * It imports nothing from agent-connector: every hook invocation shells out to\n * the stable home binary's universal entrypoint and JSON-parses the normalized\n * response. Fail-open: any bridge error degrades to \"allow\".\n */\nimport { execFileSync, execSync } from \"node:child_process\";\n\n${renderBridgePrelude({\n homeBin: ctx.homeBinPath,\n connectorId: ctx.connector.id,\n hookSlug: \"opencode\",\n payloadNoun: \"OpenCode\",\n eventDoc: \" (PreToolUse|PostToolUse|SessionStart)\",\n failOpenComment: \"Fail-open — never wedge a tool call on a bridge error.\",\n})}\n`;\n\n const handlers: string[] = [];\n\n if (has(\"PreToolUse\")) {\n handlers.push(` // PreToolUse → block (throw) / rewrite args (mutate output.args).\n \"tool.execute.before\": async (input, output) => {\n const payload = {\n toolName: input.tool ?? \"\",\n toolInput: (output && output.args) ?? {},\n sessionId: input.sessionID ?? \"\",\n projectDir: PROJECT_DIR,\n };\n const res = bridge(\"PreToolUse\", payload);\n if (!res) return;\n // OpenCode has no \"ask\" gate — degrade \"ask\" to a block (safe direction).\n if (res.decision === \"deny\" || res.decision === \"ask\") {\n throw new Error(res.reason || \"Blocked by ${ctx.connector.id}\");\n }\n if (res.updatedInput && output && output.args) {\n Object.assign(output.args, res.updatedInput);\n }\n },`);\n }\n\n if (has(\"PostToolUse\")) {\n handlers.push(` // PostToolUse → observe / rewrite tool output (mutate output.output).\n \"tool.execute.after\": async (input, output) => {\n const payload = {\n toolName: input.tool ?? \"\",\n toolInput: input.args ?? {},\n toolOutput: output ? output.output : undefined,\n sessionId: input.sessionID ?? \"\",\n projectDir: PROJECT_DIR,\n };\n const res = bridge(\"PostToolUse\", payload);\n if (!res) return;\n if (typeof res.updatedOutput === \"string\" && output) {\n output.output = res.updatedOutput;\n }\n },`);\n }\n\n if (has(\"SessionStart\")) {\n handlers.push(` // SessionStart surrogate → inject context into the system prompt.\n // OpenCode has no real SessionStart hook (#14808 / #5409); the\n // experimental.chat.system.transform hook is the verified injection point.\n \"experimental.chat.system.transform\": async (input, output) => {\n const payload = {\n sessionId: (input && input.sessionID) ?? \"\",\n projectDir: PROJECT_DIR,\n };\n const res = bridge(\"SessionStart\", payload);\n if (!res) return;\n if (res.additionalContext && output && Array.isArray(output.system)) {\n // Insert at index 1 (after the header) to preserve OpenCode's\n // prompt-cache fold (header must remain system[0]).\n output.system.splice(1, 0, res.additionalContext);\n }\n },`);\n }\n\n if (has(\"PermissionRequest\")) {\n handlers.push(` // PermissionRequest → decision-capable permission gate.\n // OpenCode's \"permission.ask\" MUTATES output.status (\"ask\"|\"deny\"|\"allow\")\n // — it does NOT return a value (mirrors tool.execute.before/output.args).\n // A normalized \"deny\" maps to output.status \"deny\"; \"ask\" to \"ask\";\n // allow/void leave the default status untouched.\n \"permission.ask\": async (input, output) => {\n const payload = {\n toolName: (input && (input.type || input.tool)) ?? \"\",\n toolInput: (input && (input.metadata || input.args)) ?? {},\n sessionId: (input && input.sessionID) ?? \"\",\n projectDir: PROJECT_DIR,\n };\n const res = bridge(\"PermissionRequest\", payload);\n if (!res || !output) return;\n if (res.decision === \"deny\") output.status = \"deny\";\n else if (res.decision === \"ask\") output.status = \"ask\";\n },`);\n }\n\n // NATIVE PASSTHROUGH events: OpenCode-native plugin event names declared on\n // platforms[\"opencode\"].nativeHooks (chat.message, session.idle,\n // permission.replied, command.execute.before, shell.env, …). No canonical\n // mapping — each is emitted as a fire-and-forget bridge registration; the\n // home-bin's runNativeHook dispatches them host-generically (raw payload →\n // handler → verbatim reply). Keys are computed → emitted as quoted keys.\n for (const nativeEvent of this.nativeHookEvents(ctx)) {\n const key = JSON.stringify(nativeEvent);\n handlers.push(` // native passthrough → ${nativeEvent} (runNativeHook host-generic dispatch).\n [${key}]: async (input, output) => {\n bridge(${key}, {\n sessionId: (input && input.sessionID) ?? \"\",\n projectDir: PROJECT_DIR,\n raw: input,\n });\n },`);\n }\n\n const factory = `\nexport default async function (ctx) {\n // ctx.directory is the OpenCode project root; fall back to cwd.\n const PROJECT_DIR =\n (ctx && (ctx.directory || (ctx.worktree && ctx.worktree.path))) ||\n process.cwd();\n\n return {\n${handlers.join(\"\\n\")}\n };\n}\n`;\n\n return header + factory;\n }\n\n // ── Runtime: parse OUR bridge payload → normalized event ───────────────\n\n /**\n * `raw` is the payload OUR generated plugin posts (NOT a host-native shape):\n * { toolName, toolInput, toolOutput?, isError?, sessionId, projectDir }\n * so this maps straight through.\n */\n parseEvent(event: HookEventName, raw: unknown): NormalizedEvent {\n const input = (raw ?? {}) as OpenCodeBridgePayload;\n const base = {\n hostPlatform: HOST,\n connectorId: \"\",\n sessionId: typeof input.sessionId === \"string\" ? input.sessionId : \"\",\n raw,\n ...(typeof input.projectDir === \"string\"\n ? { projectDir: input.projectDir }\n : {}),\n } as const;\n\n switch (event) {\n case \"PreToolUse\": {\n const ev: PreToolUseEvent = {\n ...base,\n toolName: input.toolName ?? \"\",\n toolInput: input.toolInput ?? {},\n };\n return ev;\n }\n case \"PostToolUse\": {\n const ev: PostToolUseEvent = {\n ...base,\n toolName: input.toolName ?? \"\",\n toolInput: input.toolInput ?? {},\n ...(typeof input.toolOutput === \"string\"\n ? { toolOutput: input.toolOutput }\n : {}),\n ...(typeof input.isError === \"boolean\"\n ? { isError: input.isError }\n : {}),\n };\n return ev;\n }\n case \"PermissionRequest\": {\n // Our generated bridge posts the same {toolName,toolInput,...} shape it\n // posts for PreToolUse, so this maps straight through (no host-native\n // permission_suggestions are surfaced through the plugin payload).\n const ev: PermissionRequestEvent = {\n ...base,\n toolName: input.toolName ?? \"\",\n toolInput: input.toolInput ?? {},\n };\n return ev;\n }\n case \"SessionStart\": {\n const ev: SessionStartEvent = { ...base, source: \"startup\" };\n return ev;\n }\n default:\n // Other canonical events are not surfaced by OpenCode; treat as a\n // session-start-shaped no-op so the dispatcher fails open gracefully.\n return { ...base, source: \"startup\" } satisfies SessionStartEvent;\n }\n }\n\n // ── Runtime: normalized response → reply the generated bridge parses ───\n\n /**\n * Unlike json-stdio hosts (whose reply is the host's NATIVE control payload),\n * OUR generated bridge consumes this stdout directly. So the reply body is the\n * NORMALIZED HookResponse itself — the bridge JSON.parses it and reads\n * decision / updatedInput / updatedOutput / additionalContext.\n */\n formatReply(_event: HookEventName, response: HookResponse): HookReply {\n return {\n exitCode: 0,\n stdout: JSON.stringify(response ?? { decision: \"allow\" }),\n };\n }\n\n // ── Diagnostics ────────────────────────────────────────────────────────\n\n override getHealthChecks(ctx: InstallContext): readonly HealthCheck[] {\n const serverPath = this.getServerConfigPath(ctx);\n const pluginPath = this.getHookConfigPath(ctx);\n const connectorId = ctx.connector.id;\n const hasHooks = ctx.connector.hookEvents.length > 0;\n\n const checks: HealthCheck[] = [\n {\n name: `${this.name}: opencode.json present`,\n check: () =>\n existsSync(serverPath)\n ? { status: \"OK\", detail: serverPath }\n : { status: \"FAIL\", detail: `not found: ${serverPath}` },\n },\n {\n name: `${this.name}: mcp.${connectorId} registered`,\n check: () => {\n if (!ctx.connector.server) {\n return { status: \"OK\", detail: \"no MCP server declared\" };\n }\n const cfg = this.readJson<{ [k: string]: Record<string, unknown> }>(\n serverPath,\n );\n const bucket = cfg?.[MCP_ROOT_KEY];\n if (!cfg || !bucket) {\n return { status: \"FAIL\", detail: `no ${MCP_ROOT_KEY} in ${serverPath}` };\n }\n return connectorId in bucket\n ? { status: \"OK\", detail: `${MCP_ROOT_KEY}.${connectorId} present` }\n : {\n status: \"FAIL\",\n detail: `no ${MCP_ROOT_KEY}.${connectorId} in ${serverPath}`,\n };\n },\n },\n {\n name: `${this.name}: plugin module present`,\n check: () => {\n if (!hasHooks) return { status: \"OK\", detail: \"no hooks declared\" };\n return existsSync(pluginPath)\n ? { status: \"OK\", detail: pluginPath }\n : { status: \"FAIL\", detail: `not found: ${pluginPath}` };\n },\n },\n ];\n\n // Content-surface checks: only assert presence of the files this connector\n // declares (skip silently for surfaces it never asked for).\n for (const cmd of ctx.connector.commands) {\n const p = this.commandPath(ctx, cmd.name);\n checks.push({\n name: `${this.name}: command ${cmd.name} present`,\n check: () =>\n existsSync(p) ? { status: \"OK\", detail: p } : { status: \"FAIL\", detail: `not found: ${p}` },\n });\n }\n for (const skill of ctx.connector.skills) {\n const p = join(this.skillDir(ctx, skill.name), \"SKILL.md\");\n checks.push({\n name: `${this.name}: skill ${skill.name} present`,\n check: () =>\n existsSync(p) ? { status: \"OK\", detail: p } : { status: \"FAIL\", detail: `not found: ${p}` },\n });\n }\n for (const agent of ctx.connector.subagents) {\n const p = this.subagentPath(ctx, agent.name);\n checks.push({\n name: `${this.name}: subagent ${agent.name} present`,\n check: () =>\n existsSync(p) ? { status: \"OK\", detail: p } : { status: \"FAIL\", detail: `not found: ${p}` },\n });\n }\n return checks;\n }\n\n /** Read a file, returning undefined on any error (idempotency compare). */\n private safeRead(path: string): string | undefined {\n try {\n return readFileSync(path, \"utf8\");\n } catch {\n return undefined;\n }\n }\n}\n\n/** Create a directory (recursive) if it does not already exist. */\nfunction ensureDir(dir: string): void {\n if (!existsSync(dir)) mkdirSync(dir, { recursive: true });\n}\n\nexport const adapter = new OpenCodeAdapter();\nexport default adapter;\n"],"mappings":"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","names":["entry"]}
|
|
@@ -6,21 +6,21 @@ import {
|
|
|
6
6
|
isPackageFormat,
|
|
7
7
|
packageConnector,
|
|
8
8
|
packageConnectorAll
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-CDVOBKSG.js";
|
|
10
10
|
import {
|
|
11
11
|
fail,
|
|
12
12
|
print
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-A2T4Q7RM.js";
|
|
14
14
|
import {
|
|
15
15
|
findConnectorConfig,
|
|
16
16
|
loadConnectorFromPath
|
|
17
|
-
} from "./chunk-
|
|
18
|
-
import "./chunk-
|
|
19
|
-
import "./chunk-
|
|
17
|
+
} from "./chunk-MOW2RKHX.js";
|
|
18
|
+
import "./chunk-HOE2MN36.js";
|
|
19
|
+
import "./chunk-XQUUNAGC.js";
|
|
20
20
|
import "./chunk-FAHIMJRU.js";
|
|
21
21
|
import "./chunk-OPXAP3AC.js";
|
|
22
|
-
import "./chunk-
|
|
23
|
-
import "./chunk-
|
|
22
|
+
import "./chunk-IEGR4TP3.js";
|
|
23
|
+
import "./chunk-TO57WYBB.js";
|
|
24
24
|
import "./chunk-N6HH7K6P.js";
|
|
25
25
|
import "./chunk-TRQKHP7D.js";
|
|
26
26
|
|
|
@@ -129,4 +129,4 @@ async function run(argv) {
|
|
|
129
129
|
export {
|
|
130
130
|
run
|
|
131
131
|
};
|
|
132
|
-
//# sourceMappingURL=package-
|
|
132
|
+
//# sourceMappingURL=package-BSCCMW4E.js.map
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
BaseAdapter
|
|
4
|
-
} from "./chunk-
|
|
5
|
-
import "./chunk-
|
|
6
|
-
import "./chunk-
|
|
4
|
+
} from "./chunk-KG6T3YNJ.js";
|
|
5
|
+
import "./chunk-IEGR4TP3.js";
|
|
6
|
+
import "./chunk-TO57WYBB.js";
|
|
7
7
|
import "./chunk-N6HH7K6P.js";
|
|
8
8
|
import "./chunk-TRQKHP7D.js";
|
|
9
9
|
|
|
@@ -289,4 +289,4 @@ export {
|
|
|
289
289
|
adapter,
|
|
290
290
|
pi_default as default
|
|
291
291
|
};
|
|
292
|
-
//# sourceMappingURL=pi-
|
|
292
|
+
//# sourceMappingURL=pi-H2KBBDDJ.js.map
|
|
@@ -15,22 +15,24 @@ import {
|
|
|
15
15
|
import {
|
|
16
16
|
writeTomlString
|
|
17
17
|
} from "./chunk-OPXAP3AC.js";
|
|
18
|
+
import {
|
|
19
|
+
normalizeSessionSource
|
|
20
|
+
} from "./chunk-H53QZQJI.js";
|
|
18
21
|
import {
|
|
19
22
|
resolveEnvRefsDeep
|
|
20
23
|
} from "./chunk-DBQMX75U.js";
|
|
21
24
|
import {
|
|
22
25
|
BaseAdapter
|
|
23
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-KG6T3YNJ.js";
|
|
24
27
|
import {
|
|
25
28
|
renderSkillMd
|
|
26
|
-
} from "./chunk-
|
|
29
|
+
} from "./chunk-IEGR4TP3.js";
|
|
27
30
|
import {
|
|
28
31
|
buildHomeBinStatuslineCommand,
|
|
29
|
-
|
|
32
|
+
buildWrappedStdio,
|
|
30
33
|
isHomeBinHookCommand,
|
|
31
|
-
isHomeBinStatuslineCommand
|
|
32
|
-
|
|
33
|
-
} from "./chunk-I5MLE6S7.js";
|
|
34
|
+
isHomeBinStatuslineCommand
|
|
35
|
+
} from "./chunk-TO57WYBB.js";
|
|
34
36
|
import "./chunk-N6HH7K6P.js";
|
|
35
37
|
import "./chunk-TRQKHP7D.js";
|
|
36
38
|
|
|
@@ -187,18 +189,7 @@ var QwenCodeAdapter = class extends BaseAdapter {
|
|
|
187
189
|
if (transport === "stdio") {
|
|
188
190
|
let command = server.command ?? "";
|
|
189
191
|
let args = [...server.args ?? []];
|
|
190
|
-
|
|
191
|
-
const wrapped = buildServeWrapperCommand(
|
|
192
|
-
ctx.homeBinPath,
|
|
193
|
-
ctx.connector.id,
|
|
194
|
-
command,
|
|
195
|
-
args,
|
|
196
|
-
ctx.scope,
|
|
197
|
-
this.id
|
|
198
|
-
);
|
|
199
|
-
command = wrapped.command;
|
|
200
|
-
args = wrapped.args;
|
|
201
|
-
}
|
|
192
|
+
({ command, args } = buildWrappedStdio(ctx, server, this.id, command, args));
|
|
202
193
|
const entry2 = {
|
|
203
194
|
type: "stdio",
|
|
204
195
|
command: resolveEnvRefsDeep(command),
|
|
@@ -1080,18 +1071,6 @@ function toolResponseToString(value) {
|
|
|
1080
1071
|
return String(value);
|
|
1081
1072
|
}
|
|
1082
1073
|
}
|
|
1083
|
-
function normalizeSessionSource(source) {
|
|
1084
|
-
switch (source) {
|
|
1085
|
-
case "compact":
|
|
1086
|
-
return "compact";
|
|
1087
|
-
case "resume":
|
|
1088
|
-
return "resume";
|
|
1089
|
-
case "clear":
|
|
1090
|
-
return "clear";
|
|
1091
|
-
default:
|
|
1092
|
-
return "startup";
|
|
1093
|
-
}
|
|
1094
|
-
}
|
|
1095
1074
|
var adapter = new QwenCodeAdapter();
|
|
1096
1075
|
var qwen_code_default = adapter;
|
|
1097
1076
|
export {
|
|
@@ -1099,4 +1078,4 @@ export {
|
|
|
1099
1078
|
adapter,
|
|
1100
1079
|
qwen_code_default as default
|
|
1101
1080
|
};
|
|
1102
|
-
//# sourceMappingURL=qwen-code-
|
|
1081
|
+
//# sourceMappingURL=qwen-code-5LE34FNE.js.map
|