@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.
- package/README.md +64 -30
- package/dist/{chunk-G3OBZSWY.js → chunk-FCTZLWP7.js} +234 -180
- package/dist/cli.js +51 -24
- package/dist/index.d.ts +172 -135
- package/dist/index.js +5 -1
- package/package.json +1 -1
|
@@ -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
|
-
|
|
4343
|
-
|
|
4344
|
-
|
|
4345
|
-
|
|
4346
|
-
|
|
4347
|
-
|
|
4348
|
-
|
|
4349
|
-
|
|
4350
|
-
|
|
4351
|
-
|
|
4352
|
-
|
|
4353
|
-
|
|
4354
|
-
|
|
4355
|
-
|
|
4356
|
-
|
|
4357
|
-
|
|
4358
|
-
|
|
4359
|
-
|
|
4360
|
-
|
|
4361
|
-
|
|
4362
|
-
|
|
4363
|
-
|
|
4364
|
-
|
|
4365
|
-
|
|
4366
|
-
|
|
4367
|
-
|
|
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
|
-
|
|
4389
|
-
|
|
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(
|
|
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
|
-
|
|
4406
|
-
|
|
4407
|
-
|
|
4408
|
-
|
|
4409
|
-
|
|
4410
|
-
|
|
4411
|
-
|
|
4412
|
-
|
|
4413
|
-
|
|
4414
|
-
|
|
4415
|
-
|
|
4416
|
-
|
|
4417
|
-
|
|
4418
|
-
|
|
4419
|
-
|
|
4420
|
-
|
|
4421
|
-
|
|
4422
|
-
|
|
4423
|
-
|
|
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
|
-
|
|
4428
|
-
|
|
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:
|
|
4453
|
-
changeCallCount:
|
|
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, {
|
|
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, {
|
|
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
|
-
|
|
4565
|
-
|
|
4566
|
-
|
|
4567
|
-
|
|
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
|
|
4584
|
-
|
|
4585
|
-
|
|
4586
|
-
|
|
4587
|
-
|
|
4588
|
-
|
|
4589
|
-
|
|
4590
|
-
|
|
4591
|
-
|
|
4592
|
-
|
|
4593
|
-
|
|
4594
|
-
|
|
4595
|
-
|
|
4596
|
-
|
|
4597
|
-
|
|
4598
|
-
|
|
4599
|
-
|
|
4600
|
-
|
|
4601
|
-
|
|
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
|
-
|
|
4615
|
-
|
|
4616
|
-
|
|
4617
|
-
|
|
4618
|
-
|
|
4619
|
-
|
|
4620
|
-
|
|
4621
|
-
opts.onError
|
|
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
|
-
|
|
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,
|