@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,451 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
resolveEnvRefsDeep
|
|
4
|
+
} from "./chunk-DBQMX75U.js";
|
|
5
|
+
import {
|
|
6
|
+
BaseAdapter
|
|
7
|
+
} from "./chunk-TIIP3RG2.js";
|
|
8
|
+
import "./chunk-7L6ITC4T.js";
|
|
9
|
+
import {
|
|
10
|
+
buildHomeBinHookCommand,
|
|
11
|
+
buildServeWrapperCommand,
|
|
12
|
+
isHomeBinHookCommand,
|
|
13
|
+
shouldWrapForTelemetry
|
|
14
|
+
} from "./chunk-MEH7GC7R.js";
|
|
15
|
+
import "./chunk-TRQKHP7D.js";
|
|
16
|
+
|
|
17
|
+
// src/adapters/kiro/index.ts
|
|
18
|
+
import { existsSync } from "fs";
|
|
19
|
+
import { homedir } from "os";
|
|
20
|
+
import { join } from "path";
|
|
21
|
+
var HOST = "kiro";
|
|
22
|
+
var MCP_ROOT_KEY = "mcpServers";
|
|
23
|
+
var DEFAULT_AGENT_FILE = "kiro_default.json";
|
|
24
|
+
var KIRO_EVENT = {
|
|
25
|
+
preToolUse: "preToolUse",
|
|
26
|
+
postToolUse: "postToolUse",
|
|
27
|
+
agentSpawn: "agentSpawn",
|
|
28
|
+
userPromptSubmit: "userPromptSubmit",
|
|
29
|
+
stop: "stop"
|
|
30
|
+
};
|
|
31
|
+
var EVENT_MAP = {
|
|
32
|
+
PreToolUse: KIRO_EVENT.preToolUse,
|
|
33
|
+
PostToolUse: KIRO_EVENT.postToolUse,
|
|
34
|
+
SessionStart: KIRO_EVENT.agentSpawn,
|
|
35
|
+
UserPromptSubmit: KIRO_EVENT.userPromptSubmit,
|
|
36
|
+
Stop: KIRO_EVENT.stop
|
|
37
|
+
};
|
|
38
|
+
var KiroAdapter = class extends BaseAdapter {
|
|
39
|
+
id = HOST;
|
|
40
|
+
name = "Kiro";
|
|
41
|
+
paradigm = "json-stdio";
|
|
42
|
+
capabilities = {
|
|
43
|
+
preToolUse: true,
|
|
44
|
+
postToolUse: true,
|
|
45
|
+
preCompact: false,
|
|
46
|
+
sessionStart: true,
|
|
47
|
+
sessionEnd: false,
|
|
48
|
+
// Kiro fires userPromptSubmit and stop, but it has no PreCompact /
|
|
49
|
+
// SessionEnd / Notification equivalent.
|
|
50
|
+
userPromptSubmit: true,
|
|
51
|
+
stop: true,
|
|
52
|
+
notification: false,
|
|
53
|
+
// Kiro's hook protocol is exit-code only — a hook can allow (0), block (2),
|
|
54
|
+
// or inject agentSpawn context, but it CANNOT rewrite tool args or output.
|
|
55
|
+
canModifyArgs: false,
|
|
56
|
+
canModifyOutput: false,
|
|
57
|
+
// agentSpawn returns additionalContext via JSON stdout.
|
|
58
|
+
canInjectSessionContext: true,
|
|
59
|
+
transports: ["stdio", "http"]
|
|
60
|
+
};
|
|
61
|
+
// ── Detection ────────────────────────────────────────────────────────────
|
|
62
|
+
detectInstalled(projectDir) {
|
|
63
|
+
const userDir = join(homedir(), ".kiro");
|
|
64
|
+
const userMcp = this.userMcpPath();
|
|
65
|
+
const projectDirKiro = join(projectDir, ".kiro");
|
|
66
|
+
const projectMcp = this.projectMcpPath(projectDir);
|
|
67
|
+
const userInstalled = existsSync(userDir) || existsSync(userMcp);
|
|
68
|
+
const projInstalled = existsSync(projectDirKiro) || existsSync(projectMcp);
|
|
69
|
+
const installed = userInstalled || projInstalled;
|
|
70
|
+
const scope = projInstalled && !userInstalled ? "project" : "user";
|
|
71
|
+
const configPath = scope === "project" ? projectMcp : userMcp;
|
|
72
|
+
return {
|
|
73
|
+
id: this.id,
|
|
74
|
+
name: this.name,
|
|
75
|
+
installed,
|
|
76
|
+
paradigm: this.paradigm,
|
|
77
|
+
capabilities: this.capabilities,
|
|
78
|
+
configPath,
|
|
79
|
+
scope,
|
|
80
|
+
reason: installed ? scope === "project" ? `found project Kiro config at ${projectMcp}` : `found Kiro config under ${userDir}` : `no Kiro config at ${userDir}`,
|
|
81
|
+
confidence: installed ? "high" : "low"
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
// ── Native paths ─────────────────────────────────────────────────────────
|
|
85
|
+
getConfigDir(ctx) {
|
|
86
|
+
return ctx.scope === "project" ? join(ctx.projectDir, ".kiro") : join(homedir(), ".kiro");
|
|
87
|
+
}
|
|
88
|
+
/** MCP servers live in mcp.json under the scope's `.kiro/settings/`. */
|
|
89
|
+
getServerConfigPath(ctx) {
|
|
90
|
+
return ctx.scope === "project" ? this.projectMcpPath(ctx.projectDir) : this.userMcpPath();
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Hooks live in an AGENT file, NOT a settings file. Kiro auto-loads the
|
|
94
|
+
* built-in default agent (`kiro_default`) for a new chat session, so we always
|
|
95
|
+
* register hooks on the user-scope default agent — that is the agent Kiro
|
|
96
|
+
* actually loads regardless of install scope.
|
|
97
|
+
*/
|
|
98
|
+
getHookConfigPath(_ctx) {
|
|
99
|
+
return join(homedir(), ".kiro", "agents", DEFAULT_AGENT_FILE);
|
|
100
|
+
}
|
|
101
|
+
userMcpPath() {
|
|
102
|
+
return join(homedir(), ".kiro", "settings", "mcp.json");
|
|
103
|
+
}
|
|
104
|
+
projectMcpPath(projectDir) {
|
|
105
|
+
return join(projectDir, ".kiro", "settings", "mcp.json");
|
|
106
|
+
}
|
|
107
|
+
// ── MCP server install / uninstall ───────────────────────────────────────
|
|
108
|
+
installServer(ctx) {
|
|
109
|
+
const { connector } = 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
|
+
detail: connector.server ? "server registration disabled for kiro" : "connector declares no MCP server"
|
|
117
|
+
}
|
|
118
|
+
];
|
|
119
|
+
}
|
|
120
|
+
const server = override && typeof override === "object" ? { ...connector.server, ...override } : connector.server;
|
|
121
|
+
const serverPath = this.getServerConfigPath(ctx);
|
|
122
|
+
const entry = this.renderServerEntry(ctx, server);
|
|
123
|
+
return [
|
|
124
|
+
this.upsertServerInJson(serverPath, MCP_ROOT_KEY, connector.id, entry, ctx.dryRun)
|
|
125
|
+
];
|
|
126
|
+
}
|
|
127
|
+
uninstallServer(ctx) {
|
|
128
|
+
const serverPath = this.getServerConfigPath(ctx);
|
|
129
|
+
return [
|
|
130
|
+
this.removeServerFromJson(serverPath, MCP_ROOT_KEY, ctx.connector.id, ctx.dryRun)
|
|
131
|
+
];
|
|
132
|
+
}
|
|
133
|
+
/** Render a normalized ServerDef into Kiro's native mcpServers entry. */
|
|
134
|
+
renderServerEntry(ctx, server) {
|
|
135
|
+
const transport = server.transport;
|
|
136
|
+
if (transport === "stdio") {
|
|
137
|
+
let command = server.command ?? "";
|
|
138
|
+
let args = [...server.args ?? []];
|
|
139
|
+
if (shouldWrapForTelemetry(server, ctx.connector.telemetry)) {
|
|
140
|
+
const wrapped = buildServeWrapperCommand(
|
|
141
|
+
ctx.homeBinPath,
|
|
142
|
+
ctx.connector.id,
|
|
143
|
+
command,
|
|
144
|
+
args,
|
|
145
|
+
ctx.scope,
|
|
146
|
+
this.id
|
|
147
|
+
);
|
|
148
|
+
command = wrapped.command;
|
|
149
|
+
args = wrapped.args;
|
|
150
|
+
}
|
|
151
|
+
const entry2 = { command: resolveEnvRefsDeep(command) };
|
|
152
|
+
if (args.length > 0) entry2.args = resolveEnvRefsDeep(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 = { url: resolveEnvRefsDeep(server.url ?? "") };
|
|
159
|
+
const headers = this.renderEnv(server.headers);
|
|
160
|
+
if (headers) entry.headers = headers;
|
|
161
|
+
return entry;
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Render env/header values. Kiro documents no native interpolation token, so
|
|
165
|
+
* resolve `${env:VAR}` references to literals at install time.
|
|
166
|
+
*/
|
|
167
|
+
renderEnv(env) {
|
|
168
|
+
if (!env || Object.keys(env).length === 0) return void 0;
|
|
169
|
+
return resolveEnvRefsDeep({ ...env });
|
|
170
|
+
}
|
|
171
|
+
// ── Hook install / uninstall (merge into the agent file) ─────────────────
|
|
172
|
+
installHooks(ctx) {
|
|
173
|
+
const { connector } = ctx;
|
|
174
|
+
if (connector.platforms[HOST]?.hooks === false) {
|
|
175
|
+
return [{ platform: this.id, action: "skip", detail: "hooks disabled for kiro" }];
|
|
176
|
+
}
|
|
177
|
+
if (connector.hookEvents.length === 0) {
|
|
178
|
+
return [{ platform: this.id, action: "skip", detail: "connector declares no hooks" }];
|
|
179
|
+
}
|
|
180
|
+
const agentPath = this.getHookConfigPath(ctx);
|
|
181
|
+
const agent = this.readJson(agentPath) ?? {};
|
|
182
|
+
const hooks = agent.hooks ??= {};
|
|
183
|
+
const changes = [];
|
|
184
|
+
let mutated = false;
|
|
185
|
+
for (const event of connector.hookEvents) {
|
|
186
|
+
const kiroEvent = EVENT_MAP[event];
|
|
187
|
+
if (!kiroEvent) {
|
|
188
|
+
changes.push({
|
|
189
|
+
platform: this.id,
|
|
190
|
+
action: "warn",
|
|
191
|
+
path: agentPath,
|
|
192
|
+
detail: `${event} has no Kiro hook equivalent \u2014 skipped`
|
|
193
|
+
});
|
|
194
|
+
continue;
|
|
195
|
+
}
|
|
196
|
+
const command = buildHomeBinHookCommand(ctx.homeBinPath, HOST, event, connector.id);
|
|
197
|
+
const matcher = connector.hooks[event]?.matcher ?? "";
|
|
198
|
+
const entry = {
|
|
199
|
+
matcher,
|
|
200
|
+
hooks: [{ type: "command", command }]
|
|
201
|
+
};
|
|
202
|
+
const bucket = hooks[kiroEvent] ??= [];
|
|
203
|
+
const existingIdx = bucket.findIndex((e) => this.entryHasOurCommand(e, ctx));
|
|
204
|
+
if (existingIdx >= 0) {
|
|
205
|
+
if (JSON.stringify(bucket[existingIdx]) === JSON.stringify(entry)) {
|
|
206
|
+
changes.push({
|
|
207
|
+
platform: this.id,
|
|
208
|
+
action: "skip",
|
|
209
|
+
path: agentPath,
|
|
210
|
+
detail: `hooks.${kiroEvent} already registered`
|
|
211
|
+
});
|
|
212
|
+
continue;
|
|
213
|
+
}
|
|
214
|
+
bucket[existingIdx] = entry;
|
|
215
|
+
changes.push({
|
|
216
|
+
platform: this.id,
|
|
217
|
+
action: "update",
|
|
218
|
+
path: agentPath,
|
|
219
|
+
detail: `hooks.${kiroEvent}`
|
|
220
|
+
});
|
|
221
|
+
} else {
|
|
222
|
+
bucket.push(entry);
|
|
223
|
+
changes.push({
|
|
224
|
+
platform: this.id,
|
|
225
|
+
action: "create",
|
|
226
|
+
path: agentPath,
|
|
227
|
+
detail: `hooks.${kiroEvent}`
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
mutated = true;
|
|
231
|
+
}
|
|
232
|
+
if (mutated) this.writeJson(agentPath, agent, ctx.dryRun);
|
|
233
|
+
return changes;
|
|
234
|
+
}
|
|
235
|
+
uninstallHooks(ctx) {
|
|
236
|
+
const agentPath = this.getHookConfigPath(ctx);
|
|
237
|
+
const agent = this.readJson(agentPath);
|
|
238
|
+
const hooks = agent?.hooks;
|
|
239
|
+
if (!agent || !hooks) {
|
|
240
|
+
return [
|
|
241
|
+
{
|
|
242
|
+
platform: this.id,
|
|
243
|
+
action: "skip",
|
|
244
|
+
path: agentPath,
|
|
245
|
+
detail: "no hooks section present"
|
|
246
|
+
}
|
|
247
|
+
];
|
|
248
|
+
}
|
|
249
|
+
const changes = [];
|
|
250
|
+
let mutated = false;
|
|
251
|
+
for (const kiroEvent of Object.keys(hooks)) {
|
|
252
|
+
const bucket = hooks[kiroEvent];
|
|
253
|
+
if (!Array.isArray(bucket)) continue;
|
|
254
|
+
const next = [];
|
|
255
|
+
let removed = 0;
|
|
256
|
+
for (const e of bucket) {
|
|
257
|
+
const innerBefore = e.hooks?.length ?? 0;
|
|
258
|
+
const inner = (e.hooks ?? []).filter((h) => !this.isOurCommand(h.command, ctx));
|
|
259
|
+
removed += innerBefore - inner.length;
|
|
260
|
+
if (inner.length > 0) next.push({ matcher: e.matcher ?? "", hooks: inner });
|
|
261
|
+
}
|
|
262
|
+
if (removed > 0) {
|
|
263
|
+
if (next.length > 0) hooks[kiroEvent] = next;
|
|
264
|
+
else delete hooks[kiroEvent];
|
|
265
|
+
changes.push({
|
|
266
|
+
platform: this.id,
|
|
267
|
+
action: "remove",
|
|
268
|
+
path: agentPath,
|
|
269
|
+
detail: `hooks.${kiroEvent} (${removed})`
|
|
270
|
+
});
|
|
271
|
+
mutated = true;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
if (mutated) this.writeJson(agentPath, agent, ctx.dryRun);
|
|
275
|
+
if (changes.length === 0) {
|
|
276
|
+
changes.push({
|
|
277
|
+
platform: this.id,
|
|
278
|
+
action: "skip",
|
|
279
|
+
path: agentPath,
|
|
280
|
+
detail: "no matching hook entries"
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
return changes;
|
|
284
|
+
}
|
|
285
|
+
entryHasOurCommand(entry, ctx) {
|
|
286
|
+
return (entry.hooks ?? []).some((h) => this.isOurCommand(h.command, ctx));
|
|
287
|
+
}
|
|
288
|
+
/** True when a hook command references our home binary AND this connector id
|
|
289
|
+
* (anchored so a shared-prefix id can't collide — see isHomeBinHookCommand). */
|
|
290
|
+
isOurCommand(command, ctx) {
|
|
291
|
+
return isHomeBinHookCommand(command, ctx.homeBinPath, ctx.connector.id);
|
|
292
|
+
}
|
|
293
|
+
// ── Diagnostics ──────────────────────────────────────────────────────────
|
|
294
|
+
getHealthChecks(ctx) {
|
|
295
|
+
const mcpPath = this.getServerConfigPath(ctx);
|
|
296
|
+
const agentPath = this.getHookConfigPath(ctx);
|
|
297
|
+
const connectorId = ctx.connector.id;
|
|
298
|
+
const homeBin = ctx.homeBinPath;
|
|
299
|
+
const hookEvents = ctx.connector.hookEvents;
|
|
300
|
+
return [
|
|
301
|
+
{
|
|
302
|
+
name: `${this.name}: mcp.json present`,
|
|
303
|
+
check: () => existsSync(mcpPath) ? { status: "OK", detail: mcpPath } : { status: "FAIL", detail: `not found: ${mcpPath}` }
|
|
304
|
+
},
|
|
305
|
+
{
|
|
306
|
+
name: `${this.name}: server entry registered`,
|
|
307
|
+
check: () => {
|
|
308
|
+
const cfg = this.readJson(mcpPath);
|
|
309
|
+
const bucket = cfg?.mcpServers;
|
|
310
|
+
if (!cfg || !bucket) {
|
|
311
|
+
return { status: "FAIL", detail: `no ${MCP_ROOT_KEY} in ${mcpPath}` };
|
|
312
|
+
}
|
|
313
|
+
return connectorId in bucket ? { status: "OK", detail: `${MCP_ROOT_KEY}.${connectorId} present` } : { status: "FAIL", detail: `no ${MCP_ROOT_KEY}.${connectorId} in ${mcpPath}` };
|
|
314
|
+
}
|
|
315
|
+
},
|
|
316
|
+
{
|
|
317
|
+
name: `${this.name}: hook command registered`,
|
|
318
|
+
check: () => {
|
|
319
|
+
if (hookEvents.length === 0) {
|
|
320
|
+
return { status: "OK", detail: "no hooks declared" };
|
|
321
|
+
}
|
|
322
|
+
const agent = this.readJson(agentPath);
|
|
323
|
+
if (!agent) return { status: "FAIL", detail: `cannot read ${agentPath}` };
|
|
324
|
+
const hooks = agent.hooks ?? {};
|
|
325
|
+
const registered = Object.values(hooks).some(
|
|
326
|
+
(entries) => (entries ?? []).some(
|
|
327
|
+
(e) => (e.hooks ?? []).some(
|
|
328
|
+
(h) => isHomeBinHookCommand(h.command, homeBin, connectorId)
|
|
329
|
+
)
|
|
330
|
+
)
|
|
331
|
+
);
|
|
332
|
+
return registered ? { status: "OK", detail: "hook command present" } : { status: "FAIL", detail: `no hook for ${connectorId} in ${agentPath}` };
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
];
|
|
336
|
+
}
|
|
337
|
+
// ── Runtime: parse Kiro stdin JSON → normalized event ────────────────────
|
|
338
|
+
parseEvent(event, raw) {
|
|
339
|
+
const input = raw ?? {};
|
|
340
|
+
const connectorId = typeof input.connector === "string" ? input.connector : "";
|
|
341
|
+
const sessionId = typeof input.session_id === "string" ? input.session_id : "";
|
|
342
|
+
const projectDir = typeof input.cwd === "string" ? input.cwd : void 0;
|
|
343
|
+
const base = {
|
|
344
|
+
hostPlatform: HOST,
|
|
345
|
+
connectorId,
|
|
346
|
+
sessionId,
|
|
347
|
+
raw,
|
|
348
|
+
...projectDir !== void 0 ? { projectDir } : {}
|
|
349
|
+
};
|
|
350
|
+
switch (event) {
|
|
351
|
+
case "PreToolUse": {
|
|
352
|
+
const ev = {
|
|
353
|
+
...base,
|
|
354
|
+
toolName: input.tool_name ?? "",
|
|
355
|
+
toolInput: input.tool_input ?? {}
|
|
356
|
+
};
|
|
357
|
+
return ev;
|
|
358
|
+
}
|
|
359
|
+
case "PostToolUse": {
|
|
360
|
+
const ev = {
|
|
361
|
+
...base,
|
|
362
|
+
toolName: input.tool_name ?? "",
|
|
363
|
+
toolInput: input.tool_input ?? {},
|
|
364
|
+
...toolResponseToString(input.tool_response) !== void 0 ? { toolOutput: toolResponseToString(input.tool_response) } : {}
|
|
365
|
+
};
|
|
366
|
+
return ev;
|
|
367
|
+
}
|
|
368
|
+
case "SessionStart": {
|
|
369
|
+
const ev = {
|
|
370
|
+
...base,
|
|
371
|
+
source: normalizeSessionSource(input.source)
|
|
372
|
+
};
|
|
373
|
+
return ev;
|
|
374
|
+
}
|
|
375
|
+
case "UserPromptSubmit": {
|
|
376
|
+
const ev = {
|
|
377
|
+
...base,
|
|
378
|
+
prompt: typeof input.prompt === "string" ? input.prompt : ""
|
|
379
|
+
};
|
|
380
|
+
return ev;
|
|
381
|
+
}
|
|
382
|
+
case "Stop": {
|
|
383
|
+
const ev = {
|
|
384
|
+
...base,
|
|
385
|
+
...typeof input.stop_hook_active === "boolean" ? { stopHookActive: input.stop_hook_active } : {}
|
|
386
|
+
};
|
|
387
|
+
return ev;
|
|
388
|
+
}
|
|
389
|
+
default: {
|
|
390
|
+
throw new Error(`unsupported kiro hook event: ${String(event)}`);
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
// ── Runtime: normalized response → Kiro native (exit-code) hook reply ─────
|
|
395
|
+
formatReply(event, response) {
|
|
396
|
+
const decision = response.decision ?? "allow";
|
|
397
|
+
if (decision === "deny") {
|
|
398
|
+
return { exitCode: 2, stderr: response.reason ?? "Blocked by hook" };
|
|
399
|
+
}
|
|
400
|
+
if (decision === "ask") {
|
|
401
|
+
return {
|
|
402
|
+
exitCode: 2,
|
|
403
|
+
stderr: response.reason ?? "Action requires user confirmation (security policy)"
|
|
404
|
+
};
|
|
405
|
+
}
|
|
406
|
+
if (event === "Stop") {
|
|
407
|
+
return { exitCode: 0 };
|
|
408
|
+
}
|
|
409
|
+
if (decision === "context" && response.additionalContext) {
|
|
410
|
+
return {
|
|
411
|
+
exitCode: 0,
|
|
412
|
+
stdout: JSON.stringify({
|
|
413
|
+
hookSpecificOutput: {
|
|
414
|
+
hookEventName: KIRO_EVENT.agentSpawn,
|
|
415
|
+
additionalContext: response.additionalContext
|
|
416
|
+
}
|
|
417
|
+
})
|
|
418
|
+
};
|
|
419
|
+
}
|
|
420
|
+
return { exitCode: 0 };
|
|
421
|
+
}
|
|
422
|
+
};
|
|
423
|
+
function toolResponseToString(value) {
|
|
424
|
+
if (value == null) return void 0;
|
|
425
|
+
if (typeof value === "string") return value;
|
|
426
|
+
try {
|
|
427
|
+
return JSON.stringify(value);
|
|
428
|
+
} catch {
|
|
429
|
+
return String(value);
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
function normalizeSessionSource(source) {
|
|
433
|
+
switch (source) {
|
|
434
|
+
case "compact":
|
|
435
|
+
return "compact";
|
|
436
|
+
case "resume":
|
|
437
|
+
return "resume";
|
|
438
|
+
case "clear":
|
|
439
|
+
return "clear";
|
|
440
|
+
default:
|
|
441
|
+
return "startup";
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
var adapter = new KiroAdapter();
|
|
445
|
+
var kiro_default = adapter;
|
|
446
|
+
export {
|
|
447
|
+
KiroAdapter,
|
|
448
|
+
adapter,
|
|
449
|
+
kiro_default as default
|
|
450
|
+
};
|
|
451
|
+
//# sourceMappingURL=kiro-VQTT6LO2.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/adapters/kiro/index.ts"],"sourcesContent":["/**\n * adapters/kiro — Kiro (AWS) platform adapter for agent-connector.\n *\n * Kiro is a json-stdio host with TWO native config surfaces that live in\n * DIFFERENT files (so getServerConfigPath ≠ getHookConfigPath):\n *\n * 1. MCP servers — `mcp.json` under `~/.kiro/settings/` (user) or\n * `<projectDir>/.kiro/settings/` (project). The file is JSONC; we WRITE\n * plain JSON (valid JSONC), mirroring the other JSON-config adapters. Root\n * key `mcpServers`; a stdio server is `{ command, args, env }`.\n * Ref: https://kiro.dev/docs/mcp/configuration/\n *\n * 2. Hooks — NOT a settings file but an AGENT file:\n * `~/.kiro/agents/kiro_default.json`. Kiro auto-loads the built-in default\n * agent `kiro_default` for a new chat session, so hooks must register on\n * THAT agent (a file literally named `default.json` would define an inactive\n * custom agent the user must `/agent`-swap to). We merge a `hooks` key into\n * the existing agent JSON, creating a minimal agent object if absent.\n * Ref: kiro.dev/docs/cli/custom-agents/configuration-reference#hooks-field\n *\n * Hook protocol is EXIT-CODE based (unlike Claude's JSON-decision wrapper):\n * - exit 0 → allow the action.\n * - exit 2 → block the action; the reason is written to stderr.\n * - agentSpawn (≈ SessionStart) context injection → exit 0 + stdout JSON\n * `{ hookSpecificOutput: { additionalContext } }`.\n * Kiro CANNOT rewrite tool arguments or output (exit codes only), so\n * canModifyArgs / canModifyOutput are false; `modify` degrades to allow.\n *\n * Native hook event vocabulary differs from the canonical names and is mapped:\n * PreToolUse → preToolUse\n * PostToolUse → postToolUse\n * SessionStart → agentSpawn (Kiro's session-start equivalent)\n * UserPromptSubmit → userPromptSubmit\n * Stop → stop (documented Kiro hook)\n * Kiro has no equivalent for PreCompact / SessionEnd / Notification; those are\n * reported as a warn/skip at install time.\n *\n * Env handling: Kiro documents no `${env:VAR}` token of the framework's syntax,\n * so env/header/url refs are resolved to literals at install time via\n * resolveEnvRefsDeep — the safe default matching the Gemini/Codex adapters.\n *\n * Grounded in context-mode's proven Kiro adapter (src/adapters/kiro/*).\n */\n\nimport { existsSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\nimport { BaseAdapter } from \"../base.js\";\nimport type { Adapter, HookReply, InstallContext, NormalizedEvent } from \"../spi.js\";\nimport type {\n ChangeRecord,\n DetectedPlatform,\n HealthCheck,\n HookEventName,\n HookParadigm,\n HookResponse,\n PlatformCapabilities,\n PlatformId,\n PostToolUseEvent,\n PreToolUseEvent,\n ServerDef,\n SessionStartEvent,\n StopEvent,\n Transport,\n UserPromptSubmitEvent,\n} from \"../../core/types.js\";\nimport { resolveEnvRefsDeep } from \"../../core/interpolate.js\";\nimport {\n buildHomeBinHookCommand,\n buildServeWrapperCommand,\n isHomeBinHookCommand,\n shouldWrapForTelemetry,\n} from \"../../core/spawn.js\";\n\nconst HOST: PlatformId = \"kiro\";\nconst MCP_ROOT_KEY = \"mcpServers\";\n\n/** The built-in agent Kiro auto-loads for a new chat session. */\nconst DEFAULT_AGENT_FILE = \"kiro_default.json\";\n\n/**\n * Kiro-native hook event names (the keys under an agent file's `hooks` object).\n * Only the events Kiro actually fires for the json-stdio command paradigm.\n */\nconst KIRO_EVENT = {\n preToolUse: \"preToolUse\",\n postToolUse: \"postToolUse\",\n agentSpawn: \"agentSpawn\",\n userPromptSubmit: \"userPromptSubmit\",\n stop: \"stop\",\n} as const;\n\n/**\n * Map canonical event names → Kiro's native hook event names. Only the events\n * Kiro supports are present; PreCompact / SessionEnd / Notification have no Kiro\n * equivalent and are reported as a warn/skip at install time.\n */\nconst EVENT_MAP: Partial<Record<HookEventName, string>> = {\n PreToolUse: KIRO_EVENT.preToolUse,\n PostToolUse: KIRO_EVENT.postToolUse,\n SessionStart: KIRO_EVENT.agentSpawn,\n UserPromptSubmit: KIRO_EVENT.userPromptSubmit,\n Stop: KIRO_EVENT.stop,\n};\n\n/** A single Kiro native hook registration entry (Claude-shaped, nested). */\ninterface KiroHookEntry {\n matcher: string;\n hooks: Array<{ type: \"command\"; command: string }>;\n}\n\n/** The shape of a Kiro agent file (only the parts we touch). */\ninterface KiroAgentFile {\n hooks?: Record<string, KiroHookEntry[]>;\n [key: string]: unknown;\n}\n\n/** The shape of Kiro's mcp.json (only the parts we touch). */\ninterface KiroMcpFile {\n mcpServers?: Record<string, unknown>;\n [key: string]: unknown;\n}\n\n/** Native MCP server entry shapes Kiro accepts under `mcpServers`. */\ninterface KiroStdioServer {\n command: string;\n args?: string[];\n env?: Record<string, string>;\n cwd?: string;\n}\ninterface KiroHttpServer {\n url: string;\n headers?: Record<string, string>;\n}\n\n/** Raw Kiro CLI hook stdin payload (snake_case wire fields). */\ninterface KiroWireInput {\n connector?: unknown;\n hook_event_name?: string;\n cwd?: string;\n session_id?: string;\n tool_name?: string;\n tool_input?: Record<string, unknown>;\n tool_response?: unknown;\n source?: string;\n prompt?: string;\n stop_hook_active?: boolean;\n}\n\nexport class KiroAdapter extends BaseAdapter implements Adapter {\n readonly id: PlatformId = HOST;\n readonly name = \"Kiro\";\n readonly paradigm: HookParadigm = \"json-stdio\";\n\n readonly capabilities: PlatformCapabilities = {\n preToolUse: true,\n postToolUse: true,\n preCompact: false,\n sessionStart: true,\n sessionEnd: false,\n // Kiro fires userPromptSubmit and stop, but it has no PreCompact /\n // SessionEnd / Notification equivalent.\n userPromptSubmit: true,\n stop: true,\n notification: false,\n // Kiro's hook protocol is exit-code only — a hook can allow (0), block (2),\n // or inject agentSpawn context, but it CANNOT rewrite tool args or output.\n canModifyArgs: false,\n canModifyOutput: false,\n // agentSpawn returns additionalContext via JSON stdout.\n canInjectSessionContext: true,\n transports: [\"stdio\", \"http\"],\n };\n\n // ── Detection ────────────────────────────────────────────────────────────\n\n detectInstalled(projectDir: string): DetectedPlatform {\n const userDir = join(homedir(), \".kiro\");\n const userMcp = this.userMcpPath();\n const projectDirKiro = join(projectDir, \".kiro\");\n const projectMcp = this.projectMcpPath(projectDir);\n\n const userInstalled = existsSync(userDir) || existsSync(userMcp);\n const projInstalled = existsSync(projectDirKiro) || existsSync(projectMcp);\n const installed = userInstalled || projInstalled;\n // Report the scope/path that actually matched, so a project-only install\n // isn't misreported as a (non-existent) user install.\n const scope = projInstalled && !userInstalled ? \"project\" : \"user\";\n const configPath = scope === \"project\" ? projectMcp : userMcp;\n return {\n id: this.id,\n name: this.name,\n installed,\n paradigm: this.paradigm,\n capabilities: this.capabilities,\n configPath,\n scope,\n reason: installed\n ? scope === \"project\"\n ? `found project Kiro config at ${projectMcp}`\n : `found Kiro config under ${userDir}`\n : `no Kiro config at ${userDir}`,\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, \".kiro\")\n : join(homedir(), \".kiro\");\n }\n\n /** MCP servers live in mcp.json under the scope's `.kiro/settings/`. */\n getServerConfigPath(ctx: InstallContext): string {\n return ctx.scope === \"project\"\n ? this.projectMcpPath(ctx.projectDir)\n : this.userMcpPath();\n }\n\n /**\n * Hooks live in an AGENT file, NOT a settings file. Kiro auto-loads the\n * built-in default agent (`kiro_default`) for a new chat session, so we always\n * register hooks on the user-scope default agent — that is the agent Kiro\n * actually loads regardless of install scope.\n */\n getHookConfigPath(_ctx: InstallContext): string {\n return join(homedir(), \".kiro\", \"agents\", DEFAULT_AGENT_FILE);\n }\n\n private userMcpPath(): string {\n return join(homedir(), \".kiro\", \"settings\", \"mcp.json\");\n }\n\n private projectMcpPath(projectDir: string): string {\n return join(projectDir, \".kiro\", \"settings\", \"mcp.json\");\n }\n\n // ── MCP server install / uninstall ───────────────────────────────────────\n\n installServer(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n const override = connector.platforms[HOST]?.server;\n if (!connector.server || override === false) {\n return [\n {\n platform: this.id,\n action: \"skip\",\n detail: connector.server\n ? \"server registration disabled for kiro\"\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 Kiro's native mcpServers entry. */\n private renderServerEntry(\n ctx: InstallContext,\n server: ServerDef,\n ): KiroStdioServer | KiroHttpServer {\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 if (shouldWrapForTelemetry(server, ctx.connector.telemetry)) {\n const wrapped = buildServeWrapperCommand(\n ctx.homeBinPath,\n ctx.connector.id,\n command,\n args,\n ctx.scope,\n this.id,\n );\n command = wrapped.command;\n args = wrapped.args;\n }\n\n // Kiro documents no native interpolation token, so resolve every\n // ${env:VAR} to a literal at install time.\n const entry: KiroStdioServer = { command: resolveEnvRefsDeep(command) };\n if (args.length > 0) entry.args = resolveEnvRefsDeep(args);\n const env = this.renderEnv(server.env);\n if (env) entry.env = env;\n if (server.cwd) entry.cwd = resolveEnvRefsDeep(server.cwd);\n return entry;\n }\n\n // http (and any other remote transport) — Kiro registers a URL.\n const entry: KiroHttpServer = { url: resolveEnvRefsDeep(server.url ?? \"\") };\n const headers = this.renderEnv(server.headers);\n if (headers) entry.headers = headers;\n return entry;\n }\n\n /**\n * Render env/header values. Kiro documents no native interpolation token, so\n * resolve `${env:VAR}` references to literals at install time.\n */\n private renderEnv(\n env: Record<string, string> | undefined,\n ): Record<string, string> | undefined {\n if (!env || Object.keys(env).length === 0) return undefined;\n return resolveEnvRefsDeep({ ...env });\n }\n\n // ── Hook install / uninstall (merge into the agent file) ─────────────────\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 kiro\" }];\n }\n if (connector.hookEvents.length === 0) {\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no hooks\" }];\n }\n\n const agentPath = this.getHookConfigPath(ctx);\n // Merge into the existing agent JSON; create a minimal agent object if absent.\n const agent = this.readJson<KiroAgentFile>(agentPath) ?? {};\n const hooks = (agent.hooks ??= {});\n\n const changes: ChangeRecord[] = [];\n let mutated = false;\n\n for (const event of connector.hookEvents) {\n const kiroEvent = EVENT_MAP[event];\n if (!kiroEvent) {\n // No Kiro equivalent for this canonical event — report and continue.\n changes.push({\n platform: this.id,\n action: \"warn\",\n path: agentPath,\n detail: `${event} has no Kiro hook equivalent — skipped`,\n });\n continue;\n }\n\n const command = buildHomeBinHookCommand(ctx.homeBinPath, HOST, event, connector.id);\n const matcher = connector.hooks[event]?.matcher ?? \"\";\n const entry: KiroHookEntry = {\n matcher,\n hooks: [{ type: \"command\", command }],\n };\n\n const bucket = (hooks[kiroEvent] ??= []);\n const existingIdx = bucket.findIndex((e) => this.entryHasOurCommand(e, ctx));\n\n if (existingIdx >= 0) {\n if (JSON.stringify(bucket[existingIdx]) === JSON.stringify(entry)) {\n changes.push({\n platform: this.id,\n action: \"skip\",\n path: agentPath,\n detail: `hooks.${kiroEvent} already registered`,\n });\n continue;\n }\n bucket[existingIdx] = entry;\n changes.push({\n platform: this.id,\n action: \"update\",\n path: agentPath,\n detail: `hooks.${kiroEvent}`,\n });\n } else {\n bucket.push(entry);\n changes.push({\n platform: this.id,\n action: \"create\",\n path: agentPath,\n detail: `hooks.${kiroEvent}`,\n });\n }\n mutated = true;\n }\n\n if (mutated) this.writeJson(agentPath, agent, ctx.dryRun);\n return changes;\n }\n\n uninstallHooks(ctx: InstallContext): ChangeRecord[] {\n const agentPath = this.getHookConfigPath(ctx);\n const agent = this.readJson<KiroAgentFile>(agentPath);\n const hooks = agent?.hooks;\n if (!agent || !hooks) {\n return [\n {\n platform: this.id,\n action: \"skip\",\n path: agentPath,\n detail: \"no hooks section present\",\n },\n ];\n }\n\n const changes: ChangeRecord[] = [];\n let mutated = false;\n\n for (const kiroEvent of Object.keys(hooks)) {\n const bucket = hooks[kiroEvent];\n if (!Array.isArray(bucket)) continue;\n\n // Strip our hook command from each entry; drop entries left empty so we\n // never remove another connector's (or the user's own) hook commands.\n const next: KiroHookEntry[] = [];\n let removed = 0;\n for (const e of bucket) {\n const innerBefore = e.hooks?.length ?? 0;\n const inner = (e.hooks ?? []).filter((h) => !this.isOurCommand(h.command, ctx));\n removed += innerBefore - inner.length;\n if (inner.length > 0) next.push({ matcher: e.matcher ?? \"\", hooks: inner });\n }\n\n if (removed > 0) {\n if (next.length > 0) hooks[kiroEvent] = next;\n else delete hooks[kiroEvent];\n changes.push({\n platform: this.id,\n action: \"remove\",\n path: agentPath,\n detail: `hooks.${kiroEvent} (${removed})`,\n });\n mutated = true;\n }\n }\n\n if (mutated) this.writeJson(agentPath, agent, ctx.dryRun);\n if (changes.length === 0) {\n changes.push({\n platform: this.id,\n action: \"skip\",\n path: agentPath,\n detail: \"no matching hook entries\",\n });\n }\n return changes;\n }\n\n private entryHasOurCommand(entry: KiroHookEntry, ctx: InstallContext): boolean {\n return (entry.hooks ?? []).some((h) => this.isOurCommand(h.command, ctx));\n }\n\n /** True when a hook command references our home binary AND this connector id\n * (anchored so a shared-prefix id can't collide — see isHomeBinHookCommand). */\n private isOurCommand(command: string | undefined, ctx: InstallContext): boolean {\n return isHomeBinHookCommand(command, ctx.homeBinPath, ctx.connector.id);\n }\n\n // ── Diagnostics ──────────────────────────────────────────────────────────\n\n override getHealthChecks(ctx: InstallContext): readonly HealthCheck[] {\n const mcpPath = this.getServerConfigPath(ctx);\n const agentPath = this.getHookConfigPath(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}: mcp.json present`,\n check: () =>\n existsSync(mcpPath)\n ? { status: \"OK\", detail: mcpPath }\n : { status: \"FAIL\", detail: `not found: ${mcpPath}` },\n },\n {\n name: `${this.name}: server entry registered`,\n check: () => {\n const cfg = this.readJson<KiroMcpFile>(mcpPath);\n const bucket = cfg?.mcpServers;\n if (!cfg || !bucket) {\n return { status: \"FAIL\", detail: `no ${MCP_ROOT_KEY} in ${mcpPath}` };\n }\n return connectorId in bucket\n ? { status: \"OK\", detail: `${MCP_ROOT_KEY}.${connectorId} present` }\n : { status: \"FAIL\", detail: `no ${MCP_ROOT_KEY}.${connectorId} in ${mcpPath}` };\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 agent = this.readJson<KiroAgentFile>(agentPath);\n if (!agent) return { status: \"FAIL\", detail: `cannot read ${agentPath}` };\n const hooks = agent.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 ${agentPath}` };\n },\n },\n ];\n }\n\n // ── Runtime: parse Kiro stdin JSON → normalized event ────────────────────\n\n parseEvent(event: HookEventName, raw: unknown): NormalizedEvent {\n const input = (raw ?? {}) as KiroWireInput;\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 \"SessionStart\": {\n const ev: SessionStartEvent = {\n ...base,\n source: normalizeSessionSource(input.source),\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 default: {\n // Kiro never delivers PreCompact / SessionEnd / Notification (no native\n // equivalent). If the runtime dispatches one anyway, surface it loudly\n // rather than silently mis-parse.\n throw new Error(`unsupported kiro hook event: ${String(event)}`);\n }\n }\n }\n\n // ── Runtime: normalized response → Kiro native (exit-code) hook reply ─────\n\n formatReply(event: HookEventName, response: HookResponse): HookReply {\n const decision = response.decision ?? \"allow\";\n\n // deny → block the action: exit 2 with the reason on stderr.\n if (decision === \"deny\") {\n return { exitCode: 2, stderr: response.reason ?? \"Blocked by hook\" };\n }\n\n // ask → Kiro has no native \"ask\"; degrade to deny (exit 2) to stay fail-safe.\n if (decision === \"ask\") {\n return {\n exitCode: 2,\n stderr: response.reason ?? \"Action requires user confirmation (security policy)\",\n };\n }\n\n // Stop → exit-code only (deny already handled above as exit 2). There is no\n // context/additionalContext channel on a Stop hook, so anything non-deny\n // passes through with exit 0 (do not fall into the agentSpawn branch).\n if (event === \"Stop\") {\n return { exitCode: 0 };\n }\n\n // context → inject soft guidance. Kiro reads agentSpawn additionalContext\n // from stdout JSON (mirrors the Claude SessionStart shape). exit 0 = allow.\n if (decision === \"context\" && response.additionalContext) {\n return {\n exitCode: 0,\n stdout: JSON.stringify({\n hookSpecificOutput: {\n hookEventName: KIRO_EVENT.agentSpawn,\n additionalContext: response.additionalContext,\n },\n }),\n };\n }\n\n // modify is unsupported on Kiro (exit-code protocol — cannot rewrite\n // args/output); allow / void → pass through with exit 0.\n return { exitCode: 0 };\n }\n}\n\n/** Coerce a Kiro 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\nfunction normalizeSessionSource(source: string | undefined): SessionStartEvent[\"source\"] {\n switch (source) {\n case \"compact\":\n return \"compact\";\n case \"resume\":\n return \"resume\";\n case \"clear\":\n return \"clear\";\n default:\n return \"startup\";\n }\n}\n\nexport const adapter = new KiroAdapter();\nexport default adapter;\n"],"mappings":"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","names":["entry"]}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
formatHostLeaderboard,
|
|
4
|
+
hostLeaderboard
|
|
5
|
+
} from "./chunk-WV63X7IK.js";
|
|
6
|
+
import {
|
|
7
|
+
SCOPE_FILTER_VALUES,
|
|
8
|
+
formatHostNativeTurns,
|
|
9
|
+
formatMcpLeaderboard,
|
|
10
|
+
hostNativeTurns,
|
|
11
|
+
isScopeFilter,
|
|
12
|
+
mcpLeaderboard
|
|
13
|
+
} from "./chunk-JNM3TPLX.js";
|
|
14
|
+
import "./chunk-XD7MY6HB.js";
|
|
15
|
+
import {
|
|
16
|
+
fail,
|
|
17
|
+
print
|
|
18
|
+
} from "./chunk-54EMKTTX.js";
|
|
19
|
+
import "./chunk-BCHWFTV4.js";
|
|
20
|
+
import "./chunk-TRQKHP7D.js";
|
|
21
|
+
|
|
22
|
+
// src/cli/commands/leaderboard.ts
|
|
23
|
+
import { parseArgs } from "util";
|
|
24
|
+
function parseSince(since) {
|
|
25
|
+
if (since == null || since.trim() === "") return void 0;
|
|
26
|
+
const m = since.trim().match(/^(\d+)\s*([smhd])$/i);
|
|
27
|
+
if (!m || !m[1] || !m[2]) return null;
|
|
28
|
+
const n = Number(m[1]);
|
|
29
|
+
const unitMs = {
|
|
30
|
+
s: 1e3,
|
|
31
|
+
m: 6e4,
|
|
32
|
+
h: 36e5,
|
|
33
|
+
d: 864e5
|
|
34
|
+
};
|
|
35
|
+
const factor = unitMs[m[2].toLowerCase()];
|
|
36
|
+
if (factor == null) return null;
|
|
37
|
+
return Date.now() - n * factor;
|
|
38
|
+
}
|
|
39
|
+
async function run(argv) {
|
|
40
|
+
const first = argv[0];
|
|
41
|
+
if (first === "--help" || first === "-h") {
|
|
42
|
+
print("usage: agent-connector leaderboard [flags]");
|
|
43
|
+
print(" --since 7d|24h|\u2026 window applied to BOTH sources");
|
|
44
|
+
print(` --scope <value> MCP-section slice (${SCOPE_FILTER_VALUES.join("|")})`);
|
|
45
|
+
print(" --connector <id> restrict the \u{1F50C} MCP + \u{1F6F0}\uFE0F host-native sections to one connector");
|
|
46
|
+
print(" --json emit { mcp:[...], host:[...] } (never summed)");
|
|
47
|
+
return 0;
|
|
48
|
+
}
|
|
49
|
+
const { values } = parseArgs({
|
|
50
|
+
args: argv,
|
|
51
|
+
options: {
|
|
52
|
+
since: { type: "string" },
|
|
53
|
+
scope: { type: "string" },
|
|
54
|
+
connector: { type: "string" },
|
|
55
|
+
json: { type: "boolean", default: false }
|
|
56
|
+
},
|
|
57
|
+
allowPositionals: false
|
|
58
|
+
});
|
|
59
|
+
const sinceMs = parseSince(values.since);
|
|
60
|
+
if (sinceMs === null) {
|
|
61
|
+
return fail(`invalid --since "${values.since}" (use forms like 30s, 15m, 24h, 7d)`);
|
|
62
|
+
}
|
|
63
|
+
let scope;
|
|
64
|
+
if (values.scope !== void 0 && values.scope.trim() !== "") {
|
|
65
|
+
const s = values.scope.trim();
|
|
66
|
+
if (!isScopeFilter(s)) {
|
|
67
|
+
return fail(`invalid --scope "${s}" (use ${SCOPE_FILTER_VALUES.join("|")})`);
|
|
68
|
+
}
|
|
69
|
+
scope = s;
|
|
70
|
+
}
|
|
71
|
+
const connectorId = values.connector !== void 0 && values.connector.trim() !== "" ? values.connector.trim() : void 0;
|
|
72
|
+
const mcpOpts = {};
|
|
73
|
+
if (sinceMs !== void 0) mcpOpts.sinceMs = sinceMs;
|
|
74
|
+
if (scope !== void 0) mcpOpts.scope = scope;
|
|
75
|
+
if (connectorId !== void 0) mcpOpts.connectorId = connectorId;
|
|
76
|
+
const mcp = mcpLeaderboard(mcpOpts);
|
|
77
|
+
const hostOpts = {};
|
|
78
|
+
if (sinceMs !== void 0) hostOpts.sinceMs = sinceMs;
|
|
79
|
+
const host = await hostLeaderboard(hostOpts);
|
|
80
|
+
const turnsOpts = {};
|
|
81
|
+
if (sinceMs !== void 0) turnsOpts.sinceMs = sinceMs;
|
|
82
|
+
if (scope !== void 0) turnsOpts.scope = scope;
|
|
83
|
+
if (connectorId !== void 0) turnsOpts.connectorId = connectorId;
|
|
84
|
+
const turns = hostNativeTurns(turnsOpts);
|
|
85
|
+
if (values.json) {
|
|
86
|
+
print(
|
|
87
|
+
JSON.stringify(
|
|
88
|
+
{
|
|
89
|
+
mcp,
|
|
90
|
+
// origin: mcp-self
|
|
91
|
+
host: host.rows,
|
|
92
|
+
// origin: host-scan-logs
|
|
93
|
+
hostSkipped: host.skipped,
|
|
94
|
+
hostNativeTurns: turns
|
|
95
|
+
// origin: host-native-live (scope model_turn)
|
|
96
|
+
},
|
|
97
|
+
null,
|
|
98
|
+
2
|
|
99
|
+
)
|
|
100
|
+
);
|
|
101
|
+
return 0;
|
|
102
|
+
}
|
|
103
|
+
const lines = [];
|
|
104
|
+
lines.push(
|
|
105
|
+
"\u{1F50C} MCP / Plugin leaderboard (origin: mcp-self \u2014 per-MCP server bytes we wrap; excludes host-native model_turn rows)"
|
|
106
|
+
);
|
|
107
|
+
if (scope !== void 0) lines.push(` scope: ${scope}`);
|
|
108
|
+
if (connectorId !== void 0) lines.push(` connector: ${connectorId}`);
|
|
109
|
+
lines.push("");
|
|
110
|
+
lines.push(formatMcpLeaderboard(mcp));
|
|
111
|
+
lines.push("");
|
|
112
|
+
lines.push(
|
|
113
|
+
"\u{1F5A5}\uFE0F Host / User leaderboard (origin: host-scan-logs \u2014 whole-conversation usage from CLI logs)"
|
|
114
|
+
);
|
|
115
|
+
if (connectorId !== void 0) {
|
|
116
|
+
lines.push(" (connector-agnostic \u2014 host CLI logs carry no connector attribution; --connector not applied here)");
|
|
117
|
+
}
|
|
118
|
+
lines.push("");
|
|
119
|
+
lines.push(formatHostLeaderboard(host));
|
|
120
|
+
lines.push("");
|
|
121
|
+
lines.push(
|
|
122
|
+
"\u{1F6F0}\uFE0F Host-native turns (live, exact) (origin: host-native-live \u2014 opt-in AfterModel usage hook)"
|
|
123
|
+
);
|
|
124
|
+
lines.push("");
|
|
125
|
+
lines.push(formatHostNativeTurns(turns));
|
|
126
|
+
lines.push("");
|
|
127
|
+
lines.push(
|
|
128
|
+
"note: the THREE leaderboards measure DIFFERENT things (per-MCP server bytes vs whole-conversation usage from logs vs live host-native turns) and are never summed together (their totals are NEVER added across origins)."
|
|
129
|
+
);
|
|
130
|
+
print(lines.join("\n"));
|
|
131
|
+
return 0;
|
|
132
|
+
}
|
|
133
|
+
export {
|
|
134
|
+
parseSince,
|
|
135
|
+
run
|
|
136
|
+
};
|
|
137
|
+
//# sourceMappingURL=leaderboard-K6ON3SWW.js.map
|