@foothill/agent-move 1.0.6

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 (163) hide show
  1. package/.github/screenshot.png +0 -0
  2. package/README.md +266 -0
  3. package/bin/cli.js +229 -0
  4. package/package.json +53 -0
  5. package/packages/client/dist/assets/BufferResource-Ddjob236.js +185 -0
  6. package/packages/client/dist/assets/CanvasRenderer-B0w6SYyW.js +1 -0
  7. package/packages/client/dist/assets/Filter-NcMGuiK-.js +1 -0
  8. package/packages/client/dist/assets/RenderTargetSystem-DgAzY5_U.js +172 -0
  9. package/packages/client/dist/assets/WebGLRenderer-DUWXDPIX.js +156 -0
  10. package/packages/client/dist/assets/WebGPURenderer-C1HbrllR.js +41 -0
  11. package/packages/client/dist/assets/browserAll-CaF1Fl0O.js +14 -0
  12. package/packages/client/dist/assets/index-CMmR_RuS.css +1 -0
  13. package/packages/client/dist/assets/index-Dh8yWoLP.js +711 -0
  14. package/packages/client/dist/assets/webworkerAll-BJ6UhC7r.js +83 -0
  15. package/packages/client/dist/favicon.svg +27 -0
  16. package/packages/client/dist/index.html +167 -0
  17. package/packages/client/package.json +19 -0
  18. package/packages/server/dist/config.d.ts +12 -0
  19. package/packages/server/dist/config.d.ts.map +1 -0
  20. package/packages/server/dist/config.js +19 -0
  21. package/packages/server/dist/config.js.map +1 -0
  22. package/packages/server/dist/hooks/hook-event-manager.d.ts +39 -0
  23. package/packages/server/dist/hooks/hook-event-manager.d.ts.map +1 -0
  24. package/packages/server/dist/hooks/hook-event-manager.js +161 -0
  25. package/packages/server/dist/hooks/hook-event-manager.js.map +1 -0
  26. package/packages/server/dist/hooks/hook-installer.d.ts +14 -0
  27. package/packages/server/dist/hooks/hook-installer.d.ts.map +1 -0
  28. package/packages/server/dist/hooks/hook-installer.js +179 -0
  29. package/packages/server/dist/hooks/hook-installer.js.map +1 -0
  30. package/packages/server/dist/index.d.ts +4 -0
  31. package/packages/server/dist/index.d.ts.map +1 -0
  32. package/packages/server/dist/index.js +3544 -0
  33. package/packages/server/dist/index.js.map +1 -0
  34. package/packages/server/dist/routes/api.d.ts +4 -0
  35. package/packages/server/dist/routes/api.d.ts.map +1 -0
  36. package/packages/server/dist/routes/api.js +27 -0
  37. package/packages/server/dist/routes/api.js.map +1 -0
  38. package/packages/server/dist/state/activity-processor.d.ts +31 -0
  39. package/packages/server/dist/state/activity-processor.d.ts.map +1 -0
  40. package/packages/server/dist/state/activity-processor.js +417 -0
  41. package/packages/server/dist/state/activity-processor.js.map +1 -0
  42. package/packages/server/dist/state/agent-state-manager.d.ts +107 -0
  43. package/packages/server/dist/state/agent-state-manager.d.ts.map +1 -0
  44. package/packages/server/dist/state/agent-state-manager.js +1622 -0
  45. package/packages/server/dist/state/agent-state-manager.js.map +1 -0
  46. package/packages/server/dist/state/anomaly-detector.d.ts +23 -0
  47. package/packages/server/dist/state/anomaly-detector.d.ts.map +1 -0
  48. package/packages/server/dist/state/anomaly-detector.js +272 -0
  49. package/packages/server/dist/state/anomaly-detector.js.map +1 -0
  50. package/packages/server/dist/state/identity-manager.d.ts +31 -0
  51. package/packages/server/dist/state/identity-manager.d.ts.map +1 -0
  52. package/packages/server/dist/state/identity-manager.js +63 -0
  53. package/packages/server/dist/state/identity-manager.js.map +1 -0
  54. package/packages/server/dist/state/role-resolver.d.ts +23 -0
  55. package/packages/server/dist/state/role-resolver.d.ts.map +1 -0
  56. package/packages/server/dist/state/role-resolver.js +43 -0
  57. package/packages/server/dist/state/role-resolver.js.map +1 -0
  58. package/packages/server/dist/state/task-graph-manager.d.ts +31 -0
  59. package/packages/server/dist/state/task-graph-manager.d.ts.map +1 -0
  60. package/packages/server/dist/state/task-graph-manager.js +191 -0
  61. package/packages/server/dist/state/task-graph-manager.js.map +1 -0
  62. package/packages/server/dist/state/tool-chain-tracker.d.ts +23 -0
  63. package/packages/server/dist/state/tool-chain-tracker.d.ts.map +1 -0
  64. package/packages/server/dist/state/tool-chain-tracker.js +113 -0
  65. package/packages/server/dist/state/tool-chain-tracker.js.map +1 -0
  66. package/packages/server/dist/watcher/agent-watcher.d.ts +16 -0
  67. package/packages/server/dist/watcher/agent-watcher.d.ts.map +1 -0
  68. package/packages/server/dist/watcher/agent-watcher.js +0 -0
  69. package/packages/server/dist/watcher/agent-watcher.js.map +1 -0
  70. package/packages/server/dist/watcher/claude-paths.d.ts +32 -0
  71. package/packages/server/dist/watcher/claude-paths.d.ts.map +1 -0
  72. package/packages/server/dist/watcher/claude-paths.js +104 -0
  73. package/packages/server/dist/watcher/claude-paths.js.map +1 -0
  74. package/packages/server/dist/watcher/file-watcher.d.ts +17 -0
  75. package/packages/server/dist/watcher/file-watcher.d.ts.map +1 -0
  76. package/packages/server/dist/watcher/file-watcher.js +347 -0
  77. package/packages/server/dist/watcher/file-watcher.js.map +1 -0
  78. package/packages/server/dist/watcher/git-info.d.ts +3 -0
  79. package/packages/server/dist/watcher/git-info.d.ts.map +1 -0
  80. package/packages/server/dist/watcher/git-info.js +35 -0
  81. package/packages/server/dist/watcher/git-info.js.map +1 -0
  82. package/packages/server/dist/watcher/jsonl-parser.d.ts +21 -0
  83. package/packages/server/dist/watcher/jsonl-parser.d.ts.map +1 -0
  84. package/packages/server/dist/watcher/jsonl-parser.js +95 -0
  85. package/packages/server/dist/watcher/jsonl-parser.js.map +1 -0
  86. package/packages/server/dist/watcher/opencode/opencode-parser.d.ts +58 -0
  87. package/packages/server/dist/watcher/opencode/opencode-parser.d.ts.map +1 -0
  88. package/packages/server/dist/watcher/opencode/opencode-parser.js +256 -0
  89. package/packages/server/dist/watcher/opencode/opencode-parser.js.map +1 -0
  90. package/packages/server/dist/watcher/opencode/opencode-paths.d.ts +20 -0
  91. package/packages/server/dist/watcher/opencode/opencode-paths.d.ts.map +1 -0
  92. package/packages/server/dist/watcher/opencode/opencode-paths.js +35 -0
  93. package/packages/server/dist/watcher/opencode/opencode-paths.js.map +1 -0
  94. package/packages/server/dist/watcher/opencode/opencode-watcher.d.ts +49 -0
  95. package/packages/server/dist/watcher/opencode/opencode-watcher.d.ts.map +1 -0
  96. package/packages/server/dist/watcher/opencode/opencode-watcher.js +1292 -0
  97. package/packages/server/dist/watcher/opencode/opencode-watcher.js.map +1 -0
  98. package/packages/server/dist/watcher/session-scanner.d.ts +7 -0
  99. package/packages/server/dist/watcher/session-scanner.d.ts.map +1 -0
  100. package/packages/server/dist/watcher/session-scanner.js +69 -0
  101. package/packages/server/dist/watcher/session-scanner.js.map +1 -0
  102. package/packages/server/dist/ws/broadcaster.d.ts +18 -0
  103. package/packages/server/dist/ws/broadcaster.d.ts.map +1 -0
  104. package/packages/server/dist/ws/broadcaster.js +152 -0
  105. package/packages/server/dist/ws/broadcaster.js.map +1 -0
  106. package/packages/server/dist/ws/ws-handler.d.ts +6 -0
  107. package/packages/server/dist/ws/ws-handler.d.ts.map +1 -0
  108. package/packages/server/dist/ws/ws-handler.js +55 -0
  109. package/packages/server/dist/ws/ws-handler.js.map +1 -0
  110. package/packages/server/package.json +25 -0
  111. package/packages/shared/dist/constants/colors.d.ts +46 -0
  112. package/packages/shared/dist/constants/colors.d.ts.map +1 -0
  113. package/packages/shared/dist/constants/colors.js +178 -0
  114. package/packages/shared/dist/constants/colors.js.map +1 -0
  115. package/packages/shared/dist/constants/names.d.ts +6 -0
  116. package/packages/shared/dist/constants/names.d.ts.map +1 -0
  117. package/packages/shared/dist/constants/names.js +28 -0
  118. package/packages/shared/dist/constants/names.js.map +1 -0
  119. package/packages/shared/dist/constants/tools.d.ts +15 -0
  120. package/packages/shared/dist/constants/tools.d.ts.map +1 -0
  121. package/packages/shared/dist/constants/tools.js +120 -0
  122. package/packages/shared/dist/constants/tools.js.map +1 -0
  123. package/packages/shared/dist/constants/zones.d.ts +37 -0
  124. package/packages/shared/dist/constants/zones.d.ts.map +1 -0
  125. package/packages/shared/dist/constants/zones.js +128 -0
  126. package/packages/shared/dist/constants/zones.js.map +1 -0
  127. package/packages/shared/dist/index.d.ts +15 -0
  128. package/packages/shared/dist/index.d.ts.map +1 -0
  129. package/packages/shared/dist/index.js +7 -0
  130. package/packages/shared/dist/index.js.map +1 -0
  131. package/packages/shared/dist/types/agent.d.ts +85 -0
  132. package/packages/shared/dist/types/agent.d.ts.map +1 -0
  133. package/packages/shared/dist/types/agent.js +2 -0
  134. package/packages/shared/dist/types/agent.js.map +1 -0
  135. package/packages/shared/dist/types/anomaly.d.ts +18 -0
  136. package/packages/shared/dist/types/anomaly.d.ts.map +1 -0
  137. package/packages/shared/dist/types/anomaly.js +6 -0
  138. package/packages/shared/dist/types/anomaly.js.map +1 -0
  139. package/packages/shared/dist/types/hooks.d.ts +51 -0
  140. package/packages/shared/dist/types/hooks.d.ts.map +1 -0
  141. package/packages/shared/dist/types/hooks.js +2 -0
  142. package/packages/shared/dist/types/hooks.js.map +1 -0
  143. package/packages/shared/dist/types/jsonl.d.ts +62 -0
  144. package/packages/shared/dist/types/jsonl.d.ts.map +1 -0
  145. package/packages/shared/dist/types/jsonl.js +3 -0
  146. package/packages/shared/dist/types/jsonl.js.map +1 -0
  147. package/packages/shared/dist/types/task-graph.d.ts +20 -0
  148. package/packages/shared/dist/types/task-graph.d.ts.map +1 -0
  149. package/packages/shared/dist/types/task-graph.js +2 -0
  150. package/packages/shared/dist/types/task-graph.js.map +1 -0
  151. package/packages/shared/dist/types/tool-chain.d.ts +17 -0
  152. package/packages/shared/dist/types/tool-chain.d.ts.map +1 -0
  153. package/packages/shared/dist/types/tool-chain.js +2 -0
  154. package/packages/shared/dist/types/tool-chain.js.map +1 -0
  155. package/packages/shared/dist/types/websocket.d.ts +132 -0
  156. package/packages/shared/dist/types/websocket.d.ts.map +1 -0
  157. package/packages/shared/dist/types/websocket.js +2 -0
  158. package/packages/shared/dist/types/websocket.js.map +1 -0
  159. package/packages/shared/dist/types/zone.d.ts +21 -0
  160. package/packages/shared/dist/types/zone.d.ts.map +1 -0
  161. package/packages/shared/dist/types/zone.js +2 -0
  162. package/packages/shared/dist/types/zone.js.map +1 -0
  163. package/packages/shared/package.json +15 -0
@@ -0,0 +1,347 @@
1
+ // dist/watcher/file-watcher.js
2
+ import chokidar from "chokidar";
3
+ import { stat as stat2, open } from "fs/promises";
4
+ import { join as join4, basename } from "path";
5
+ import { existsSync } from "fs";
6
+ import { join } from "path";
7
+ import { readdir, stat } from "fs/promises";
8
+ import { join as join3 } from "path";
9
+ import { homedir } from "os";
10
+ import { join as join2 } from "path";
11
+ var JsonlParser = class {
12
+ parseLine(line) {
13
+ try {
14
+ const msg = JSON.parse(line);
15
+ return this.extractActivity(msg);
16
+ } catch {
17
+ return null;
18
+ }
19
+ }
20
+ extractActivity(msg) {
21
+ const sessionId = msg.sessionId;
22
+ if (msg.toolUseResult?.routing?.sender) {
23
+ const agentName = msg.toolUseResult.routing.sender;
24
+ if (msg.message?.role === "user" || msg.type === "user") {
25
+ return {
26
+ type: "text",
27
+ text: void 0,
28
+ agentName,
29
+ sessionId
30
+ };
31
+ }
32
+ }
33
+ if ((msg.message?.role === "user" || msg.type === "user") && msg.message?.content) {
34
+ const content2 = typeof msg.message.content === "string" ? msg.message.content : Array.isArray(msg.message.content) ? msg.message.content.map((b) => b.text ?? "").join("") : "";
35
+ if (content2.includes("<teammate-message")) {
36
+ const senderMatch = content2.match(/<teammate-message\s+teammate_id="([^"]+)"/);
37
+ if (senderMatch) {
38
+ return {
39
+ type: "text",
40
+ text: void 0,
41
+ messageSender: senderMatch[1],
42
+ sessionId
43
+ };
44
+ }
45
+ }
46
+ }
47
+ if (!msg.message?.content || !Array.isArray(msg.message.content)) {
48
+ return null;
49
+ }
50
+ if (msg.message.role !== "assistant") {
51
+ return null;
52
+ }
53
+ const content = msg.message.content;
54
+ for (const block of content) {
55
+ if (block.type === "tool_use") {
56
+ const toolBlock = block;
57
+ return {
58
+ type: "tool_use",
59
+ toolName: toolBlock.name,
60
+ toolInput: toolBlock.input,
61
+ model: msg.message.model,
62
+ sessionId,
63
+ inputTokens: msg.message.usage?.input_tokens,
64
+ outputTokens: msg.message.usage?.output_tokens,
65
+ cacheReadTokens: msg.message.usage?.cache_read_input_tokens,
66
+ cacheCreationTokens: msg.message.usage?.cache_creation_input_tokens
67
+ };
68
+ }
69
+ }
70
+ for (const block of content) {
71
+ if (block.type === "text") {
72
+ const textBlock = block;
73
+ const text = textBlock.text.trim();
74
+ if (text.length > 0 && text.length < 200) {
75
+ return {
76
+ type: "text",
77
+ text,
78
+ model: msg.message.model,
79
+ sessionId,
80
+ inputTokens: msg.message.usage?.input_tokens,
81
+ outputTokens: msg.message.usage?.output_tokens,
82
+ cacheReadTokens: msg.message.usage?.cache_read_input_tokens,
83
+ cacheCreationTokens: msg.message.usage?.cache_creation_input_tokens
84
+ };
85
+ }
86
+ }
87
+ }
88
+ if (msg.message.usage) {
89
+ return {
90
+ type: "token_usage",
91
+ inputTokens: msg.message.usage.input_tokens,
92
+ outputTokens: msg.message.usage.output_tokens,
93
+ cacheReadTokens: msg.message.usage.cache_read_input_tokens,
94
+ cacheCreationTokens: msg.message.usage.cache_creation_input_tokens,
95
+ model: msg.message.model,
96
+ sessionId
97
+ };
98
+ }
99
+ return null;
100
+ }
101
+ };
102
+ var ClaudePaths = class {
103
+ /**
104
+ * Parse a JSONL session file path to extract project info.
105
+ * Paths look like: ~/.claude/projects/{encoded-project-path}/{sessionId}.jsonl
106
+ * Subagent paths may be nested deeper.
107
+ */
108
+ parseSessionPath(filePath) {
109
+ const normalized = filePath.replace(/\\/g, "/");
110
+ const parts = normalized.split("/");
111
+ const projectsIdx = parts.indexOf("projects");
112
+ if (projectsIdx === -1 || projectsIdx + 1 >= parts.length) {
113
+ return {
114
+ projectPath: "unknown",
115
+ projectName: "Unknown",
116
+ isSubagent: false,
117
+ projectDir: "unknown",
118
+ parentSessionId: null
119
+ };
120
+ }
121
+ const encodedProjectName = parts[projectsIdx + 1];
122
+ const projectName = this.decodeProjectName(encodedProjectName);
123
+ const depthAfterProject = parts.length - projectsIdx - 2;
124
+ const isSubagent = depthAfterProject > 1;
125
+ const parentSessionId = isSubagent ? parts[projectsIdx + 2] : null;
126
+ return {
127
+ projectPath: encodedProjectName,
128
+ projectName,
129
+ isSubagent,
130
+ projectDir: encodedProjectName,
131
+ parentSessionId
132
+ };
133
+ }
134
+ /**
135
+ * Decode Claude Code's encoded project path format.
136
+ * Resolves against the filesystem to correctly handle dashes in folder names.
137
+ * e.g., "C--projects-fts-temp-agent-move" → "agent-move"
138
+ */
139
+ decodeProjectName(encoded) {
140
+ const resolved = this.resolveToFolderName(encoded);
141
+ if (resolved)
142
+ return resolved;
143
+ const parts = encoded.split("-").filter((p) => p.length > 0);
144
+ if (parts.length <= 2)
145
+ return parts.join("/");
146
+ return parts.slice(-2).join("/");
147
+ }
148
+ /**
149
+ * Greedily resolve the encoded path against the filesystem.
150
+ * Tries each dash-segment as a directory, joining multiple segments
151
+ * when a single one doesn't exist (to handle dashes in folder names).
152
+ */
153
+ resolveToFolderName(encoded) {
154
+ try {
155
+ let root;
156
+ let rest;
157
+ const driveMatch = encoded.match(/^([A-Za-z])--(.*)/);
158
+ const unixMatch = !driveMatch && encoded.match(/^-(.*)/);
159
+ if (driveMatch) {
160
+ root = driveMatch[1] + ":/";
161
+ rest = driveMatch[2];
162
+ } else if (unixMatch) {
163
+ root = "/";
164
+ rest = unixMatch[1];
165
+ } else {
166
+ return null;
167
+ }
168
+ const parts = rest.split("-").filter(Boolean);
169
+ let currentPath = root;
170
+ let lastName = "";
171
+ let i = 0;
172
+ while (i < parts.length) {
173
+ let found = false;
174
+ const maxLen = Math.min(parts.length - i, 6);
175
+ for (let len = 1; len <= maxLen; len++) {
176
+ const segment = parts.slice(i, i + len).join("-");
177
+ for (const prefix of ["", "."]) {
178
+ const testPath = join(currentPath, prefix + segment);
179
+ if (existsSync(testPath)) {
180
+ currentPath = testPath;
181
+ lastName = prefix + segment;
182
+ i += len;
183
+ found = true;
184
+ break;
185
+ }
186
+ }
187
+ if (found)
188
+ break;
189
+ }
190
+ if (!found)
191
+ break;
192
+ }
193
+ return lastName || null;
194
+ } catch {
195
+ return null;
196
+ }
197
+ }
198
+ };
199
+ var claudePaths = new ClaudePaths();
200
+ var config = {
201
+ port: parseInt(process.env.AGENT_MOVE_PORT || "3333", 10),
202
+ claudeHome: join2(homedir(), ".claude"),
203
+ idleTimeoutMs: 45e3,
204
+ /** How long after going idle before an agent is automatically shutdown/removed */
205
+ shutdownTimeoutMs: 30 * 60 * 1e3,
206
+ // 30 minutes
207
+ /** How recently a session file must be modified to be considered "active" on startup */
208
+ activeThresholdMs: 10 * 60 * 1e3,
209
+ // 10 minutes
210
+ /** Enable OpenCode session watching (auto-detected if storage dir exists) */
211
+ enableOpenCode: process.env.AGENT_MOVE_OPENCODE !== "false"
212
+ };
213
+ var SessionScanner = class {
214
+ claudeHome;
215
+ constructor(claudeHome) {
216
+ this.claudeHome = claudeHome;
217
+ }
218
+ /** Find all recently active JSONL session files */
219
+ async scan() {
220
+ const results = [];
221
+ const projectsDir = join3(this.claudeHome, "projects");
222
+ try {
223
+ const projects = await readdir(projectsDir);
224
+ const now = Date.now();
225
+ for (const project of projects) {
226
+ const projectDir = join3(projectsDir, project);
227
+ try {
228
+ const projectStat = await stat(projectDir);
229
+ if (!projectStat.isDirectory())
230
+ continue;
231
+ const files = await readdir(projectDir);
232
+ let newestFile = null;
233
+ let newestMtime = 0;
234
+ for (const file of files) {
235
+ if (!file.endsWith(".jsonl"))
236
+ continue;
237
+ const filePath = join3(projectDir, file);
238
+ try {
239
+ const fileStat = await stat(filePath);
240
+ if (now - fileStat.mtimeMs < config.activeThresholdMs) {
241
+ if (fileStat.mtimeMs > newestMtime) {
242
+ newestMtime = fileStat.mtimeMs;
243
+ newestFile = filePath;
244
+ }
245
+ }
246
+ } catch {
247
+ }
248
+ }
249
+ if (newestFile) {
250
+ results.push(newestFile);
251
+ }
252
+ } catch {
253
+ }
254
+ }
255
+ } catch {
256
+ console.log("No projects directory found \u2014 will wait for new sessions");
257
+ }
258
+ return results;
259
+ }
260
+ };
261
+ var FileWatcher = class {
262
+ claudeHome;
263
+ stateManager;
264
+ watcher = null;
265
+ byteOffsets = /* @__PURE__ */ new Map();
266
+ parser = new JsonlParser();
267
+ /** Per-file lock to prevent concurrent processFile calls for the same file */
268
+ fileLocks = /* @__PURE__ */ new Map();
269
+ constructor(claudeHome, stateManager) {
270
+ this.claudeHome = claudeHome;
271
+ this.stateManager = stateManager;
272
+ }
273
+ async start() {
274
+ const scanner = new SessionScanner(this.claudeHome);
275
+ const existingFiles = await scanner.scan();
276
+ for (const file of existingFiles) {
277
+ await this.processFile(file);
278
+ }
279
+ const pattern = join4(this.claudeHome, "projects", "**", "*.jsonl");
280
+ this.watcher = chokidar.watch(pattern, {
281
+ persistent: true,
282
+ ignoreInitial: true,
283
+ awaitWriteFinish: { stabilityThreshold: 200, pollInterval: 50 }
284
+ });
285
+ this.watcher.on("add", (filePath) => {
286
+ console.log(`New session file: ${filePath}`);
287
+ this.processFile(filePath);
288
+ });
289
+ this.watcher.on("change", (filePath) => {
290
+ this.processFile(filePath);
291
+ });
292
+ console.log(`Watching for JSONL files in ${this.claudeHome}/projects/`);
293
+ }
294
+ stop() {
295
+ this.watcher?.close();
296
+ this.byteOffsets.clear();
297
+ this.fileLocks.clear();
298
+ }
299
+ processFile(filePath) {
300
+ const prev = this.fileLocks.get(filePath) ?? Promise.resolve();
301
+ const next = prev.then(() => this.doProcessFile(filePath)).catch(() => {
302
+ }).finally(() => {
303
+ if (this.fileLocks.get(filePath) === next) {
304
+ this.fileLocks.delete(filePath);
305
+ }
306
+ });
307
+ this.fileLocks.set(filePath, next);
308
+ }
309
+ async doProcessFile(filePath) {
310
+ try {
311
+ const fileStats = await stat2(filePath);
312
+ const currentOffset = this.byteOffsets.get(filePath) ?? 0;
313
+ if (fileStats.size <= currentOffset)
314
+ return;
315
+ const handle = await open(filePath, "r");
316
+ try {
317
+ const buffer = Buffer.alloc(fileStats.size - currentOffset);
318
+ await handle.read(buffer, 0, buffer.length, currentOffset);
319
+ this.byteOffsets.set(filePath, fileStats.size);
320
+ const newContent = buffer.toString("utf-8");
321
+ const lines = newContent.split("\n").filter((l) => l.trim());
322
+ const sessionId = basename(filePath, ".jsonl");
323
+ const sessionInfo = claudePaths.parseSessionPath(filePath);
324
+ let hadParsedActivity = false;
325
+ for (const line of lines) {
326
+ const parsed = this.parser.parseLine(line);
327
+ if (parsed) {
328
+ hadParsedActivity = true;
329
+ this.stateManager.processMessage(sessionId, parsed, sessionInfo);
330
+ }
331
+ }
332
+ if (!hadParsedActivity && lines.length > 0) {
333
+ this.stateManager.heartbeat(sessionId);
334
+ }
335
+ } finally {
336
+ await handle.close();
337
+ }
338
+ } catch (err) {
339
+ if (err.code !== "ENOENT") {
340
+ console.error(`Error processing ${filePath}:`, err);
341
+ }
342
+ }
343
+ }
344
+ };
345
+ export {
346
+ FileWatcher
347
+ };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-watcher.js","sourceRoot":"","sources":["../../src/watcher/file-watcher.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ /** Get the current git branch for a project path, with caching */
2
+ export declare function getGitBranch(projectPath: string): string | null;
3
+ //# sourceMappingURL=git-info.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git-info.d.ts","sourceRoot":"","sources":["../../src/watcher/git-info.ts"],"names":[],"mappings":"AAMA,kEAAkE;AAClE,wBAAgB,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAkB/D"}
@@ -0,0 +1,35 @@
1
+ // dist/watcher/git-info.js
2
+ import { execSync } from "child_process";
3
+ var branchCache = /* @__PURE__ */ new Map();
4
+ var CACHE_TTL = 3e4;
5
+ var MAX_CACHE_SIZE = 100;
6
+ function getGitBranch(projectPath) {
7
+ const cached = branchCache.get(projectPath);
8
+ if (cached && Date.now() - cached.ts < CACHE_TTL)
9
+ return cached.branch;
10
+ try {
11
+ const branch = execSync("git rev-parse --abbrev-ref HEAD", {
12
+ cwd: projectPath,
13
+ timeout: 5e3,
14
+ encoding: "utf-8",
15
+ stdio: ["ignore", "pipe", "ignore"]
16
+ }).trim() || null;
17
+ branchCache.set(projectPath, { branch, ts: Date.now() });
18
+ pruneCache();
19
+ return branch;
20
+ } catch {
21
+ branchCache.set(projectPath, { branch: null, ts: Date.now() });
22
+ return null;
23
+ }
24
+ }
25
+ function pruneCache() {
26
+ if (branchCache.size <= MAX_CACHE_SIZE)
27
+ return;
28
+ const entries = [...branchCache.entries()].sort((a, b) => a[1].ts - b[1].ts);
29
+ const toRemove = entries.slice(0, branchCache.size - MAX_CACHE_SIZE);
30
+ for (const [key] of toRemove)
31
+ branchCache.delete(key);
32
+ }
33
+ export {
34
+ getGitBranch
35
+ };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git-info.js","sourceRoot":"","sources":["../../src/watcher/git-info.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEzC,MAAM,WAAW,GAAG,IAAI,GAAG,EAAiD,CAAC;AAC7E,MAAM,SAAS,GAAG,MAAM,CAAC,CAAC,MAAM;AAChC,MAAM,cAAc,GAAG,GAAG,CAAC;AAE3B,kEAAkE;AAClE,MAAM,UAAU,YAAY,CAAC,WAAmB;IAC9C,MAAM,MAAM,GAAG,WAAW,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IAC5C,IAAI,MAAM,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,MAAM,CAAC,EAAE,GAAG,SAAS;QAAE,OAAO,MAAM,CAAC,MAAM,CAAC;IAEvE,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,QAAQ,CAAC,iCAAiC,EAAE;YACzD,GAAG,EAAE,WAAW;YAChB,OAAO,EAAE,IAAI;YACb,QAAQ,EAAE,OAAO;YACjB,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC;SACpC,CAAC,CAAC,IAAI,EAAE,IAAI,IAAI,CAAC;QAClB,WAAW,CAAC,GAAG,CAAC,WAAW,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;QACzD,UAAU,EAAE,CAAC;QACb,OAAO,MAAM,CAAC;IAChB,CAAC;IAAC,MAAM,CAAC;QACP,WAAW,CAAC,GAAG,CAAC,WAAW,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;QAC/D,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAS,UAAU;IACjB,IAAI,WAAW,CAAC,IAAI,IAAI,cAAc;QAAE,OAAO;IAC/C,wBAAwB;IACxB,MAAM,OAAO,GAAG,CAAC,GAAG,WAAW,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IAC7E,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,WAAW,CAAC,IAAI,GAAG,cAAc,CAAC,CAAC;IACrE,KAAK,MAAM,CAAC,GAAG,CAAC,IAAI,QAAQ;QAAE,WAAW,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;AACxD,CAAC"}
@@ -0,0 +1,21 @@
1
+ export interface ParsedActivity {
2
+ type: 'tool_use' | 'text' | 'token_usage';
3
+ toolName?: string;
4
+ toolInput?: Record<string, unknown>;
5
+ text?: string;
6
+ inputTokens?: number;
7
+ outputTokens?: number;
8
+ cacheReadTokens?: number;
9
+ cacheCreationTokens?: number;
10
+ model?: string;
11
+ sessionId?: string;
12
+ /** Logical agent name discovered from SendMessage routing */
13
+ agentName?: string;
14
+ /** Sender name from <teammate-message teammate_id="X"> tags */
15
+ messageSender?: string;
16
+ }
17
+ export declare class JsonlParser {
18
+ parseLine(line: string): ParsedActivity | null;
19
+ private extractActivity;
20
+ }
21
+ //# sourceMappingURL=jsonl-parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jsonl-parser.d.ts","sourceRoot":"","sources":["../../src/watcher/jsonl-parser.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,UAAU,GAAG,MAAM,GAAG,aAAa,CAAC;IAC1C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6DAA6D;IAC7D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,+DAA+D;IAC/D,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,qBAAa,WAAW;IACtB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI;IAS9C,OAAO,CAAC,eAAe;CAsGxB"}
@@ -0,0 +1,95 @@
1
+ // dist/watcher/jsonl-parser.js
2
+ var JsonlParser = class {
3
+ parseLine(line) {
4
+ try {
5
+ const msg = JSON.parse(line);
6
+ return this.extractActivity(msg);
7
+ } catch {
8
+ return null;
9
+ }
10
+ }
11
+ extractActivity(msg) {
12
+ const sessionId = msg.sessionId;
13
+ if (msg.toolUseResult?.routing?.sender) {
14
+ const agentName = msg.toolUseResult.routing.sender;
15
+ if (msg.message?.role === "user" || msg.type === "user") {
16
+ return {
17
+ type: "text",
18
+ text: void 0,
19
+ agentName,
20
+ sessionId
21
+ };
22
+ }
23
+ }
24
+ if ((msg.message?.role === "user" || msg.type === "user") && msg.message?.content) {
25
+ const content2 = typeof msg.message.content === "string" ? msg.message.content : Array.isArray(msg.message.content) ? msg.message.content.map((b) => b.text ?? "").join("") : "";
26
+ if (content2.includes("<teammate-message")) {
27
+ const senderMatch = content2.match(/<teammate-message\s+teammate_id="([^"]+)"/);
28
+ if (senderMatch) {
29
+ return {
30
+ type: "text",
31
+ text: void 0,
32
+ messageSender: senderMatch[1],
33
+ sessionId
34
+ };
35
+ }
36
+ }
37
+ }
38
+ if (!msg.message?.content || !Array.isArray(msg.message.content)) {
39
+ return null;
40
+ }
41
+ if (msg.message.role !== "assistant") {
42
+ return null;
43
+ }
44
+ const content = msg.message.content;
45
+ for (const block of content) {
46
+ if (block.type === "tool_use") {
47
+ const toolBlock = block;
48
+ return {
49
+ type: "tool_use",
50
+ toolName: toolBlock.name,
51
+ toolInput: toolBlock.input,
52
+ model: msg.message.model,
53
+ sessionId,
54
+ inputTokens: msg.message.usage?.input_tokens,
55
+ outputTokens: msg.message.usage?.output_tokens,
56
+ cacheReadTokens: msg.message.usage?.cache_read_input_tokens,
57
+ cacheCreationTokens: msg.message.usage?.cache_creation_input_tokens
58
+ };
59
+ }
60
+ }
61
+ for (const block of content) {
62
+ if (block.type === "text") {
63
+ const textBlock = block;
64
+ const text = textBlock.text.trim();
65
+ if (text.length > 0 && text.length < 200) {
66
+ return {
67
+ type: "text",
68
+ text,
69
+ model: msg.message.model,
70
+ sessionId,
71
+ inputTokens: msg.message.usage?.input_tokens,
72
+ outputTokens: msg.message.usage?.output_tokens,
73
+ cacheReadTokens: msg.message.usage?.cache_read_input_tokens,
74
+ cacheCreationTokens: msg.message.usage?.cache_creation_input_tokens
75
+ };
76
+ }
77
+ }
78
+ }
79
+ if (msg.message.usage) {
80
+ return {
81
+ type: "token_usage",
82
+ inputTokens: msg.message.usage.input_tokens,
83
+ outputTokens: msg.message.usage.output_tokens,
84
+ cacheReadTokens: msg.message.usage.cache_read_input_tokens,
85
+ cacheCreationTokens: msg.message.usage.cache_creation_input_tokens,
86
+ model: msg.message.model,
87
+ sessionId
88
+ };
89
+ }
90
+ return null;
91
+ }
92
+ };
93
+ export {
94
+ JsonlParser
95
+ };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jsonl-parser.js","sourceRoot":"","sources":["../../src/watcher/jsonl-parser.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,58 @@
1
+ import type { ParsedActivity } from '../jsonl-parser.js';
2
+ export interface OpenCodeMessageData {
3
+ id: string;
4
+ sessionID: string;
5
+ role: 'assistant' | 'user';
6
+ tokens?: {
7
+ input?: number;
8
+ output?: number;
9
+ cache?: {
10
+ read?: number;
11
+ write?: number;
12
+ };
13
+ };
14
+ modelID?: string;
15
+ /** Agent preset name (e.g. "build", "research") */
16
+ agent?: string;
17
+ }
18
+ interface ToolState {
19
+ status: 'pending' | 'running' | 'completed' | 'error';
20
+ input?: Record<string, unknown>;
21
+ title?: string;
22
+ }
23
+ interface ToolPart {
24
+ type: 'tool';
25
+ callID: string;
26
+ tool: string;
27
+ state: ToolState;
28
+ }
29
+ interface TextPart {
30
+ type: 'text';
31
+ text: string;
32
+ synthetic?: boolean;
33
+ }
34
+ interface ReasoningPart {
35
+ type: 'reasoning';
36
+ text: string;
37
+ }
38
+ type Part = ToolPart | TextPart | ReasoningPart | {
39
+ type: string;
40
+ };
41
+ export declare class OpenCodeParser {
42
+ /**
43
+ * Convert an OpenCode part JSON object into a ParsedActivity.
44
+ * All tool names and input field names are normalized to canonical form
45
+ * so downstream code (activity-processor, TOOL_ZONE_MAP, etc.) needs no
46
+ * agent-specific branches.
47
+ *
48
+ * Returns null for parts that carry no actionable activity.
49
+ */
50
+ parsePart(partData: Part, messageData?: OpenCodeMessageData): ParsedActivity | null;
51
+ /**
52
+ * Emit token usage from an assistant message row.
53
+ * Called once per assistant message.
54
+ */
55
+ parseTokenUsage(messageData: OpenCodeMessageData): ParsedActivity | null;
56
+ }
57
+ export {};
58
+ //# sourceMappingURL=opencode-parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"opencode-parser.d.ts","sourceRoot":"","sources":["../../../src/watcher/opencode/opencode-parser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAKzD,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,WAAW,GAAG,MAAM,CAAC;IAC3B,MAAM,CAAC,EAAE;QACP,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,KAAK,CAAC,EAAE;YAAE,IAAI,CAAC,EAAE,MAAM,CAAC;YAAC,KAAK,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;KAC3C,CAAC;IACF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,mDAAmD;IACnD,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAID,UAAU,SAAS;IACjB,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,OAAO,CAAC;IACtD,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,UAAU,QAAQ;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,SAAS,CAAC;CAClB;AAED,UAAU,QAAQ;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,UAAU,aAAa;IACrB,IAAI,EAAE,WAAW,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,KAAK,IAAI,GAAG,QAAQ,GAAG,QAAQ,GAAG,aAAa,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAEnE,qBAAa,cAAc;IACzB;;;;;;;OAOG;IACH,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,WAAW,CAAC,EAAE,mBAAmB,GAAG,cAAc,GAAG,IAAI;IAiDnF;;;OAGG;IACH,eAAe,CAAC,WAAW,EAAE,mBAAmB,GAAG,cAAc,GAAG,IAAI;CAezE"}