@halyard/cli 0.1.1 → 0.2.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.
Files changed (142) hide show
  1. package/README.md +115 -0
  2. package/dist/cli.js +30 -3
  3. package/dist/cli.js.map +1 -1
  4. package/dist/commands/api-keys.d.ts +3 -0
  5. package/dist/commands/api-keys.d.ts.map +1 -0
  6. package/dist/commands/api-keys.js +90 -0
  7. package/dist/commands/api-keys.js.map +1 -0
  8. package/dist/commands/hook.d.ts +6 -0
  9. package/dist/commands/hook.d.ts.map +1 -0
  10. package/dist/commands/hook.js +106 -0
  11. package/dist/commands/hook.js.map +1 -0
  12. package/dist/commands/login.d.ts +17 -0
  13. package/dist/commands/login.d.ts.map +1 -1
  14. package/dist/commands/login.js +170 -65
  15. package/dist/commands/login.js.map +1 -1
  16. package/dist/commands/orgs.d.ts +3 -0
  17. package/dist/commands/orgs.d.ts.map +1 -0
  18. package/dist/commands/orgs.js +102 -0
  19. package/dist/commands/orgs.js.map +1 -0
  20. package/dist/commands/push.d.ts.map +1 -1
  21. package/dist/commands/push.js +29 -6
  22. package/dist/commands/push.js.map +1 -1
  23. package/dist/commands/sessions.d.ts +3 -0
  24. package/dist/commands/sessions.d.ts.map +1 -0
  25. package/dist/commands/sessions.js +139 -0
  26. package/dist/commands/sessions.js.map +1 -0
  27. package/dist/commands/setup.d.ts +3 -0
  28. package/dist/commands/setup.d.ts.map +1 -0
  29. package/dist/commands/setup.js +58 -0
  30. package/dist/commands/setup.js.map +1 -0
  31. package/dist/commands/skills.d.ts +12 -0
  32. package/dist/commands/skills.d.ts.map +1 -0
  33. package/dist/commands/skills.js +171 -0
  34. package/dist/commands/skills.js.map +1 -0
  35. package/dist/commands/sync.d.ts.map +1 -1
  36. package/dist/commands/sync.js +51 -49
  37. package/dist/commands/sync.js.map +1 -1
  38. package/dist/commands/users.d.ts +13 -0
  39. package/dist/commands/users.d.ts.map +1 -0
  40. package/dist/commands/users.js +205 -0
  41. package/dist/commands/users.js.map +1 -0
  42. package/dist/commands/whoami.d.ts +21 -0
  43. package/dist/commands/whoami.d.ts.map +1 -0
  44. package/dist/commands/whoami.js +77 -0
  45. package/dist/commands/whoami.js.map +1 -0
  46. package/dist/lib/api-client.d.ts +64 -2
  47. package/dist/lib/api-client.d.ts.map +1 -1
  48. package/dist/lib/api-client.js +32 -7
  49. package/dist/lib/api-client.js.map +1 -1
  50. package/dist/lib/auth.d.ts +43 -6
  51. package/dist/lib/auth.d.ts.map +1 -1
  52. package/dist/lib/auth.js +106 -25
  53. package/dist/lib/auth.js.map +1 -1
  54. package/dist/lib/config-files.d.ts +6 -0
  55. package/dist/lib/config-files.d.ts.map +1 -0
  56. package/dist/lib/config-files.js +27 -0
  57. package/dist/lib/config-files.js.map +1 -0
  58. package/dist/lib/config.d.ts +13 -7
  59. package/dist/lib/config.d.ts.map +1 -1
  60. package/dist/lib/config.js +22 -8
  61. package/dist/lib/config.js.map +1 -1
  62. package/dist/lib/copilot-export.d.ts +31 -0
  63. package/dist/lib/copilot-export.d.ts.map +1 -0
  64. package/dist/lib/copilot-export.js +129 -0
  65. package/dist/lib/copilot-export.js.map +1 -0
  66. package/dist/lib/discovery.d.ts +60 -2
  67. package/dist/lib/discovery.d.ts.map +1 -1
  68. package/dist/lib/discovery.js +187 -15
  69. package/dist/lib/discovery.js.map +1 -1
  70. package/dist/lib/hook-discovery.d.ts +43 -0
  71. package/dist/lib/hook-discovery.d.ts.map +1 -0
  72. package/dist/lib/hook-discovery.js +90 -0
  73. package/dist/lib/hook-discovery.js.map +1 -0
  74. package/dist/lib/hook-input.d.ts +36 -0
  75. package/dist/lib/hook-input.d.ts.map +1 -0
  76. package/dist/lib/hook-input.js +161 -0
  77. package/dist/lib/hook-input.js.map +1 -0
  78. package/dist/lib/hook-runner.d.ts +48 -0
  79. package/dist/lib/hook-runner.d.ts.map +1 -0
  80. package/dist/lib/hook-runner.js +306 -0
  81. package/dist/lib/hook-runner.js.map +1 -0
  82. package/dist/lib/http.d.ts +18 -0
  83. package/dist/lib/http.d.ts.map +1 -0
  84. package/dist/lib/http.js +54 -0
  85. package/dist/lib/http.js.map +1 -0
  86. package/dist/lib/opencode-export.d.ts +22 -0
  87. package/dist/lib/opencode-export.d.ts.map +1 -0
  88. package/dist/lib/opencode-export.js +53 -0
  89. package/dist/lib/opencode-export.js.map +1 -0
  90. package/dist/lib/output.d.ts +27 -0
  91. package/dist/lib/output.d.ts.map +1 -0
  92. package/dist/lib/output.js +74 -0
  93. package/dist/lib/output.js.map +1 -0
  94. package/dist/lib/preflight.d.ts +35 -0
  95. package/dist/lib/preflight.d.ts.map +1 -0
  96. package/dist/lib/preflight.js +54 -0
  97. package/dist/lib/preflight.js.map +1 -0
  98. package/dist/lib/repo-binding.d.ts +43 -0
  99. package/dist/lib/repo-binding.d.ts.map +1 -0
  100. package/dist/lib/repo-binding.js +158 -0
  101. package/dist/lib/repo-binding.js.map +1 -0
  102. package/dist/lib/repo-identity.d.ts +29 -0
  103. package/dist/lib/repo-identity.d.ts.map +1 -0
  104. package/dist/lib/repo-identity.js +113 -0
  105. package/dist/lib/repo-identity.js.map +1 -0
  106. package/dist/lib/setup-hooks.d.ts +41 -0
  107. package/dist/lib/setup-hooks.d.ts.map +1 -0
  108. package/dist/lib/setup-hooks.js +276 -0
  109. package/dist/lib/setup-hooks.js.map +1 -0
  110. package/dist/lib/setup.d.ts +47 -0
  111. package/dist/lib/setup.d.ts.map +1 -0
  112. package/dist/lib/setup.js +179 -0
  113. package/dist/lib/setup.js.map +1 -0
  114. package/dist/lib/skill-batches.d.ts +16 -0
  115. package/dist/lib/skill-batches.d.ts.map +1 -0
  116. package/dist/lib/skill-batches.js +35 -0
  117. package/dist/lib/skill-batches.js.map +1 -0
  118. package/dist/lib/skill-files.d.ts +4 -0
  119. package/dist/lib/skill-files.d.ts.map +1 -0
  120. package/dist/lib/skill-files.js +36 -0
  121. package/dist/lib/skill-files.js.map +1 -0
  122. package/dist/lib/skill-fingerprint.d.ts +55 -0
  123. package/dist/lib/skill-fingerprint.d.ts.map +1 -0
  124. package/dist/lib/skill-fingerprint.js +204 -0
  125. package/dist/lib/skill-fingerprint.js.map +1 -0
  126. package/dist/lib/skills-discovery.d.ts +57 -0
  127. package/dist/lib/skills-discovery.d.ts.map +1 -0
  128. package/dist/lib/skills-discovery.js +157 -0
  129. package/dist/lib/skills-discovery.js.map +1 -0
  130. package/dist/lib/skills-sync.d.ts +66 -0
  131. package/dist/lib/skills-sync.d.ts.map +1 -0
  132. package/dist/lib/skills-sync.js +251 -0
  133. package/dist/lib/skills-sync.js.map +1 -0
  134. package/dist/lib/sync-runner.d.ts +56 -0
  135. package/dist/lib/sync-runner.d.ts.map +1 -0
  136. package/dist/lib/sync-runner.js +106 -0
  137. package/dist/lib/sync-runner.js.map +1 -0
  138. package/dist/lib/sync-state.d.ts +36 -6
  139. package/dist/lib/sync-state.d.ts.map +1 -1
  140. package/dist/lib/sync-state.js +41 -11
  141. package/dist/lib/sync-state.js.map +1 -1
  142. package/package.json +16 -8
@@ -1,9 +1,22 @@
1
1
  import { homedir } from 'node:os';
2
- import { join, basename } from 'node:path';
3
- import { readdirSync, statSync, existsSync } from 'node:fs';
2
+ import { join, basename, extname } from 'node:path';
3
+ import { readdirSync, readFileSync, statSync, existsSync, openSync, readSync, closeSync, } from 'node:fs';
4
+ import { buildCopilotBundle, listCopilotSessions } from './copilot-export.js';
5
+ import { exportOpencodeSession, listOpencodeSessions } from './opencode-export.js';
6
+ export const SESSION_PROVIDERS = [
7
+ 'claude',
8
+ 'codex',
9
+ 'gemini',
10
+ 'opencode',
11
+ 'copilot',
12
+ ];
13
+ /** How much of a session file to read when looking for the cwd record. */
14
+ const HEAD_BYTES = 64 * 1024;
15
+ /** How many head lines to scan for a Claude cwd record. */
16
+ const MAX_HEAD_LINES = 50;
4
17
  /**
5
18
  * Discover Claude Code session log files.
6
- * Claude Code stores sessions in ~/.claude/projects/<project-hash>/sessions/
19
+ * Claude Code stores sessions in ~/.claude/projects/<project-hash>/
7
20
  * Session files are JSONL format.
8
21
  */
9
22
  export function discoverClaudeSessions() {
@@ -18,7 +31,7 @@ export function discoverClaudeSessions() {
18
31
  if (!statSync(projectPath).isDirectory())
19
32
  continue;
20
33
  // Look for JSONL files directly in project dir and in sessions subdirs
21
- walkForJsonl(projectPath, 'claude', sessions, 0);
34
+ walkForSessionFiles(projectPath, 'claude', ['.jsonl'], sessions, 0);
22
35
  }
23
36
  }
24
37
  catch {
@@ -35,24 +48,108 @@ export function discoverCodexSessions() {
35
48
  if (!existsSync(codexDir))
36
49
  return [];
37
50
  const sessions = [];
38
- walkForJsonl(codexDir, 'codex', sessions, 0);
51
+ walkForSessionFiles(codexDir, 'codex', ['.jsonl'], sessions, 0);
39
52
  return sessions;
40
53
  }
54
+ /**
55
+ * Discover Gemini CLI chat session files.
56
+ * Gemini CLI stores sessions in ~/.gemini/tmp/<project>/chats/session-*.jsonl
57
+ * (legacy sessions are single-JSON `.json` files; subagent sessions live in
58
+ * chats/<parent-session-id>/ subdirectories).
59
+ */
60
+ export function discoverGeminiSessions() {
61
+ const geminiTmp = join(homedir(), '.gemini', 'tmp');
62
+ if (!existsSync(geminiTmp))
63
+ return [];
64
+ const sessions = [];
65
+ try {
66
+ for (const project of readdirSync(geminiTmp)) {
67
+ const chatsDir = join(geminiTmp, project, 'chats');
68
+ try {
69
+ if (!statSync(chatsDir).isDirectory())
70
+ continue;
71
+ }
72
+ catch {
73
+ continue;
74
+ }
75
+ walkForSessionFiles(chatsDir, 'gemini', ['.jsonl', '.json'], sessions, 0);
76
+ }
77
+ }
78
+ catch {
79
+ // Permission errors - silently skip
80
+ }
81
+ return sessions;
82
+ }
83
+ /**
84
+ * Discover OpenCode sessions. OpenCode keeps everything in a SQLite
85
+ * database; sessions are listed via the `opencode` CLI itself and exported
86
+ * one at a time at upload time (see loadSessionContent).
87
+ */
88
+ export function discoverOpencodeSessions() {
89
+ return listOpencodeSessions().map((s) => ({
90
+ provider: 'opencode',
91
+ filePath: `opencode://${s.id}`,
92
+ sessionId: s.id,
93
+ sizeBytes: 0,
94
+ freshness: `${s.id}:${s.timeUpdated}`,
95
+ }));
96
+ }
97
+ /**
98
+ * Discover GitHub Copilot CLI sessions. Copilot CLI keeps all sessions in
99
+ * one shared SQLite store (~/.copilot/session-store.db); each session is
100
+ * exported as a JSONL bundle at upload time (see loadSessionContent).
101
+ */
102
+ export function discoverCopilotSessions() {
103
+ return listCopilotSessions().map((s) => ({
104
+ provider: 'copilot',
105
+ filePath: `copilot://${s.id}`,
106
+ sessionId: s.id,
107
+ sizeBytes: 0,
108
+ freshness: `${s.id}:${s.updatedAt}`,
109
+ }));
110
+ }
111
+ const DISCOVERERS = {
112
+ claude: discoverClaudeSessions,
113
+ codex: discoverCodexSessions,
114
+ gemini: discoverGeminiSessions,
115
+ opencode: discoverOpencodeSessions,
116
+ copilot: discoverCopilotSessions,
117
+ };
41
118
  /**
42
119
  * Auto-detect which providers have session files available.
43
120
  */
44
121
  export function discoverAllSessions(providerFilter) {
45
122
  const sessions = [];
46
- if (!providerFilter || providerFilter === 'claude') {
47
- sessions.push(...discoverClaudeSessions());
48
- }
49
- if (!providerFilter || providerFilter === 'codex') {
50
- sessions.push(...discoverCodexSessions());
123
+ for (const provider of SESSION_PROVIDERS) {
124
+ if (providerFilter && providerFilter !== provider)
125
+ continue;
126
+ sessions.push(...DISCOVERERS[provider]());
51
127
  }
52
128
  return sessions;
53
129
  }
54
- /** Recursively walk a directory for .jsonl files, with a max depth. */
55
- function walkForJsonl(dir, provider, results, depth) {
130
+ /**
131
+ * Materialize the bytes to upload for a discovered session: the file itself
132
+ * for file-backed providers, or a synthesized export for store-backed ones.
133
+ */
134
+ export async function loadSessionContent(session) {
135
+ if (session.provider === 'opencode') {
136
+ return exportOpencodeSession(session.sessionId);
137
+ }
138
+ if (session.provider === 'copilot') {
139
+ return buildCopilotBundle(session.sessionId);
140
+ }
141
+ return readFileSync(session.filePath);
142
+ }
143
+ /** The name the ingest endpoint stores for the uploaded blob. */
144
+ export function uploadFileName(session) {
145
+ if (session.provider === 'opencode')
146
+ return `${session.sessionId}.json`;
147
+ if (session.provider === 'copilot')
148
+ return `${session.sessionId}.jsonl`;
149
+ return basename(session.filePath);
150
+ }
151
+ /** Recursively walk a directory for session files, with a max depth. */
152
+ function walkForSessionFiles(dir, provider, extensions, results, depth) {
56
153
  if (depth > 3)
57
154
  return; // Don't recurse too deep
58
155
  try {
@@ -62,14 +159,15 @@ function walkForJsonl(dir, provider, results, depth) {
62
159
  try {
63
160
  const stat = statSync(fullPath);
64
161
  if (stat.isDirectory()) {
65
- walkForJsonl(fullPath, provider, results, depth + 1);
162
+ walkForSessionFiles(fullPath, provider, extensions, results, depth + 1);
66
163
  }
67
- else if (entry.endsWith('.jsonl') && stat.size > 0) {
164
+ else if (extensions.includes(extname(entry)) && stat.size > 0) {
68
165
  results.push({
69
166
  provider,
70
167
  filePath: fullPath,
71
- sessionId: basename(entry, '.jsonl'),
168
+ sessionId: basename(entry, extname(entry)),
72
169
  sizeBytes: stat.size,
170
+ cwd: extractSessionCwd(fullPath, provider),
73
171
  });
74
172
  }
75
173
  }
@@ -82,4 +180,78 @@ function walkForJsonl(dir, provider, results, depth) {
82
180
  // Skip directories we can't read
83
181
  }
84
182
  }
183
+ /**
184
+ * Extract the session's working directory from the head of a log file.
185
+ * Only claude and codex formats are known to carry it; other providers
186
+ * return undefined (their sessions count as unresolved in scoped sync).
187
+ */
188
+ function extractSessionCwd(filePath, provider) {
189
+ if (provider !== 'claude' && provider !== 'codex')
190
+ return undefined;
191
+ const head = readFileHead(filePath);
192
+ if (head === null)
193
+ return undefined;
194
+ if (provider === 'codex') {
195
+ const firstLine = head.split('\n', 1)[0] ?? '';
196
+ return extractCodexCwd(firstLine);
197
+ }
198
+ return extractClaudeCwd(head);
199
+ }
200
+ /**
201
+ * Claude session logs: the first records are often non-cwd entries
202
+ * (type:"queue-operation", "last-prompt", ...); a record carrying a `cwd`
203
+ * string reliably appears within the first few lines. Scan up to
204
+ * MAX_HEAD_LINES JSON lines and take the first `cwd` found.
205
+ */
206
+ export function extractClaudeCwd(head) {
207
+ const lines = head.split('\n', MAX_HEAD_LINES);
208
+ for (const line of lines) {
209
+ if (!line.trim())
210
+ continue;
211
+ try {
212
+ const parsed = JSON.parse(line);
213
+ if (typeof parsed.cwd === 'string' && parsed.cwd.length > 0)
214
+ return parsed.cwd;
215
+ }
216
+ catch {
217
+ // Malformed (or truncated tail) line - keep scanning
218
+ }
219
+ }
220
+ return undefined;
221
+ }
222
+ /**
223
+ * Codex session logs: the first line is a session_meta record with the cwd at
224
+ * `payload.cwd` (older formats used a top-level `cwd`).
225
+ */
226
+ export function extractCodexCwd(firstLine) {
227
+ try {
228
+ const parsed = JSON.parse(firstLine);
229
+ if (typeof parsed.payload?.cwd === 'string' && parsed.payload.cwd.length > 0) {
230
+ return parsed.payload.cwd;
231
+ }
232
+ if (typeof parsed.cwd === 'string' && parsed.cwd.length > 0)
233
+ return parsed.cwd;
234
+ }
235
+ catch {
236
+ // Malformed first line
237
+ }
238
+ return undefined;
239
+ }
240
+ /** Read up to HEAD_BYTES from the start of a file without loading the rest. */
241
+ function readFileHead(filePath) {
242
+ try {
243
+ const fd = openSync(filePath, 'r');
244
+ try {
245
+ const buffer = Buffer.alloc(HEAD_BYTES);
246
+ const bytesRead = readSync(fd, buffer, 0, HEAD_BYTES, 0);
247
+ return buffer.toString('utf-8', 0, bytesRead);
248
+ }
249
+ finally {
250
+ closeSync(fd);
251
+ }
252
+ }
253
+ catch {
254
+ return null;
255
+ }
256
+ }
85
257
  //# sourceMappingURL=discovery.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"discovery.js","sourceRoot":"","sources":["../../src/lib/discovery.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"discovery.js","sourceRoot":"","sources":["../../src/lib/discovery.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AACjC,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnD,OAAO,EACL,WAAW,EACX,YAAY,EACZ,QAAQ,EACR,UAAU,EACV,QAAQ,EACR,QAAQ,EACR,SAAS,GACV,MAAM,SAAS,CAAA;AAEhB,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAA;AAC7E,OAAO,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAA;AAIlF,MAAM,CAAC,MAAM,iBAAiB,GAAsB;IAClD,QAAQ;IACR,OAAO;IACP,QAAQ;IACR,UAAU;IACV,SAAS;CACV,CAAA;AA2BD,0EAA0E;AAC1E,MAAM,UAAU,GAAG,EAAE,GAAG,IAAI,CAAA;AAC5B,2DAA2D;AAC3D,MAAM,cAAc,GAAG,EAAE,CAAA;AAEzB;;;;GAIG;AACH,MAAM,UAAU,sBAAsB;IACpC,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,UAAU,CAAC,CAAA;IACxD,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC;QAAE,OAAO,EAAE,CAAA;IAErC,MAAM,QAAQ,GAAwB,EAAE,CAAA;IAExC,IAAI,CAAC;QACH,MAAM,WAAW,GAAG,WAAW,CAAC,SAAS,CAAC,CAAA;QAC1C,KAAK,MAAM,OAAO,IAAI,WAAW,EAAE,CAAC;YAClC,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC,CAAA;YAC5C,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,WAAW,EAAE;gBAAE,SAAQ;YAElD,uEAAuE;YACvE,mBAAmB,CAAC,WAAW,EAAE,QAAQ,EAAE,CAAC,QAAQ,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAA;QACrE,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,oDAAoD;IACtD,CAAC;IAED,OAAO,QAAQ,CAAA;AACjB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,qBAAqB;IACnC,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAA;IACtD,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC;QAAE,OAAO,EAAE,CAAA;IAEpC,MAAM,QAAQ,GAAwB,EAAE,CAAA;IACxC,mBAAmB,CAAC,QAAQ,EAAE,OAAO,EAAE,CAAC,QAAQ,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAA;IAC/D,OAAO,QAAQ,CAAA;AACjB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,sBAAsB;IACpC,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,KAAK,CAAC,CAAA;IACnD,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC;QAAE,OAAO,EAAE,CAAA;IAErC,MAAM,QAAQ,GAAwB,EAAE,CAAA;IACxC,IAAI,CAAC;QACH,KAAK,MAAM,OAAO,IAAI,WAAW,CAAC,SAAS,CAAC,EAAE,CAAC;YAC7C,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,EAAE,OAAO,EAAE,OAAO,CAAC,CAAA;YAClD,IAAI,CAAC;gBACH,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE;oBAAE,SAAQ;YACjD,CAAC;YAAC,MAAM,CAAC;gBACP,SAAQ;YACV,CAAC;YACD,mBAAmB,CAAC,QAAQ,EAAE,QAAQ,EAAE,CAAC,QAAQ,EAAE,OAAO,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAA;QAC3E,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,oCAAoC;IACtC,CAAC;IACD,OAAO,QAAQ,CAAA;AACjB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,wBAAwB;IACtC,OAAO,oBAAoB,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACxC,QAAQ,EAAE,UAAU;QACpB,QAAQ,EAAE,cAAc,CAAC,CAAC,EAAE,EAAE;QAC9B,SAAS,EAAE,CAAC,CAAC,EAAE;QACf,SAAS,EAAE,CAAC;QACZ,SAAS,EAAE,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,WAAW,EAAE;KACtC,CAAC,CAAC,CAAA;AACL,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,uBAAuB;IACrC,OAAO,mBAAmB,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACvC,QAAQ,EAAE,SAAS;QACnB,QAAQ,EAAE,aAAa,CAAC,CAAC,EAAE,EAAE;QAC7B,SAAS,EAAE,CAAC,CAAC,EAAE;QACf,SAAS,EAAE,CAAC;QACZ,SAAS,EAAE,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,SAAS,EAAE;KACpC,CAAC,CAAC,CAAA;AACL,CAAC;AAED,MAAM,WAAW,GAAuD;IACtE,MAAM,EAAE,sBAAsB;IAC9B,KAAK,EAAE,qBAAqB;IAC5B,MAAM,EAAE,sBAAsB;IAC9B,QAAQ,EAAE,wBAAwB;IAClC,OAAO,EAAE,uBAAuB;CACjC,CAAA;AAED;;GAEG;AACH,MAAM,UAAU,mBAAmB,CAAC,cAAuB;IACzD,MAAM,QAAQ,GAAwB,EAAE,CAAA;IACxC,KAAK,MAAM,QAAQ,IAAI,iBAAiB,EAAE,CAAC;QACzC,IAAI,cAAc,IAAI,cAAc,KAAK,QAAQ;YAAE,SAAQ;QAC3D,QAAQ,CAAC,IAAI,CAAC,GAAG,WAAW,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAA;IAC3C,CAAC;IACD,OAAO,QAAQ,CAAA;AACjB,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,OAA0B;IACjE,IAAI,OAAO,CAAC,QAAQ,KAAK,UAAU,EAAE,CAAC;QACpC,OAAO,qBAAqB,CAAC,OAAO,CAAC,SAAS,CAAC,CAAA;IACjD,CAAC;IACD,IAAI,OAAO,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;QACnC,OAAO,kBAAkB,CAAC,OAAO,CAAC,SAAS,CAAC,CAAA;IAC9C,CAAC;IACD,OAAO,YAAY,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;AACvC,CAAC;AAED,iEAAiE;AACjE,MAAM,UAAU,cAAc,CAAC,OAA0B;IACvD,IAAI,OAAO,CAAC,QAAQ,KAAK,UAAU;QAAE,OAAO,GAAG,OAAO,CAAC,SAAS,OAAO,CAAA;IACvE,IAAI,OAAO,CAAC,QAAQ,KAAK,SAAS;QAAE,OAAO,GAAG,OAAO,CAAC,SAAS,QAAQ,CAAA;IACvE,OAAO,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;AACnC,CAAC;AAED,wEAAwE;AACxE,SAAS,mBAAmB,CAC1B,GAAW,EACX,QAAyB,EACzB,UAAoB,EACpB,OAA4B,EAC5B,KAAa;IAEb,IAAI,KAAK,GAAG,CAAC;QAAE,OAAM,CAAC,yBAAyB;IAE/C,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,WAAW,CAAC,GAAG,CAAC,CAAA;QAChC,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;YACjC,IAAI,CAAC;gBACH,MAAM,IAAI,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAA;gBAC/B,IAAI,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;oBACvB,mBAAmB,CAAC,QAAQ,EAAE,QAAQ,EAAE,UAAU,EAAE,OAAO,EAAE,KAAK,GAAG,CAAC,CAAC,CAAA;gBACzE,CAAC;qBAAM,IAAI,UAAU,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,IAAI,IAAI,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;oBAChE,OAAO,CAAC,IAAI,CAAC;wBACX,QAAQ;wBACR,QAAQ,EAAE,QAAQ;wBAClB,SAAS,EAAE,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;wBAC1C,SAAS,EAAE,IAAI,CAAC,IAAI;wBACpB,GAAG,EAAE,iBAAiB,CAAC,QAAQ,EAAE,QAAQ,CAAC;qBAC3C,CAAC,CAAA;gBACJ,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,2BAA2B;YAC7B,CAAC;QACH,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,iCAAiC;IACnC,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,SAAS,iBAAiB,CAAC,QAAgB,EAAE,QAAyB;IACpE,IAAI,QAAQ,KAAK,QAAQ,IAAI,QAAQ,KAAK,OAAO;QAAE,OAAO,SAAS,CAAA;IACnE,MAAM,IAAI,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAA;IACnC,IAAI,IAAI,KAAK,IAAI;QAAE,OAAO,SAAS,CAAA;IACnC,IAAI,QAAQ,KAAK,OAAO,EAAE,CAAC;QACzB,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAA;QAC9C,OAAO,eAAe,CAAC,SAAS,CAAC,CAAA;IACnC,CAAC;IACD,OAAO,gBAAgB,CAAC,IAAI,CAAC,CAAA;AAC/B,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAAY;IAC3C,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,cAAc,CAAC,CAAA;IAC9C,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE;YAAE,SAAQ;QAC1B,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAsB,CAAA;YACpD,IAAI,OAAO,MAAM,CAAC,GAAG,KAAK,QAAQ,IAAI,MAAM,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC;gBAAE,OAAO,MAAM,CAAC,GAAG,CAAA;QAChF,CAAC;QAAC,MAAM,CAAC;YACP,qDAAqD;QACvD,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAA;AAClB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,SAAiB;IAC/C,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAmD,CAAA;QACtF,IAAI,OAAO,MAAM,CAAC,OAAO,EAAE,GAAG,KAAK,QAAQ,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC7E,OAAO,MAAM,CAAC,OAAO,CAAC,GAAG,CAAA;QAC3B,CAAC;QACD,IAAI,OAAO,MAAM,CAAC,GAAG,KAAK,QAAQ,IAAI,MAAM,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC;YAAE,OAAO,MAAM,CAAC,GAAG,CAAA;IAChF,CAAC;IAAC,MAAM,CAAC;QACP,uBAAuB;IACzB,CAAC;IACD,OAAO,SAAS,CAAA;AAClB,CAAC;AAED,+EAA+E;AAC/E,SAAS,YAAY,CAAC,QAAgB;IACpC,IAAI,CAAC;QACH,MAAM,EAAE,GAAG,QAAQ,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAA;QAClC,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAA;YACvC,MAAM,SAAS,GAAG,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,CAAA;YACxD,OAAO,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC,EAAE,SAAS,CAAC,CAAA;QAC/C,CAAC;gBAAS,CAAC;YACT,SAAS,CAAC,EAAE,CAAC,CAAA;QACf,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAA;IACb,CAAC;AACH,CAAC"}
@@ -0,0 +1,43 @@
1
+ import { type HookClient, type HookEvent } from './hook-input.js';
2
+ /**
3
+ * What `halyard hook` uploads for a client when the payload carries no
4
+ * transcript path. Claude and Codex logs record their cwd, so their sweeps go
5
+ * through the repo-scoped sync pipeline (`sync-runner`), which resolves each
6
+ * session's cwd to a repo identity. The clients below have no cwd in their
7
+ * transcripts, so they are matched by path or session id instead.
8
+ */
9
+ export interface SweepTarget {
10
+ file: string;
11
+ provider: string;
12
+ }
13
+ export interface SweepContext {
14
+ homeDir: string;
15
+ projectRoot: string;
16
+ sessionId: string;
17
+ transcriptPath: string;
18
+ event: HookEvent;
19
+ env: NodeJS.ProcessEnv;
20
+ }
21
+ export type SweepPlan = {
22
+ kind: 'files';
23
+ targets: SweepTarget[];
24
+ } | {
25
+ kind: 'sync';
26
+ provider: string;
27
+ /** Restrict to sessions whose cwd resolves to this repo (Claude, Codex). */
28
+ scoped: boolean;
29
+ };
30
+ /** Claude keeps subagent transcripts beside the main one:
31
+ * <dir>/<session>.jsonl + <dir>/<session>/subagents/agent-*.jsonl */
32
+ export declare function claudeSessionFiles(transcript: string): string[];
33
+ /** Rollout files end in the thread id: rollout-<timestamp>-<id>.jsonl */
34
+ export declare function findCodexRollout(homeDir: string, sessionId: string): string | null;
35
+ /** ~/.cursor/projects/<path-slug>/agent-transcripts/<conversation>/<conversation>.jsonl */
36
+ export declare function sweepCursor(ctx: SweepContext): SweepTarget[];
37
+ /** Grok Build keeps sessions under ~/.grok/sessions; the payload carries only
38
+ * the session id, so match on it. Layout is undocumented — best effort. */
39
+ export declare function sweepGrok(ctx: SweepContext): SweepTarget[];
40
+ /** Amp caches threads as T-<id>.json under ~/.local/share/amp (or AMP_DATA_DIR). */
41
+ export declare function sweepAmp(ctx: SweepContext): SweepTarget[];
42
+ export declare function sweepForClient(client: HookClient, ctx: SweepContext): SweepPlan;
43
+ //# sourceMappingURL=hook-discovery.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hook-discovery.d.ts","sourceRoot":"","sources":["../../src/lib/hook-discovery.ts"],"names":[],"mappings":"AAEA,OAAO,EAIL,KAAK,UAAU,EACf,KAAK,SAAS,EACf,MAAM,iBAAiB,CAAA;AAExB;;;;;;GAMG;AAEH,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAA;IACf,WAAW,EAAE,MAAM,CAAA;IACnB,SAAS,EAAE,MAAM,CAAA;IACjB,cAAc,EAAE,MAAM,CAAA;IACtB,KAAK,EAAE,SAAS,CAAA;IAChB,GAAG,EAAE,MAAM,CAAC,UAAU,CAAA;CACvB;AAED,MAAM,MAAM,SAAS,GACjB;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,WAAW,EAAE,CAAA;CAAE,GACzC;IACE,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,CAAA;IAChB,4EAA4E;IAC5E,MAAM,EAAE,OAAO,CAAA;CAChB,CAAA;AAuBL;sEACsE;AACtE,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE,CAW/D;AAED,yEAAyE;AACzE,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CASlF;AAED,2FAA2F;AAC3F,wBAAgB,WAAW,CAAC,GAAG,EAAE,YAAY,GAAG,WAAW,EAAE,CAO5D;AAED;4EAC4E;AAC5E,wBAAgB,SAAS,CAAC,GAAG,EAAE,YAAY,GAAG,WAAW,EAAE,CAQ1D;AAED,oFAAoF;AACpF,wBAAgB,QAAQ,CAAC,GAAG,EAAE,YAAY,GAAG,WAAW,EAAE,CAQzD;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,UAAU,EAAE,GAAG,EAAE,YAAY,GAAG,SAAS,CAe/E"}
@@ -0,0 +1,90 @@
1
+ import { readdirSync } from 'node:fs';
2
+ import { basename, dirname, join } from 'node:path';
3
+ import { isDirectory, isNonEmptyFile, pathSlug, } from './hook-input.js';
4
+ function listFiles(dir, depth, predicate, out = []) {
5
+ if (depth < 0 || !isDirectory(dir))
6
+ return out;
7
+ let entries = [];
8
+ try {
9
+ entries = readdirSync(dir).sort();
10
+ }
11
+ catch {
12
+ return out;
13
+ }
14
+ for (const name of entries) {
15
+ const full = join(dir, name);
16
+ if (isDirectory(full))
17
+ listFiles(full, depth - 1, predicate, out);
18
+ else if (predicate(name) && isNonEmptyFile(full))
19
+ out.push(full);
20
+ }
21
+ return out;
22
+ }
23
+ /** Claude keeps subagent transcripts beside the main one:
24
+ * <dir>/<session>.jsonl + <dir>/<session>/subagents/agent-*.jsonl */
25
+ export function claudeSessionFiles(transcript) {
26
+ const dir = dirname(transcript);
27
+ const sessionId = basename(transcript, '.jsonl');
28
+ const files = [transcript];
29
+ const subagents = join(dir, sessionId, 'subagents');
30
+ if (isDirectory(subagents)) {
31
+ for (const name of readdirSync(subagents).sort()) {
32
+ if (name.endsWith('.jsonl'))
33
+ files.push(join(subagents, name));
34
+ }
35
+ }
36
+ return files.filter(isNonEmptyFile);
37
+ }
38
+ /** Rollout files end in the thread id: rollout-<timestamp>-<id>.jsonl */
39
+ export function findCodexRollout(homeDir, sessionId) {
40
+ if (!sessionId)
41
+ return null;
42
+ const suffix = `-${sessionId}.jsonl`;
43
+ const rollouts = listFiles(join(homeDir, '.codex', 'sessions'), 6, (name) => name.startsWith('rollout-') && name.endsWith(suffix));
44
+ return rollouts[0] ?? null;
45
+ }
46
+ /** ~/.cursor/projects/<path-slug>/agent-transcripts/<conversation>/<conversation>.jsonl */
47
+ export function sweepCursor(ctx) {
48
+ const slug = pathSlug(ctx.projectRoot).replace(/^-/, '');
49
+ const dir = join(ctx.homeDir, '.cursor', 'projects', slug, 'agent-transcripts');
50
+ return listFiles(dir, 1, (name) => name.endsWith('.jsonl')).map((file) => ({
51
+ file,
52
+ provider: 'cursor',
53
+ }));
54
+ }
55
+ /** Grok Build keeps sessions under ~/.grok/sessions; the payload carries only
56
+ * the session id, so match on it. Layout is undocumented — best effort. */
57
+ export function sweepGrok(ctx) {
58
+ if (!ctx.sessionId)
59
+ return [];
60
+ const dir = join(ctx.homeDir, '.grok', 'sessions');
61
+ return listFiles(dir, 4, (name) => name.includes(ctx.sessionId) && (name.endsWith('.json') || name.endsWith('.jsonl'))).map((file) => ({ file, provider: 'other' }));
62
+ }
63
+ /** Amp caches threads as T-<id>.json under ~/.local/share/amp (or AMP_DATA_DIR). */
64
+ export function sweepAmp(ctx) {
65
+ if (!ctx.sessionId)
66
+ return [];
67
+ const dir = ctx.env['AMP_DATA_DIR'] ?? join(ctx.homeDir, '.local', 'share', 'amp');
68
+ const wanted = `${ctx.sessionId}.json`;
69
+ return listFiles(dir, 6, (name) => name === wanted).map((file) => ({
70
+ file,
71
+ provider: 'other',
72
+ }));
73
+ }
74
+ export function sweepForClient(client, ctx) {
75
+ switch (client) {
76
+ case 'claude':
77
+ case 'codex':
78
+ return { kind: 'sync', provider: client, scoped: true };
79
+ case 'cursor':
80
+ return { kind: 'files', targets: sweepCursor(ctx) };
81
+ case 'grok':
82
+ return { kind: 'files', targets: sweepGrok(ctx) };
83
+ case 'amp':
84
+ return { kind: 'files', targets: sweepAmp(ctx) };
85
+ default:
86
+ // Gemini / OpenCode / Copilot logs carry no cwd: machine-wide sync.
87
+ return { kind: 'sync', provider: client, scoped: false };
88
+ }
89
+ }
90
+ //# sourceMappingURL=hook-discovery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hook-discovery.js","sourceRoot":"","sources":["../../src/lib/hook-discovery.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Parsing and normalisation for `halyard hook`: the JSON every client pipes to
3
+ * a lifecycle hook, the event names they use, and where the repo root is.
4
+ */
5
+ export type HookClient = 'claude' | 'codex' | 'cursor' | 'gemini' | 'copilot' | 'opencode' | 'grok' | 'amp';
6
+ /** `start` sweeps missed transcripts, `end` uploads the one that just finished. */
7
+ export type HookEvent = 'start' | 'end' | 'sweep';
8
+ export declare const HOOK_CLIENTS: readonly HookClient[];
9
+ export declare function isHookClient(value: string): value is HookClient;
10
+ export interface HookInput {
11
+ event: string;
12
+ sessionId: string;
13
+ transcriptPath: string;
14
+ cwd: string;
15
+ }
16
+ /**
17
+ * Field names differ per client (Claude/Codex/Gemini: snake_case, Copilot:
18
+ * camelCase, Cursor: conversation_id + workspace_roots[]), so pick from lists.
19
+ */
20
+ export declare function parseHookInput(raw: string): HookInput;
21
+ export declare function normalizeEvent(name: string): HookEvent | null;
22
+ /** Transcript path first, then the host's environment. Cursor also exports
23
+ * CLAUDE_PROJECT_DIR as a compatibility alias, so it is tested before Claude. */
24
+ export declare function detectClient(transcriptPath: string, env: NodeJS.ProcessEnv): HookClient;
25
+ /** Ingest provider for a client. Clients without a Halyard parser upload as
26
+ * `other`: the raw log is kept and re-processed once a parser lands. */
27
+ export declare function providerForClient(client: HookClient): string;
28
+ export declare function isDirectory(path: string): boolean;
29
+ export declare function isNonEmptyFile(path: string): boolean;
30
+ /** First existing directory among the candidates, promoted to its git root. */
31
+ export declare function resolveProjectRoot(candidates: ReadonlyArray<string | undefined>, fallback: string): string;
32
+ /** Last `KEY=value` line of a dotenv file (quotes stripped), or ''. */
33
+ export declare function readDotenvVar(file: string, key: string): string;
34
+ /** Claude and Cursor name project dirs by the path with `/` and `.` → `-`. */
35
+ export declare function pathSlug(path: string): string;
36
+ //# sourceMappingURL=hook-input.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hook-input.d.ts","sourceRoot":"","sources":["../../src/lib/hook-input.ts"],"names":[],"mappings":"AAGA;;;GAGG;AAEH,MAAM,MAAM,UAAU,GAClB,QAAQ,GACR,OAAO,GACP,QAAQ,GACR,QAAQ,GACR,SAAS,GACT,UAAU,GACV,MAAM,GACN,KAAK,CAAA;AAET,mFAAmF;AACnF,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,KAAK,GAAG,OAAO,CAAA;AAEjD,eAAO,MAAM,YAAY,EAAE,SAAS,UAAU,EAS7C,CAAA;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,UAAU,CAE/D;AAED,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAA;IACb,SAAS,EAAE,MAAM,CAAA;IACjB,cAAc,EAAE,MAAM,CAAA;IACtB,GAAG,EAAE,MAAM,CAAA;CACZ;AAgBD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAqBrD;AAeD,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAK7D;AAUD;kFACkF;AAClF,wBAAgB,YAAY,CAAC,cAAc,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,UAAU,GAAG,UAAU,CAQvF;AAED;yEACyE;AACzE,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CAE5D;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAMjD;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAOpD;AAWD,+EAA+E;AAC/E,wBAAgB,kBAAkB,CAChC,UAAU,EAAE,aAAa,CAAC,MAAM,GAAG,SAAS,CAAC,EAC7C,QAAQ,EAAE,MAAM,GACf,MAAM,CAMR;AAUD,uEAAuE;AACvE,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAS/D;AAED,8EAA8E;AAC9E,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE7C"}
@@ -0,0 +1,161 @@
1
+ import { spawnSync } from 'node:child_process';
2
+ import { existsSync, readFileSync, statSync } from 'node:fs';
3
+ export const HOOK_CLIENTS = [
4
+ 'claude',
5
+ 'codex',
6
+ 'cursor',
7
+ 'gemini',
8
+ 'copilot',
9
+ 'opencode',
10
+ 'grok',
11
+ 'amp',
12
+ ];
13
+ export function isHookClient(value) {
14
+ return HOOK_CLIENTS.includes(value);
15
+ }
16
+ function asRecord(value) {
17
+ return value && typeof value === 'object' && !Array.isArray(value)
18
+ ? value
19
+ : {};
20
+ }
21
+ function pickString(record, keys) {
22
+ for (const key of keys) {
23
+ const value = record[key];
24
+ if (typeof value === 'string' && value.length > 0)
25
+ return value;
26
+ }
27
+ return '';
28
+ }
29
+ /**
30
+ * Field names differ per client (Claude/Codex/Gemini: snake_case, Copilot:
31
+ * camelCase, Cursor: conversation_id + workspace_roots[]), so pick from lists.
32
+ */
33
+ export function parseHookInput(raw) {
34
+ let record = {};
35
+ try {
36
+ record = asRecord(JSON.parse(raw));
37
+ }
38
+ catch {
39
+ record = {};
40
+ }
41
+ const roots = Array.isArray(record['workspace_roots']) ? record['workspace_roots'] : [];
42
+ const firstRoot = typeof roots[0] === 'string' ? roots[0] : '';
43
+ return {
44
+ event: pickString(record, ['hook_event_name', 'hookEventName', 'event', 'type']),
45
+ sessionId: pickString(record, [
46
+ 'session_id',
47
+ 'sessionId',
48
+ 'conversation_id',
49
+ 'thread_id',
50
+ 'threadId',
51
+ ]),
52
+ transcriptPath: pickString(record, ['transcript_path', 'transcriptPath']),
53
+ cwd: pickString(record, ['cwd', 'workspace_root', 'workspaceRoot', 'project_dir']) || firstRoot,
54
+ };
55
+ }
56
+ const START_EVENTS = new Set(['SessionStart', 'sessionStart', 'session_start', 'session.start']);
57
+ const END_EVENTS = new Set([
58
+ 'SessionEnd',
59
+ 'sessionEnd',
60
+ 'session_end',
61
+ 'session.end',
62
+ 'Stop',
63
+ 'stop',
64
+ 'session.idle',
65
+ 'agent-turn-complete',
66
+ 'agent.end',
67
+ ]);
68
+ export function normalizeEvent(name) {
69
+ if (name === 'sweep')
70
+ return 'sweep';
71
+ if (START_EVENTS.has(name))
72
+ return 'start';
73
+ if (END_EVENTS.has(name))
74
+ return 'end';
75
+ return null;
76
+ }
77
+ const CLIENT_BY_PATH = [
78
+ ['/.claude/', 'claude'],
79
+ ['/.codex/', 'codex'],
80
+ ['/.cursor/', 'cursor'],
81
+ ['/.gemini/', 'gemini'],
82
+ ['/.copilot/', 'copilot'],
83
+ ];
84
+ /** Transcript path first, then the host's environment. Cursor also exports
85
+ * CLAUDE_PROJECT_DIR as a compatibility alias, so it is tested before Claude. */
86
+ export function detectClient(transcriptPath, env) {
87
+ for (const [needle, client] of CLIENT_BY_PATH) {
88
+ if (transcriptPath.includes(needle))
89
+ return client;
90
+ }
91
+ if (env['CURSOR_PROJECT_DIR'] || env['CURSOR_VERSION'])
92
+ return 'cursor';
93
+ if (env['GEMINI_PROJECT_DIR'])
94
+ return 'gemini';
95
+ if (env['CODEX_CWD'] || env['CODEX_HOME'])
96
+ return 'codex';
97
+ return 'claude';
98
+ }
99
+ /** Ingest provider for a client. Clients without a Halyard parser upload as
100
+ * `other`: the raw log is kept and re-processed once a parser lands. */
101
+ export function providerForClient(client) {
102
+ return client === 'grok' || client === 'amp' ? 'other' : client;
103
+ }
104
+ export function isDirectory(path) {
105
+ try {
106
+ return statSync(path).isDirectory();
107
+ }
108
+ catch {
109
+ return false;
110
+ }
111
+ }
112
+ export function isNonEmptyFile(path) {
113
+ try {
114
+ const stat = statSync(path);
115
+ return stat.isFile() && stat.size > 0;
116
+ }
117
+ catch {
118
+ return false;
119
+ }
120
+ }
121
+ function gitToplevel(dir) {
122
+ const result = spawnSync('git', ['-C', dir, 'rev-parse', '--show-toplevel'], {
123
+ encoding: 'utf8',
124
+ stdio: ['ignore', 'pipe', 'ignore'],
125
+ });
126
+ const out = result.status === 0 ? result.stdout.trim() : '';
127
+ return out.length > 0 ? out : null;
128
+ }
129
+ /** First existing directory among the candidates, promoted to its git root. */
130
+ export function resolveProjectRoot(candidates, fallback) {
131
+ for (const candidate of candidates) {
132
+ if (!candidate || !isDirectory(candidate))
133
+ continue;
134
+ return gitToplevel(candidate) ?? candidate;
135
+ }
136
+ return fallback;
137
+ }
138
+ function unquote(value) {
139
+ const trimmed = value.trim();
140
+ const quoted = (trimmed.startsWith('"') && trimmed.endsWith('"')) ||
141
+ (trimmed.startsWith("'") && trimmed.endsWith("'"));
142
+ return quoted && trimmed.length >= 2 ? trimmed.slice(1, -1) : trimmed;
143
+ }
144
+ /** Last `KEY=value` line of a dotenv file (quotes stripped), or ''. */
145
+ export function readDotenvVar(file, key) {
146
+ if (!existsSync(file))
147
+ return '';
148
+ const pattern = new RegExp(`^\\s*(?:export\\s+)?${key}=(.*)$`);
149
+ let found = '';
150
+ for (const line of readFileSync(file, 'utf8').split('\n')) {
151
+ const match = pattern.exec(line.replace(/\r$/, ''));
152
+ if (match)
153
+ found = unquote(match[1] ?? '');
154
+ }
155
+ return found;
156
+ }
157
+ /** Claude and Cursor name project dirs by the path with `/` and `.` → `-`. */
158
+ export function pathSlug(path) {
159
+ return path.replace(/[/.]/g, '-');
160
+ }
161
+ //# sourceMappingURL=hook-input.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hook-input.js","sourceRoot":"","sources":["../../src/lib/hook-input.ts"],"names":[],"mappings":"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"}