@ken-jo/agent-connector 0.4.61 → 0.4.75
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/README.md +43 -6
- package/dist/{action-AIB2W4DU.js → action-TCKBTTZX.js} +12 -12
- package/dist/{amazon-q-PH7OFPJD.js → amazon-q-CB4XFX7T.js} +5 -5
- package/dist/{amp-ZYRC2VCH.js → amp-6Q5OYHNW.js} +9 -5
- package/dist/amp-6Q5OYHNW.js.map +1 -0
- package/dist/{antigravity-PM5NMS2J.js → antigravity-WIK3XBN5.js} +6 -6
- package/dist/{antigravity-cli-LN25XGWX.js → antigravity-cli-L3RZMF6V.js} +6 -6
- package/dist/{chunk-NFMHYIN2.js → chunk-24K6JOKV.js} +5 -5
- package/dist/{chunk-D65GIBCG.js → chunk-2HCJV6UO.js} +13 -14
- package/dist/chunk-2HCJV6UO.js.map +1 -0
- package/dist/{chunk-FVARNRCE.js → chunk-2L6LTQ6L.js} +45 -10
- package/dist/chunk-2L6LTQ6L.js.map +1 -0
- package/dist/{chunk-O4BKQSPP.js → chunk-5LAFKXFM.js} +3 -3
- package/dist/{chunk-BZOOVTFG.js → chunk-7CZKXXBD.js} +2 -2
- package/dist/{chunk-JZIM33C2.js → chunk-7ITLLYWB.js} +5 -5
- package/dist/{chunk-LBOGRZGY.js → chunk-ALVXORZM.js} +2 -2
- package/dist/{chunk-WOUGWPZQ.js → chunk-AXAHW2KU.js} +2 -2
- package/dist/{chunk-DBQMX75U.js → chunk-BEFVJ2OE.js} +28 -2
- package/dist/chunk-BEFVJ2OE.js.map +1 -0
- package/dist/{chunk-ZQCT63JU.js → chunk-D6ZJS4ND.js} +2 -2
- package/dist/{chunk-O3HIYTBK.js → chunk-DI6OWKH2.js} +7 -3
- package/dist/chunk-DI6OWKH2.js.map +1 -0
- package/dist/chunk-ECSRTK4M.js +386 -0
- package/dist/chunk-ECSRTK4M.js.map +1 -0
- package/dist/{chunk-C3TFA4CJ.js → chunk-FUXUEXDP.js} +3 -3
- package/dist/{chunk-KAEYJGK7.js → chunk-HKM3HUOK.js} +19 -19
- package/dist/{chunk-KAEYJGK7.js.map → chunk-HKM3HUOK.js.map} +1 -1
- package/dist/{chunk-AEQRMVRB.js → chunk-IU42THN7.js} +2 -2
- package/dist/{chunk-AAOYOAQT.js → chunk-MDZG5QHB.js} +49 -3
- package/dist/chunk-MDZG5QHB.js.map +1 -0
- package/dist/{chunk-RFYQXT7C.js → chunk-MHDQWZ4A.js} +7 -7
- package/dist/{chunk-GI4FDVWI.js → chunk-NUGMVVV2.js} +4 -4
- package/dist/chunk-NUGMVVV2.js.map +1 -0
- package/dist/{chunk-RGQTN7K3.js → chunk-OEQJGBBW.js} +5 -5
- package/dist/{chunk-4K5HEGVE.js → chunk-Q42SEI7W.js} +11 -11
- package/dist/chunk-Q42SEI7W.js.map +1 -0
- package/dist/{chunk-IDKI42JW.js → chunk-Q5LECKZL.js} +36 -36
- package/dist/{chunk-QP35SRUZ.js → chunk-TW4DVR4V.js} +2 -2
- package/dist/{chunk-3QCDVSMX.js → chunk-TZ5KGCE2.js} +2 -2
- package/dist/{claude-code-GCXXEWUN.js → claude-code-HFBAAVWS.js} +13 -9
- package/dist/claude-code-HFBAAVWS.js.map +1 -0
- package/dist/cli/sdk.js +7 -7
- package/dist/cli.js +1 -1
- package/dist/{cline-KHZLG7CU.js → cline-26W4FEZ6.js} +5 -5
- package/dist/{codebuff-EQGWZEP4.js → codebuff-J5KEEBIL.js} +9 -5
- package/dist/codebuff-J5KEEBIL.js.map +1 -0
- package/dist/{codex-7X7RC6JJ.js → codex-JKQ6TLRI.js} +18 -25
- package/dist/codex-JKQ6TLRI.js.map +1 -0
- package/dist/{continue-V4MB3WQ3.js → continue-KQSJUSWX.js} +6 -6
- package/dist/{copilot-cli-7EPIJHFM.js → copilot-cli-YBNKLYUB.js} +121 -43
- package/dist/copilot-cli-YBNKLYUB.js.map +1 -0
- package/dist/{crush-3AAA75C5.js → crush-JTWTZIPB.js} +22 -12
- package/dist/crush-JTWTZIPB.js.map +1 -0
- package/dist/{cursor-DTYZROKS.js → cursor-2NIZSDZ4.js} +6 -6
- package/dist/{detect-LWZEM7SN.js → detect-CWEIQCRC.js} +4 -4
- package/dist/{doctor-54P4JFA6.js → doctor-AC437ZAW.js} +99 -17
- package/dist/doctor-AC437ZAW.js.map +1 -0
- package/dist/{droid-QMNO5WZ2.js → droid-HF2AIFB2.js} +5 -5
- package/dist/{gemini-cli-7JU7ZWQL.js → gemini-cli-2EOK26S2.js} +5 -5
- package/dist/{goose-36TJNDKD.js → goose-55JOTXS5.js} +6 -6
- package/dist/{hermes-S4JZ6H42.js → hermes-QVZOZU4B.js} +6 -6
- package/dist/{hook-UT3Q43AB.js → hook-VYD3OCLM.js} +12 -12
- package/dist/index.d.ts +2 -2
- package/dist/index.js +5 -5
- package/dist/{install-F4OIDYAK.js → install-S6BYIJ62.js} +15 -15
- package/dist/{introspect-BFcXpfUp.d.ts → introspect-5o5ick0_.d.ts} +9 -4
- package/dist/{jetbrains-copilot-6QLKUCAY.js → jetbrains-copilot-DZ2ATXFN.js} +6 -7
- package/dist/jetbrains-copilot-DZ2ATXFN.js.map +1 -0
- package/dist/{kilo-WLZOYKZK.js → kilo-GJNSBWVV.js} +5 -5
- package/dist/{kilo-cli-FBX4OFIZ.js → kilo-cli-2CCB3DBI.js} +5 -5
- package/dist/{kimi-7YXRAQ6Z.js → kimi-YRPCSB6N.js} +5 -5
- package/dist/{kiro-CSBQA6EX.js → kiro-BUOQFASX.js} +5 -5
- package/dist/{leaderboard-ZIAXBUWD.js → leaderboard-SUSUDKHR.js} +5 -5
- package/dist/{mimo-code-GYJNEULG.js → mimo-code-V4FP5PUJ.js} +5 -5
- package/dist/{mux-DAIC3VY7.js → mux-CMJSM42O.js} +5 -5
- package/dist/{nemoclaw-GS3XA7V2.js → nemoclaw-VP56PGKC.js} +6 -6
- package/dist/{omp-O6KNB4MM.js → omp-OOFGD3GG.js} +5 -5
- package/dist/openclaw-V73XHPXP.js +17 -0
- package/dist/{opencode-JPHRZPDQ.js → opencode-MKLHSQRD.js} +5 -5
- package/dist/{package-5FRMSWRT.js → package-KOAAVKHH.js} +12 -12
- package/dist/{pi-EFBTBI2B.js → pi-NMVL7OFL.js} +4 -4
- package/dist/{qwen-code-CLSMTMHX.js → qwen-code-2XE2T6F4.js} +6 -6
- package/dist/{roo-code-YIX3RPR2.js → roo-code-YJOIKCCS.js} +5 -5
- package/dist/runtime/index.d.ts +1 -1
- package/dist/runtime/index.js +10 -10
- package/dist/sdk/index.d.ts +3 -3
- package/dist/sdk/index.js +6 -6
- package/dist/sdk/test.d.ts +33 -3
- package/dist/sdk/test.js +14 -284
- package/dist/sdk/test.js.map +1 -1
- package/dist/{serve-NQBXN4FG.js → serve-BU23QUSJ.js} +12 -12
- package/dist/{status-5ZM6LXHV.js → status-N5LCQQ3R.js} +10 -10
- package/dist/{statusline-O76BCBUK.js → statusline-442XOF7R.js} +11 -11
- package/dist/{telemetry-NO7UUUSJ.js → telemetry-V4YQL2NU.js} +10 -10
- package/dist/{trae-JESXQKAF.js → trae-QSV2JZFT.js} +5 -5
- package/dist/{types-ChUrvw0j.d.ts → types-D6RWGXm1.d.ts} +13 -0
- package/dist/{uninstall-QCROBR6A.js → uninstall-WGEKTCDZ.js} +22 -15
- package/dist/uninstall-WGEKTCDZ.js.map +1 -0
- package/dist/{upgrade-KJ4QRZDZ.js → upgrade-IH7CKPTO.js} +15 -15
- package/dist/{usage-UY6DCND6.js → usage-DI7XRCKM.js} +2 -2
- package/dist/{usage-event-T4HWQDZF.js → usage-event-2FCU55AN.js} +11 -11
- package/dist/{vscode-copilot-56USZ5X4.js → vscode-copilot-R23RTVST.js} +9 -5
- package/dist/vscode-copilot-R23RTVST.js.map +1 -0
- package/dist/{warp-Y6JNLLGR.js → warp-B72XSQ5G.js} +5 -5
- package/dist/{windsurf-X7QCJ3XR.js → windsurf-642VBMQ2.js} +5 -5
- package/dist/{zed-L3ML5MHF.js → zed-6UJS7JKB.js} +5 -5
- package/package.json +1 -1
- package/dist/amp-ZYRC2VCH.js.map +0 -1
- package/dist/chunk-4K5HEGVE.js.map +0 -1
- package/dist/chunk-AAOYOAQT.js.map +0 -1
- package/dist/chunk-D65GIBCG.js.map +0 -1
- package/dist/chunk-DBQMX75U.js.map +0 -1
- package/dist/chunk-FVARNRCE.js.map +0 -1
- package/dist/chunk-GI4FDVWI.js.map +0 -1
- package/dist/chunk-O3HIYTBK.js.map +0 -1
- package/dist/claude-code-GCXXEWUN.js.map +0 -1
- package/dist/codebuff-EQGWZEP4.js.map +0 -1
- package/dist/codex-7X7RC6JJ.js.map +0 -1
- package/dist/copilot-cli-7EPIJHFM.js.map +0 -1
- package/dist/crush-3AAA75C5.js.map +0 -1
- package/dist/doctor-54P4JFA6.js.map +0 -1
- package/dist/jetbrains-copilot-6QLKUCAY.js.map +0 -1
- package/dist/openclaw-344VBMLY.js +0 -17
- package/dist/uninstall-QCROBR6A.js.map +0 -1
- package/dist/vscode-copilot-56USZ5X4.js.map +0 -1
- /package/dist/{action-AIB2W4DU.js.map → action-TCKBTTZX.js.map} +0 -0
- /package/dist/{amazon-q-PH7OFPJD.js.map → amazon-q-CB4XFX7T.js.map} +0 -0
- /package/dist/{antigravity-PM5NMS2J.js.map → antigravity-WIK3XBN5.js.map} +0 -0
- /package/dist/{antigravity-cli-LN25XGWX.js.map → antigravity-cli-L3RZMF6V.js.map} +0 -0
- /package/dist/{chunk-NFMHYIN2.js.map → chunk-24K6JOKV.js.map} +0 -0
- /package/dist/{chunk-O4BKQSPP.js.map → chunk-5LAFKXFM.js.map} +0 -0
- /package/dist/{chunk-BZOOVTFG.js.map → chunk-7CZKXXBD.js.map} +0 -0
- /package/dist/{chunk-JZIM33C2.js.map → chunk-7ITLLYWB.js.map} +0 -0
- /package/dist/{chunk-LBOGRZGY.js.map → chunk-ALVXORZM.js.map} +0 -0
- /package/dist/{chunk-WOUGWPZQ.js.map → chunk-AXAHW2KU.js.map} +0 -0
- /package/dist/{chunk-ZQCT63JU.js.map → chunk-D6ZJS4ND.js.map} +0 -0
- /package/dist/{chunk-C3TFA4CJ.js.map → chunk-FUXUEXDP.js.map} +0 -0
- /package/dist/{chunk-AEQRMVRB.js.map → chunk-IU42THN7.js.map} +0 -0
- /package/dist/{chunk-RFYQXT7C.js.map → chunk-MHDQWZ4A.js.map} +0 -0
- /package/dist/{chunk-RGQTN7K3.js.map → chunk-OEQJGBBW.js.map} +0 -0
- /package/dist/{chunk-IDKI42JW.js.map → chunk-Q5LECKZL.js.map} +0 -0
- /package/dist/{chunk-QP35SRUZ.js.map → chunk-TW4DVR4V.js.map} +0 -0
- /package/dist/{chunk-3QCDVSMX.js.map → chunk-TZ5KGCE2.js.map} +0 -0
- /package/dist/{cline-KHZLG7CU.js.map → cline-26W4FEZ6.js.map} +0 -0
- /package/dist/{continue-V4MB3WQ3.js.map → continue-KQSJUSWX.js.map} +0 -0
- /package/dist/{cursor-DTYZROKS.js.map → cursor-2NIZSDZ4.js.map} +0 -0
- /package/dist/{detect-LWZEM7SN.js.map → detect-CWEIQCRC.js.map} +0 -0
- /package/dist/{droid-QMNO5WZ2.js.map → droid-HF2AIFB2.js.map} +0 -0
- /package/dist/{gemini-cli-7JU7ZWQL.js.map → gemini-cli-2EOK26S2.js.map} +0 -0
- /package/dist/{goose-36TJNDKD.js.map → goose-55JOTXS5.js.map} +0 -0
- /package/dist/{hermes-S4JZ6H42.js.map → hermes-QVZOZU4B.js.map} +0 -0
- /package/dist/{hook-UT3Q43AB.js.map → hook-VYD3OCLM.js.map} +0 -0
- /package/dist/{install-F4OIDYAK.js.map → install-S6BYIJ62.js.map} +0 -0
- /package/dist/{kilo-WLZOYKZK.js.map → kilo-GJNSBWVV.js.map} +0 -0
- /package/dist/{kilo-cli-FBX4OFIZ.js.map → kilo-cli-2CCB3DBI.js.map} +0 -0
- /package/dist/{kimi-7YXRAQ6Z.js.map → kimi-YRPCSB6N.js.map} +0 -0
- /package/dist/{kiro-CSBQA6EX.js.map → kiro-BUOQFASX.js.map} +0 -0
- /package/dist/{leaderboard-ZIAXBUWD.js.map → leaderboard-SUSUDKHR.js.map} +0 -0
- /package/dist/{mimo-code-GYJNEULG.js.map → mimo-code-V4FP5PUJ.js.map} +0 -0
- /package/dist/{mux-DAIC3VY7.js.map → mux-CMJSM42O.js.map} +0 -0
- /package/dist/{nemoclaw-GS3XA7V2.js.map → nemoclaw-VP56PGKC.js.map} +0 -0
- /package/dist/{omp-O6KNB4MM.js.map → omp-OOFGD3GG.js.map} +0 -0
- /package/dist/{openclaw-344VBMLY.js.map → openclaw-V73XHPXP.js.map} +0 -0
- /package/dist/{opencode-JPHRZPDQ.js.map → opencode-MKLHSQRD.js.map} +0 -0
- /package/dist/{package-5FRMSWRT.js.map → package-KOAAVKHH.js.map} +0 -0
- /package/dist/{pi-EFBTBI2B.js.map → pi-NMVL7OFL.js.map} +0 -0
- /package/dist/{qwen-code-CLSMTMHX.js.map → qwen-code-2XE2T6F4.js.map} +0 -0
- /package/dist/{roo-code-YIX3RPR2.js.map → roo-code-YJOIKCCS.js.map} +0 -0
- /package/dist/{serve-NQBXN4FG.js.map → serve-BU23QUSJ.js.map} +0 -0
- /package/dist/{status-5ZM6LXHV.js.map → status-N5LCQQ3R.js.map} +0 -0
- /package/dist/{statusline-O76BCBUK.js.map → statusline-442XOF7R.js.map} +0 -0
- /package/dist/{telemetry-NO7UUUSJ.js.map → telemetry-V4YQL2NU.js.map} +0 -0
- /package/dist/{trae-JESXQKAF.js.map → trae-QSV2JZFT.js.map} +0 -0
- /package/dist/{upgrade-KJ4QRZDZ.js.map → upgrade-IH7CKPTO.js.map} +0 -0
- /package/dist/{usage-UY6DCND6.js.map → usage-DI7XRCKM.js.map} +0 -0
- /package/dist/{usage-event-T4HWQDZF.js.map → usage-event-2FCU55AN.js.map} +0 -0
- /package/dist/{warp-Y6JNLLGR.js.map → warp-B72XSQ5G.js.map} +0 -0
- /package/dist/{windsurf-X7QCJ3XR.js.map → windsurf-642VBMQ2.js.map} +0 -0
- /package/dist/{zed-L3ML5MHF.js.map → zed-6UJS7JKB.js.map} +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/adapters/copilot-cli/index.ts"],"sourcesContent":["/**\n * adapters/copilot-cli — GitHub Copilot CLI platform adapter for agent-connector.\n *\n * GitHub Copilot CLI is a json-stdio host: the host pipes a JSON payload to a\n * hook command on stdin and reads JSON/exit-code back. Its hook event names and\n * reply shape are Claude-compatible (PascalCase events, `hookSpecificOutput`\n * reply wrapper), so the normalized HookEventName values map 1:1 — no event\n * rename table is needed.\n *\n * Native config (user/global only — Copilot CLI has no project-scoped config):\n * - MCP servers: ~/.copilot/mcp-config.json, root key \"mcpServers\". An stdio\n * server is written with type \"local\" (the host also accepts \"stdio\") plus\n * `tools: [\"*\"]`. Remote servers use type \"http\".\n * - Hooks: a Claude-compatible hooks file shaped `{ version: 1, hooks: { … } }`\n * discovered from ~/.copilot/hooks/*.json. We write a single dedicated file,\n * ~/.copilot/hooks/agent-connector.json, so we never disturb a user's own\n * hook files and removal is a clean, scoped operation. Each event maps to an\n * array of flat command entries `{ matcher?, hooks: [{ type:\"command\", command }] }`\n * — the Claude shape, which Copilot CLI reads.\n * - Reply: a `hookSpecificOutput` object keyed by `hookEventName` carrying\n * `permissionDecision` (allow|deny|ask) + `permissionDecisionReason`,\n * `additionalContext`, and (PreToolUse) `updatedInput`. PreToolUse is\n * fail-closed on the host side; exit 0 + JSON refines the decision.\n *\n * Env handling: the host is not documented to support `${env:VAR}` interpolation\n * inside mcp-config.json, so env/header/url refs are resolved to literals at\n * install time via resolveEnvRefsDeep (the safe default for a no-native-interp\n * host, matching the Codex adapter's approach).\n *\n * Content surfaces (surfaces-design §4-5): Copilot CLI exposes skills and\n * subagents but NO prompt-file command surface, so commands inherit the\n * BaseAdapter skip/warn default (supportsCommands stays false).\n * - skills: folder-per-skill `<dir>/skills/<name>/SKILL.md` (+ resource files).\n * user scope → ~/.copilot/skills; project scope → <projectDir>/.github/skills.\n * - subagents: user scope → ~/.copilot/agents/<name>.agent.md; project scope →\n * <projectDir>/.github/agents/<name>.agent.md (md + frontmatter:\n * name, description, tools, model).\n * The .github/ tree is shared with the vscode-copilot and jetbrains-copilot\n * connectors; we write identical, idempotent content and on uninstall remove\n * only the files this connector wrote.\n *\n * Grounded in docs/research/understand-report.md §2 (Platform Integration\n * Matrix, \"GitHub Copilot CLI\" row).\n */\n\nimport { existsSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\nimport { BaseAdapter } from \"../base.js\";\nimport type { Adapter, HookReply, InstallContext, MemoryTarget, NormalizedEvent } from \"../spi.js\";\nimport type {\n ChangeRecord,\n DetectedPlatform,\n HealthCheck,\n HookEventName,\n HookParadigm,\n HookResponse,\n NotificationEvent,\n PermissionRequestEvent,\n PlatformCapabilities,\n PlatformId,\n PostToolUseEvent,\n PostToolUseFailureEvent,\n PostCompactEvent,\n PreCompactEvent,\n PreToolUseEvent,\n ServerDef,\n SessionEndEvent,\n SessionStartEvent,\n StopEvent,\n SubagentStartEvent,\n SubagentStopEvent,\n Transport,\n UserPromptSubmitEvent,\n} from \"../../core/types.js\";\nimport { resolveEnvRefsDeep } from \"../../core/interpolate.js\";\nimport {\n buildHomeBinHookCommand,\n buildWrappedStdio,\n isHomeBinHookCommand,\n} from \"../../core/spawn.js\";\nimport { renderSkillMd, renderSubagentMd } from \"../claude-code/render.js\";\nimport { normalizeSessionSource } from \"../claude-code/wire.js\";\n\nconst HOST: PlatformId = \"copilot-cli\";\nconst MCP_ROOT_KEY = \"mcpServers\";\n\n/** Native hooks-file version Copilot CLI expects (`{ version: 1, hooks: {…} }`). */\nconst COPILOT_HOOKS_VERSION = 1;\n\n/**\n * Copilot CLI accepts both camelCase and PascalCase hook event names; PascalCase\n * is the portable, Claude/VS Code-compatible form (and selects the snake_case\n * payload dialect), so we emit it directly. Our normalized HookEventName values\n * are already PascalCase and match 1:1, hence no rename table — every declared\n * event has a native equivalent, including the newer four: subagentStart\n * (additionalContext only, matcher on agent name), subagentStop (can block and\n * force continuation), permissionRequest (decision control), and\n * postToolUseFailure (recovery guidance; the host also has a broader\n * errorOccurred event with no normalized analog — reachable via\n * platforms[\"copilot-cli\"].nativeHooks, see capabilities.supportsNativeHooks).\n */\ntype CopilotHookEvent = HookEventName;\n\n/**\n * CAPABILITY FILTER for installHooks — maps each canonical HookEventName to the\n * `capabilities` flag that gates it. The adapter's `capabilities` literal is the\n * single source of truth for what Copilot CLI's runtime actually fires; declared\n * events (connector.hookEvents is the connector-level set, NOT pre-filtered by\n * host) are screened through this map so an unsupported event — Copilot CLI has\n * NO post-compaction hook, so `postCompact` stays unset — is reported as a\n * graceful warn/skip instead of being written as a dead `hooks.PostCompact` the\n * host would never fire. Same shape as the goose adapter's EVENT_CAPABILITY.\n */\nconst EVENT_CAPABILITY: Record<HookEventName, keyof PlatformCapabilities> = {\n SessionStart: \"sessionStart\",\n SessionEnd: \"sessionEnd\",\n UserPromptSubmit: \"userPromptSubmit\",\n PreToolUse: \"preToolUse\",\n PostToolUse: \"postToolUse\",\n PreCompact: \"preCompact\",\n Stop: \"stop\",\n Notification: \"notification\",\n PermissionRequest: \"permissionRequest\",\n PostToolUseFailure: \"postToolUseFailure\",\n SubagentStart: \"subagentStart\",\n SubagentStop: \"subagentStop\",\n // Copilot CLI has no post-compaction hook — postCompact stays unset on\n // `capabilities`, so a declared PostCompact warn-skips at install.\n PostCompact: \"postCompact\",\n};\n\n/** A single Copilot CLI hook registration entry (Claude-shaped). */\ninterface CopilotHookEntry {\n matcher: string;\n hooks: Array<{ type: \"command\"; command: string }>;\n}\n\n/** The shape of the Copilot CLI hooks file we own. */\ninterface CopilotHooksFile {\n version?: number;\n hooks?: Record<string, CopilotHookEntry[]>;\n}\n\n/** Native MCP server entry shapes Copilot CLI accepts under `mcpServers`. */\ninterface CopilotLocalServer {\n /** stdio transport is registered as type \"local\" (host also accepts \"stdio\"). */\n type: \"local\";\n command: string;\n args?: string[];\n env?: Record<string, string>;\n cwd?: string;\n tools: string[];\n}\ninterface CopilotHttpServer {\n /** Remote transport: \"http\" (Streamable HTTP) or \"sse\" (legacy). */\n type: \"http\" | \"sse\";\n url: string;\n headers?: Record<string, string>;\n tools: string[];\n}\n\n/** Raw Copilot CLI hook stdin payload (Claude-style: PascalCase event, snake_case fields). */\ninterface CopilotWireInput {\n connector?: unknown;\n session_id?: string;\n transcript_path?: string;\n cwd?: string;\n hook_event_name?: string;\n\n // tool events\n tool_name?: string;\n tool_input?: Record<string, unknown>;\n // PostToolUse (VS Code-compatible dialect): the tool result rides under\n // `tool_result`, NOT `tool_response`. PostToolUse fires success-only, so\n // result_type is always \"success\" (hooks-reference.md:397-400).\n tool_result?: { result_type?: string; text_result_for_llm?: string };\n\n // SessionStart\n source?: string;\n // SessionEnd\n reason?: string;\n // UserPromptSubmit\n prompt?: string;\n // PreCompact\n trigger?: string;\n // Notification\n message?: string;\n\n // PostToolUseFailure — payload is {tool_name, tool_input, error} + base\n // (hooks-reference.md:421-430). No tool_use_id/is_interrupt/duration_ms.\n error?: string;\n\n // SubagentStart / SubagentStop — VS Code dialect identity is `agent_name`\n // (+ optional `agent_display_name`); there is no agent_id/agent_type\n // (hooks-reference.md:467-476,497-507).\n agent_name?: string;\n agent_display_name?: string;\n}\n\nexport class CopilotCliAdapter extends BaseAdapter implements Adapter {\n readonly id: PlatformId = HOST;\n readonly name = \"GitHub Copilot CLI\";\n readonly paradigm: HookParadigm = \"json-stdio\";\n\n readonly capabilities: PlatformCapabilities = {\n // Memory surface: AGENTS.md-first managed block (project <projectDir>/AGENTS.md\n // via the base default; user scope → ~/.copilot/copilot-instructions.md below).\n supportsMemory: true,\n // Copilot CLI delivers the full Claude-compatible lifecycle event set.\n preToolUse: true,\n postToolUse: true,\n preCompact: true,\n sessionStart: true,\n sessionEnd: true,\n userPromptSubmit: true,\n stop: true,\n notification: true,\n // Newer events — Copilot CLI has native analogs for all four:\n // permissionRequest (decision control), postToolUseFailure (recovery\n // guidance), subagentStart (context-only), subagentStop (blockable).\n permissionRequest: true,\n postToolUseFailure: true,\n subagentStart: true,\n subagentStop: true,\n // PreToolUse is fail-closed and can rewrite tool input (updatedInput); a\n // PostToolUse hook cannot rewrite already-emitted tool output.\n canModifyArgs: true,\n canModifyOutput: false,\n canInjectSessionContext: true,\n // Copilot CLI's mcp-config.json `type` accepts stdio (written \"local\"),\n // http (Streamable HTTP), and sse (legacy) — per GitHub's add-mcp-servers docs.\n transports: [\"stdio\", \"http\", \"sse\"],\n // Content surfaces: Copilot CLI exposes skills + subagents, but has no\n // prompt-file command surface, so commands stay false (inherits BaseAdapter\n // skip/warn).\n supportsCommands: false,\n supportsSkills: true,\n supportsSubagents: true,\n // Native passthrough: Copilot CLI documents an `errorOccurred` lifecycle\n // event (plus camelCase aliases) with NO canonical HookEventName analog —\n // below the >=3-host core bar (docs/research/host-specific-hook-events-design.md).\n // A connector reaches it via platforms[\"copilot-cli\"].nativeHooks; installHooks\n // files the event-name key VERBATIM with the same home-bin command shape, and\n // the generic uninstall reverses it.\n supportsNativeHooks: true,\n };\n\n // ── Detection ────────────────────────────────────────────────────────────\n\n detectInstalled(_projectDir: string): DetectedPlatform {\n const userDir = join(homedir(), \".copilot\");\n const mcpConfig = join(userDir, \"mcp-config.json\");\n const hooksDir = join(userDir, \"hooks\");\n const installed =\n existsSync(userDir) || existsSync(mcpConfig) || existsSync(hooksDir);\n return {\n id: this.id,\n name: this.name,\n installed,\n paradigm: this.paradigm,\n capabilities: this.capabilities,\n configPath: mcpConfig,\n scope: \"user\",\n reason: installed\n ? `found GitHub Copilot CLI config under ${userDir}`\n : `no GitHub Copilot CLI config at ${userDir}`,\n confidence: installed ? \"high\" : \"low\",\n };\n }\n\n // ── Memory surface: user-scope global instructions file ─────────────────\n // Project scope stays on the AGENTS.md base default (root AGENTS.md is the\n // primary instructions file). User scope targets Copilot CLI's documented\n // $HOME/.copilot/copilot-instructions.md — a markdown file shared with other\n // writers, so the managed block (not whole-file ownership) applies as usual.\n protected override memoryTargets(ctx: InstallContext): MemoryTarget[] {\n if (this.memoryOverride(ctx)?.path || ctx.scope !== \"user\") {\n return super.memoryTargets(ctx);\n }\n return [\n {\n path: join(homedir(), \".copilot\", \"copilot-instructions.md\"),\n reason: \"copilot-cli global instructions (~/.copilot/copilot-instructions.md)\",\n },\n ];\n }\n\n // ── Native paths ─────────────────────────────────────────────────────────\n\n /** Copilot CLI is user/global only — scope is ignored. */\n getConfigDir(_ctx: InstallContext): string {\n return join(homedir(), \".copilot\");\n }\n\n getServerConfigPath(ctx: InstallContext): string {\n return join(this.getConfigDir(ctx), \"mcp-config.json\");\n }\n\n /**\n * Copilot CLI discovers hooks from any `~/.copilot/hooks/*.json`. We write a\n * single dedicated file so we never disturb the user's own hook files and\n * uninstall is a clean, scoped operation.\n */\n getHookConfigPath(ctx: InstallContext): string {\n return join(this.getConfigDir(ctx), \"hooks\", \"agent-connector.json\");\n }\n\n // ── MCP server install / uninstall ───────────────────────────────────────\n\n installServer(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n const override = connector.platforms[HOST]?.server;\n if (!connector.server || override === false) {\n return [\n {\n platform: this.id,\n action: \"skip\",\n detail: connector.server\n ? \"server registration disabled for copilot-cli\"\n : \"connector declares no MCP server\",\n },\n ];\n }\n\n // Shallow-merge any per-platform server override into the base ServerDef.\n const server: ServerDef =\n override && typeof override === \"object\"\n ? { ...connector.server, ...override }\n : connector.server;\n\n const serverPath = this.getServerConfigPath(ctx);\n const entry = this.renderServerEntry(ctx, server);\n\n return [\n this.upsertServerInJson(serverPath, MCP_ROOT_KEY, connector.id, entry, ctx.dryRun),\n ];\n }\n\n uninstallServer(ctx: InstallContext): ChangeRecord[] {\n const serverPath = this.getServerConfigPath(ctx);\n return [\n this.removeServerFromJson(serverPath, MCP_ROOT_KEY, ctx.connector.id, ctx.dryRun),\n ];\n }\n\n /** Render a normalized ServerDef into Copilot CLI's native mcpServers entry. */\n private renderServerEntry(\n ctx: InstallContext,\n server: ServerDef,\n ): CopilotLocalServer | CopilotHttpServer {\n const transport: Transport = server.transport;\n const tools = this.renderTools(server);\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 const entry: CopilotLocalServer = {\n type: \"local\",\n command: resolveEnvRefsDeep(command),\n tools,\n };\n if (args.length > 0) entry.args = args.map((a) => resolveEnvRefsDeep(a));\n const env = this.renderEnv(server.env);\n if (env) entry.env = env;\n if (server.cwd) entry.cwd = resolveEnvRefsDeep(server.cwd);\n return entry;\n }\n\n // remote (Streamable http / legacy sse) — Copilot registers a URL keyed by\n // its `type`. AC's canonical \"sse\" → \"sse\"; everything else → \"http\".\n const entry: CopilotHttpServer = {\n type: server.transport === \"sse\" ? \"sse\" : \"http\",\n url: resolveEnvRefsDeep(server.url ?? \"\"),\n tools,\n };\n const headers = this.renderEnv(server.headers);\n if (headers) entry.headers = headers;\n return entry;\n }\n\n /**\n * Render env/header values. Copilot CLI is not documented to support native\n * `${env:VAR}` interpolation in mcp-config.json, so refs resolve to literals\n * at install time (the safe default for a no-native-interp host).\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 /** Render the tool allow-list. Copilot CLI expects `tools` on every entry; default [\"*\"]. */\n private renderTools(server: ServerDef): string[] {\n const include = server.tools?.include;\n return include && include.length > 0 ? [...include] : [\"*\"];\n }\n\n // ── Hook install / uninstall ─────────────────────────────────────────────\n\n installHooks(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n const override = connector.platforms[HOST];\n const hooksDisabled = override?.hooks === false;\n // `hooks: false` disables only the NORMALIZED events; nativeHooks is a\n // sibling, copilot-cli-scoped declaration that installs regardless.\n const normalizedEvents = hooksDisabled ? [] : connector.hookEvents;\n const nativeHooks = override?.nativeHooks ?? {};\n const nativeEvents = Object.keys(nativeHooks);\n\n if (normalizedEvents.length === 0 && nativeEvents.length === 0) {\n return [\n {\n platform: this.id,\n action: \"skip\",\n detail: hooksDisabled\n ? \"hooks disabled for copilot-cli\"\n : \"connector declares no hooks\",\n },\n ];\n }\n\n const hooksPath = this.getHookConfigPath(ctx);\n const file = this.readJson<CopilotHooksFile>(hooksPath) ?? {};\n const __skip = this.malformedHookRootSkip(hooksPath, (file as Record<string, unknown>).hooks);\n if (__skip) return [__skip];\n const hooks = (file.hooks ??= {});\n\n const changes: ChangeRecord[] = [];\n let mutated = false;\n\n for (const event of normalizedEvents) {\n // CAPABILITY FILTER: an event Copilot CLI's runtime does not deliver (e.g.\n // PostCompact — postCompact unset on `capabilities`) must NOT be written as\n // a dead hook the host never fires; report a graceful warn/skip instead.\n if (this.capabilities[EVENT_CAPABILITY[event]] !== true) {\n changes.push({\n platform: this.id,\n action: \"warn\",\n path: hooksPath,\n detail: `${event} unsupported on copilot-cli — skipped`,\n });\n continue;\n }\n // PascalCase events map 1:1 to Copilot CLI's native event names.\n const copilotEvent: CopilotHookEvent = event;\n const command = buildHomeBinHookCommand(ctx.homeBinPath, HOST, event, connector.id);\n const matcher = connector.hooks[event]?.matcher ?? \"\";\n const entry: CopilotHookEntry = {\n matcher,\n hooks: [{ type: \"command\", command }],\n };\n\n const bucket = (hooks[copilotEvent] ??= []);\n const existingIdx = bucket.findIndex((e) => this.entryHasOurCommand(e, ctx));\n\n if (existingIdx >= 0) {\n if (JSON.stringify(bucket[existingIdx]) === JSON.stringify(entry)) {\n changes.push({\n platform: this.id,\n action: \"skip\",\n path: hooksPath,\n detail: `hooks.${copilotEvent} already registered`,\n });\n continue;\n }\n bucket[existingIdx] = entry;\n changes.push({\n platform: this.id,\n action: \"update\",\n path: hooksPath,\n detail: `hooks.${copilotEvent}`,\n });\n } else {\n bucket.push(entry);\n changes.push({\n platform: this.id,\n action: \"create\",\n path: hooksPath,\n detail: `hooks.${copilotEvent}`,\n });\n }\n mutated = true;\n }\n\n // NATIVE passthrough events: copilot-cli-native event-name keys (e.g.\n // ErrorOccurred) filed VERBATIM into the hooks map — no EVENT_MAP, since they\n // ARE Copilot events. The command keeps the native token; matched by EXACT\n // command so a native key coinciding with a normalized one never clobbers it.\n for (const nativeEvent of nativeEvents) {\n const command = buildHomeBinHookCommand(ctx.homeBinPath, HOST, nativeEvent, connector.id);\n const entry: CopilotHookEntry = {\n matcher: nativeHooks[nativeEvent]?.matcher ?? \"\",\n hooks: [{ type: \"command\", command }],\n };\n const bucket = (hooks[nativeEvent] ??= []);\n const existingIdx = bucket.findIndex((e) => e.hooks?.[0]?.command === command);\n if (existingIdx >= 0) {\n if (JSON.stringify(bucket[existingIdx]) === JSON.stringify(entry)) {\n changes.push({\n platform: this.id,\n action: \"skip\",\n path: hooksPath,\n detail: `hooks.${nativeEvent} (native) already registered`,\n });\n continue;\n }\n bucket[existingIdx] = entry;\n changes.push({\n platform: this.id,\n action: \"update\",\n path: hooksPath,\n detail: `hooks.${nativeEvent} (native)`,\n });\n } else {\n bucket.push(entry);\n changes.push({\n platform: this.id,\n action: \"create\",\n path: hooksPath,\n detail: `hooks.${nativeEvent} (native)`,\n });\n }\n mutated = true;\n }\n\n if (mutated) {\n file.version = COPILOT_HOOKS_VERSION;\n this.writeJson(hooksPath, file, ctx.dryRun);\n }\n return changes;\n }\n\n uninstallHooks(ctx: InstallContext): ChangeRecord[] {\n const hooksPath = this.getHookConfigPath(ctx);\n const file = this.readJson<CopilotHooksFile>(hooksPath);\n const hooks = file?.hooks;\n if (!file || !hooks) {\n return [\n {\n platform: this.id,\n action: \"skip\",\n path: hooksPath,\n detail: \"no hooks section present\",\n },\n ];\n }\n\n const changes: ChangeRecord[] = [];\n let mutated = false;\n\n for (const copilotEvent of Object.keys(hooks)) {\n const bucket = hooks[copilotEvent];\n if (!Array.isArray(bucket)) continue;\n\n // Strip our hook command from each entry; drop entries left empty so we\n // never remove another connector's (or the user's own) hook commands.\n const next: CopilotHookEntry[] = [];\n let removed = 0;\n for (const e of bucket) {\n const innerBefore = e.hooks?.length ?? 0;\n const inner = (e.hooks ?? []).filter((h) => !this.isOurCommand(h.command, ctx));\n removed += innerBefore - inner.length;\n if (inner.length > 0) next.push({ matcher: e.matcher ?? \"\", hooks: inner });\n }\n\n if (removed > 0) {\n if (next.length > 0) hooks[copilotEvent] = next;\n else delete hooks[copilotEvent];\n changes.push({\n platform: this.id,\n action: \"remove\",\n path: hooksPath,\n detail: `hooks.${copilotEvent} (${removed})`,\n });\n mutated = true;\n }\n }\n\n if (mutated) this.writeJson(hooksPath, file, ctx.dryRun);\n if (changes.length === 0) {\n changes.push({\n platform: this.id,\n action: \"skip\",\n path: hooksPath,\n detail: \"no matching hook entries\",\n });\n }\n return changes;\n }\n\n private entryHasOurCommand(entry: CopilotHookEntry, ctx: InstallContext): boolean {\n return (entry.hooks ?? []).some((h) => this.isOurCommand(h.command, ctx));\n }\n\n /** True when a hook command references our home binary AND this connector id\n * (anchored so a shared-prefix id can't collide — see isHomeBinHookCommand). */\n private isOurCommand(command: string | undefined, ctx: InstallContext): boolean {\n return isHomeBinHookCommand(command, ctx.homeBinPath, ctx.connector.id);\n }\n\n // ── Content surfaces: skills / subagents ─────────────────────────────────\n // CONTENT-ONLY: pure native-file writers. No runtime dispatch, no home-bin\n // pointer, no telemetry wrap. Each method is idempotent (byte-identical →\n // skip) via BaseAdapter.writeContentFile and reversible via removeContentFile.\n // Honors platforms[\"copilot-cli\"] per-surface false to skip. Commands are\n // unsupported here — they inherit the BaseAdapter skip/warn default.\n //\n // Path scoping: user scope lives under ~/.copilot (getConfigDir); project\n // scope lives under the shared <projectDir>/.github tree (the same files\n // vscode-copilot / jetbrains-copilot would write). We write identical content\n // and on uninstall remove only the files this connector wrote.\n\n /** Root dir for content surfaces: ~/.copilot (user) or <projectDir>/.github (project). */\n private contentDir(ctx: InstallContext): string {\n return ctx.scope === \"project\"\n ? join(ctx.projectDir, \".github\")\n : this.getConfigDir(ctx);\n }\n\n private skillsDir(ctx: InstallContext): string {\n return join(this.contentDir(ctx), \"skills\");\n }\n private agentsDir(ctx: InstallContext): string {\n return join(this.contentDir(ctx), \"agents\");\n }\n\n /** Native skill dir: <contentDir>/skills/<name>. */\n private skillDir(ctx: InstallContext, name: string): string {\n return join(this.skillsDir(ctx), name);\n }\n /** Native subagent file path: <contentDir>/agents/<name>.agent.md. */\n private subagentPath(ctx: InstallContext, name: string): string {\n return join(this.agentsDir(ctx), `${name}.agent.md`);\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 copilot-cli\" }];\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 copilot-cli\" }];\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 renderSubagentMd(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 // ── Diagnostics ──────────────────────────────────────────────────────────\n\n override getHealthChecks(ctx: InstallContext): readonly HealthCheck[] {\n const mcpPath = this.getServerConfigPath(ctx);\n const hooksPath = this.getHookConfigPath(ctx);\n const connectorId = ctx.connector.id;\n const homeBin = ctx.homeBinPath;\n const hookEvents = ctx.connector.hookEvents;\n const checks: HealthCheck[] = [\n {\n name: `${this.name}: mcp-config.json present`,\n check: () =>\n existsSync(mcpPath)\n ? { status: \"OK\", detail: mcpPath }\n : { status: \"FAIL\", detail: `not found: ${mcpPath}` },\n },\n {\n name: `${this.name}: hook command registered`,\n check: () => {\n if (hookEvents.length === 0) {\n return { status: \"OK\", detail: \"no hooks declared\" };\n }\n const file = this.readJson<CopilotHooksFile>(hooksPath);\n if (!file) return { status: \"FAIL\", detail: `cannot read ${hooksPath}` };\n const hooks = file.hooks ?? {};\n const registered = Object.values(hooks).some((entries) =>\n (entries ?? []).some((e) =>\n (e.hooks ?? []).some((h) =>\n isHomeBinHookCommand(h.command, homeBin, connectorId),\n ),\n ),\n );\n return registered\n ? { status: \"OK\", detail: \"hook command present\" }\n : { status: \"FAIL\", detail: `no hook for ${connectorId} in ${hooksPath}` };\n },\n },\n ];\n\n // Content-surface checks: only assert presence of the surfaces this\n // connector declares (skip silently for surfaces it never asked for).\n // Commands are unsupported on Copilot CLI, so no command check.\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 // ── Runtime: parse Copilot CLI stdin JSON → normalized event ─────────────\n\n parseEvent(event: HookEventName, raw: unknown): NormalizedEvent {\n const input = (raw ?? {}) as CopilotWireInput;\n const connectorId = typeof input.connector === \"string\" ? input.connector : \"\";\n const sessionId = extractSessionId(input);\n const projectDir = typeof input.cwd === \"string\" ? input.cwd : undefined;\n\n const base = {\n hostPlatform: HOST,\n connectorId,\n sessionId,\n raw,\n ...(projectDir !== undefined ? { projectDir } : {}),\n } as const;\n\n switch (event) {\n case \"PreToolUse\": {\n const ev: PreToolUseEvent = {\n ...base,\n toolName: input.tool_name ?? \"\",\n toolInput: input.tool_input ?? {},\n };\n return ev;\n }\n case \"PostToolUse\": {\n // PostToolUse fires success-only and carries the result under\n // `tool_result.text_result_for_llm` (VS Code dialect). Failures arrive\n // via the separate PostToolUseFailure event, so isError is never set\n // here (hooks-reference.md:219,397-400).\n const toolOutput = input.tool_result?.text_result_for_llm;\n const ev: PostToolUseEvent = {\n ...base,\n toolName: input.tool_name ?? \"\",\n toolInput: input.tool_input ?? {},\n ...(typeof toolOutput === \"string\" ? { toolOutput } : {}),\n };\n return ev;\n }\n case \"SessionStart\": {\n const ev: SessionStartEvent = {\n ...base,\n source: normalizeSessionSource(input.source),\n };\n return ev;\n }\n case \"SessionEnd\": {\n const ev: SessionEndEvent = {\n ...base,\n ...(typeof input.reason === \"string\" ? { reason: input.reason } : {}),\n };\n return ev;\n }\n case \"UserPromptSubmit\": {\n const ev: UserPromptSubmitEvent = {\n ...base,\n prompt: typeof input.prompt === \"string\" ? input.prompt : \"\",\n };\n return ev;\n }\n case \"PreCompact\": {\n const ev: PreCompactEvent = {\n ...base,\n ...(input.trigger === \"auto\" || input.trigger === \"manual\"\n ? { trigger: input.trigger }\n : {}),\n };\n return ev;\n }\n case \"PostCompact\": {\n // Copilot CLI does not fire PostCompact natively (postCompact unset →\n // warn-skip at install). Parsed defensively, mirroring PreCompact, so a\n // manual/mis-routed dispatch normalizes instead of hitting the guard.\n const ev: PostCompactEvent = {\n ...base,\n ...(input.trigger === \"auto\" || input.trigger === \"manual\"\n ? { trigger: input.trigger }\n : {}),\n };\n return ev;\n }\n case \"Stop\": {\n // The host signals completion via stop_reason:\"end_turn\", not the\n // stopHookActive loop-guard boolean, so nothing maps onto StopEvent\n // beyond base (hooks-reference.md:449-457).\n const ev: StopEvent = { ...base };\n return ev;\n }\n case \"Notification\": {\n const ev: NotificationEvent = {\n ...base,\n message: typeof input.message === \"string\" ? input.message : \"\",\n };\n return ev;\n }\n case \"PermissionRequest\": {\n // permissionRequest uses the PreToolUse shape (tool_name + tool_input\n // only); the host emits no permission_suggestions payload\n // (hooks-reference.md:218,627-649).\n const ev: PermissionRequestEvent = {\n ...base,\n toolName: input.tool_name ?? \"\",\n toolInput: input.tool_input ?? {},\n };\n return ev;\n }\n case \"PostToolUseFailure\": {\n // Host payload is {tool_name, tool_input, error} + base; it carries no\n // tool_use_id / is_interrupt / duration_ms correlation fields\n // (hooks-reference.md:421-430).\n const ev: PostToolUseFailureEvent = {\n ...base,\n toolName: input.tool_name ?? \"\",\n toolInput: input.tool_input ?? {},\n error: typeof input.error === \"string\" ? input.error : \"\",\n };\n return ev;\n }\n case \"SubagentStart\": {\n // The host's subagent identity field is `agent_name`; there is no\n // agent_id or agent_type (agent_display_name is a human label, not a\n // type), so agentType stays unset (hooks-reference.md:467-476).\n const ev: SubagentStartEvent = {\n ...base,\n ...(typeof input.agent_name === \"string\" ? { agentId: input.agent_name } : {}),\n };\n return ev;\n }\n case \"SubagentStop\": {\n // VS Code dialect: identity is `agent_name`, the subagent transcript is\n // the BASE `transcript_path` (not agent_transcript_path), and there is\n // no agent_type / last_assistant_message / stop_hook_active — the final\n // response is reachable only via transcript_path, and completion is\n // signalled by stop_reason (hooks-reference.md:497-507).\n const ev: SubagentStopEvent = {\n ...base,\n ...(typeof input.agent_name === \"string\" ? { agentId: input.agent_name } : {}),\n ...(typeof input.transcript_path === \"string\"\n ? { agentTranscriptPath: input.transcript_path }\n : {}),\n };\n return ev;\n }\n default: {\n // Exhaustive guard — every HookEventName is handled above.\n const _never: never = event;\n throw new Error(`unsupported copilot-cli hook event: ${String(_never)}`);\n }\n }\n }\n\n // ── Runtime: normalized response → Copilot CLI native hook reply ─────────\n\n formatReply(event: HookEventName, response: HookResponse): HookReply {\n const hookEventName = event;\n const decision = response.decision ?? \"allow\";\n\n // PermissionRequest replies use the Claude-compatible nested\n // decision{behavior} envelope and are the ONE event where an EXPLICIT\n // \"allow\" is an ACTIVE grant (it suppresses the permission dialog) rather\n // than passthrough:\n // allow → decision{behavior:\"allow\"} (+updatedInput when set);\n // the host still enforces its own deny rules.\n // modify → an allow grant carrying updatedInput.\n // deny → decision{behavior:\"deny\", message}.\n // ask/context/void → NO decision output: fall through to the native\n // dialog (the dialog IS the ask).\n if (event === \"PermissionRequest\") {\n if (response.decision === \"deny\") {\n return this.stdout({\n hookSpecificOutput: {\n hookEventName,\n decision: {\n behavior: \"deny\",\n message: response.reason ?? \"Blocked by hook\",\n },\n },\n });\n }\n if (\n response.decision === \"allow\" ||\n (response.decision === \"modify\" && response.updatedInput)\n ) {\n return this.stdout({\n hookSpecificOutput: {\n hookEventName,\n decision: {\n behavior: \"allow\",\n ...(response.updatedInput\n ? { updatedInput: response.updatedInput }\n : {}),\n },\n },\n });\n }\n return { exitCode: 0 };\n }\n\n // PostToolUseFailure (recovery guidance beside the error) and SubagentStart\n // (context prepended to the SUBAGENT's conversation — creation is not\n // blockable on Copilot CLI) are observe/context-only: \"context\" emits\n // additionalContext, and a \"deny\" DEGRADES to the same shape carrying the\n // reason. Everything else passes through.\n if (event === \"PostToolUseFailure\" || event === \"SubagentStart\") {\n const context =\n decision === \"context\"\n ? response.additionalContext\n : decision === \"deny\"\n ? response.reason ?? response.additionalContext\n : undefined;\n if (context) {\n return this.stdout({\n hookSpecificOutput: { hookEventName, additionalContext: context },\n });\n }\n return { exitCode: 0 };\n }\n\n // deny → block the action with a reason (exit 0; JSON carries the decision).\n // SubagentStop is the Stop-semantics exception: like Claude, the block is\n // the TOP-LEVEL {\"decision\":\"block\",\"reason\"} — it keeps the subagent\n // running with `reason` as its next instruction (the host \"can block and\n // force continuation\").\n if (decision === \"deny\") {\n if (event === \"SubagentStop\") {\n return this.stdout({\n decision: \"block\",\n reason: response.reason ?? \"Blocked by hook\",\n });\n }\n return this.stdout({\n hookSpecificOutput: {\n hookEventName,\n permissionDecision: \"deny\",\n permissionDecisionReason: response.reason ?? \"Blocked by hook\",\n },\n });\n }\n\n // ask → prompt the user to confirm.\n if (decision === \"ask\") {\n return this.stdout({\n hookSpecificOutput: {\n hookEventName,\n permissionDecision: \"ask\",\n permissionDecisionReason: response.reason ?? \"Confirmation required by hook\",\n },\n });\n }\n\n // modify → rewrite PreToolUse input (only where Copilot CLI supports it).\n if (decision === \"modify\") {\n if (event === \"PreToolUse\" && response.updatedInput) {\n return this.stdout({\n hookSpecificOutput: { hookEventName, updatedInput: response.updatedInput },\n });\n }\n // Output rewrite is unsupported on Copilot CLI; fall through to allow.\n }\n\n // context → inject soft guidance (also the SessionStart context path).\n if (decision === \"context\" && response.additionalContext) {\n return this.stdout({\n hookSpecificOutput: { hookEventName, additionalContext: response.additionalContext },\n });\n }\n\n // allow / void / unsupported-degradation → pass through with exit 0.\n return { exitCode: 0 };\n }\n\n private stdout(payload: unknown): HookReply {\n return { exitCode: 0, stdout: JSON.stringify(payload) };\n }\n}\n\n/**\n * Extract a stable session id from a Copilot CLI wire payload.\n * Priority mirrors the Claude wire protocol: transcript UUID > session_id > \"\".\n */\nfunction extractSessionId(input: CopilotWireInput): string {\n if (typeof input.transcript_path === \"string\") {\n const m = input.transcript_path.match(/([a-f0-9-]{36})\\.jsonl$/);\n if (m && m[1]) return m[1];\n }\n if (typeof input.session_id === \"string\" && input.session_id !== \"\") {\n return input.session_id;\n }\n return \"\";\n}\n\nexport const adapter = new CopilotCliAdapter();\nexport default adapter;\n"],"mappings":"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","names":["entry"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/adapters/crush/index.ts"],"sourcesContent":["/**\n * adapters/crush — Crush (Charm) platform adapter for agent-connector.\n *\n * Crush is a json-stdio host. A single JSON config file holds BOTH the MCP\n * server registrations and the hook registrations, and agent-connector MERGES\n * into it (never replaces it — unrelated keys are preserved verbatim):\n * - User scope: ~/.config/crush/crush.json\n * (Windows: %LOCALAPPDATA%\\crush\\crush.json)\n * - Project scope: ./.crush.json (preferred) or ./crush.json\n *\n * MCP servers live under the ROOT KEY \"mcp\" (NOT \"mcpServers\"). A stdio entry is\n * { type:\"stdio\", command, args, env, timeout:120, disabled:false }.\n * Hooks live under the top-level \"hooks\" key. Crush supports PreToolUse ONLY;\n * the hook reads the host's JSON on stdin and writes a JSON object on stdout\n * carrying a `decision` field. A deny is `{ decision:\"deny\", reason }` on\n * stdout (exit 0); an allow is an empty stdout (exit 0). Crush cannot rewrite\n * tool args/output nor inject session context — every non-deny decision (and\n * every non-PreToolUse event) degrades to a silent allow.\n *\n * SECURITY NOTE: Crush expands `$(...)` command substitution in its config file\n * at load time. We therefore NEVER emit shell-substitution syntax into the\n * command/args/env we write — every value is a literal path/string built by the\n * spawn helpers (which quote, not interpolate). Connector ids are kebab-case and\n * the home-bin path is an absolute literal, so nothing we write can be coerced\n * into a `$(...)` substitution.\n */\n\nimport { existsSync, statSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\n\nimport { BaseAdapter } from \"../base.js\";\nimport type { Adapter, HookReply, InstallContext, NormalizedEvent } from \"../spi.js\";\nimport type {\n ChangeRecord,\n DetectedPlatform,\n HealthCheck,\n HookEventName,\n HookParadigm,\n HookResponse,\n PlatformCapabilities,\n PlatformId,\n PreToolUseEvent,\n ServerDef,\n Transport,\n} from \"../../core/types.js\";\nimport { resolveEnvRefsDeep } from \"../../core/interpolate.js\";\nimport { localAppData, xdgConfigHome } from \"../../core/host-paths.js\";\nimport {\n buildHomeBinHookCommand,\n buildWrappedStdio,\n isHomeBinHookCommand,\n} from \"../../core/spawn.js\";\nimport { renderSkillMd } from \"../claude-code/render.js\";\n\nconst HOST: PlatformId = \"crush\";\n/** Crush registers MCP servers under \"mcp\" — NOT the \"mcpServers\" of Claude/Gemini. */\nconst MCP_ROOT_KEY = \"mcp\";\n/** Default per-server timeout (seconds) Crush expects on a stdio entry. */\nconst STDIO_TIMEOUT_SECONDS = 120;\n\n/**\n * Crush hook events agent-connector can register. Crush honors PreToolUse ONLY,\n * and only its deny decision is meaningful; every other normalized event has no\n * Crush equivalent and is skipped at install time.\n */\nconst CRUSH_HOOK_EVENTS = [\"PreToolUse\"] as const;\ntype CrushHookEventName = (typeof CRUSH_HOOK_EVENTS)[number];\n\n/**\n * Newer canonical events with NO Crush analog: there is no permission-dialog,\n * tool-failure, or subagent lifecycle hook. Declared hooks for these warn-skip\n * at install so the degradation is reported, never silent. (The legacy silent\n * drop of the other unwired events — SessionStart, Stop, … — predates this\n * convention and is deliberately left untouched.)\n */\nconst WARN_SKIP_EVENTS: ReadonlySet<HookEventName> = new Set([\n \"PermissionRequest\",\n \"PostToolUseFailure\",\n \"SubagentStart\",\n \"SubagentStop\",\n]);\n\n// ─────────────────────────────────────────────────────────────────────────\n// Native config shapes (only the parts we touch; rest preserved verbatim)\n// ─────────────────────────────────────────────────────────────────────────\n\n/** One hook registration entry as Crush stores it under top-level \"hooks\". */\ninterface CrushHookEntry {\n matcher?: string;\n command: string;\n [key: string]: unknown;\n}\n\n/** Crush's crush.json shape — only the keys we read/merge. */\ninterface CrushConfigFile {\n mcp?: Record<string, unknown>;\n hooks?: Record<string, CrushHookEntry[]>;\n [key: string]: unknown;\n}\n\n/** Native stdio MCP server entry under \"mcp\". */\ninterface CrushStdioServer {\n type: \"stdio\";\n command: string;\n args: string[];\n env?: Record<string, string>;\n timeout: number;\n disabled: boolean;\n}\n\n/** Native HTTP MCP server entry under \"mcp\". */\ninterface CrushHttpServer {\n type: \"http\";\n url: string;\n headers?: Record<string, string>;\n timeout: number;\n disabled: boolean;\n}\n\n/** Raw Crush hook stdin payload (Claude-style: PascalCase event, snake_case fields). */\ninterface CrushHookInput {\n tool_name?: string;\n tool_input?: Record<string, unknown>;\n session_id?: string;\n cwd?: string;\n hook_event_name?: string;\n connector?: unknown;\n}\n\nexport class CrushAdapter extends BaseAdapter implements Adapter {\n readonly id: PlatformId = HOST;\n readonly name = \"Crush\";\n readonly paradigm: HookParadigm = \"json-stdio\";\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 deny is the only hook decision Crush honors.\n preToolUse: true,\n postToolUse: false,\n preCompact: false,\n sessionStart: false,\n sessionEnd: false,\n userPromptSubmit: false,\n stop: false,\n notification: false,\n // Newer events: Crush honors PreToolUse ONLY — no permission-dialog,\n // tool-failure, or subagent lifecycle events exist, so permissionRequest /\n // postToolUseFailure / subagentStart / subagentStop stay unset — install\n // reports the standard skip-warn for them.\n // Crush is deny-only: it cannot rewrite tool args/output nor inject context.\n canModifyArgs: false,\n canModifyOutput: false,\n canInjectSessionContext: false,\n transports: [\"stdio\", \"http\"],\n // Content surface: Crush auto-discovers Agent-Skills dirs (dir-per-skill\n // SKILL.md). Paths are HARD-CODED — no crush.json entry needed\n // (charmbracelet/crush internal/config/load.go GlobalSkillsDirs +\n // ProjectSkillsDir, fetched 2026-06-16):\n // project → <projectDir>/.crush/skills/<name>/SKILL.md (crush-native, in\n // projectSkillSubdirs; preferred over .agents/.claude/.cursor)\n // user → ~/.config/crush/skills/<name>/SKILL.md (home.Config()/crush/\n // skills; XDG_CONFIG_HOME or ~/.config).\n supportsSkills: true,\n };\n\n // ── Detection ────────────────────────────────────────────────────────────\n\n detectInstalled(projectDir: string): DetectedPlatform {\n const userDir = this.userConfigDir();\n const userConfig = join(userDir, \"crush.json\");\n const projectDot = join(projectDir, \".crush.json\");\n const projectBare = join(projectDir, \"crush.json\");\n const userInstalled = existsSync(userDir) || existsSync(userConfig);\n const projInstalled = existsSync(projectDot) || existsSync(projectBare);\n const installed = userInstalled || projInstalled;\n // Report the scope/path that actually matched so a project-only install is\n // not misreported as a (non-existent) user install.\n const scope = projInstalled && !userInstalled ? \"project\" : \"user\";\n const projectPath = existsSync(projectBare) && !existsSync(projectDot) ? projectBare : projectDot;\n const configPath = scope === \"project\" ? projectPath : userConfig;\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 Crush config at ${configPath}`\n : `found Crush config under ${userDir}`\n : `no Crush config at ${userConfig}`,\n confidence: installed ? \"high\" : \"low\",\n };\n }\n\n // ── Native paths ─────────────────────────────────────────────────────────\n\n getConfigDir(ctx: InstallContext): string {\n return ctx.scope === \"project\" ? ctx.projectDir : this.userConfigDir();\n }\n\n /** MCP servers and hooks share ONE crush.json file. */\n getServerConfigPath(ctx: InstallContext): string {\n if (ctx.scope === \"project\") {\n // Prefer ./.crush.json, but MERGE into an existing ./crush.json if that is\n // the file already present (so we don't fork the user's config in two).\n const dot = join(ctx.projectDir, \".crush.json\");\n const bare = join(ctx.projectDir, \"crush.json\");\n if (existsSync(bare) && !existsSync(dot)) return bare;\n return dot;\n }\n return join(this.userConfigDir(), \"crush.json\");\n }\n\n /** Hooks live in the SAME crush.json under the top-level \"hooks\" key. */\n getHookConfigPath(ctx: InstallContext): string {\n return this.getServerConfigPath(ctx);\n }\n\n /**\n * Crush's user config dir, mirroring its own `home.Config()` resolution\n * (charmbracelet/crush internal/home/home.go: `cmp.Or(XDG_CONFIG_HOME, ~/.config)`):\n * - Windows: %LOCALAPPDATA%\\crush (Local; falls back to AppData/Local)\n * - macOS / Linux: $XDG_CONFIG_HOME/crush or ~/.config/crush\n * (crush honors $XDG_CONFIG_HOME on Linux/macOS; the `xdgConfigHome()` helper\n * is byte-identical to ~/.config when XDG is unset.)\n */\n private userConfigDir(): string {\n if (process.platform === \"win32\") {\n return join(localAppData(), \"crush\");\n }\n return join(xdgConfigHome(), \"crush\");\n }\n\n // ── MCP server install / uninstall (crush.json → mcp.<id>) ───────────────\n\n installServer(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n const override = connector.platforms[HOST]?.server;\n if (!connector.server || override === false) {\n return [\n {\n platform: this.id,\n action: \"skip\",\n detail: connector.server\n ? \"server registration disabled for crush\"\n : \"connector declares no MCP server\",\n },\n ];\n }\n\n // Shallow-merge any per-platform server override into the base ServerDef.\n const server: ServerDef =\n override && typeof override === \"object\"\n ? { ...connector.server, ...override }\n : connector.server;\n\n const serverPath = this.getServerConfigPath(ctx);\n const entry = this.renderServerEntry(ctx, server);\n\n return [\n this.upsertServerInJson(serverPath, MCP_ROOT_KEY, connector.id, entry, ctx.dryRun),\n ];\n }\n\n uninstallServer(ctx: InstallContext): ChangeRecord[] {\n const serverPath = this.getServerConfigPath(ctx);\n return [\n this.removeServerFromJson(serverPath, MCP_ROOT_KEY, ctx.connector.id, ctx.dryRun),\n ];\n }\n\n /**\n * Render a normalized ServerDef into Crush's native \"mcp\" entry. Crush has no\n * documented native `${env:VAR}` interpolation — and it expands `$(...)` at\n * load time — so refs are resolved to LITERALS at install time (the safe\n * posture for a host without native interpolation, matching Codex/Kimi).\n */\n private renderServerEntry(\n ctx: InstallContext,\n server: ServerDef,\n ): CrushStdioServer | CrushHttpServer {\n const transport: Transport = server.transport;\n const disabled = server.enabled === false;\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 // Resolve to literals — never emit `$(...)` Crush would expand at load.\n command = resolveEnvRefsDeep(command);\n args = resolveEnvRefsDeep(args);\n\n const entry: CrushStdioServer = {\n type: \"stdio\",\n command,\n args,\n timeout: STDIO_TIMEOUT_SECONDS,\n disabled,\n };\n const env = this.renderEnv(server.env);\n if (env) entry.env = env;\n return entry;\n }\n\n // http (and any other remote transport we surface) — Crush registers a URL.\n const entry: CrushHttpServer = {\n type: \"http\",\n url: resolveEnvRefsDeep(server.url ?? \"\"),\n timeout: STDIO_TIMEOUT_SECONDS,\n disabled,\n };\n const headers = this.renderEnv(server.headers);\n if (headers) entry.headers = headers;\n return entry;\n }\n\n /** Resolve env/header values to literals (no native interpolation on Crush). */\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 const out: Record<string, string> = {};\n for (const [k, v] of Object.entries(resolveEnvRefsDeep({ ...env }))) {\n out[k] = String(v);\n }\n return out;\n }\n\n // ── Hook install / uninstall (crush.json → hooks.PreToolUse[]) ───────────\n\n installHooks(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n if (connector.platforms[HOST]?.hooks === false) {\n return [{ platform: this.id, action: \"skip\", detail: \"hooks disabled for crush\" }];\n }\n\n const events = this.effectiveHookEvents(ctx);\n const dropped = this.warnSkipHookEvents(ctx);\n const path = this.getHookConfigPath(ctx);\n\n if (events.length === 0 && dropped.length === 0) {\n return [{ platform: this.id, action: \"skip\", path, detail: \"no hooks declared\" }];\n }\n\n const cfg = this.readJson<CrushConfigFile>(path) ?? {};\n const __skip = this.malformedHookRootSkip(path, (cfg as Record<string, unknown>).hooks);\n if (__skip) return [__skip];\n const hooks = (cfg.hooks ??= {});\n\n const changes: ChangeRecord[] = [];\n let mutated = false;\n\n // Declared events Crush cannot fire are reported, never silently dropped.\n for (const event of dropped) {\n changes.push({\n platform: this.id,\n action: \"warn\",\n path,\n detail: `${event} has no Crush hook equivalent — skipped`,\n });\n }\n\n for (const event of events) {\n const command = buildHomeBinHookCommand(ctx.homeBinPath, HOST, event, connector.id);\n const matcher = connector.hooks[event]?.matcher ?? \"\";\n const entry: CrushHookEntry = { matcher, command };\n\n const bucket = (hooks[event] ??= []);\n const existingIdx = bucket.findIndex((e) => this.isOurHook(e, ctx));\n\n if (existingIdx >= 0) {\n if (JSON.stringify(bucket[existingIdx]) === JSON.stringify(entry)) {\n changes.push({\n platform: this.id,\n action: \"skip\",\n path,\n detail: `hooks.${event} already registered`,\n });\n continue;\n }\n bucket[existingIdx] = entry;\n changes.push({ platform: this.id, action: \"update\", path, detail: `hooks.${event}` });\n } else {\n bucket.push(entry);\n changes.push({ platform: this.id, action: \"create\", path, detail: `hooks.${event}` });\n }\n mutated = true;\n }\n\n if (mutated) this.writeJson(path, cfg, ctx.dryRun);\n return changes;\n }\n\n uninstallHooks(ctx: InstallContext): ChangeRecord[] {\n const path = this.getHookConfigPath(ctx);\n const cfg = this.readJson<CrushConfigFile>(path);\n const hooks = cfg?.hooks;\n if (!cfg || !hooks) {\n return [\n { platform: this.id, action: \"skip\", path, detail: \"no hooks section present\" },\n ];\n }\n\n const changes: ChangeRecord[] = [];\n let mutated = false;\n\n for (const event of Object.keys(hooks)) {\n const bucket = hooks[event];\n if (!Array.isArray(bucket)) continue;\n\n // Keep every entry that is NOT ours (anchored match) so a shared-prefix\n // connector id — or the user's own hook — is never stripped.\n const kept = bucket.filter((e) => !this.isOurHook(e, ctx));\n const removed = bucket.length - kept.length;\n if (removed > 0) {\n if (kept.length > 0) hooks[event] = kept;\n else delete hooks[event];\n changes.push({\n platform: this.id,\n action: \"remove\",\n path,\n detail: `hooks.${event} (${removed})`,\n });\n mutated = true;\n }\n }\n\n if (mutated) this.writeJson(path, cfg, ctx.dryRun);\n if (changes.length === 0) {\n changes.push({\n platform: this.id,\n action: \"skip\",\n path,\n detail: \"no matching hook entries\",\n });\n }\n return changes;\n }\n\n // ── Internal helpers ─────────────────────────────────────────────────────\n\n /** Which canonical hook events to register for Crush, honoring overrides. */\n private effectiveHookEvents(ctx: InstallContext): CrushHookEventName[] {\n if (ctx.connector.platforms[HOST]?.hooks === false) return [];\n return CRUSH_HOOK_EVENTS.filter((e) => ctx.connector.hookEvents.includes(e));\n }\n\n /** Declared events Crush has no analog for — install reports a warn-skip. */\n private warnSkipHookEvents(ctx: InstallContext): HookEventName[] {\n if (ctx.connector.platforms[HOST]?.hooks === false) return [];\n return ctx.connector.hookEvents.filter((e) => WARN_SKIP_EVENTS.has(e));\n }\n\n /**\n * Does this hook entry belong to this connector? Anchored on the home-bin +\n * connector-id token (isHomeBinHookCommand) so uninstalling a shared-prefix\n * connector id never strips a sibling's hook.\n */\n private isOurHook(entry: CrushHookEntry | undefined, ctx: InstallContext): boolean {\n if (!entry || typeof entry !== \"object\") return false;\n return isHomeBinHookCommand(entry.command, ctx.homeBinPath, ctx.connector.id);\n }\n\n // ── Content surface: skills (dir-per-skill SKILL.md) ─────────────────────\n // CONTENT-ONLY: pure native-file writers, mirroring goose/openclaw. No\n // runtime dispatch, no home-bin pointer, no telemetry wrap. Each write is\n // idempotent (byte-identical → skip) via writeContentFile and reversible via\n // removeContentFile + removeDirIfEmpty (never rm -rf a shared dir). Honors\n // platforms[\"crush\"].skills === false. No crush.json entry is written — Crush\n // auto-discovers these hard-coded dirs (load.go GlobalSkillsDirs/ProjectSkillsDir).\n //\n // Native locations (Agent-Skills spec — dir-per-skill SKILL.md + resources):\n // project → <projectDir>/.crush/skills/<name>/SKILL.md\n // user → ~/.config/crush/skills/<name>/SKILL.md\n\n /** The skills ROOT dir for ctx.scope (parent of every per-skill dir). */\n private skillsDir(ctx: InstallContext): string {\n return ctx.scope === \"project\"\n ? join(ctx.projectDir, \".crush\", \"skills\")\n : join(this.userConfigDir(), \"skills\");\n }\n\n /** Per-skill directory: <skillsDir>/<name>. */\n private skillDir(ctx: InstallContext, name: string): string {\n return join(this.skillsDir(ctx), name);\n }\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 crush\" }];\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 // Guard a skills path occupied by a regular FILE (would throw ENOTDIR on\n // mkdir): skip-warn rather than crash (the cline `.clinerules`-is-a-file\n // precedent). The per-skill dir or any parent up to the scope root counts.\n const blockingFile = firstFileOnPath(this.skillsDir(ctx), dir);\n if (blockingFile !== null) {\n changes.push({\n platform: this.id,\n action: \"warn\",\n path: blockingFile,\n detail: `${blockingFile} is a file, not a directory; skill \"${skill.name}\" skipped`,\n });\n continue;\n }\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 // ── Diagnostics ──────────────────────────────────────────────────────────\n\n override getHealthChecks(ctx: InstallContext): readonly HealthCheck[] {\n const configPath = this.getServerConfigPath(ctx);\n const connectorId = ctx.connector.id;\n const homeBin = ctx.homeBinPath;\n const hookEvents = this.effectiveHookEvents(ctx);\n return [\n {\n name: `${this.name}: crush.json present`,\n check: () =>\n existsSync(configPath)\n ? { status: \"OK\", detail: configPath }\n : { status: \"FAIL\", detail: `not found: ${configPath}` },\n },\n {\n name: `${this.name}: mcp.${connectorId} registered`,\n check: () => {\n if (!ctx.connector.server) return { status: \"OK\", detail: \"no MCP server declared\" };\n const cfg = this.readJson<CrushConfigFile>(configPath);\n const bucket = cfg?.[MCP_ROOT_KEY];\n const present =\n typeof bucket === \"object\" && bucket !== null && connectorId in bucket;\n return present\n ? { status: \"OK\", detail: `mcp.${connectorId}` }\n : { status: \"FAIL\", detail: `mcp.${connectorId} not found in ${configPath}` };\n },\n },\n {\n name: `${this.name}: hook command registered`,\n check: () => {\n if (hookEvents.length === 0) {\n return { status: \"OK\", detail: \"no hooks declared\" };\n }\n const cfg = this.readJson<CrushConfigFile>(configPath);\n if (!cfg) return { status: \"FAIL\", detail: `cannot read ${configPath}` };\n const hooks = cfg.hooks ?? {};\n const registered = Object.values(hooks).some((entries) =>\n (entries ?? []).some((e) => isHomeBinHookCommand(e?.command, homeBin, connectorId)),\n );\n return registered\n ? { status: \"OK\", detail: \"hook command present\" }\n : { status: \"FAIL\", detail: `no hook for ${connectorId} in ${configPath}` };\n },\n },\n ];\n }\n\n // ── Runtime: parse Crush stdin JSON → normalized event ───────────────────\n\n parseEvent(event: HookEventName, raw: unknown): NormalizedEvent {\n const input = (raw ?? {}) as CrushHookInput;\n const connectorId = typeof input.connector === \"string\" ? input.connector : \"\";\n const sessionId = typeof input.session_id === \"string\" ? input.session_id : \"\";\n const projectDir = typeof input.cwd === \"string\" ? input.cwd : undefined;\n\n const base = {\n hostPlatform: HOST,\n connectorId,\n sessionId,\n raw,\n ...(projectDir !== undefined ? { projectDir } : {}),\n } as const;\n\n if (event === \"PreToolUse\") {\n const ev: PreToolUseEvent = {\n ...base,\n toolName: input.tool_name ?? \"\",\n toolInput: input.tool_input ?? {},\n };\n return ev;\n }\n\n // Crush only ever delivers PreToolUse. Surface anything else loudly rather\n // than silently mis-parsing a payload the host cannot actually produce.\n throw new Error(`unsupported crush hook event: ${String(event)}`);\n }\n\n // ── Runtime: normalized response → Crush native hook reply ───────────────\n\n formatReply(event: HookEventName, response: HookResponse): HookReply {\n const decision = response.decision ?? \"allow\";\n\n // deny → Crush blocks the pending tool call via a stdout JSON object with a\n // `decision:\"deny\"` (+ reason). Only PreToolUse is honored; every other\n // event/decision degrades to a silent allow.\n if (decision === \"deny\" && event === \"PreToolUse\") {\n return this.stdout({\n decision: \"deny\",\n reason: response.reason ?? \"Blocked by hook\",\n });\n }\n\n // allow / modify / context / ask / unsupported → pass through (exit 0, empty\n // stdout). Crush cannot rewrite args/output or inject context, so those are\n // dropped fail-open here (the deny path above is the only fail-safe lever).\n return { exitCode: 0 };\n }\n\n private stdout(payload: unknown): HookReply {\n return { exitCode: 0, stdout: JSON.stringify(payload) };\n }\n}\n\n/**\n * Walk every path segment from `root` down to (and including) `leaf` and return\n * the FIRST one that exists as a regular file (which would make a mkdir for the\n * skill dir throw ENOTDIR), else null. Used to skip-warn instead of crashing\n * when a user has a `.crush/skills` file where we need a directory.\n */\nfunction firstFileOnPath(root: string, leaf: string): string | null {\n const segments: string[] = [];\n let cur = leaf;\n while (cur.length >= root.length) {\n segments.unshift(cur);\n if (cur === root) break;\n const parent = dirname(cur);\n if (parent === cur) break;\n cur = parent;\n }\n for (const p of segments) {\n if (!existsSync(p)) return null; // nothing planted from here down\n try {\n if (statSync(p).isFile()) return p;\n } catch {\n return null;\n }\n }\n return null;\n}\n\nexport const adapter = new CrushAdapter();\nexport default adapter;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AA2BA,SAAS,YAAY,gBAAgB;AACrC,SAAS,SAAS,YAAY;AA0B9B,IAAM,OAAmB;AAEzB,IAAM,eAAe;AAErB,IAAM,wBAAwB;AAO9B,IAAM,oBAAoB,CAAC,YAAY;AAUvC,IAAM,mBAA+C,oBAAI,IAAI;AAAA,EAC3D;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAiDM,IAAM,eAAN,cAA2B,YAA+B;AAAA,EACtD,KAAiB;AAAA,EACjB,OAAO;AAAA,EACP,WAAyB;AAAA,EAEzB,eAAqC;AAAA;AAAA;AAAA,IAG5C,gBAAgB;AAAA;AAAA,IAEhB,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,YAAY;AAAA,IACZ,cAAc;AAAA,IACd,YAAY;AAAA,IACZ,kBAAkB;AAAA,IAClB,MAAM;AAAA,IACN,cAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAMd,eAAe;AAAA,IACf,iBAAiB;AAAA,IACjB,yBAAyB;AAAA,IACzB,YAAY,CAAC,SAAS,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAS5B,gBAAgB;AAAA,EAClB;AAAA;AAAA,EAIA,gBAAgB,YAAsC;AACpD,UAAM,UAAU,KAAK,cAAc;AACnC,UAAM,aAAa,KAAK,SAAS,YAAY;AAC7C,UAAM,aAAa,KAAK,YAAY,aAAa;AACjD,UAAM,cAAc,KAAK,YAAY,YAAY;AACjD,UAAM,gBAAgB,WAAW,OAAO,KAAK,WAAW,UAAU;AAClE,UAAM,gBAAgB,WAAW,UAAU,KAAK,WAAW,WAAW;AACtE,UAAM,YAAY,iBAAiB;AAGnC,UAAM,QAAQ,iBAAiB,CAAC,gBAAgB,YAAY;AAC5D,UAAM,cAAc,WAAW,WAAW,KAAK,CAAC,WAAW,UAAU,IAAI,cAAc;AACvF,UAAM,aAAa,UAAU,YAAY,cAAc;AACvD,WAAO;AAAA,MACL,IAAI,KAAK;AAAA,MACT,MAAM,KAAK;AAAA,MACX;AAAA,MACA,UAAU,KAAK;AAAA,MACf,cAAc,KAAK;AAAA,MACnB;AAAA,MACA;AAAA,MACA,QAAQ,YACJ,UAAU,YACR,iCAAiC,UAAU,KAC3C,4BAA4B,OAAO,KACrC,sBAAsB,UAAU;AAAA,MACpC,YAAY,YAAY,SAAS;AAAA,IACnC;AAAA,EACF;AAAA;AAAA,EAIA,aAAa,KAA6B;AACxC,WAAO,IAAI,UAAU,YAAY,IAAI,aAAa,KAAK,cAAc;AAAA,EACvE;AAAA;AAAA,EAGA,oBAAoB,KAA6B;AAC/C,QAAI,IAAI,UAAU,WAAW;AAG3B,YAAM,MAAM,KAAK,IAAI,YAAY,aAAa;AAC9C,YAAM,OAAO,KAAK,IAAI,YAAY,YAAY;AAC9C,UAAI,WAAW,IAAI,KAAK,CAAC,WAAW,GAAG,EAAG,QAAO;AACjD,aAAO;AAAA,IACT;AACA,WAAO,KAAK,KAAK,cAAc,GAAG,YAAY;AAAA,EAChD;AAAA;AAAA,EAGA,kBAAkB,KAA6B;AAC7C,WAAO,KAAK,oBAAoB,GAAG;AAAA,EACrC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUQ,gBAAwB;AAC9B,QAAI,QAAQ,aAAa,SAAS;AAChC,aAAO,KAAK,aAAa,GAAG,OAAO;AAAA,IACrC;AACA,WAAO,KAAK,cAAc,GAAG,OAAO;AAAA,EACtC;AAAA;AAAA,EAIA,cAAc,KAAqC;AACjD,UAAM,EAAE,UAAU,IAAI;AACtB,UAAM,WAAW,UAAU,UAAU,IAAI,GAAG;AAC5C,QAAI,CAAC,UAAU,UAAU,aAAa,OAAO;AAC3C,aAAO;AAAA,QACL;AAAA,UACE,UAAU,KAAK;AAAA,UACf,QAAQ;AAAA,UACR,QAAQ,UAAU,SACd,2CACA;AAAA,QACN;AAAA,MACF;AAAA,IACF;AAGA,UAAM,SACJ,YAAY,OAAO,aAAa,WAC5B,EAAE,GAAG,UAAU,QAAQ,GAAG,SAAS,IACnC,UAAU;AAEhB,UAAM,aAAa,KAAK,oBAAoB,GAAG;AAC/C,UAAM,QAAQ,KAAK,kBAAkB,KAAK,MAAM;AAEhD,WAAO;AAAA,MACL,KAAK,mBAAmB,YAAY,cAAc,UAAU,IAAI,OAAO,IAAI,MAAM;AAAA,IACnF;AAAA,EACF;AAAA,EAEA,gBAAgB,KAAqC;AACnD,UAAM,aAAa,KAAK,oBAAoB,GAAG;AAC/C,WAAO;AAAA,MACL,KAAK,qBAAqB,YAAY,cAAc,IAAI,UAAU,IAAI,IAAI,MAAM;AAAA,IAClF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQQ,kBACN,KACA,QACoC;AACpC,UAAM,YAAuB,OAAO;AACpC,UAAM,WAAW,OAAO,YAAY;AAEpC,QAAI,cAAc,SAAS;AACzB,UAAI,UAAU,OAAO,WAAW;AAChC,UAAI,OAAO,CAAC,GAAI,OAAO,QAAQ,CAAC,CAAE;AAIlC,OAAC,EAAE,SAAS,KAAK,IAAI,kBAAkB,KAAK,QAAQ,KAAK,IAAI,SAAS,IAAI;AAG1E,gBAAU,mBAAmB,OAAO;AACpC,aAAO,mBAAmB,IAAI;AAE9B,YAAMA,SAA0B;AAAA,QAC9B,MAAM;AAAA,QACN;AAAA,QACA;AAAA,QACA,SAAS;AAAA,QACT;AAAA,MACF;AACA,YAAM,MAAM,KAAK,UAAU,OAAO,GAAG;AACrC,UAAI,IAAK,CAAAA,OAAM,MAAM;AACrB,aAAOA;AAAA,IACT;AAGA,UAAM,QAAyB;AAAA,MAC7B,MAAM;AAAA,MACN,KAAK,mBAAmB,OAAO,OAAO,EAAE;AAAA,MACxC,SAAS;AAAA,MACT;AAAA,IACF;AACA,UAAM,UAAU,KAAK,UAAU,OAAO,OAAO;AAC7C,QAAI,QAAS,OAAM,UAAU;AAC7B,WAAO;AAAA,EACT;AAAA;AAAA,EAGQ,UACN,KACoC;AACpC,QAAI,CAAC,OAAO,OAAO,KAAK,GAAG,EAAE,WAAW,EAAG,QAAO;AAClD,UAAM,MAA8B,CAAC;AACrC,eAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,mBAAmB,EAAE,GAAG,IAAI,CAAC,CAAC,GAAG;AACnE,UAAI,CAAC,IAAI,OAAO,CAAC;AAAA,IACnB;AACA,WAAO;AAAA,EACT;AAAA;AAAA,EAIA,aAAa,KAAqC;AAChD,UAAM,EAAE,UAAU,IAAI;AACtB,QAAI,UAAU,UAAU,IAAI,GAAG,UAAU,OAAO;AAC9C,aAAO,CAAC,EAAE,UAAU,KAAK,IAAI,QAAQ,QAAQ,QAAQ,2BAA2B,CAAC;AAAA,IACnF;AAEA,UAAM,SAAS,KAAK,oBAAoB,GAAG;AAC3C,UAAM,UAAU,KAAK,mBAAmB,GAAG;AAC3C,UAAM,OAAO,KAAK,kBAAkB,GAAG;AAEvC,QAAI,OAAO,WAAW,KAAK,QAAQ,WAAW,GAAG;AAC/C,aAAO,CAAC,EAAE,UAAU,KAAK,IAAI,QAAQ,QAAQ,MAAM,QAAQ,oBAAoB,CAAC;AAAA,IAClF;AAEA,UAAM,MAAM,KAAK,SAA0B,IAAI,KAAK,CAAC;AACrD,UAAM,SAAS,KAAK,sBAAsB,MAAO,IAAgC,KAAK;AACtF,QAAI,OAAQ,QAAO,CAAC,MAAM;AAC1B,UAAM,QAAS,IAAI,UAAU,CAAC;AAE9B,UAAM,UAA0B,CAAC;AACjC,QAAI,UAAU;AAGd,eAAW,SAAS,SAAS;AAC3B,cAAQ,KAAK;AAAA,QACX,UAAU,KAAK;AAAA,QACf,QAAQ;AAAA,QACR;AAAA,QACA,QAAQ,GAAG,KAAK;AAAA,MAClB,CAAC;AAAA,IACH;AAEA,eAAW,SAAS,QAAQ;AAC1B,YAAM,UAAU,wBAAwB,IAAI,aAAa,MAAM,OAAO,UAAU,EAAE;AAClF,YAAM,UAAU,UAAU,MAAM,KAAK,GAAG,WAAW;AACnD,YAAM,QAAwB,EAAE,SAAS,QAAQ;AAEjD,YAAM,SAAU,MAAM,KAAK,MAAM,CAAC;AAClC,YAAM,cAAc,OAAO,UAAU,CAAC,MAAM,KAAK,UAAU,GAAG,GAAG,CAAC;AAElE,UAAI,eAAe,GAAG;AACpB,YAAI,KAAK,UAAU,OAAO,WAAW,CAAC,MAAM,KAAK,UAAU,KAAK,GAAG;AACjE,kBAAQ,KAAK;AAAA,YACX,UAAU,KAAK;AAAA,YACf,QAAQ;AAAA,YACR;AAAA,YACA,QAAQ,SAAS,KAAK;AAAA,UACxB,CAAC;AACD;AAAA,QACF;AACA,eAAO,WAAW,IAAI;AACtB,gBAAQ,KAAK,EAAE,UAAU,KAAK,IAAI,QAAQ,UAAU,MAAM,QAAQ,SAAS,KAAK,GAAG,CAAC;AAAA,MACtF,OAAO;AACL,eAAO,KAAK,KAAK;AACjB,gBAAQ,KAAK,EAAE,UAAU,KAAK,IAAI,QAAQ,UAAU,MAAM,QAAQ,SAAS,KAAK,GAAG,CAAC;AAAA,MACtF;AACA,gBAAU;AAAA,IACZ;AAEA,QAAI,QAAS,MAAK,UAAU,MAAM,KAAK,IAAI,MAAM;AACjD,WAAO;AAAA,EACT;AAAA,EAEA,eAAe,KAAqC;AAClD,UAAM,OAAO,KAAK,kBAAkB,GAAG;AACvC,UAAM,MAAM,KAAK,SAA0B,IAAI;AAC/C,UAAM,QAAQ,KAAK;AACnB,QAAI,CAAC,OAAO,CAAC,OAAO;AAClB,aAAO;AAAA,QACL,EAAE,UAAU,KAAK,IAAI,QAAQ,QAAQ,MAAM,QAAQ,2BAA2B;AAAA,MAChF;AAAA,IACF;AAEA,UAAM,UAA0B,CAAC;AACjC,QAAI,UAAU;AAEd,eAAW,SAAS,OAAO,KAAK,KAAK,GAAG;AACtC,YAAM,SAAS,MAAM,KAAK;AAC1B,UAAI,CAAC,MAAM,QAAQ,MAAM,EAAG;AAI5B,YAAM,OAAO,OAAO,OAAO,CAAC,MAAM,CAAC,KAAK,UAAU,GAAG,GAAG,CAAC;AACzD,YAAM,UAAU,OAAO,SAAS,KAAK;AACrC,UAAI,UAAU,GAAG;AACf,YAAI,KAAK,SAAS,EAAG,OAAM,KAAK,IAAI;AAAA,YAC/B,QAAO,MAAM,KAAK;AACvB,gBAAQ,KAAK;AAAA,UACX,UAAU,KAAK;AAAA,UACf,QAAQ;AAAA,UACR;AAAA,UACA,QAAQ,SAAS,KAAK,KAAK,OAAO;AAAA,QACpC,CAAC;AACD,kBAAU;AAAA,MACZ;AAAA,IACF;AAEA,QAAI,QAAS,MAAK,UAAU,MAAM,KAAK,IAAI,MAAM;AACjD,QAAI,QAAQ,WAAW,GAAG;AACxB,cAAQ,KAAK;AAAA,QACX,UAAU,KAAK;AAAA,QACf,QAAQ;AAAA,QACR;AAAA,QACA,QAAQ;AAAA,MACV,CAAC;AAAA,IACH;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA,EAKQ,oBAAoB,KAA2C;AACrE,QAAI,IAAI,UAAU,UAAU,IAAI,GAAG,UAAU,MAAO,QAAO,CAAC;AAC5D,WAAO,kBAAkB,OAAO,CAAC,MAAM,IAAI,UAAU,WAAW,SAAS,CAAC,CAAC;AAAA,EAC7E;AAAA;AAAA,EAGQ,mBAAmB,KAAsC;AAC/D,QAAI,IAAI,UAAU,UAAU,IAAI,GAAG,UAAU,MAAO,QAAO,CAAC;AAC5D,WAAO,IAAI,UAAU,WAAW,OAAO,CAAC,MAAM,iBAAiB,IAAI,CAAC,CAAC;AAAA,EACvE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,UAAU,OAAmC,KAA8B;AACjF,QAAI,CAAC,SAAS,OAAO,UAAU,SAAU,QAAO;AAChD,WAAO,qBAAqB,MAAM,SAAS,IAAI,aAAa,IAAI,UAAU,EAAE;AAAA,EAC9E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeQ,UAAU,KAA6B;AAC7C,WAAO,IAAI,UAAU,YACjB,KAAK,IAAI,YAAY,UAAU,QAAQ,IACvC,KAAK,KAAK,cAAc,GAAG,QAAQ;AAAA,EACzC;AAAA;AAAA,EAGQ,SAAS,KAAqB,MAAsB;AAC1D,WAAO,KAAK,KAAK,UAAU,GAAG,GAAG,IAAI;AAAA,EACvC;AAAA,EAES,cAAc,KAAqC;AAC1D,UAAM,EAAE,UAAU,IAAI;AACtB,QAAI,UAAU,UAAU,IAAI,GAAG,WAAW,OAAO;AAC/C,aAAO,CAAC,EAAE,UAAU,KAAK,IAAI,QAAQ,QAAQ,QAAQ,4BAA4B,CAAC;AAAA,IACpF;AACA,QAAI,UAAU,OAAO,WAAW,GAAG;AACjC,aAAO,CAAC,EAAE,UAAU,KAAK,IAAI,QAAQ,QAAQ,QAAQ,+BAA+B,CAAC;AAAA,IACvF;AACA,UAAM,UAA0B,CAAC;AACjC,eAAW,SAAS,UAAU,QAAQ;AACpC,YAAM,MAAM,KAAK,SAAS,KAAK,MAAM,IAAI;AAIzC,YAAM,eAAe,gBAAgB,KAAK,UAAU,GAAG,GAAG,GAAG;AAC7D,UAAI,iBAAiB,MAAM;AACzB,gBAAQ,KAAK;AAAA,UACX,UAAU,KAAK;AAAA,UACf,QAAQ;AAAA,UACR,MAAM;AAAA,UACN,QAAQ,GAAG,YAAY,uCAAuC,MAAM,IAAI;AAAA,QAC1E,CAAC;AACD;AAAA,MACF;AACA,cAAQ;AAAA,QACN,KAAK,iBAAiB,KAAK,KAAK,UAAU,GAAG,cAAc,KAAK,GAAG,IAAI,MAAM;AAAA,MAC/E;AAIA,iBAAW,CAAC,KAAK,QAAQ,KAAK,OAAO,QAAQ,MAAM,aAAa,CAAC,CAAC,GAAG;AACnE,cAAM,SAAS,KAAK,cAAc,KAAK,GAAG;AAC1C,YAAI,WAAW,MAAM;AACnB,kBAAQ,KAAK;AAAA,YACX,UAAU,KAAK;AAAA,YACf,QAAQ;AAAA,YACR,QAAQ,mBAAmB,GAAG;AAAA,UAChC,CAAC;AACD;AAAA,QACF;AACA,gBAAQ,KAAK,KAAK,iBAAiB,QAAQ,UAAU,IAAI,MAAM,CAAC;AAAA,MAClE;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EAES,gBAAgB,KAAqC;AAC5D,UAAM,EAAE,UAAU,IAAI;AACtB,QAAI,UAAU,OAAO,WAAW,GAAG;AACjC,aAAO,CAAC,EAAE,UAAU,KAAK,IAAI,QAAQ,QAAQ,QAAQ,+BAA+B,CAAC;AAAA,IACvF;AACA,UAAM,UAA0B,CAAC;AACjC,eAAW,SAAS,UAAU,QAAQ;AACpC,YAAM,MAAM,KAAK,SAAS,KAAK,MAAM,IAAI;AAGzC,cAAQ,KAAK,KAAK,kBAAkB,KAAK,KAAK,UAAU,GAAG,IAAI,MAAM,CAAC;AACtE,iBAAW,OAAO,OAAO,KAAK,MAAM,aAAa,CAAC,CAAC,GAAG;AACpD,cAAM,SAAS,KAAK,cAAc,KAAK,GAAG;AAC1C,YAAI,WAAW,KAAM;AACrB,gBAAQ,KAAK,KAAK,kBAAkB,QAAQ,IAAI,MAAM,CAAC;AAAA,MACzD;AAGA,cAAQ,KAAK,KAAK,iBAAiB,KAAK,IAAI,MAAM,CAAC;AAAA,IACrD;AACA,WAAO;AAAA,EACT;AAAA;AAAA,EAIS,gBAAgB,KAA6C;AACpE,UAAM,aAAa,KAAK,oBAAoB,GAAG;AAC/C,UAAM,cAAc,IAAI,UAAU;AAClC,UAAM,UAAU,IAAI;AACpB,UAAM,aAAa,KAAK,oBAAoB,GAAG;AAC/C,WAAO;AAAA,MACL;AAAA,QACE,MAAM,GAAG,KAAK,IAAI;AAAA,QAClB,OAAO,MACL,WAAW,UAAU,IACjB,EAAE,QAAQ,MAAM,QAAQ,WAAW,IACnC,EAAE,QAAQ,QAAQ,QAAQ,cAAc,UAAU,GAAG;AAAA,MAC7D;AAAA,MACA;AAAA,QACE,MAAM,GAAG,KAAK,IAAI,SAAS,WAAW;AAAA,QACtC,OAAO,MAAM;AACX,cAAI,CAAC,IAAI,UAAU,OAAQ,QAAO,EAAE,QAAQ,MAAM,QAAQ,yBAAyB;AACnF,gBAAM,MAAM,KAAK,SAA0B,UAAU;AACrD,gBAAM,SAAS,MAAM,YAAY;AACjC,gBAAM,UACJ,OAAO,WAAW,YAAY,WAAW,QAAQ,eAAe;AAClE,iBAAO,UACH,EAAE,QAAQ,MAAM,QAAQ,OAAO,WAAW,GAAG,IAC7C,EAAE,QAAQ,QAAQ,QAAQ,OAAO,WAAW,iBAAiB,UAAU,GAAG;AAAA,QAChF;AAAA,MACF;AAAA,MACA;AAAA,QACE,MAAM,GAAG,KAAK,IAAI;AAAA,QAClB,OAAO,MAAM;AACX,cAAI,WAAW,WAAW,GAAG;AAC3B,mBAAO,EAAE,QAAQ,MAAM,QAAQ,oBAAoB;AAAA,UACrD;AACA,gBAAM,MAAM,KAAK,SAA0B,UAAU;AACrD,cAAI,CAAC,IAAK,QAAO,EAAE,QAAQ,QAAQ,QAAQ,eAAe,UAAU,GAAG;AACvE,gBAAM,QAAQ,IAAI,SAAS,CAAC;AAC5B,gBAAM,aAAa,OAAO,OAAO,KAAK,EAAE;AAAA,YAAK,CAAC,aAC3C,WAAW,CAAC,GAAG,KAAK,CAAC,MAAM,qBAAqB,GAAG,SAAS,SAAS,WAAW,CAAC;AAAA,UACpF;AACA,iBAAO,aACH,EAAE,QAAQ,MAAM,QAAQ,uBAAuB,IAC/C,EAAE,QAAQ,QAAQ,QAAQ,eAAe,WAAW,OAAO,UAAU,GAAG;AAAA,QAC9E;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA,EAIA,WAAW,OAAsB,KAA+B;AAC9D,UAAM,QAAS,OAAO,CAAC;AACvB,UAAM,cAAc,OAAO,MAAM,cAAc,WAAW,MAAM,YAAY;AAC5E,UAAM,YAAY,OAAO,MAAM,eAAe,WAAW,MAAM,aAAa;AAC5E,UAAM,aAAa,OAAO,MAAM,QAAQ,WAAW,MAAM,MAAM;AAE/D,UAAM,OAAO;AAAA,MACX,cAAc;AAAA,MACd;AAAA,MACA;AAAA,MACA;AAAA,MACA,GAAI,eAAe,SAAY,EAAE,WAAW,IAAI,CAAC;AAAA,IACnD;AAEA,QAAI,UAAU,cAAc;AAC1B,YAAM,KAAsB;AAAA,QAC1B,GAAG;AAAA,QACH,UAAU,MAAM,aAAa;AAAA,QAC7B,WAAW,MAAM,cAAc,CAAC;AAAA,MAClC;AACA,aAAO;AAAA,IACT;AAIA,UAAM,IAAI,MAAM,iCAAiC,OAAO,KAAK,CAAC,EAAE;AAAA,EAClE;AAAA;AAAA,EAIA,YAAY,OAAsB,UAAmC;AACnE,UAAM,WAAW,SAAS,YAAY;AAKtC,QAAI,aAAa,UAAU,UAAU,cAAc;AACjD,aAAO,KAAK,OAAO;AAAA,QACjB,UAAU;AAAA,QACV,QAAQ,SAAS,UAAU;AAAA,MAC7B,CAAC;AAAA,IACH;AAKA,WAAO,EAAE,UAAU,EAAE;AAAA,EACvB;AAAA,EAEQ,OAAO,SAA6B;AAC1C,WAAO,EAAE,UAAU,GAAG,QAAQ,KAAK,UAAU,OAAO,EAAE;AAAA,EACxD;AACF;AAQA,SAAS,gBAAgB,MAAc,MAA6B;AAClE,QAAM,WAAqB,CAAC;AAC5B,MAAI,MAAM;AACV,SAAO,IAAI,UAAU,KAAK,QAAQ;AAChC,aAAS,QAAQ,GAAG;AACpB,QAAI,QAAQ,KAAM;AAClB,UAAM,SAAS,QAAQ,GAAG;AAC1B,QAAI,WAAW,IAAK;AACpB,UAAM;AAAA,EACR;AACA,aAAW,KAAK,UAAU;AACxB,QAAI,CAAC,WAAW,CAAC,EAAG,QAAO;AAC3B,QAAI;AACF,UAAI,SAAS,CAAC,EAAE,OAAO,EAAG,QAAO;AAAA,IACnC,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO;AACT;AAEO,IAAM,UAAU,IAAI,aAAa;AACxC,IAAO,gBAAQ;","names":["entry"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli/commands/doctor.ts","../src/runtime/probe.ts"],"sourcesContent":["/**\n * cli/commands/doctor — health-check every detected platform.\n *\n * For each detected host (or the explicit --targets list) we load its adapter,\n * build a uniform InstallContext, and run adapter.doctor(ctx). Results are\n * printed as pass/warn/fail with any suggested fix. Exit code is non-zero when\n * any check fails (warns alone do not fail the command).\n *\n * The connector context comes from the local config when present; otherwise a\n * minimal id-only connector is used so path-only checks still run.\n */\n\nimport { parseArgs } from \"node:util\";\n\nimport type {\n DiagnosticResult,\n InstallScope,\n PlatformId,\n ResolvedConnector,\n} from \"../../core/types.js\";\nimport type { InstallContext } from \"../../adapters/spi.js\";\nimport { detectInstalledPlatforms } from \"../../adapters/detect.js\";\nimport { loadAdapter, REGISTERED_PLATFORM_IDS } from \"../../adapters/registry.js\";\nimport {\n findConnectorConfig,\n listRegisteredConnectors,\n loadConnectorFromPath,\n readRegisteredMeta,\n} from \"../../core/load-connector.js\";\nimport { syncConnector } from \"../../core/installer.js\";\nimport { marketplaceDoctorChecks } from \"../../core/marketplace.js\";\nimport { readMarketplaceInstalls } from \"../../core/marketplace-state.js\";\nimport { dataRoot, homeBinPath } from \"../../core/paths.js\";\nimport { probeStdioServer } from \"../../runtime/probe.js\";\nimport { fail, parseScope, parseTargets, print } from \"../app.js\";\n\nconst STATUS_GLYPH: Record<DiagnosticResult[\"status\"], string> = {\n pass: \"[pass]\",\n warn: \"[warn]\",\n fail: \"[FAIL]\",\n};\n\n/** A resolved connector together with the path to its source module. */\ninterface ConnectorEntry {\n connector: ResolvedConnector;\n /** Absolute path to the connector source (JSON or JS/TS). Used by syncConnector. */\n modulePath: string;\n}\n\n/**\n * Resolve which connector(s) doctor should health-check, in precedence order:\n * 1. An explicit --connector path, or a local agent-connector.config.* file.\n * 2. Every connector registered under the data-root (what is actually\n * installed). This is the common case — `doctor` from anywhere reports on\n * the real installs, not a guess from the working directory.\n * 3. A minimal id-only placeholder so path-only checks still run.\n */\nasync function resolveDoctorConnectors(\n connectorPath: string | undefined,\n projectDir: string,\n): Promise<ConnectorEntry[]> {\n const configPath = connectorPath ?? findConnectorConfig(projectDir);\n if (configPath) {\n try {\n const { connector, modulePath } = await loadConnectorFromPath(configPath);\n return [{ connector, modulePath }];\n } catch {\n /* fall through */\n }\n }\n\n const registered = listRegisteredConnectors();\n if (registered.length > 0) {\n return registered.map((connector) => {\n const meta = readRegisteredMeta(connector.id);\n return { connector, modulePath: meta?.modulePath ?? \"\" };\n });\n }\n\n const fallback: ResolvedConnector = {\n id: \"agent-connector\",\n displayName: \"agent-connector\",\n version: \"0.0.0\",\n hooks: {},\n hookEvents: [],\n telemetry: {\n enabled: true,\n modelFamilyHint: \"auto\",\n measureToolDefs: true,\n hostNativeUsage: false,\n store: \"ndjson\",\n calibration: { anthropicCountTokens: false },\n },\n commands: [],\n skills: [],\n subagents: [],\n memory: [],\n actions: [],\n platforms: {},\n targets: \"auto\",\n };\n return [{ connector: fallback, modulePath: \"\" }];\n}\n\nfunction buildContext(\n connector: ResolvedConnector,\n id: PlatformId,\n scope: InstallScope,\n projectDir: string,\n): InstallContext {\n return {\n connector,\n scope: connector.platforms[id]?.scope ?? scope,\n projectDir,\n homeBinPath: homeBinPath(),\n dataRoot: dataRoot(),\n dryRun: true,\n };\n}\n\n/** Collected diagnostics tagged with the connector entry they came from. */\ninterface TaggedResult {\n result: DiagnosticResult;\n /** Index into the entries array — used to group by connector for heal. */\n entryIndex: number;\n}\n\n/**\n * Run all diagnostic checks for the given entries/ids and return tagged results\n * plus the flat byPlatform buckets for display.\n */\nasync function collectDiagnostics(\n entries: ConnectorEntry[],\n ids: PlatformId[],\n scope: InstallScope,\n projectDir: string,\n): Promise<{\n byPlatform: { platform: PlatformId; results: DiagnosticResult[] }[];\n tagged: TaggedResult[];\n anyFail: boolean;\n}> {\n const multi = entries.length > 1;\n const byPlatform: { platform: PlatformId; results: DiagnosticResult[] }[] = [];\n const tagged: TaggedResult[] = [];\n let anyFail = false;\n\n for (const id of ids) {\n const adapter = await loadAdapter(id);\n if (!adapter) {\n const r: DiagnosticResult = {\n check: `${id}: adapter`,\n status: \"fail\",\n message: `no adapter registered for ${id}`,\n };\n byPlatform.push({ platform: id, results: [r] });\n anyFail = true;\n continue;\n }\n const results: DiagnosticResult[] = [];\n for (let i = 0; i < entries.length; i++) {\n const { connector } = entries[i]!;\n // A connector with an explicit target list is only checked on those hosts.\n if (connector.targets !== \"auto\" && !connector.targets.includes(id)) continue;\n\n // MARKETPLACE-installed on this host: its surfaces are delivered via the\n // host's plugin (in the plugin cache), NOT the direct-config locations the\n // adapter's doctor() inspects — so the direct checks would falsely FAIL\n // (mcp_servers/command/skill \"not found\"). Skip them; the marketplace-method\n // checks below cover this install's real health.\n if (readMarketplaceInstalls(connector.id)[id]) {\n const note: DiagnosticResult = {\n check: `${connector.id}: ${id} delivery`,\n status: \"pass\",\n message: \"surfaces delivered via the marketplace plugin — see marketplace checks\",\n };\n const tagged_note = multi ? { ...note, check: `(${connector.id}) ${note.check}` } : note;\n results.push(tagged_note);\n tagged.push({ result: tagged_note, entryIndex: i });\n continue;\n }\n\n const ctx = buildContext(connector, id, scope, projectDir);\n let r: DiagnosticResult[];\n try {\n r = adapter.doctor(ctx);\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n r = [{ check: `${adapter.name}: doctor`, status: \"fail\", message }];\n }\n // When checking multiple connectors, tag each check with the connector id.\n const tagged_r = multi ? r.map((d) => ({ ...d, check: `(${connector.id}) ${d.check}` })) : r;\n results.push(...tagged_r);\n for (const tr of tagged_r) tagged.push({ result: tr, entryIndex: i });\n }\n if (results.some((d) => d.status === \"fail\")) anyFail = true;\n byPlatform.push({ platform: id, results });\n }\n\n // ── Marketplace-method checks ─────────────────────────────────────────────\n for (let i = 0; i < entries.length; i++) {\n const { connector } = entries[i]!;\n const groups = await marketplaceDoctorChecks(connector, scope, projectDir);\n for (const group of groups) {\n const tagged_g = multi\n ? group.results.map((d) => ({ ...d, check: `(${connector.id}) ${d.check}` }))\n : group.results;\n if (tagged_g.some((d) => d.status === \"fail\")) anyFail = true;\n for (const tg of tagged_g) tagged.push({ result: tg, entryIndex: i });\n const bucket = byPlatform.find((b) => b.platform === group.platform);\n if (bucket) bucket.results.push(...tagged_g);\n else byPlatform.push({ platform: group.platform, results: tagged_g });\n }\n }\n\n return { byPlatform, tagged, anyFail };\n}\n\nexport async function run(argv: string[]): Promise<number> {\n const { values } = parseArgs({\n args: argv,\n options: {\n scope: { type: \"string\", default: \"user\" },\n targets: { type: \"string\" },\n connector: { type: \"string\" },\n project: { type: \"string\" },\n json: { type: \"boolean\", default: false },\n probe: { type: \"boolean\", default: false },\n heal: { type: \"boolean\", default: false },\n \"dry-run\": { type: \"boolean\", default: false },\n },\n allowPositionals: false,\n });\n\n const projectDir = values.project ?? process.cwd();\n\n const scope = parseScope(values.scope);\n if (scope == null) return fail(`invalid --scope \"${values.scope}\" (use user|project)`);\n\n const entries = await resolveDoctorConnectors(values.connector, projectDir);\n const connectors = entries.map((e) => e.connector);\n\n // Target set: explicit --targets (intersected with the registry), else the\n // same chain install uses — connector-declared targets ∩ detected platforms\n // (\"auto\" = everything detected). Without this, doctor red-flags every\n // detected host the connector never targeted (found dogfooding context-mode:\n // targets:[5 ids] installed clean, doctor FAILed the other 9 detected hosts).\n const explicit = parseTargets(values.targets);\n let ids: PlatformId[];\n if (explicit && explicit.length > 0) {\n ids = explicit.filter((id) => REGISTERED_PLATFORM_IDS.has(id));\n } else {\n const detected = await detectInstalledPlatforms(projectDir);\n ids = detected.map((p) => p.id);\n const anyAuto = connectors.some((c) => c.targets === \"auto\");\n if (!anyAuto) {\n const targeted = new Set(connectors.flatMap((c) => c.targets as PlatformId[]));\n ids = ids.filter((id) => targeted.has(id));\n }\n }\n\n if (ids.length === 0 && !values.probe) {\n print(\"doctor: no target platforms (none detected; pass --targets to force).\");\n return 0;\n }\n\n // ── Heal path ─────────────────────────────────────────────────────────────\n if (values.heal) {\n const { tagged, anyFail: preFail } = await collectDiagnostics(\n entries,\n ids,\n scope,\n projectDir,\n );\n\n // Partition: fixable vs deferred (non-pass, not fixable)\n const fixableByEntry = new Map<number, DiagnosticResult[]>();\n const deferredByEntry = new Map<number, DiagnosticResult[]>();\n for (const { result, entryIndex } of tagged) {\n if (result.status === \"pass\") continue;\n // A finding is only HEALABLE if it is fixable AND its connector has a\n // module path we can re-sync from. A placeholder/unregistered connector\n // (empty modulePath) must NEVER be synced — doing so would fabricate a\n // bogus registry record via registerConnector(connector, \"\"). Route its\n // fixable findings to deferred instead.\n const canSync = !!entries[entryIndex]!.modulePath;\n if (result.fixable && canSync) {\n if (!fixableByEntry.has(entryIndex)) fixableByEntry.set(entryIndex, []);\n fixableByEntry.get(entryIndex)!.push(result);\n } else {\n if (!deferredByEntry.has(entryIndex)) deferredByEntry.set(entryIndex, []);\n deferredByEntry.get(entryIndex)!.push(result);\n }\n }\n\n if (values[\"dry-run\"]) {\n // Dry-run: print what would happen, write nothing.\n for (const [idx, fixable] of fixableByEntry) {\n const { connector } = entries[idx]!;\n print(\n `would heal via sync (${connector.id}): ${fixable.map((r) => r.check).join(\", \")}`,\n );\n }\n for (const [idx, deferred] of deferredByEntry) {\n const { connector } = entries[idx]!;\n for (const r of deferred) {\n print(\n `would defer (${connector.id}): ${r.check} — ${r.fix ?? \"no auto-fix available\"}`,\n );\n }\n }\n if (fixableByEntry.size === 0 && deferredByEntry.size === 0) {\n print(\"doctor --heal --dry-run: nothing to heal.\");\n }\n return 0;\n }\n\n // Real heal: sync each connector that has fixable findings.\n for (const [idx] of fixableByEntry) {\n const { connector, modulePath } = entries[idx]!;\n await syncConnector({\n connector,\n modulePath,\n scope,\n projectDir,\n targets: ids,\n dryRun: false,\n });\n }\n\n // Re-run diagnostics to compute what changed.\n const { tagged: postTagged, anyFail: postFail } = await collectDiagnostics(\n entries,\n ids,\n scope,\n projectDir,\n );\n\n // Classify post-heal results.\n const preNonPass = new Set(\n tagged\n .filter((t) => t.result.status !== \"pass\")\n .map((t) => t.result.check),\n );\n const postNonPass = new Set(\n postTagged\n .filter((t) => t.result.status !== \"pass\")\n .map((t) => t.result.check),\n );\n\n const healed: string[] = [];\n const stillFailing: DiagnosticResult[] = [];\n const deferred: DiagnosticResult[] = [];\n\n // Healed = was non-pass before, now pass\n for (const check of preNonPass) {\n if (!postNonPass.has(check)) healed.push(check);\n }\n // Post-heal non-pass findings. Classify consistently with the pre-heal\n // partition: a fixable finding we could not sync (no modulePath) is deferred,\n // not \"still failing after sync\" — we never attempted a sync for it.\n for (const { result, entryIndex } of postTagged) {\n if (result.status === \"pass\") continue;\n const canSync = !!entries[entryIndex]!.modulePath;\n if (result.fixable && canSync) {\n stillFailing.push(result);\n } else {\n deferred.push(result);\n }\n }\n\n if (values.json) {\n print(JSON.stringify({ healed, deferred, stillFailing }, null, 2));\n return postFail ? 1 : 0;\n }\n\n if (healed.length > 0) {\n print(`healed (${healed.length}):`);\n for (const c of healed) print(` [pass] ${c}`);\n print(\"\");\n }\n if (stillFailing.length > 0) {\n print(`still failing after sync (${stillFailing.length}):`);\n for (const r of stillFailing) {\n print(` ${STATUS_GLYPH[r.status]} ${r.check} — ${r.message}`);\n if (r.fix) print(` fix: ${r.fix}`);\n }\n print(\"\");\n }\n if (deferred.length > 0) {\n print(`deferred — requires manual action (${deferred.length}):`);\n for (const r of deferred) {\n print(` ${STATUS_GLYPH[r.status]} ${r.check} — ${r.message}`);\n if (r.fix) print(` fix: ${r.fix}`);\n }\n print(\"\");\n }\n if (healed.length === 0 && stillFailing.length === 0 && deferred.length === 0 && !preFail) {\n print(\"doctor --heal: nothing to heal, all checks passed.\");\n } else if (stillFailing.length === 0 && deferred.length === 0) {\n print(\"doctor --heal: all fixable findings resolved.\");\n }\n return postFail ? 1 : 0;\n }\n\n // ── Normal diagnose path (no --heal) ─────────────────────────────────────\n const { byPlatform, anyFail } = await collectDiagnostics(entries, ids, scope, projectDir);\n\n // ── Live MCP probe (--probe): connector-scoped, not platform-scoped ──────\n // Spawns each connector's REAL stdio server and runs initialize → ping →\n // tools/list. Probe FAILs fold into the doctor exit code.\n const probes: { connector: string; results: DiagnosticResult[] }[] = [];\n if (values.probe) {\n for (const { connector } of entries) {\n const s = connector.server;\n if (!s || s.transport !== \"stdio\" || !s.command) {\n probes.push({\n connector: connector.id,\n results: [\n {\n check: `${connector.id}: MCP probe`,\n status: \"warn\",\n message: s\n ? `transport \"${s.transport}\" is not stdio — live probe skipped`\n : \"no server to probe\",\n },\n ],\n });\n continue;\n }\n const results = await probeStdioServer(s.command, s.args ?? [], {\n label: connector.id,\n ...(s.env ? { env: s.env } : {}),\n });\n probes.push({ connector: connector.id, results });\n }\n }\n\n const probesFail = probes.some((p) => p.results.some((r) => r.status === \"fail\"));\n\n if (values.json) {\n print(JSON.stringify(values.probe ? { platforms: byPlatform, probes } : byPlatform, null, 2));\n return anyFail || probesFail ? 1 : 0;\n }\n\n for (const { platform, results } of byPlatform) {\n print(`${platform}:`);\n for (const r of results) {\n print(` ${STATUS_GLYPH[r.status]} ${r.check} — ${r.message}`);\n if (r.fix) print(` fix: ${r.fix}`);\n }\n print(\"\");\n }\n for (const { connector, results } of probes) {\n print(`probe ${connector}:`);\n for (const r of results) {\n print(` ${STATUS_GLYPH[r.status]} ${r.check} — ${r.message}`);\n if (r.fix) print(` fix: ${r.fix}`);\n }\n print(\"\");\n }\n print(anyFail || probesFail ? \"doctor: one or more checks FAILED.\" : \"doctor: all checks passed.\");\n return anyFail || probesFail ? 1 : 0;\n}\n","/**\n * runtime/probe — a live MCP connection-lifecycle probe for `doctor --probe`.\n *\n * Where `doctor` checks files on disk, this spawns the connector's REAL stdio\n * server and speaks the MCP wire protocol to it: initialize → (read negotiated\n * protocolVersion + capabilities + serverInfo) → notifications/initialized →\n * ping (liveness) → tools/list (gated on the tools capability). It reuses the\n * SAME newline-delimited JSON-RPC framing + id-correlation as the telemetry\n * proxy (telemetry/jsonrpc), so the probe and the serve path read the wire\n * identically. Each step becomes a DiagnosticResult so doctor renders/aggregates\n * it uniformly; a dead/unlaunchable server FAILs (non-zero doctor exit).\n *\n * Negotiation rule: we OFFER {@link MCP_PROTOCOL_VERSION} but ACCEPT whatever\n * version the server returns (we only report it), per the spec — never a\n * hardcoded equality. There is no MCP shutdown message; we close stdin then\n * SIGTERM/SIGKILL.\n */\n\nimport type { DiagnosticResult } from \"../core/types.js\";\nimport { MCP_PROTOCOL_VERSION } from \"../core/mcp-standard.js\";\nimport { spawnChild } from \"../core/spawn-child.js\";\nimport { type JsonRpcMessage, LineBuffer, idKey, isObject } from \"../telemetry/jsonrpc.js\";\n\nconst DEFAULT_TIMEOUT_MS = 5000;\n\nexport interface ProbeOptions {\n /** Per-step timeout in ms (default 5000). */\n timeoutMs?: number;\n /** Prefix for each DiagnosticResult.check (e.g. the connector id). */\n label?: string;\n /** Env merged over process.env for the spawned server (${env:VAR} resolved). */\n env?: Record<string, string>;\n /** Protocol version offered in initialize. Default {@link MCP_PROTOCOL_VERSION}. */\n protocolVersion?: string;\n}\n\nfunction diag(\n status: DiagnosticResult[\"status\"],\n check: string,\n message: string,\n fix?: string,\n): DiagnosticResult {\n return { check, status, message, ...(fix ? { fix } : {}) };\n}\n\nfunction errMsg(e: unknown): string {\n return e instanceof Error ? e.message : String(e);\n}\n\n/** Resolve `${env:VAR}` references in env values against the current process env. */\nfunction resolveEnv(env: Record<string, string> | undefined): Record<string, string> {\n const out: Record<string, string> = {};\n for (const [k, v] of Object.entries(env ?? {})) {\n out[k] = v.replace(/\\$\\{env:([A-Za-z_][A-Za-z0-9_]*)\\}/g, (_m, name) => process.env[name] ?? \"\");\n }\n return out;\n}\n\n/**\n * Spawn the stdio MCP server `command args` and run a real lifecycle probe.\n * Always resolves (never rejects) with one DiagnosticResult per step.\n */\nexport async function probeStdioServer(\n command: string,\n args: string[],\n opts: ProbeOptions = {},\n): Promise<DiagnosticResult[]> {\n const label = opts.label ? `${opts.label}: ` : \"\";\n const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n const protocolVersion = opts.protocolVersion ?? MCP_PROTOCOL_VERSION;\n const results: DiagnosticResult[] = [];\n\n // spawnChild resolves a bare Windows package runner (npx/uvx → .cmd/.exe) so\n // the probe agrees with the live serve path; no-op on macOS/Linux.\n const child = spawnChild(command, args, {\n stdio: [\"pipe\", \"pipe\", \"inherit\"],\n env: { ...process.env, ...resolveEnv(opts.env) },\n });\n\n interface Pending {\n resolve: (m: JsonRpcMessage) => void;\n reject: (e: Error) => void;\n }\n const pending = new Map<string, Pending>();\n let spawnErr: Error | null = null;\n let exitCode: number | null = null;\n\n const rejectAll = (e: Error): void => {\n for (const p of pending.values()) p.reject(e);\n pending.clear();\n };\n child.on(\"error\", (e) => {\n spawnErr = e;\n rejectAll(e);\n });\n child.on(\"exit\", (code) => {\n exitCode = code ?? 0;\n rejectAll(new Error(`server exited (code ${exitCode}) before responding`));\n });\n\n const lines = new LineBuffer((line) => {\n let parsed: unknown;\n try {\n parsed = JSON.parse(line);\n } catch {\n return; // non-JSON stdout noise — ignore\n }\n if (!isObject(parsed)) return;\n const k = idKey((parsed as JsonRpcMessage).id);\n if (k && pending.has(k)) {\n const p = pending.get(k)!;\n pending.delete(k);\n p.resolve(parsed as JsonRpcMessage);\n }\n });\n child.stdout?.on(\"data\", (c: Buffer) => lines.push(c));\n\n const send = (m: JsonRpcMessage): void => {\n if (child.stdin && child.stdin.writable) child.stdin.write(`${JSON.stringify(m)}\\n`);\n };\n const request = (id: number | string, method: string, params?: unknown): Promise<JsonRpcMessage> => {\n const key = idKey(id)!;\n return new Promise<JsonRpcMessage>((resolve, reject) => {\n const timer = setTimeout(() => {\n pending.delete(key);\n reject(new Error(`no response within ${timeoutMs}ms`));\n }, timeoutMs);\n if (typeof timer.unref === \"function\") timer.unref();\n pending.set(key, {\n resolve: (m) => {\n clearTimeout(timer);\n resolve(m);\n },\n reject: (e) => {\n clearTimeout(timer);\n reject(e);\n },\n });\n send({ jsonrpc: \"2.0\", id, method, ...(params !== undefined ? { params } : {}) });\n });\n };\n\n const cleanup = (): DiagnosticResult[] => {\n try {\n if (child.stdin && child.stdin.writable) child.stdin.end();\n } catch {\n /* ignore */\n }\n try {\n child.kill(\"SIGTERM\");\n } catch {\n /* ignore */\n }\n const killTimer = setTimeout(() => {\n try {\n child.kill(\"SIGKILL\");\n } catch {\n /* ignore */\n }\n }, 500);\n if (typeof killTimer.unref === \"function\") killTimer.unref();\n return results;\n };\n\n // 1. initialize\n let initResult: Record<string, unknown>;\n try {\n const res = await request(1, \"initialize\", {\n protocolVersion,\n capabilities: {},\n clientInfo: { name: \"agent-connector-probe\", version: \"1\" },\n });\n if (isObject(res.error)) {\n results.push(\n diag(\"fail\", `${label}MCP initialize`, `server returned error: ${JSON.stringify(res.error)}`),\n );\n return cleanup();\n }\n initResult = isObject(res.result) ? res.result : {};\n } catch (e) {\n if (spawnErr) {\n results.push(\n diag(\n \"fail\",\n `${label}MCP initialize`,\n `server not launchable: ${errMsg(spawnErr)}`,\n `check that \"${command}\" is installed and on PATH`,\n ),\n );\n } else if (exitCode !== null) {\n // On Windows an unresolvable command surfaces as an early non-zero exit\n // (cmd.exe \"command not found\") rather than a spawn 'error' event, so fold\n // the not-launchable hint in here too — useful whether the command is\n // missing or the server genuinely crashed before initialize.\n results.push(\n diag(\n \"fail\",\n `${label}MCP initialize`,\n `server not launchable, or it exited (code ${exitCode}) before initialize`,\n `check that \"${command}\" is installed and on PATH`,\n ),\n );\n } else {\n results.push(diag(\"fail\", `${label}MCP initialize`, errMsg(e)));\n }\n return cleanup();\n }\n\n const serverInfo = isObject(initResult.serverInfo) ? initResult.serverInfo : {};\n const sName = typeof serverInfo.name === \"string\" ? serverInfo.name : \"unknown\";\n const sVer = typeof serverInfo.version === \"string\" ? serverInfo.version : \"?\";\n const negotiated =\n typeof initResult.protocolVersion === \"string\" ? initResult.protocolVersion : \"(none)\";\n results.push(diag(\"pass\", `${label}MCP initialize`, `serverInfo ${sName}@${sVer}, protocol ${negotiated}`));\n\n // capabilities (presence = feature offered)\n const caps = isObject(initResult.capabilities) ? initResult.capabilities : {};\n const capNames = [\"tools\", \"resources\", \"prompts\", \"logging\", \"completions\"].filter((c) => c in caps);\n results.push(\n diag(\"pass\", `${label}capabilities`, capNames.length > 0 ? capNames.join(\", \") : \"(none advertised)\"),\n );\n\n // 2. initialized notification (required before normal requests)\n send({ jsonrpc: \"2.0\", method: \"notifications/initialized\" });\n\n // 3. ping — liveness confirm (warn, not fail, on timeout)\n try {\n await request(\"probe-ping\", \"ping\");\n results.push(diag(\"pass\", `${label}ping`, \"alive\"));\n } catch (e) {\n results.push(diag(\"warn\", `${label}ping`, `no ping response (${errMsg(e)})`));\n }\n\n // 4. tools/list — only if the server advertised a tools capability\n if (\"tools\" in caps) {\n try {\n const res = await request(2, \"tools/list\", {});\n const r = isObject(res.result) ? res.result : {};\n const tools = Array.isArray(r.tools) ? r.tools : [];\n results.push(diag(\"pass\", `${label}tools/list`, `${tools.length} tool(s)`));\n } catch (e) {\n results.push(diag(\"fail\", `${label}tools/list`, `no tools/list response (${errMsg(e)})`));\n }\n } else {\n results.push(\n diag(\"warn\", `${label}tools/list`, \"skipped — server advertised no tools capability\"),\n );\n }\n\n return cleanup();\n}\n"],"mappings":"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","names":["deferred"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/adapters/jetbrains-copilot/index.ts"],"sourcesContent":["/**\n * adapters/jetbrains-copilot — JetBrains Copilot platform adapter for agent-connector.\n *\n * JetBrains Copilot shares the Copilot hook paradigm with VS Code Copilot\n * (Claude-compatible json-stdio), but diverges on MCP registration:\n *\n * - MCP servers: JetBrains stores MCP server registration via the IDE Settings\n * UI (Settings > Tools > GitHub Copilot > MCP > Configure), NOT in any file\n * we can reliably write — the runtime owns the `servers` key behind the UI.\n * So `installServer` writes NOTHING and returns a \"warn\" ChangeRecord telling\n * the user to add the server via the JetBrains MCP settings UI. Writing a\n * bogus file would be ignored at best and corrupt real UI state at worst.\n * `getHealthChecks` surfaces this as a WARN (not FAIL).\n *\n * - Hooks (Copilot Preview hooks): file-based and identical in shape to VS Code\n * Copilot. We write one per-connector file at\n * <projectDir>/.github/hooks/<connector-id>.json shaped as:\n * { \"version\": 1, \"hooks\": { <Event>: [ { \"type\": \"command\", \"command\" } ] } }\n * The top-level `version: 1` is REQUIRED — the Copilot hooks runtime rejects a\n * version-less file and no hooks fire. Each entry is a FLAT { type, command }\n * object (no Claude-style { matcher, hooks:[...] } wrapper). JetBrains parses\n * matchers but IGNORES them — ALL hooks fire on ALL tools — so we omit the\n * matcher entirely rather than persist an advisory one that never applies.\n *\n * - Reply: Claude-compatible JSON on stdout (exit 0), a `hookSpecificOutput`\n * object keyed by the PascalCase `hookEventName` carrying permissionDecision\n * (deny|ask) + permissionDecisionReason and additionalContext. This mirrors\n * vscode-copilot/claude-code exactly EXCEPT JetBrains cannot rewrite tool\n * input (canModifyArgs:false), so a \"modify\" decision degrades to allow.\n *\n * Env interpolation: GitHub Copilot does not document a portable native env\n * token for the hooks file, and the hooks file only ever carries our home-bin\n * hook command (no secrets), so there is nothing to interpolate here. MCP env\n * interpolation is moot because we never write the MCP file.\n */\n\nimport { existsSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\n\nimport { BaseAdapter } from \"../base.js\";\nimport type { Adapter, HookReply, InstallContext, NormalizedEvent } from \"../spi.js\";\nimport type {\n ChangeRecord,\n CommandDef,\n DetectedPlatform,\n HealthCheck,\n HookEventName,\n HookParadigm,\n HookResponse,\n NotificationEvent,\n PlatformCapabilities,\n PlatformId,\n PostToolUseEvent,\n PostCompactEvent,\n PreCompactEvent,\n PreToolUseEvent,\n SessionEndEvent,\n SessionStartEvent,\n StopEvent,\n UserPromptSubmitEvent,\n} from \"../../core/types.js\";\nimport {\n buildHomeBinHookCommand,\n isHomeBinHookCommand,\n} from \"../../core/spawn.js\";\nimport { renderSkillMd } from \"../claude-code/render.js\";\nimport { normalizeSessionSource } from \"../claude-code/wire.js\";\n\nconst HOST: PlatformId = \"jetbrains-copilot\";\n\n/** Top-level version the Copilot hooks runtime requires; a version-less file is rejected. */\nconst JETBRAINS_HOOKS_VERSION = 1;\n\n/**\n * JetBrains Copilot reads PascalCase hook event names from its hooks file —\n * identical to VS Code Copilot / Claude Code. Only the events JetBrains actually\n * delivers are registered; everything else has no Copilot equivalent and is\n * reported as a warn/skip at install time.\n */\nconst EVENT_MAP: Partial<Record<HookEventName, string>> = {\n PreToolUse: \"PreToolUse\",\n PostToolUse: \"PostToolUse\",\n PreCompact: \"PreCompact\",\n SessionStart: \"SessionStart\",\n SessionEnd: \"SessionEnd\",\n UserPromptSubmit: \"UserPromptSubmit\",\n};\n\n/** A single JetBrains Copilot native hook entry — a flat command object. */\ninterface JetBrainsHookEntry {\n type: \"command\";\n command: string;\n}\n\n/** The shape of a JetBrains Copilot .github/hooks/<connector>.json file. */\ninterface JetBrainsHooksFile {\n version?: number;\n hooks?: Record<string, JetBrainsHookEntry[]>;\n}\n\n/** Raw JetBrains Copilot hook stdin payload (Claude-compatible snake_case fields). */\ninterface JetBrainsWireInput {\n session_id?: string;\n transcript_path?: string;\n cwd?: string;\n workspace_roots?: string[];\n hook_event_name?: string;\n\n // tool events\n tool_name?: string;\n tool_input?: Record<string, unknown>;\n tool_response?: unknown;\n tool_output?: string;\n error_message?: string;\n\n // SessionStart\n source?: string;\n // SessionEnd\n reason?: string;\n // UserPromptSubmit\n prompt?: string;\n // PreCompact\n trigger?: string;\n // Stop\n stop_hook_active?: boolean;\n // Notification\n message?: string;\n\n /** Injected by the entrypoint so the runtime knows which connector to dispatch. */\n connector?: string;\n}\n\nexport class JetBrainsCopilotAdapter extends BaseAdapter implements Adapter {\n readonly id: PlatformId = HOST;\n readonly name = \"JetBrains Copilot\";\n readonly paradigm: HookParadigm = \"json-stdio\";\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 // JetBrains Copilot's Preview hooks runtime delivers Pre/PostToolUse,\n // PreCompact, SessionStart, SessionEnd, and UserPromptSubmit (GitHub's\n // hooks-reference) — same surface as VS Code Copilot, whose reply contract\n // this adapter mirrors exactly (see formatReply: UserPromptSubmit/PostToolUse\n // deny → top-level {decision:block}). Stop stays unwired (refuted for\n // JetBrains: an unimplemented feature request, not in the documented schema).\n preToolUse: true,\n postToolUse: true,\n preCompact: true,\n sessionStart: true,\n sessionEnd: true,\n userPromptSubmit: true,\n stop: false,\n notification: false,\n // Newer events: the JetBrains Copilot Preview hooks runtime documents no\n // permission-dialog, tool-failure, or subagent lifecycle events, so\n // permissionRequest / postToolUseFailure / subagentStart / subagentStop\n // stay unset — install reports the standard skip-warn for them.\n // Per the JetBrains spec this host is deny/ask-only: a PreToolUse hook\n // CANNOT rewrite tool input, and PostToolUse cannot rewrite tool output.\n canModifyArgs: false,\n canModifyOutput: false,\n canInjectSessionContext: true,\n // MCP is managed via the IDE Settings UI (Settings > Tools > GitHub Copilot\n // > MCP). The UI accepts local stdio servers AND remote Streamable HTTP / SSE\n // servers; AC writes no file, so this list only describes what the UI accepts\n // (install reports a UI-managed warn for every transport).\n transports: [\"stdio\", \"http\", \"sse\"],\n // Content surfaces: JetBrains Copilot consumes the GitHub Copilot .github/\n // files (it has no distinct authoring location), so it is an ALIAS of the\n // vscode-copilot writer for prompt files and Agent Skills. It has no native\n // subagent/chat-mode surface, so subagents stay unsupported (BaseAdapter\n // returns the skip/warn default).\n supportsCommands: true,\n supportsSkills: true,\n supportsSubagents: false,\n // Native passthrough: GitHub's JetBrains-Copilot changelog documents an\n // errorOccurred / ErrorOccurred lifecycle event with NO canonical\n // HookEventName analog (PostToolUseFailure is tool-scoped, not a session-wide\n // error event). A connector reaches it via platforms[\"jetbrains-copilot\"].\n // nativeHooks; installHooks files the event-name key VERBATIM and the generic\n // uninstall reverses it. PascalCase ErrorOccurred matches the adapter's\n // Claude-compatible payload dialect (GitHub hooks-reference accepts both).\n supportsNativeHooks: true,\n };\n\n // ── Detection ────────────────────────────────────────────────────────────\n\n detectInstalled(projectDir: string): DetectedPlatform {\n // JetBrains Copilot integration is observable through two markers:\n // • the project hooks tree (<projectDir>/.github/hooks) we write to, and\n // • our per-connector hooks file specifically.\n // There is no reliable user-profile MCP file to probe (the UI owns it), so\n // detection is project-scoped and keyed on the hooks footprint.\n const githubDir = join(projectDir, \".github\");\n const hooksDir = join(githubDir, \"hooks\");\n const installed = existsSync(hooksDir) || existsSync(githubDir);\n const configPath = hooksDir;\n return {\n id: this.id,\n name: this.name,\n installed,\n paradigm: this.paradigm,\n capabilities: this.capabilities,\n configPath,\n scope: \"project\",\n reason: installed\n ? `found JetBrains Copilot hooks tree at ${hooksDir}`\n : `no JetBrains Copilot hooks tree at ${hooksDir}`,\n confidence: installed ? \"medium\" : \"low\",\n };\n }\n\n // ── Native paths ─────────────────────────────────────────────────────────\n\n /** Hooks live under the workspace .github tree for both scopes. */\n getConfigDir(ctx: InstallContext): string {\n return join(ctx.projectDir, \".github\");\n }\n\n /**\n * MCP server registration has NO writable file on JetBrains — the IDE owns it\n * behind the Settings UI. We still return a stable path (the hooks file) so the\n * base-adapter `doctor`/`backupSettings` helpers have a sensible target rather\n * than a nonexistent/bogus MCP path. `installServer` never writes here.\n */\n getServerConfigPath(ctx: InstallContext): string {\n return this.getHookConfigPath(ctx);\n }\n\n /**\n * Hook registration lives in the workspace-discovered .github/hooks tree, which\n * JetBrains Copilot scans for *.json hook files. We write one file per connector\n * so installs/uninstalls never clobber another connector's hooks. Anchored on\n * projectDir for both scopes — .github/hooks is a workspace concept (there is no\n * user-profile equivalent in the Copilot hooks schema).\n */\n getHookConfigPath(ctx: InstallContext): string {\n return join(ctx.projectDir, \".github\", \"hooks\", `${ctx.connector.id}.json`);\n }\n\n // ── MCP server install / uninstall ───────────────────────────────────────\n\n /**\n * JetBrains MCP registration is UI-only. We never write a file: a bogus file is\n * ignored at best and corrupts real UI-managed state at worst. Emit a \"warn\"\n * ChangeRecord that tells the user exactly where to add the server by hand.\n */\n installServer(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n const override = connector.platforms[HOST]?.server;\n if (!connector.server || override === false) {\n return [\n {\n platform: this.id,\n action: \"skip\",\n detail: connector.server\n ? \"server registration disabled for jetbrains-copilot\"\n : \"connector declares no MCP server\",\n },\n ];\n }\n\n return [\n {\n platform: this.id,\n action: \"warn\",\n detail:\n `JetBrains Copilot manages MCP servers via the IDE Settings UI — ` +\n `add \"${connector.id}\" manually under Settings > Tools > GitHub Copilot ` +\n `> MCP > Configure (no file is written here).`,\n },\n ];\n }\n\n /**\n * Nothing was written for the MCP server, so there is nothing to remove. Mirror\n * the install-time guidance as a \"warn\" so an uninstall report is honest about\n * the UI-managed entry the user may still want to remove by hand.\n */\n uninstallServer(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n if (!connector.server || connector.platforms[HOST]?.server === false) {\n return [\n {\n platform: this.id,\n action: \"skip\",\n detail: \"no MCP server was registered for jetbrains-copilot\",\n },\n ];\n }\n return [\n {\n platform: this.id,\n action: \"warn\",\n detail:\n `JetBrains Copilot MCP servers are UI-managed — if \"${connector.id}\" was ` +\n `added manually, remove it under Settings > Tools > GitHub Copilot > MCP.`,\n },\n ];\n }\n\n // ── Hook install / uninstall ─────────────────────────────────────────────\n\n installHooks(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n const override = connector.platforms[HOST];\n const hooksDisabled = override?.hooks === false;\n // `hooks: false` disables only the NORMALIZED events; nativeHooks is a\n // sibling, jetbrains-copilot-scoped declaration that installs regardless.\n const normalizedEvents = hooksDisabled ? [] : connector.hookEvents;\n const nativeHooks = override?.nativeHooks ?? {};\n const nativeEvents = Object.keys(nativeHooks);\n\n if (normalizedEvents.length === 0 && nativeEvents.length === 0) {\n return [\n {\n platform: this.id,\n action: \"skip\",\n detail: hooksDisabled\n ? \"hooks disabled for jetbrains-copilot\"\n : \"connector declares no hooks\",\n },\n ];\n }\n\n const hooksPath = this.getHookConfigPath(ctx);\n const symlink = this.symlinkPathWarning(hooksPath);\n if (symlink) return [symlink];\n\n const file = this.readJson<JetBrainsHooksFile>(hooksPath) ?? {};\n const __skip = this.malformedHookRootSkip(hooksPath, (file as Record<string, unknown>).hooks);\n if (__skip) return [__skip];\n const hooks = (file.hooks ??= {});\n\n const changes: ChangeRecord[] = [];\n let mutated = false;\n\n for (const event of normalizedEvents) {\n const jetbrainsEvent = EVENT_MAP[event];\n if (!jetbrainsEvent) {\n // No JetBrains Copilot equivalent for this normalized event — report+skip.\n changes.push({\n platform: this.id,\n action: \"warn\",\n path: hooksPath,\n detail: `${event} has no JetBrains Copilot hook equivalent — skipped`,\n });\n continue;\n }\n\n const command = buildHomeBinHookCommand(ctx.homeBinPath, HOST, event, connector.id);\n // Matchers are IGNORED by JetBrains (all hooks fire on all tools), so we omit\n // the matcher entirely — a flat { type, command } entry.\n const entry: JetBrainsHookEntry = { type: \"command\", command };\n\n const bucket = (hooks[jetbrainsEvent] ??= []);\n const existingIdx = bucket.findIndex((e) => this.isOurCommand(e.command, ctx));\n\n if (existingIdx >= 0) {\n if (JSON.stringify(bucket[existingIdx]) === JSON.stringify(entry)) {\n changes.push({\n platform: this.id,\n action: \"skip\",\n path: hooksPath,\n detail: `hooks.${jetbrainsEvent} already registered`,\n });\n continue;\n }\n bucket[existingIdx] = entry;\n changes.push({\n platform: this.id,\n action: \"update\",\n path: hooksPath,\n detail: `hooks.${jetbrainsEvent}`,\n });\n } else {\n bucket.push(entry);\n changes.push({\n platform: this.id,\n action: \"create\",\n path: hooksPath,\n detail: `hooks.${jetbrainsEvent}`,\n });\n }\n mutated = true;\n }\n\n // NATIVE passthrough events: jetbrains-copilot-native event-name keys (e.g.\n // ErrorOccurred) filed VERBATIM into the hooks map — no EVENT_MAP, since they\n // ARE Copilot events. Flat { type, command } entry (matchers are ignored);\n // matched by EXACT command so a native key coinciding with a normalized one\n // never clobbers it.\n for (const nativeEvent of nativeEvents) {\n const command = buildHomeBinHookCommand(ctx.homeBinPath, HOST, nativeEvent, connector.id);\n const entry: JetBrainsHookEntry = { type: \"command\", command };\n const bucket = (hooks[nativeEvent] ??= []);\n const existingIdx = bucket.findIndex((e) => e.command === command);\n if (existingIdx >= 0) {\n if (JSON.stringify(bucket[existingIdx]) === JSON.stringify(entry)) {\n changes.push({\n platform: this.id,\n action: \"skip\",\n path: hooksPath,\n detail: `hooks.${nativeEvent} (native) already registered`,\n });\n continue;\n }\n bucket[existingIdx] = entry;\n changes.push({\n platform: this.id,\n action: \"update\",\n path: hooksPath,\n detail: `hooks.${nativeEvent} (native)`,\n });\n } else {\n bucket.push(entry);\n changes.push({\n platform: this.id,\n action: \"create\",\n path: hooksPath,\n detail: `hooks.${nativeEvent} (native)`,\n });\n }\n mutated = true;\n }\n\n if (mutated) {\n // The top-level version is REQUIRED — a version-less file is rejected and\n // no hooks fire. Always (re)assert it when we write.\n file.version = JETBRAINS_HOOKS_VERSION;\n this.writeJson(hooksPath, file, ctx.dryRun);\n }\n return changes;\n }\n\n uninstallHooks(ctx: InstallContext): ChangeRecord[] {\n const hooksPath = this.getHookConfigPath(ctx);\n const symlink = this.symlinkPathWarning(hooksPath);\n if (symlink) return [symlink];\n\n const file = this.readJson<JetBrainsHooksFile>(hooksPath);\n const hooks = file?.hooks;\n if (!file || !hooks) {\n return [\n {\n platform: this.id,\n action: \"skip\",\n path: hooksPath,\n detail: \"no hooks section present\",\n },\n ];\n }\n\n const changes: ChangeRecord[] = [];\n let mutated = false;\n\n for (const jetbrainsEvent of Object.keys(hooks)) {\n const bucket = hooks[jetbrainsEvent];\n if (!Array.isArray(bucket)) continue;\n\n const before = bucket.length;\n // Only strip OUR connector's home-bin commands — never another connector's\n // (isHomeBinHookCommand is id-anchored against a shared-prefix collision).\n const next = bucket.filter((e) => !this.isOurCommand(e.command, ctx));\n const removed = before - next.length;\n if (removed > 0) {\n if (next.length > 0) hooks[jetbrainsEvent] = next;\n else delete hooks[jetbrainsEvent];\n changes.push({\n platform: this.id,\n action: \"remove\",\n path: hooksPath,\n detail: `hooks.${jetbrainsEvent} (${removed})`,\n });\n mutated = true;\n }\n }\n\n if (mutated) {\n // The hooks file is connector-OWNED (<connector-id>.json), so when our\n // strip leaves it with NO hooks we must DELETE the whole file rather than\n // rewrite a `{ \"hooks\": {}, \"version\": 1 }` shell — an empty shell is an\n // orphan per-connector file that lingers after uninstall. A non-empty\n // result still belongs to us, so we rewrite it as before. dryRun reports\n // the would-be remove without mutating the filesystem.\n if (Object.keys(hooks).length === 0) {\n changes.push(\n this.removeManagedFile(\n hooksPath,\n ctx.dryRun,\n \"removed empty connector hooks file\",\n \"no hooks file present\",\n ),\n );\n // Clean up the parent .github/hooks dir only when it is now empty (it is\n // a per-connector tree; leave it in place if other connectors' files\n // remain).\n changes.push(this.removeDirIfEmpty(dirname(hooksPath), ctx.dryRun));\n } else {\n this.writeJson(hooksPath, file, ctx.dryRun);\n }\n }\n if (changes.length === 0) {\n changes.push({\n platform: this.id,\n action: \"skip\",\n path: hooksPath,\n detail: \"no matching hook entries\",\n });\n }\n return changes;\n }\n\n /** True when a hook command references our home binary AND this connector id\n * (anchored so a shared-prefix id can't collide — see isHomeBinHookCommand). */\n private isOurCommand(command: string | undefined, ctx: InstallContext): boolean {\n return isHomeBinHookCommand(command, ctx.homeBinPath, ctx.connector.id);\n }\n\n // ── Content surfaces: commands / skills ──────────────────────────────────\n // CONTENT-ONLY: pure native-file writers under the workspace .github/ tree\n // ({prompts,skills}). No runtime dispatch, no home-bin pointer, no telemetry\n // wrap. Each method is idempotent (byte-identical → skip) via\n // BaseAdapter.writeContentFile and reversible via removeContentFile. Honors\n // platforms[\"jetbrains-copilot\"] per-surface false to skip.\n //\n // ALIAS of vscode-copilot: JetBrains consumes the GitHub Copilot .github/\n // files and has no distinct authoring location, so the rendered content +\n // paths here are IDENTICAL to the vscode-copilot writer.\n //\n // SHARED .github TREE: vscode-copilot, copilot-cli, and jetbrains-copilot all\n // write under the SAME project <projectDir>/.github tree. The rendered content\n // is identical and idempotent across those connectors, and uninstall here only\n // removes the files THIS connector declared — never another writer's files.\n //\n // SCOPE NOTE: .github is a workspace concept and this adapter is project-\n // scoped (no user-profile .github authoring location exists in the Copilot\n // prompt/skill discovery), so the content root is always the project .github\n // tree — the same dir getConfigDir already anchors on.\n\n /** Root of the content tree — the project .github tree (see getConfigDir). */\n private contentRootDir(ctx: InstallContext): string {\n return this.getConfigDir(ctx);\n }\n\n private promptsDir(ctx: InstallContext): string {\n return join(this.contentRootDir(ctx), \"prompts\");\n }\n private skillsDir(ctx: InstallContext): string {\n return join(this.contentRootDir(ctx), \"skills\");\n }\n\n /** Native command file path: <ghDir>/prompts/<name>.prompt.md. */\n private commandPath(ctx: InstallContext, name: string): string {\n return join(this.promptsDir(ctx), `${name}.prompt.md`);\n }\n /** Native skill dir: <ghDir>/skills/<name>. */\n private skillDir(ctx: InstallContext, name: string): string {\n return join(this.skillsDir(ctx), name);\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 jetbrains-copilot\" }];\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 Copilot prompt file: md+frontmatter(description, tools, model, argument-hint). */\n private renderCommand(cmd: CommandDef): string {\n const frontmatter: Record<string, unknown> = {};\n if (cmd.description !== undefined) frontmatter.description = cmd.description;\n // Copilot prompt files express tool access as a `tools` array, sourced from\n // the portable tools.allow policy.\n const allow = cmd.tools?.allow;\n if (allow && allow.length > 0) frontmatter.tools = [...allow];\n if (cmd.model !== undefined) frontmatter.model = cmd.model;\n if (cmd.argumentHint !== undefined) frontmatter[\"argument-hint\"] = cmd.argumentHint;\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 jetbrains-copilot\" }];\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 // ── Diagnostics ──────────────────────────────────────────────────────────\n\n override getHealthChecks(ctx: InstallContext): readonly HealthCheck[] {\n const hooksPath = this.getHookConfigPath(ctx);\n const connectorId = ctx.connector.id;\n const homeBin = ctx.homeBinPath;\n const hookEvents = ctx.connector.hookEvents;\n const hasServer =\n ctx.connector.server != null &&\n ctx.connector.platforms[HOST]?.server !== false;\n const checks: HealthCheck[] = [\n {\n // MCP cannot be verified from disk — JetBrains owns it behind the UI.\n // BaseAdapter.doctor maps != OK to a hard FAIL, but an unverifiable\n // UI-managed surface must NOT hard-fail doctor (that contradicts the\n // install-time WARN). Return OK with a verify-in-UI detail instead.\n name: `${this.name}: MCP server (UI-managed)`,\n check: () =>\n hasServer\n ? {\n status: \"OK\",\n detail:\n \"MCP is UI-managed — verify in Settings > Tools > GitHub Copilot > MCP\",\n }\n : { status: \"OK\", detail: \"connector declares no MCP server\" },\n },\n {\n name: `${this.name}: hook command registered`,\n check: () => {\n if (hookEvents.length === 0) {\n return { status: \"OK\", detail: \"no hooks declared\" };\n }\n const file = this.readJson<JetBrainsHooksFile>(hooksPath);\n if (!file) return { status: \"FAIL\", detail: `not found: ${hooksPath}` };\n if (file.version !== JETBRAINS_HOOKS_VERSION) {\n return {\n status: \"FAIL\",\n detail: `${hooksPath} missing required \"version\": ${JETBRAINS_HOOKS_VERSION} — Copilot rejects it`,\n };\n }\n const registered = Object.values(file.hooks ?? {}).some((entries) =>\n (entries ?? []).some((e) =>\n isHomeBinHookCommand(e.command, homeBin, connectorId),\n ),\n );\n return registered\n ? { status: \"OK\", detail: \"hook command present\" }\n : { status: \"FAIL\", detail: `no hook for ${connectorId} in ${hooksPath}` };\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). Subagents are\n // unsupported here, so they are never checked.\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 return checks;\n }\n\n // ── Runtime: parse JetBrains Copilot stdin JSON → normalized event ────────\n\n parseEvent(event: HookEventName, raw: unknown): NormalizedEvent {\n const input = (raw ?? {}) as JetBrainsWireInput;\n const connectorId = typeof input.connector === \"string\" ? input.connector : \"\";\n const sessionId = extractSessionId(input);\n const projectDir = this.getProjectDir(input);\n\n const base = {\n hostPlatform: HOST,\n connectorId,\n sessionId,\n raw,\n ...(projectDir !== undefined ? { projectDir } : {}),\n } as const;\n\n switch (event) {\n case \"PreToolUse\": {\n const ev: PreToolUseEvent = {\n ...base,\n toolName: input.tool_name ?? \"\",\n toolInput: input.tool_input ?? {},\n };\n return ev;\n }\n case \"PostToolUse\": {\n const toolOutput =\n toolResponseToString(input.tool_response) ??\n input.tool_output ??\n input.error_message;\n const ev: PostToolUseEvent = {\n ...base,\n toolName: input.tool_name ?? \"\",\n toolInput: input.tool_input ?? {},\n ...(toolOutput !== undefined ? { toolOutput } : {}),\n ...(input.error_message ? { isError: true } : {}),\n };\n return ev;\n }\n case \"PreCompact\": {\n const ev: PreCompactEvent = {\n ...base,\n ...(input.trigger === \"auto\" || input.trigger === \"manual\"\n ? { trigger: input.trigger }\n : {}),\n };\n return ev;\n }\n case \"PostCompact\": {\n // JetBrains Copilot does not fire PostCompact natively (postCompact\n // unset → warn-skip at install). Parsed defensively, mirroring\n // PreCompact, so a manual/mis-routed dispatch normalizes instead of\n // hitting the guard.\n const ev: PostCompactEvent = {\n ...base,\n ...(input.trigger === \"auto\" || input.trigger === \"manual\"\n ? { trigger: input.trigger }\n : {}),\n };\n return ev;\n }\n case \"SessionStart\": {\n const ev: SessionStartEvent = {\n ...base,\n source: normalizeSessionSource(input.source ?? input.trigger),\n };\n return ev;\n }\n case \"SessionEnd\": {\n const ev: SessionEndEvent = {\n ...base,\n ...(typeof input.reason === \"string\" ? { reason: input.reason } : {}),\n };\n return ev;\n }\n case \"UserPromptSubmit\": {\n const ev: UserPromptSubmitEvent = {\n ...base,\n prompt: typeof input.prompt === \"string\" ? input.prompt : \"\",\n };\n return ev;\n }\n case \"Stop\": {\n const ev: StopEvent = {\n ...base,\n ...(typeof input.stop_hook_active === \"boolean\"\n ? { stopHookActive: input.stop_hook_active }\n : {}),\n };\n return ev;\n }\n case \"Notification\": {\n const ev: NotificationEvent = {\n ...base,\n message: typeof input.message === \"string\" ? input.message : \"\",\n };\n return ev;\n }\n case \"PermissionRequest\":\n case \"PostToolUseFailure\":\n case \"SubagentStart\":\n case \"SubagentStop\": {\n // No JetBrains Copilot analog — its Preview hooks runtime documents no\n // permission-dialog, tool-failure, or subagent lifecycle events.\n // Install already skip-warns these via EVENT_MAP; a runtime dispatch is\n // a mis-route — fail loudly.\n throw new Error(`unsupported jetbrains-copilot hook event: ${String(event)}`);\n }\n default: {\n // Exhaustive guard — every HookEventName is handled above. (JetBrains only\n // delivers the four it declares; the rest are handled defensively so a\n // mis-dispatch stays inert rather than crashing.)\n const _never: never = event;\n throw new Error(`unsupported jetbrains-copilot hook event: ${String(_never)}`);\n }\n }\n }\n\n /** Resolve the project dir from the wire payload, preferring the explicit cwd. */\n private getProjectDir(input: JetBrainsWireInput): string | undefined {\n return input.cwd ?? input.workspace_roots?.[0] ?? undefined;\n }\n\n // ── Runtime: normalized response → JetBrains Copilot native hook reply ────\n\n formatReply(event: HookEventName, response: HookResponse): HookReply {\n const hookEventName = event;\n const decision = response.decision ?? \"allow\";\n\n // deny → block the action with a reason (exit 0; JSON carries the decision).\n // JetBrains Copilot's reply is Claude-compatible, identical to vscode-copilot:\n // `hookSpecificOutput.permissionDecision` is read ONLY for the pre-execution\n // PreToolUse permission event. The post-execution / turn-control events —\n // PostToolUse, UserPromptSubmit, Stop, SubagentStop — block via the TOP-LEVEL\n // {\"decision\":\"block\",\"reason\"} instead (PostToolUse runs AFTER the tool, so a\n // permissionDecision there is silently ignored). Mirrors vscode-copilot #56/#58.\n if (decision === \"deny\") {\n if (\n event === \"PostToolUse\" ||\n event === \"UserPromptSubmit\" ||\n event === \"Stop\" ||\n event === \"SubagentStop\"\n ) {\n return this.stdout({\n decision: \"block\",\n reason: response.reason ?? \"Blocked by hook\",\n });\n }\n return this.stdout({\n hookSpecificOutput: {\n hookEventName,\n permissionDecision: \"deny\",\n permissionDecisionReason: response.reason ?? \"Blocked by hook\",\n },\n });\n }\n\n // ask → prompt the user to confirm.\n if (decision === \"ask\") {\n return this.stdout({\n hookSpecificOutput: {\n hookEventName,\n permissionDecision: \"ask\",\n permissionDecisionReason:\n response.reason ?? \"Confirmation required by hook\",\n },\n });\n }\n\n // modify → unsupported on JetBrains (canModifyArgs:false): a PreToolUse hook\n // cannot rewrite tool input here, so degrade to allow rather than emit an\n // updatedInput the host will ignore.\n\n // context → inject soft guidance (also the SessionStart context path).\n if (decision === \"context\" && response.additionalContext) {\n return this.stdout({\n hookSpecificOutput: { hookEventName, additionalContext: response.additionalContext },\n });\n }\n\n // allow / void / modify-degradation / unsupported → pass through with exit 0.\n return { exitCode: 0 };\n }\n\n private stdout(payload: unknown): HookReply {\n return { exitCode: 0, stdout: JSON.stringify(payload) };\n }\n}\n\n/**\n * Extract a stable session id from a JetBrains Copilot wire payload. Priority\n * mirrors the Claude-compatible wire: transcript UUID > session_id > \"\" (the\n * framework uses \"\" when no id is available — no ppid fabrication here).\n */\nfunction extractSessionId(input: JetBrainsWireInput): string {\n if (typeof input.transcript_path === \"string\") {\n const m = input.transcript_path.match(/([a-f0-9-]{36})\\.jsonl$/);\n if (m && m[1]) return m[1];\n }\n if (typeof input.session_id === \"string\" && input.session_id !== \"\") {\n return input.session_id;\n }\n return \"\";\n}\n\n/** Coerce a Claude-compatible PostToolUse `tool_response` into a string. */\nfunction toolResponseToString(value: unknown): string | undefined {\n if (value == null) return undefined;\n if (typeof value === \"string\") return value;\n try {\n return JSON.stringify(value);\n } catch {\n return String(value);\n }\n}\n\nexport const adapter = new JetBrainsCopilotAdapter();\nexport default adapter;\n"],"mappings":"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","names":[]}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
OpenClawAdapter,
|
|
4
|
-
adapter,
|
|
5
|
-
openclaw_default
|
|
6
|
-
} from "./chunk-C3TFA4CJ.js";
|
|
7
|
-
import "./chunk-DBQMX75U.js";
|
|
8
|
-
import "./chunk-GI4FDVWI.js";
|
|
9
|
-
import "./chunk-TO57WYBB.js";
|
|
10
|
-
import "./chunk-LBOGRZGY.js";
|
|
11
|
-
import "./chunk-D65GIBCG.js";
|
|
12
|
-
export {
|
|
13
|
-
OpenClawAdapter,
|
|
14
|
-
adapter,
|
|
15
|
-
openclaw_default as default
|
|
16
|
-
};
|
|
17
|
-
//# sourceMappingURL=openclaw-344VBMLY.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli/commands/uninstall.ts"],"sourcesContent":["/**\n * cli/commands/uninstall — strip a connector's registrations, method-aware.\n *\n * The connector id is taken from --connector-id, or inferred from the local\n * connector config (--connector <path> / findConnectorConfig).\n *\n * --method auto (default) reverses WHATEVER is actually there, per target:\n * targets with marketplace evidence (the state record, or the host's own plugin\n * state) get the HOST plugin uninstall; everything else gets the existing\n * direct adapter strip. Install chooses a method (a user decision); uninstall\n * reverses what exists (a state decision) — and since the double-install guard\n * enforces exactly one method per (connector, host, scope), auto is\n * unambiguous. Explicit --method direct|marketplace forces one path for every\n * target. Config removal vs plugin uninstall is therefore method-resolved:\n * never both, never neither.\n *\n * --purge additionally removes the framework-state this connector left behind:\n * its DATA-dir connector record (connectorDir(id)), the empty marketplace\n * staging root, and, when no connectors remain, the shared home-bin launcher.\n * Without --purge those linger so the connector can be re-synced without\n * re-registering.\n */\n\nimport { parseArgs } from \"node:util\";\n\nimport {\n purgeFrameworkState,\n resolveUninstallTargets,\n uninstallConnector,\n} from \"../../core/installer.js\";\nimport {\n marketplaceEvidence,\n parseUninstallMethod,\n uninstallViaMarketplace,\n} from \"../../core/marketplace.js\";\nimport { readMarketplaceInstalls } from \"../../core/marketplace-state.js\";\nimport { findConnectorConfig, loadConnectorFromPath } from \"../../core/load-connector.js\";\nimport type { InstallResult, PlatformId } from \"../../core/types.js\";\nimport { fail, parseScope, parseTargets, print, renderInstallResult } from \"../app.js\";\n\n/** Resolve the connector id from flags, then from a local config file. */\nasync function resolveConnectorId(\n explicitId: string | undefined,\n connectorPath: string | undefined,\n projectDir: string,\n): Promise<string | null> {\n if (explicitId && explicitId.trim() !== \"\") return explicitId;\n const configPath = connectorPath ?? findConnectorConfig(projectDir);\n if (!configPath) return null;\n const { connector } = await loadConnectorFromPath(configPath);\n return connector.id;\n}\n\nexport async function run(argv: string[]): Promise<number> {\n const { values } = parseArgs({\n args: argv,\n options: {\n method: { type: \"string\", default: \"auto\" },\n scope: { type: \"string\", default: \"user\" },\n targets: { type: \"string\" },\n connector: { type: \"string\" },\n \"connector-id\": { type: \"string\" },\n project: { type: \"string\" },\n \"dry-run\": { type: \"boolean\", default: false },\n purge: { type: \"boolean\", default: false },\n },\n allowPositionals: false,\n });\n\n const method = parseUninstallMethod(values.method);\n if (method == null) {\n return fail(`invalid --method \"${values.method}\" (use auto|direct|marketplace)`);\n }\n\n const projectDir = values.project ?? process.cwd();\n\n const scope = parseScope(values.scope);\n if (scope == null) return fail(`invalid --scope \"${values.scope}\" (use user|project)`);\n\n const connectorId = await resolveConnectorId(\n values[\"connector-id\"],\n values.connector,\n projectDir,\n );\n if (!connectorId) {\n return fail(\n \"could not determine connector id. Pass --connector-id <id>, \" +\n \"--connector <path>, or run inside a project with an agent-connector config.\",\n );\n }\n\n const targets = parseTargets(values.targets);\n const dryRun = values[\"dry-run\"];\n\n // ── Explicit --method marketplace: every target goes to the marketplace path\n // (targets default to the recorded installs); framework purge runs here since\n // no direct pass follows.\n if (method === \"marketplace\") {\n const result = await uninstallViaMarketplace({\n connectorId,\n projectDir,\n dryRun,\n purge: values.purge,\n ...(targets ? { targets } : {}),\n });\n if (values.purge) purgeFrameworkState(connectorId, dryRun, result);\n print(renderInstallResult(result, \"uninstall\"));\n return result.changes.some((c) => c.action === \"warn\") ? 1 : 0;\n }\n\n // ── --method auto: partition the resolved targets by marketplace evidence.\n // (--method direct keeps every target on the adapter strip — today's path.)\n let marketplaceTargets: PlatformId[] = [];\n let directTargets: PlatformId[] = [];\n if (method === \"auto\") {\n const resolved = await resolveUninstallTargets(connectorId, targets, projectDir);\n // With no explicit --targets, recorded marketplace platforms are unioned\n // in: the state record IS the authority for what we installed, and host\n // detection can miss a host whose probe-able config dir was relocated.\n // An explicit --targets list is always respected as-is.\n const recorded = targets\n ? []\n : (Object.keys(readMarketplaceInstalls(connectorId)) as PlatformId[]);\n const candidates = [...new Set([...resolved, ...recorded])];\n marketplaceTargets = candidates.filter(\n (id) => marketplaceEvidence(connectorId, id) != null,\n );\n directTargets = resolved.filter((id) => !marketplaceTargets.includes(id));\n }\n\n // No marketplace evidence anywhere (or --method direct): exactly today's\n // single-orchestration path, byte-for-byte — zero behavior change for users\n // who never touched the marketplace method.\n if (marketplaceTargets.length === 0) {\n const result = await uninstallConnector({\n connectorId,\n scope,\n projectDir,\n dryRun,\n purge: values.purge,\n ...(targets ? { targets } : {}),\n });\n print(renderInstallResult(result, \"uninstall\"));\n return result.changes.some((c) => c.action === \"warn\") ? 1 : 0;\n }\n\n const results: InstallResult[] = [\n await uninstallViaMarketplace({\n connectorId,\n projectDir,\n targets: marketplaceTargets,\n dryRun,\n purge: values.purge,\n }),\n ];\n\n // The direct strip runs only for its partition (never both methods on one\n // target). When every target was marketplace-routed, --purge still runs the\n // framework purge (the marketplace records were just cleared, so it can\n // proceed to the connector record + home-bin).\n if (directTargets.length > 0) {\n results.push(\n await uninstallConnector({\n connectorId,\n scope,\n projectDir,\n dryRun,\n purge: values.purge,\n targets: directTargets,\n }),\n );\n } else if (values.purge) {\n const purgeResult: InstallResult = {\n connectorId,\n dryRun,\n changes: [],\n warnings: [],\n };\n if (dryRun) {\n // On a real run the marketplace records are removed BEFORE this purge;\n // calling purgeFrameworkState now would false-refuse on records that the\n // marketplace pass only PLANNED to remove. Report the plan instead.\n purgeResult.changes.push({\n platform: connectorId as PlatformId,\n action: \"remove\",\n detail:\n \"would purge framework state (connector record; home-bin when no connectors remain)\",\n });\n } else {\n purgeFrameworkState(connectorId, dryRun, purgeResult);\n }\n results.push(purgeResult);\n }\n\n const merged: InstallResult = {\n connectorId,\n dryRun,\n changes: results.flatMap((r) => r.changes),\n warnings: results.flatMap((r) => r.warnings),\n };\n print(renderInstallResult(merged, \"uninstall\"));\n return merged.changes.some((c) => c.action === \"warn\") ? 1 : 0;\n}\n"],"mappings":"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","names":[]}
|