@varveai/adit-hooks 0.3.0 → 0.3.1
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/dist/adapters/codex.d.ts +16 -0
- package/dist/adapters/codex.d.ts.map +1 -0
- package/dist/adapters/codex.js +220 -0
- package/dist/adapters/codex.js.map +1 -0
- package/dist/adapters/cursor.d.ts +19 -0
- package/dist/adapters/cursor.d.ts.map +1 -0
- package/dist/adapters/cursor.js +330 -0
- package/dist/adapters/cursor.js.map +1 -0
- package/dist/adapters/gemini.d.ts +9 -0
- package/dist/adapters/gemini.d.ts.map +1 -0
- package/dist/adapters/gemini.js +216 -0
- package/dist/adapters/gemini.js.map +1 -0
- package/dist/adapters/index.d.ts +5 -2
- package/dist/adapters/index.d.ts.map +1 -1
- package/dist/adapters/index.js +5 -2
- package/dist/adapters/index.js.map +1 -1
- package/dist/adapters/registry.d.ts +11 -0
- package/dist/adapters/registry.d.ts.map +1 -1
- package/dist/adapters/registry.js +92 -11
- package/dist/adapters/registry.js.map +1 -1
- package/dist/adapters/stub.d.ts +0 -4
- package/dist/adapters/stub.d.ts.map +1 -1
- package/dist/adapters/stub.js +0 -4
- package/dist/adapters/stub.js.map +1 -1
- package/dist/handlers/unified.d.ts.map +1 -1
- package/dist/handlers/unified.js +70 -1
- package/dist/handlers/unified.js.map +1 -1
- package/dist/index.js +42 -2
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Google Gemini CLI platform adapter.
|
|
3
|
+
*
|
|
4
|
+
* Maps Gemini CLI's hook events to ADIT's internal model.
|
|
5
|
+
* Handles installation into .gemini/settings.json.
|
|
6
|
+
*/
|
|
7
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync } from "node:fs";
|
|
8
|
+
import { join } from "node:path";
|
|
9
|
+
const HOOK_MAPPINGS = [
|
|
10
|
+
{ platformEvent: "SessionStart", aditHandler: "session-start" },
|
|
11
|
+
{ platformEvent: "BeforeAgent", aditHandler: "prompt-submit" },
|
|
12
|
+
{ platformEvent: "AfterAgent", aditHandler: "stop" },
|
|
13
|
+
{ platformEvent: "SessionEnd", aditHandler: "session-end" },
|
|
14
|
+
{ platformEvent: "AfterTool", aditHandler: "notification" },
|
|
15
|
+
{ platformEvent: "Notification", aditHandler: "notification" },
|
|
16
|
+
];
|
|
17
|
+
/** Map Gemini CLI platform events to ADIT hook types (derived from HOOK_MAPPINGS) */
|
|
18
|
+
const PLATFORM_TO_ADIT = Object.fromEntries(HOOK_MAPPINGS.map((m) => [m.platformEvent, m.aditHandler]));
|
|
19
|
+
/** Check if a command string is an ADIT hook (matches both npx and resolved-path formats) */
|
|
20
|
+
function isAditHookCommand(command) {
|
|
21
|
+
return command.includes("adit-hook") || command.includes("hooks/dist/index.js");
|
|
22
|
+
}
|
|
23
|
+
export const geminiAdapter = {
|
|
24
|
+
platform: "gemini",
|
|
25
|
+
displayName: "Gemini CLI",
|
|
26
|
+
hookMappings: HOOK_MAPPINGS,
|
|
27
|
+
parseInput(raw, hookType) {
|
|
28
|
+
const aditHookType = PLATFORM_TO_ADIT[hookType] ?? hookType;
|
|
29
|
+
const cwd = raw.cwd ?? process.cwd();
|
|
30
|
+
return {
|
|
31
|
+
cwd,
|
|
32
|
+
hookType: aditHookType,
|
|
33
|
+
platformCli: "gemini",
|
|
34
|
+
platformSessionId: raw.session_id,
|
|
35
|
+
transcriptPath: raw.transcript_path,
|
|
36
|
+
// Prompt
|
|
37
|
+
prompt: raw.prompt,
|
|
38
|
+
// Tool use
|
|
39
|
+
toolName: raw.tool_name,
|
|
40
|
+
toolInput: raw.tool_input,
|
|
41
|
+
toolOutput: raw.tool_response,
|
|
42
|
+
// Stop
|
|
43
|
+
stopReason: raw.stop_reason,
|
|
44
|
+
lastAssistantMessage: raw.prompt_response,
|
|
45
|
+
stopHookActive: raw.stop_hook_active,
|
|
46
|
+
// Notification
|
|
47
|
+
notificationMessage: raw.message,
|
|
48
|
+
notificationTitle: raw.title,
|
|
49
|
+
notificationType: raw.notification_type,
|
|
50
|
+
// Session lifecycle
|
|
51
|
+
sessionSource: raw.source,
|
|
52
|
+
sessionEndReason: raw.reason,
|
|
53
|
+
// Common metadata
|
|
54
|
+
permissionMode: raw.permission_mode,
|
|
55
|
+
model: raw.model,
|
|
56
|
+
rawPlatformData: raw,
|
|
57
|
+
};
|
|
58
|
+
},
|
|
59
|
+
generateHookConfig(aditBinaryPath) {
|
|
60
|
+
const makeHookEntry = (command) => [
|
|
61
|
+
{ hooks: [{ type: "command", command: `CLAUDE_CODE= GEMINI=1 ${command}`, timeout: 5000 }] },
|
|
62
|
+
];
|
|
63
|
+
return {
|
|
64
|
+
configPath: ".gemini/settings.json",
|
|
65
|
+
content: {
|
|
66
|
+
hooks: {
|
|
67
|
+
SessionStart: makeHookEntry(`${aditBinaryPath} session-start`),
|
|
68
|
+
BeforeAgent: makeHookEntry(`${aditBinaryPath} prompt-submit`),
|
|
69
|
+
AfterAgent: makeHookEntry(`${aditBinaryPath} stop`),
|
|
70
|
+
SessionEnd: makeHookEntry(`${aditBinaryPath} session-end`),
|
|
71
|
+
AfterTool: makeHookEntry(`${aditBinaryPath} notification`),
|
|
72
|
+
Notification: makeHookEntry(`${aditBinaryPath} notification`),
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
};
|
|
76
|
+
},
|
|
77
|
+
async validateInstallation(projectRoot) {
|
|
78
|
+
const checks = [];
|
|
79
|
+
// Check .gemini directory exists
|
|
80
|
+
const geminiDir = join(projectRoot, ".gemini");
|
|
81
|
+
const geminiDirExists = existsSync(geminiDir);
|
|
82
|
+
checks.push({
|
|
83
|
+
name: ".gemini directory",
|
|
84
|
+
ok: geminiDirExists,
|
|
85
|
+
detail: geminiDirExists ? geminiDir : "Not found",
|
|
86
|
+
});
|
|
87
|
+
// Check settings file for hook configuration
|
|
88
|
+
const settingsPath = join(projectRoot, ".gemini", "settings.json");
|
|
89
|
+
let hooksFound = false;
|
|
90
|
+
let hooksDetail = "No hook configuration found";
|
|
91
|
+
const requiredHooks = HOOK_MAPPINGS.map((m) => m.platformEvent);
|
|
92
|
+
const missingHooks = [];
|
|
93
|
+
if (existsSync(settingsPath)) {
|
|
94
|
+
try {
|
|
95
|
+
const settings = JSON.parse(readFileSync(settingsPath, "utf-8"));
|
|
96
|
+
if (!settings.hooks) {
|
|
97
|
+
hooksDetail = "No hooks section in settings.json";
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
for (const hookName of requiredHooks) {
|
|
101
|
+
const entries = settings.hooks[hookName];
|
|
102
|
+
if (!Array.isArray(entries)) {
|
|
103
|
+
missingHooks.push(hookName);
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
const hasAdit = entries.some((entry) => {
|
|
107
|
+
if (typeof entry.command === "string" && isAditHookCommand(entry.command))
|
|
108
|
+
return true;
|
|
109
|
+
if (Array.isArray(entry.hooks)) {
|
|
110
|
+
return entry.hooks.some((h) => typeof h.command === "string" && isAditHookCommand(h.command));
|
|
111
|
+
}
|
|
112
|
+
return false;
|
|
113
|
+
});
|
|
114
|
+
if (!hasAdit)
|
|
115
|
+
missingHooks.push(hookName);
|
|
116
|
+
}
|
|
117
|
+
hooksFound = missingHooks.length === 0;
|
|
118
|
+
hooksDetail = hooksFound
|
|
119
|
+
? `All hooks registered in ${settingsPath}`
|
|
120
|
+
: `Missing hooks: ${missingHooks.join(", ")}`;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
catch {
|
|
124
|
+
hooksDetail = `Failed to parse ${settingsPath}`;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
checks.push({
|
|
128
|
+
name: "Hook configuration",
|
|
129
|
+
ok: hooksFound,
|
|
130
|
+
detail: hooksDetail,
|
|
131
|
+
});
|
|
132
|
+
return {
|
|
133
|
+
valid: checks.every((c) => c.ok),
|
|
134
|
+
checks,
|
|
135
|
+
};
|
|
136
|
+
},
|
|
137
|
+
async installHooks(projectRoot, aditBinaryPath) {
|
|
138
|
+
const geminiDir = join(projectRoot, ".gemini");
|
|
139
|
+
if (!existsSync(geminiDir)) {
|
|
140
|
+
mkdirSync(geminiDir, { recursive: true });
|
|
141
|
+
}
|
|
142
|
+
const settingsPath = join(geminiDir, "settings.json");
|
|
143
|
+
let settings = {};
|
|
144
|
+
if (existsSync(settingsPath)) {
|
|
145
|
+
try {
|
|
146
|
+
settings = JSON.parse(readFileSync(settingsPath, "utf-8"));
|
|
147
|
+
}
|
|
148
|
+
catch {
|
|
149
|
+
// Start fresh if settings are invalid
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
const hookConfig = this.generateHookConfig(aditBinaryPath);
|
|
153
|
+
const existingHooks = settings.hooks ?? {};
|
|
154
|
+
const newHooks = hookConfig.content.hooks;
|
|
155
|
+
// Merge hook entries per event key: preserve other tools' hooks,
|
|
156
|
+
// remove stale ADIT entries, then append new ADIT entries.
|
|
157
|
+
const mergedHooks = { ...existingHooks };
|
|
158
|
+
for (const [eventKey, aditEntries] of Object.entries(newHooks)) {
|
|
159
|
+
const existing = Array.isArray(mergedHooks[eventKey]) ? mergedHooks[eventKey] : [];
|
|
160
|
+
// Remove stale ADIT entries (same logic as uninstallHooks)
|
|
161
|
+
const nonAditEntries = existing.filter((raw) => {
|
|
162
|
+
const entry = raw;
|
|
163
|
+
if (typeof entry.command === "string" && isAditHookCommand(entry.command))
|
|
164
|
+
return false;
|
|
165
|
+
if (Array.isArray(entry.hooks)) {
|
|
166
|
+
return !entry.hooks.some((h) => typeof h.command === "string" && isAditHookCommand(h.command));
|
|
167
|
+
}
|
|
168
|
+
return true;
|
|
169
|
+
});
|
|
170
|
+
// Append new ADIT entries after other tools' hooks
|
|
171
|
+
mergedHooks[eventKey] = [...nonAditEntries, ...aditEntries];
|
|
172
|
+
}
|
|
173
|
+
settings.hooks = mergedHooks;
|
|
174
|
+
writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n");
|
|
175
|
+
},
|
|
176
|
+
getResumeCommand(_projectRoot) {
|
|
177
|
+
return "gemini";
|
|
178
|
+
},
|
|
179
|
+
async uninstallHooks(projectRoot) {
|
|
180
|
+
const settingsPath = join(projectRoot, ".gemini", "settings.json");
|
|
181
|
+
if (!existsSync(settingsPath))
|
|
182
|
+
return;
|
|
183
|
+
try {
|
|
184
|
+
const settings = JSON.parse(readFileSync(settingsPath, "utf-8"));
|
|
185
|
+
if (!settings.hooks)
|
|
186
|
+
return;
|
|
187
|
+
// Remove ADIT hook entries
|
|
188
|
+
for (const hookName of Object.keys(settings.hooks)) {
|
|
189
|
+
const entries = settings.hooks[hookName];
|
|
190
|
+
if (!Array.isArray(entries))
|
|
191
|
+
continue;
|
|
192
|
+
settings.hooks[hookName] = entries.filter((entry) => {
|
|
193
|
+
if (typeof entry.command === "string" && isAditHookCommand(entry.command))
|
|
194
|
+
return false;
|
|
195
|
+
if (Array.isArray(entry.hooks)) {
|
|
196
|
+
return !entry.hooks.some((h) => typeof h.command === "string" && isAditHookCommand(h.command));
|
|
197
|
+
}
|
|
198
|
+
return true;
|
|
199
|
+
});
|
|
200
|
+
// Clean up empty arrays
|
|
201
|
+
if (settings.hooks[hookName].length === 0) {
|
|
202
|
+
delete settings.hooks[hookName];
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
// Clean up empty hooks object
|
|
206
|
+
if (Object.keys(settings.hooks).length === 0) {
|
|
207
|
+
delete settings.hooks;
|
|
208
|
+
}
|
|
209
|
+
writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n");
|
|
210
|
+
}
|
|
211
|
+
catch {
|
|
212
|
+
// Ignore parse errors
|
|
213
|
+
}
|
|
214
|
+
},
|
|
215
|
+
};
|
|
216
|
+
//# sourceMappingURL=gemini.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gemini.js","sourceRoot":"","sources":["../../src/adapters/gemini.ts"],"names":[],"mappings":"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"}
|
package/dist/adapters/index.d.ts
CHANGED
|
@@ -2,8 +2,11 @@ export type { PlatformAdapter, HookMapping, NormalizedHookInput, PlatformHookCon
|
|
|
2
2
|
export { claudeCodeAdapter } from "./claude-code.js";
|
|
3
3
|
export { claudeVscodeAdapter } from "./claude-vscode.js";
|
|
4
4
|
export { opencodeAdapter } from "./opencode.js";
|
|
5
|
-
export { createStubAdapter,
|
|
6
|
-
export {
|
|
5
|
+
export { createStubAdapter, copilotAdapter, otherAdapter } from "./stub.js";
|
|
6
|
+
export { cursorAdapter } from "./cursor.js";
|
|
7
|
+
export { codexAdapter } from "./codex.js";
|
|
8
|
+
export { geminiAdapter } from "./gemini.js";
|
|
9
|
+
export { getAdapter, listAdapters, registerAdapter, detectPlatform, detectPlatformFromPayload, detectPlatforms } from "./registry.js";
|
|
7
10
|
/**
|
|
8
11
|
* Resolve the absolute path to the adit-hook binary for reliable invocation.
|
|
9
12
|
* Navigates from this module's location to the entry point (dist/index.js),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/adapters/index.ts"],"names":[],"mappings":"AAIA,YAAY,EACV,eAAe,EACf,WAAW,EACX,mBAAmB,EACnB,kBAAkB,EAClB,gBAAgB,EAChB,eAAe,EACf,YAAY,GACb,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/adapters/index.ts"],"names":[],"mappings":"AAIA,YAAY,EACV,eAAe,EACf,WAAW,EACX,mBAAmB,EACnB,kBAAkB,EAClB,gBAAgB,EAChB,eAAe,EACf,YAAY,GACb,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAC5E,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,yBAAyB,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEtI;;;;GAIG;AACH,wBAAgB,qBAAqB,IAAI,MAAM,CAc9C"}
|
package/dist/adapters/index.js
CHANGED
|
@@ -4,8 +4,11 @@ import { existsSync } from "node:fs";
|
|
|
4
4
|
export { claudeCodeAdapter } from "./claude-code.js";
|
|
5
5
|
export { claudeVscodeAdapter } from "./claude-vscode.js";
|
|
6
6
|
export { opencodeAdapter } from "./opencode.js";
|
|
7
|
-
export { createStubAdapter,
|
|
8
|
-
export {
|
|
7
|
+
export { createStubAdapter, copilotAdapter, otherAdapter } from "./stub.js";
|
|
8
|
+
export { cursorAdapter } from "./cursor.js";
|
|
9
|
+
export { codexAdapter } from "./codex.js";
|
|
10
|
+
export { geminiAdapter } from "./gemini.js";
|
|
11
|
+
export { getAdapter, listAdapters, registerAdapter, detectPlatform, detectPlatformFromPayload, detectPlatforms } from "./registry.js";
|
|
9
12
|
/**
|
|
10
13
|
* Resolve the absolute path to the adit-hook binary for reliable invocation.
|
|
11
14
|
* Navigates from this module's location to the entry point (dist/index.js),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/adapters/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAYrC,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/adapters/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAYrC,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAC5E,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,yBAAyB,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEtI;;;;GAIG;AACH,MAAM,UAAU,qBAAqB;IACnC,IAAI,CAAC;QACH,sEAAsE;QACtE,qEAAqE;QACrE,MAAM,OAAO,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QACxD,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC;QACnD,IAAI,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YAC3B,OAAO,SAAS,UAAU,GAAG,CAAC;QAChC,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,kBAAkB;IACpB,CAAC;IACD,kEAAkE;IAClE,OAAO,WAAW,CAAC;AACrB,CAAC"}
|
|
@@ -18,6 +18,17 @@ export declare function registerAdapter(adapter: PlatformAdapter): void;
|
|
|
18
18
|
* Falls back to "other" when no platform is detected.
|
|
19
19
|
*/
|
|
20
20
|
export declare function detectPlatform(): Platform;
|
|
21
|
+
/**
|
|
22
|
+
* Detect platform from the raw stdin JSON payload.
|
|
23
|
+
*
|
|
24
|
+
* Used as a fallback when env-var detection returns "other".
|
|
25
|
+
* Some platforms (notably Cursor) may not set the expected env vars
|
|
26
|
+
* when spawning hook child processes, but the payload always carries
|
|
27
|
+
* identifying fields like `cursor_version`.
|
|
28
|
+
*
|
|
29
|
+
* Returns `null` if the payload doesn't match any known platform.
|
|
30
|
+
*/
|
|
31
|
+
export declare function detectPlatformFromPayload(raw: Record<string, unknown>): Platform | null;
|
|
21
32
|
/**
|
|
22
33
|
* Detect which platforms are present in a project by checking for their
|
|
23
34
|
* config directories on disk. Falls back to env-based detection if no
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/adapters/registry.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/adapters/registry.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AA+BlD,qCAAqC;AACrC,wBAAgB,UAAU,CAAC,QAAQ,EAAE,QAAQ,GAAG,eAAe,CAQ9D;AAED,mCAAmC;AACnC,wBAAgB,YAAY,IAAI,eAAe,EAAE,CAEhD;AAED,iDAAiD;AACjD,wBAAgB,eAAe,CAAC,OAAO,EAAE,eAAe,GAAG,IAAI,CAE9D;AAED;;;GAGG;AACH,wBAAgB,cAAc,IAAI,QAAQ,CAkDzC;AA+BD;;;;;;;;;GASG;AACH,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,QAAQ,GAAG,IAAI,CAkBvF;AAED;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,QAAQ,EAAE,CA4C/D"}
|
|
@@ -9,8 +9,11 @@ import { existsSync } from "node:fs";
|
|
|
9
9
|
import { join } from "node:path";
|
|
10
10
|
import { claudeCodeAdapter } from "./claude-code.js";
|
|
11
11
|
import { claudeVscodeAdapter } from "./claude-vscode.js";
|
|
12
|
-
import {
|
|
12
|
+
import { copilotAdapter, otherAdapter, } from "./stub.js";
|
|
13
13
|
import { opencodeAdapter } from "./opencode.js";
|
|
14
|
+
import { cursorAdapter } from "./cursor.js";
|
|
15
|
+
import { codexAdapter } from "./codex.js";
|
|
16
|
+
import { geminiAdapter } from "./gemini.js";
|
|
14
17
|
/** Registered adapters keyed by platform */
|
|
15
18
|
const adapters = new Map();
|
|
16
19
|
// Register built-in adapters
|
|
@@ -19,10 +22,12 @@ adapters.set("claude-vscode", claudeVscodeAdapter);
|
|
|
19
22
|
// Register OpenCode adapter (fully implemented)
|
|
20
23
|
adapters.set("opencode", opencodeAdapter);
|
|
21
24
|
// Register stub adapters (detected but not yet fully implemented)
|
|
22
|
-
adapters.set("cursor", cursorAdapter);
|
|
23
25
|
adapters.set("copilot", copilotAdapter);
|
|
24
|
-
adapters.set("codex", codexAdapter);
|
|
25
26
|
adapters.set("other", otherAdapter);
|
|
27
|
+
// Register fully implemented adapters
|
|
28
|
+
adapters.set("cursor", cursorAdapter);
|
|
29
|
+
adapters.set("codex", codexAdapter);
|
|
30
|
+
adapters.set("gemini", geminiAdapter);
|
|
26
31
|
/** Get the adapter for a platform */
|
|
27
32
|
export function getAdapter(platform) {
|
|
28
33
|
const adapter = adapters.get(platform);
|
|
@@ -44,21 +49,36 @@ export function registerAdapter(adapter) {
|
|
|
44
49
|
* Falls back to "other" when no platform is detected.
|
|
45
50
|
*/
|
|
46
51
|
export function detectPlatform() {
|
|
52
|
+
// Hook-explicit platform env vars are checked BEFORE inherited ones.
|
|
53
|
+
// When running Gemini/Codex/Cursor inside another tool's terminal
|
|
54
|
+
// (e.g., Gemini inside Claude Code), the parent's env vars (CLAUDE_CODE)
|
|
55
|
+
// are inherited by the child. The hook command prefix explicitly sets the
|
|
56
|
+
// correct platform var (GEMINI=1, CODEX=1, CURSOR=1), so those must win.
|
|
57
|
+
// Cursor detection
|
|
58
|
+
if (process.env.CURSOR_SESSION_ID || process.env.CURSOR || process.env.CURSOR_PROJECT_DIR) {
|
|
59
|
+
return "cursor";
|
|
60
|
+
}
|
|
61
|
+
// Codex detection (OpenAI's AI coding agent)
|
|
62
|
+
if (process.env.CODEX || process.env.CODEX_SESSION) {
|
|
63
|
+
return "codex";
|
|
64
|
+
}
|
|
65
|
+
// Gemini CLI detection (Google's AI coding agent)
|
|
66
|
+
if (process.env.GEMINI || process.env.GEMINI_SESSION_ID || process.env.GEMINI_PROJECT_DIR) {
|
|
67
|
+
return "gemini";
|
|
68
|
+
}
|
|
47
69
|
// Claude Code (CLI or VS Code extension).
|
|
48
70
|
// ADIT's hook command prefix sets CLAUDE_CODE=1 for both platforms.
|
|
49
71
|
// The VS Code extension host additionally sets ELECTRON_RUN_AS_NODE and
|
|
50
72
|
// VSCODE_IPC_HOOK — these are NOT inherited by terminal child processes,
|
|
51
73
|
// so running CLI from VS Code's terminal won't trigger false detection.
|
|
74
|
+
// Checked AFTER other platforms because CLAUDE_CODE is often inherited
|
|
75
|
+
// from the parent shell when running other tools inside Claude Code.
|
|
52
76
|
if (process.env.CLAUDE_CODE || process.env.CLAUDE_PLUGIN_ROOT) {
|
|
53
77
|
if (process.env.ELECTRON_RUN_AS_NODE && process.env.VSCODE_IPC_HOOK) {
|
|
54
78
|
return "claude-vscode";
|
|
55
79
|
}
|
|
56
80
|
return "claude-code";
|
|
57
81
|
}
|
|
58
|
-
// Cursor detection
|
|
59
|
-
if (process.env.CURSOR_SESSION_ID || process.env.CURSOR) {
|
|
60
|
-
return "cursor";
|
|
61
|
-
}
|
|
62
82
|
// GitHub Copilot detection
|
|
63
83
|
if (process.env.GITHUB_COPILOT || process.env.COPILOT_SESSION) {
|
|
64
84
|
return "copilot";
|
|
@@ -67,15 +87,64 @@ export function detectPlatform() {
|
|
|
67
87
|
if (process.env.OPENCODE || process.env.OPENCODE_SESSION) {
|
|
68
88
|
return "opencode";
|
|
69
89
|
}
|
|
70
|
-
// Codex detection (OpenAI's AI coding agent)
|
|
71
|
-
if (process.env.CODEX || process.env.CODEX_SESSION) {
|
|
72
|
-
return "codex";
|
|
73
|
-
}
|
|
74
90
|
// No platform env vars detected — return "other" to stay platform-neutral.
|
|
75
91
|
// Callers that need a concrete adapter should check for "other" and handle
|
|
76
92
|
// it explicitly rather than silently assuming a specific platform.
|
|
77
93
|
return "other";
|
|
78
94
|
}
|
|
95
|
+
/**
|
|
96
|
+
* Cursor-native hook event names (lowercase).
|
|
97
|
+
* Used by payload-based detection to distinguish Cursor from other platforms.
|
|
98
|
+
*/
|
|
99
|
+
const CURSOR_HOOK_EVENTS = new Set([
|
|
100
|
+
"beforeSubmitPrompt",
|
|
101
|
+
"stop",
|
|
102
|
+
"sessionStart",
|
|
103
|
+
"sessionEnd",
|
|
104
|
+
"afterAgentResponse",
|
|
105
|
+
"beforeShellExecution",
|
|
106
|
+
"afterShellExecution",
|
|
107
|
+
"afterFileEdit",
|
|
108
|
+
]);
|
|
109
|
+
/**
|
|
110
|
+
* Gemini CLI hook event names (PascalCase).
|
|
111
|
+
* Used by payload-based detection to distinguish Gemini from other platforms.
|
|
112
|
+
* Excludes names that overlap with Codex ("SessionStart") or other tools.
|
|
113
|
+
*/
|
|
114
|
+
const GEMINI_HOOK_EVENTS = new Set([
|
|
115
|
+
"BeforeAgent",
|
|
116
|
+
"AfterAgent",
|
|
117
|
+
"BeforeModel",
|
|
118
|
+
"AfterModel",
|
|
119
|
+
"BeforeToolSelection",
|
|
120
|
+
"PreCompress",
|
|
121
|
+
]);
|
|
122
|
+
/**
|
|
123
|
+
* Detect platform from the raw stdin JSON payload.
|
|
124
|
+
*
|
|
125
|
+
* Used as a fallback when env-var detection returns "other".
|
|
126
|
+
* Some platforms (notably Cursor) may not set the expected env vars
|
|
127
|
+
* when spawning hook child processes, but the payload always carries
|
|
128
|
+
* identifying fields like `cursor_version`.
|
|
129
|
+
*
|
|
130
|
+
* Returns `null` if the payload doesn't match any known platform.
|
|
131
|
+
*/
|
|
132
|
+
export function detectPlatformFromPayload(raw) {
|
|
133
|
+
// Cursor: always includes cursor_version in every hook event payload
|
|
134
|
+
if (typeof raw.cursor_version === "string") {
|
|
135
|
+
return "cursor";
|
|
136
|
+
}
|
|
137
|
+
// Cursor (fallback): Cursor-native hook_event_name values that differ from
|
|
138
|
+
// Claude Code's CamelCase names (e.g. "beforeSubmitPrompt" vs "UserPromptSubmit")
|
|
139
|
+
if (typeof raw.hook_event_name === "string" && CURSOR_HOOK_EVENTS.has(raw.hook_event_name)) {
|
|
140
|
+
return "cursor";
|
|
141
|
+
}
|
|
142
|
+
// Gemini: unique PascalCase event names not used by other platforms
|
|
143
|
+
if (typeof raw.hook_event_name === "string" && GEMINI_HOOK_EVENTS.has(raw.hook_event_name)) {
|
|
144
|
+
return "gemini";
|
|
145
|
+
}
|
|
146
|
+
return null;
|
|
147
|
+
}
|
|
79
148
|
/**
|
|
80
149
|
* Detect which platforms are present in a project by checking for their
|
|
81
150
|
* config directories on disk. Falls back to env-based detection if no
|
|
@@ -98,6 +167,18 @@ export function detectPlatforms(projectRoot) {
|
|
|
98
167
|
existsSync(join(projectRoot, "opencode.jsonc"))) {
|
|
99
168
|
platforms.add("opencode");
|
|
100
169
|
}
|
|
170
|
+
// Check for Cursor config directory
|
|
171
|
+
if (existsSync(join(projectRoot, ".cursor"))) {
|
|
172
|
+
platforms.add("cursor");
|
|
173
|
+
}
|
|
174
|
+
// Check for Codex config directory
|
|
175
|
+
if (existsSync(join(projectRoot, ".codex"))) {
|
|
176
|
+
platforms.add("codex");
|
|
177
|
+
}
|
|
178
|
+
// Check for Gemini config directory
|
|
179
|
+
if (existsSync(join(projectRoot, ".gemini"))) {
|
|
180
|
+
platforms.add("gemini");
|
|
181
|
+
}
|
|
101
182
|
// If no platform directories found, fall back to env detection.
|
|
102
183
|
// This handles cases where adit is run from within an AI tool session
|
|
103
184
|
// (e.g. the AI agent running `adit plugin install`).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/adapters/registry.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAGjC,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EACL,
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/adapters/registry.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAGjC,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EACL,cAAc,EACd,YAAY,GACb,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,4CAA4C;AAC5C,MAAM,QAAQ,GAAG,IAAI,GAAG,EAA6B,CAAC;AAEtD,6BAA6B;AAC7B,QAAQ,CAAC,GAAG,CAAC,aAAa,EAAE,iBAAiB,CAAC,CAAC;AAC/C,QAAQ,CAAC,GAAG,CAAC,eAAe,EAAE,mBAAmB,CAAC,CAAC;AAEnD,gDAAgD;AAChD,QAAQ,CAAC,GAAG,CAAC,UAAU,EAAE,eAAe,CAAC,CAAC;AAE1C,kEAAkE;AAClE,QAAQ,CAAC,GAAG,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC;AACxC,QAAQ,CAAC,GAAG,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;AAEpC,sCAAsC;AACtC,QAAQ,CAAC,GAAG,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;AACtC,QAAQ,CAAC,GAAG,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;AACpC,QAAQ,CAAC,GAAG,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;AAEtC,qCAAqC;AACrC,MAAM,UAAU,UAAU,CAAC,QAAkB;IAC3C,MAAM,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACvC,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CACb,uCAAuC,QAAQ,iBAAiB,YAAY,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CACnH,CAAC;IACJ,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,mCAAmC;AACnC,MAAM,UAAU,YAAY;IAC1B,OAAO,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;AACvC,CAAC;AAED,iDAAiD;AACjD,MAAM,UAAU,eAAe,CAAC,OAAwB;IACtD,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;AAC1C,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,cAAc;IAC5B,qEAAqE;IACrE,kEAAkE;IAClE,yEAAyE;IACzE,0EAA0E;IAC1E,yEAAyE;IAEzE,mBAAmB;IACnB,IAAI,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,OAAO,CAAC,GAAG,CAAC,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,kBAAkB,EAAE,CAAC;QAC1F,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,6CAA6C;IAC7C,IAAI,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,OAAO,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;QACnD,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,kDAAkD;IAClD,IAAI,OAAO,CAAC,GAAG,CAAC,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,OAAO,CAAC,GAAG,CAAC,kBAAkB,EAAE,CAAC;QAC1F,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,0CAA0C;IAC1C,oEAAoE;IACpE,wEAAwE;IACxE,yEAAyE;IACzE,wEAAwE;IACxE,uEAAuE;IACvE,qEAAqE;IACrE,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,OAAO,CAAC,GAAG,CAAC,kBAAkB,EAAE,CAAC;QAC9D,IAAI,OAAO,CAAC,GAAG,CAAC,oBAAoB,IAAI,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,CAAC;YACpE,OAAO,eAAe,CAAC;QACzB,CAAC;QACD,OAAO,aAAa,CAAC;IACvB,CAAC;IAED,2BAA2B;IAC3B,IAAI,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,CAAC;QAC9D,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,8CAA8C;IAC9C,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,OAAO,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;QACzD,OAAO,UAAU,CAAC;IACpB,CAAC;IAED,2EAA2E;IAC3E,2EAA2E;IAC3E,mEAAmE;IACnE,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;GAGG;AACH,MAAM,kBAAkB,GAAG,IAAI,GAAG,CAAC;IACjC,oBAAoB;IACpB,MAAM;IACN,cAAc;IACd,YAAY;IACZ,oBAAoB;IACpB,sBAAsB;IACtB,qBAAqB;IACrB,eAAe;CAChB,CAAC,CAAC;AAEH;;;;GAIG;AACH,MAAM,kBAAkB,GAAG,IAAI,GAAG,CAAC;IACjC,aAAa;IACb,YAAY;IACZ,aAAa;IACb,YAAY;IACZ,qBAAqB;IACrB,aAAa;CACd,CAAC,CAAC;AAEH;;;;;;;;;GASG;AACH,MAAM,UAAU,yBAAyB,CAAC,GAA4B;IACpE,qEAAqE;IACrE,IAAI,OAAO,GAAG,CAAC,cAAc,KAAK,QAAQ,EAAE,CAAC;QAC3C,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,2EAA2E;IAC3E,kFAAkF;IAClF,IAAI,OAAO,GAAG,CAAC,eAAe,KAAK,QAAQ,IAAI,kBAAkB,CAAC,GAAG,CAAC,GAAG,CAAC,eAAe,CAAC,EAAE,CAAC;QAC3F,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,oEAAoE;IACpE,IAAI,OAAO,GAAG,CAAC,eAAe,KAAK,QAAQ,IAAI,kBAAkB,CAAC,GAAG,CAAC,GAAG,CAAC,eAAe,CAAC,EAAE,CAAC;QAC3F,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,eAAe,CAAC,WAAmB;IACjD,MAAM,SAAS,GAAG,IAAI,GAAG,EAAY,CAAC;IAEtC,+EAA+E;IAC/E,IAAI,UAAU,CAAC,IAAI,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC,EAAE,CAAC;QAC7C,SAAS,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;QAC7B,SAAS,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;IACjC,CAAC;IAED,qDAAqD;IACrD,IACE,UAAU,CAAC,IAAI,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;QAC1C,UAAU,CAAC,IAAI,CAAC,WAAW,EAAE,eAAe,CAAC,CAAC;QAC9C,UAAU,CAAC,IAAI,CAAC,WAAW,EAAE,gBAAgB,CAAC,CAAC,EAC/C,CAAC;QACD,SAAS,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IAC5B,CAAC;IAED,oCAAoC;IACpC,IAAI,UAAU,CAAC,IAAI,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC,EAAE,CAAC;QAC7C,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC1B,CAAC;IAED,mCAAmC;IACnC,IAAI,UAAU,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC,EAAE,CAAC;QAC5C,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IACzB,CAAC;IAED,oCAAoC;IACpC,IAAI,UAAU,CAAC,IAAI,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC,EAAE,CAAC;QAC7C,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC1B,CAAC;IAED,gEAAgE;IAChE,sEAAsE;IACtE,qDAAqD;IACrD,IAAI,SAAS,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;QACzB,MAAM,WAAW,GAAG,cAAc,EAAE,CAAC;QACrC,IAAI,WAAW,KAAK,OAAO,EAAE,CAAC;YAC5B,SAAS,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QAC7B,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;AAC/B,CAAC"}
|
package/dist/adapters/stub.d.ts
CHANGED
|
@@ -13,12 +13,8 @@ import type { PlatformAdapter } from "./types.js";
|
|
|
13
13
|
* All methods throw with a clear message explaining the platform is not yet implemented.
|
|
14
14
|
*/
|
|
15
15
|
export declare function createStubAdapter(platform: Platform, displayName: string, envVarHints: string[]): PlatformAdapter;
|
|
16
|
-
/** Cursor — VS Code-based AI coding assistant */
|
|
17
|
-
export declare const cursorAdapter: PlatformAdapter;
|
|
18
16
|
/** GitHub Copilot — AI pair programmer */
|
|
19
17
|
export declare const copilotAdapter: PlatformAdapter;
|
|
20
|
-
/** Codex — OpenAI's AI coding agent */
|
|
21
|
-
export declare const codexAdapter: PlatformAdapter;
|
|
22
18
|
/** Unknown / undetected platform */
|
|
23
19
|
export declare const otherAdapter: PlatformAdapter;
|
|
24
20
|
//# sourceMappingURL=stub.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stub.d.ts","sourceRoot":"","sources":["../../src/adapters/stub.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,KAAK,EACV,eAAe,EAKhB,MAAM,YAAY,CAAC;AAEpB;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,QAAQ,EAClB,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,EAAE,GACpB,eAAe,CA+CjB;AAED,
|
|
1
|
+
{"version":3,"file":"stub.d.ts","sourceRoot":"","sources":["../../src/adapters/stub.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,KAAK,EACV,eAAe,EAKhB,MAAM,YAAY,CAAC;AAEpB;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,QAAQ,EAClB,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,EAAE,GACpB,eAAe,CA+CjB;AAED,0CAA0C;AAC1C,eAAO,MAAM,cAAc,iBAI1B,CAAC;AAEF,oCAAoC;AACpC,eAAO,MAAM,YAAY,iBAIxB,CAAC"}
|
package/dist/adapters/stub.js
CHANGED
|
@@ -49,12 +49,8 @@ export function createStubAdapter(platform, displayName, envVarHints) {
|
|
|
49
49
|
},
|
|
50
50
|
};
|
|
51
51
|
}
|
|
52
|
-
/** Cursor — VS Code-based AI coding assistant */
|
|
53
|
-
export const cursorAdapter = createStubAdapter("cursor", "Cursor", ["CURSOR_SESSION_ID", "CURSOR"]);
|
|
54
52
|
/** GitHub Copilot — AI pair programmer */
|
|
55
53
|
export const copilotAdapter = createStubAdapter("copilot", "GitHub Copilot", ["GITHUB_COPILOT", "COPILOT_SESSION"]);
|
|
56
|
-
/** Codex — OpenAI's AI coding agent */
|
|
57
|
-
export const codexAdapter = createStubAdapter("codex", "Codex", ["CODEX", "CODEX_SESSION"]);
|
|
58
54
|
/** Unknown / undetected platform */
|
|
59
55
|
export const otherAdapter = createStubAdapter("other", "Unknown Platform", []);
|
|
60
56
|
//# sourceMappingURL=stub.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stub.js","sourceRoot":"","sources":["../../src/adapters/stub.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAWH;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAC/B,QAAkB,EAClB,WAAmB,EACnB,WAAqB;IAErB,MAAM,YAAY,GAAG,CAAC,MAAc,EAAS,EAAE;QAC7C,MAAM,IAAI,KAAK,CACb,GAAG,WAAW,4CAA4C,MAAM,KAAK;YACnE,0DAA0D,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK;YACrF,oFAAoF,CACvF,CAAC;IACJ,CAAC,CAAC;IAEF,OAAO;QACL,QAAQ;QACR,WAAW;QACX,YAAY,EAAE,EAAmB;QAEjC,UAAU,CAAC,IAA6B,EAAE,SAAiB;YACzD,OAAO,YAAY,CAAC,YAAY,CAAC,CAAC;QACpC,CAAC;QAED,kBAAkB,CAAC,eAAuB;YACxC,OAAO,YAAY,CAAC,oBAAoB,CAAC,CAAC;QAC5C,CAAC;QAED,KAAK,CAAC,oBAAoB,CAAC,YAAoB;YAC7C,OAAO;gBACL,KAAK,EAAE,KAAK;gBACZ,MAAM,EAAE;oBACN;wBACE,IAAI,EAAE,GAAG,WAAW,UAAU;wBAC9B,EAAE,EAAE,KAAK;wBACT,MAAM,EAAE,GAAG,WAAW,iCAAiC;qBACxD;iBACF;aACF,CAAC;QACJ,CAAC;QAED,KAAK,CAAC,YAAY,CAAC,YAAoB,EAAE,eAAuB;YAC9D,YAAY,CAAC,cAAc,CAAC,CAAC;QAC/B,CAAC;QAED,KAAK,CAAC,cAAc,CAAC,YAAoB;YACvC,YAAY,CAAC,gBAAgB,CAAC,CAAC;QACjC,CAAC;QAED,gBAAgB,CAAC,YAAoB;YACnC,OAAO,IAAI,CAAC;QACd,CAAC;KACF,CAAC;AACJ,CAAC;AAED,
|
|
1
|
+
{"version":3,"file":"stub.js","sourceRoot":"","sources":["../../src/adapters/stub.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAWH;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAC/B,QAAkB,EAClB,WAAmB,EACnB,WAAqB;IAErB,MAAM,YAAY,GAAG,CAAC,MAAc,EAAS,EAAE;QAC7C,MAAM,IAAI,KAAK,CACb,GAAG,WAAW,4CAA4C,MAAM,KAAK;YACnE,0DAA0D,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK;YACrF,oFAAoF,CACvF,CAAC;IACJ,CAAC,CAAC;IAEF,OAAO;QACL,QAAQ;QACR,WAAW;QACX,YAAY,EAAE,EAAmB;QAEjC,UAAU,CAAC,IAA6B,EAAE,SAAiB;YACzD,OAAO,YAAY,CAAC,YAAY,CAAC,CAAC;QACpC,CAAC;QAED,kBAAkB,CAAC,eAAuB;YACxC,OAAO,YAAY,CAAC,oBAAoB,CAAC,CAAC;QAC5C,CAAC;QAED,KAAK,CAAC,oBAAoB,CAAC,YAAoB;YAC7C,OAAO;gBACL,KAAK,EAAE,KAAK;gBACZ,MAAM,EAAE;oBACN;wBACE,IAAI,EAAE,GAAG,WAAW,UAAU;wBAC9B,EAAE,EAAE,KAAK;wBACT,MAAM,EAAE,GAAG,WAAW,iCAAiC;qBACxD;iBACF;aACF,CAAC;QACJ,CAAC;QAED,KAAK,CAAC,YAAY,CAAC,YAAoB,EAAE,eAAuB;YAC9D,YAAY,CAAC,cAAc,CAAC,CAAC;QAC/B,CAAC;QAED,KAAK,CAAC,cAAc,CAAC,YAAoB;YACvC,YAAY,CAAC,gBAAgB,CAAC,CAAC;QACjC,CAAC;QAED,gBAAgB,CAAC,YAAoB;YACnC,OAAO,IAAI,CAAC;QACd,CAAC;KACF,CAAC;AACJ,CAAC;AAED,0CAA0C;AAC1C,MAAM,CAAC,MAAM,cAAc,GAAG,iBAAiB,CAC7C,SAAS,EACT,gBAAgB,EAChB,CAAC,gBAAgB,EAAE,iBAAiB,CAAC,CACtC,CAAC;AAEF,oCAAoC;AACpC,MAAM,CAAC,MAAM,YAAY,GAAG,iBAAiB,CAC3C,OAAO,EACP,kBAAkB,EAClB,EAAE,CACH,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"unified.d.ts","sourceRoot":"","sources":["../../src/handlers/unified.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;
|
|
1
|
+
{"version":3,"file":"unified.d.ts","sourceRoot":"","sources":["../../src/handlers/unified.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAeH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAEhE;;;GAGG;AACH,wBAAsB,YAAY,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CAmE5E"}
|
package/dist/handlers/unified.js
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
import { getLatestEnvSnapshot, endSession, withPerf, } from "@varveai/adit-core";
|
|
8
8
|
import { getChangedFiles, createTimelineManager, captureEnvironment, diffEnvironments, } from "@varveai/adit-engine";
|
|
9
9
|
import { initHookContext } from "../common/context.js";
|
|
10
|
+
import { appendFileSync, existsSync, readFileSync } from "node:fs";
|
|
10
11
|
/**
|
|
11
12
|
* Dispatch a normalized hook input to the appropriate handler.
|
|
12
13
|
* This is the single entry point for all platform hook events.
|
|
@@ -103,9 +104,30 @@ async function handleStopUnified(ctx, input) {
|
|
|
103
104
|
});
|
|
104
105
|
const lastPrompt = recentPrompts[0]?.promptText ?? null;
|
|
105
106
|
// Use last_assistant_message as the response text (what the model actually said).
|
|
107
|
+
// Cursor sometimes fires stop before transcript text is fully flushed, so
|
|
108
|
+
// we retry transcript extraction briefly when message text is missing.
|
|
109
|
+
const recoveredAssistantMessage = input.lastAssistantMessage
|
|
110
|
+
?? await recoverAssistantMessageFromTranscript(input.transcriptPath);
|
|
106
111
|
// Fall back to stop_reason for backward compatibility, then to "completed".
|
|
107
|
-
const responseText =
|
|
112
|
+
const responseText = recoveredAssistantMessage ?? input.stopReason ?? "completed";
|
|
108
113
|
const checkpointLabel = input.stopReason ?? "completed";
|
|
114
|
+
// Debug: log response resolution chain to trace why "completed" is recorded
|
|
115
|
+
try {
|
|
116
|
+
appendFileSync("/tmp/adit-hook-debug.jsonl", JSON.stringify({
|
|
117
|
+
timestamp: new Date().toISOString(),
|
|
118
|
+
phase: "stop-response-resolution",
|
|
119
|
+
hookType: input.hookType,
|
|
120
|
+
platformCli: input.platformCli,
|
|
121
|
+
hasLastAssistantMessage: !!input.lastAssistantMessage,
|
|
122
|
+
hasTranscriptPath: !!input.transcriptPath,
|
|
123
|
+
transcriptRecoveryResult: recoveredAssistantMessage ? "found" : "not-found",
|
|
124
|
+
stopReason: input.stopReason,
|
|
125
|
+
finalResponseText: responseText,
|
|
126
|
+
rawPlatformDataKeys: input.rawPlatformData ? Object.keys(input.rawPlatformData) : [],
|
|
127
|
+
rawPlatformData: input.rawPlatformData,
|
|
128
|
+
}) + "\n");
|
|
129
|
+
}
|
|
130
|
+
catch { /* best-effort */ }
|
|
109
131
|
const event = await timeline.recordEvent({
|
|
110
132
|
sessionId: ctx.session.id,
|
|
111
133
|
eventType: "assistant_response",
|
|
@@ -146,6 +168,53 @@ async function handleStopUnified(ctx, input) {
|
|
|
146
168
|
}
|
|
147
169
|
}
|
|
148
170
|
}
|
|
171
|
+
function extractLastAssistantTextFromTranscript(transcriptPath) {
|
|
172
|
+
if (!transcriptPath || !existsSync(transcriptPath))
|
|
173
|
+
return undefined;
|
|
174
|
+
try {
|
|
175
|
+
const lines = readFileSync(transcriptPath, "utf-8")
|
|
176
|
+
.split("\n")
|
|
177
|
+
.filter((l) => l.trim().length > 0);
|
|
178
|
+
for (let i = lines.length - 1; i >= 0; i--) {
|
|
179
|
+
try {
|
|
180
|
+
const entry = JSON.parse(lines[i]);
|
|
181
|
+
if (entry.role !== "assistant")
|
|
182
|
+
continue;
|
|
183
|
+
const content = entry.message?.content;
|
|
184
|
+
if (!Array.isArray(content))
|
|
185
|
+
continue;
|
|
186
|
+
const text = content
|
|
187
|
+
.filter((c) => c?.type === "text" && typeof c.text === "string")
|
|
188
|
+
.map((c) => c.text.trim())
|
|
189
|
+
.filter((t) => t.length > 0)
|
|
190
|
+
.join("\n");
|
|
191
|
+
if (text)
|
|
192
|
+
return text;
|
|
193
|
+
}
|
|
194
|
+
catch {
|
|
195
|
+
// ignore malformed lines
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
catch {
|
|
200
|
+
// fail-open
|
|
201
|
+
}
|
|
202
|
+
return undefined;
|
|
203
|
+
}
|
|
204
|
+
async function recoverAssistantMessageFromTranscript(transcriptPath) {
|
|
205
|
+
if (!transcriptPath)
|
|
206
|
+
return undefined;
|
|
207
|
+
const delaysMs = [0, 120, 240, 480, 800];
|
|
208
|
+
for (const delayMs of delaysMs) {
|
|
209
|
+
if (delayMs > 0) {
|
|
210
|
+
await new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
211
|
+
}
|
|
212
|
+
const text = extractLastAssistantTextFromTranscript(transcriptPath);
|
|
213
|
+
if (text)
|
|
214
|
+
return text;
|
|
215
|
+
}
|
|
216
|
+
return undefined;
|
|
217
|
+
}
|
|
149
218
|
/** Handle session start — capture initial env snapshot and record metadata */
|
|
150
219
|
async function handleSessionStart(ctx, input) {
|
|
151
220
|
const timeline = createTimelineManager(ctx.db, ctx.config);
|