@ken-jo/agent-connector 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +202 -0
- package/NOTICE +6 -0
- package/README.md +348 -0
- package/dist/amp-QSFH2V7Y.js +217 -0
- package/dist/amp-QSFH2V7Y.js.map +1 -0
- package/dist/amp-TULUPXXL.js +237 -0
- package/dist/amp-TULUPXXL.js.map +1 -0
- package/dist/antigravity-CX2YLSY7.js +17 -0
- package/dist/antigravity-CX2YLSY7.js.map +1 -0
- package/dist/antigravity-STHZWMP3.js +171 -0
- package/dist/antigravity-STHZWMP3.js.map +1 -0
- package/dist/antigravity-cli-P6HADOAO.js +121 -0
- package/dist/antigravity-cli-P6HADOAO.js.map +1 -0
- package/dist/antigravity-cli-YQDFVV4U.js +86 -0
- package/dist/antigravity-cli-YQDFVV4U.js.map +1 -0
- package/dist/chunk-54EMKTTX.js +191 -0
- package/dist/chunk-54EMKTTX.js.map +1 -0
- package/dist/chunk-7L6ITC4T.js +54 -0
- package/dist/chunk-7L6ITC4T.js.map +1 -0
- package/dist/chunk-7MSDGHJW.js +316 -0
- package/dist/chunk-7MSDGHJW.js.map +1 -0
- package/dist/chunk-BCHWFTV4.js +196 -0
- package/dist/chunk-BCHWFTV4.js.map +1 -0
- package/dist/chunk-DBQMX75U.js +36 -0
- package/dist/chunk-DBQMX75U.js.map +1 -0
- package/dist/chunk-EXLS7BSI.js +29 -0
- package/dist/chunk-EXLS7BSI.js.map +1 -0
- package/dist/chunk-JNM3TPLX.js +593 -0
- package/dist/chunk-JNM3TPLX.js.map +1 -0
- package/dist/chunk-JWNT5KW7.js +197 -0
- package/dist/chunk-JWNT5KW7.js.map +1 -0
- package/dist/chunk-KHO5WNTP.js +30 -0
- package/dist/chunk-KHO5WNTP.js.map +1 -0
- package/dist/chunk-LTT56GI3.js +155 -0
- package/dist/chunk-LTT56GI3.js.map +1 -0
- package/dist/chunk-MEH7GC7R.js +111 -0
- package/dist/chunk-MEH7GC7R.js.map +1 -0
- package/dist/chunk-MQPNU2CY.js +64 -0
- package/dist/chunk-MQPNU2CY.js.map +1 -0
- package/dist/chunk-OPXAP3AC.js +12 -0
- package/dist/chunk-OPXAP3AC.js.map +1 -0
- package/dist/chunk-RK6VBLXP.js +50 -0
- package/dist/chunk-RK6VBLXP.js.map +1 -0
- package/dist/chunk-TIIP3RG2.js +420 -0
- package/dist/chunk-TIIP3RG2.js.map +1 -0
- package/dist/chunk-TRKWUNO4.js +702 -0
- package/dist/chunk-TRKWUNO4.js.map +1 -0
- package/dist/chunk-TRQKHP7D.js +93 -0
- package/dist/chunk-TRQKHP7D.js.map +1 -0
- package/dist/chunk-WCETQWWK.js +59 -0
- package/dist/chunk-WCETQWWK.js.map +1 -0
- package/dist/chunk-WV63X7IK.js +357 -0
- package/dist/chunk-WV63X7IK.js.map +1 -0
- package/dist/chunk-XD7MY6HB.js +343 -0
- package/dist/chunk-XD7MY6HB.js.map +1 -0
- package/dist/chunk-XNAM7F35.js +276 -0
- package/dist/chunk-XNAM7F35.js.map +1 -0
- package/dist/chunk-XUCWLJY5.js +238 -0
- package/dist/chunk-XUCWLJY5.js.map +1 -0
- package/dist/chunk-YNZU6PAV.js +800 -0
- package/dist/chunk-YNZU6PAV.js.map +1 -0
- package/dist/chunk-YT43MUSJ.js +146 -0
- package/dist/chunk-YT43MUSJ.js.map +1 -0
- package/dist/claude-code-HKDV7T32.js +637 -0
- package/dist/claude-code-HKDV7T32.js.map +1 -0
- package/dist/claude-code-W74MNTAC.js +652 -0
- package/dist/claude-code-W74MNTAC.js.map +1 -0
- package/dist/cli/sdk.d.ts +54 -0
- package/dist/cli/sdk.js +82 -0
- package/dist/cli/sdk.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +15 -0
- package/dist/cli.js.map +1 -0
- package/dist/codebuff-3PMZJJHP.js +307 -0
- package/dist/codebuff-3PMZJJHP.js.map +1 -0
- package/dist/codebuff-QX57FJDN.js +220 -0
- package/dist/codebuff-QX57FJDN.js.map +1 -0
- package/dist/codex-JFQTS6LU.js +593 -0
- package/dist/codex-JFQTS6LU.js.map +1 -0
- package/dist/codex-Q3ATRRX3.js +364 -0
- package/dist/codex-Q3ATRRX3.js.map +1 -0
- package/dist/copilot-cli-MTCGHZ2T.js +622 -0
- package/dist/copilot-cli-MTCGHZ2T.js.map +1 -0
- package/dist/copilot-cli-SJGIXVSD.js +369 -0
- package/dist/copilot-cli-SJGIXVSD.js.map +1 -0
- package/dist/crush-I7PK3FGI.js +360 -0
- package/dist/crush-I7PK3FGI.js.map +1 -0
- package/dist/crush-LN5QFFR2.js +183 -0
- package/dist/crush-LN5QFFR2.js.map +1 -0
- package/dist/cursor-4TMXKJOZ.js +603 -0
- package/dist/cursor-4TMXKJOZ.js.map +1 -0
- package/dist/cursor-QZ6MTO74.js +194 -0
- package/dist/cursor-QZ6MTO74.js.map +1 -0
- package/dist/detect-WIAGVYS4.js +68 -0
- package/dist/detect-WIAGVYS4.js.map +1 -0
- package/dist/doctor-EZW2K4NI.js +372 -0
- package/dist/doctor-EZW2K4NI.js.map +1 -0
- package/dist/droid-KN6VRMMT.js +424 -0
- package/dist/droid-KN6VRMMT.js.map +1 -0
- package/dist/droid-W5WF5XEX.js +224 -0
- package/dist/droid-W5WF5XEX.js.map +1 -0
- package/dist/gemini-cli-CIRW37TU.js +369 -0
- package/dist/gemini-cli-CIRW37TU.js.map +1 -0
- package/dist/gemini-cli-Y35FFK4M.js +705 -0
- package/dist/gemini-cli-Y35FFK4M.js.map +1 -0
- package/dist/goose-A3M5GODH.js +212 -0
- package/dist/goose-A3M5GODH.js.map +1 -0
- package/dist/goose-ZTGTSUFJ.js +480 -0
- package/dist/goose-ZTGTSUFJ.js.map +1 -0
- package/dist/hermes-H2KV44GK.js +470 -0
- package/dist/hermes-H2KV44GK.js.map +1 -0
- package/dist/hermes-ZYLMOFLZ.js +196 -0
- package/dist/hermes-ZYLMOFLZ.js.map +1 -0
- package/dist/hook-YVDILAMZ.js +75 -0
- package/dist/hook-YVDILAMZ.js.map +1 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/install-HQRYZOQ2.js +60 -0
- package/dist/install-HQRYZOQ2.js.map +1 -0
- package/dist/jetbrains-copilot-HWA3DMH7.js +633 -0
- package/dist/jetbrains-copilot-HWA3DMH7.js.map +1 -0
- package/dist/kilo-NSWAVP6P.js +235 -0
- package/dist/kilo-NSWAVP6P.js.map +1 -0
- package/dist/kilo-QXJRCSLT.js +384 -0
- package/dist/kilo-QXJRCSLT.js.map +1 -0
- package/dist/kilo-cli-EAQTHXUW.js +587 -0
- package/dist/kilo-cli-EAQTHXUW.js.map +1 -0
- package/dist/kilo-cli-EVBKUODA.js +160 -0
- package/dist/kilo-cli-EVBKUODA.js.map +1 -0
- package/dist/kimi-EI3UM3ZV.js +155 -0
- package/dist/kimi-EI3UM3ZV.js.map +1 -0
- package/dist/kimi-GQ7VXNYT.js +423 -0
- package/dist/kimi-GQ7VXNYT.js.map +1 -0
- package/dist/kiro-UCLSLBW2.js +217 -0
- package/dist/kiro-UCLSLBW2.js.map +1 -0
- package/dist/kiro-VQTT6LO2.js +451 -0
- package/dist/kiro-VQTT6LO2.js.map +1 -0
- package/dist/leaderboard-K6ON3SWW.js +137 -0
- package/dist/leaderboard-K6ON3SWW.js.map +1 -0
- package/dist/mux-T2TV4CIQ.js +211 -0
- package/dist/mux-T2TV4CIQ.js.map +1 -0
- package/dist/mux-ZMLVAXOO.js +96 -0
- package/dist/mux-ZMLVAXOO.js.map +1 -0
- package/dist/omp-PB4VDKS6.js +586 -0
- package/dist/omp-PB4VDKS6.js.map +1 -0
- package/dist/openclaw-ETN2M63O.js +751 -0
- package/dist/openclaw-ETN2M63O.js.map +1 -0
- package/dist/openclaw-IYA7ASL6.js +150 -0
- package/dist/openclaw-IYA7ASL6.js.map +1 -0
- package/dist/opencode-FZ33JKUZ.js +734 -0
- package/dist/opencode-FZ33JKUZ.js.map +1 -0
- package/dist/opencode-HWT3RSMN.js +216 -0
- package/dist/opencode-HWT3RSMN.js.map +1 -0
- package/dist/package-DLOVE2E4.js +1132 -0
- package/dist/package-DLOVE2E4.js.map +1 -0
- package/dist/pi-CIU2QHT4.js +208 -0
- package/dist/pi-CIU2QHT4.js.map +1 -0
- package/dist/pi-UFX2OYFV.js +139 -0
- package/dist/pi-UFX2OYFV.js.map +1 -0
- package/dist/qwen-code-5POCNU6P.js +573 -0
- package/dist/qwen-code-5POCNU6P.js.map +1 -0
- package/dist/qwen-code-W7NUCDEN.js +134 -0
- package/dist/qwen-code-W7NUCDEN.js.map +1 -0
- package/dist/roo-code-IOIUXRDE.js +242 -0
- package/dist/roo-code-IOIUXRDE.js.map +1 -0
- package/dist/roo-code-ZLKH4A7N.js +229 -0
- package/dist/roo-code-ZLKH4A7N.js.map +1 -0
- package/dist/runtime/index.d.ts +157 -0
- package/dist/runtime/index.js +20 -0
- package/dist/runtime/index.js.map +1 -0
- package/dist/serve-HVWWY4B6.js +65 -0
- package/dist/serve-HVWWY4B6.js.map +1 -0
- package/dist/status-FE7TECZD.js +128 -0
- package/dist/status-FE7TECZD.js.map +1 -0
- package/dist/synthetic-UKR6SMGS.js +178 -0
- package/dist/synthetic-UKR6SMGS.js.map +1 -0
- package/dist/telemetry-36GESKQQ.js +349 -0
- package/dist/telemetry-36GESKQQ.js.map +1 -0
- package/dist/trae-JSNDZFKL.js +204 -0
- package/dist/trae-JSNDZFKL.js.map +1 -0
- package/dist/trae-PA26DPBW.js +157 -0
- package/dist/trae-PA26DPBW.js.map +1 -0
- package/dist/types-CYUB1OTr.d.ts +427 -0
- package/dist/uninstall-IGCKNOSF.js +72 -0
- package/dist/uninstall-IGCKNOSF.js.map +1 -0
- package/dist/upgrade-JV2VK242.js +104 -0
- package/dist/upgrade-JV2VK242.js.map +1 -0
- package/dist/usage-6ER6EMEY.js +324 -0
- package/dist/usage-6ER6EMEY.js.map +1 -0
- package/dist/usage-event-JKBI6XCF.js +48 -0
- package/dist/usage-event-JKBI6XCF.js.map +1 -0
- package/dist/vscode-copilot-CK3NO54M.js +715 -0
- package/dist/vscode-copilot-CK3NO54M.js.map +1 -0
- package/dist/warp-JNQA7PBU.js +126 -0
- package/dist/warp-JNQA7PBU.js.map +1 -0
- package/dist/warp-QNVDXOG4.js +199 -0
- package/dist/warp-QNVDXOG4.js.map +1 -0
- package/dist/zed-NNNX5MNT.js +272 -0
- package/dist/zed-NNNX5MNT.js.map +1 -0
- package/dist/zed-VRJKWYUR.js +209 -0
- package/dist/zed-VRJKWYUR.js.map +1 -0
- package/package.json +79 -0
|
@@ -0,0 +1,637 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
resolveEnvRefsDeep,
|
|
4
|
+
rewriteEnvRefs
|
|
5
|
+
} from "./chunk-DBQMX75U.js";
|
|
6
|
+
import {
|
|
7
|
+
BaseAdapter
|
|
8
|
+
} from "./chunk-TIIP3RG2.js";
|
|
9
|
+
import {
|
|
10
|
+
renderCommandMd,
|
|
11
|
+
renderSkillMd,
|
|
12
|
+
renderSubagentMd
|
|
13
|
+
} from "./chunk-7L6ITC4T.js";
|
|
14
|
+
import {
|
|
15
|
+
buildHomeBinHookCommand,
|
|
16
|
+
buildServeWrapperCommand,
|
|
17
|
+
isHomeBinHookCommand,
|
|
18
|
+
shouldWrapForTelemetry
|
|
19
|
+
} from "./chunk-MEH7GC7R.js";
|
|
20
|
+
import "./chunk-TRQKHP7D.js";
|
|
21
|
+
|
|
22
|
+
// src/adapters/claude-code/index.ts
|
|
23
|
+
import { existsSync } from "fs";
|
|
24
|
+
import { homedir } from "os";
|
|
25
|
+
import { join } from "path";
|
|
26
|
+
|
|
27
|
+
// src/adapters/claude-code/wire.ts
|
|
28
|
+
function extractSessionId(input) {
|
|
29
|
+
if (typeof input.transcript_path === "string") {
|
|
30
|
+
const m = input.transcript_path.match(/([a-f0-9-]{36})\.jsonl$/);
|
|
31
|
+
if (m && m[1]) return m[1];
|
|
32
|
+
}
|
|
33
|
+
if (typeof input.session_id === "string" && input.session_id !== "") {
|
|
34
|
+
return input.session_id;
|
|
35
|
+
}
|
|
36
|
+
return "";
|
|
37
|
+
}
|
|
38
|
+
function toolResponseToString(value) {
|
|
39
|
+
if (value == null) return void 0;
|
|
40
|
+
if (typeof value === "string") return value;
|
|
41
|
+
try {
|
|
42
|
+
return JSON.stringify(value);
|
|
43
|
+
} catch {
|
|
44
|
+
return String(value);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// src/adapters/claude-code/index.ts
|
|
49
|
+
var HOST = "claude-code";
|
|
50
|
+
var MCP_ROOT_KEY = "mcpServers";
|
|
51
|
+
var ClaudeCodeAdapter = class extends BaseAdapter {
|
|
52
|
+
id = HOST;
|
|
53
|
+
name = "Claude Code";
|
|
54
|
+
paradigm = "json-stdio";
|
|
55
|
+
capabilities = {
|
|
56
|
+
preToolUse: true,
|
|
57
|
+
postToolUse: true,
|
|
58
|
+
preCompact: true,
|
|
59
|
+
sessionStart: true,
|
|
60
|
+
sessionEnd: true,
|
|
61
|
+
userPromptSubmit: true,
|
|
62
|
+
stop: true,
|
|
63
|
+
notification: true,
|
|
64
|
+
// Claude Code can rewrite PreToolUse input (updatedInput) but does NOT let a
|
|
65
|
+
// PostToolUse hook rewrite already-emitted tool output.
|
|
66
|
+
canModifyArgs: true,
|
|
67
|
+
canModifyOutput: false,
|
|
68
|
+
canInjectSessionContext: true,
|
|
69
|
+
transports: ["stdio", "http"],
|
|
70
|
+
// Content surfaces: Claude Code is the reference implementation for all three.
|
|
71
|
+
supportsCommands: true,
|
|
72
|
+
supportsSkills: true,
|
|
73
|
+
supportsSubagents: true
|
|
74
|
+
};
|
|
75
|
+
// ── Detection ────────────────────────────────────────────────────────────
|
|
76
|
+
detectInstalled(projectDir) {
|
|
77
|
+
const userDir = join(homedir(), ".claude");
|
|
78
|
+
const userSettings = join(userDir, "settings.json");
|
|
79
|
+
const userServers = join(homedir(), ".claude.json");
|
|
80
|
+
const projectServers = join(projectDir, ".mcp.json");
|
|
81
|
+
const userInstalled = existsSync(userDir) || existsSync(userSettings) || existsSync(userServers);
|
|
82
|
+
const projInstalled = existsSync(projectServers);
|
|
83
|
+
const installed = userInstalled || projInstalled;
|
|
84
|
+
const scope = projInstalled && !userInstalled ? "project" : "user";
|
|
85
|
+
const configPath = scope === "project" ? projectServers : userSettings;
|
|
86
|
+
return {
|
|
87
|
+
id: this.id,
|
|
88
|
+
name: this.name,
|
|
89
|
+
installed,
|
|
90
|
+
paradigm: this.paradigm,
|
|
91
|
+
capabilities: this.capabilities,
|
|
92
|
+
configPath,
|
|
93
|
+
scope,
|
|
94
|
+
reason: installed ? scope === "project" ? `found project Claude Code config at ${projectServers}` : `found Claude Code config under ${userDir}` : `no Claude Code config at ${userDir}`,
|
|
95
|
+
confidence: installed ? "high" : "low"
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
// ── Native paths ─────────────────────────────────────────────────────────
|
|
99
|
+
getConfigDir(ctx) {
|
|
100
|
+
return ctx.scope === "project" ? join(ctx.projectDir, ".claude") : join(homedir(), ".claude");
|
|
101
|
+
}
|
|
102
|
+
getServerConfigPath(ctx) {
|
|
103
|
+
return ctx.scope === "project" ? join(ctx.projectDir, ".mcp.json") : join(homedir(), ".claude.json");
|
|
104
|
+
}
|
|
105
|
+
getHookConfigPath(ctx) {
|
|
106
|
+
return join(this.getConfigDir(ctx), "settings.json");
|
|
107
|
+
}
|
|
108
|
+
// ── MCP server install / uninstall ───────────────────────────────────────
|
|
109
|
+
installServer(ctx) {
|
|
110
|
+
const { connector } = ctx;
|
|
111
|
+
const override = connector.platforms[HOST]?.server;
|
|
112
|
+
if (!connector.server || override === false) {
|
|
113
|
+
return [
|
|
114
|
+
{
|
|
115
|
+
platform: this.id,
|
|
116
|
+
action: "skip",
|
|
117
|
+
detail: connector.server ? "server registration disabled for claude-code" : "connector declares no MCP server"
|
|
118
|
+
}
|
|
119
|
+
];
|
|
120
|
+
}
|
|
121
|
+
const server = override && typeof override === "object" ? { ...connector.server, ...override } : connector.server;
|
|
122
|
+
const serverPath = this.getServerConfigPath(ctx);
|
|
123
|
+
const entry = this.renderServerEntry(ctx, server);
|
|
124
|
+
return [
|
|
125
|
+
this.upsertServerInJson(serverPath, MCP_ROOT_KEY, connector.id, entry, ctx.dryRun)
|
|
126
|
+
];
|
|
127
|
+
}
|
|
128
|
+
uninstallServer(ctx) {
|
|
129
|
+
const serverPath = this.getServerConfigPath(ctx);
|
|
130
|
+
return [
|
|
131
|
+
this.removeServerFromJson(serverPath, MCP_ROOT_KEY, ctx.connector.id, ctx.dryRun)
|
|
132
|
+
];
|
|
133
|
+
}
|
|
134
|
+
/** Render a normalized ServerDef into Claude Code's native mcpServers entry. */
|
|
135
|
+
renderServerEntry(ctx, server) {
|
|
136
|
+
const transport = server.transport;
|
|
137
|
+
if (transport === "stdio") {
|
|
138
|
+
let command = server.command ?? "";
|
|
139
|
+
let args = [...server.args ?? []];
|
|
140
|
+
if (shouldWrapForTelemetry(server, ctx.connector.telemetry)) {
|
|
141
|
+
const wrapped = buildServeWrapperCommand(
|
|
142
|
+
ctx.homeBinPath,
|
|
143
|
+
ctx.connector.id,
|
|
144
|
+
command,
|
|
145
|
+
args,
|
|
146
|
+
ctx.scope,
|
|
147
|
+
this.id
|
|
148
|
+
);
|
|
149
|
+
command = wrapped.command;
|
|
150
|
+
args = wrapped.args;
|
|
151
|
+
}
|
|
152
|
+
const entry2 = { type: "stdio", command, args };
|
|
153
|
+
const env = this.renderEnv(server.env);
|
|
154
|
+
if (env) entry2.env = env;
|
|
155
|
+
if (server.cwd) entry2.cwd = resolveEnvRefsDeep(server.cwd);
|
|
156
|
+
return entry2;
|
|
157
|
+
}
|
|
158
|
+
const entry = {
|
|
159
|
+
type: "http",
|
|
160
|
+
url: rewriteEnvRefs(server.url ?? "", claudeEnvToken)
|
|
161
|
+
};
|
|
162
|
+
if (server.headers) {
|
|
163
|
+
entry.headers = this.renderEnv(server.headers) ?? {};
|
|
164
|
+
}
|
|
165
|
+
return entry;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Render env/header values. Claude Code supports its own `${VAR}` native
|
|
169
|
+
* interpolation, so translate `${env:VAR}` refs to that native token rather
|
|
170
|
+
* than baking secrets into the file. Literals pass through unchanged.
|
|
171
|
+
*/
|
|
172
|
+
renderEnv(env) {
|
|
173
|
+
if (!env || Object.keys(env).length === 0) return void 0;
|
|
174
|
+
const out = {};
|
|
175
|
+
for (const [k, v] of Object.entries(env)) {
|
|
176
|
+
out[k] = rewriteEnvRefs(v, claudeEnvToken);
|
|
177
|
+
}
|
|
178
|
+
return out;
|
|
179
|
+
}
|
|
180
|
+
// ── Hook install / uninstall ─────────────────────────────────────────────
|
|
181
|
+
installHooks(ctx) {
|
|
182
|
+
const { connector } = ctx;
|
|
183
|
+
if (connector.platforms[HOST]?.hooks === false) {
|
|
184
|
+
return [
|
|
185
|
+
{ platform: this.id, action: "skip", detail: "hooks disabled for claude-code" }
|
|
186
|
+
];
|
|
187
|
+
}
|
|
188
|
+
if (connector.hookEvents.length === 0) {
|
|
189
|
+
return [
|
|
190
|
+
{ platform: this.id, action: "skip", detail: "connector declares no hooks" }
|
|
191
|
+
];
|
|
192
|
+
}
|
|
193
|
+
const settingsPath = this.getHookConfigPath(ctx);
|
|
194
|
+
const settings = this.readJson(settingsPath) ?? {};
|
|
195
|
+
const hooks = settings.hooks ??= {};
|
|
196
|
+
const changes = [];
|
|
197
|
+
let mutated = false;
|
|
198
|
+
for (const event of connector.hookEvents) {
|
|
199
|
+
const command = buildHomeBinHookCommand(ctx.homeBinPath, HOST, event, connector.id);
|
|
200
|
+
const matcher = connector.hooks[event]?.matcher ?? "";
|
|
201
|
+
const entry = {
|
|
202
|
+
matcher,
|
|
203
|
+
hooks: [{ type: "command", command }]
|
|
204
|
+
};
|
|
205
|
+
const bucket = hooks[event] ??= [];
|
|
206
|
+
const existingIdx = bucket.findIndex((e) => this.entryHasCommand(e, command));
|
|
207
|
+
if (existingIdx >= 0) {
|
|
208
|
+
if (JSON.stringify(bucket[existingIdx]) === JSON.stringify(entry)) {
|
|
209
|
+
changes.push({
|
|
210
|
+
platform: this.id,
|
|
211
|
+
action: "skip",
|
|
212
|
+
path: settingsPath,
|
|
213
|
+
detail: `hooks.${event} already registered`
|
|
214
|
+
});
|
|
215
|
+
continue;
|
|
216
|
+
}
|
|
217
|
+
bucket[existingIdx] = entry;
|
|
218
|
+
changes.push({
|
|
219
|
+
platform: this.id,
|
|
220
|
+
action: "update",
|
|
221
|
+
path: settingsPath,
|
|
222
|
+
detail: `hooks.${event}`
|
|
223
|
+
});
|
|
224
|
+
} else {
|
|
225
|
+
bucket.push(entry);
|
|
226
|
+
changes.push({
|
|
227
|
+
platform: this.id,
|
|
228
|
+
action: "create",
|
|
229
|
+
path: settingsPath,
|
|
230
|
+
detail: `hooks.${event}`
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
mutated = true;
|
|
234
|
+
}
|
|
235
|
+
if (mutated) this.writeJson(settingsPath, settings, ctx.dryRun);
|
|
236
|
+
return changes;
|
|
237
|
+
}
|
|
238
|
+
uninstallHooks(ctx) {
|
|
239
|
+
const settingsPath = this.getHookConfigPath(ctx);
|
|
240
|
+
const settings = this.readJson(settingsPath);
|
|
241
|
+
const hooks = settings?.hooks;
|
|
242
|
+
if (!settings || !hooks) {
|
|
243
|
+
return [
|
|
244
|
+
{
|
|
245
|
+
platform: this.id,
|
|
246
|
+
action: "skip",
|
|
247
|
+
path: settingsPath,
|
|
248
|
+
detail: "no hooks section present"
|
|
249
|
+
}
|
|
250
|
+
];
|
|
251
|
+
}
|
|
252
|
+
const changes = [];
|
|
253
|
+
let mutated = false;
|
|
254
|
+
for (const event of Object.keys(hooks)) {
|
|
255
|
+
const bucket = hooks[event];
|
|
256
|
+
if (!Array.isArray(bucket)) continue;
|
|
257
|
+
const next = [];
|
|
258
|
+
let removed = 0;
|
|
259
|
+
for (const e of bucket) {
|
|
260
|
+
const innerBefore = e.hooks?.length ?? 0;
|
|
261
|
+
const inner = (e.hooks ?? []).filter(
|
|
262
|
+
(h) => !this.isOurCommand(h.command, ctx)
|
|
263
|
+
);
|
|
264
|
+
removed += innerBefore - inner.length;
|
|
265
|
+
if (inner.length > 0) next.push({ matcher: e.matcher ?? "", hooks: inner });
|
|
266
|
+
}
|
|
267
|
+
if (removed > 0) {
|
|
268
|
+
if (next.length > 0) hooks[event] = next;
|
|
269
|
+
else delete hooks[event];
|
|
270
|
+
changes.push({
|
|
271
|
+
platform: this.id,
|
|
272
|
+
action: "remove",
|
|
273
|
+
path: settingsPath,
|
|
274
|
+
detail: `hooks.${event} (${removed})`
|
|
275
|
+
});
|
|
276
|
+
mutated = true;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
if (mutated) this.writeJson(settingsPath, settings, ctx.dryRun);
|
|
280
|
+
if (changes.length === 0) {
|
|
281
|
+
changes.push({
|
|
282
|
+
platform: this.id,
|
|
283
|
+
action: "skip",
|
|
284
|
+
path: settingsPath,
|
|
285
|
+
detail: "no matching hook entries"
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
return changes;
|
|
289
|
+
}
|
|
290
|
+
entryHasCommand(entry, command) {
|
|
291
|
+
return (entry.hooks ?? []).some((h) => h.command === command);
|
|
292
|
+
}
|
|
293
|
+
// ── Content surfaces: commands / skills / subagents ──────────────────────
|
|
294
|
+
// CONTENT-ONLY: pure native-file writers under <configDir>/{commands,skills,
|
|
295
|
+
// agents}. No runtime dispatch, no home-bin pointer, no telemetry wrap. Each
|
|
296
|
+
// method is idempotent (byte-identical → skip) via BaseAdapter.writeContentFile
|
|
297
|
+
// and reversible via removeContentFile. Honors platforms["claude-code"]
|
|
298
|
+
// per-surface false to skip.
|
|
299
|
+
commandsDir(ctx) {
|
|
300
|
+
return join(this.getConfigDir(ctx), "commands");
|
|
301
|
+
}
|
|
302
|
+
skillsDir(ctx) {
|
|
303
|
+
return join(this.getConfigDir(ctx), "skills");
|
|
304
|
+
}
|
|
305
|
+
agentsDir(ctx) {
|
|
306
|
+
return join(this.getConfigDir(ctx), "agents");
|
|
307
|
+
}
|
|
308
|
+
/** Native command file path: <configDir>/commands/<name>.md. */
|
|
309
|
+
commandPath(ctx, name) {
|
|
310
|
+
return join(this.commandsDir(ctx), `${name}.md`);
|
|
311
|
+
}
|
|
312
|
+
/** Native skill dir: <configDir>/skills/<name>. */
|
|
313
|
+
skillDir(ctx, name) {
|
|
314
|
+
return join(this.skillsDir(ctx), name);
|
|
315
|
+
}
|
|
316
|
+
/** Native subagent file path: <configDir>/agents/<name>.md. */
|
|
317
|
+
subagentPath(ctx, name) {
|
|
318
|
+
return join(this.agentsDir(ctx), `${name}.md`);
|
|
319
|
+
}
|
|
320
|
+
// ── Commands ──────────────────────────────────────────────────────────────
|
|
321
|
+
installCommands(ctx) {
|
|
322
|
+
const { connector } = ctx;
|
|
323
|
+
if (connector.platforms[HOST]?.commands === false) {
|
|
324
|
+
return [{ platform: this.id, action: "skip", detail: "commands disabled for claude-code" }];
|
|
325
|
+
}
|
|
326
|
+
if (connector.commands.length === 0) {
|
|
327
|
+
return [{ platform: this.id, action: "skip", detail: "connector declares no commands" }];
|
|
328
|
+
}
|
|
329
|
+
return connector.commands.map(
|
|
330
|
+
(cmd) => this.writeContentFile(
|
|
331
|
+
this.commandPath(ctx, cmd.name),
|
|
332
|
+
this.renderCommand(cmd),
|
|
333
|
+
ctx.dryRun
|
|
334
|
+
)
|
|
335
|
+
);
|
|
336
|
+
}
|
|
337
|
+
uninstallCommands(ctx) {
|
|
338
|
+
const { connector } = ctx;
|
|
339
|
+
if (connector.commands.length === 0) {
|
|
340
|
+
return [{ platform: this.id, action: "skip", detail: "connector declares no commands" }];
|
|
341
|
+
}
|
|
342
|
+
return connector.commands.map(
|
|
343
|
+
(cmd) => this.removeContentFile(this.commandPath(ctx, cmd.name), ctx.dryRun)
|
|
344
|
+
);
|
|
345
|
+
}
|
|
346
|
+
/** Render a command to md+frontmatter (delegates to the shared renderer). */
|
|
347
|
+
renderCommand(cmd) {
|
|
348
|
+
return renderCommandMd(cmd);
|
|
349
|
+
}
|
|
350
|
+
// ── Skills ────────────────────────────────────────────────────────────────
|
|
351
|
+
installSkills(ctx) {
|
|
352
|
+
const { connector } = ctx;
|
|
353
|
+
if (connector.platforms[HOST]?.skills === false) {
|
|
354
|
+
return [{ platform: this.id, action: "skip", detail: "skills disabled for claude-code" }];
|
|
355
|
+
}
|
|
356
|
+
if (connector.skills.length === 0) {
|
|
357
|
+
return [{ platform: this.id, action: "skip", detail: "connector declares no skills" }];
|
|
358
|
+
}
|
|
359
|
+
const changes = [];
|
|
360
|
+
for (const skill of connector.skills) {
|
|
361
|
+
const dir = this.skillDir(ctx, skill.name);
|
|
362
|
+
changes.push(
|
|
363
|
+
this.writeContentFile(join(dir, "SKILL.md"), this.renderSkill(skill), ctx.dryRun)
|
|
364
|
+
);
|
|
365
|
+
for (const [rel, contents] of Object.entries(skill.resources ?? {})) {
|
|
366
|
+
const target = this.resolveWithin(dir, rel);
|
|
367
|
+
if (target === null) {
|
|
368
|
+
changes.push({
|
|
369
|
+
platform: this.id,
|
|
370
|
+
action: "warn",
|
|
371
|
+
detail: `skill resource "${rel}" escapes the skill dir; skipped`
|
|
372
|
+
});
|
|
373
|
+
continue;
|
|
374
|
+
}
|
|
375
|
+
changes.push(this.writeContentFile(target, contents, ctx.dryRun));
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
return changes;
|
|
379
|
+
}
|
|
380
|
+
uninstallSkills(ctx) {
|
|
381
|
+
const { connector } = ctx;
|
|
382
|
+
if (connector.skills.length === 0) {
|
|
383
|
+
return [{ platform: this.id, action: "skip", detail: "connector declares no skills" }];
|
|
384
|
+
}
|
|
385
|
+
const changes = [];
|
|
386
|
+
for (const skill of connector.skills) {
|
|
387
|
+
const dir = this.skillDir(ctx, skill.name);
|
|
388
|
+
changes.push(this.removeContentFile(join(dir, "SKILL.md"), ctx.dryRun));
|
|
389
|
+
for (const rel of Object.keys(skill.resources ?? {})) {
|
|
390
|
+
const target = this.resolveWithin(dir, rel);
|
|
391
|
+
if (target === null) continue;
|
|
392
|
+
changes.push(this.removeContentFile(target, ctx.dryRun));
|
|
393
|
+
}
|
|
394
|
+
changes.push(this.removeDirIfEmpty(dir, ctx.dryRun));
|
|
395
|
+
}
|
|
396
|
+
return changes;
|
|
397
|
+
}
|
|
398
|
+
/** Render a skill's SKILL.md (delegates to the shared renderer). */
|
|
399
|
+
renderSkill(skill) {
|
|
400
|
+
return renderSkillMd(skill);
|
|
401
|
+
}
|
|
402
|
+
// ── Subagents ───────────────────────────────────────────────────────────────
|
|
403
|
+
installSubagents(ctx) {
|
|
404
|
+
const { connector } = ctx;
|
|
405
|
+
if (connector.platforms[HOST]?.subagents === false) {
|
|
406
|
+
return [{ platform: this.id, action: "skip", detail: "subagents disabled for claude-code" }];
|
|
407
|
+
}
|
|
408
|
+
if (connector.subagents.length === 0) {
|
|
409
|
+
return [{ platform: this.id, action: "skip", detail: "connector declares no subagents" }];
|
|
410
|
+
}
|
|
411
|
+
return connector.subagents.map(
|
|
412
|
+
(agent) => this.writeContentFile(
|
|
413
|
+
this.subagentPath(ctx, agent.name),
|
|
414
|
+
this.renderSubagent(agent),
|
|
415
|
+
ctx.dryRun
|
|
416
|
+
)
|
|
417
|
+
);
|
|
418
|
+
}
|
|
419
|
+
uninstallSubagents(ctx) {
|
|
420
|
+
const { connector } = ctx;
|
|
421
|
+
if (connector.subagents.length === 0) {
|
|
422
|
+
return [{ platform: this.id, action: "skip", detail: "connector declares no subagents" }];
|
|
423
|
+
}
|
|
424
|
+
return connector.subagents.map(
|
|
425
|
+
(agent) => this.removeContentFile(this.subagentPath(ctx, agent.name), ctx.dryRun)
|
|
426
|
+
);
|
|
427
|
+
}
|
|
428
|
+
/** Render a subagent to md+frontmatter (delegates to the shared renderer). */
|
|
429
|
+
renderSubagent(agent) {
|
|
430
|
+
return renderSubagentMd(agent);
|
|
431
|
+
}
|
|
432
|
+
/** True when a hook command references our home binary AND this connector id
|
|
433
|
+
* (anchored so a shared-prefix id can't collide — see isHomeBinHookCommand). */
|
|
434
|
+
isOurCommand(command, ctx) {
|
|
435
|
+
return isHomeBinHookCommand(command, ctx.homeBinPath, ctx.connector.id);
|
|
436
|
+
}
|
|
437
|
+
// ── Diagnostics ──────────────────────────────────────────────────────────
|
|
438
|
+
getHealthChecks(ctx) {
|
|
439
|
+
const settingsPath = this.getHookConfigPath(ctx);
|
|
440
|
+
const connectorId = ctx.connector.id;
|
|
441
|
+
const homeBin = ctx.homeBinPath;
|
|
442
|
+
const hookEvents = ctx.connector.hookEvents;
|
|
443
|
+
const checks = [
|
|
444
|
+
{
|
|
445
|
+
name: `${this.name}: settings.json present`,
|
|
446
|
+
check: () => existsSync(settingsPath) ? { status: "OK", detail: settingsPath } : { status: "FAIL", detail: `not found: ${settingsPath}` }
|
|
447
|
+
},
|
|
448
|
+
{
|
|
449
|
+
name: `${this.name}: hook command registered`,
|
|
450
|
+
check: () => {
|
|
451
|
+
if (hookEvents.length === 0) {
|
|
452
|
+
return { status: "OK", detail: "no hooks declared" };
|
|
453
|
+
}
|
|
454
|
+
const settings = this.readJson(
|
|
455
|
+
settingsPath
|
|
456
|
+
);
|
|
457
|
+
if (!settings) return { status: "FAIL", detail: `cannot read ${settingsPath}` };
|
|
458
|
+
const hooks = settings.hooks ?? {};
|
|
459
|
+
const registered = Object.values(hooks).some(
|
|
460
|
+
(entries) => (entries ?? []).some(
|
|
461
|
+
(e) => (e.hooks ?? []).some(
|
|
462
|
+
(h) => isHomeBinHookCommand(h.command, homeBin, connectorId)
|
|
463
|
+
)
|
|
464
|
+
)
|
|
465
|
+
);
|
|
466
|
+
return registered ? { status: "OK", detail: "hook command present" } : {
|
|
467
|
+
status: "FAIL",
|
|
468
|
+
detail: `no hook for ${connectorId} in ${settingsPath}`
|
|
469
|
+
};
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
];
|
|
473
|
+
for (const cmd of ctx.connector.commands) {
|
|
474
|
+
const p = this.commandPath(ctx, cmd.name);
|
|
475
|
+
checks.push({
|
|
476
|
+
name: `${this.name}: command ${cmd.name} present`,
|
|
477
|
+
check: () => existsSync(p) ? { status: "OK", detail: p } : { status: "FAIL", detail: `not found: ${p}` }
|
|
478
|
+
});
|
|
479
|
+
}
|
|
480
|
+
for (const skill of ctx.connector.skills) {
|
|
481
|
+
const p = join(this.skillDir(ctx, skill.name), "SKILL.md");
|
|
482
|
+
checks.push({
|
|
483
|
+
name: `${this.name}: skill ${skill.name} present`,
|
|
484
|
+
check: () => existsSync(p) ? { status: "OK", detail: p } : { status: "FAIL", detail: `not found: ${p}` }
|
|
485
|
+
});
|
|
486
|
+
}
|
|
487
|
+
for (const agent of ctx.connector.subagents) {
|
|
488
|
+
const p = this.subagentPath(ctx, agent.name);
|
|
489
|
+
checks.push({
|
|
490
|
+
name: `${this.name}: subagent ${agent.name} present`,
|
|
491
|
+
check: () => existsSync(p) ? { status: "OK", detail: p } : { status: "FAIL", detail: `not found: ${p}` }
|
|
492
|
+
});
|
|
493
|
+
}
|
|
494
|
+
return checks;
|
|
495
|
+
}
|
|
496
|
+
// ── Runtime: parse Claude stdin JSON → normalized event ──────────────────
|
|
497
|
+
parseEvent(event, raw) {
|
|
498
|
+
const input = raw ?? {};
|
|
499
|
+
const connectorId = typeof input.connector === "string" ? input.connector : "";
|
|
500
|
+
const sessionId = extractSessionId(input);
|
|
501
|
+
const projectDir = typeof input.cwd === "string" ? input.cwd : void 0;
|
|
502
|
+
const base = {
|
|
503
|
+
hostPlatform: HOST,
|
|
504
|
+
connectorId,
|
|
505
|
+
sessionId,
|
|
506
|
+
raw,
|
|
507
|
+
...projectDir !== void 0 ? { projectDir } : {}
|
|
508
|
+
};
|
|
509
|
+
switch (event) {
|
|
510
|
+
case "PreToolUse": {
|
|
511
|
+
const ev = {
|
|
512
|
+
...base,
|
|
513
|
+
toolName: input.tool_name ?? "",
|
|
514
|
+
toolInput: input.tool_input ?? {}
|
|
515
|
+
};
|
|
516
|
+
return ev;
|
|
517
|
+
}
|
|
518
|
+
case "PostToolUse": {
|
|
519
|
+
const ev = {
|
|
520
|
+
...base,
|
|
521
|
+
toolName: input.tool_name ?? "",
|
|
522
|
+
toolInput: input.tool_input ?? {},
|
|
523
|
+
...toolResponseToString(input.tool_response) !== void 0 ? { toolOutput: toolResponseToString(input.tool_response) } : {}
|
|
524
|
+
};
|
|
525
|
+
return ev;
|
|
526
|
+
}
|
|
527
|
+
case "SessionStart": {
|
|
528
|
+
const ev = {
|
|
529
|
+
...base,
|
|
530
|
+
source: normalizeSessionSource(input.source)
|
|
531
|
+
};
|
|
532
|
+
return ev;
|
|
533
|
+
}
|
|
534
|
+
case "SessionEnd": {
|
|
535
|
+
const ev = {
|
|
536
|
+
...base,
|
|
537
|
+
...typeof input.reason === "string" ? { reason: input.reason } : {}
|
|
538
|
+
};
|
|
539
|
+
return ev;
|
|
540
|
+
}
|
|
541
|
+
case "UserPromptSubmit": {
|
|
542
|
+
const ev = {
|
|
543
|
+
...base,
|
|
544
|
+
prompt: typeof input.prompt === "string" ? input.prompt : ""
|
|
545
|
+
};
|
|
546
|
+
return ev;
|
|
547
|
+
}
|
|
548
|
+
case "PreCompact": {
|
|
549
|
+
const ev = {
|
|
550
|
+
...base,
|
|
551
|
+
...input.trigger === "auto" || input.trigger === "manual" ? { trigger: input.trigger } : {}
|
|
552
|
+
};
|
|
553
|
+
return ev;
|
|
554
|
+
}
|
|
555
|
+
case "Stop": {
|
|
556
|
+
const ev = {
|
|
557
|
+
...base,
|
|
558
|
+
...typeof input.stop_hook_active === "boolean" ? { stopHookActive: input.stop_hook_active } : {}
|
|
559
|
+
};
|
|
560
|
+
return ev;
|
|
561
|
+
}
|
|
562
|
+
case "Notification": {
|
|
563
|
+
const ev = {
|
|
564
|
+
...base,
|
|
565
|
+
message: typeof input.message === "string" ? input.message : ""
|
|
566
|
+
};
|
|
567
|
+
return ev;
|
|
568
|
+
}
|
|
569
|
+
default: {
|
|
570
|
+
const _never = event;
|
|
571
|
+
throw new Error(`unsupported claude-code hook event: ${String(_never)}`);
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
// ── Runtime: normalized response → Claude native hook reply ──────────────
|
|
576
|
+
formatReply(event, response) {
|
|
577
|
+
const hookEventName = event;
|
|
578
|
+
const decision = response.decision ?? "allow";
|
|
579
|
+
if (decision === "deny") {
|
|
580
|
+
return this.stdout({
|
|
581
|
+
hookSpecificOutput: {
|
|
582
|
+
hookEventName,
|
|
583
|
+
permissionDecision: "deny",
|
|
584
|
+
permissionDecisionReason: response.reason ?? "Blocked by hook"
|
|
585
|
+
}
|
|
586
|
+
});
|
|
587
|
+
}
|
|
588
|
+
if (decision === "ask") {
|
|
589
|
+
return this.stdout({
|
|
590
|
+
hookSpecificOutput: {
|
|
591
|
+
hookEventName,
|
|
592
|
+
permissionDecision: "ask",
|
|
593
|
+
permissionDecisionReason: response.reason ?? "Confirmation required by hook"
|
|
594
|
+
}
|
|
595
|
+
});
|
|
596
|
+
}
|
|
597
|
+
if (decision === "modify") {
|
|
598
|
+
if (event === "PreToolUse" && response.updatedInput) {
|
|
599
|
+
return this.stdout({
|
|
600
|
+
hookSpecificOutput: { hookEventName, updatedInput: response.updatedInput }
|
|
601
|
+
});
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
if (decision === "context" && response.additionalContext) {
|
|
605
|
+
return this.stdout({
|
|
606
|
+
hookSpecificOutput: { hookEventName, additionalContext: response.additionalContext }
|
|
607
|
+
});
|
|
608
|
+
}
|
|
609
|
+
return { exitCode: 0 };
|
|
610
|
+
}
|
|
611
|
+
stdout(payload) {
|
|
612
|
+
return { exitCode: 0, stdout: JSON.stringify(payload) };
|
|
613
|
+
}
|
|
614
|
+
};
|
|
615
|
+
function claudeEnvToken(name) {
|
|
616
|
+
return `\${${name}}`;
|
|
617
|
+
}
|
|
618
|
+
function normalizeSessionSource(source) {
|
|
619
|
+
switch (source) {
|
|
620
|
+
case "compact":
|
|
621
|
+
return "compact";
|
|
622
|
+
case "resume":
|
|
623
|
+
return "resume";
|
|
624
|
+
case "clear":
|
|
625
|
+
return "clear";
|
|
626
|
+
default:
|
|
627
|
+
return "startup";
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
var adapter = new ClaudeCodeAdapter();
|
|
631
|
+
var claude_code_default = adapter;
|
|
632
|
+
export {
|
|
633
|
+
ClaudeCodeAdapter,
|
|
634
|
+
adapter,
|
|
635
|
+
claude_code_default as default
|
|
636
|
+
};
|
|
637
|
+
//# sourceMappingURL=claude-code-HKDV7T32.js.map
|