@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.
@@ -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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"}
@@ -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, cursorAdapter, copilotAdapter, codexAdapter, otherAdapter } from "./stub.js";
6
- export { getAdapter, listAdapters, registerAdapter, detectPlatform, detectPlatforms } from "./registry.js";
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,cAAc,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzG,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAE3G;;;;GAIG;AACH,wBAAgB,qBAAqB,IAAI,MAAM,CAc9C"}
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"}
@@ -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, cursorAdapter, copilotAdapter, codexAdapter, otherAdapter } from "./stub.js";
8
- export { getAdapter, listAdapters, registerAdapter, detectPlatform, detectPlatforms } from "./registry.js";
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,cAAc,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzG,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAE3G;;;;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"}
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;AA2BlD,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,CAqCzC;AAED;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,QAAQ,EAAE,CA6B/D"}
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 { cursorAdapter, copilotAdapter, codexAdapter, otherAdapter, } from "./stub.js";
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":"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"}
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/adapters/registry.ts"],"names":[],"mappings":"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"}
@@ -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,iDAAiD;AACjD,eAAO,MAAM,aAAa,iBAIzB,CAAC;AAEF,0CAA0C;AAC1C,eAAO,MAAM,cAAc,iBAI1B,CAAC;AAEF,uCAAuC;AACvC,eAAO,MAAM,YAAY,iBAIxB,CAAC;AAEF,oCAAoC;AACpC,eAAO,MAAM,YAAY,iBAIxB,CAAC"}
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"}
@@ -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,iDAAiD;AACjD,MAAM,CAAC,MAAM,aAAa,GAAG,iBAAiB,CAC5C,QAAQ,EACR,QAAQ,EACR,CAAC,mBAAmB,EAAE,QAAQ,CAAC,CAChC,CAAC;AAEF,0CAA0C;AAC1C,MAAM,CAAC,MAAM,cAAc,GAAG,iBAAiB,CAC7C,SAAS,EACT,gBAAgB,EAChB,CAAC,gBAAgB,EAAE,iBAAiB,CAAC,CACtC,CAAC;AAEF,uCAAuC;AACvC,MAAM,CAAC,MAAM,YAAY,GAAG,iBAAiB,CAC3C,OAAO,EACP,OAAO,EACP,CAAC,OAAO,EAAE,eAAe,CAAC,CAC3B,CAAC;AAEF,oCAAoC;AACpC,MAAM,CAAC,MAAM,YAAY,GAAG,iBAAiB,CAC3C,OAAO,EACP,kBAAkB,EAClB,EAAE,CACH,CAAC"}
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;AAcH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAEhE;;;GAGG;AACH,wBAAsB,YAAY,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CAmE5E"}
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"}
@@ -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 = input.lastAssistantMessage ?? input.stopReason ?? "completed";
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);