@tangle-network/traces 0.20.0 → 0.21.1

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 CHANGED
@@ -364,6 +364,7 @@ See [Replay verification](./docs/replay-verify.md) for setup, semantics, and hon
364
364
  | `--question <text>` | `ask`: one question, repeatable. Kept short so the engine sees it whole |
365
365
  | `--questions <file>` | `ask`: JSON array of questions — strings, or `{ id?, question, instructions?, answerSchema? }` |
366
366
  | `--question-budget <usd>` | `ask`: provider ceiling for ONE question; `--budget` is the ceiling shared by all of them |
367
+ | `--question-timeout <seconds>` | `ask`: wall-clock deadline for ONE question's investigation (default 600); raise it for questions over many large sessions |
367
368
  | `--concurrency <n>` | `ask`: questions running at once (default 4); `import-codetracebench`: trajectories imported at once |
368
369
  | `--config <path>` | `analyze` / `investigate` / `improve` / `stream`: load BYO analysts, live analysts, and external analyzers |
369
370
  | `--interval <s>` / `--window <m>` | `watch` / live `stream`: poll seconds (sessions 5, run tree 2) / active-session window minutes (default 30) |
@@ -17497,12 +17497,14 @@ function asRecord(v) {
17497
17497
  function str(v) {
17498
17498
  return typeof v === "string" && v.length > 0 ? v : null;
17499
17499
  }
17500
+ var RETIRED_WAIT_KINDS = /* @__PURE__ */ new Set(["waiting", "woken"]);
17500
17501
  function readRunContextJournal(text2) {
17501
17502
  const parsed = readJsonlLines(text2);
17502
17503
  let root = null;
17503
17504
  let begunAt = null;
17504
17505
  const events = [];
17505
17506
  let invalidRows = parsed.invalidRows;
17507
+ let retiredWaitRows = 0;
17506
17508
  for (const record2 of parsed.rows) {
17507
17509
  const recordRoot = str(record2.root);
17508
17510
  if (root === null && recordRoot !== null) root = recordRoot;
@@ -17519,11 +17521,15 @@ function readRunContextJournal(text2) {
17519
17521
  invalidRows += 1;
17520
17522
  continue;
17521
17523
  }
17524
+ if (RETIRED_WAIT_KINDS.has(event.kind)) {
17525
+ retiredWaitRows += 1;
17526
+ continue;
17527
+ }
17522
17528
  events.push(event);
17523
17529
  }
17524
17530
  const supervisorIds = /* @__PURE__ */ new Set();
17525
17531
  for (const event of events) {
17526
- if (event.kind !== "spawned" && event.kind !== "waiting") continue;
17532
+ if (event.kind !== "spawned") continue;
17527
17533
  const parent = event.parent;
17528
17534
  if (typeof parent === "string" && parent.length > 0) supervisorIds.add(parent);
17529
17535
  }
@@ -17533,6 +17539,7 @@ function readRunContextJournal(text2) {
17533
17539
  events,
17534
17540
  supervisorIds,
17535
17541
  invalidRows,
17542
+ retiredWaitRows,
17536
17543
  partialTail: parsed.partialTail,
17537
17544
  present: parsed.present
17538
17545
  };
@@ -17722,6 +17729,7 @@ async function readRunContextSnapshot(runDir) {
17722
17729
  result,
17723
17730
  terminal: resultText !== null,
17724
17731
  invalidJournalRows: journal.invalidRows,
17732
+ retiredWaitRows: journal.retiredWaitRows,
17725
17733
  invalidCoordinationRows: coordination.invalidRows,
17726
17734
  partialTail: journal.partialTail || coordination.partialTail,
17727
17735
  treeError: view === null && journal.present ? "spawn journal could not be folded into a tree (a settle or cancel names a node that was never spawned)" : null
@@ -17745,7 +17753,7 @@ function orderNodes(view, journal) {
17745
17753
  const parentOf = new Map(view.nodes.map((n) => [n.id, n.parent]));
17746
17754
  for (const event of journal.events) {
17747
17755
  const at = parseInstant(event.at);
17748
- if (event.kind === "spawned" || event.kind === "waiting") {
17756
+ if (event.kind === "spawned") {
17749
17757
  spawnedAt.set(event.id, at);
17750
17758
  } else if (event.kind === "metered") {
17751
17759
  driver.set(event.id, addSpend(driver.get(event.id) ?? ZERO_ROLL, event.spend));
@@ -17759,8 +17767,6 @@ function orderNodes(view, journal) {
17759
17767
  } else if (event.kind === "cancelled") {
17760
17768
  settledAt.set(event.id, at);
17761
17769
  cancelReason.set(event.id, event.reason);
17762
- } else if (event.kind === "woken") {
17763
- settledAt.set(event.id, at);
17764
17770
  }
17765
17771
  }
17766
17772
  const byParent = /* @__PURE__ */ new Map();
@@ -17844,7 +17850,6 @@ var STATUS_MARK = {
17844
17850
  pending: "\xB7",
17845
17851
  acquiring: "\u25D0",
17846
17852
  running: "\u25B6",
17847
- waiting: "\u23F8",
17848
17853
  done: "\u2713",
17849
17854
  failed: "\u2717",
17850
17855
  cancelled: "\u2298"
@@ -18265,6 +18270,9 @@ function renderRunContextSnapshot(snapshot) {
18265
18270
  }
18266
18271
  const problems = [];
18267
18272
  if (snapshot.invalidJournalRows > 0) problems.push(`${snapshot.invalidJournalRows} unreadable journal row(s)`);
18273
+ if (snapshot.retiredWaitRows > 0) {
18274
+ problems.push(`${snapshot.retiredWaitRows} wait-state journal row(s) from an older Runtime left out of the tree`);
18275
+ }
18268
18276
  if (snapshot.invalidCoordinationRows > 0) {
18269
18277
  problems.push(`${snapshot.invalidCoordinationRows} unreadable coordination row(s)`);
18270
18278
  }
@@ -18447,6 +18455,7 @@ import { profileOptimizerModelCall } from "@tangle-network/agent-runtime/kernel"
18447
18455
  import { createDspyRlmTraceEngine } from "@tangle-network/agent-eval/analyst";
18448
18456
  var DEFAULT_ANALYST_MODEL = "gpt-5.6-luna";
18449
18457
  var DEFAULT_QUESTION_MAX_COST_USD = 1;
18458
+ var DEFAULT_QUESTION_TIMEOUT_MS = 6e5;
18450
18459
  var TANGLE_ROUTER_BASE_URL = "https://router.tangle.tools/v1";
18451
18460
  var ANALYST_MAX_OUTPUT_TOKENS = 16384;
18452
18461
  var GPT_5_6_ANALYST_MAX_OUTPUT_TOKENS = 8192;
@@ -18462,7 +18471,11 @@ function createAnalystModelOwner(opts) {
18462
18471
  provider: opts.provider,
18463
18472
  default: opts.model,
18464
18473
  reasoningEffort: "none",
18465
- maxVisibleOutputTokens: maxOutputTokens
18474
+ maxVisibleOutputTokens: maxOutputTokens,
18475
+ // Stream every analyst call. The Tangle Router bounds a buffered request by a deadline that
18476
+ // ends when response headers are sent, and a thinking model's long recursive step outlives
18477
+ // it (`request_deadline_exceeded`). A streamed response sends headers at the first byte.
18478
+ metadata: { stream: true }
18466
18479
  }
18467
18480
  };
18468
18481
  return {
@@ -18521,6 +18534,7 @@ function analysisEngineFromEnv(opts) {
18521
18534
  // reservation grows ~4x, so that default can bind before the caller's own
18522
18535
  // allocation and kill investigations mid-run.
18523
18536
  ...opts.maxCostUsd !== void 0 && Number.isFinite(opts.maxCostUsd) && opts.maxCostUsd > 0 ? { maxCostUsd: opts.maxCostUsd } : {},
18537
+ timeoutMs: opts.timeoutMs ?? DEFAULT_QUESTION_TIMEOUT_MS,
18524
18538
  ...python ? { runner: { command: python } } : {}
18525
18539
  });
18526
18540
  }
@@ -19108,6 +19122,7 @@ async function runTraceQuestions(opts) {
19108
19122
  effectiveConcurrency,
19109
19123
  budgetUsd: budgetUsd ?? null,
19110
19124
  questionBudgetUsd: typeof opts.engine.executionConfig.max_cost_usd === "number" ? opts.engine.executionConfig.max_cost_usd : null,
19125
+ questionTimeoutMs: typeof opts.engine.executionConfig.timeout_ms === "number" ? opts.engine.executionConfig.timeout_ms : null,
19111
19126
  spanCount: opts.spans.length,
19112
19127
  otlpPath: traceFile.otlpPath,
19113
19128
  traces,
@@ -20874,6 +20889,7 @@ export {
20874
20889
  watchRunTarget,
20875
20890
  DEFAULT_ANALYST_MODEL,
20876
20891
  DEFAULT_QUESTION_MAX_COST_USD,
20892
+ DEFAULT_QUESTION_TIMEOUT_MS,
20877
20893
  analysisEngineFromEnv,
20878
20894
  assertAnswerSchema,
20879
20895
  answerSchemaErrors,
package/dist/cli.js CHANGED
@@ -2,6 +2,7 @@
2
2
  import {
3
3
  DEFAULT_ANALYST_MODEL,
4
4
  DEFAULT_QUESTION_MAX_COST_USD,
5
+ DEFAULT_QUESTION_TIMEOUT_MS,
5
6
  DEFAULT_SANDBOX_BASE_URL,
6
7
  DEFAULT_SWEEP_THRESHOLD,
7
8
  MAX_TRACE_QUESTION_CHARS,
@@ -89,7 +90,7 @@ import {
89
90
  writeSessionIndexFile,
90
91
  writeTraceEvidenceExportFile,
91
92
  writeTraceQuestionsArtifacts
92
- } from "./chunk-2NINDZCW.js";
93
+ } from "./chunk-LB6AD6SX.js";
93
94
 
94
95
  // src/cli.ts
95
96
  import { readFileSync } from "fs";
@@ -590,6 +591,9 @@ function parseArgs(argv) {
590
591
  case "--question-budget":
591
592
  a.questionBudget = Number(next());
592
593
  break;
594
+ case "--question-timeout":
595
+ a.questionTimeout = Number(next());
596
+ break;
593
597
  case "--redactor":
594
598
  a.redactorCmd = next();
595
599
  break;
@@ -1523,9 +1527,14 @@ async function cmdAsk(args) {
1523
1527
  if (args.budget !== void 0 && (!Number.isFinite(args.budget) || args.budget <= 0)) {
1524
1528
  throw new Error("--budget must be a positive number of USD");
1525
1529
  }
1530
+ const questionTimeoutMs = args.questionTimeout === void 0 ? void 0 : Math.round(args.questionTimeout * 1e3);
1531
+ if (questionTimeoutMs !== void 0 && (!Number.isSafeInteger(questionTimeoutMs) || questionTimeoutMs < 1e3)) {
1532
+ throw new Error("--question-timeout must be a number of seconds, at least 1");
1533
+ }
1526
1534
  const engine = analysisEngineFromEnv({
1527
1535
  model: analystModelFor(args),
1528
1536
  maxCostUsd: args.questionBudget ?? Math.min(args.budget ?? Infinity, DEFAULT_QUESTION_MAX_COST_USD),
1537
+ ...questionTimeoutMs !== void 0 ? { timeoutMs: questionTimeoutMs } : {},
1529
1538
  log: analystLog
1530
1539
  });
1531
1540
  const collected = await collectSpans(args);
@@ -2161,6 +2170,9 @@ Options:
2161
2170
  --question-budget <usd>
2162
2171
  ask: provider ceiling for one question (default: the smaller
2163
2172
  of --budget and $${DEFAULT_QUESTION_MAX_COST_USD})
2173
+ --question-timeout <seconds>
2174
+ ask: wall-clock deadline for one question's investigation
2175
+ (default: ${DEFAULT_QUESTION_TIMEOUT_MS / 1e3})
2164
2176
  --concurrency <n> ask: questions running at once (default 4);
2165
2177
  import-codetracebench: trajectories imported at once
2166
2178
  --analyzer <id> analyze: also run halo, hodoscope, prime, or an installed command (repeatable);
package/dist/index.d.ts CHANGED
@@ -3593,6 +3593,8 @@ interface TraceQuestionsResult {
3593
3593
  readonly budgetUsd: number | null;
3594
3594
  /** The engine's own ceiling for one question, when it declares one. */
3595
3595
  readonly questionBudgetUsd: number | null;
3596
+ /** The engine's wall-clock deadline for one question, when it declares one. */
3597
+ readonly questionTimeoutMs: number | null;
3596
3598
  readonly spanCount: number;
3597
3599
  readonly otlpPath: string;
3598
3600
  readonly traces: readonly TraceQuestionTrace[];
@@ -4154,6 +4156,8 @@ interface AnalysisEngineFromEnvOptions {
4154
4156
  * cap here and the total to the ledger.
4155
4157
  */
4156
4158
  maxCostUsd?: number;
4159
+ /** Wall-clock deadline for ONE investigation. Default: {@link DEFAULT_QUESTION_TIMEOUT_MS}. */
4160
+ timeoutMs?: number;
4157
4161
  /** Receives one line per model call, in the CLI's analyst log format. */
4158
4162
  log?: (msg: string, fields?: Record<string, unknown>) => void;
4159
4163
  /** Environment to read credentials and the Python interpreter from. Default: process.env. */
@@ -4389,6 +4393,8 @@ interface RunContextJournal {
4389
4393
  /** Node ids that appear as some spawn's `parent` — the exact supervisor set. */
4390
4394
  readonly supervisorIds: ReadonlySet<string>;
4391
4395
  readonly invalidRows: number;
4396
+ /** Readable `waiting`/`woken` rows from a Runtime that still had wait-state nodes. */
4397
+ readonly retiredWaitRows: number;
4392
4398
  readonly partialTail: boolean;
4393
4399
  readonly present: boolean;
4394
4400
  }
@@ -4526,6 +4532,8 @@ interface RunContextSnapshot {
4526
4532
  readonly terminal: boolean;
4527
4533
  /** Rows that were present and unreadable, per artifact. */
4528
4534
  readonly invalidJournalRows: number;
4535
+ /** Wait-state rows from a pre-0.305 Runtime, left out of the tree. */
4536
+ readonly retiredWaitRows: number;
4529
4537
  readonly invalidCoordinationRows: number;
4530
4538
  /** True when an artifact's last line was still being written. */
4531
4539
  readonly partialTail: boolean;
package/dist/index.js CHANGED
@@ -284,7 +284,7 @@ import {
284
284
  writeTraceQuestionsArtifacts,
285
285
  zaiChatCaller,
286
286
  zeroPricedCost
287
- } from "./chunk-2NINDZCW.js";
287
+ } from "./chunk-LB6AD6SX.js";
288
288
 
289
289
  // src/adapters/factory.ts
290
290
  import { readdir, stat } from "fs/promises";
@@ -124,6 +124,7 @@ This package carries no JSON Schema library, and a constraint that is quietly ig
124
124
  - Ctrl-C keeps what the run already bought. The signal reaches the engine, not the checks that follow it: an answer that came back is kept with its citations resolved, and each question the run never reached is recorded as `aborted`.
125
125
  - The artifacts are written before the exit code is decided. `ask` exits 1 when any question failed, returned no answer, broke its schema, or cited a missing span.
126
126
  - `totals.wallTimeMs` covers the whole run, including writing and indexing the trace file; `totals.setupTimeMs` names that part. `result.effectiveConcurrency` is the number of workers the run created, `min(--concurrency, questions)`, and `totals.peakConcurrency` is how many actually overlapped.
127
+ - `--question-timeout <seconds>` is the wall-clock deadline for one question's investigation (default 600). A question over many large sessions can need longer; the timeout fails that question alone.
127
128
 
128
129
  ### Budget under concurrency
129
130
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tangle-network/traces",
3
- "version": "0.20.0",
3
+ "version": "0.21.1",
4
4
  "description": "Point it at your coding-agent session traces (Claude Code, Codex, OpenCode, Gemini, Pi, \u2026) and get failure-mode + efficiency findings. CLI + SDK over the @tangle-network/agent-eval analyst suite \u2014 observe live sessions, run your own analysts, redact, and upload to the Tangle Intelligence Platform.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -61,9 +61,9 @@
61
61
  "prepublishOnly": "pnpm check:source && pnpm build && pnpm check:package"
62
62
  },
63
63
  "dependencies": {
64
- "@tangle-network/agent-eval": "0.205.1",
65
- "@tangle-network/agent-interface": "2.17.0",
66
- "@tangle-network/agent-runtime": "0.293.0",
64
+ "@tangle-network/agent-eval": "0.209.1",
65
+ "@tangle-network/agent-interface": "3.1.2",
66
+ "@tangle-network/agent-runtime": "0.313.3",
67
67
  "@tangle-network/agent-trace-contract": "2.0.0",
68
68
  "@tangle-network/harness-sessions": "0.1.0",
69
69
  "@tangle-network/sandbox": "0.60.10"