@tangle-network/traces 0.8.18 → 0.8.20

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.
@@ -4297,6 +4297,36 @@ function isChange(span2) {
4297
4297
  if (!isTool(span2)) return false;
4298
4298
  return CHANGE_RE.test(`${toolName2(span2)} ${span2.name} ${spanContent(span2)}`);
4299
4299
  }
4300
+ function isRead(span2) {
4301
+ if (!isTool(span2)) return false;
4302
+ return /\b(read|cat|less|grep|rg|sed -n|nl|ls|find|git show|git diff)\b/i.test(`${toolName2(span2)} ${span2.name} ${spanContent(span2)}`);
4303
+ }
4304
+ function actionKind(span2) {
4305
+ if (isVerification(span2)) return "verify";
4306
+ if (isChange(span2)) return "edit";
4307
+ if (isRead(span2)) return "read";
4308
+ if (isTool(span2)) return "tool";
4309
+ if (isTextSpan(span2) && CLAIM_DONE_RE.test(spanContent(span2))) return "claim";
4310
+ return "other";
4311
+ }
4312
+ function classifyLiveActions(spans) {
4313
+ return orderSpans(spans).map((span2) => {
4314
+ const tool = isTool(span2) ? toolName2(span2) : void 0;
4315
+ return {
4316
+ kind: actionKind(span2),
4317
+ spanId: span2.span_id,
4318
+ span: span2,
4319
+ ...tool ? { toolName: tool } : {},
4320
+ signature: toolSignature(span2),
4321
+ errored: span2.status.code === "ERROR"
4322
+ };
4323
+ });
4324
+ }
4325
+ function actionCounts(actions) {
4326
+ const counts = { tool: 0, read: 0, edit: 0, verify: 0, claim: 0, other: 0 };
4327
+ for (const action of actions) counts[action.kind] += 1;
4328
+ return counts;
4329
+ }
4300
4330
  function timeOf(span2) {
4301
4331
  const parsed = Date.parse(span2.start_time);
4302
4332
  return Number.isFinite(parsed) ? parsed : 0;
@@ -4339,54 +4369,52 @@ function finding(input) {
4339
4369
  observedAt: input.observedAt
4340
4370
  };
4341
4371
  }
4342
- function analyzeLiveBatch(spans, opts = {}) {
4343
- const ordered2 = orderSpans(spans);
4344
- const generatedAt = opts.generatedAt ?? (/* @__PURE__ */ new Date()).toISOString();
4345
- const session = sessionFrom(ordered2, opts);
4346
- const tools = ordered2.filter(isTool);
4347
- const erroredTools = tools.filter((span2) => span2.status.code === "ERROR");
4348
- const verificationCalls = tools.filter(isVerification);
4349
- const changeCalls = tools.filter(isChange);
4350
- const findings = [];
4351
- const failedBySignature = /* @__PURE__ */ new Map();
4352
- for (const span2 of erroredTools) {
4353
- const signature = toolSignature(span2);
4354
- failedBySignature.set(signature, [...failedBySignature.get(signature) ?? [], span2]);
4355
- }
4356
- for (const [signature, rows] of failedBySignature) {
4357
- if (rows.length < 2) continue;
4358
- findings.push(finding({
4359
- ruleId: "same-failing-command",
4360
- severity: rows.length >= 3 ? "high" : "medium",
4361
- title: "Same failing command is repeating",
4362
- claim: `${rows.length} failed tool call(s) repeated the same command or arguments.`,
4363
- action: "Stop rerunning it; inspect the first failure, change state, or choose a different diagnostic path before another retry.",
4364
- check: "The next action should read the failing file, inspect the stack/output, or edit code before this command runs again.",
4365
- evidence: [
4366
- evidence2("pattern", "command", signature, rows.map((span2) => span2.span_id)),
4367
- evidence2("metric", "failed_repeats", String(rows.length))
4368
- ],
4369
- session,
4370
- observedAt: generatedAt,
4371
- signature: [signature, String(rows.length)]
4372
- }));
4373
- }
4374
- let lastChangeIndex = -1;
4375
- let verificationSinceChange = 0;
4376
- const verificationSpanIds = [];
4377
- for (let i = 0; i < ordered2.length; i++) {
4378
- const span2 = ordered2[i];
4379
- if (isChange(span2)) {
4380
- lastChangeIndex = i;
4381
- verificationSinceChange = 0;
4382
- verificationSpanIds.length = 0;
4383
- } else if (isVerification(span2)) {
4384
- verificationSinceChange += 1;
4385
- verificationSpanIds.push(span2.span_id);
4372
+ var sameFailingCommandAnalyst = {
4373
+ id: "same-failing-command",
4374
+ analyze(context) {
4375
+ const findings = [];
4376
+ const failedBySignature = /* @__PURE__ */ new Map();
4377
+ for (const action of context.actions) {
4378
+ if (!action.toolName || !action.errored) continue;
4379
+ failedBySignature.set(action.signature, [...failedBySignature.get(action.signature) ?? [], action.span]);
4380
+ }
4381
+ for (const [signature, rows] of failedBySignature) {
4382
+ if (rows.length < 2) continue;
4383
+ findings.push(finding({
4384
+ ruleId: "same-failing-command",
4385
+ severity: rows.length >= 3 ? "high" : "medium",
4386
+ title: "Same failing command is repeating",
4387
+ claim: `${rows.length} failed tool call(s) repeated the same command or arguments.`,
4388
+ action: "Stop rerunning it; inspect the first failure, change state, or choose a different diagnostic path before another retry.",
4389
+ check: "The next action should read the failing file, inspect the stack/output, or edit code before this command runs again.",
4390
+ evidence: [
4391
+ evidence2("pattern", "command", signature, rows.map((span2) => span2.span_id)),
4392
+ evidence2("metric", "failed_repeats", String(rows.length))
4393
+ ],
4394
+ session: context.session,
4395
+ observedAt: context.generatedAt,
4396
+ signature: [signature, String(rows.length)]
4397
+ }));
4386
4398
  }
4399
+ return findings;
4387
4400
  }
4388
- if (verificationSinceChange >= 2) {
4389
- findings.push(finding({
4401
+ };
4402
+ var verificationWithoutChangeAnalyst = {
4403
+ id: "verification-without-change",
4404
+ analyze(context) {
4405
+ let verificationSinceChange = 0;
4406
+ const verificationSpanIds = [];
4407
+ for (const action of context.actions) {
4408
+ if (action.kind === "edit") {
4409
+ verificationSinceChange = 0;
4410
+ verificationSpanIds.length = 0;
4411
+ } else if (action.kind === "verify") {
4412
+ verificationSinceChange += 1;
4413
+ verificationSpanIds.push(action.spanId);
4414
+ }
4415
+ }
4416
+ if (verificationSinceChange < 2) return [];
4417
+ return [finding({
4390
4418
  ruleId: "verification-without-change",
4391
4419
  severity: verificationSinceChange >= 3 ? "high" : "medium",
4392
4420
  title: "Verification is repeating without a state change",
@@ -4395,51 +4423,89 @@ function analyzeLiveBatch(spans, opts = {}) {
4395
4423
  check: "The next action should be a code/config edit, targeted file read, or a different narrow diagnostic command.",
4396
4424
  evidence: [
4397
4425
  evidence2("metric", "verification_calls_since_change", String(verificationSinceChange), verificationSpanIds),
4398
- evidence2("metric", "change_calls", String(changeCalls.length))
4426
+ evidence2("metric", "change_calls", String(context.changeActions.length))
4399
4427
  ],
4400
- session,
4401
- observedAt: generatedAt,
4428
+ session: context.session,
4429
+ observedAt: context.generatedAt,
4402
4430
  signature: [String(verificationSinceChange), verificationSpanIds.join(",")]
4403
- }));
4431
+ })];
4404
4432
  }
4405
- const lastClaim = [...ordered2].reverse().find((span2) => isTextSpan(span2) && CLAIM_DONE_RE.test(spanContent(span2)));
4406
- if (lastClaim) {
4407
- const claimTime = timeOf(lastClaim);
4408
- const verificationAfterClaim = verificationCalls.some((span2) => timeOf(span2) > claimTime);
4409
- if (!verificationAfterClaim) {
4410
- findings.push(finding({
4411
- ruleId: "completion-claim-without-verification",
4412
- severity: "medium",
4413
- title: "Completion claim has no later verification",
4414
- claim: "The agent claimed completion, correctness, or verification without a later verification tool call in the observed trace.",
4415
- action: "Require a concrete check after the claim, or downgrade the claim to an unverified hypothesis.",
4416
- check: "A later test/build/typecheck/lint/smoke command should appear after the claim.",
4417
- evidence: [
4418
- evidence2("span", "claim_span", spanContent(lastClaim).slice(0, 240), [lastClaim.span_id]),
4419
- evidence2("metric", "verification_after_claim", "0")
4420
- ],
4421
- session,
4422
- observedAt: generatedAt,
4423
- signature: [lastClaim.span_id, spanContent(lastClaim).slice(0, 120)]
4424
- }));
4425
- }
4433
+ };
4434
+ var completionClaimWithoutVerificationAnalyst = {
4435
+ id: "completion-claim-without-verification",
4436
+ analyze(context) {
4437
+ const lastClaim = [...context.actions].reverse().find((action) => action.kind === "claim");
4438
+ if (!lastClaim) return [];
4439
+ const claimTime = timeOf(lastClaim.span);
4440
+ const verificationAfterClaim = context.verificationActions.some((action) => timeOf(action.span) > claimTime);
4441
+ if (verificationAfterClaim) return [];
4442
+ return [finding({
4443
+ ruleId: "completion-claim-without-verification",
4444
+ severity: "medium",
4445
+ title: "Completion claim has no later verification",
4446
+ claim: "The agent claimed completion, correctness, or verification without a later verification tool call in the observed trace.",
4447
+ action: "Require a concrete check after the claim, or downgrade the claim to an unverified hypothesis.",
4448
+ check: "A later test/build/typecheck/lint/smoke command should appear after the claim.",
4449
+ evidence: [
4450
+ evidence2("span", "claim_span", spanContent(lastClaim.span).slice(0, 240), [lastClaim.spanId]),
4451
+ evidence2("metric", "verification_after_claim", "0")
4452
+ ],
4453
+ session: context.session,
4454
+ observedAt: context.generatedAt,
4455
+ signature: [lastClaim.spanId, spanContent(lastClaim.span).slice(0, 120)]
4456
+ })];
4426
4457
  }
4427
- if (tools.length >= 4 && erroredTools.length / tools.length >= 0.5) {
4428
- findings.push(finding({
4458
+ };
4459
+ var highToolErrorRateAnalyst = {
4460
+ id: "high-tool-error-rate",
4461
+ analyze(context) {
4462
+ if (context.tools.length < 4 || context.erroredTools.length / context.tools.length < 0.5) return [];
4463
+ return [finding({
4429
4464
  ruleId: "high-tool-error-rate",
4430
- severity: erroredTools.length / tools.length >= 0.75 ? "high" : "medium",
4465
+ severity: context.erroredTools.length / context.tools.length >= 0.75 ? "high" : "medium",
4431
4466
  title: "Tool calls are mostly failing",
4432
- claim: `${erroredTools.length}/${tools.length} tool call(s) in this live batch ended with ERROR.`,
4467
+ claim: `${context.erroredTools.length}/${context.tools.length} tool call(s) in this live batch ended with ERROR.`,
4433
4468
  action: "Switch from broad execution to diagnosis: classify the dominant error, then run one targeted command to validate the fix path.",
4434
4469
  check: "The next batch should reduce the error ratio or show a new targeted diagnostic result.",
4435
4470
  evidence: [
4436
- evidence2("metric", "errored_tool_calls", `${erroredTools.length}/${tools.length}`, erroredTools.map((span2) => span2.span_id))
4471
+ evidence2("metric", "errored_tool_calls", `${context.erroredTools.length}/${context.tools.length}`, context.erroredTools.map((span2) => span2.span_id))
4437
4472
  ],
4438
- session,
4439
- observedAt: generatedAt,
4440
- signature: [String(erroredTools.length), String(tools.length)]
4441
- }));
4473
+ session: context.session,
4474
+ observedAt: context.generatedAt,
4475
+ signature: [String(context.erroredTools.length), String(context.tools.length)]
4476
+ })];
4442
4477
  }
4478
+ };
4479
+ var defaultTraceLiveAnalysts = [
4480
+ sameFailingCommandAnalyst,
4481
+ verificationWithoutChangeAnalyst,
4482
+ completionClaimWithoutVerificationAnalyst,
4483
+ highToolErrorRateAnalyst
4484
+ ];
4485
+ function liveAnalysts(opts) {
4486
+ return [...opts.analysts ?? defaultTraceLiveAnalysts, ...opts.extraAnalysts ?? []];
4487
+ }
4488
+ function analyzeLiveBatch(spans, opts = {}) {
4489
+ const ordered2 = orderSpans(spans);
4490
+ const generatedAt = opts.generatedAt ?? (/* @__PURE__ */ new Date()).toISOString();
4491
+ const session = sessionFrom(ordered2, opts);
4492
+ const actions = classifyLiveActions(ordered2);
4493
+ const tools = ordered2.filter(isTool);
4494
+ const erroredTools = tools.filter((span2) => span2.status.code === "ERROR");
4495
+ const verificationActions = actions.filter((action) => action.kind === "verify");
4496
+ const changeActions = actions.filter((action) => action.kind === "edit");
4497
+ const context = {
4498
+ spans: ordered2,
4499
+ actions,
4500
+ tools,
4501
+ erroredTools,
4502
+ verificationActions,
4503
+ changeActions,
4504
+ session,
4505
+ generatedAt,
4506
+ newSpanCount: opts.newSpanCount ?? ordered2.length
4507
+ };
4508
+ const findings = liveAnalysts(opts).flatMap((analyst) => [...analyst.analyze(context)]);
4443
4509
  return {
4444
4510
  schemaVersion: 1,
4445
4511
  kind: "traces.live_batch",
@@ -4449,8 +4515,9 @@ function analyzeLiveBatch(spans, opts = {}) {
4449
4515
  newSpanCount: opts.newSpanCount ?? ordered2.length,
4450
4516
  toolCallCount: tools.length,
4451
4517
  erroredToolCallCount: erroredTools.length,
4452
- verificationCallCount: verificationCalls.length,
4453
- changeCallCount: changeCalls.length,
4518
+ verificationCallCount: verificationActions.length,
4519
+ changeCallCount: changeActions.length,
4520
+ actionCounts: actionCounts(actions),
4454
4521
  findingCount: findings.length,
4455
4522
  findings
4456
4523
  };
@@ -4475,14 +4542,20 @@ function traceStreamEventsFromSpans(spans, opts = {}) {
4475
4542
  session: opts.ref ? { harness: opts.ref.harness, sessionId: opts.ref.sessionId, cwd: opts.ref.cwd, path: opts.ref.path } : opts.session
4476
4543
  });
4477
4544
  const ordered2 = orderSpans(spans);
4478
- const batch = analyzeLiveBatch(ordered2, { generatedAt, session, newSpanCount: ordered2.length });
4545
+ const batch = analyzeLiveBatch(ordered2, {
4546
+ generatedAt,
4547
+ session,
4548
+ newSpanCount: ordered2.length,
4549
+ analysts: opts.analysts,
4550
+ extraAnalysts: opts.extraAnalysts
4551
+ });
4479
4552
  const events = [sessionEvent(session, ordered2, generatedAt)];
4480
4553
  if (opts.includeSpans !== false) {
4481
4554
  for (const span2 of ordered2) {
4482
4555
  events.push({ schemaVersion: 1, kind: "traces.stream.span", event: "span", generatedAt, session, span: span2 });
4483
4556
  }
4484
4557
  }
4485
- events.push({ schemaVersion: 1, kind: "traces.stream.batch", event: "analysis_batch", generatedAt, batch });
4558
+ events.push({ schemaVersion: 1, kind: "traces.stream.batch", event: "analysis_batch", generatedAt, ref: opts.ref, batch });
4486
4559
  if (opts.includeFindings !== false) {
4487
4560
  for (const liveFinding of batch.findings) {
4488
4561
  events.push({ schemaVersion: 1, kind: "traces.stream.finding", event: "finding", generatedAt, finding: liveFinding });
@@ -4494,12 +4567,24 @@ function serializeTraceStreamEvent(event) {
4494
4567
  return `${JSON.stringify(event)}
4495
4568
  `;
4496
4569
  }
4570
+ function loopsFromReport(session, report) {
4571
+ return report.stuckLoops.findings.map((loop) => ({
4572
+ harness: session.harness,
4573
+ sessionId: session.sessionId,
4574
+ cwd: session.cwd,
4575
+ toolName: loop.toolName,
4576
+ argHash: loop.argHash,
4577
+ occurrences: loop.occurrences,
4578
+ windowMs: loop.windowMs
4579
+ }));
4580
+ }
4497
4581
  async function streamSessions(opts) {
4498
4582
  const intervalMs = Math.max(250, opts.intervalMs ?? 5e3);
4499
4583
  const windowMs = opts.windowMs ?? 30 * 6e4;
4500
4584
  const includeSpans = opts.includeSpans !== false;
4501
4585
  const includeFindings = opts.includeFindings !== false;
4502
4586
  const includeBatches = opts.includeBatches !== false;
4587
+ const includeReports = opts.includeReports === true;
4503
4588
  const seenSessions = /* @__PURE__ */ new Set();
4504
4589
  const seenSpans = /* @__PURE__ */ new Set();
4505
4590
  const seenFindings = /* @__PURE__ */ new Set();
@@ -4533,9 +4618,31 @@ async function streamSessions(opts) {
4533
4618
  await opts.onEvent({ schemaVersion: 1, kind: "traces.stream.span", event: "span", generatedAt, session, span: span2 });
4534
4619
  }
4535
4620
  }
4536
- const batch = analyzeLiveBatch(ordered2, { generatedAt, session, newSpanCount: unseen.length });
4621
+ const batch = analyzeLiveBatch(ordered2, {
4622
+ generatedAt,
4623
+ session,
4624
+ newSpanCount: unseen.length,
4625
+ extraAnalysts: opts.extraAnalysts
4626
+ });
4537
4627
  if (includeBatches) {
4538
- await opts.onEvent({ schemaVersion: 1, kind: "traces.stream.batch", event: "analysis_batch", generatedAt, batch });
4628
+ await opts.onEvent({ schemaVersion: 1, kind: "traces.stream.batch", event: "analysis_batch", generatedAt, ref, batch });
4629
+ }
4630
+ if (includeReports) {
4631
+ try {
4632
+ const report = await runPipelines(ordered2, { minLoopOccurrences: opts.minLoopOccurrences });
4633
+ await opts.onEvent({
4634
+ schemaVersion: 1,
4635
+ kind: "traces.stream.report",
4636
+ event: "report",
4637
+ generatedAt,
4638
+ session,
4639
+ ref,
4640
+ report,
4641
+ loops: loopsFromReport(session, report)
4642
+ });
4643
+ } catch (err) {
4644
+ opts.onError?.(err, ref);
4645
+ }
4539
4646
  }
4540
4647
  if (includeFindings) {
4541
4648
  for (const liveFinding of batch.findings) {
@@ -4561,107 +4668,52 @@ async function streamSessions(opts) {
4561
4668
  }
4562
4669
 
4563
4670
  // src/observer.ts
4564
- var sleep2 = (ms, signal) => new Promise((resolve2) => {
4565
- if (signal?.aborted) {
4566
- resolve2();
4567
- return;
4671
+ function loopKey(loop) {
4672
+ return `${loop.sessionId}:${loop.toolName}:${loop.argHash}`;
4673
+ }
4674
+ async function callSafely(ref, onError, fn) {
4675
+ try {
4676
+ await fn();
4677
+ } catch (err) {
4678
+ onError?.(err, ref);
4568
4679
  }
4569
- const onAbort = () => {
4570
- clearTimeout(t);
4571
- resolve2();
4572
- };
4573
- const t = setTimeout(() => {
4574
- signal?.removeEventListener("abort", onAbort);
4575
- resolve2();
4576
- }, ms);
4577
- signal?.addEventListener("abort", onAbort, { once: true });
4578
- });
4579
- function loopKey(sessionId, toolName3, argHash) {
4580
- return `${sessionId}:${toolName3}:${argHash}`;
4581
4680
  }
4582
4681
  async function watchSessions(opts) {
4583
- const windowMs = opts.windowMs ?? 30 * 6e4;
4584
- const intervalMs = Math.max(250, opts.intervalMs ?? 5e3);
4585
- const minLoop = opts.minLoopOccurrences ?? 3;
4586
- const seen = /* @__PURE__ */ new Map();
4587
- const seenFindings = /* @__PURE__ */ new Set();
4588
- while (!opts.signal?.aborted) {
4589
- let sessionCount = 0;
4590
- for await (const { adapter, ref, spans } of scanSessions({
4591
- adapters: opts.adapters,
4592
- all: opts.all,
4593
- harnesses: opts.harnesses,
4594
- cwd: opts.cwd,
4595
- sinceMs: Date.now() - windowMs,
4596
- signal: opts.signal,
4597
- onError: opts.onError
4598
- })) {
4599
- let report;
4600
- try {
4601
- report = await runPipelines(spans, { minLoopOccurrences: minLoop });
4602
- } catch (err) {
4603
- opts.onError?.(err, ref);
4604
- continue;
4605
- }
4606
- sessionCount += 1;
4607
- if (opts.onReport) {
4608
- try {
4609
- await opts.onReport(ref, report);
4610
- } catch (err) {
4611
- opts.onError?.(err, ref);
4682
+ const seenLoops = /* @__PURE__ */ new Map();
4683
+ await streamSessions({
4684
+ adapters: opts.adapters,
4685
+ all: opts.all,
4686
+ harnesses: opts.harnesses,
4687
+ cwd: opts.cwd,
4688
+ windowMs: opts.windowMs,
4689
+ intervalMs: opts.intervalMs,
4690
+ minLoopOccurrences: opts.minLoopOccurrences,
4691
+ signal: opts.signal,
4692
+ includeSpans: false,
4693
+ includeBatches: Boolean(opts.onBatch),
4694
+ includeFindings: Boolean(opts.onFinding),
4695
+ includeReports: Boolean(opts.onReport || opts.onLoop),
4696
+ onError: opts.onError,
4697
+ onEvent: async (event) => {
4698
+ if (event.event === "analysis_batch") {
4699
+ if (event.ref) {
4700
+ await callSafely(event.ref, opts.onError, () => opts.onBatch?.(event.ref, event.batch));
4612
4701
  }
4613
- }
4614
- const batch = analyzeLiveBatch(spans, {
4615
- session: { harness: adapter.harness, sessionId: ref.sessionId, cwd: ref.cwd, path: ref.path }
4616
- });
4617
- if (opts.onBatch) {
4618
- try {
4619
- await opts.onBatch(ref, batch);
4620
- } catch (err) {
4621
- opts.onError?.(err, ref);
4622
- }
4623
- }
4624
- if (opts.onFinding) {
4625
- for (const finding2 of batch.findings) {
4626
- if (seenFindings.has(finding2.id)) continue;
4627
- seenFindings.add(finding2.id);
4628
- try {
4629
- await opts.onFinding(finding2);
4630
- } catch (err) {
4631
- opts.onError?.(err, ref);
4632
- }
4633
- }
4634
- }
4635
- for (const f of report.stuckLoops.findings) {
4636
- const key = loopKey(ref.sessionId, f.toolName, f.argHash);
4637
- if (f.occurrences > (seen.get(key) ?? 0)) {
4638
- seen.set(key, f.occurrences);
4639
- if (opts.onLoop) {
4640
- try {
4641
- await opts.onLoop({
4642
- harness: adapter.harness,
4643
- sessionId: ref.sessionId,
4644
- cwd: ref.cwd,
4645
- toolName: f.toolName,
4646
- argHash: f.argHash,
4647
- occurrences: f.occurrences,
4648
- windowMs: f.windowMs
4649
- });
4650
- } catch (err) {
4651
- opts.onError?.(err, ref);
4652
- }
4653
- }
4702
+ } else if (event.event === "finding") {
4703
+ await callSafely(void 0, opts.onError, () => opts.onFinding?.(event.finding));
4704
+ } else if (event.event === "report") {
4705
+ await callSafely(event.ref, opts.onError, () => opts.onReport?.(event.ref, event.report));
4706
+ for (const loop of event.loops) {
4707
+ const key = loopKey(loop);
4708
+ if (loop.occurrences <= (seenLoops.get(key) ?? 0)) continue;
4709
+ seenLoops.set(key, loop.occurrences);
4710
+ await callSafely(event.ref, opts.onError, () => opts.onLoop?.(loop));
4654
4711
  }
4712
+ } else if (event.event === "tick") {
4713
+ await callSafely(void 0, opts.onError, () => opts.onTick?.({ sessions: event.sessions }));
4655
4714
  }
4656
4715
  }
4657
- try {
4658
- opts.onTick?.({ sessions: sessionCount });
4659
- } catch (err) {
4660
- opts.onError?.(err);
4661
- }
4662
- if (opts.signal?.aborted) break;
4663
- await sleep2(intervalMs, opts.signal);
4664
- }
4716
+ });
4665
4717
  }
4666
4718
 
4667
4719
  // src/session-index.ts
@@ -5140,6 +5192,8 @@ export {
5140
5192
  writeTraceImprovementArtifacts,
5141
5193
  runTraceImprovementLoop,
5142
5194
  saveReport,
5195
+ classifyLiveActions,
5196
+ defaultTraceLiveAnalysts,
5143
5197
  analyzeLiveBatch,
5144
5198
  traceStreamEventsFromSpans,
5145
5199
  serializeTraceStreamEvent,