@ken-jo/agent-connector 0.4.79 → 0.4.91
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 +3 -3
- package/dist/{action-OHGFVKMC.js → action-L44DXFHT.js} +9 -9
- package/dist/antigravity-cli-JO6GUTV7.js +436 -0
- package/dist/antigravity-cli-JO6GUTV7.js.map +1 -0
- package/dist/{chunk-X457NOFE.js → chunk-25CPWJA7.js} +91 -11
- package/dist/chunk-25CPWJA7.js.map +1 -0
- package/dist/{chunk-VKRGQLY4.js → chunk-7HUUINPB.js} +18 -18
- package/dist/{chunk-LKAVD4HP.js → chunk-BLTVZACS.js} +8 -8
- package/dist/{chunk-PZHB5TVA.js → chunk-G4CEELKO.js} +2 -2
- package/dist/{chunk-VD4EG6SG.js → chunk-KIRCPLM4.js} +5 -5
- package/dist/{chunk-ZXX5DVSE.js → chunk-LAIITCMW.js} +6 -6
- package/dist/{chunk-UYZ53KWS.js → chunk-LF76VPGQ.js} +5 -5
- package/dist/{chunk-IRUYJD23.js → chunk-NLE2J5P4.js} +1 -1
- package/dist/{chunk-7NXEHZAK.js → chunk-NWLRJNXM.js} +2 -2
- package/dist/{chunk-YJP3KGLM.js → chunk-QARPXSIV.js} +4 -4
- package/dist/{chunk-AMK2K6XZ.js → chunk-R6LML2YS.js} +2 -2
- package/dist/{chunk-S4E6QQEM.js → chunk-ZMLVR4J7.js} +7 -2
- package/dist/chunk-ZMLVR4J7.js.map +1 -0
- package/dist/{claude-code-T6ZRCMA7.js → claude-code-WS4NAGZT.js} +4 -4
- package/dist/cli/sdk.js +4 -4
- package/dist/cli.js +1 -1
- package/dist/codebuddy-RBEZGXBG.js +643 -0
- package/dist/codebuddy-RBEZGXBG.js.map +1 -0
- package/dist/{codex-RHKQKNNG.js → codex-ZZ434GYR.js} +4 -4
- package/dist/{detect-ALAKE54S.js → detect-3S46RUMK.js} +4 -4
- package/dist/devin-PRJY2TTD.js +510 -0
- package/dist/devin-PRJY2TTD.js.map +1 -0
- package/dist/{doctor-UNF7FCF4.js → doctor-3CUBPQKU.js} +14 -14
- package/dist/grok-cli-5QD235UB.js +482 -0
- package/dist/grok-cli-5QD235UB.js.map +1 -0
- package/dist/{hook-GM2IDA3C.js → hook-P6EKDINW.js} +9 -9
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/{install-7O4XWH7T.js → install-7DMK53SB.js} +10 -10
- package/dist/{introspect-5o5ick0_.d.ts → introspect-DYOIX8Ov.d.ts} +1 -1
- package/dist/{jetbrains-copilot-4IOT3I2Y.js → jetbrains-copilot-T2EPKROP.js} +9 -3
- package/dist/jetbrains-copilot-T2EPKROP.js.map +1 -0
- package/dist/junie-SQ4SDLGK.js +227 -0
- package/dist/junie-SQ4SDLGK.js.map +1 -0
- package/dist/{kilo-TAHOPT2Q.js → kilo-OU2ZLZKB.js} +4 -4
- package/dist/{kilo-cli-X4NPJWGX.js → kilo-cli-NMWGYF4F.js} +4 -4
- package/dist/{kiro-YZ4TTZGD.js → kiro-4IN5IH46.js} +77 -2
- package/dist/kiro-4IN5IH46.js.map +1 -0
- package/dist/{leaderboard-DVW4WYJ6.js → leaderboard-LF5SP6X2.js} +4 -4
- package/dist/mistral-vibe-TRQDHAWV.js +300 -0
- package/dist/mistral-vibe-TRQDHAWV.js.map +1 -0
- package/dist/open-interpreter-4PKL56AA.js +264 -0
- package/dist/open-interpreter-4PKL56AA.js.map +1 -0
- package/dist/openhands-5LNH3BKB.js +384 -0
- package/dist/openhands-5LNH3BKB.js.map +1 -0
- package/dist/{package-H5V3AZHR.js → package-2EAIYSJ4.js} +7 -7
- package/dist/{pi-I7BLL4EI.js → pi-BUADR5MJ.js} +139 -2
- package/dist/pi-BUADR5MJ.js.map +1 -0
- package/dist/{qwen-code-JG7AF442.js → qwen-code-TUJNHKNI.js} +4 -4
- package/dist/runtime/index.d.ts +1 -1
- package/dist/runtime/index.js +7 -7
- package/dist/sdk/index.d.ts +3 -3
- package/dist/sdk/index.js +3 -3
- package/dist/sdk/test.d.ts +2 -2
- package/dist/sdk/test.js +7 -7
- package/dist/{serve-WMO2TUW3.js → serve-K62FW3V7.js} +9 -9
- package/dist/{status-WRLBTBRE.js → status-E5MCFZM6.js} +7 -7
- package/dist/{statusline-EUD4DMIP.js → statusline-LIPF2KVP.js} +8 -8
- package/dist/{telemetry-U3LGMR3D.js → telemetry-4OC56NTM.js} +5 -5
- package/dist/{types-D6RWGXm1.d.ts → types-C4qMgbJn.d.ts} +10 -9
- package/dist/{uninstall-TWPUEJEC.js → uninstall-2YYKN5DX.js} +10 -10
- package/dist/{upgrade-EM6Y7QLH.js → upgrade-55AFPJEF.js} +10 -10
- package/dist/{usage-3HQDTXGY.js → usage-3PB3WZSL.js} +3 -3
- package/dist/{usage-event-DWIGKO7V.js → usage-event-KD5FW6W4.js} +8 -8
- package/dist/{zed-LLOAUXSA.js → zed-ZF2OQ75O.js} +119 -3
- package/dist/zed-ZF2OQ75O.js.map +1 -0
- package/package.json +1 -1
- package/dist/antigravity-cli-KODEKUTM.js +0 -87
- package/dist/antigravity-cli-KODEKUTM.js.map +0 -1
- package/dist/chunk-S4E6QQEM.js.map +0 -1
- package/dist/chunk-X457NOFE.js.map +0 -1
- package/dist/jetbrains-copilot-4IOT3I2Y.js.map +0 -1
- package/dist/kiro-YZ4TTZGD.js.map +0 -1
- package/dist/pi-I7BLL4EI.js.map +0 -1
- package/dist/zed-LLOAUXSA.js.map +0 -1
- /package/dist/{action-OHGFVKMC.js.map → action-L44DXFHT.js.map} +0 -0
- /package/dist/{chunk-VKRGQLY4.js.map → chunk-7HUUINPB.js.map} +0 -0
- /package/dist/{chunk-LKAVD4HP.js.map → chunk-BLTVZACS.js.map} +0 -0
- /package/dist/{chunk-PZHB5TVA.js.map → chunk-G4CEELKO.js.map} +0 -0
- /package/dist/{chunk-VD4EG6SG.js.map → chunk-KIRCPLM4.js.map} +0 -0
- /package/dist/{chunk-ZXX5DVSE.js.map → chunk-LAIITCMW.js.map} +0 -0
- /package/dist/{chunk-UYZ53KWS.js.map → chunk-LF76VPGQ.js.map} +0 -0
- /package/dist/{chunk-IRUYJD23.js.map → chunk-NLE2J5P4.js.map} +0 -0
- /package/dist/{chunk-7NXEHZAK.js.map → chunk-NWLRJNXM.js.map} +0 -0
- /package/dist/{chunk-YJP3KGLM.js.map → chunk-QARPXSIV.js.map} +0 -0
- /package/dist/{chunk-AMK2K6XZ.js.map → chunk-R6LML2YS.js.map} +0 -0
- /package/dist/{claude-code-T6ZRCMA7.js.map → claude-code-WS4NAGZT.js.map} +0 -0
- /package/dist/{codex-RHKQKNNG.js.map → codex-ZZ434GYR.js.map} +0 -0
- /package/dist/{detect-ALAKE54S.js.map → detect-3S46RUMK.js.map} +0 -0
- /package/dist/{doctor-UNF7FCF4.js.map → doctor-3CUBPQKU.js.map} +0 -0
- /package/dist/{hook-GM2IDA3C.js.map → hook-P6EKDINW.js.map} +0 -0
- /package/dist/{install-7O4XWH7T.js.map → install-7DMK53SB.js.map} +0 -0
- /package/dist/{kilo-TAHOPT2Q.js.map → kilo-OU2ZLZKB.js.map} +0 -0
- /package/dist/{kilo-cli-X4NPJWGX.js.map → kilo-cli-NMWGYF4F.js.map} +0 -0
- /package/dist/{leaderboard-DVW4WYJ6.js.map → leaderboard-LF5SP6X2.js.map} +0 -0
- /package/dist/{package-H5V3AZHR.js.map → package-2EAIYSJ4.js.map} +0 -0
- /package/dist/{qwen-code-JG7AF442.js.map → qwen-code-TUJNHKNI.js.map} +0 -0
- /package/dist/{serve-WMO2TUW3.js.map → serve-K62FW3V7.js.map} +0 -0
- /package/dist/{status-WRLBTBRE.js.map → status-E5MCFZM6.js.map} +0 -0
- /package/dist/{statusline-EUD4DMIP.js.map → statusline-LIPF2KVP.js.map} +0 -0
- /package/dist/{telemetry-U3LGMR3D.js.map → telemetry-4OC56NTM.js.map} +0 -0
- /package/dist/{uninstall-TWPUEJEC.js.map → uninstall-2YYKN5DX.js.map} +0 -0
- /package/dist/{upgrade-EM6Y7QLH.js.map → upgrade-55AFPJEF.js.map} +0 -0
- /package/dist/{usage-3HQDTXGY.js.map → usage-3PB3WZSL.js.map} +0 -0
- /package/dist/{usage-event-DWIGKO7V.js.map → usage-event-KD5FW6W4.js.map} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/adapters/devin/index.ts"],"sourcesContent":["/**\n * adapters/devin — Devin CLI (Cognition) platform adapter for agent-connector.\n *\n * Devin CLI is a Rust binary (`devin`, installed via `curl cli.devin.ai/install.sh`\n * → symlinked at `~/.local/bin/devin`; XDG namespace `devin`). It is a\n * **json-stdio** host: it ships a FULL Claude-Code-compatible lifecycle hook\n * system alongside MCP server registration. Both surfaces live in ONE JSON\n * config file per scope:\n *\n * - user scope → ~/.config/devin/config.json\n * (%APPDATA%\\devin\\config.json on Windows)\n * - project scope → <projectDir>/.devin/config.json\n *\n * MCP servers — root key `mcpServers` (object map keyed by server name; the\n * Claude-Desktop dialect). Native stdio entry { command, args?, env? } (NO\n * `type`/`disabled` discriminator); remote entry { url, transport?, headers?,\n * oauthClientId?, oauthClientSecret? } where transport is \"http\" (Streamable\n * HTTP, the URL default) or \"sse\" (legacy). Devin natively interpolates\n * `${env:VAR}` and `${file:/path}` in secret-bearing fields, so we PASS the\n * ${env:VAR} token THROUGH (nativeServerEnvInterpolation) rather than baking a\n * literal at install time. Primary source:\n * docs.devin.ai/cli/extensibility/mcp/configuration.\n *\n * Hooks — the `\"hooks\"` key IN the same config.json (root key `hooks`,\n * Claude NESTED-rule shape). Devin's hook format is documented as\n * \"compatible with Claude Code hooks\" — PascalCase event names, Claude\n * snake_case stdin wire fields. We deliberately write the `\"hooks\"` key in\n * config.json (a first-party-documented hook location whose object-map shape\n * fits the shared hook-merge engine exactly) rather than the alternative\n * standalone `.devin/hooks.v1.json` (whose event map is the WHOLE file with NO\n * `hooks` wrapper — incompatible with the engine's `file.hooks` contract). Both\n * are documented; config.json keeps us on the shared, Windows-safe engine with\n * zero hand-rolled file handling. Primary source:\n * docs.devin.ai/cli/extensibility/hooks/overview (\"Where Hooks Live\").\n *\n * Supported events (docs.devin.ai/cli/extensibility/hooks/lifecycle-hooks):\n * PreToolUse, PostToolUse, PermissionRequest, UserPromptSubmit, Stop,\n * PostCompaction (canonical PostCompact), SessionStart, SessionEnd. Devin\n * exposes no Notification / PreCompact / SubagentStart / SubagentStop /\n * PostToolUseFailure, so those degrade to a warn/skip at install time.\n *\n * Reply protocol — Devin's stdout reply is the SIMPLE top-level\n * { \"decision\": \"approve\"|\"block\"|\"deny\", \"reason\" } form (NOT Claude's\n * `hookSpecificOutput.permissionDecision` envelope). exit 0 = success,\n * exit 2 = block. \"block\" denies a tool/stop with a reason; on PermissionRequest\n * \"approve\"/\"deny\" are the grant/refuse verbs. Devin documents no\n * output-rewrite or context-injection reply channel, so canModifyOutput /\n * canInjectSessionContext stay false. Primary source:\n * docs.devin.ai/cli/extensibility/hooks/overview (\"Command Hooks\" output +\n * \"Exit Codes\") + lifecycle-hooks (PermissionRequest / Stop examples).\n */\n\nimport { existsSync } from \"node:fs\";\nimport { homedir, platform as osPlatform } from \"node:os\";\nimport { join } from \"node:path\";\n\nimport { BaseAdapter, type HookMergeDescriptor } 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 PermissionRequestEvent,\n PlatformCapabilities,\n PlatformId,\n PostCompactEvent,\n PostToolUseEvent,\n PreToolUseEvent,\n ServerDef,\n SessionEndEvent,\n SessionStartEvent,\n SkillDef,\n StopEvent,\n Transport,\n UserPromptSubmitEvent,\n} from \"../../core/types.js\";\nimport { rewriteEnvRefs } from \"../../core/interpolate.js\";\nimport {\n buildWrappedStdio,\n isHomeBinHookCommand,\n} from \"../../core/spawn.js\";\nimport { normalizeSessionSource } from \"../claude-code/wire.js\";\n\nconst HOST: PlatformId = \"devin\";\nconst MCP_ROOT_KEY = \"mcpServers\";\n\n/**\n * Resolve the Devin user config directory: ~/.config/devin (POSIX) or\n * %APPDATA%\\devin (Windows). Mirrors the documented user-scope path in\n * docs.devin.ai/cli/extensibility/mcp/configuration.\n */\nfunction devinUserConfigDir(): string {\n if (osPlatform() === \"win32\") {\n const appData = process.env.APPDATA ?? join(homedir(), \"AppData\", \"Roaming\");\n return join(appData, \"devin\");\n }\n return join(homedir(), \".config\", \"devin\");\n}\n\n/**\n * Canonical events Devin actually fires. Devin's hook event names are\n * Claude-identical PascalCase, so each canonical name is registered directly\n * EXCEPT PostCompaction, which Devin spells \"PostCompaction\" on the wire while\n * agent-connector's canonical name is \"PostCompact\" — handled by the descriptor\n * mapEvent / parseEvent so the home binary still dispatches on the canonical\n * \"PostCompact\" command.\n */\nconst SUPPORTED_EVENTS: ReadonlySet<HookEventName> = new Set<HookEventName>([\n \"PreToolUse\",\n \"PostToolUse\",\n \"PermissionRequest\",\n \"UserPromptSubmit\",\n \"Stop\",\n \"PostCompact\",\n \"SessionStart\",\n \"SessionEnd\",\n]);\n\n/** Devin's on-the-wire event name for the canonical PostCompact event. */\nconst DEVIN_POSTCOMPACT = \"PostCompaction\";\n\n/**\n * Native MCP server entry shapes Devin accepts under `mcpServers`.\n * A stdio entry is { command, args?, env? } — no type/disabled discriminator;\n * remote transports register a URL with an optional `transport` (\"http\"|\"sse\").\n */\ninterface DevinStdioServer {\n command: string;\n args?: string[];\n env?: Record<string, string>;\n}\ninterface DevinHttpServer {\n url: string;\n transport?: \"http\" | \"sse\";\n headers?: Record<string, string>;\n}\n\n/** A single Devin native hook registration entry (Claude-shaped, nested). */\ninterface DevinHookEntry {\n matcher: string;\n hooks: Array<{ type: \"command\"; command: string }>;\n}\n\n/** The shape of Devin's config.json hooks section (only the parts we touch). */\ninterface DevinHooksFile {\n hooks?: Record<string, DevinHookEntry[]>;\n [key: string]: unknown;\n}\n\n/** Raw Devin CLI hook stdin payload (Claude-compatible snake_case wire fields). */\ninterface DevinWireInput {\n hook_event_name?: string;\n tool_name?: string;\n tool_input?: Record<string, unknown>;\n /** PostToolUse — object { success, output, error }. */\n tool_response?: unknown;\n /** UserPromptSubmit — the user's message text. */\n prompt?: string;\n /** SessionStart — how the session was started. */\n source?: string;\n /** SessionEnd — why the session ended. */\n reason?: string;\n /** Stop loop guard. */\n stop_hook_active?: boolean;\n /** PostCompaction — compactor summary (may be null). Rides on raw; no normalized field. */\n summary?: unknown;\n /** Injected by the entrypoint so the runtime knows which connector to dispatch. */\n connector?: unknown;\n /** Session/cwd are not documented Devin wire fields; read defensively. */\n session_id?: string;\n cwd?: string;\n}\n\nexport class DevinAdapter extends BaseAdapter implements Adapter {\n readonly id: PlatformId = HOST;\n readonly name = \"Devin CLI (Cognition)\";\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 → ~/.config/devin/AGENTS.md (override below).\n // Devin reads AGENTS.md / AGENT.md / CLAUDE.md identically as always-on rules\n // (docs.devin.ai/cli/extensibility/rules).\n supportsMemory: true,\n preToolUse: true,\n postToolUse: true,\n userPromptSubmit: true,\n stop: true,\n sessionStart: true,\n sessionEnd: true,\n // PermissionRequest is a documented Devin hook event (decision-capable).\n permissionRequest: true,\n // PostCompaction (canonical PostCompact) — observe-only post-compaction hook.\n postCompact: true,\n // Devin documents NO Notification / PreCompact / SubagentStart / SubagentStop /\n // PostToolUseFailure event — those stay unset (install reports the skip-warn).\n notification: false,\n preCompact: false,\n // Devin's PreToolUse/PermissionRequest can block/deny via the simple\n // {decision} reply, but it documents no tool-arg/-output rewrite and no\n // context-injection reply channel.\n canModifyArgs: false,\n canModifyOutput: false,\n canInjectSessionContext: false,\n // Devin registers stdio and remote MCP servers. Remote is Streamable HTTP\n // (\"http\", the URL default) with a legacy \"sse\" fallback — both map to our\n // remote-transport handling; advertise both.\n transports: [\"stdio\", \"http\", \"sse\"],\n // Devin natively interpolates ${env:VAR} / ${file:/path} in secret-bearing\n // server fields, so the token survives into the host config (pass-through).\n nativeServerEnvInterpolation: true,\n // Content surfaces. Devin reads Agent Skills from its `.devin` config tree\n // at <configDir>/skills/<name>/SKILL.md — the SKILL.md format + frontmatter\n // are byte-confirmed (docs.devin.ai/cli/extensibility/skills/creating-skills),\n // so skills IS wired.\n supportsSkills: true,\n // Devin ALSO documents native slash commands (/cli/reference/commands) and\n // subagents (/cli/subagents), but their exact on-disk dir names are NOT\n // byte-confirmed from a first-party config reference — to avoid fabricating a\n // path, commands/subagents stay unset (BaseAdapter skip-warn) in v1. See the\n // module header CEILING note.\n };\n\n // ── Detection ────────────────────────────────────────────────────────────\n\n detectInstalled(projectDir: string): DetectedPlatform {\n const userDir = devinUserConfigDir();\n const userCfg = join(userDir, \"config.json\");\n const projDir = join(projectDir, \".devin\");\n const projCfg = join(projDir, \"config.json\");\n // The installed binary symlink (~/.local/bin/devin) is a strong marker even\n // before any config file is written.\n const binMarker = join(homedir(), \".local\", \"bin\", \"devin\");\n\n const userInstalled = existsSync(userDir) || existsSync(userCfg) || existsSync(binMarker);\n const projInstalled = existsSync(projDir) || existsSync(projCfg);\n const installed = userInstalled || projInstalled;\n const scope = projInstalled && !userInstalled ? \"project\" : \"user\";\n const configPath = scope === \"project\" ? projCfg : userCfg;\n\n return {\n id: this.id,\n name: this.name,\n installed,\n paradigm: this.paradigm,\n capabilities: this.capabilities,\n configPath,\n scope,\n reason: installed\n ? `found Devin CLI config (${scope}) at ${configPath}`\n : `no Devin CLI config at ${userDir} or ${projDir}`,\n confidence: installed ? \"high\" : \"low\",\n };\n }\n\n // ── Native paths ─────────────────────────────────────────────────────────\n\n getConfigDir(ctx: InstallContext): string {\n return ctx.scope === \"project\"\n ? join(ctx.projectDir, \".devin\")\n : devinUserConfigDir();\n }\n\n getServerConfigPath(ctx: InstallContext): string {\n return join(this.getConfigDir(ctx), \"config.json\");\n }\n\n /** Hooks live under the `\"hooks\"` key in the SAME config.json. */\n getHookConfigPath(ctx: InstallContext): string {\n return this.getServerConfigPath(ctx);\n }\n\n // ── Memory surface: user-scope AGENTS.md ─────────────────────────────────\n // Project scope rides on the AGENTS.md base default (project root). User scope\n // targets ~/.config/devin/AGENTS.md (%APPDATA%\\devin\\AGENTS.md on Windows) —\n // Devin's documented global-rules file (docs.devin.ai/cli/extensibility/rules).\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(devinUserConfigDir(), \"AGENTS.md\"),\n reason: \"Devin CLI global rules file (~/.config/devin/AGENTS.md)\",\n },\n ];\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 devin\"\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 Devin's native mcpServers entry. */\n private renderServerEntry(\n ctx: InstallContext,\n server: ServerDef,\n ): DevinStdioServer | DevinHttpServer {\n const transport: Transport = server.transport;\n\n if (transport === \"stdio\") {\n let command = server.command ?? \"\";\n let args = [...(server.args ?? [])];\n\n // Transparent telemetry wrapping: route the real command through\n // `<homeBin> serve --connector <id> -- <command> <args...>`.\n ({ command, args } = buildWrappedStdio(ctx, server, this.id, command, args));\n\n // command/args are passed verbatim (mirrors claude-code — they route\n // through the serve wrapper and rarely carry secrets).\n const entry: DevinStdioServer = { command };\n if (args.length > 0) entry.args = args;\n const env = this.renderEnv(server.env);\n if (env) entry.env = env;\n return entry;\n }\n\n // http / sse (and any other remote transport) — Devin registers a URL.\n // Map our \"http\" transport to Streamable HTTP (the URL default) and \"sse\" to\n // legacy SSE; omit `transport` for the default-http case to keep the entry\n // minimal (Devin infers http from a URL). ${env:VAR} survives into the\n // config via Devin's native interpolation (rewriteEnvRefs/devinEnvToken).\n const entry: DevinHttpServer = {\n url: rewriteEnvRefs(server.url ?? \"\", devinEnvToken),\n };\n if (transport === \"sse\") entry.transport = \"sse\";\n const headers = this.renderEnv(server.headers);\n if (headers) entry.headers = headers;\n return entry;\n }\n\n /**\n * Render env/header values. Devin interpolates ${env:VAR} natively, so each\n * ${env:VAR} token is passed THROUGH (rewriteEnvRefs/devinEnvToken) rather\n * than baked to a literal — secrets never land in the committed config.\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 const out: Record<string, string> = {};\n for (const [k, v] of Object.entries(env)) {\n out[k] = rewriteEnvRefs(v, devinEnvToken);\n }\n return out;\n }\n\n // ── Hook install / uninstall (config.json \"hooks\" key, nested-rule shape) ──\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 devin\" }];\n }\n if (connector.hookEvents.length === 0) {\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no hooks\" }];\n }\n\n const pending = connector.hookEvents.map((event) => ({\n event,\n matcher: connector.hooks[event]?.matcher ?? \"\",\n }));\n return this.upsertHookEntries(\n ctx,\n this.getHookConfigPath(ctx),\n pending,\n this.hookDescriptor(ctx),\n );\n }\n\n uninstallHooks(ctx: InstallContext): ChangeRecord[] {\n return this.removeHookEntries(ctx, this.getHookConfigPath(ctx), this.hookDescriptor(ctx));\n }\n\n /**\n * Devin's hook-merge descriptor (NESTED shape `{ matcher, hooks: [...] }`).\n * Bound to `ctx` because Devin's ownership is CONNECTOR-GENERIC (ANY of our\n * commands in the entry's inner `hooks`):\n * - mapEvent = drop events outside SUPPORTED_EVENTS; the canonical\n * PostCompact is rewritten to Devin's on-wire \"PostCompaction\" key while\n * all other supported events map 1:1.\n * - entryOwnsCommand reuses isOurCommand over the inner commands.\n * - uninstall = inner-strip ONLY (ownsEntryForRemove never-true).\n */\n private hookDescriptor(ctx: InstallContext): HookMergeDescriptor<DevinHookEntry> {\n return {\n mapEvent: (e) => {\n if (!SUPPORTED_EVENTS.has(e as HookEventName)) return undefined;\n return e === \"PostCompact\" ? DEVIN_POSTCOMPACT : e;\n },\n unmappedWarnDetail: (e) => `${e} has no Devin hook equivalent — skipped`,\n renderEntry: (_event, matcher, command) => ({\n matcher,\n hooks: [{ type: \"command\", command }],\n }),\n entryOwnsCommand: (entry, _command) =>\n (entry.hooks ?? []).some((h) => this.isOurCommand(h.command, ctx)),\n ownsEntryForRemove: () => () => false,\n stripInner: (c) => (entry) => {\n const innerBefore = entry.hooks?.length ?? 0;\n const inner = (entry.hooks ?? []).filter((h) => !this.isOurCommand(h.command, c));\n return {\n next: inner.length > 0 ? { matcher: entry.matcher ?? \"\", hooks: inner } : null,\n removed: innerBefore - inner.length,\n };\n },\n skipDetail: (event) => `hooks.${event} already registered`,\n removeDetail: (event, removed) => `hooks.${event} (${removed})`,\n absentDetail: \"no hooks section present\",\n noMatchDetail: \"no matching hook entries\",\n };\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 ──────────────────────────────────────────────\n // CEILING (v1): only the byte-confirmed SKILL.md layout is wired. Devin\n // documents the SKILL.md format + frontmatter\n // (docs.devin.ai/cli/extensibility/skills/creating-skills) under the `.devin`\n // tree (<configDir>/skills/<name>/SKILL.md). Commands/subagents on-disk dir\n // names are NOT byte-confirmed from a first-party config reference, so they\n // stay on the BaseAdapter skip-warn rather than guessing a path.\n\n /** Native skill dir: <configDir>/skills/<name>. */\n private skillDir(ctx: InstallContext, name: string): string {\n return join(this.getConfigDir(ctx), \"skills\", 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 devin\" }];\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\"), this.renderSkill(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 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 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.\n changes.push(this.removeDirIfEmpty(dir, ctx.dryRun));\n }\n return changes;\n }\n\n /**\n * Render a skill's SKILL.md: frontmatter (name, description) + body. Devin's\n * SKILL.md frontmatter documents name/description; extra keys pass through\n * verbatim. No model/allowed-tools skill field is emitted.\n */\n private renderSkill(skill: SkillDef): string {\n const frontmatter: Record<string, unknown> = {\n name: skill.name,\n description: skill.description,\n };\n if (skill.extra) Object.assign(frontmatter, skill.extra);\n return this.renderFrontmatterMd(frontmatter, skill.body);\n }\n\n // ── Diagnostics ──────────────────────────────────────────────────────────\n\n override getHealthChecks(ctx: InstallContext): readonly HealthCheck[] {\n const cfgPath = this.getServerConfigPath(ctx);\n const connectorId = ctx.connector.id;\n const homeBin = ctx.homeBinPath;\n const hookEvents = ctx.connector.hookEvents;\n return [\n {\n name: `${this.name}: config.json present`,\n check: () =>\n existsSync(cfgPath)\n ? { status: \"OK\", detail: cfgPath }\n : { status: \"FAIL\", detail: `not found: ${cfgPath}` },\n },\n {\n name: `${this.name}: server entry registered`,\n check: () => {\n if (!ctx.connector.server) {\n return { status: \"OK\", detail: \"no MCP server declared\" };\n }\n const cfg = this.readJson<{ [k: string]: Record<string, unknown> }>(cfgPath);\n const bucket = cfg?.[MCP_ROOT_KEY];\n if (!cfg || !bucket) {\n return { status: \"FAIL\", detail: `no ${MCP_ROOT_KEY} in ${cfgPath}` };\n }\n return connectorId in bucket\n ? { status: \"OK\", detail: `${MCP_ROOT_KEY}.${connectorId} present` }\n : {\n status: \"FAIL\",\n detail: `no ${MCP_ROOT_KEY}.${connectorId} in ${cfgPath}`,\n };\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 file = this.readJson<DevinHooksFile>(cfgPath);\n if (!file) return { status: \"FAIL\", detail: `cannot read ${cfgPath}` };\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 ${cfgPath}` };\n },\n },\n ];\n }\n\n // ── Runtime: parse Devin stdin JSON → normalized event ─────────────────────\n\n parseEvent(event: HookEventName, raw: unknown): NormalizedEvent {\n const input = (raw ?? {}) as DevinWireInput;\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 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 ev: PostToolUseEvent = {\n ...base,\n toolName: input.tool_name ?? \"\",\n toolInput: input.tool_input ?? {},\n ...(toolResponseToString(input.tool_response) !== undefined\n ? { toolOutput: toolResponseToString(input.tool_response) }\n : {}),\n };\n return ev;\n }\n case \"PermissionRequest\": {\n // Devin PermissionRequest stdin: { tool_name, tool_input }. No\n // permission-suggestion entries are documented.\n const ev: PermissionRequestEvent = {\n ...base,\n toolName: input.tool_name ?? \"\",\n toolInput: input.tool_input ?? {},\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 \"PostCompact\": {\n // Devin's PostCompaction wire carries { summary } (no trigger enum);\n // summary rides on base.raw (no normalized field).\n const ev: PostCompactEvent = { ...base };\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 default: {\n // Devin never delivers Notification / PreCompact / SubagentStart /\n // SubagentStop / PostToolUseFailure (see SUPPORTED_EVENTS). Surface it\n // loudly rather than silently mis-parse.\n throw new Error(`unsupported devin hook event: ${String(event)}`);\n }\n }\n }\n\n // ── Runtime: normalized response → Devin native (simple {decision}) reply ──\n\n formatReply(event: HookEventName, response: HookResponse): HookReply {\n const decision = response.decision ?? \"allow\";\n\n // PostCompaction / SessionEnd are observe-only — no Decision Control. Every\n // decision is an unconditional no-op passthrough.\n if (event === \"PostCompact\" || event === \"SessionEnd\") {\n return { exitCode: 0 };\n }\n\n // PermissionRequest: an explicit allow is an active GRANT (Devin's \"approve\"\n // verb); deny refuses the tool. ask/context/void fall through to the native\n // dialog (exit 0, no decision output).\n if (event === \"PermissionRequest\") {\n if (decision === \"deny\") {\n return this.stdout({\n decision: \"deny\",\n reason: response.reason ?? \"Denied by hook\",\n });\n }\n if (decision === \"allow\") {\n return this.stdout({ decision: \"approve\" });\n }\n return { exitCode: 0 };\n }\n\n // deny → block the action with a reason (Devin's top-level {decision:\"block\"}\n // form, NOT Claude's hookSpecificOutput envelope). Covers PreToolUse and\n // Stop (Stop-block keeps the agent running with `reason` as guidance).\n if (decision === \"deny\") {\n return this.stdout({\n decision: \"block\",\n reason: response.reason ?? \"Blocked by hook\",\n });\n }\n\n // ask is not a distinct Devin reply verb (only approve/block/deny) — fall\n // through to allow. allow / modify (no rewrite channel) / context (no\n // injection channel) / void → 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 * Devin's native interpolation token reconstructor. Devin reads the SAME\n * `${env:VAR}` (and `${env:VAR:-default}`) form the connector author writes, so\n * the rewrite is a faithful round-trip of the token (Devin resolves it at\n * runtime — the secret never lands in the committed config).\n */\nfunction devinEnvToken(name: string, def?: string): string {\n return def !== undefined ? `\\${env:${name}:-${def}}` : `\\${env:${name}}`;\n}\n\n/** Coerce a Devin PostToolUse `tool_response` into a string for the normalized event. */\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 DevinAdapter();\nexport default adapter;\n"],"mappings":"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","names":["entry"]}
|
|
@@ -2,18 +2,20 @@
|
|
|
2
2
|
import {
|
|
3
3
|
marketplaceDoctorChecks,
|
|
4
4
|
syncConnector
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
5
|
+
} from "./chunk-KIRCPLM4.js";
|
|
6
|
+
import "./chunk-LF76VPGQ.js";
|
|
7
7
|
import {
|
|
8
8
|
readMarketplaceInstalls
|
|
9
9
|
} from "./chunk-QKLJU4JX.js";
|
|
10
|
+
import "./chunk-UM5S7DKK.js";
|
|
10
11
|
import "./chunk-NBUEL74R.js";
|
|
12
|
+
import "./chunk-OPXAP3AC.js";
|
|
11
13
|
import {
|
|
12
14
|
fail,
|
|
13
15
|
parseScope,
|
|
14
16
|
parseTargets,
|
|
15
17
|
print
|
|
16
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-7HUUINPB.js";
|
|
17
19
|
import {
|
|
18
20
|
LineBuffer,
|
|
19
21
|
idKey,
|
|
@@ -24,30 +26,28 @@ import {
|
|
|
24
26
|
} from "./chunk-LN76OGNR.js";
|
|
25
27
|
import {
|
|
26
28
|
detectInstalledPlatforms
|
|
27
|
-
} from "./chunk-
|
|
29
|
+
} from "./chunk-ZMLVR4J7.js";
|
|
28
30
|
import {
|
|
29
31
|
explainHooks
|
|
30
|
-
} from "./chunk-
|
|
31
|
-
import "./chunk-
|
|
32
|
-
import "./chunk-4FWETID5.js";
|
|
32
|
+
} from "./chunk-QARPXSIV.js";
|
|
33
|
+
import "./chunk-LAIITCMW.js";
|
|
33
34
|
import "./chunk-KHO5WNTP.js";
|
|
34
|
-
import "./chunk-
|
|
35
|
+
import "./chunk-4FWETID5.js";
|
|
36
|
+
import "./chunk-R6LML2YS.js";
|
|
35
37
|
import {
|
|
36
38
|
findConnectorConfig,
|
|
37
39
|
listRegisteredConnectors,
|
|
38
40
|
loadConnectorFromPath,
|
|
39
41
|
readRegisteredMeta
|
|
40
|
-
} from "./chunk-
|
|
42
|
+
} from "./chunk-NWLRJNXM.js";
|
|
41
43
|
import {
|
|
42
44
|
MCP_PROTOCOL_VERSION
|
|
43
|
-
} from "./chunk-
|
|
45
|
+
} from "./chunk-G4CEELKO.js";
|
|
44
46
|
import {
|
|
45
47
|
REGISTERED_PLATFORM_IDS,
|
|
46
48
|
loadAdapter
|
|
47
|
-
} from "./chunk-
|
|
49
|
+
} from "./chunk-25CPWJA7.js";
|
|
48
50
|
import "./chunk-56R2ER7K.js";
|
|
49
|
-
import "./chunk-OPXAP3AC.js";
|
|
50
|
-
import "./chunk-UM5S7DKK.js";
|
|
51
51
|
import "./chunk-H53QZQJI.js";
|
|
52
52
|
import "./chunk-BEFVJ2OE.js";
|
|
53
53
|
import "./chunk-VVFDU4IX.js";
|
|
@@ -623,4 +623,4 @@ async function run(argv) {
|
|
|
623
623
|
export {
|
|
624
624
|
run
|
|
625
625
|
};
|
|
626
|
-
//# sourceMappingURL=doctor-
|
|
626
|
+
//# sourceMappingURL=doctor-3CUBPQKU.js.map
|
|
@@ -0,0 +1,482 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
normalizeSessionSource
|
|
4
|
+
} from "./chunk-H53QZQJI.js";
|
|
5
|
+
import {
|
|
6
|
+
resolveEnvRefsDeep
|
|
7
|
+
} from "./chunk-BEFVJ2OE.js";
|
|
8
|
+
import {
|
|
9
|
+
BaseAdapter
|
|
10
|
+
} from "./chunk-VVFDU4IX.js";
|
|
11
|
+
import {
|
|
12
|
+
buildWrappedStdio,
|
|
13
|
+
isHomeBinHookCommand
|
|
14
|
+
} from "./chunk-HORHRHNG.js";
|
|
15
|
+
import "./chunk-YYNXIUR2.js";
|
|
16
|
+
import "./chunk-IXOQDZWC.js";
|
|
17
|
+
|
|
18
|
+
// src/adapters/grok-cli/index.ts
|
|
19
|
+
import { existsSync } from "fs";
|
|
20
|
+
import { homedir } from "os";
|
|
21
|
+
import { join } from "path";
|
|
22
|
+
var HOST = "grok-cli";
|
|
23
|
+
var SUPPORTED_EVENTS = /* @__PURE__ */ new Set([
|
|
24
|
+
"PreToolUse",
|
|
25
|
+
"PostToolUse",
|
|
26
|
+
"PostToolUseFailure",
|
|
27
|
+
"UserPromptSubmit",
|
|
28
|
+
"SessionStart",
|
|
29
|
+
"SessionEnd",
|
|
30
|
+
"Stop",
|
|
31
|
+
"SubagentStart",
|
|
32
|
+
"SubagentStop",
|
|
33
|
+
"PreCompact",
|
|
34
|
+
"PostCompact",
|
|
35
|
+
"Notification"
|
|
36
|
+
]);
|
|
37
|
+
var GrokCliAdapter = class extends BaseAdapter {
|
|
38
|
+
id = HOST;
|
|
39
|
+
name = "Grok CLI";
|
|
40
|
+
paradigm = "json-stdio";
|
|
41
|
+
capabilities = {
|
|
42
|
+
// Memory surface: Grok reads AGENTS.md ("merged from git root down to your
|
|
43
|
+
// cwd; AGENTS.override.md wins per directory" — README). The BaseAdapter
|
|
44
|
+
// AGENTS.md-first default handles it.
|
|
45
|
+
supportsMemory: true,
|
|
46
|
+
preToolUse: true,
|
|
47
|
+
postToolUse: true,
|
|
48
|
+
postToolUseFailure: true,
|
|
49
|
+
userPromptSubmit: true,
|
|
50
|
+
sessionStart: true,
|
|
51
|
+
sessionEnd: true,
|
|
52
|
+
stop: true,
|
|
53
|
+
notification: true,
|
|
54
|
+
preCompact: true,
|
|
55
|
+
// Grok fires PostCompact (its HOOK_EVENTS lists it beside PreCompact).
|
|
56
|
+
postCompact: true,
|
|
57
|
+
// Grok fires SubagentStart AND SubagentStop (both in HOOK_EVENTS).
|
|
58
|
+
subagentStart: true,
|
|
59
|
+
subagentStop: true,
|
|
60
|
+
// No PermissionRequest event in Grok's HOOK_EVENTS → warn/skip at install.
|
|
61
|
+
// Grok's reply protocol is block/approve/context only — it cannot rewrite
|
|
62
|
+
// tool args or already-emitted output.
|
|
63
|
+
canModifyArgs: false,
|
|
64
|
+
canModifyOutput: false,
|
|
65
|
+
// Grok injects `additionalContext` from a hook's stdout JSON.
|
|
66
|
+
canInjectSessionContext: true,
|
|
67
|
+
// Grok's settings.json hook keys are free-form event names (its HOOK_EVENTS
|
|
68
|
+
// superset includes StopFailure/TaskCreated/TaskCompleted/InstructionsLoaded/
|
|
69
|
+
// CwdChanged with no canonical analog), so any host event declared under
|
|
70
|
+
// platforms["grok-cli"].nativeHooks installs verbatim.
|
|
71
|
+
supportsNativeHooks: true,
|
|
72
|
+
// MCP entry supports stdio + remote (http / sse) per McpServerConfig.transport.
|
|
73
|
+
transports: ["stdio", "http", "sse"]
|
|
74
|
+
};
|
|
75
|
+
// ── Detection ────────────────────────────────────────────────────────────
|
|
76
|
+
detectInstalled(_projectDir) {
|
|
77
|
+
const userDir = join(homedir(), ".grok");
|
|
78
|
+
const userSettings = join(userDir, "user-settings.json");
|
|
79
|
+
const installed = existsSync(userDir) || existsSync(userSettings);
|
|
80
|
+
return {
|
|
81
|
+
id: this.id,
|
|
82
|
+
name: this.name,
|
|
83
|
+
installed,
|
|
84
|
+
paradigm: this.paradigm,
|
|
85
|
+
capabilities: this.capabilities,
|
|
86
|
+
// MCP + hooks both live in user-settings.json (user scope only).
|
|
87
|
+
configPath: userSettings,
|
|
88
|
+
scope: "user",
|
|
89
|
+
reason: installed ? `found Grok CLI config at ${userSettings}` : `no Grok CLI config at ${userDir}`,
|
|
90
|
+
confidence: installed ? "high" : "low"
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
// ── Native paths ───────────────────────────────────────────────────────────
|
|
94
|
+
// BOTH MCP servers (mcp.servers array) and hooks (top-level hooks map) live in
|
|
95
|
+
// the SAME user-settings.json. Project .grok/settings.json holds neither, so
|
|
96
|
+
// every scope resolves to the user file.
|
|
97
|
+
getConfigDir(_ctx) {
|
|
98
|
+
return join(homedir(), ".grok");
|
|
99
|
+
}
|
|
100
|
+
getServerConfigPath(ctx) {
|
|
101
|
+
return join(this.getConfigDir(ctx), "user-settings.json");
|
|
102
|
+
}
|
|
103
|
+
getHookConfigPath(ctx) {
|
|
104
|
+
return join(this.getConfigDir(ctx), "user-settings.json");
|
|
105
|
+
}
|
|
106
|
+
// ── MCP server install / uninstall (JSON — nested mcp.servers ARRAY) ───────
|
|
107
|
+
installServer(ctx) {
|
|
108
|
+
const { connector, dryRun } = ctx;
|
|
109
|
+
const path = this.getServerConfigPath(ctx);
|
|
110
|
+
const override = connector.platforms[HOST]?.server;
|
|
111
|
+
if (!connector.server || override === false) {
|
|
112
|
+
return [
|
|
113
|
+
{
|
|
114
|
+
platform: this.id,
|
|
115
|
+
action: "skip",
|
|
116
|
+
path,
|
|
117
|
+
detail: connector.server ? "server registration disabled for grok-cli" : "connector declares no MCP server"
|
|
118
|
+
}
|
|
119
|
+
];
|
|
120
|
+
}
|
|
121
|
+
const symlink = this.symlinkPathWarning(path);
|
|
122
|
+
if (symlink) return [symlink];
|
|
123
|
+
const server = override && typeof override === "object" ? { ...connector.server, ...override } : connector.server;
|
|
124
|
+
const entry = this.renderServerEntry(ctx, server);
|
|
125
|
+
if (this.isPresentButUnparseable(path)) {
|
|
126
|
+
return [
|
|
127
|
+
{
|
|
128
|
+
platform: this.id,
|
|
129
|
+
action: "warn",
|
|
130
|
+
path,
|
|
131
|
+
detail: `existing ${path} is not parseable; left untouched (back it up / fix it, then re-run)`
|
|
132
|
+
}
|
|
133
|
+
];
|
|
134
|
+
}
|
|
135
|
+
const cfg = this.readJson(path) ?? {};
|
|
136
|
+
const existingMcp = cfg.mcp;
|
|
137
|
+
if (existingMcp !== void 0 && (typeof existingMcp !== "object" || Array.isArray(existingMcp))) {
|
|
138
|
+
return [{ platform: this.id, action: "warn", path, detail: "mcp is not an object \u2014 left untouched (manual fix needed)" }];
|
|
139
|
+
}
|
|
140
|
+
const existingServers = existingMcp?.servers;
|
|
141
|
+
if (existingServers !== void 0 && !Array.isArray(existingServers)) {
|
|
142
|
+
return [{ platform: this.id, action: "warn", path, detail: "mcp.servers is not an array \u2014 left untouched (manual fix needed)" }];
|
|
143
|
+
}
|
|
144
|
+
const list = Array.isArray(existingServers) ? [...existingServers] : [];
|
|
145
|
+
const idx = list.findIndex((e) => e?.id === connector.id);
|
|
146
|
+
let action;
|
|
147
|
+
if (idx < 0) {
|
|
148
|
+
list.push(entry);
|
|
149
|
+
action = "create";
|
|
150
|
+
} else if (JSON.stringify(list[idx]) === JSON.stringify(entry)) {
|
|
151
|
+
action = "skip";
|
|
152
|
+
} else {
|
|
153
|
+
list[idx] = entry;
|
|
154
|
+
action = "update";
|
|
155
|
+
}
|
|
156
|
+
if (action !== "skip") {
|
|
157
|
+
cfg.mcp = { ...existingMcp ?? {}, servers: list };
|
|
158
|
+
this.writeJson(path, cfg, dryRun);
|
|
159
|
+
}
|
|
160
|
+
return [{ platform: this.id, action, path, detail: `mcp.servers[id=${connector.id}]` }];
|
|
161
|
+
}
|
|
162
|
+
uninstallServer(ctx) {
|
|
163
|
+
const { connector, dryRun } = ctx;
|
|
164
|
+
const path = this.getServerConfigPath(ctx);
|
|
165
|
+
const symlink = this.symlinkPathWarning(path);
|
|
166
|
+
if (symlink) return [symlink];
|
|
167
|
+
const cfg = this.readJson(path);
|
|
168
|
+
const rawList = cfg?.mcp?.servers;
|
|
169
|
+
if (!cfg || !Array.isArray(rawList)) {
|
|
170
|
+
return [{ platform: this.id, action: "skip", path, detail: `mcp.servers[id=${connector.id}] absent` }];
|
|
171
|
+
}
|
|
172
|
+
const list = rawList;
|
|
173
|
+
const kept = list.filter((e) => e?.id !== connector.id);
|
|
174
|
+
if (kept.length === list.length) {
|
|
175
|
+
return [{ platform: this.id, action: "skip", path, detail: `mcp.servers[id=${connector.id}] absent` }];
|
|
176
|
+
}
|
|
177
|
+
cfg.mcp = { ...cfg.mcp, servers: kept };
|
|
178
|
+
this.writeJson(path, cfg, dryRun);
|
|
179
|
+
return [{ platform: this.id, action: "remove", path, detail: `mcp.servers[id=${connector.id}]` }];
|
|
180
|
+
}
|
|
181
|
+
/** Render a normalized ServerDef into Grok's native McpServerConfig entry. */
|
|
182
|
+
renderServerEntry(ctx, server) {
|
|
183
|
+
const transport = server.transport;
|
|
184
|
+
const enabled = server.enabled !== false;
|
|
185
|
+
const id = ctx.connector.id;
|
|
186
|
+
const label = ctx.connector.displayName?.trim() || id;
|
|
187
|
+
if (transport === "stdio") {
|
|
188
|
+
let command = server.command ?? "";
|
|
189
|
+
let args = [...server.args ?? []];
|
|
190
|
+
({ command, args } = buildWrappedStdio(ctx, server, this.id, command, args));
|
|
191
|
+
const entry2 = {
|
|
192
|
+
id,
|
|
193
|
+
label,
|
|
194
|
+
enabled,
|
|
195
|
+
transport: "stdio",
|
|
196
|
+
command: resolveEnvRefsDeep(command)
|
|
197
|
+
};
|
|
198
|
+
if (args.length > 0) entry2.args = resolveEnvRefsDeep(args);
|
|
199
|
+
const env = this.renderEnv(server.env);
|
|
200
|
+
if (env) entry2.env = env;
|
|
201
|
+
if (typeof server.cwd === "string" && server.cwd.length > 0) {
|
|
202
|
+
entry2.cwd = resolveEnvRefsDeep(server.cwd);
|
|
203
|
+
}
|
|
204
|
+
return entry2;
|
|
205
|
+
}
|
|
206
|
+
const entry = {
|
|
207
|
+
id,
|
|
208
|
+
label,
|
|
209
|
+
enabled,
|
|
210
|
+
transport: transport === "sse" ? "sse" : "http",
|
|
211
|
+
url: resolveEnvRefsDeep(server.url ?? "")
|
|
212
|
+
};
|
|
213
|
+
const headers = this.renderEnv(server.headers);
|
|
214
|
+
if (headers) entry.headers = headers;
|
|
215
|
+
return entry;
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Render env/header values. Grok documents no native ${VAR} server
|
|
219
|
+
* interpolation, so resolve `${env:VAR}` references to literals at install
|
|
220
|
+
* time (the safe path; matches continue/droid).
|
|
221
|
+
*/
|
|
222
|
+
renderEnv(env) {
|
|
223
|
+
if (!env || Object.keys(env).length === 0) return void 0;
|
|
224
|
+
return resolveEnvRefsDeep({ ...env });
|
|
225
|
+
}
|
|
226
|
+
// ── Hook install / uninstall (top-level hooks, Claude nested-rule shape) ───
|
|
227
|
+
installHooks(ctx) {
|
|
228
|
+
const { connector } = ctx;
|
|
229
|
+
const override = connector.platforms[HOST];
|
|
230
|
+
const normalizedEvents = override?.hooks === false ? [] : connector.hookEvents;
|
|
231
|
+
const nativeHooks = override?.nativeHooks ?? {};
|
|
232
|
+
const nativeEvents = Object.keys(nativeHooks);
|
|
233
|
+
if (normalizedEvents.length === 0 && nativeEvents.length === 0) {
|
|
234
|
+
return [
|
|
235
|
+
{
|
|
236
|
+
platform: this.id,
|
|
237
|
+
action: "skip",
|
|
238
|
+
detail: override?.hooks === false ? "hooks disabled for grok-cli" : "connector declares no hooks"
|
|
239
|
+
}
|
|
240
|
+
];
|
|
241
|
+
}
|
|
242
|
+
const pending = normalizedEvents.map((event) => ({
|
|
243
|
+
event,
|
|
244
|
+
matcher: connector.hooks[event]?.matcher ?? ""
|
|
245
|
+
}));
|
|
246
|
+
const native = nativeEvents.map((event) => ({
|
|
247
|
+
event,
|
|
248
|
+
matcher: nativeHooks[event]?.matcher ?? ""
|
|
249
|
+
}));
|
|
250
|
+
return this.upsertHookEntries(
|
|
251
|
+
ctx,
|
|
252
|
+
this.getHookConfigPath(ctx),
|
|
253
|
+
pending,
|
|
254
|
+
this.hookDescriptor(ctx),
|
|
255
|
+
native
|
|
256
|
+
);
|
|
257
|
+
}
|
|
258
|
+
uninstallHooks(ctx) {
|
|
259
|
+
return this.removeHookEntries(ctx, this.getHookConfigPath(ctx), this.hookDescriptor(ctx));
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Grok's hook-merge descriptor (NESTED shape `{ matcher?, hooks: [...] }`).
|
|
263
|
+
* Connector-generic ownership (any of our home-bin commands in the inner
|
|
264
|
+
* `hooks`), matching droid:
|
|
265
|
+
* - mapEvent drops events outside SUPPORTED_EVENTS (Grok has no
|
|
266
|
+
* PermissionRequest); supported events map 1:1 (PascalCase identical);
|
|
267
|
+
* - the native pass installs free-form host-only event keys verbatim;
|
|
268
|
+
* - uninstall = inner-strip ONLY (ownsEntryForRemove never-true).
|
|
269
|
+
*/
|
|
270
|
+
hookDescriptor(ctx) {
|
|
271
|
+
const stripInner = (c) => (entry) => {
|
|
272
|
+
const innerBefore = entry.hooks?.length ?? 0;
|
|
273
|
+
const inner = (entry.hooks ?? []).filter((h) => !this.isOurCommand(h.command, c));
|
|
274
|
+
return {
|
|
275
|
+
next: inner.length > 0 ? { matcher: entry.matcher ?? "", hooks: inner } : null,
|
|
276
|
+
removed: innerBefore - inner.length
|
|
277
|
+
};
|
|
278
|
+
};
|
|
279
|
+
return {
|
|
280
|
+
mapEvent: (e) => SUPPORTED_EVENTS.has(e) ? e : void 0,
|
|
281
|
+
unmappedWarnDetail: (e) => `${e} has no Grok CLI hook equivalent \u2014 skipped`,
|
|
282
|
+
renderEntry: (_event, matcher, command) => ({
|
|
283
|
+
matcher,
|
|
284
|
+
hooks: [{ type: "command", command }]
|
|
285
|
+
}),
|
|
286
|
+
entryOwnsCommand: (entry, _command) => (entry.hooks ?? []).some((h) => this.isOurCommand(h.command, ctx)),
|
|
287
|
+
nativeOwnsCommand: (entry, command) => (entry.hooks ?? []).some((h) => h.command === command),
|
|
288
|
+
ownsEntryForRemove: () => () => false,
|
|
289
|
+
stripInner,
|
|
290
|
+
skipDetail: (event) => `hooks.${event} already registered`,
|
|
291
|
+
removeDetail: (event, removed) => `hooks.${event} (${removed})`,
|
|
292
|
+
nativeSkipDetail: (event) => `hooks.${event} already registered (native)`,
|
|
293
|
+
nativeMutateDetail: (event) => `hooks.${event} (native)`,
|
|
294
|
+
absentDetail: "no hooks section present",
|
|
295
|
+
noMatchDetail: "no matching hook entries"
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
/** True when a hook command references our home binary AND this connector id. */
|
|
299
|
+
isOurCommand(command, ctx) {
|
|
300
|
+
return isHomeBinHookCommand(command, ctx.homeBinPath, ctx.connector.id);
|
|
301
|
+
}
|
|
302
|
+
// ── Diagnostics ──────────────────────────────────────────────────────────
|
|
303
|
+
getHealthChecks(ctx) {
|
|
304
|
+
const path = this.getServerConfigPath(ctx);
|
|
305
|
+
const connectorId = ctx.connector.id;
|
|
306
|
+
const homeBin = ctx.homeBinPath;
|
|
307
|
+
const hookEvents = ctx.connector.hookEvents;
|
|
308
|
+
return [
|
|
309
|
+
{
|
|
310
|
+
name: `${this.name}: user-settings.json present`,
|
|
311
|
+
check: () => existsSync(path) ? { status: "OK", detail: path } : { status: "FAIL", detail: `not found: ${path}` }
|
|
312
|
+
},
|
|
313
|
+
{
|
|
314
|
+
name: `${this.name}: server entry registered`,
|
|
315
|
+
check: () => {
|
|
316
|
+
if (!ctx.connector.server) {
|
|
317
|
+
return { status: "OK", detail: "no MCP server declared" };
|
|
318
|
+
}
|
|
319
|
+
const cfg = this.readJson(path);
|
|
320
|
+
const list = cfg?.mcp?.servers;
|
|
321
|
+
if (!cfg || !Array.isArray(list)) {
|
|
322
|
+
return { status: "FAIL", detail: `no mcp.servers array in ${path}` };
|
|
323
|
+
}
|
|
324
|
+
return list.some((e) => e?.id === connectorId) ? { status: "OK", detail: `mcp.servers[id=${connectorId}] present` } : { status: "FAIL", detail: `no mcp.servers[id=${connectorId}] in ${path}` };
|
|
325
|
+
}
|
|
326
|
+
},
|
|
327
|
+
{
|
|
328
|
+
name: `${this.name}: hook command registered`,
|
|
329
|
+
check: () => {
|
|
330
|
+
if (hookEvents.length === 0) {
|
|
331
|
+
return { status: "OK", detail: "no hooks declared" };
|
|
332
|
+
}
|
|
333
|
+
const cfg = this.readJson(path);
|
|
334
|
+
const hooks = cfg?.hooks ?? {};
|
|
335
|
+
const registered = Object.values(hooks).some(
|
|
336
|
+
(entries) => (entries ?? []).some(
|
|
337
|
+
(e) => (e.hooks ?? []).some((h) => isHomeBinHookCommand(h.command, homeBin, connectorId))
|
|
338
|
+
)
|
|
339
|
+
);
|
|
340
|
+
return registered ? { status: "OK", detail: "hook command present" } : { status: "FAIL", detail: `no hook for ${connectorId} in ${path}` };
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
];
|
|
344
|
+
}
|
|
345
|
+
// ── Runtime: parse Grok stdin JSON → normalized event ──────────────────────
|
|
346
|
+
parseEvent(event, raw) {
|
|
347
|
+
const input = raw ?? {};
|
|
348
|
+
const connectorId = typeof input.connector === "string" ? input.connector : "";
|
|
349
|
+
const sessionId = typeof input.session_id === "string" ? input.session_id : "";
|
|
350
|
+
const projectDir = typeof input.cwd === "string" ? input.cwd : void 0;
|
|
351
|
+
const base = {
|
|
352
|
+
hostPlatform: HOST,
|
|
353
|
+
connectorId,
|
|
354
|
+
sessionId,
|
|
355
|
+
raw,
|
|
356
|
+
...projectDir !== void 0 ? { projectDir } : {}
|
|
357
|
+
};
|
|
358
|
+
switch (event) {
|
|
359
|
+
case "PreToolUse": {
|
|
360
|
+
const ev = {
|
|
361
|
+
...base,
|
|
362
|
+
toolName: typeof input.tool_name === "string" ? input.tool_name : "",
|
|
363
|
+
toolInput: input.tool_input ?? {}
|
|
364
|
+
};
|
|
365
|
+
return ev;
|
|
366
|
+
}
|
|
367
|
+
case "PostToolUse": {
|
|
368
|
+
const ev = {
|
|
369
|
+
...base,
|
|
370
|
+
toolName: typeof input.tool_name === "string" ? input.tool_name : "",
|
|
371
|
+
toolInput: input.tool_input ?? {},
|
|
372
|
+
...toolOutputToString(input.tool_output) !== void 0 ? { toolOutput: toolOutputToString(input.tool_output) } : {}
|
|
373
|
+
};
|
|
374
|
+
return ev;
|
|
375
|
+
}
|
|
376
|
+
case "PostToolUseFailure": {
|
|
377
|
+
const ev = {
|
|
378
|
+
...base,
|
|
379
|
+
toolName: typeof input.tool_name === "string" ? input.tool_name : "",
|
|
380
|
+
toolInput: input.tool_input ?? {},
|
|
381
|
+
error: typeof input.error === "string" ? input.error : ""
|
|
382
|
+
};
|
|
383
|
+
return ev;
|
|
384
|
+
}
|
|
385
|
+
case "UserPromptSubmit": {
|
|
386
|
+
const ev = {
|
|
387
|
+
...base,
|
|
388
|
+
prompt: typeof input.user_prompt === "string" ? input.user_prompt : ""
|
|
389
|
+
};
|
|
390
|
+
return ev;
|
|
391
|
+
}
|
|
392
|
+
case "SessionStart": {
|
|
393
|
+
const ev = {
|
|
394
|
+
...base,
|
|
395
|
+
source: normalizeSessionSource(input.source)
|
|
396
|
+
};
|
|
397
|
+
return ev;
|
|
398
|
+
}
|
|
399
|
+
case "SessionEnd": {
|
|
400
|
+
const ev = { ...base };
|
|
401
|
+
return ev;
|
|
402
|
+
}
|
|
403
|
+
case "Stop": {
|
|
404
|
+
const ev = { ...base };
|
|
405
|
+
return ev;
|
|
406
|
+
}
|
|
407
|
+
case "Notification": {
|
|
408
|
+
const ev = {
|
|
409
|
+
...base,
|
|
410
|
+
message: typeof input.message === "string" ? input.message : ""
|
|
411
|
+
};
|
|
412
|
+
return ev;
|
|
413
|
+
}
|
|
414
|
+
case "PreCompact": {
|
|
415
|
+
const ev = {
|
|
416
|
+
...base,
|
|
417
|
+
...input.trigger === "auto" || input.trigger === "manual" ? { trigger: input.trigger } : {}
|
|
418
|
+
};
|
|
419
|
+
return ev;
|
|
420
|
+
}
|
|
421
|
+
case "PostCompact": {
|
|
422
|
+
const ev = {
|
|
423
|
+
...base,
|
|
424
|
+
...input.trigger === "auto" || input.trigger === "manual" ? { trigger: input.trigger } : {}
|
|
425
|
+
};
|
|
426
|
+
return ev;
|
|
427
|
+
}
|
|
428
|
+
case "SubagentStart": {
|
|
429
|
+
const ev = {
|
|
430
|
+
...base,
|
|
431
|
+
...typeof input.agent_type === "string" ? { agentType: input.agent_type } : {}
|
|
432
|
+
};
|
|
433
|
+
return ev;
|
|
434
|
+
}
|
|
435
|
+
case "SubagentStop": {
|
|
436
|
+
const ev = {
|
|
437
|
+
...base,
|
|
438
|
+
...typeof input.agent_type === "string" ? { agentType: input.agent_type } : {}
|
|
439
|
+
};
|
|
440
|
+
return ev;
|
|
441
|
+
}
|
|
442
|
+
default: {
|
|
443
|
+
throw new Error(`unsupported grok-cli hook event: ${String(event)}`);
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
// ── Runtime: normalized response → Grok native hook reply ──────────────────
|
|
448
|
+
// Grok parses stdout as JSON when it starts with `{` and aggregates:
|
|
449
|
+
// decision:"block" (or exit 2) → block; decision:"approve" → approve;
|
|
450
|
+
// additionalContext → injected context; continue:false + stopReason → halt.
|
|
451
|
+
// We emit exit 0 + a structured stdout object so the JSON is always parsed.
|
|
452
|
+
formatReply(_event, response) {
|
|
453
|
+
const decision = response.decision ?? "allow";
|
|
454
|
+
if (decision === "deny") {
|
|
455
|
+
return this.stdout({ decision: "block", reason: response.reason ?? "Blocked by hook" });
|
|
456
|
+
}
|
|
457
|
+
if (decision === "context" && response.additionalContext) {
|
|
458
|
+
return this.stdout({ additionalContext: response.additionalContext });
|
|
459
|
+
}
|
|
460
|
+
return { exitCode: 0 };
|
|
461
|
+
}
|
|
462
|
+
stdout(payload) {
|
|
463
|
+
return { exitCode: 0, stdout: JSON.stringify(payload) };
|
|
464
|
+
}
|
|
465
|
+
};
|
|
466
|
+
function toolOutputToString(value) {
|
|
467
|
+
if (value == null) return void 0;
|
|
468
|
+
if (typeof value === "string") return value;
|
|
469
|
+
try {
|
|
470
|
+
return JSON.stringify(value);
|
|
471
|
+
} catch {
|
|
472
|
+
return String(value);
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
var adapter = new GrokCliAdapter();
|
|
476
|
+
var grok_cli_default = adapter;
|
|
477
|
+
export {
|
|
478
|
+
GrokCliAdapter,
|
|
479
|
+
adapter,
|
|
480
|
+
grok_cli_default as default
|
|
481
|
+
};
|
|
482
|
+
//# sourceMappingURL=grok-cli-5QD235UB.js.map
|