@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,715 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
rewriteEnvRefs
|
|
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/vscode-copilot/index.ts
|
|
18
|
+
import { existsSync } from "fs";
|
|
19
|
+
import { homedir } from "os";
|
|
20
|
+
import { join } from "path";
|
|
21
|
+
var HOST = "vscode-copilot";
|
|
22
|
+
var MCP_ROOT_KEY = "servers";
|
|
23
|
+
var VSCODE_HOOKS_VERSION = 1;
|
|
24
|
+
var EVENT_MAP = {
|
|
25
|
+
PreToolUse: "PreToolUse",
|
|
26
|
+
PostToolUse: "PostToolUse",
|
|
27
|
+
PreCompact: "PreCompact",
|
|
28
|
+
SessionStart: "SessionStart"
|
|
29
|
+
};
|
|
30
|
+
var VSCodeCopilotAdapter = class extends BaseAdapter {
|
|
31
|
+
id = HOST;
|
|
32
|
+
name = "VS Code Copilot";
|
|
33
|
+
paradigm = "json-stdio";
|
|
34
|
+
capabilities = {
|
|
35
|
+
// VS Code Copilot's Preview hooks runtime delivers Pre/PostToolUse,
|
|
36
|
+
// PreCompact, and SessionStart (the four events its schema documents).
|
|
37
|
+
preToolUse: true,
|
|
38
|
+
postToolUse: true,
|
|
39
|
+
preCompact: true,
|
|
40
|
+
sessionStart: true,
|
|
41
|
+
sessionEnd: false,
|
|
42
|
+
userPromptSubmit: false,
|
|
43
|
+
stop: false,
|
|
44
|
+
notification: false,
|
|
45
|
+
// PreToolUse can rewrite tool input (updatedInput) but a PostToolUse hook
|
|
46
|
+
// cannot rewrite already-emitted tool output — same as Claude/Cursor.
|
|
47
|
+
canModifyArgs: true,
|
|
48
|
+
canModifyOutput: false,
|
|
49
|
+
canInjectSessionContext: true,
|
|
50
|
+
transports: ["stdio", "http"],
|
|
51
|
+
// Content surfaces: VS Code Copilot authors prompt files, Agent Skills, and
|
|
52
|
+
// chat-mode agent files under the workspace .github/ tree (see content-file
|
|
53
|
+
// path helpers below). All three are supported.
|
|
54
|
+
supportsCommands: true,
|
|
55
|
+
supportsSkills: true,
|
|
56
|
+
supportsSubagents: true
|
|
57
|
+
};
|
|
58
|
+
// ── Detection ────────────────────────────────────────────────────────────
|
|
59
|
+
detectInstalled(projectDir) {
|
|
60
|
+
const userDir = join(homedir(), ".vscode");
|
|
61
|
+
const userMcp = join(userDir, "mcp.json");
|
|
62
|
+
const userInsidersDir = join(homedir(), ".vscode-insiders");
|
|
63
|
+
const projectVscode = join(projectDir, ".vscode");
|
|
64
|
+
const projectMcp = join(projectVscode, "mcp.json");
|
|
65
|
+
const projInstalled = existsSync(projectMcp) || existsSync(projectVscode);
|
|
66
|
+
const userInstalled = existsSync(userMcp) || existsSync(userDir) || existsSync(userInsidersDir);
|
|
67
|
+
const installed = projInstalled || userInstalled;
|
|
68
|
+
const scope = projInstalled && !userInstalled ? "project" : "user";
|
|
69
|
+
const configPath = scope === "project" ? projectMcp : userMcp;
|
|
70
|
+
return {
|
|
71
|
+
id: this.id,
|
|
72
|
+
name: this.name,
|
|
73
|
+
installed,
|
|
74
|
+
paradigm: this.paradigm,
|
|
75
|
+
capabilities: this.capabilities,
|
|
76
|
+
configPath,
|
|
77
|
+
scope,
|
|
78
|
+
reason: installed ? scope === "project" ? `found project VS Code config at ${projectVscode}` : `found VS Code config under ${userDir}` : `no VS Code config at ${userDir}`,
|
|
79
|
+
confidence: installed ? "high" : "low"
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
// ── Native paths ─────────────────────────────────────────────────────────
|
|
83
|
+
/**
|
|
84
|
+
* Config dir choice (documented per task brief): project (workspace) scope →
|
|
85
|
+
* <projectDir>/.vscode; user-profile scope → ~/.vscode. The real VS Code user
|
|
86
|
+
* profile dir is OS-specific and not reliably discoverable without launching
|
|
87
|
+
* VS Code, so ~/.vscode is the reasonable, cross-OS, no-launch choice — it is
|
|
88
|
+
* also where "MCP: Open User Configuration" writes on a default profile.
|
|
89
|
+
*/
|
|
90
|
+
getConfigDir(ctx) {
|
|
91
|
+
return ctx.scope === "project" ? join(ctx.projectDir, ".vscode") : join(homedir(), ".vscode");
|
|
92
|
+
}
|
|
93
|
+
/** MCP server registration lives in <configDir>/mcp.json under root "servers". */
|
|
94
|
+
getServerConfigPath(ctx) {
|
|
95
|
+
return join(this.getConfigDir(ctx), "mcp.json");
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Hook registration lives in the workspace-discovered .github/hooks tree,
|
|
99
|
+
* which VS Code Copilot scans for *.json hook files. We write one file per
|
|
100
|
+
* connector so installs/uninstalls never clobber another connector's hooks.
|
|
101
|
+
* Anchored on projectDir for both scopes — .github/hooks is a workspace
|
|
102
|
+
* concept (there is no user-profile equivalent in the Copilot hooks schema).
|
|
103
|
+
*/
|
|
104
|
+
getHookConfigPath(ctx) {
|
|
105
|
+
return join(ctx.projectDir, ".github", "hooks", `${ctx.connector.id}.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 vscode-copilot" : "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 VS Code's native `servers` 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 = { type: "stdio", command: this.rewrite(command) };
|
|
152
|
+
if (args.length > 0) entry2.args = args.map((a) => this.rewrite(a));
|
|
153
|
+
const env = this.renderEnv(server.env);
|
|
154
|
+
if (env) entry2.env = env;
|
|
155
|
+
if (server.cwd) entry2.cwd = this.rewrite(server.cwd);
|
|
156
|
+
return entry2;
|
|
157
|
+
}
|
|
158
|
+
const entry = {
|
|
159
|
+
type: "http",
|
|
160
|
+
url: this.rewrite(server.url ?? "")
|
|
161
|
+
};
|
|
162
|
+
const headers = this.renderEnv(server.headers);
|
|
163
|
+
if (headers) entry.headers = headers;
|
|
164
|
+
return entry;
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Render env/header values. VS Code supports its own `${env:VAR}` native
|
|
168
|
+
* interpolation, so translate `${env:VAR}` refs to that native token rather
|
|
169
|
+
* than baking secrets into the file. Literals pass through unchanged.
|
|
170
|
+
*/
|
|
171
|
+
renderEnv(env) {
|
|
172
|
+
if (!env || Object.keys(env).length === 0) return void 0;
|
|
173
|
+
const out = {};
|
|
174
|
+
for (const [k, v] of Object.entries(env)) out[k] = this.rewrite(v);
|
|
175
|
+
return out;
|
|
176
|
+
}
|
|
177
|
+
/** Translate `${env:VAR(:-default)}` to VS Code's native `${env:VAR}` token. */
|
|
178
|
+
rewrite(value) {
|
|
179
|
+
return rewriteEnvRefs(value, vscodeEnvToken);
|
|
180
|
+
}
|
|
181
|
+
// ── Hook install / uninstall ─────────────────────────────────────────────
|
|
182
|
+
installHooks(ctx) {
|
|
183
|
+
const { connector } = ctx;
|
|
184
|
+
if (connector.platforms[HOST]?.hooks === false) {
|
|
185
|
+
return [
|
|
186
|
+
{ platform: this.id, action: "skip", detail: "hooks disabled for vscode-copilot" }
|
|
187
|
+
];
|
|
188
|
+
}
|
|
189
|
+
if (connector.hookEvents.length === 0) {
|
|
190
|
+
return [{ platform: this.id, action: "skip", detail: "connector declares no hooks" }];
|
|
191
|
+
}
|
|
192
|
+
const hooksPath = this.getHookConfigPath(ctx);
|
|
193
|
+
const file = this.readJson(hooksPath) ?? {};
|
|
194
|
+
const hooks = file.hooks ??= {};
|
|
195
|
+
const changes = [];
|
|
196
|
+
let mutated = false;
|
|
197
|
+
for (const event of connector.hookEvents) {
|
|
198
|
+
const vscodeEvent = EVENT_MAP[event];
|
|
199
|
+
if (!vscodeEvent) {
|
|
200
|
+
changes.push({
|
|
201
|
+
platform: this.id,
|
|
202
|
+
action: "warn",
|
|
203
|
+
path: hooksPath,
|
|
204
|
+
detail: `${event} has no VS Code Copilot hook equivalent \u2014 skipped`
|
|
205
|
+
});
|
|
206
|
+
continue;
|
|
207
|
+
}
|
|
208
|
+
const command = buildHomeBinHookCommand(ctx.homeBinPath, HOST, event, connector.id);
|
|
209
|
+
const entry = { type: "command", command };
|
|
210
|
+
const bucket = hooks[vscodeEvent] ??= [];
|
|
211
|
+
const existingIdx = bucket.findIndex((e) => this.isOurCommand(e.command, ctx));
|
|
212
|
+
if (existingIdx >= 0) {
|
|
213
|
+
if (JSON.stringify(bucket[existingIdx]) === JSON.stringify(entry)) {
|
|
214
|
+
changes.push({
|
|
215
|
+
platform: this.id,
|
|
216
|
+
action: "skip",
|
|
217
|
+
path: hooksPath,
|
|
218
|
+
detail: `hooks.${vscodeEvent} already registered`
|
|
219
|
+
});
|
|
220
|
+
continue;
|
|
221
|
+
}
|
|
222
|
+
bucket[existingIdx] = entry;
|
|
223
|
+
changes.push({
|
|
224
|
+
platform: this.id,
|
|
225
|
+
action: "update",
|
|
226
|
+
path: hooksPath,
|
|
227
|
+
detail: `hooks.${vscodeEvent}`
|
|
228
|
+
});
|
|
229
|
+
} else {
|
|
230
|
+
bucket.push(entry);
|
|
231
|
+
changes.push({
|
|
232
|
+
platform: this.id,
|
|
233
|
+
action: "create",
|
|
234
|
+
path: hooksPath,
|
|
235
|
+
detail: `hooks.${vscodeEvent}`
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
mutated = true;
|
|
239
|
+
}
|
|
240
|
+
if (mutated) {
|
|
241
|
+
file.version = VSCODE_HOOKS_VERSION;
|
|
242
|
+
this.writeJson(hooksPath, file, ctx.dryRun);
|
|
243
|
+
}
|
|
244
|
+
return changes;
|
|
245
|
+
}
|
|
246
|
+
uninstallHooks(ctx) {
|
|
247
|
+
const hooksPath = this.getHookConfigPath(ctx);
|
|
248
|
+
const file = this.readJson(hooksPath);
|
|
249
|
+
const hooks = file?.hooks;
|
|
250
|
+
if (!file || !hooks) {
|
|
251
|
+
return [
|
|
252
|
+
{
|
|
253
|
+
platform: this.id,
|
|
254
|
+
action: "skip",
|
|
255
|
+
path: hooksPath,
|
|
256
|
+
detail: "no hooks section present"
|
|
257
|
+
}
|
|
258
|
+
];
|
|
259
|
+
}
|
|
260
|
+
const changes = [];
|
|
261
|
+
let mutated = false;
|
|
262
|
+
for (const vscodeEvent of Object.keys(hooks)) {
|
|
263
|
+
const bucket = hooks[vscodeEvent];
|
|
264
|
+
if (!Array.isArray(bucket)) continue;
|
|
265
|
+
const before = bucket.length;
|
|
266
|
+
const next = bucket.filter((e) => !this.isOurCommand(e.command, ctx));
|
|
267
|
+
const removed = before - next.length;
|
|
268
|
+
if (removed > 0) {
|
|
269
|
+
if (next.length > 0) hooks[vscodeEvent] = next;
|
|
270
|
+
else delete hooks[vscodeEvent];
|
|
271
|
+
changes.push({
|
|
272
|
+
platform: this.id,
|
|
273
|
+
action: "remove",
|
|
274
|
+
path: hooksPath,
|
|
275
|
+
detail: `hooks.${vscodeEvent} (${removed})`
|
|
276
|
+
});
|
|
277
|
+
mutated = true;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
if (mutated) this.writeJson(hooksPath, file, ctx.dryRun);
|
|
281
|
+
if (changes.length === 0) {
|
|
282
|
+
changes.push({
|
|
283
|
+
platform: this.id,
|
|
284
|
+
action: "skip",
|
|
285
|
+
path: hooksPath,
|
|
286
|
+
detail: "no matching hook entries"
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
return changes;
|
|
290
|
+
}
|
|
291
|
+
/** True when a hook command references our home binary AND this connector id
|
|
292
|
+
* (anchored so a shared-prefix id can't collide — see isHomeBinHookCommand). */
|
|
293
|
+
isOurCommand(command, ctx) {
|
|
294
|
+
return isHomeBinHookCommand(command, ctx.homeBinPath, ctx.connector.id);
|
|
295
|
+
}
|
|
296
|
+
// ── Content surfaces: commands / skills / subagents ──────────────────────
|
|
297
|
+
// CONTENT-ONLY: pure native-file writers under the workspace .github/ tree
|
|
298
|
+
// ({prompts,skills,agents}). No runtime dispatch, no home-bin pointer, no
|
|
299
|
+
// telemetry wrap. Each method is idempotent (byte-identical → skip) via
|
|
300
|
+
// BaseAdapter.writeContentFile and reversible via removeContentFile. Honors
|
|
301
|
+
// platforms["vscode-copilot"] per-surface false to skip.
|
|
302
|
+
//
|
|
303
|
+
// SHARED .github TREE: vscode-copilot, copilot-cli, and jetbrains-copilot all
|
|
304
|
+
// write under the SAME project <projectDir>/.github tree. The rendered content
|
|
305
|
+
// is identical and idempotent across those connectors, and uninstall here only
|
|
306
|
+
// removes the files THIS connector declared — never another writer's files.
|
|
307
|
+
//
|
|
308
|
+
// SCOPE NOTE: .github is a workspace concept; the Copilot prompt/skill/agent
|
|
309
|
+
// discovery is workspace-rooted and there is no documented per-user .github
|
|
310
|
+
// authoring location. VS Code's reliable per-user authoring root is the user
|
|
311
|
+
// profile prompts dir under the OS app-data path, which is not discoverable
|
|
312
|
+
// without launching VS Code. So for user scope we anchor on
|
|
313
|
+
// <homedir>/.config/github-copilot (the documented cross-OS Copilot user dir;
|
|
314
|
+
// see contentRootDir) rather than fabricating a profile path. Project scope is
|
|
315
|
+
// the primary, fully-supported path.
|
|
316
|
+
/**
|
|
317
|
+
* Root of the content tree. Project (workspace) scope → <projectDir>/.github,
|
|
318
|
+
* which VS Code Copilot scans for prompt/skill/agent files (and which
|
|
319
|
+
* copilot-cli + jetbrains-copilot share). User scope has no documented
|
|
320
|
+
* workspace-independent .github equivalent, so we anchor on the documented
|
|
321
|
+
* cross-OS Copilot user dir ~/.config/github-copilot to keep user-scope writes
|
|
322
|
+
* deterministic and removable.
|
|
323
|
+
*/
|
|
324
|
+
contentRootDir(ctx) {
|
|
325
|
+
return ctx.scope === "project" ? join(ctx.projectDir, ".github") : join(homedir(), ".config", "github-copilot");
|
|
326
|
+
}
|
|
327
|
+
promptsDir(ctx) {
|
|
328
|
+
return join(this.contentRootDir(ctx), "prompts");
|
|
329
|
+
}
|
|
330
|
+
skillsDir(ctx) {
|
|
331
|
+
return join(this.contentRootDir(ctx), "skills");
|
|
332
|
+
}
|
|
333
|
+
agentsDir(ctx) {
|
|
334
|
+
return join(this.contentRootDir(ctx), "agents");
|
|
335
|
+
}
|
|
336
|
+
/** Native command file path: <ghDir>/prompts/<name>.prompt.md. */
|
|
337
|
+
commandPath(ctx, name) {
|
|
338
|
+
return join(this.promptsDir(ctx), `${name}.prompt.md`);
|
|
339
|
+
}
|
|
340
|
+
/** Native skill dir: <ghDir>/skills/<name>. */
|
|
341
|
+
skillDir(ctx, name) {
|
|
342
|
+
return join(this.skillsDir(ctx), name);
|
|
343
|
+
}
|
|
344
|
+
/** Native subagent file path: <ghDir>/agents/<name>.agent.md. */
|
|
345
|
+
subagentPath(ctx, name) {
|
|
346
|
+
return join(this.agentsDir(ctx), `${name}.agent.md`);
|
|
347
|
+
}
|
|
348
|
+
// ── Commands ──────────────────────────────────────────────────────────────
|
|
349
|
+
installCommands(ctx) {
|
|
350
|
+
const { connector } = ctx;
|
|
351
|
+
if (connector.platforms[HOST]?.commands === false) {
|
|
352
|
+
return [{ platform: this.id, action: "skip", detail: "commands disabled for vscode-copilot" }];
|
|
353
|
+
}
|
|
354
|
+
if (connector.commands.length === 0) {
|
|
355
|
+
return [{ platform: this.id, action: "skip", detail: "connector declares no commands" }];
|
|
356
|
+
}
|
|
357
|
+
return connector.commands.map(
|
|
358
|
+
(cmd) => this.writeContentFile(
|
|
359
|
+
this.commandPath(ctx, cmd.name),
|
|
360
|
+
this.renderCommand(cmd),
|
|
361
|
+
ctx.dryRun
|
|
362
|
+
)
|
|
363
|
+
);
|
|
364
|
+
}
|
|
365
|
+
uninstallCommands(ctx) {
|
|
366
|
+
const { connector } = ctx;
|
|
367
|
+
if (connector.commands.length === 0) {
|
|
368
|
+
return [{ platform: this.id, action: "skip", detail: "connector declares no commands" }];
|
|
369
|
+
}
|
|
370
|
+
return connector.commands.map(
|
|
371
|
+
(cmd) => this.removeContentFile(this.commandPath(ctx, cmd.name), ctx.dryRun)
|
|
372
|
+
);
|
|
373
|
+
}
|
|
374
|
+
/** Render a VS Code Copilot prompt file: md+frontmatter(description, tools, model, argument-hint). */
|
|
375
|
+
renderCommand(cmd) {
|
|
376
|
+
const frontmatter = {};
|
|
377
|
+
if (cmd.description !== void 0) frontmatter.description = cmd.description;
|
|
378
|
+
const allow = cmd.tools?.allow;
|
|
379
|
+
if (allow && allow.length > 0) frontmatter.tools = [...allow];
|
|
380
|
+
if (cmd.model !== void 0) frontmatter.model = cmd.model;
|
|
381
|
+
if (cmd.argumentHint !== void 0) frontmatter["argument-hint"] = cmd.argumentHint;
|
|
382
|
+
if (cmd.extra) Object.assign(frontmatter, cmd.extra);
|
|
383
|
+
return this.renderFrontmatterMd(frontmatter, cmd.prompt);
|
|
384
|
+
}
|
|
385
|
+
// ── Skills ────────────────────────────────────────────────────────────────
|
|
386
|
+
installSkills(ctx) {
|
|
387
|
+
const { connector } = ctx;
|
|
388
|
+
if (connector.platforms[HOST]?.skills === false) {
|
|
389
|
+
return [{ platform: this.id, action: "skip", detail: "skills disabled for vscode-copilot" }];
|
|
390
|
+
}
|
|
391
|
+
if (connector.skills.length === 0) {
|
|
392
|
+
return [{ platform: this.id, action: "skip", detail: "connector declares no skills" }];
|
|
393
|
+
}
|
|
394
|
+
const changes = [];
|
|
395
|
+
for (const skill of connector.skills) {
|
|
396
|
+
const dir = this.skillDir(ctx, skill.name);
|
|
397
|
+
changes.push(
|
|
398
|
+
this.writeContentFile(join(dir, "SKILL.md"), this.renderSkill(skill), ctx.dryRun)
|
|
399
|
+
);
|
|
400
|
+
for (const [rel, contents] of Object.entries(skill.resources ?? {})) {
|
|
401
|
+
const target = this.resolveWithin(dir, rel);
|
|
402
|
+
if (target === null) {
|
|
403
|
+
changes.push({
|
|
404
|
+
platform: this.id,
|
|
405
|
+
action: "warn",
|
|
406
|
+
detail: `skill resource "${rel}" escapes the skill dir; skipped`
|
|
407
|
+
});
|
|
408
|
+
continue;
|
|
409
|
+
}
|
|
410
|
+
changes.push(this.writeContentFile(target, contents, ctx.dryRun));
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
return changes;
|
|
414
|
+
}
|
|
415
|
+
uninstallSkills(ctx) {
|
|
416
|
+
const { connector } = ctx;
|
|
417
|
+
if (connector.skills.length === 0) {
|
|
418
|
+
return [{ platform: this.id, action: "skip", detail: "connector declares no skills" }];
|
|
419
|
+
}
|
|
420
|
+
const changes = [];
|
|
421
|
+
for (const skill of connector.skills) {
|
|
422
|
+
const dir = this.skillDir(ctx, skill.name);
|
|
423
|
+
changes.push(this.removeContentFile(join(dir, "SKILL.md"), ctx.dryRun));
|
|
424
|
+
for (const rel of Object.keys(skill.resources ?? {})) {
|
|
425
|
+
const target = this.resolveWithin(dir, rel);
|
|
426
|
+
if (target === null) continue;
|
|
427
|
+
changes.push(this.removeContentFile(target, ctx.dryRun));
|
|
428
|
+
}
|
|
429
|
+
changes.push(this.removeDirIfEmpty(dir, ctx.dryRun));
|
|
430
|
+
}
|
|
431
|
+
return changes;
|
|
432
|
+
}
|
|
433
|
+
/**
|
|
434
|
+
* Render a skill's SKILL.md — the uniform Agent Skills format: frontmatter
|
|
435
|
+
* (name, description + optional model, allowed-tools, disable-model-invocation)
|
|
436
|
+
* + body. Byte-identical to the other .github-sharing connectors so a shared
|
|
437
|
+
* skill folder never thrashes.
|
|
438
|
+
*/
|
|
439
|
+
renderSkill(skill) {
|
|
440
|
+
const frontmatter = {
|
|
441
|
+
name: skill.name,
|
|
442
|
+
description: skill.description
|
|
443
|
+
};
|
|
444
|
+
if (skill.model !== void 0) frontmatter.model = skill.model;
|
|
445
|
+
const allow = skill.tools?.allow;
|
|
446
|
+
if (allow && allow.length > 0) frontmatter["allowed-tools"] = allow.join(", ");
|
|
447
|
+
if (skill.disableModelInvocation !== void 0) {
|
|
448
|
+
frontmatter["disable-model-invocation"] = skill.disableModelInvocation;
|
|
449
|
+
}
|
|
450
|
+
if (skill.extra) Object.assign(frontmatter, skill.extra);
|
|
451
|
+
return this.renderFrontmatterMd(frontmatter, skill.body);
|
|
452
|
+
}
|
|
453
|
+
// ── Subagents ───────────────────────────────────────────────────────────────
|
|
454
|
+
installSubagents(ctx) {
|
|
455
|
+
const { connector } = ctx;
|
|
456
|
+
if (connector.platforms[HOST]?.subagents === false) {
|
|
457
|
+
return [{ platform: this.id, action: "skip", detail: "subagents disabled for vscode-copilot" }];
|
|
458
|
+
}
|
|
459
|
+
if (connector.subagents.length === 0) {
|
|
460
|
+
return [{ platform: this.id, action: "skip", detail: "connector declares no subagents" }];
|
|
461
|
+
}
|
|
462
|
+
return connector.subagents.map(
|
|
463
|
+
(agent) => this.writeContentFile(
|
|
464
|
+
this.subagentPath(ctx, agent.name),
|
|
465
|
+
this.renderSubagent(agent),
|
|
466
|
+
ctx.dryRun
|
|
467
|
+
)
|
|
468
|
+
);
|
|
469
|
+
}
|
|
470
|
+
uninstallSubagents(ctx) {
|
|
471
|
+
const { connector } = ctx;
|
|
472
|
+
if (connector.subagents.length === 0) {
|
|
473
|
+
return [{ platform: this.id, action: "skip", detail: "connector declares no subagents" }];
|
|
474
|
+
}
|
|
475
|
+
return connector.subagents.map(
|
|
476
|
+
(agent) => this.removeContentFile(this.subagentPath(ctx, agent.name), ctx.dryRun)
|
|
477
|
+
);
|
|
478
|
+
}
|
|
479
|
+
/** Render a subagent agent file: md+frontmatter(name, description, tools, model) + prompt body. */
|
|
480
|
+
renderSubagent(agent) {
|
|
481
|
+
const frontmatter = {
|
|
482
|
+
name: agent.name,
|
|
483
|
+
description: agent.description
|
|
484
|
+
};
|
|
485
|
+
const allow = agent.tools?.allow;
|
|
486
|
+
if (allow && allow.length > 0) frontmatter.tools = allow.join(", ");
|
|
487
|
+
if (agent.model !== void 0) frontmatter.model = agent.model;
|
|
488
|
+
if (agent.extra) Object.assign(frontmatter, agent.extra);
|
|
489
|
+
return this.renderFrontmatterMd(frontmatter, agent.prompt);
|
|
490
|
+
}
|
|
491
|
+
// ── Diagnostics ──────────────────────────────────────────────────────────
|
|
492
|
+
getHealthChecks(ctx) {
|
|
493
|
+
const mcpPath = this.getServerConfigPath(ctx);
|
|
494
|
+
const hooksPath = this.getHookConfigPath(ctx);
|
|
495
|
+
const connectorId = ctx.connector.id;
|
|
496
|
+
const homeBin = ctx.homeBinPath;
|
|
497
|
+
const hookEvents = ctx.connector.hookEvents;
|
|
498
|
+
const checks = [
|
|
499
|
+
{
|
|
500
|
+
name: `${this.name}: mcp.json present`,
|
|
501
|
+
check: () => existsSync(mcpPath) ? { status: "OK", detail: mcpPath } : { status: "FAIL", detail: `not found: ${mcpPath}` }
|
|
502
|
+
},
|
|
503
|
+
{
|
|
504
|
+
name: `${this.name}: hook command registered`,
|
|
505
|
+
check: () => {
|
|
506
|
+
if (hookEvents.length === 0) {
|
|
507
|
+
return { status: "OK", detail: "no hooks declared" };
|
|
508
|
+
}
|
|
509
|
+
const file = this.readJson(hooksPath);
|
|
510
|
+
if (!file) return { status: "FAIL", detail: `not found: ${hooksPath}` };
|
|
511
|
+
if (file.version !== VSCODE_HOOKS_VERSION) {
|
|
512
|
+
return {
|
|
513
|
+
status: "FAIL",
|
|
514
|
+
detail: `${hooksPath} missing required "version": ${VSCODE_HOOKS_VERSION} \u2014 Copilot rejects it`
|
|
515
|
+
};
|
|
516
|
+
}
|
|
517
|
+
const registered = Object.values(file.hooks ?? {}).some(
|
|
518
|
+
(entries) => (entries ?? []).some(
|
|
519
|
+
(e) => isHomeBinHookCommand(e.command, homeBin, connectorId)
|
|
520
|
+
)
|
|
521
|
+
);
|
|
522
|
+
return registered ? { status: "OK", detail: "hook command present" } : { status: "FAIL", detail: `no hook for ${connectorId} in ${hooksPath}` };
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
];
|
|
526
|
+
for (const cmd of ctx.connector.commands) {
|
|
527
|
+
const p = this.commandPath(ctx, cmd.name);
|
|
528
|
+
checks.push({
|
|
529
|
+
name: `${this.name}: command ${cmd.name} present`,
|
|
530
|
+
check: () => existsSync(p) ? { status: "OK", detail: p } : { status: "FAIL", detail: `not found: ${p}` }
|
|
531
|
+
});
|
|
532
|
+
}
|
|
533
|
+
for (const skill of ctx.connector.skills) {
|
|
534
|
+
const p = join(this.skillDir(ctx, skill.name), "SKILL.md");
|
|
535
|
+
checks.push({
|
|
536
|
+
name: `${this.name}: skill ${skill.name} present`,
|
|
537
|
+
check: () => existsSync(p) ? { status: "OK", detail: p } : { status: "FAIL", detail: `not found: ${p}` }
|
|
538
|
+
});
|
|
539
|
+
}
|
|
540
|
+
for (const agent of ctx.connector.subagents) {
|
|
541
|
+
const p = this.subagentPath(ctx, agent.name);
|
|
542
|
+
checks.push({
|
|
543
|
+
name: `${this.name}: subagent ${agent.name} present`,
|
|
544
|
+
check: () => existsSync(p) ? { status: "OK", detail: p } : { status: "FAIL", detail: `not found: ${p}` }
|
|
545
|
+
});
|
|
546
|
+
}
|
|
547
|
+
return checks;
|
|
548
|
+
}
|
|
549
|
+
// ── Runtime: parse VS Code Copilot stdin JSON → normalized event ──────────
|
|
550
|
+
parseEvent(event, raw) {
|
|
551
|
+
const input = raw ?? {};
|
|
552
|
+
const connectorId = typeof input.connector === "string" ? input.connector : "";
|
|
553
|
+
const sessionId = extractSessionId(input);
|
|
554
|
+
const projectDir = this.getProjectDir(input);
|
|
555
|
+
const base = {
|
|
556
|
+
hostPlatform: HOST,
|
|
557
|
+
connectorId,
|
|
558
|
+
sessionId,
|
|
559
|
+
raw,
|
|
560
|
+
...projectDir !== void 0 ? { projectDir } : {}
|
|
561
|
+
};
|
|
562
|
+
switch (event) {
|
|
563
|
+
case "PreToolUse": {
|
|
564
|
+
const ev = {
|
|
565
|
+
...base,
|
|
566
|
+
toolName: input.tool_name ?? "",
|
|
567
|
+
toolInput: input.tool_input ?? {}
|
|
568
|
+
};
|
|
569
|
+
return ev;
|
|
570
|
+
}
|
|
571
|
+
case "PostToolUse": {
|
|
572
|
+
const toolOutput = toolResponseToString(input.tool_response) ?? input.tool_output ?? input.error_message;
|
|
573
|
+
const ev = {
|
|
574
|
+
...base,
|
|
575
|
+
toolName: input.tool_name ?? "",
|
|
576
|
+
toolInput: input.tool_input ?? {},
|
|
577
|
+
...toolOutput !== void 0 ? { toolOutput } : {},
|
|
578
|
+
...input.error_message ? { isError: true } : {}
|
|
579
|
+
};
|
|
580
|
+
return ev;
|
|
581
|
+
}
|
|
582
|
+
case "PreCompact": {
|
|
583
|
+
const ev = {
|
|
584
|
+
...base,
|
|
585
|
+
...input.trigger === "auto" || input.trigger === "manual" ? { trigger: input.trigger } : {}
|
|
586
|
+
};
|
|
587
|
+
return ev;
|
|
588
|
+
}
|
|
589
|
+
case "SessionStart": {
|
|
590
|
+
const ev = {
|
|
591
|
+
...base,
|
|
592
|
+
source: normalizeSessionSource(input.source ?? input.trigger)
|
|
593
|
+
};
|
|
594
|
+
return ev;
|
|
595
|
+
}
|
|
596
|
+
case "SessionEnd": {
|
|
597
|
+
const ev = {
|
|
598
|
+
...base,
|
|
599
|
+
...typeof input.reason === "string" ? { reason: input.reason } : {}
|
|
600
|
+
};
|
|
601
|
+
return ev;
|
|
602
|
+
}
|
|
603
|
+
case "UserPromptSubmit": {
|
|
604
|
+
const ev = {
|
|
605
|
+
...base,
|
|
606
|
+
prompt: typeof input.prompt === "string" ? input.prompt : ""
|
|
607
|
+
};
|
|
608
|
+
return ev;
|
|
609
|
+
}
|
|
610
|
+
case "Stop": {
|
|
611
|
+
const ev = {
|
|
612
|
+
...base,
|
|
613
|
+
...typeof input.stop_hook_active === "boolean" ? { stopHookActive: input.stop_hook_active } : {}
|
|
614
|
+
};
|
|
615
|
+
return ev;
|
|
616
|
+
}
|
|
617
|
+
case "Notification": {
|
|
618
|
+
const ev = {
|
|
619
|
+
...base,
|
|
620
|
+
message: typeof input.message === "string" ? input.message : ""
|
|
621
|
+
};
|
|
622
|
+
return ev;
|
|
623
|
+
}
|
|
624
|
+
default: {
|
|
625
|
+
const _never = event;
|
|
626
|
+
throw new Error(`unsupported vscode-copilot hook event: ${String(_never)}`);
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
/** Resolve the project dir from the wire payload, preferring the explicit cwd. */
|
|
631
|
+
getProjectDir(input) {
|
|
632
|
+
return input.cwd ?? input.workspace_roots?.[0] ?? void 0;
|
|
633
|
+
}
|
|
634
|
+
// ── Runtime: normalized response → VS Code Copilot native hook reply ──────
|
|
635
|
+
formatReply(event, response) {
|
|
636
|
+
const hookEventName = event;
|
|
637
|
+
const decision = response.decision ?? "allow";
|
|
638
|
+
if (decision === "deny") {
|
|
639
|
+
return this.stdout({
|
|
640
|
+
hookSpecificOutput: {
|
|
641
|
+
hookEventName,
|
|
642
|
+
permissionDecision: "deny",
|
|
643
|
+
permissionDecisionReason: response.reason ?? "Blocked by hook"
|
|
644
|
+
}
|
|
645
|
+
});
|
|
646
|
+
}
|
|
647
|
+
if (decision === "ask") {
|
|
648
|
+
return this.stdout({
|
|
649
|
+
hookSpecificOutput: {
|
|
650
|
+
hookEventName,
|
|
651
|
+
permissionDecision: "ask",
|
|
652
|
+
permissionDecisionReason: response.reason ?? "Confirmation required by hook"
|
|
653
|
+
}
|
|
654
|
+
});
|
|
655
|
+
}
|
|
656
|
+
if (decision === "modify") {
|
|
657
|
+
if (event === "PreToolUse" && response.updatedInput) {
|
|
658
|
+
return this.stdout({
|
|
659
|
+
hookSpecificOutput: { hookEventName, updatedInput: response.updatedInput }
|
|
660
|
+
});
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
if (decision === "context" && response.additionalContext) {
|
|
664
|
+
return this.stdout({
|
|
665
|
+
hookSpecificOutput: { hookEventName, additionalContext: response.additionalContext }
|
|
666
|
+
});
|
|
667
|
+
}
|
|
668
|
+
return { exitCode: 0 };
|
|
669
|
+
}
|
|
670
|
+
stdout(payload) {
|
|
671
|
+
return { exitCode: 0, stdout: JSON.stringify(payload) };
|
|
672
|
+
}
|
|
673
|
+
};
|
|
674
|
+
function vscodeEnvToken(name) {
|
|
675
|
+
return `\${env:${name}}`;
|
|
676
|
+
}
|
|
677
|
+
function extractSessionId(input) {
|
|
678
|
+
if (typeof input.transcript_path === "string") {
|
|
679
|
+
const m = input.transcript_path.match(/([a-f0-9-]{36})\.jsonl$/);
|
|
680
|
+
if (m && m[1]) return m[1];
|
|
681
|
+
}
|
|
682
|
+
if (typeof input.session_id === "string" && input.session_id !== "") {
|
|
683
|
+
return input.session_id;
|
|
684
|
+
}
|
|
685
|
+
return "";
|
|
686
|
+
}
|
|
687
|
+
function toolResponseToString(value) {
|
|
688
|
+
if (value == null) return void 0;
|
|
689
|
+
if (typeof value === "string") return value;
|
|
690
|
+
try {
|
|
691
|
+
return JSON.stringify(value);
|
|
692
|
+
} catch {
|
|
693
|
+
return String(value);
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
function normalizeSessionSource(source) {
|
|
697
|
+
switch (source) {
|
|
698
|
+
case "compact":
|
|
699
|
+
return "compact";
|
|
700
|
+
case "resume":
|
|
701
|
+
return "resume";
|
|
702
|
+
case "clear":
|
|
703
|
+
return "clear";
|
|
704
|
+
default:
|
|
705
|
+
return "startup";
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
var adapter = new VSCodeCopilotAdapter();
|
|
709
|
+
var vscode_copilot_default = adapter;
|
|
710
|
+
export {
|
|
711
|
+
VSCodeCopilotAdapter,
|
|
712
|
+
adapter,
|
|
713
|
+
vscode_copilot_default as default
|
|
714
|
+
};
|
|
715
|
+
//# sourceMappingURL=vscode-copilot-CK3NO54M.js.map
|