@ai-devkit/agent-manager 0.35.0 → 0.36.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 (92) hide show
  1. package/dist/__tests__/adapters/AntigravityCliAdapter.test.js +381 -0
  2. package/dist/__tests__/adapters/AntigravityCliAdapter.test.js.map +1 -0
  3. package/dist/__tests__/adapters/KiroAdapter.test.js +607 -0
  4. package/dist/__tests__/adapters/KiroAdapter.test.js.map +1 -0
  5. package/dist/__tests__/capacity/claude.test.js +485 -0
  6. package/dist/__tests__/capacity/claude.test.js.map +1 -0
  7. package/dist/__tests__/capacity/openai.test.js +672 -0
  8. package/dist/__tests__/capacity/openai.test.js.map +1 -0
  9. package/dist/__tests__/capacity/wham.test.js +144 -0
  10. package/dist/__tests__/capacity/wham.test.js.map +1 -0
  11. package/dist/__tests__/utils/agents.test.js +6 -0
  12. package/dist/__tests__/utils/agents.test.js.map +1 -1
  13. package/dist/adapters/AgentAdapter.d.ts +1 -1
  14. package/dist/adapters/AgentAdapter.d.ts.map +1 -1
  15. package/dist/adapters/AgentAdapter.js.map +1 -1
  16. package/dist/adapters/AntigravityCliAdapter.d.ts +57 -0
  17. package/dist/adapters/AntigravityCliAdapter.d.ts.map +1 -0
  18. package/dist/adapters/AntigravityCliAdapter.js +273 -0
  19. package/dist/adapters/AntigravityCliAdapter.js.map +1 -0
  20. package/dist/adapters/KiroAdapter.d.ts +46 -0
  21. package/dist/adapters/KiroAdapter.d.ts.map +1 -0
  22. package/dist/adapters/KiroAdapter.js +344 -0
  23. package/dist/adapters/KiroAdapter.js.map +1 -0
  24. package/dist/adapters/index.d.ts +2 -0
  25. package/dist/adapters/index.d.ts.map +1 -1
  26. package/dist/adapters/index.js +2 -0
  27. package/dist/adapters/index.js.map +1 -1
  28. package/dist/capacity/claude.d.ts +17 -0
  29. package/dist/capacity/claude.d.ts.map +1 -0
  30. package/dist/capacity/claude.js +271 -0
  31. package/dist/capacity/claude.js.map +1 -0
  32. package/dist/capacity/codex.d.ts +1 -2
  33. package/dist/capacity/codex.d.ts.map +1 -1
  34. package/dist/capacity/codex.js +5 -47
  35. package/dist/capacity/codex.js.map +1 -1
  36. package/dist/capacity/index.d.ts +11 -0
  37. package/dist/capacity/index.d.ts.map +1 -1
  38. package/dist/capacity/index.js +17 -0
  39. package/dist/capacity/index.js.map +1 -1
  40. package/dist/capacity/openai.d.ts +48 -0
  41. package/dist/capacity/openai.d.ts.map +1 -0
  42. package/dist/capacity/openai.js +312 -0
  43. package/dist/capacity/openai.js.map +1 -0
  44. package/dist/capacity/wham.d.ts +16 -0
  45. package/dist/capacity/wham.d.ts.map +1 -0
  46. package/dist/capacity/wham.js +66 -0
  47. package/dist/capacity/wham.js.map +1 -0
  48. package/dist/index.d.ts +4 -2
  49. package/dist/index.d.ts.map +1 -1
  50. package/dist/index.js +3 -1
  51. package/dist/index.js.map +1 -1
  52. package/dist/readiness/AgentReadiness.d.ts +1 -1
  53. package/dist/readiness/AgentReadiness.d.ts.map +1 -1
  54. package/dist/readiness/AgentReadiness.js.map +1 -1
  55. package/dist/runtime/ManagedAgentRuntime.js +3 -1
  56. package/dist/runtime/ManagedAgentRuntime.js.map +1 -1
  57. package/dist/runtime/herdr/HerdrAgentDiscovery.js +10 -0
  58. package/dist/runtime/herdr/HerdrAgentDiscovery.js.map +1 -1
  59. package/dist/utils/agents.d.ts +1 -1
  60. package/dist/utils/agents.d.ts.map +1 -1
  61. package/dist/utils/agents.js +11 -0
  62. package/dist/utils/agents.js.map +1 -1
  63. package/package.json +1 -1
  64. package/src/__tests__/adapters/AntigravityCliAdapter.test.ts +324 -0
  65. package/src/__tests__/adapters/KiroAdapter.test.ts +534 -0
  66. package/src/__tests__/capacity/claude.test.ts +467 -0
  67. package/src/__tests__/capacity/fixtures/claude-credentials.json +7 -0
  68. package/src/__tests__/capacity/fixtures/claude-usage-malformed.json +1 -0
  69. package/src/__tests__/capacity/fixtures/claude-usage-partial.json +15 -0
  70. package/src/__tests__/capacity/fixtures/claude-usage.json +63 -0
  71. package/src/__tests__/capacity/fixtures/openai-auth.json +6 -0
  72. package/src/__tests__/capacity/fixtures/openai-codex-auth.json +9 -0
  73. package/src/__tests__/capacity/fixtures/openai-usage-completions.json +67 -0
  74. package/src/__tests__/capacity/fixtures/openai-usage-responses.json +20 -0
  75. package/src/__tests__/capacity/fixtures/wham-usage.json +32 -0
  76. package/src/__tests__/capacity/openai.test.ts +570 -0
  77. package/src/__tests__/capacity/wham.test.ts +104 -0
  78. package/src/__tests__/utils/agents.test.ts +7 -0
  79. package/src/adapters/AgentAdapter.ts +2 -0
  80. package/src/adapters/AntigravityCliAdapter.ts +356 -0
  81. package/src/adapters/KiroAdapter.ts +456 -0
  82. package/src/adapters/index.ts +2 -0
  83. package/src/capacity/claude.ts +313 -0
  84. package/src/capacity/codex.ts +25 -134
  85. package/src/capacity/index.ts +33 -4
  86. package/src/capacity/openai.ts +361 -0
  87. package/src/capacity/wham.ts +84 -0
  88. package/src/index.ts +10 -1
  89. package/src/readiness/AgentReadiness.ts +4 -1
  90. package/src/runtime/ManagedAgentRuntime.ts +2 -0
  91. package/src/runtime/herdr/HerdrAgentDiscovery.ts +5 -1
  92. package/src/utils/agents.ts +11 -1
@@ -0,0 +1,607 @@
1
+ /**
2
+ * Tests for KiroAdapter
3
+ */ import * as fs from "fs";
4
+ import * as os from "os";
5
+ import * as path from "path";
6
+ import { KiroAdapter } from "../../adapters/KiroAdapter.js";
7
+ import { AgentStatus } from "../../adapters/AgentAdapter.js";
8
+ import { listAgentProcesses, enrichProcesses, captureProcessSnapshot } from "../../utils/process.js";
9
+ import { generateAgentName } from "../../utils/matching.js";
10
+ vi.mock("../../utils/process.js", async (importOriginal)=>{
11
+ const actual = await importOriginal();
12
+ return {
13
+ ...actual,
14
+ listAgentProcesses: vi.fn(),
15
+ enrichProcesses: vi.fn(),
16
+ captureProcessSnapshot: vi.fn()
17
+ };
18
+ });
19
+ vi.mock("../../utils/matching.js", async (importOriginal)=>{
20
+ const actual = await importOriginal();
21
+ return {
22
+ ...actual,
23
+ generateAgentName: vi.fn()
24
+ };
25
+ });
26
+ const mockedListAgentProcesses = listAgentProcesses;
27
+ const mockedEnrichProcesses = enrichProcesses;
28
+ const mockedCaptureProcessSnapshot = captureProcessSnapshot;
29
+ const mockedGenerateAgentName = generateAgentName;
30
+ describe("KiroAdapter", ()=>{
31
+ let adapter;
32
+ let tmpHome;
33
+ let sessionsDir;
34
+ beforeEach(()=>{
35
+ tmpHome = fs.mkdtempSync(path.join(os.tmpdir(), "kiro-adapter-test-"));
36
+ process.env.HOME = tmpHome;
37
+ sessionsDir = path.join(tmpHome, ".kiro", "sessions", "cli");
38
+ fs.mkdirSync(sessionsDir, {
39
+ recursive: true
40
+ });
41
+ adapter = new KiroAdapter();
42
+ mockedListAgentProcesses.mockReset();
43
+ mockedEnrichProcesses.mockReset();
44
+ mockedCaptureProcessSnapshot.mockReset();
45
+ mockedGenerateAgentName.mockReset();
46
+ mockedEnrichProcesses.mockImplementation((procs)=>procs);
47
+ // Compatibility shim for standalone adapter discovery; the manager captures once and slices by name.
48
+ mockedCaptureProcessSnapshot.mockImplementation(async (names)=>enrichProcesses(names.flatMap((name)=>listAgentProcesses(name))));
49
+ mockedGenerateAgentName.mockImplementation((cwd, pid)=>{
50
+ const folder = path.basename(cwd) || "unknown";
51
+ return `${folder} (${pid})`;
52
+ });
53
+ });
54
+ afterEach(()=>{
55
+ fs.rmSync(tmpHome, {
56
+ recursive: true,
57
+ force: true
58
+ });
59
+ });
60
+ describe("initialization", ()=>{
61
+ it("exposes the kiro type and process names", ()=>{
62
+ expect(adapter.type).toBe("kiro");
63
+ expect(adapter.processNames).toEqual([
64
+ "kiro-cli",
65
+ "kiro",
66
+ "kiro-cli-chat",
67
+ "node"
68
+ ]);
69
+ });
70
+ });
71
+ describe("canHandle", ()=>{
72
+ it("identifies Kiro commands without matching unrelated paths", ()=>{
73
+ expect(adapter.canHandle({
74
+ pid: 1,
75
+ command: "kiro-cli",
76
+ cwd: "/repo",
77
+ tty: "ttys001"
78
+ })).toBe(true);
79
+ expect(adapter.canHandle({
80
+ pid: 2,
81
+ command: "/usr/local/bin/kiro --model x",
82
+ cwd: "/repo",
83
+ tty: "ttys002"
84
+ })).toBe(true);
85
+ expect(adapter.canHandle({
86
+ pid: 3,
87
+ command: "node /opt/kiro/bin/kiro-cli.js",
88
+ cwd: "/repo",
89
+ tty: "ttys003"
90
+ })).toBe(true);
91
+ expect(adapter.canHandle({
92
+ pid: 4,
93
+ command: "node /repo/feature-kiro-adapter/script.js",
94
+ cwd: "/repo",
95
+ tty: "ttys004"
96
+ })).toBe(false);
97
+ expect(adapter.canHandle({
98
+ pid: 5,
99
+ command: "kiro-cli chat",
100
+ cwd: "/repo",
101
+ tty: "ttys005"
102
+ })).toBe(true);
103
+ expect(adapter.canHandle({
104
+ pid: 6,
105
+ command: "bun /opt/kiro/bin/kiro-cli.js",
106
+ cwd: "/repo",
107
+ tty: "ttys006"
108
+ })).toBe(true);
109
+ expect(adapter.canHandle({
110
+ pid: 7,
111
+ command: "node /usr/local/bin/ai-devkit agent start --type kiro",
112
+ cwd: "/repo",
113
+ tty: "ttys007"
114
+ })).toBe(false);
115
+ expect(adapter.canHandle({
116
+ pid: 8,
117
+ command: "node server.js --name kiro",
118
+ cwd: "/repo",
119
+ tty: "ttys008"
120
+ })).toBe(false);
121
+ expect(adapter.canHandle({
122
+ pid: 9,
123
+ command: "kiro-cli-chat acp",
124
+ cwd: "/repo",
125
+ tty: "ttys009"
126
+ })).toBe(false);
127
+ });
128
+ });
129
+ describe("detectAgents", ()=>{
130
+ it("returns [] when there are no Kiro processes", async ()=>{
131
+ mockedListAgentProcesses.mockReturnValue([]);
132
+ expect(await adapter.detectAgents()).toEqual([]);
133
+ });
134
+ it("maps a running Kiro process through its session lock and metadata", async ()=>{
135
+ const cwd = "/repo/project-a";
136
+ const proc = makeProcess({
137
+ pid: 101,
138
+ cwd: "/process/cwd"
139
+ });
140
+ const updatedAt = new Date().toISOString();
141
+ const sessionFile = writeKiroSession("sess-101", cwd, [
142
+ prompt("implement Kiro adapter", 1781098057),
143
+ assistantText("working on it")
144
+ ], 101, updatedAt);
145
+ mockedCaptureProcessSnapshot.mockResolvedValue([
146
+ proc
147
+ ]);
148
+ const agents = await adapter.detectAgents();
149
+ expect(agents).toHaveLength(1);
150
+ expect(agents[0]).toMatchObject({
151
+ type: "kiro",
152
+ pid: 101,
153
+ projectPath: cwd,
154
+ sessionId: "sess-101",
155
+ summary: "implement Kiro adapter",
156
+ status: AgentStatus.WAITING,
157
+ sessionFilePath: sessionFile,
158
+ lastActive: new Date(updatedAt)
159
+ });
160
+ });
161
+ it("matches a lock held by a kiro-cli-chat acp descendant when bun is not collected", async ()=>{
162
+ const cwd = "/repo/project-a";
163
+ const sessionFile = writeKiroSession("sess-acp", cwd, [
164
+ prompt("implement Kiro adapter", 1781098057),
165
+ assistantText("working on it")
166
+ ], 55236);
167
+ const kiro = makeProcess({
168
+ pid: 55111,
169
+ command: "kiro-cli",
170
+ cwd: "/process/cwd",
171
+ ppid: 1
172
+ });
173
+ const chat = makeProcess({
174
+ pid: 55168,
175
+ command: "kiro-cli-chat chat",
176
+ ppid: 55111,
177
+ tty: "ttys001"
178
+ });
179
+ const acp = makeProcess({
180
+ pid: 55236,
181
+ command: "kiro-cli-chat acp",
182
+ ppid: 55198,
183
+ tty: "ttys001"
184
+ });
185
+ mockedCaptureProcessSnapshot.mockResolvedValue([
186
+ kiro,
187
+ chat,
188
+ acp
189
+ ]);
190
+ const agents = await adapter.detectAgents();
191
+ expect(agents).toEqual([
192
+ expect.objectContaining({
193
+ type: "kiro",
194
+ pid: 55111,
195
+ projectPath: cwd,
196
+ sessionId: "sess-acp",
197
+ summary: "implement Kiro adapter",
198
+ sessionFilePath: sessionFile
199
+ })
200
+ ]);
201
+ });
202
+ it("walks a collected kiro-cli-chat parent chain to the owning kiro-cli", async ()=>{
203
+ const sessionFile = writeKiroSession("sess-owner", "/repo/owner", [
204
+ prompt("owned session", 1781098057)
205
+ ], 55236);
206
+ const owner = makeProcess({
207
+ pid: 55111,
208
+ command: "kiro-cli",
209
+ cwd: "/repo/owner",
210
+ ppid: 1
211
+ });
212
+ const other = makeProcess({
213
+ pid: 66111,
214
+ command: "kiro-cli",
215
+ cwd: "/repo/other",
216
+ ppid: 1
217
+ });
218
+ const chat = makeProcess({
219
+ pid: 55168,
220
+ command: "kiro-cli-chat chat",
221
+ ppid: 55111
222
+ });
223
+ const acp = makeProcess({
224
+ pid: 55236,
225
+ command: "kiro-cli-chat acp",
226
+ ppid: 55168
227
+ });
228
+ mockedCaptureProcessSnapshot.mockResolvedValue([
229
+ owner,
230
+ other,
231
+ chat,
232
+ acp
233
+ ]);
234
+ const agents = await adapter.detectAgents();
235
+ expect(agents).toEqual([
236
+ expect.objectContaining({
237
+ pid: 55111,
238
+ projectPath: "/repo/owner",
239
+ sessionId: "sess-owner",
240
+ sessionFilePath: sessionFile
241
+ }),
242
+ expect.objectContaining({
243
+ pid: 66111,
244
+ sessionId: "pid-66111"
245
+ })
246
+ ]);
247
+ });
248
+ it("does not attach a session through tty ?? or an ambiguous tty", async ()=>{
249
+ writeKiroSession("sess-unknown-tty", "/repo/unknown", [
250
+ prompt("hello", 1781098057)
251
+ ], 55236);
252
+ const unknownTty = makeProcess({
253
+ pid: 55111,
254
+ command: "kiro-cli",
255
+ tty: "??",
256
+ ppid: 1
257
+ });
258
+ const unknownAcp = makeProcess({
259
+ pid: 55236,
260
+ command: "kiro-cli-chat acp",
261
+ tty: "??",
262
+ ppid: 55198
263
+ });
264
+ mockedCaptureProcessSnapshot.mockResolvedValue([
265
+ unknownTty,
266
+ unknownAcp
267
+ ]);
268
+ expect(await adapter.detectAgents()).toEqual([
269
+ expect.objectContaining({
270
+ pid: 55111,
271
+ sessionId: "pid-55111"
272
+ })
273
+ ]);
274
+ writeKiroSession("sess-shared-tty", "/repo/shared", [
275
+ prompt("hello", 1781098057)
276
+ ], 66236);
277
+ const first = makeProcess({
278
+ pid: 55111,
279
+ command: "kiro-cli",
280
+ tty: "ttys001",
281
+ ppid: 1
282
+ });
283
+ const second = makeProcess({
284
+ pid: 66111,
285
+ command: "kiro-cli",
286
+ tty: "ttys001",
287
+ ppid: 1
288
+ });
289
+ const sharedAcp = makeProcess({
290
+ pid: 66236,
291
+ command: "kiro-cli-chat acp",
292
+ tty: "ttys001",
293
+ ppid: 55198
294
+ });
295
+ mockedCaptureProcessSnapshot.mockResolvedValue([
296
+ first,
297
+ second,
298
+ sharedAcp
299
+ ]);
300
+ expect(await adapter.detectAgents()).toEqual([
301
+ expect.objectContaining({
302
+ pid: 55111,
303
+ sessionId: "pid-55111"
304
+ }),
305
+ expect.objectContaining({
306
+ pid: 66111,
307
+ sessionId: "pid-66111"
308
+ })
309
+ ]);
310
+ });
311
+ it("uses a supplied process snapshot instead of scanning again", async ()=>{
312
+ const proc = makeProcess({
313
+ pid: 606,
314
+ cwd: "/repo/context"
315
+ });
316
+ mockedCaptureProcessSnapshot.mockResolvedValue([
317
+ makeProcess({
318
+ pid: 999
319
+ })
320
+ ]);
321
+ const agents = await adapter.detectAgents({
322
+ processes: [
323
+ proc
324
+ ]
325
+ });
326
+ expect(mockedCaptureProcessSnapshot).not.toHaveBeenCalled();
327
+ expect(agents).toEqual([
328
+ expect.objectContaining({
329
+ pid: 606,
330
+ projectPath: "/repo/context",
331
+ sessionId: "pid-606"
332
+ })
333
+ ]);
334
+ });
335
+ it("uses only a lock whose PID belongs to a running Kiro process", async ()=>{
336
+ writeKiroSession("ended-session", "/repo/ended", [
337
+ prompt("old conversation", 1781098057)
338
+ ]);
339
+ writeKiroSession("other-process", "/repo/other", [
340
+ prompt("other conversation", 1781098057)
341
+ ], 999);
342
+ const proc = makeProcess({
343
+ pid: 202,
344
+ cwd: "/repo/current"
345
+ });
346
+ mockedCaptureProcessSnapshot.mockResolvedValue([
347
+ proc
348
+ ]);
349
+ const agents = await adapter.detectAgents();
350
+ expect(agents).toEqual([
351
+ expect.objectContaining({
352
+ pid: 202,
353
+ projectPath: "/repo/current",
354
+ sessionId: "pid-202",
355
+ summary: "Kiro process running"
356
+ })
357
+ ]);
358
+ });
359
+ it("ignores malformed lock files", async ()=>{
360
+ writeKiroSession("bad-lock", "/repo/project", [
361
+ prompt("hello", 1781098057)
362
+ ]);
363
+ fs.writeFileSync(path.join(sessionsDir, "bad-lock.lock"), "{bad json");
364
+ const proc = makeProcess({
365
+ pid: 303,
366
+ cwd: "/repo/project"
367
+ });
368
+ mockedCaptureProcessSnapshot.mockResolvedValue([
369
+ proc
370
+ ]);
371
+ const agents = await adapter.detectAgents();
372
+ expect(agents[0]).toMatchObject({
373
+ sessionId: "pid-303"
374
+ });
375
+ });
376
+ it("reports running while the latest assistant event invokes a tool", async ()=>{
377
+ writeKiroSession("tool-session", "/repo/project", [
378
+ prompt("inspect the file", Math.floor(Date.now() / 1000)),
379
+ assistantTool("fs_read", {
380
+ path: "/repo/project/file.ts"
381
+ })
382
+ ], 404, new Date().toISOString());
383
+ const proc = makeProcess({
384
+ pid: 404,
385
+ cwd: "/repo/project"
386
+ });
387
+ mockedCaptureProcessSnapshot.mockResolvedValue([
388
+ proc
389
+ ]);
390
+ const agents = await adapter.detectAgents();
391
+ expect(agents[0].status).toBe(AgentStatus.RUNNING);
392
+ });
393
+ it("returns a process-only agent when the locked transcript is missing", async ()=>{
394
+ fs.writeFileSync(path.join(sessionsDir, "missing.lock"), JSON.stringify({
395
+ pid: 505
396
+ }));
397
+ const proc = makeProcess({
398
+ pid: 505,
399
+ cwd: "/repo/project-e"
400
+ });
401
+ mockedCaptureProcessSnapshot.mockResolvedValue([
402
+ proc
403
+ ]);
404
+ const agents = await adapter.detectAgents();
405
+ expect(agents).toEqual([
406
+ expect.objectContaining({
407
+ type: "kiro",
408
+ status: AgentStatus.RUNNING,
409
+ pid: 505,
410
+ projectPath: "/repo/project-e",
411
+ sessionId: "pid-505",
412
+ summary: "Kiro process running"
413
+ })
414
+ ]);
415
+ });
416
+ });
417
+ describe("getConversation", ()=>{
418
+ it("reads real Kiro prompt and assistant message envelopes", ()=>{
419
+ const sessionFile = writeKiroSession("conversation", "/repo/project-f", [
420
+ prompt("hello kiro", 1781098057),
421
+ assistantText("Hello! How can I help?"),
422
+ "{not json"
423
+ ]);
424
+ expect(adapter.getConversation(sessionFile)).toEqual([
425
+ {
426
+ role: "user",
427
+ content: "hello kiro",
428
+ timestamp: "2026-06-10T13:27:37.000Z"
429
+ },
430
+ {
431
+ role: "assistant",
432
+ content: "Hello! How can I help?",
433
+ timestamp: undefined
434
+ }
435
+ ]);
436
+ });
437
+ it("includes Kiro tool use and results only in verbose conversation mode", ()=>{
438
+ const sessionFile = writeKiroSession("tools", "/repo/project-tools", [
439
+ prompt("read package.json", 1781098057),
440
+ assistantTool("fs_read", {
441
+ path: "package.json"
442
+ }),
443
+ toolResult("contents", "success"),
444
+ assistantText("Done.")
445
+ ]);
446
+ expect(adapter.getConversation(sessionFile)).toEqual([
447
+ {
448
+ role: "user",
449
+ content: "read package.json",
450
+ timestamp: "2026-06-10T13:27:37.000Z"
451
+ },
452
+ {
453
+ role: "assistant",
454
+ content: "Done.",
455
+ timestamp: undefined
456
+ }
457
+ ]);
458
+ expect(adapter.getConversation(sessionFile, {
459
+ verbose: true
460
+ })).toEqual([
461
+ {
462
+ role: "user",
463
+ content: "read package.json",
464
+ timestamp: "2026-06-10T13:27:37.000Z"
465
+ },
466
+ {
467
+ role: "assistant",
468
+ content: '[Tool: fs_read] {"path":"package.json"}',
469
+ timestamp: undefined
470
+ },
471
+ {
472
+ role: "system",
473
+ content: "[Tool Result] contents",
474
+ timestamp: undefined
475
+ },
476
+ {
477
+ role: "assistant",
478
+ content: "Done.",
479
+ timestamp: undefined
480
+ }
481
+ ]);
482
+ });
483
+ });
484
+ describe("listSessions", ()=>{
485
+ it("lists historical sessions using metadata and applies cwd filtering", async ()=>{
486
+ const matchingCwd = "/repo/project-g";
487
+ const matchingSession = writeKiroSession("sess-g", matchingCwd, [
488
+ prompt("first matching message", 1781098057),
489
+ assistantText("response")
490
+ ]);
491
+ writeKiroSession("sess-h", "/repo/project-h", [
492
+ prompt("other message", 1781098057)
493
+ ]);
494
+ const sessions = await adapter.listSessions({
495
+ cwd: matchingCwd
496
+ });
497
+ expect(sessions).toEqual([
498
+ expect.objectContaining({
499
+ type: "kiro",
500
+ sessionId: "sess-g",
501
+ cwd: matchingCwd,
502
+ firstUserMessage: "first matching message",
503
+ startedAt: new Date("2026-06-10T13:27:17.000Z"),
504
+ lastActive: new Date("2026-06-10T13:27:40.000Z"),
505
+ sessionFilePath: matchingSession
506
+ })
507
+ ]);
508
+ });
509
+ });
510
+ function makeProcess(overrides) {
511
+ return {
512
+ pid: 1,
513
+ command: "kiro-cli chat",
514
+ cwd: "/repo",
515
+ tty: "ttys001",
516
+ startTime: new Date("2026-06-10T13:27:17.000Z"),
517
+ ...overrides
518
+ };
519
+ }
520
+ function writeKiroSession(sessionId, cwd, entries, pid, updatedAt = "2026-06-10T13:27:40.000Z") {
521
+ fs.writeFileSync(path.join(sessionsDir, `${sessionId}.json`), JSON.stringify({
522
+ session_id: sessionId,
523
+ cwd,
524
+ created_at: "2026-06-10T13:27:17.000Z",
525
+ updated_at: updatedAt,
526
+ title: "Session title"
527
+ }));
528
+ const filePath = path.join(sessionsDir, `${sessionId}.jsonl`);
529
+ fs.writeFileSync(filePath, entries.map((entry)=>typeof entry === "string" ? entry : JSON.stringify(entry)).join("\n"));
530
+ if (pid !== undefined) {
531
+ fs.writeFileSync(path.join(sessionsDir, `${sessionId}.lock`), JSON.stringify({
532
+ pid,
533
+ started_at: "2026-06-10T13:27:17.000Z"
534
+ }));
535
+ }
536
+ return filePath;
537
+ }
538
+ function prompt(text, timestamp) {
539
+ return {
540
+ version: "v1",
541
+ kind: "Prompt",
542
+ data: {
543
+ content: [
544
+ {
545
+ kind: "text",
546
+ data: text
547
+ }
548
+ ],
549
+ meta: {
550
+ timestamp
551
+ }
552
+ }
553
+ };
554
+ }
555
+ function assistantText(text) {
556
+ return {
557
+ version: "v1",
558
+ kind: "AssistantMessage",
559
+ data: {
560
+ content: [
561
+ {
562
+ kind: "text",
563
+ data: text
564
+ }
565
+ ]
566
+ }
567
+ };
568
+ }
569
+ function assistantTool(name, input) {
570
+ return {
571
+ version: "v1",
572
+ kind: "AssistantMessage",
573
+ data: {
574
+ content: [
575
+ {
576
+ kind: "toolUse",
577
+ data: {
578
+ toolUseId: "tool-1",
579
+ name,
580
+ input
581
+ }
582
+ }
583
+ ]
584
+ }
585
+ };
586
+ }
587
+ function toolResult(result, status) {
588
+ return {
589
+ version: "v1",
590
+ kind: "ToolResults",
591
+ data: {
592
+ content: [
593
+ {
594
+ kind: "toolResult",
595
+ data: {
596
+ toolUseId: "tool-1",
597
+ status,
598
+ result
599
+ }
600
+ }
601
+ ]
602
+ }
603
+ };
604
+ }
605
+ });
606
+
607
+ //# sourceMappingURL=KiroAdapter.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/__tests__/adapters/KiroAdapter.test.ts"],"sourcesContent":["/**\n * Tests for KiroAdapter\n */\n\nimport type { MockedFunction } from \"vitest\";\nimport * as fs from \"fs\";\nimport * as os from \"os\";\nimport * as path from \"path\";\n\nimport { KiroAdapter } from \"../../adapters/KiroAdapter.js\";\nimport type { ProcessInfo } from \"../../adapters/AgentAdapter.js\";\nimport { AgentStatus } from \"../../adapters/AgentAdapter.js\";\nimport {\n listAgentProcesses,\n enrichProcesses,\n captureProcessSnapshot,\n} from \"../../utils/process.js\";\nimport { generateAgentName } from \"../../utils/matching.js\";\n\nvi.mock(\"../../utils/process.js\", async (importOriginal) => {\n const actual = (await importOriginal()) as typeof import(\"../../utils/process.js\");\n return {\n ...actual,\n listAgentProcesses: vi.fn(),\n enrichProcesses: vi.fn(),\n captureProcessSnapshot: vi.fn(),\n };\n});\n\nvi.mock(\"../../utils/matching.js\", async (importOriginal) => {\n const actual = (await importOriginal()) as typeof import(\"../../utils/matching.js\");\n return {\n ...actual,\n generateAgentName: vi.fn(),\n };\n});\n\nconst mockedListAgentProcesses = listAgentProcesses as MockedFunction<typeof listAgentProcesses>;\nconst mockedEnrichProcesses = enrichProcesses as MockedFunction<typeof enrichProcesses>;\nconst mockedCaptureProcessSnapshot = captureProcessSnapshot as MockedFunction<\n typeof captureProcessSnapshot\n>;\nconst mockedGenerateAgentName = generateAgentName as MockedFunction<typeof generateAgentName>;\n\ndescribe(\"KiroAdapter\", () => {\n let adapter: KiroAdapter;\n let tmpHome: string;\n let sessionsDir: string;\n\n beforeEach(() => {\n tmpHome = fs.mkdtempSync(path.join(os.tmpdir(), \"kiro-adapter-test-\"));\n process.env.HOME = tmpHome;\n sessionsDir = path.join(tmpHome, \".kiro\", \"sessions\", \"cli\");\n fs.mkdirSync(sessionsDir, { recursive: true });\n\n adapter = new KiroAdapter();\n\n mockedListAgentProcesses.mockReset();\n mockedEnrichProcesses.mockReset();\n mockedCaptureProcessSnapshot.mockReset();\n mockedGenerateAgentName.mockReset();\n\n mockedEnrichProcesses.mockImplementation((procs) => procs);\n // Compatibility shim for standalone adapter discovery; the manager captures once and slices by name.\n mockedCaptureProcessSnapshot.mockImplementation(async (names) =>\n enrichProcesses(names.flatMap((name) => listAgentProcesses(name))),\n );\n mockedGenerateAgentName.mockImplementation((cwd: string, pid: number) => {\n const folder = path.basename(cwd) || \"unknown\";\n return `${folder} (${pid})`;\n });\n });\n\n afterEach(() => {\n fs.rmSync(tmpHome, { recursive: true, force: true });\n });\n\n describe(\"initialization\", () => {\n it(\"exposes the kiro type and process names\", () => {\n expect(adapter.type).toBe(\"kiro\");\n expect(adapter.processNames).toEqual([\"kiro-cli\", \"kiro\", \"kiro-cli-chat\", \"node\"]);\n });\n });\n\n describe(\"canHandle\", () => {\n it(\"identifies Kiro commands without matching unrelated paths\", () => {\n expect(adapter.canHandle({ pid: 1, command: \"kiro-cli\", cwd: \"/repo\", tty: \"ttys001\" })).toBe(\n true,\n );\n expect(\n adapter.canHandle({\n pid: 2,\n command: \"/usr/local/bin/kiro --model x\",\n cwd: \"/repo\",\n tty: \"ttys002\",\n }),\n ).toBe(true);\n expect(\n adapter.canHandle({\n pid: 3,\n command: \"node /opt/kiro/bin/kiro-cli.js\",\n cwd: \"/repo\",\n tty: \"ttys003\",\n }),\n ).toBe(true);\n expect(\n adapter.canHandle({\n pid: 4,\n command: \"node /repo/feature-kiro-adapter/script.js\",\n cwd: \"/repo\",\n tty: \"ttys004\",\n }),\n ).toBe(false);\n expect(\n adapter.canHandle({\n pid: 5,\n command: \"kiro-cli chat\",\n cwd: \"/repo\",\n tty: \"ttys005\",\n }),\n ).toBe(true);\n expect(\n adapter.canHandle({\n pid: 6,\n command: \"bun /opt/kiro/bin/kiro-cli.js\",\n cwd: \"/repo\",\n tty: \"ttys006\",\n }),\n ).toBe(true);\n expect(\n adapter.canHandle({\n pid: 7,\n command: \"node /usr/local/bin/ai-devkit agent start --type kiro\",\n cwd: \"/repo\",\n tty: \"ttys007\",\n }),\n ).toBe(false);\n expect(\n adapter.canHandle({\n pid: 8,\n command: \"node server.js --name kiro\",\n cwd: \"/repo\",\n tty: \"ttys008\",\n }),\n ).toBe(false);\n expect(\n adapter.canHandle({\n pid: 9,\n command: \"kiro-cli-chat acp\",\n cwd: \"/repo\",\n tty: \"ttys009\",\n }),\n ).toBe(false);\n });\n });\n\n describe(\"detectAgents\", () => {\n it(\"returns [] when there are no Kiro processes\", async () => {\n mockedListAgentProcesses.mockReturnValue([]);\n expect(await adapter.detectAgents()).toEqual([]);\n });\n\n it(\"maps a running Kiro process through its session lock and metadata\", async () => {\n const cwd = \"/repo/project-a\";\n const proc = makeProcess({ pid: 101, cwd: \"/process/cwd\" });\n const updatedAt = new Date().toISOString();\n const sessionFile = writeKiroSession(\n \"sess-101\",\n cwd,\n [prompt(\"implement Kiro adapter\", 1781098057), assistantText(\"working on it\")],\n 101,\n updatedAt,\n );\n mockedCaptureProcessSnapshot.mockResolvedValue([proc]);\n\n const agents = await adapter.detectAgents();\n\n expect(agents).toHaveLength(1);\n expect(agents[0]).toMatchObject({\n type: \"kiro\",\n pid: 101,\n projectPath: cwd,\n sessionId: \"sess-101\",\n summary: \"implement Kiro adapter\",\n status: AgentStatus.WAITING,\n sessionFilePath: sessionFile,\n lastActive: new Date(updatedAt),\n });\n });\n\n it(\"matches a lock held by a kiro-cli-chat acp descendant when bun is not collected\", async () => {\n const cwd = \"/repo/project-a\";\n const sessionFile = writeKiroSession(\n \"sess-acp\",\n cwd,\n [prompt(\"implement Kiro adapter\", 1781098057), assistantText(\"working on it\")],\n 55236,\n );\n const kiro = makeProcess({ pid: 55111, command: \"kiro-cli\", cwd: \"/process/cwd\", ppid: 1 });\n const chat = makeProcess({\n pid: 55168,\n command: \"kiro-cli-chat chat\",\n ppid: 55111,\n tty: \"ttys001\",\n });\n const acp = makeProcess({\n pid: 55236,\n command: \"kiro-cli-chat acp\",\n ppid: 55198,\n tty: \"ttys001\",\n });\n mockedCaptureProcessSnapshot.mockResolvedValue([kiro, chat, acp]);\n\n const agents = await adapter.detectAgents();\n\n expect(agents).toEqual([\n expect.objectContaining({\n type: \"kiro\",\n pid: 55111,\n projectPath: cwd,\n sessionId: \"sess-acp\",\n summary: \"implement Kiro adapter\",\n sessionFilePath: sessionFile,\n }),\n ]);\n });\n\n it(\"walks a collected kiro-cli-chat parent chain to the owning kiro-cli\", async () => {\n const sessionFile = writeKiroSession(\n \"sess-owner\",\n \"/repo/owner\",\n [prompt(\"owned session\", 1781098057)],\n 55236,\n );\n const owner = makeProcess({ pid: 55111, command: \"kiro-cli\", cwd: \"/repo/owner\", ppid: 1 });\n const other = makeProcess({ pid: 66111, command: \"kiro-cli\", cwd: \"/repo/other\", ppid: 1 });\n const chat = makeProcess({ pid: 55168, command: \"kiro-cli-chat chat\", ppid: 55111 });\n const acp = makeProcess({ pid: 55236, command: \"kiro-cli-chat acp\", ppid: 55168 });\n mockedCaptureProcessSnapshot.mockResolvedValue([owner, other, chat, acp]);\n\n const agents = await adapter.detectAgents();\n\n expect(agents).toEqual([\n expect.objectContaining({\n pid: 55111,\n projectPath: \"/repo/owner\",\n sessionId: \"sess-owner\",\n sessionFilePath: sessionFile,\n }),\n expect.objectContaining({ pid: 66111, sessionId: \"pid-66111\" }),\n ]);\n });\n\n it(\"does not attach a session through tty ?? or an ambiguous tty\", async () => {\n writeKiroSession(\"sess-unknown-tty\", \"/repo/unknown\", [prompt(\"hello\", 1781098057)], 55236);\n const unknownTty = makeProcess({ pid: 55111, command: \"kiro-cli\", tty: \"??\", ppid: 1 });\n const unknownAcp = makeProcess({\n pid: 55236,\n command: \"kiro-cli-chat acp\",\n tty: \"??\",\n ppid: 55198,\n });\n mockedCaptureProcessSnapshot.mockResolvedValue([unknownTty, unknownAcp]);\n\n expect(await adapter.detectAgents()).toEqual([\n expect.objectContaining({ pid: 55111, sessionId: \"pid-55111\" }),\n ]);\n\n writeKiroSession(\"sess-shared-tty\", \"/repo/shared\", [prompt(\"hello\", 1781098057)], 66236);\n const first = makeProcess({ pid: 55111, command: \"kiro-cli\", tty: \"ttys001\", ppid: 1 });\n const second = makeProcess({ pid: 66111, command: \"kiro-cli\", tty: \"ttys001\", ppid: 1 });\n const sharedAcp = makeProcess({\n pid: 66236,\n command: \"kiro-cli-chat acp\",\n tty: \"ttys001\",\n ppid: 55198,\n });\n mockedCaptureProcessSnapshot.mockResolvedValue([first, second, sharedAcp]);\n\n expect(await adapter.detectAgents()).toEqual([\n expect.objectContaining({ pid: 55111, sessionId: \"pid-55111\" }),\n expect.objectContaining({ pid: 66111, sessionId: \"pid-66111\" }),\n ]);\n });\n\n it(\"uses a supplied process snapshot instead of scanning again\", async () => {\n const proc = makeProcess({ pid: 606, cwd: \"/repo/context\" });\n mockedCaptureProcessSnapshot.mockResolvedValue([makeProcess({ pid: 999 })]);\n\n const agents = await adapter.detectAgents({ processes: [proc] });\n\n expect(mockedCaptureProcessSnapshot).not.toHaveBeenCalled();\n expect(agents).toEqual([\n expect.objectContaining({\n pid: 606,\n projectPath: \"/repo/context\",\n sessionId: \"pid-606\",\n }),\n ]);\n });\n\n it(\"uses only a lock whose PID belongs to a running Kiro process\", async () => {\n writeKiroSession(\"ended-session\", \"/repo/ended\", [prompt(\"old conversation\", 1781098057)]);\n writeKiroSession(\n \"other-process\",\n \"/repo/other\",\n [prompt(\"other conversation\", 1781098057)],\n 999,\n );\n const proc = makeProcess({ pid: 202, cwd: \"/repo/current\" });\n mockedCaptureProcessSnapshot.mockResolvedValue([proc]);\n\n const agents = await adapter.detectAgents();\n\n expect(agents).toEqual([\n expect.objectContaining({\n pid: 202,\n projectPath: \"/repo/current\",\n sessionId: \"pid-202\",\n summary: \"Kiro process running\",\n }),\n ]);\n });\n\n it(\"ignores malformed lock files\", async () => {\n writeKiroSession(\"bad-lock\", \"/repo/project\", [prompt(\"hello\", 1781098057)]);\n fs.writeFileSync(path.join(sessionsDir, \"bad-lock.lock\"), \"{bad json\");\n const proc = makeProcess({ pid: 303, cwd: \"/repo/project\" });\n mockedCaptureProcessSnapshot.mockResolvedValue([proc]);\n\n const agents = await adapter.detectAgents();\n\n expect(agents[0]).toMatchObject({ sessionId: \"pid-303\" });\n });\n\n it(\"reports running while the latest assistant event invokes a tool\", async () => {\n writeKiroSession(\n \"tool-session\",\n \"/repo/project\",\n [\n prompt(\"inspect the file\", Math.floor(Date.now() / 1000)),\n assistantTool(\"fs_read\", { path: \"/repo/project/file.ts\" }),\n ],\n 404,\n new Date().toISOString(),\n );\n const proc = makeProcess({ pid: 404, cwd: \"/repo/project\" });\n mockedCaptureProcessSnapshot.mockResolvedValue([proc]);\n\n const agents = await adapter.detectAgents();\n\n expect(agents[0].status).toBe(AgentStatus.RUNNING);\n });\n\n it(\"returns a process-only agent when the locked transcript is missing\", async () => {\n fs.writeFileSync(path.join(sessionsDir, \"missing.lock\"), JSON.stringify({ pid: 505 }));\n const proc = makeProcess({ pid: 505, cwd: \"/repo/project-e\" });\n mockedCaptureProcessSnapshot.mockResolvedValue([proc]);\n\n const agents = await adapter.detectAgents();\n\n expect(agents).toEqual([\n expect.objectContaining({\n type: \"kiro\",\n status: AgentStatus.RUNNING,\n pid: 505,\n projectPath: \"/repo/project-e\",\n sessionId: \"pid-505\",\n summary: \"Kiro process running\",\n }),\n ]);\n });\n });\n\n describe(\"getConversation\", () => {\n it(\"reads real Kiro prompt and assistant message envelopes\", () => {\n const sessionFile = writeKiroSession(\"conversation\", \"/repo/project-f\", [\n prompt(\"hello kiro\", 1781098057),\n assistantText(\"Hello! How can I help?\"),\n \"{not json\",\n ]);\n\n expect(adapter.getConversation(sessionFile)).toEqual([\n { role: \"user\", content: \"hello kiro\", timestamp: \"2026-06-10T13:27:37.000Z\" },\n { role: \"assistant\", content: \"Hello! How can I help?\", timestamp: undefined },\n ]);\n });\n\n it(\"includes Kiro tool use and results only in verbose conversation mode\", () => {\n const sessionFile = writeKiroSession(\"tools\", \"/repo/project-tools\", [\n prompt(\"read package.json\", 1781098057),\n assistantTool(\"fs_read\", { path: \"package.json\" }),\n toolResult(\"contents\", \"success\"),\n assistantText(\"Done.\"),\n ]);\n\n expect(adapter.getConversation(sessionFile)).toEqual([\n { role: \"user\", content: \"read package.json\", timestamp: \"2026-06-10T13:27:37.000Z\" },\n { role: \"assistant\", content: \"Done.\", timestamp: undefined },\n ]);\n expect(adapter.getConversation(sessionFile, { verbose: true })).toEqual([\n { role: \"user\", content: \"read package.json\", timestamp: \"2026-06-10T13:27:37.000Z\" },\n {\n role: \"assistant\",\n content: '[Tool: fs_read] {\"path\":\"package.json\"}',\n timestamp: undefined,\n },\n { role: \"system\", content: \"[Tool Result] contents\", timestamp: undefined },\n { role: \"assistant\", content: \"Done.\", timestamp: undefined },\n ]);\n });\n });\n\n describe(\"listSessions\", () => {\n it(\"lists historical sessions using metadata and applies cwd filtering\", async () => {\n const matchingCwd = \"/repo/project-g\";\n const matchingSession = writeKiroSession(\"sess-g\", matchingCwd, [\n prompt(\"first matching message\", 1781098057),\n assistantText(\"response\"),\n ]);\n writeKiroSession(\"sess-h\", \"/repo/project-h\", [prompt(\"other message\", 1781098057)]);\n\n const sessions = await adapter.listSessions({ cwd: matchingCwd });\n\n expect(sessions).toEqual([\n expect.objectContaining({\n type: \"kiro\",\n sessionId: \"sess-g\",\n cwd: matchingCwd,\n firstUserMessage: \"first matching message\",\n startedAt: new Date(\"2026-06-10T13:27:17.000Z\"),\n lastActive: new Date(\"2026-06-10T13:27:40.000Z\"),\n sessionFilePath: matchingSession,\n }),\n ]);\n });\n });\n\n function makeProcess(overrides: Partial<ProcessInfo>): ProcessInfo {\n return {\n pid: 1,\n command: \"kiro-cli chat\",\n cwd: \"/repo\",\n tty: \"ttys001\",\n startTime: new Date(\"2026-06-10T13:27:17.000Z\"),\n ...overrides,\n };\n }\n\n function writeKiroSession(\n sessionId: string,\n cwd: string,\n entries: Array<Record<string, unknown> | string>,\n pid?: number,\n updatedAt = \"2026-06-10T13:27:40.000Z\",\n ): string {\n fs.writeFileSync(\n path.join(sessionsDir, `${sessionId}.json`),\n JSON.stringify({\n session_id: sessionId,\n cwd,\n created_at: \"2026-06-10T13:27:17.000Z\",\n updated_at: updatedAt,\n title: \"Session title\",\n }),\n );\n const filePath = path.join(sessionsDir, `${sessionId}.jsonl`);\n fs.writeFileSync(\n filePath,\n entries\n .map((entry) => (typeof entry === \"string\" ? entry : JSON.stringify(entry)))\n .join(\"\\n\"),\n );\n if (pid !== undefined) {\n fs.writeFileSync(\n path.join(sessionsDir, `${sessionId}.lock`),\n JSON.stringify({\n pid,\n started_at: \"2026-06-10T13:27:17.000Z\",\n }),\n );\n }\n return filePath;\n }\n\n function prompt(text: string, timestamp: number): Record<string, unknown> {\n return {\n version: \"v1\",\n kind: \"Prompt\",\n data: {\n content: [{ kind: \"text\", data: text }],\n meta: { timestamp },\n },\n };\n }\n\n function assistantText(text: string): Record<string, unknown> {\n return {\n version: \"v1\",\n kind: \"AssistantMessage\",\n data: { content: [{ kind: \"text\", data: text }] },\n };\n }\n\n function assistantTool(name: string, input: Record<string, unknown>): Record<string, unknown> {\n return {\n version: \"v1\",\n kind: \"AssistantMessage\",\n data: {\n content: [\n {\n kind: \"toolUse\",\n data: { toolUseId: \"tool-1\", name, input },\n },\n ],\n },\n };\n }\n\n function toolResult(result: string, status: string): Record<string, unknown> {\n return {\n version: \"v1\",\n kind: \"ToolResults\",\n data: {\n content: [\n {\n kind: \"toolResult\",\n data: { toolUseId: \"tool-1\", status, result },\n },\n ],\n },\n };\n }\n});\n"],"names":["fs","os","path","KiroAdapter","AgentStatus","listAgentProcesses","enrichProcesses","captureProcessSnapshot","generateAgentName","vi","mock","importOriginal","actual","fn","mockedListAgentProcesses","mockedEnrichProcesses","mockedCaptureProcessSnapshot","mockedGenerateAgentName","describe","adapter","tmpHome","sessionsDir","beforeEach","mkdtempSync","join","tmpdir","process","env","HOME","mkdirSync","recursive","mockReset","mockImplementation","procs","names","flatMap","name","cwd","pid","folder","basename","afterEach","rmSync","force","it","expect","type","toBe","processNames","toEqual","canHandle","command","tty","mockReturnValue","detectAgents","proc","makeProcess","updatedAt","Date","toISOString","sessionFile","writeKiroSession","prompt","assistantText","mockResolvedValue","agents","toHaveLength","toMatchObject","projectPath","sessionId","summary","status","WAITING","sessionFilePath","lastActive","kiro","ppid","chat","acp","objectContaining","owner","other","unknownTty","unknownAcp","first","second","sharedAcp","processes","not","toHaveBeenCalled","writeFileSync","Math","floor","now","assistantTool","RUNNING","JSON","stringify","getConversation","role","content","timestamp","undefined","toolResult","verbose","matchingCwd","matchingSession","sessions","listSessions","firstUserMessage","startedAt","overrides","startTime","entries","session_id","created_at","updated_at","title","filePath","map","entry","started_at","text","version","kind","data","meta","input","toolUseId","result"],"mappings":"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"}