zeitzeuge 0.6.5 → 0.6.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.
@@ -1 +1 @@
1
- {"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/analysis/agent.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,eAAe,EAGrB,MAAM,YAAY,CAAC;AAEpB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6CAA6C,CAAC;AACjF,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAM/B,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACrE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAwC/D,6DAA6D;AAC7D,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,EAAE,WAAW,CAAC;IACzB,WAAW,EAAE,WAAW,CAAC;CAC1B;AA6DD;;;GAGG;AACH,wBAAsB,OAAO,CAC3B,KAAK,EAAE,aAAa,EACpB,OAAO,EAAE,eAAe,EACxB,OAAO,EAAE,GAAG,EACZ,OAAO,CAAC,EAAE,eAAe,GACxB,OAAO,CAAC,OAAO,EAAE,CAAC,CAwBpB;AAED,0DAA0D;AAC1D,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,kBAAkB,CAAC;IAC5B,eAAe,EAAE,OAAO,CAAC;IACzB,mBAAmB,EAAE,OAAO,CAAC;CAC9B;AAkDD;;;GAGG;AACH,wBAAsB,sBAAsB,CAC1C,KAAK,EAAE,aAAa,EACpB,OAAO,EAAE,eAAe,EACxB,OAAO,EAAE,GAAG,EACZ,OAAO,CAAC,EAAE,qBAAqB,GAC9B,OAAO,CAAC,OAAO,EAAE,CAAC,CAwBpB;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAIjD"}
1
+ {"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/analysis/agent.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,KAAK,eAAe,EAGrB,MAAM,YAAY,CAAC;AAEpB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6CAA6C,CAAC;AACjF,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAM/B,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACrE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAyE/D,6DAA6D;AAC7D,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,EAAE,WAAW,CAAC;IACzB,WAAW,EAAE,WAAW,CAAC;CAC1B;AA6DD;;;GAGG;AACH,wBAAsB,OAAO,CAC3B,KAAK,EAAE,aAAa,EACpB,OAAO,EAAE,eAAe,EACxB,OAAO,EAAE,GAAG,EACZ,OAAO,CAAC,EAAE,eAAe,GACxB,OAAO,CAAC,OAAO,EAAE,CAAC,CAwBpB;AAED,0DAA0D;AAC1D,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,kBAAkB,CAAC;IAC5B,eAAe,EAAE,OAAO,CAAC;IACzB,mBAAmB,EAAE,OAAO,CAAC;CAC9B;AAkDD;;;GAGG;AACH,wBAAsB,sBAAsB,CAC1C,KAAK,EAAE,aAAa,EACpB,OAAO,EAAE,eAAe,EACxB,OAAO,EAAE,GAAG,EACZ,OAAO,CAAC,EAAE,qBAAqB,GAC9B,OAAO,CAAC,OAAO,EAAE,CAAC,CAwBpB;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAIjD"}
package/dist/cli.js CHANGED
@@ -779,6 +779,7 @@ function parseSnapshot(rawSnapshot) {
779
779
  }
780
780
 
781
781
  // src/analysis/agent.ts
782
+ import { setMaxListeners } from "node:events";
782
783
  import {
783
784
  createDeepAgent
784
785
  } from "deepagents";
@@ -1219,6 +1220,7 @@ class TodoProgressRenderer {
1219
1220
  baseSpinnerText;
1220
1221
  printedHeader = false;
1221
1222
  lastToolCallName;
1223
+ lastSubagentToolCallName;
1222
1224
  currentInProgressContent;
1223
1225
  totalTodos = 0;
1224
1226
  completedTodos = 0;
@@ -1257,23 +1259,31 @@ class TodoProgressRenderer {
1257
1259
  const ctx = contextLabel ? ` (${contextLabel})` : "";
1258
1260
  this.spinner.text = `${prefix}${base}${ctx}`;
1259
1261
  }
1260
- handleChunk(chunk) {
1262
+ handleChunk(chunk, meta) {
1263
+ const isSubagent = meta?.isSubagent === true;
1261
1264
  const toolCalls = extractToolCallsFromStreamChunk(chunk);
1262
1265
  if (toolCalls && toolCalls.length > 0) {
1263
1266
  for (const tc of toolCalls) {
1264
1267
  const signature = formatToolCall(tc);
1265
- if (tc.name !== this.lastToolCallName) {
1266
- this.lastToolCallName = tc.name;
1268
+ const lastName = isSubagent ? this.lastSubagentToolCallName : this.lastToolCallName;
1269
+ if (tc.name !== lastName) {
1270
+ if (isSubagent)
1271
+ this.lastSubagentToolCallName = tc.name;
1272
+ else
1273
+ this.lastToolCallName = tc.name;
1267
1274
  this.printHeaderOnce();
1275
+ const label = isSubagent ? ` ↳ ${pc.cyan("[subagent]")} ${signature}` : ` ↳ ${signature}`;
1268
1276
  this.spinner.stopAndPersist({
1269
1277
  symbol: " ",
1270
- text: pc.dim(` ↳ ${signature}`)
1278
+ text: pc.dim(label)
1271
1279
  });
1272
1280
  this.spinner.start();
1273
1281
  this.updateSpinnerText(this.currentInProgressContent);
1274
1282
  }
1275
1283
  }
1276
1284
  }
1285
+ if (isSubagent)
1286
+ return;
1277
1287
  const todos = extractTodosFromStreamChunk(chunk);
1278
1288
  if (!todos)
1279
1289
  return;
@@ -1292,6 +1302,7 @@ class TodoProgressRenderer {
1292
1302
  });
1293
1303
  this.spinner.start();
1294
1304
  this.lastToolCallName = undefined;
1305
+ this.lastSubagentToolCallName = undefined;
1295
1306
  }
1296
1307
  if (nextStatus === "in_progress" && this.lastInProgressKey !== key) {
1297
1308
  this.lastInProgressKey = key;
@@ -1299,6 +1310,7 @@ class TodoProgressRenderer {
1299
1310
  this.printHeaderOnce();
1300
1311
  this.updateSpinnerText(todo.content);
1301
1312
  this.lastToolCallName = undefined;
1313
+ this.lastSubagentToolCallName = undefined;
1302
1314
  }
1303
1315
  }
1304
1316
  }
@@ -1392,21 +1404,40 @@ function truncateValue(val, maxLen = 40) {
1392
1404
  }
1393
1405
 
1394
1406
  // src/analysis/agent.ts
1407
+ function isSubagentNamespace(ns) {
1408
+ if (typeof ns === "string")
1409
+ return ns.includes("tools:");
1410
+ if (Array.isArray(ns))
1411
+ return ns.some((s) => typeof s === "string" && s.includes("tools:"));
1412
+ return false;
1413
+ }
1395
1414
  async function invokeWithTodoStreaming(agent, userMessage, spinner) {
1396
1415
  const renderer = new TodoProgressRenderer(spinner);
1397
- const stream = await agent.stream({ messages: [{ role: "user", content: userMessage }] }, { streamMode: ["updates", "values"] });
1416
+ const controller = new AbortController;
1417
+ setMaxListeners(0, controller.signal);
1418
+ const stream = await agent.stream({ messages: [{ role: "user", content: userMessage }] }, { streamMode: ["updates", "values"], subgraphs: true, signal: controller.signal });
1398
1419
  let lastValues;
1399
1420
  for await (const item of stream) {
1400
- if (Array.isArray(item) && item.length === 2) {
1401
- const mode = item[0];
1402
- const chunk = item[1];
1421
+ if (!Array.isArray(item)) {
1422
+ renderer.handleChunk(item);
1423
+ lastValues = item;
1424
+ continue;
1425
+ }
1426
+ if (item.length === 3) {
1427
+ const [ns, mode, chunk] = item;
1428
+ const isSubagent = isSubagentNamespace(ns);
1429
+ renderer.handleChunk(chunk, { isSubagent });
1430
+ if (!isSubagent && mode === "values")
1431
+ lastValues = chunk;
1432
+ continue;
1433
+ }
1434
+ if (item.length === 2) {
1435
+ const [mode, chunk] = item;
1403
1436
  renderer.handleChunk(chunk);
1404
1437
  if (mode === "values")
1405
1438
  lastValues = chunk;
1406
1439
  continue;
1407
1440
  }
1408
- renderer.handleChunk(item);
1409
- lastValues = item;
1410
1441
  }
1411
1442
  return lastValues;
1412
1443
  }
@@ -1,11 +1,19 @@
1
1
  import type { Ora } from 'ora';
2
+ /** Options passed alongside a chunk to provide context about its origin. */
3
+ export interface ChunkMeta {
4
+ /** True when the chunk originates from a subagent (subgraph). */
5
+ isSubagent?: boolean;
6
+ }
2
7
  export declare class TodoProgressRenderer {
3
8
  private spinner;
4
9
  private lastStatusByKey;
5
10
  private lastInProgressKey;
6
11
  private baseSpinnerText;
7
12
  private printedHeader;
13
+ /** Last tool call name for the main agent (dedup). */
8
14
  private lastToolCallName;
15
+ /** Last tool call name for subagents (separate dedup). */
16
+ private lastSubagentToolCallName;
9
17
  private currentInProgressContent;
10
18
  private totalTodos;
11
19
  private completedTodos;
@@ -17,6 +25,6 @@ export declare class TodoProgressRenderer {
17
25
  private recomputeCounts;
18
26
  /** Update the spinner text with current progress & context. */
19
27
  private updateSpinnerText;
20
- handleChunk(chunk: unknown): void;
28
+ handleChunk(chunk: unknown, meta?: ChunkMeta): void;
21
29
  }
22
30
  //# sourceMappingURL=progress.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"progress.d.ts","sourceRoot":"","sources":["../../src/output/progress.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAgB/B,qBAAa,oBAAoB;IAUnB,OAAO,CAAC,OAAO;IAT3B,OAAO,CAAC,eAAe,CAA6B;IACpD,OAAO,CAAC,iBAAiB,CAAqB;IAC9C,OAAO,CAAC,eAAe,CAAqB;IAC5C,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,gBAAgB,CAAqB;IAC7C,OAAO,CAAC,wBAAwB,CAAqB;IACrD,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,cAAc,CAAK;gBAEP,OAAO,EAAE,GAAG;IAIhC,OAAO,CAAC,eAAe;IASvB,yEAAyE;IACzE,OAAO,CAAC,cAAc;IAKtB,sDAAsD;IACtD,OAAO,CAAC,eAAe;IAWvB,+DAA+D;IAC/D,OAAO,CAAC,iBAAiB;IAOzB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI;CAuDlC"}
1
+ {"version":3,"file":"progress.d.ts","sourceRoot":"","sources":["../../src/output/progress.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAgB/B,4EAA4E;AAC5E,MAAM,WAAW,SAAS;IACxB,iEAAiE;IACjE,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,qBAAa,oBAAoB;IAanB,OAAO,CAAC,OAAO;IAZ3B,OAAO,CAAC,eAAe,CAA6B;IACpD,OAAO,CAAC,iBAAiB,CAAqB;IAC9C,OAAO,CAAC,eAAe,CAAqB;IAC5C,OAAO,CAAC,aAAa,CAAS;IAC9B,sDAAsD;IACtD,OAAO,CAAC,gBAAgB,CAAqB;IAC7C,0DAA0D;IAC1D,OAAO,CAAC,wBAAwB,CAAqB;IACrD,OAAO,CAAC,wBAAwB,CAAqB;IACrD,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,cAAc,CAAK;gBAEP,OAAO,EAAE,GAAG;IAIhC,OAAO,CAAC,eAAe;IASvB,yEAAyE;IACzE,OAAO,CAAC,cAAc;IAKtB,sDAAsD;IACtD,OAAO,CAAC,eAAe;IAWvB,+DAA+D;IAC/D,OAAO,CAAC,iBAAiB;IAOzB,WAAW,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,GAAG,IAAI;CAuEpD"}
@@ -1084,6 +1084,7 @@ function formatBytes(bytes) {
1084
1084
  }
1085
1085
 
1086
1086
  // src/analysis/agent.ts
1087
+ import { setMaxListeners } from "node:events";
1087
1088
  import {
1088
1089
  createDeepAgent
1089
1090
  } from "deepagents";
@@ -1524,6 +1525,7 @@ class TodoProgressRenderer {
1524
1525
  baseSpinnerText;
1525
1526
  printedHeader = false;
1526
1527
  lastToolCallName;
1528
+ lastSubagentToolCallName;
1527
1529
  currentInProgressContent;
1528
1530
  totalTodos = 0;
1529
1531
  completedTodos = 0;
@@ -1562,23 +1564,31 @@ class TodoProgressRenderer {
1562
1564
  const ctx = contextLabel ? ` (${contextLabel})` : "";
1563
1565
  this.spinner.text = `${prefix}${base}${ctx}`;
1564
1566
  }
1565
- handleChunk(chunk) {
1567
+ handleChunk(chunk, meta) {
1568
+ const isSubagent = meta?.isSubagent === true;
1566
1569
  const toolCalls = extractToolCallsFromStreamChunk(chunk);
1567
1570
  if (toolCalls && toolCalls.length > 0) {
1568
1571
  for (const tc of toolCalls) {
1569
1572
  const signature = formatToolCall(tc);
1570
- if (tc.name !== this.lastToolCallName) {
1571
- this.lastToolCallName = tc.name;
1573
+ const lastName = isSubagent ? this.lastSubagentToolCallName : this.lastToolCallName;
1574
+ if (tc.name !== lastName) {
1575
+ if (isSubagent)
1576
+ this.lastSubagentToolCallName = tc.name;
1577
+ else
1578
+ this.lastToolCallName = tc.name;
1572
1579
  this.printHeaderOnce();
1580
+ const label = isSubagent ? ` ↳ ${pc2.cyan("[subagent]")} ${signature}` : ` ↳ ${signature}`;
1573
1581
  this.spinner.stopAndPersist({
1574
1582
  symbol: " ",
1575
- text: pc2.dim(` ↳ ${signature}`)
1583
+ text: pc2.dim(label)
1576
1584
  });
1577
1585
  this.spinner.start();
1578
1586
  this.updateSpinnerText(this.currentInProgressContent);
1579
1587
  }
1580
1588
  }
1581
1589
  }
1590
+ if (isSubagent)
1591
+ return;
1582
1592
  const todos = extractTodosFromStreamChunk(chunk);
1583
1593
  if (!todos)
1584
1594
  return;
@@ -1597,6 +1607,7 @@ class TodoProgressRenderer {
1597
1607
  });
1598
1608
  this.spinner.start();
1599
1609
  this.lastToolCallName = undefined;
1610
+ this.lastSubagentToolCallName = undefined;
1600
1611
  }
1601
1612
  if (nextStatus === "in_progress" && this.lastInProgressKey !== key) {
1602
1613
  this.lastInProgressKey = key;
@@ -1604,6 +1615,7 @@ class TodoProgressRenderer {
1604
1615
  this.printHeaderOnce();
1605
1616
  this.updateSpinnerText(todo.content);
1606
1617
  this.lastToolCallName = undefined;
1618
+ this.lastSubagentToolCallName = undefined;
1607
1619
  }
1608
1620
  }
1609
1621
  }
@@ -1697,21 +1709,40 @@ function truncateValue(val, maxLen = 40) {
1697
1709
  }
1698
1710
 
1699
1711
  // src/analysis/agent.ts
1712
+ function isSubagentNamespace(ns) {
1713
+ if (typeof ns === "string")
1714
+ return ns.includes("tools:");
1715
+ if (Array.isArray(ns))
1716
+ return ns.some((s) => typeof s === "string" && s.includes("tools:"));
1717
+ return false;
1718
+ }
1700
1719
  async function invokeWithTodoStreaming(agent, userMessage, spinner) {
1701
1720
  const renderer = new TodoProgressRenderer(spinner);
1702
- const stream = await agent.stream({ messages: [{ role: "user", content: userMessage }] }, { streamMode: ["updates", "values"] });
1721
+ const controller = new AbortController;
1722
+ setMaxListeners(0, controller.signal);
1723
+ const stream = await agent.stream({ messages: [{ role: "user", content: userMessage }] }, { streamMode: ["updates", "values"], subgraphs: true, signal: controller.signal });
1703
1724
  let lastValues;
1704
1725
  for await (const item of stream) {
1705
- if (Array.isArray(item) && item.length === 2) {
1706
- const mode = item[0];
1707
- const chunk = item[1];
1726
+ if (!Array.isArray(item)) {
1727
+ renderer.handleChunk(item);
1728
+ lastValues = item;
1729
+ continue;
1730
+ }
1731
+ if (item.length === 3) {
1732
+ const [ns, mode, chunk] = item;
1733
+ const isSubagent = isSubagentNamespace(ns);
1734
+ renderer.handleChunk(chunk, { isSubagent });
1735
+ if (!isSubagent && mode === "values")
1736
+ lastValues = chunk;
1737
+ continue;
1738
+ }
1739
+ if (item.length === 2) {
1740
+ const [mode, chunk] = item;
1708
1741
  renderer.handleChunk(chunk);
1709
1742
  if (mode === "values")
1710
1743
  lastValues = chunk;
1711
1744
  continue;
1712
1745
  }
1713
- renderer.handleChunk(item);
1714
- lastValues = item;
1715
1746
  }
1716
1747
  return lastValues;
1717
1748
  }
@@ -2342,7 +2373,7 @@ function relativize(filePath, projectRoot) {
2342
2373
  // package.json
2343
2374
  var package_default = {
2344
2375
  name: "zeitzeuge",
2345
- version: "0.6.4",
2376
+ version: "0.6.5",
2346
2377
  description: "A deepagent to witnessing slowdowns in your test runs.",
2347
2378
  keywords: [
2348
2379
  "analysis",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zeitzeuge",
3
- "version": "0.6.5",
3
+ "version": "0.6.6",
4
4
  "description": "A deepagent to witnessing slowdowns in your test runs.",
5
5
  "keywords": [
6
6
  "analysis",