@tangle-network/traces 0.21.1 → 0.22.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.
- package/README.md +0 -2
- package/dist/{chunk-LB6AD6SX.js → chunk-DON6NQ7H.js} +425 -529
- package/dist/cli.js +1 -1
- package/dist/index.d.ts +7 -26
- package/dist/index.js +1 -3
- package/package.json +6 -6
|
@@ -110,7 +110,7 @@ var ATTR = {
|
|
|
110
110
|
* (`deriveSubjectKey` reads `tangle.subject.key` first). Resolves to the git
|
|
111
111
|
* remote (host/owner/repo) when readable, else the cwd path basename. */
|
|
112
112
|
SUBJECT_KEY: "tangle.subject.key",
|
|
113
|
-
/** Normalized git remote (e.g. `github.com/tangle-network/agent-
|
|
113
|
+
/** Normalized git remote (e.g. `github.com/tangle-network/agent-container`). */
|
|
114
114
|
GIT_REPOSITORY: "git.repository",
|
|
115
115
|
/** Current branch at conversion time. */
|
|
116
116
|
GIT_BRANCH_NAME: "git.branch",
|
|
@@ -1024,8 +1024,8 @@ var OTLP_WRITE_CHUNK_CHARS = 4 * 1024 * 1024;
|
|
|
1024
1024
|
async function writeOtlpFile(spans, outPath) {
|
|
1025
1025
|
const { mkdtemp: mkdtemp8, open: open4 } = await import("fs/promises");
|
|
1026
1026
|
const { tmpdir: tmpdir8 } = await import("os");
|
|
1027
|
-
const { join:
|
|
1028
|
-
const path = outPath ??
|
|
1027
|
+
const { join: join35 } = await import("path");
|
|
1028
|
+
const path = outPath ?? join35(await mkdtemp8(join35(tmpdir8(), "traces-")), "spans.otlp.jsonl");
|
|
1029
1029
|
const handle = await open4(path, "w");
|
|
1030
1030
|
try {
|
|
1031
1031
|
let chunk = "";
|
|
@@ -2406,143 +2406,10 @@ var CopilotAdapter = class {
|
|
|
2406
2406
|
}
|
|
2407
2407
|
};
|
|
2408
2408
|
|
|
2409
|
-
// src/adapters/
|
|
2409
|
+
// src/adapters/gemini.ts
|
|
2410
2410
|
import { readdir as readdir5, stat as stat4 } from "fs/promises";
|
|
2411
2411
|
import { homedir as homedir3 } from "os";
|
|
2412
|
-
import {
|
|
2413
|
-
var SERVICE4 = "forge";
|
|
2414
|
-
function tokens(t) {
|
|
2415
|
-
if (!t) return null;
|
|
2416
|
-
return t.actual ?? t.approx ?? null;
|
|
2417
|
-
}
|
|
2418
|
-
function textOf2(content) {
|
|
2419
|
-
return capText(content ?? "");
|
|
2420
|
-
}
|
|
2421
|
-
var ForgeAdapter = class {
|
|
2422
|
-
harness = "forge";
|
|
2423
|
-
aliases = ["forgecode"];
|
|
2424
|
-
/** Directories scanned for `*-dump.json` exports. */
|
|
2425
|
-
dumpDirs() {
|
|
2426
|
-
return [process.cwd(), join5(homedir3(), ".forge")];
|
|
2427
|
-
}
|
|
2428
|
-
async locate(opts = {}) {
|
|
2429
|
-
const refs = [];
|
|
2430
|
-
const dirs = opts.cwd ? [opts.cwd] : this.dumpDirs();
|
|
2431
|
-
for (const dir of dirs) {
|
|
2432
|
-
let files;
|
|
2433
|
-
try {
|
|
2434
|
-
files = await readdir5(dir);
|
|
2435
|
-
} catch (error) {
|
|
2436
|
-
if (isMissingPathError(error)) continue;
|
|
2437
|
-
throw error;
|
|
2438
|
-
}
|
|
2439
|
-
for (const f of files) {
|
|
2440
|
-
if (!f.endsWith("-dump.json")) continue;
|
|
2441
|
-
const path = join5(dir, f);
|
|
2442
|
-
let st;
|
|
2443
|
-
try {
|
|
2444
|
-
st = await stat4(path);
|
|
2445
|
-
} catch (error) {
|
|
2446
|
-
if (isMissingPathError(error)) continue;
|
|
2447
|
-
throw error;
|
|
2448
|
-
}
|
|
2449
|
-
if (opts.sinceMs && st.mtimeMs < opts.sinceMs) continue;
|
|
2450
|
-
refs.push({ harness: this.harness, sessionId: basename3(f, ".json"), path, cwd: dir, mtimeMs: st.mtimeMs });
|
|
2451
|
-
}
|
|
2452
|
-
}
|
|
2453
|
-
return refs.sort((a, b) => b.mtimeMs - a.mtimeMs);
|
|
2454
|
-
}
|
|
2455
|
-
async parse(ref, options = {}) {
|
|
2456
|
-
const dump = await readJsonFile(ref.path, options);
|
|
2457
|
-
const ctx = dump.context ?? dump;
|
|
2458
|
-
const traceId = ctx.conversation_id ?? ref.sessionId;
|
|
2459
|
-
const rootId = `root:${traceId}`;
|
|
2460
|
-
const messages = ctx.messages ?? [];
|
|
2461
|
-
const spans = [
|
|
2462
|
-
span({ traceId, spanId: rootId, parentSpanId: null, name: "session", kind: "AGENT", startTime: (/* @__PURE__ */ new Date(0)).toISOString(), service: SERVICE4, agent: SERVICE4 })
|
|
2463
|
-
];
|
|
2464
|
-
if (ctx.conversation_id) spans[0].attributes["tangle.sessionId"] = ctx.conversation_id;
|
|
2465
|
-
const toolByCallId = /* @__PURE__ */ new Map();
|
|
2466
|
-
let step = 0;
|
|
2467
|
-
let lastLlm = rootId;
|
|
2468
|
-
for (const raw of messages) {
|
|
2469
|
-
const entry = raw.message ?? raw;
|
|
2470
|
-
const ts = (/* @__PURE__ */ new Date(0)).toISOString();
|
|
2471
|
-
if (entry.text && entry.text.role === "user") {
|
|
2472
|
-
const prompt = textOf2(entry.text.content);
|
|
2473
|
-
if (prompt) {
|
|
2474
|
-
spans.push(
|
|
2475
|
-
userPromptSpan({
|
|
2476
|
-
traceId,
|
|
2477
|
-
spanId: `user:${step}`,
|
|
2478
|
-
parentSpanId: rootId,
|
|
2479
|
-
startTime: ts,
|
|
2480
|
-
content: prompt,
|
|
2481
|
-
contentSource: textSources(entry.text, "content"),
|
|
2482
|
-
service: SERVICE4,
|
|
2483
|
-
agent: SERVICE4,
|
|
2484
|
-
step
|
|
2485
|
-
})
|
|
2486
|
-
);
|
|
2487
|
-
step += 1;
|
|
2488
|
-
}
|
|
2489
|
-
} else if (entry.text) {
|
|
2490
|
-
const llmId = `llm:${step}`;
|
|
2491
|
-
spans.push(
|
|
2492
|
-
span({
|
|
2493
|
-
traceId,
|
|
2494
|
-
spanId: llmId,
|
|
2495
|
-
parentSpanId: rootId,
|
|
2496
|
-
name: `message.${entry.text.role ?? "unknown"}`,
|
|
2497
|
-
kind: "LLM",
|
|
2498
|
-
startTime: ts,
|
|
2499
|
-
service: SERVICE4,
|
|
2500
|
-
agent: SERVICE4,
|
|
2501
|
-
model: entry.text.model ?? null,
|
|
2502
|
-
inputTokens: tokens(raw.usage?.prompt_tokens),
|
|
2503
|
-
outputTokens: tokens(raw.usage?.completion_tokens),
|
|
2504
|
-
step,
|
|
2505
|
-
content: textOf2(entry.text.content) || null,
|
|
2506
|
-
contentSource: textSources(entry.text, "content")
|
|
2507
|
-
})
|
|
2508
|
-
);
|
|
2509
|
-
lastLlm = llmId;
|
|
2510
|
-
step += 1;
|
|
2511
|
-
for (const tc of entry.text.tool_calls ?? []) {
|
|
2512
|
-
const id = tc.call_id ?? `${step}`;
|
|
2513
|
-
const t = span({
|
|
2514
|
-
traceId,
|
|
2515
|
-
spanId: `tool:${id}`,
|
|
2516
|
-
parentSpanId: llmId,
|
|
2517
|
-
name: `tool.${tc.name ?? "tool"}`,
|
|
2518
|
-
kind: "TOOL",
|
|
2519
|
-
startTime: ts,
|
|
2520
|
-
service: SERVICE4,
|
|
2521
|
-
agent: SERVICE4,
|
|
2522
|
-
tool: tc.name ?? "tool",
|
|
2523
|
-
step,
|
|
2524
|
-
extra: toolIoAttributes({ input: tc.arguments, inputSource: sourceOf(tc, "arguments") })
|
|
2525
|
-
});
|
|
2526
|
-
spans.push(t);
|
|
2527
|
-
toolByCallId.set(id, t);
|
|
2528
|
-
step += 1;
|
|
2529
|
-
}
|
|
2530
|
-
} else if (entry.tool) {
|
|
2531
|
-
const t = toolByCallId.get(entry.tool.call_id ?? "");
|
|
2532
|
-
if (t) {
|
|
2533
|
-
t.status = entry.tool.output?.is_error ? { code: "ERROR", message: "tool reported error" } : { code: "OK" };
|
|
2534
|
-
recordToolOutput(t, entry.tool.output?.values ?? entry.tool.output, entry.tool.output?.values != null ? sourceOf(entry.tool.output, "values") : sourceOf(entry.tool, "output"));
|
|
2535
|
-
}
|
|
2536
|
-
}
|
|
2537
|
-
}
|
|
2538
|
-
return spans;
|
|
2539
|
-
}
|
|
2540
|
-
};
|
|
2541
|
-
|
|
2542
|
-
// src/adapters/gemini.ts
|
|
2543
|
-
import { readdir as readdir6, stat as stat5 } from "fs/promises";
|
|
2544
|
-
import { homedir as homedir4 } from "os";
|
|
2545
|
-
import { join as join6 } from "path";
|
|
2412
|
+
import { join as join5 } from "path";
|
|
2546
2413
|
function iso(ts, fallback) {
|
|
2547
2414
|
if (typeof ts === "number") return new Date(ts).toISOString();
|
|
2548
2415
|
if (typeof ts === "string" && ts.length > 0) return ts;
|
|
@@ -2551,7 +2418,7 @@ function iso(ts, fallback) {
|
|
|
2551
2418
|
function toolStatusError(status2) {
|
|
2552
2419
|
return status2 != null && /error|fail|cancel/i.test(status2);
|
|
2553
2420
|
}
|
|
2554
|
-
function
|
|
2421
|
+
function textOf2(content) {
|
|
2555
2422
|
const s = typeof content === "string" ? content : JSON.stringify(content ?? "");
|
|
2556
2423
|
return capText(s);
|
|
2557
2424
|
}
|
|
@@ -2567,7 +2434,7 @@ var GeminiFamilyAdapter = class {
|
|
|
2567
2434
|
this.homeDirName = cfg.homeDirName;
|
|
2568
2435
|
}
|
|
2569
2436
|
chatsRoot() {
|
|
2570
|
-
return
|
|
2437
|
+
return join5(homedir3(), this.homeDirName, "tmp");
|
|
2571
2438
|
}
|
|
2572
2439
|
/** `<home>/projects.json` maps `{ <absolute-cwd>: <projectName> }`. The session
|
|
2573
2440
|
* dir name (`tmp/<projectHash>/`) is that projectName for registered projects,
|
|
@@ -2577,7 +2444,7 @@ var GeminiFamilyAdapter = class {
|
|
|
2577
2444
|
const nameToPath = /* @__PURE__ */ new Map();
|
|
2578
2445
|
try {
|
|
2579
2446
|
const projects = (await readJsonFile(
|
|
2580
|
-
|
|
2447
|
+
join5(homedir3(), this.homeDirName, "projects.json")
|
|
2581
2448
|
)).projects ?? {};
|
|
2582
2449
|
for (const [path, name] of Object.entries(projects)) nameToPath.set(name, path);
|
|
2583
2450
|
} catch (error) {
|
|
@@ -2589,7 +2456,7 @@ var GeminiFamilyAdapter = class {
|
|
|
2589
2456
|
const root = this.chatsRoot();
|
|
2590
2457
|
let projectDirs;
|
|
2591
2458
|
try {
|
|
2592
|
-
projectDirs = await
|
|
2459
|
+
projectDirs = await readdir5(root);
|
|
2593
2460
|
} catch (error) {
|
|
2594
2461
|
if (isMissingPathError(error)) return [];
|
|
2595
2462
|
throw error;
|
|
@@ -2598,20 +2465,20 @@ var GeminiFamilyAdapter = class {
|
|
|
2598
2465
|
const refs = [];
|
|
2599
2466
|
for (const pd of projectDirs) {
|
|
2600
2467
|
const cwd = projectCwds.get(pd) ?? null;
|
|
2601
|
-
const chatsDir =
|
|
2468
|
+
const chatsDir = join5(root, pd, "chats");
|
|
2602
2469
|
let files;
|
|
2603
2470
|
try {
|
|
2604
|
-
files = await
|
|
2471
|
+
files = await readdir5(chatsDir);
|
|
2605
2472
|
} catch (error) {
|
|
2606
2473
|
if (isMissingPathError(error)) continue;
|
|
2607
2474
|
throw error;
|
|
2608
2475
|
}
|
|
2609
2476
|
for (const f of files) {
|
|
2610
2477
|
if (!f.startsWith("session-") || !f.endsWith(".json")) continue;
|
|
2611
|
-
const path =
|
|
2478
|
+
const path = join5(chatsDir, f);
|
|
2612
2479
|
let st;
|
|
2613
2480
|
try {
|
|
2614
|
-
st = await
|
|
2481
|
+
st = await stat4(path);
|
|
2615
2482
|
} catch (error) {
|
|
2616
2483
|
if (isMissingPathError(error)) continue;
|
|
2617
2484
|
throw error;
|
|
@@ -2649,7 +2516,7 @@ var GeminiFamilyAdapter = class {
|
|
|
2649
2516
|
const ts = iso(m.timestamp, start);
|
|
2650
2517
|
const llmId = `llm:${mid}`;
|
|
2651
2518
|
if (m.type === "user") {
|
|
2652
|
-
const prompt =
|
|
2519
|
+
const prompt = textOf2(m.content);
|
|
2653
2520
|
if (prompt) {
|
|
2654
2521
|
spans.push(
|
|
2655
2522
|
userPromptSpan({
|
|
@@ -2681,7 +2548,7 @@ var GeminiFamilyAdapter = class {
|
|
|
2681
2548
|
inputTokens: m.tokens?.input ?? null,
|
|
2682
2549
|
outputTokens: m.tokens?.output ?? null,
|
|
2683
2550
|
step,
|
|
2684
|
-
content:
|
|
2551
|
+
content: textOf2(m.content) || null,
|
|
2685
2552
|
contentSource: sourceOf(m, "content")
|
|
2686
2553
|
})
|
|
2687
2554
|
);
|
|
@@ -2766,6 +2633,22 @@ var SYNTHETIC_MARKERS = [
|
|
|
2766
2633
|
"Staff-engineer code review"
|
|
2767
2634
|
];
|
|
2768
2635
|
var AGENT_PROMPT = /^(you are\b|you're\b|read[- ]only\b|stop now\b|your task\b|your job\b|review the\b|audit\b|analyze the\b|return (only|a |the )|here is the\b|context:|task:|do not (revert|edit|touch)|work only in\b|you have been\b|act as\b|operate the\b|goal:|objective:)/i;
|
|
2636
|
+
var CLAUDE_MACHINE_PREFIXES = [
|
|
2637
|
+
"<local-command-caveat>",
|
|
2638
|
+
"<local-command-stdout>",
|
|
2639
|
+
"<local-command-stderr>",
|
|
2640
|
+
"Caveat: The messages below",
|
|
2641
|
+
"<task-notification>",
|
|
2642
|
+
"<bash-stdout>",
|
|
2643
|
+
"<bash-stderr>",
|
|
2644
|
+
"<user-prompt-submit-hook>",
|
|
2645
|
+
"[Request interrupted by user"
|
|
2646
|
+
];
|
|
2647
|
+
function claudeRecordIsMachine(args) {
|
|
2648
|
+
if (args.isMeta === true || args.isCompactSummary === true || args.entrypoint === "sdk-cli") return true;
|
|
2649
|
+
const text2 = args.text.trimStart();
|
|
2650
|
+
return CLAUDE_MACHINE_PREFIXES.some((prefix) => text2.startsWith(prefix));
|
|
2651
|
+
}
|
|
2769
2652
|
function textIsCmdOrInject(s) {
|
|
2770
2653
|
return CMD_MARKERS.some((m) => s.includes(m)) || INJECT_MARKERS.some((m) => s.includes(m));
|
|
2771
2654
|
}
|
|
@@ -2803,7 +2686,7 @@ function claudePromptStartsTask(args) {
|
|
|
2803
2686
|
}
|
|
2804
2687
|
function claudeActor(args) {
|
|
2805
2688
|
if (args.isSidechain === true) return "subagent-spawn";
|
|
2806
|
-
if (args
|
|
2689
|
+
if (claudeRecordIsMachine(args)) return "injected";
|
|
2807
2690
|
if (args.userType != null && args.userType !== "external") return "injected";
|
|
2808
2691
|
if (textIsCmdOrInject(args.text)) return "injected";
|
|
2809
2692
|
if (textIsSynthetic(args.text)) return "injected";
|
|
@@ -2848,6 +2731,7 @@ function codexKindsAreHuman(kinds) {
|
|
|
2848
2731
|
return kinds.every((kind) => kind.startsWith("user."));
|
|
2849
2732
|
}
|
|
2850
2733
|
function codexActor(args) {
|
|
2734
|
+
if (args.isFirstUserTurn && args.scriptLaunched) return "injected";
|
|
2851
2735
|
const recorded = codexKindsAreHuman(args.kinds);
|
|
2852
2736
|
if (recorded !== void 0) return recorded ? "human" : "injected";
|
|
2853
2737
|
if ((args.blocks ?? [args.text]).some(isCodexContextBlock)) return "injected";
|
|
@@ -2875,9 +2759,9 @@ var CORRECTIVE_REACTIONS = ["correction", "frustration", "jargon", "structure"];
|
|
|
2875
2759
|
|
|
2876
2760
|
// src/adapters/claude.ts
|
|
2877
2761
|
import { createHash as createHash6 } from "crypto";
|
|
2878
|
-
import { readdir as
|
|
2879
|
-
import { homedir as
|
|
2880
|
-
import { basename as
|
|
2762
|
+
import { readdir as readdir7, stat as stat5 } from "fs/promises";
|
|
2763
|
+
import { homedir as homedir5 } from "os";
|
|
2764
|
+
import { basename as basename4, join as join7, relative as relative3 } from "path";
|
|
2881
2765
|
import {
|
|
2882
2766
|
applyLlmSpanOtlpAttributes as applyLlmSpanOtlpAttributes2,
|
|
2883
2767
|
LLM_CACHED_TOKENS,
|
|
@@ -2888,12 +2772,12 @@ import {
|
|
|
2888
2772
|
import { ATTR as ATTR3, deriveHexId as deriveHexId2 } from "@tangle-network/agent-trace-contract";
|
|
2889
2773
|
|
|
2890
2774
|
// src/adapters/claude-subagent-sources.ts
|
|
2891
|
-
import { readdir as
|
|
2892
|
-
import { homedir as
|
|
2893
|
-
import { dirname as dirname3, isAbsolute as isAbsolute2, join as
|
|
2775
|
+
import { readdir as readdir6, realpath } from "fs/promises";
|
|
2776
|
+
import { homedir as homedir4 } from "os";
|
|
2777
|
+
import { dirname as dirname3, isAbsolute as isAbsolute2, join as join6, relative as relative2, resolve as resolve3 } from "path";
|
|
2894
2778
|
|
|
2895
2779
|
// src/adapters/claude-workflow.ts
|
|
2896
|
-
import { basename as
|
|
2780
|
+
import { basename as basename3, dirname as dirname2, isAbsolute, relative, resolve as resolve2 } from "path";
|
|
2897
2781
|
var ClaudeTaskScopeError = class extends Error {
|
|
2898
2782
|
constructor(message) {
|
|
2899
2783
|
super(message);
|
|
@@ -2905,7 +2789,7 @@ function validWorkflowRunReference(runId, transcriptDir) {
|
|
|
2905
2789
|
const cleanRunId = runId.trim();
|
|
2906
2790
|
const cleanTranscriptDir = transcriptDir.trim();
|
|
2907
2791
|
const resolvedTranscriptDir = resolve2(cleanTranscriptDir);
|
|
2908
|
-
if (!cleanRunId || cleanRunId === "." || cleanRunId === ".." || cleanRunId.includes("/") || cleanRunId.includes("\\") || !isAbsolute(cleanTranscriptDir) ||
|
|
2792
|
+
if (!cleanRunId || cleanRunId === "." || cleanRunId === ".." || cleanRunId.includes("/") || cleanRunId.includes("\\") || !isAbsolute(cleanTranscriptDir) || basename3(resolvedTranscriptDir) !== cleanRunId || basename3(dirname2(resolvedTranscriptDir)) !== "workflows" || basename3(dirname2(dirname2(resolvedTranscriptDir))) !== "subagents") {
|
|
2909
2793
|
return void 0;
|
|
2910
2794
|
}
|
|
2911
2795
|
return { runId: cleanRunId, transcriptDir: cleanTranscriptDir };
|
|
@@ -3067,14 +2951,14 @@ async function listSubagentFiles(root, signal, copiedWorkflow = false) {
|
|
|
3067
2951
|
if (!dir) continue;
|
|
3068
2952
|
let entries;
|
|
3069
2953
|
try {
|
|
3070
|
-
entries = await
|
|
2954
|
+
entries = await readdir6(dir, { withFileTypes: true });
|
|
3071
2955
|
} catch (error) {
|
|
3072
2956
|
if (isMissingPathError(error)) continue;
|
|
3073
2957
|
throw error;
|
|
3074
2958
|
}
|
|
3075
2959
|
signal?.throwIfAborted();
|
|
3076
2960
|
for (const entry of entries) {
|
|
3077
|
-
const path =
|
|
2961
|
+
const path = join6(dir, entry.name);
|
|
3078
2962
|
if (copiedWorkflow && entry.isSymbolicLink()) {
|
|
3079
2963
|
throw new ClaudeTaskScopeError(
|
|
3080
2964
|
`Claude Workflow subagent does not match copied source: ${path}`
|
|
@@ -3094,7 +2978,7 @@ function pathIsWithin(root, target) {
|
|
|
3094
2978
|
return path === "" || path !== ".." && !path.startsWith("../") && !path.startsWith("..\\") && !isAbsolute2(path);
|
|
3095
2979
|
}
|
|
3096
2980
|
function workflowStorageRoot(ref) {
|
|
3097
|
-
const nativeRoot = resolve3(
|
|
2981
|
+
const nativeRoot = resolve3(homedir4(), ".claude", "projects");
|
|
3098
2982
|
return pathIsWithin(nativeRoot, ref.path) ? nativeRoot : dirname3(resolve3(ref.path));
|
|
3099
2983
|
}
|
|
3100
2984
|
function relocatedWorkflowDirectory(ref, binding) {
|
|
@@ -3103,10 +2987,10 @@ function relocatedWorkflowDirectory(ref, binding) {
|
|
|
3103
2987
|
const parts = source.split("/").slice(-7);
|
|
3104
2988
|
const sessionId = parts[3];
|
|
3105
2989
|
if (parts[0] !== ".claude" || parts[1] !== "projects" || !parts[2] || !sessionId || !/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(sessionId) || parts[4] !== "subagents" || parts[5] !== "workflows" || parts[6] !== binding.runId) return void 0;
|
|
3106
|
-
const sessionRoot2 =
|
|
2990
|
+
const sessionRoot2 = join6(dirname3(resolve3(ref.path)), sessionId);
|
|
3107
2991
|
return {
|
|
3108
2992
|
sessionRoot: sessionRoot2,
|
|
3109
|
-
transcriptDir:
|
|
2993
|
+
transcriptDir: join6(sessionRoot2, "subagents", "workflows", binding.runId)
|
|
3110
2994
|
};
|
|
3111
2995
|
}
|
|
3112
2996
|
async function workflowTranscriptDirectories(ref, bindings) {
|
|
@@ -3179,7 +3063,7 @@ async function workflowTranscriptDirectories(ref, bindings) {
|
|
|
3179
3063
|
);
|
|
3180
3064
|
}
|
|
3181
3065
|
async function collectClaudeSubagentSources(ref, bindings, signal) {
|
|
3182
|
-
const subDir =
|
|
3066
|
+
const subDir = join6(ref.path.replace(/\.jsonl$/, ""), "subagents");
|
|
3183
3067
|
const filesByPath = /* @__PURE__ */ new Map();
|
|
3184
3068
|
const workflowByPath = /* @__PURE__ */ new Map();
|
|
3185
3069
|
for (const file of await listSubagentFiles(subDir, signal)) {
|
|
@@ -3219,7 +3103,7 @@ async function collectClaudeSubagentSources(ref, bindings, signal) {
|
|
|
3219
3103
|
}
|
|
3220
3104
|
|
|
3221
3105
|
// src/adapters/claude.ts
|
|
3222
|
-
var
|
|
3106
|
+
var SERVICE4 = "claude-code";
|
|
3223
3107
|
var AGENT_TOOL_RENAMED_IN = [2, 1, 63];
|
|
3224
3108
|
function modelFacingToolNames(tools, version) {
|
|
3225
3109
|
if (typeof version !== "string" || !atLeast(version, AGENT_TOOL_RENAMED_IN)) return [...tools];
|
|
@@ -3238,6 +3122,7 @@ var RUN_STATUS_ATTR = "run.status";
|
|
|
3238
3122
|
var EPOCH = (/* @__PURE__ */ new Date(0)).toISOString();
|
|
3239
3123
|
var HUMAN_ORIGIN = "human";
|
|
3240
3124
|
var ORIGIN_EVIDENCE_ATTR = "traces.claude.actor_evidence";
|
|
3125
|
+
var MACHINE_RECORD_ATTR = "traces.claude.machine_record";
|
|
3241
3126
|
var ORIGIN_RECORDED_ATTR = "traces.claude.origin_recorded";
|
|
3242
3127
|
var ORIGIN_KIND_ATTR = "traces.claude.origin_kind";
|
|
3243
3128
|
var COMMAND_NAME = /<command-name>([\s\S]*?)<\/command-name>/;
|
|
@@ -3269,7 +3154,7 @@ function normalizeClaudeIds(spans) {
|
|
|
3269
3154
|
function asBlocks(content) {
|
|
3270
3155
|
return Array.isArray(content) ? content : [];
|
|
3271
3156
|
}
|
|
3272
|
-
function
|
|
3157
|
+
function textOf3(content) {
|
|
3273
3158
|
if (typeof content === "string") return capText(content);
|
|
3274
3159
|
return capText(
|
|
3275
3160
|
asBlocks(content).filter((b) => b.type === "text" && typeof b.text === "string").map((b) => b.text).join("\n")
|
|
@@ -3349,7 +3234,7 @@ function projectClaudeEvent(event) {
|
|
|
3349
3234
|
outputTokens: event.message.usage?.output_tokens ?? null,
|
|
3350
3235
|
cachedInputTokens: event.message.usage?.cache_read_input_tokens ?? null,
|
|
3351
3236
|
cacheWriteInputTokens: event.message.usage?.cache_creation_input_tokens ?? null,
|
|
3352
|
-
content:
|
|
3237
|
+
content: textOf3(event.message.content) || null,
|
|
3353
3238
|
contentSource: textSources(event.message, "content"),
|
|
3354
3239
|
parentToolUseId: event.parent_tool_use_id ?? null,
|
|
3355
3240
|
tools
|
|
@@ -3376,7 +3261,7 @@ function projectClaudeEvent(event) {
|
|
|
3376
3261
|
sourceOf(block, "content")
|
|
3377
3262
|
));
|
|
3378
3263
|
}
|
|
3379
|
-
const prompt =
|
|
3264
|
+
const prompt = textOf3(event.message.content);
|
|
3380
3265
|
return {
|
|
3381
3266
|
kind: "user",
|
|
3382
3267
|
timestamp,
|
|
@@ -3386,6 +3271,8 @@ function projectClaudeEvent(event) {
|
|
|
3386
3271
|
...prompt ? {
|
|
3387
3272
|
isSidechain: event.isSidechain === true,
|
|
3388
3273
|
isMeta: event.isMeta === true,
|
|
3274
|
+
isCompactSummary: event.isCompactSummary === true,
|
|
3275
|
+
entrypoint: event.entrypoint ?? null,
|
|
3389
3276
|
userType: event.userType ?? null,
|
|
3390
3277
|
originKind: recordedOrigin(event.origin)
|
|
3391
3278
|
} : {},
|
|
@@ -3406,7 +3293,7 @@ function projectClaudeEvent(event) {
|
|
|
3406
3293
|
};
|
|
3407
3294
|
}
|
|
3408
3295
|
if (event.type === "attachment" && event.attachment?.type === "queued_command") {
|
|
3409
|
-
const prompt =
|
|
3296
|
+
const prompt = textOf3(event.attachment.prompt);
|
|
3410
3297
|
if (prompt) {
|
|
3411
3298
|
return {
|
|
3412
3299
|
kind: "queued-prompt",
|
|
@@ -3512,6 +3399,7 @@ function applyOriginEnrichment(uid, originKind, state) {
|
|
|
3512
3399
|
state.sawRecordedOrigin = true;
|
|
3513
3400
|
prompt.attributes[ORIGIN_RECORDED_ATTR] = true;
|
|
3514
3401
|
prompt.attributes[ORIGIN_KIND_ATTR] = originKind;
|
|
3402
|
+
if (prompt.attributes[MACHINE_RECORD_ATTR] === true) return;
|
|
3515
3403
|
prompt.attributes[ACTOR_ATTR] = claudeActorFromOrigin(
|
|
3516
3404
|
originKind,
|
|
3517
3405
|
() => prompt.attributes[ACTOR_ATTR]
|
|
@@ -3554,7 +3442,7 @@ function consumeClaudeEvent(event, uid, ctx, state) {
|
|
|
3554
3442
|
name: "session.compacted",
|
|
3555
3443
|
kind: "CHAIN",
|
|
3556
3444
|
startTime: event.timestamp,
|
|
3557
|
-
service:
|
|
3445
|
+
service: SERVICE4,
|
|
3558
3446
|
agent: ctx.agent,
|
|
3559
3447
|
step: state.step++,
|
|
3560
3448
|
extra
|
|
@@ -3573,7 +3461,7 @@ function consumeClaudeEvent(event, uid, ctx, state) {
|
|
|
3573
3461
|
name: "llm.turn",
|
|
3574
3462
|
kind: "LLM",
|
|
3575
3463
|
startTime: event.timestamp,
|
|
3576
|
-
service:
|
|
3464
|
+
service: SERVICE4,
|
|
3577
3465
|
agent: ctx.agent,
|
|
3578
3466
|
model: event.model,
|
|
3579
3467
|
inputTokens: event.inputTokens,
|
|
@@ -3626,7 +3514,7 @@ function consumeClaudeEvent(event, uid, ctx, state) {
|
|
|
3626
3514
|
name: `tool.${tool.name}`,
|
|
3627
3515
|
kind: "TOOL",
|
|
3628
3516
|
startTime: event.timestamp,
|
|
3629
|
-
service:
|
|
3517
|
+
service: SERVICE4,
|
|
3630
3518
|
agent: ctx.agent,
|
|
3631
3519
|
tool: tool.name,
|
|
3632
3520
|
step: state.step,
|
|
@@ -3645,10 +3533,15 @@ function consumeClaudeEvent(event, uid, ctx, state) {
|
|
|
3645
3533
|
}
|
|
3646
3534
|
} else if (event.kind === "user") {
|
|
3647
3535
|
if (event.prompt) {
|
|
3648
|
-
const
|
|
3536
|
+
const machine = claudeRecordIsMachine({
|
|
3537
|
+
text: event.prompt,
|
|
3538
|
+
isMeta: event.isMeta,
|
|
3539
|
+
isCompactSummary: event.isCompactSummary,
|
|
3540
|
+
entrypoint: event.entrypoint
|
|
3541
|
+
});
|
|
3542
|
+
const actor = machine ? "injected" : claudeActorFromOrigin(event.originKind, () => claudeActor({
|
|
3649
3543
|
text: event.prompt ?? "",
|
|
3650
3544
|
isSidechain: event.isSidechain,
|
|
3651
|
-
isMeta: event.isMeta,
|
|
3652
3545
|
userType: event.userType ?? null,
|
|
3653
3546
|
isFirstUserTurn: !state.sawUserTurn
|
|
3654
3547
|
}));
|
|
@@ -3660,13 +3553,14 @@ function consumeClaudeEvent(event, uid, ctx, state) {
|
|
|
3660
3553
|
spanId: `${ctx.idPrefix}${uid}:user`,
|
|
3661
3554
|
parentSpanId: userParent ? userParent.span.span_id : ctx.rootParent,
|
|
3662
3555
|
startTime: event.timestamp,
|
|
3663
|
-
service:
|
|
3556
|
+
service: SERVICE4,
|
|
3664
3557
|
agent: ctx.agent,
|
|
3665
3558
|
step: state.step,
|
|
3666
3559
|
content: actor === "human" ? typedPromptText(event.prompt) : event.prompt,
|
|
3667
3560
|
contentSource: event.contentSource,
|
|
3668
3561
|
actor
|
|
3669
3562
|
});
|
|
3563
|
+
if (machine) prompt.attributes[MACHINE_RECORD_ATTR] = true;
|
|
3670
3564
|
if (event.originKind) {
|
|
3671
3565
|
prompt.attributes[ORIGIN_RECORDED_ATTR] = true;
|
|
3672
3566
|
prompt.attributes[ORIGIN_KIND_ATTR] = event.originKind;
|
|
@@ -3683,14 +3577,15 @@ function consumeClaudeEvent(event, uid, ctx, state) {
|
|
|
3683
3577
|
} else if (event.kind === "attachment") {
|
|
3684
3578
|
backfillResult(state.toolSpanByUseId.get(event.result.toolUseId), event.timestamp, event.result);
|
|
3685
3579
|
} else if (event.kind === "queued-prompt") {
|
|
3686
|
-
const
|
|
3580
|
+
const machine = claudeRecordIsMachine({ text: event.prompt });
|
|
3581
|
+
const actor = machine ? "injected" : claudeActorFromOrigin(event.originKind, () => "injected");
|
|
3687
3582
|
if (event.originKind) state.sawRecordedOrigin = true;
|
|
3688
3583
|
const prompt = userPromptSpan({
|
|
3689
3584
|
traceId: ctx.traceId,
|
|
3690
3585
|
spanId: `${ctx.idPrefix}${uid}:queued`,
|
|
3691
3586
|
parentSpanId: ctx.rootParent,
|
|
3692
3587
|
startTime: event.timestamp,
|
|
3693
|
-
service:
|
|
3588
|
+
service: SERVICE4,
|
|
3694
3589
|
agent: ctx.agent,
|
|
3695
3590
|
step: state.step,
|
|
3696
3591
|
content: actor === "human" ? typedPromptText(event.prompt) : event.prompt,
|
|
@@ -3698,6 +3593,7 @@ function consumeClaudeEvent(event, uid, ctx, state) {
|
|
|
3698
3593
|
actor
|
|
3699
3594
|
});
|
|
3700
3595
|
prompt.attributes["traces.claude.queued"] = true;
|
|
3596
|
+
if (machine) prompt.attributes[MACHINE_RECORD_ATTR] = true;
|
|
3701
3597
|
if (event.originKind) {
|
|
3702
3598
|
prompt.attributes[ORIGIN_RECORDED_ATTR] = true;
|
|
3703
3599
|
prompt.attributes[ORIGIN_KIND_ATTR] = event.originKind;
|
|
@@ -3715,7 +3611,7 @@ function consumeClaudeEvent(event, uid, ctx, state) {
|
|
|
3715
3611
|
kind: "CHAIN",
|
|
3716
3612
|
startTime: event.timestamp,
|
|
3717
3613
|
endTime: event.timestamp,
|
|
3718
|
-
service:
|
|
3614
|
+
service: SERVICE4,
|
|
3719
3615
|
agent: ctx.agent,
|
|
3720
3616
|
step: state.step,
|
|
3721
3617
|
extra: toolIoAttributes({ input: { path: event.path }, inputSource: event.contentSource })
|
|
@@ -3738,7 +3634,7 @@ function mergeAssistantMessage(event, messageId, llmSpan, ctx, state) {
|
|
|
3738
3634
|
kind: "CHAIN",
|
|
3739
3635
|
startTime: event.timestamp,
|
|
3740
3636
|
endTime: event.timestamp,
|
|
3741
|
-
service:
|
|
3637
|
+
service: SERVICE4,
|
|
3742
3638
|
agent: ctx.agent,
|
|
3743
3639
|
step: state.step,
|
|
3744
3640
|
content: typeof llmSpan.attributes.content === "string" ? llmSpan.attributes.content : "",
|
|
@@ -3923,7 +3819,7 @@ var ClaudeAdapter = class {
|
|
|
3923
3819
|
harness = "claude-code";
|
|
3924
3820
|
aliases = ["claude", "claudish", "openclaw", "nanoclaw"];
|
|
3925
3821
|
root() {
|
|
3926
|
-
return
|
|
3822
|
+
return join7(homedir5(), ".claude", "projects");
|
|
3927
3823
|
}
|
|
3928
3824
|
async sourcePaths(ref, options = {}) {
|
|
3929
3825
|
const bindings = await readClaudeWorkflowBindings(ref, options);
|
|
@@ -3933,7 +3829,7 @@ var ClaudeAdapter = class {
|
|
|
3933
3829
|
options.signal?.throwIfAborted();
|
|
3934
3830
|
const path = file.replace(/\.jsonl$/, ".meta.json");
|
|
3935
3831
|
try {
|
|
3936
|
-
const source = await
|
|
3832
|
+
const source = await stat5(path);
|
|
3937
3833
|
if (source.isFile()) metadataFiles.push(path);
|
|
3938
3834
|
} catch (error) {
|
|
3939
3835
|
if (!isMissingPathError(error)) throw error;
|
|
@@ -3946,27 +3842,27 @@ var ClaudeAdapter = class {
|
|
|
3946
3842
|
const root = this.root();
|
|
3947
3843
|
let projectDirs;
|
|
3948
3844
|
try {
|
|
3949
|
-
projectDirs = await
|
|
3845
|
+
projectDirs = await readdir7(root);
|
|
3950
3846
|
} catch (error) {
|
|
3951
3847
|
if (isMissingPathError(error)) return [];
|
|
3952
3848
|
throw error;
|
|
3953
3849
|
}
|
|
3954
3850
|
const refs = [];
|
|
3955
3851
|
for (const dir of projectDirs) {
|
|
3956
|
-
const dirPath =
|
|
3852
|
+
const dirPath = join7(root, dir);
|
|
3957
3853
|
let files;
|
|
3958
3854
|
try {
|
|
3959
|
-
files = await
|
|
3855
|
+
files = await readdir7(dirPath);
|
|
3960
3856
|
} catch (error) {
|
|
3961
3857
|
if (isMissingPathError(error)) continue;
|
|
3962
3858
|
throw error;
|
|
3963
3859
|
}
|
|
3964
3860
|
for (const f of files) {
|
|
3965
3861
|
if (!f.endsWith(".jsonl")) continue;
|
|
3966
|
-
const path =
|
|
3862
|
+
const path = join7(dirPath, f);
|
|
3967
3863
|
let st;
|
|
3968
3864
|
try {
|
|
3969
|
-
st = await
|
|
3865
|
+
st = await stat5(path);
|
|
3970
3866
|
} catch (error) {
|
|
3971
3867
|
if (isMissingPathError(error)) continue;
|
|
3972
3868
|
throw error;
|
|
@@ -3975,7 +3871,7 @@ var ClaudeAdapter = class {
|
|
|
3975
3871
|
if (opts.sinceMs && st.mtimeMs < opts.sinceMs) continue;
|
|
3976
3872
|
const cwd = `/${dir.replace(/^-/, "").replace(/-/g, "/")}`;
|
|
3977
3873
|
if (opts.cwd && !cwd.startsWith(opts.cwd)) continue;
|
|
3978
|
-
refs.push({ harness: this.harness, sessionId:
|
|
3874
|
+
refs.push({ harness: this.harness, sessionId: basename4(f, ".jsonl"), path, cwd, mtimeMs: st.mtimeMs });
|
|
3979
3875
|
}
|
|
3980
3876
|
}
|
|
3981
3877
|
return refs.sort((a, b) => b.mtimeMs - a.mtimeMs);
|
|
@@ -3990,7 +3886,7 @@ var ClaudeAdapter = class {
|
|
|
3990
3886
|
const sourceRootId = `root:${sourceTraceId}`;
|
|
3991
3887
|
const ctx = {
|
|
3992
3888
|
traceId: sourceTraceId,
|
|
3993
|
-
agent:
|
|
3889
|
+
agent: SERVICE4,
|
|
3994
3890
|
startStep: 0,
|
|
3995
3891
|
idPrefix: "",
|
|
3996
3892
|
rootParent: sourceRootId
|
|
@@ -4071,8 +3967,8 @@ var ClaudeAdapter = class {
|
|
|
4071
3967
|
name: "session",
|
|
4072
3968
|
kind: "AGENT",
|
|
4073
3969
|
startTime: (/* @__PURE__ */ new Date(0)).toISOString(),
|
|
4074
|
-
service:
|
|
4075
|
-
agent:
|
|
3970
|
+
service: SERVICE4,
|
|
3971
|
+
agent: SERVICE4
|
|
4076
3972
|
});
|
|
4077
3973
|
if (offeredTools) {
|
|
4078
3974
|
root.attributes[TOOL_DEFINITIONS_ATTR] = JSON.stringify(offeredTools.map((name) => ({ type: "function", name })));
|
|
@@ -4105,7 +4001,7 @@ var ClaudeAdapter = class {
|
|
|
4105
4001
|
}
|
|
4106
4002
|
/** Parse nested `subagents/.../agent-*.jsonl`, parenting each under its Agent call. */
|
|
4107
4003
|
async foldSubagents(ref, traceId, main, workflowBindings, out, options) {
|
|
4108
|
-
const subDir =
|
|
4004
|
+
const subDir = join7(ref.path.replace(/\.jsonl$/, ""), "subagents");
|
|
4109
4005
|
const sources = await collectClaudeSubagentSources(
|
|
4110
4006
|
ref,
|
|
4111
4007
|
workflowBindings,
|
|
@@ -4129,7 +4025,7 @@ var ClaudeAdapter = class {
|
|
|
4129
4025
|
const agent = {
|
|
4130
4026
|
file,
|
|
4131
4027
|
sourceKey,
|
|
4132
|
-
agentId:
|
|
4028
|
+
agentId: basename4(file, ".jsonl").replace(/^agent-/, ""),
|
|
4133
4029
|
meta,
|
|
4134
4030
|
...meta.toolUseId ? { parentToolUseId: meta.toolUseId } : {}
|
|
4135
4031
|
};
|
|
@@ -4143,7 +4039,7 @@ var ClaudeAdapter = class {
|
|
|
4143
4039
|
);
|
|
4144
4040
|
const parsed = await parseClaudeSubagent(ref, traceId, agent, options);
|
|
4145
4041
|
const { binding, confidence } = selectWorkflowBinding(
|
|
4146
|
-
|
|
4042
|
+
basename4(file),
|
|
4147
4043
|
runBindings,
|
|
4148
4044
|
firstSubagentTimestamp(agent, parsed),
|
|
4149
4045
|
meta.toolUseId
|
|
@@ -4261,7 +4157,7 @@ function subagentLifecycleSpan(agent, parsed, traceId, parentSpanId, task, subDi
|
|
|
4261
4157
|
// The transcript records what the child did, not whether the parent
|
|
4262
4158
|
// accepted it; the parent's own tool span carries that status.
|
|
4263
4159
|
status: "UNSET",
|
|
4264
|
-
service:
|
|
4160
|
+
service: SERVICE4,
|
|
4265
4161
|
agent: agent.meta.agentType ? `subagent:${agent.meta.agentType}` : "subagent",
|
|
4266
4162
|
extra: {
|
|
4267
4163
|
...toolIoAttributes({
|
|
@@ -4710,11 +4606,11 @@ async function resolveCodexParentTask(ref, childSessionId, options = {}) {
|
|
|
4710
4606
|
}
|
|
4711
4607
|
|
|
4712
4608
|
// src/adapters/codex.ts
|
|
4713
|
-
import { readdir as
|
|
4714
|
-
import { homedir as
|
|
4715
|
-
import { basename as
|
|
4609
|
+
import { readdir as readdir8, stat as stat6 } from "fs/promises";
|
|
4610
|
+
import { homedir as homedir6 } from "os";
|
|
4611
|
+
import { basename as basename5, join as join8 } from "path";
|
|
4716
4612
|
import { deriveHexId as deriveHexId3 } from "@tangle-network/agent-trace-contract";
|
|
4717
|
-
var
|
|
4613
|
+
var SERVICE5 = "codex";
|
|
4718
4614
|
var SESSION_HEAD_LINES = 40;
|
|
4719
4615
|
var MAX_INHERITED_SPANS = 200;
|
|
4720
4616
|
var CODEX_SOURCE_TRACE_ID = "traces.codex.source_trace_id";
|
|
@@ -4755,7 +4651,7 @@ function tokenUsageSignature(usage) {
|
|
|
4755
4651
|
usage.total_tokens ?? null
|
|
4756
4652
|
]);
|
|
4757
4653
|
}
|
|
4758
|
-
function
|
|
4654
|
+
function textOf4(content) {
|
|
4759
4655
|
return capText(contentToString(content));
|
|
4760
4656
|
}
|
|
4761
4657
|
function numericStatus(value) {
|
|
@@ -5029,9 +4925,9 @@ function itemCountsJson(counts) {
|
|
|
5029
4925
|
}
|
|
5030
4926
|
function placeInnerSpans(pending, windows) {
|
|
5031
4927
|
return pending.map((entry) => {
|
|
5032
|
-
const { parent, join:
|
|
4928
|
+
const { parent, join: join35 } = joinItem(windows, entry.startMs, entry.endMs);
|
|
5033
4929
|
if (parent) entry.span.parent_span_id = parent.span_id;
|
|
5034
|
-
entry.span.attributes["traces.codex.item_join"] =
|
|
4930
|
+
entry.span.attributes["traces.codex.item_join"] = join35;
|
|
5035
4931
|
return entry.span;
|
|
5036
4932
|
});
|
|
5037
4933
|
}
|
|
@@ -5047,8 +4943,8 @@ function commandSpan(context, item, command, recordTime) {
|
|
|
5047
4943
|
startTime: start,
|
|
5048
4944
|
status: status2.code,
|
|
5049
4945
|
statusMessage: status2.message,
|
|
5050
|
-
service:
|
|
5051
|
-
agent:
|
|
4946
|
+
service: SERVICE5,
|
|
4947
|
+
agent: SERVICE5,
|
|
5052
4948
|
extra: {
|
|
5053
4949
|
...toolIoAttributes({
|
|
5054
4950
|
input: { command: command.command, ...command.cwd ? { cwd: command.cwd } : {} },
|
|
@@ -5080,8 +4976,8 @@ function fileChangeSpans(context, item, fileChange, recordTime) {
|
|
|
5080
4976
|
startTime: start,
|
|
5081
4977
|
status: status2.code,
|
|
5082
4978
|
statusMessage: status2.message,
|
|
5083
|
-
service:
|
|
5084
|
-
agent:
|
|
4979
|
+
service: SERVICE5,
|
|
4980
|
+
agent: SERVICE5,
|
|
5085
4981
|
extra: {
|
|
5086
4982
|
...toolIoAttributes({
|
|
5087
4983
|
input: { path: change.path, kind: change.kind, ...change.movePath ? { move_path: change.movePath } : {} },
|
|
@@ -5129,40 +5025,40 @@ function isExpectedBlockingTool(name, input) {
|
|
|
5129
5025
|
async function* walkRollouts(root) {
|
|
5130
5026
|
let years;
|
|
5131
5027
|
try {
|
|
5132
|
-
years = await
|
|
5028
|
+
years = await readdir8(root);
|
|
5133
5029
|
} catch (error) {
|
|
5134
5030
|
if (isMissingPathError(error)) return;
|
|
5135
5031
|
throw error;
|
|
5136
5032
|
}
|
|
5137
5033
|
for (const y of years) {
|
|
5138
|
-
const yp =
|
|
5034
|
+
const yp = join8(root, y);
|
|
5139
5035
|
let months;
|
|
5140
5036
|
try {
|
|
5141
|
-
months = await
|
|
5037
|
+
months = await readdir8(yp);
|
|
5142
5038
|
} catch (error) {
|
|
5143
5039
|
if (isMissingPathError(error)) continue;
|
|
5144
5040
|
throw error;
|
|
5145
5041
|
}
|
|
5146
5042
|
for (const m of months) {
|
|
5147
|
-
const mp =
|
|
5043
|
+
const mp = join8(yp, m);
|
|
5148
5044
|
let days;
|
|
5149
5045
|
try {
|
|
5150
|
-
days = await
|
|
5046
|
+
days = await readdir8(mp);
|
|
5151
5047
|
} catch (error) {
|
|
5152
5048
|
if (isMissingPathError(error)) continue;
|
|
5153
5049
|
throw error;
|
|
5154
5050
|
}
|
|
5155
5051
|
for (const d of days) {
|
|
5156
|
-
const dp =
|
|
5052
|
+
const dp = join8(mp, d);
|
|
5157
5053
|
let files;
|
|
5158
5054
|
try {
|
|
5159
|
-
files = await
|
|
5055
|
+
files = await readdir8(dp);
|
|
5160
5056
|
} catch (error) {
|
|
5161
5057
|
if (isMissingPathError(error)) continue;
|
|
5162
5058
|
throw error;
|
|
5163
5059
|
}
|
|
5164
5060
|
for (const f of files) {
|
|
5165
|
-
if (f.startsWith("rollout-") && f.endsWith(".jsonl")) yield
|
|
5061
|
+
if (f.startsWith("rollout-") && f.endsWith(".jsonl")) yield join8(dp, f);
|
|
5166
5062
|
}
|
|
5167
5063
|
}
|
|
5168
5064
|
}
|
|
@@ -5172,19 +5068,19 @@ var CodexAdapter = class {
|
|
|
5172
5068
|
harness = "codex";
|
|
5173
5069
|
aliases = ["codex-acp"];
|
|
5174
5070
|
root() {
|
|
5175
|
-
return process.env.CODEX_HOME ?
|
|
5071
|
+
return process.env.CODEX_HOME ? join8(process.env.CODEX_HOME, "sessions") : join8(homedir6(), ".codex", "sessions");
|
|
5176
5072
|
}
|
|
5177
5073
|
async refFromPath(path, opts) {
|
|
5178
5074
|
let st;
|
|
5179
5075
|
try {
|
|
5180
|
-
st = await
|
|
5076
|
+
st = await stat6(path);
|
|
5181
5077
|
} catch (error) {
|
|
5182
5078
|
if (isMissingPathError(error)) return void 0;
|
|
5183
5079
|
throw error;
|
|
5184
5080
|
}
|
|
5185
5081
|
if (opts.sinceMs && st.mtimeMs < opts.sinceMs) return void 0;
|
|
5186
5082
|
let cwd = null;
|
|
5187
|
-
let id =
|
|
5083
|
+
let id = basename5(path).replace(/^rollout-[\dT-]+-/, "").replace(/\.jsonl$/, "");
|
|
5188
5084
|
const ref = { harness: this.harness, sessionId: id, path, cwd, mtimeMs: st.mtimeMs };
|
|
5189
5085
|
const head = await takeJsonl(path, SESSION_HEAD_LINES, sessionJsonlOptions(ref));
|
|
5190
5086
|
for (const parsed of head) {
|
|
@@ -5212,7 +5108,7 @@ var CodexAdapter = class {
|
|
|
5212
5108
|
async locateBySessionId(sessionId, opts = {}) {
|
|
5213
5109
|
const refs = [];
|
|
5214
5110
|
for await (const path of walkRollouts(this.root())) {
|
|
5215
|
-
if (!
|
|
5111
|
+
if (!basename5(path).includes(sessionId)) continue;
|
|
5216
5112
|
const ref = await this.refFromPath(path, opts);
|
|
5217
5113
|
if (ref?.sessionId === sessionId) refs.push(ref);
|
|
5218
5114
|
}
|
|
@@ -5307,6 +5203,7 @@ var CodexAdapter = class {
|
|
|
5307
5203
|
}
|
|
5308
5204
|
}
|
|
5309
5205
|
const traceId = meta?.payload?.id ?? ref.sessionId;
|
|
5206
|
+
const scriptLaunched = meta?.payload?.originator === "codex_exec" || meta?.payload?.source === "exec";
|
|
5310
5207
|
const sessionRole = parentSessionId || meta?.payload?.thread_source === "subagent" ? "child" : "operator";
|
|
5311
5208
|
const rootId = `root:${traceId}`;
|
|
5312
5209
|
const root = span({
|
|
@@ -5316,8 +5213,8 @@ var CodexAdapter = class {
|
|
|
5316
5213
|
name: "session",
|
|
5317
5214
|
kind: "AGENT",
|
|
5318
5215
|
startTime: selectedBoundary?.timestamp ?? meta?.timestamp ?? first?.timestamp ?? (/* @__PURE__ */ new Date(0)).toISOString(),
|
|
5319
|
-
service:
|
|
5320
|
-
agent:
|
|
5216
|
+
service: SERVICE5,
|
|
5217
|
+
agent: SERVICE5,
|
|
5321
5218
|
model,
|
|
5322
5219
|
status: "UNSET",
|
|
5323
5220
|
extra: {
|
|
@@ -5373,7 +5270,7 @@ var CodexAdapter = class {
|
|
|
5373
5270
|
recorded.span.attributes[USER_MESSAGE_EVENT_ATTR] = true;
|
|
5374
5271
|
return;
|
|
5375
5272
|
}
|
|
5376
|
-
const actor = sessionRole === "child" ? "agent" : codexActor({ text: prompt, isFirstUserTurn: !sawUserTurn });
|
|
5273
|
+
const actor = sessionRole === "child" ? "agent" : codexActor({ text: prompt, isFirstUserTurn: !sawUserTurn, scriptLaunched });
|
|
5377
5274
|
sawUserTurn = true;
|
|
5378
5275
|
const turnSpan = userPromptSpan({
|
|
5379
5276
|
traceId,
|
|
@@ -5382,8 +5279,8 @@ var CodexAdapter = class {
|
|
|
5382
5279
|
startTime: ts,
|
|
5383
5280
|
content: prompt,
|
|
5384
5281
|
contentSource,
|
|
5385
|
-
service:
|
|
5386
|
-
agent:
|
|
5282
|
+
service: SERVICE5,
|
|
5283
|
+
agent: SERVICE5,
|
|
5387
5284
|
step,
|
|
5388
5285
|
actor
|
|
5389
5286
|
});
|
|
@@ -5408,7 +5305,7 @@ var CodexAdapter = class {
|
|
|
5408
5305
|
if (inheritedTurnKeys.has(dedupKey)) return;
|
|
5409
5306
|
if (!claimInheritedSpan()) return;
|
|
5410
5307
|
inheritedTurnKeys.add(dedupKey);
|
|
5411
|
-
const actor = codexActor({ text: prompt, blocks, isFirstUserTurn: !sawInheritedTurn, kinds });
|
|
5308
|
+
const actor = codexActor({ text: prompt, blocks, isFirstUserTurn: !sawInheritedTurn, kinds, scriptLaunched });
|
|
5412
5309
|
sawInheritedTurn = true;
|
|
5413
5310
|
const turnSpan = userPromptSpan({
|
|
5414
5311
|
traceId,
|
|
@@ -5417,8 +5314,8 @@ var CodexAdapter = class {
|
|
|
5417
5314
|
startTime: ts,
|
|
5418
5315
|
content: prompt,
|
|
5419
5316
|
contentSource,
|
|
5420
|
-
service:
|
|
5421
|
-
agent:
|
|
5317
|
+
service: SERVICE5,
|
|
5318
|
+
agent: SERVICE5,
|
|
5422
5319
|
step,
|
|
5423
5320
|
actor
|
|
5424
5321
|
});
|
|
@@ -5440,8 +5337,8 @@ var CodexAdapter = class {
|
|
|
5440
5337
|
name: "session.compacted",
|
|
5441
5338
|
kind: "CHAIN",
|
|
5442
5339
|
startTime: ts,
|
|
5443
|
-
service:
|
|
5444
|
-
agent:
|
|
5340
|
+
service: SERVICE5,
|
|
5341
|
+
agent: SERVICE5,
|
|
5445
5342
|
step,
|
|
5446
5343
|
content: summary,
|
|
5447
5344
|
contentSource: textSources(payload, "message"),
|
|
@@ -5527,8 +5424,8 @@ var CodexAdapter = class {
|
|
|
5527
5424
|
name: "subagent.lifecycle",
|
|
5528
5425
|
kind: "AGENT",
|
|
5529
5426
|
startTime: eventTime2,
|
|
5530
|
-
service:
|
|
5531
|
-
agent:
|
|
5427
|
+
service: SERVICE5,
|
|
5428
|
+
agent: SERVICE5,
|
|
5532
5429
|
step,
|
|
5533
5430
|
status: "UNSET",
|
|
5534
5431
|
extra: {
|
|
@@ -5606,8 +5503,8 @@ var CodexAdapter = class {
|
|
|
5606
5503
|
name: "llm.turn",
|
|
5607
5504
|
kind: "LLM",
|
|
5608
5505
|
startTime: ts,
|
|
5609
|
-
service:
|
|
5610
|
-
agent:
|
|
5506
|
+
service: SERVICE5,
|
|
5507
|
+
agent: SERVICE5,
|
|
5611
5508
|
model,
|
|
5612
5509
|
inputTokens: u.input_tokens ?? null,
|
|
5613
5510
|
outputTokens: u.output_tokens ?? null,
|
|
@@ -5639,8 +5536,8 @@ var CodexAdapter = class {
|
|
|
5639
5536
|
kind: "TOOL",
|
|
5640
5537
|
startTime: ts,
|
|
5641
5538
|
status: "UNSET",
|
|
5642
|
-
service:
|
|
5643
|
-
agent:
|
|
5539
|
+
service: SERVICE5,
|
|
5540
|
+
agent: SERVICE5,
|
|
5644
5541
|
tool: name,
|
|
5645
5542
|
step,
|
|
5646
5543
|
extra: {
|
|
@@ -5750,7 +5647,7 @@ var CodexAdapter = class {
|
|
|
5750
5647
|
]);
|
|
5751
5648
|
if (seenAgentMessages.has(messageIdentity)) continue;
|
|
5752
5649
|
seenAgentMessages.add(messageIdentity);
|
|
5753
|
-
const text2 =
|
|
5650
|
+
const text2 = textOf4(l.payload.content);
|
|
5754
5651
|
const author = l.payload.author;
|
|
5755
5652
|
const recipient = l.payload.recipient;
|
|
5756
5653
|
const messageType = /^Message Type:\s*FINAL_ANSWER\b/m.test(text2) ? "final" : /^Message Type:\s*MESSAGE\b/m.test(text2) ? "progress" : "unknown";
|
|
@@ -5763,8 +5660,8 @@ var CodexAdapter = class {
|
|
|
5763
5660
|
name: `message.agent.${messageType}`,
|
|
5764
5661
|
kind: "CHAIN",
|
|
5765
5662
|
startTime: ts,
|
|
5766
|
-
service:
|
|
5767
|
-
agent:
|
|
5663
|
+
service: SERVICE5,
|
|
5664
|
+
agent: SERVICE5,
|
|
5768
5665
|
step,
|
|
5769
5666
|
content: text2,
|
|
5770
5667
|
contentSource: textSources(l.payload, "content"),
|
|
@@ -5799,6 +5696,7 @@ var CodexAdapter = class {
|
|
|
5799
5696
|
text: prompt,
|
|
5800
5697
|
blocks: contentTextBlocks(l.payload.content),
|
|
5801
5698
|
isFirstUserTurn: !sawUserTurn,
|
|
5699
|
+
scriptLaunched,
|
|
5802
5700
|
kinds: l.payload.internal_chat_message_metadata_passthrough?.content_item_kinds
|
|
5803
5701
|
});
|
|
5804
5702
|
sawUserTurn = true;
|
|
@@ -5809,8 +5707,8 @@ var CodexAdapter = class {
|
|
|
5809
5707
|
startTime: ts,
|
|
5810
5708
|
content: prompt,
|
|
5811
5709
|
contentSource: textSources(l.payload, "content"),
|
|
5812
|
-
service:
|
|
5813
|
-
agent:
|
|
5710
|
+
service: SERVICE5,
|
|
5711
|
+
agent: SERVICE5,
|
|
5814
5712
|
step,
|
|
5815
5713
|
actor
|
|
5816
5714
|
});
|
|
@@ -5819,7 +5717,7 @@ var CodexAdapter = class {
|
|
|
5819
5717
|
step += 1;
|
|
5820
5718
|
}
|
|
5821
5719
|
} else if (l.type === "response_item" && l.payload?.type === "message") {
|
|
5822
|
-
const text2 =
|
|
5720
|
+
const text2 = textOf4(l.payload.content);
|
|
5823
5721
|
if (text2) {
|
|
5824
5722
|
spans.push(
|
|
5825
5723
|
span({
|
|
@@ -5829,8 +5727,8 @@ var CodexAdapter = class {
|
|
|
5829
5727
|
name: `message.${l.payload.role ?? "unknown"}`,
|
|
5830
5728
|
kind: "CHAIN",
|
|
5831
5729
|
startTime: ts,
|
|
5832
|
-
service:
|
|
5833
|
-
agent:
|
|
5730
|
+
service: SERVICE5,
|
|
5731
|
+
agent: SERVICE5,
|
|
5834
5732
|
step,
|
|
5835
5733
|
content: text2,
|
|
5836
5734
|
contentSource: textSources(l.payload, "content")
|
|
@@ -5888,14 +5786,14 @@ var CodexAdapter = class {
|
|
|
5888
5786
|
};
|
|
5889
5787
|
|
|
5890
5788
|
// src/adapters/opencode.ts
|
|
5891
|
-
import { readdir as
|
|
5892
|
-
import { homedir as
|
|
5893
|
-
import { join as
|
|
5894
|
-
var
|
|
5789
|
+
import { readdir as readdir9, stat as stat7 } from "fs/promises";
|
|
5790
|
+
import { homedir as homedir7 } from "os";
|
|
5791
|
+
import { join as join9 } from "path";
|
|
5792
|
+
var SERVICE6 = "opencode";
|
|
5895
5793
|
function isoOf(ms2) {
|
|
5896
5794
|
return new Date(ms2 ?? 0).toISOString();
|
|
5897
5795
|
}
|
|
5898
|
-
function
|
|
5796
|
+
function textOf5(parts) {
|
|
5899
5797
|
return capText(
|
|
5900
5798
|
parts.filter((p) => p.type === "text" && typeof p.text === "string").map((p) => p.text).join("\n")
|
|
5901
5799
|
);
|
|
@@ -5903,24 +5801,24 @@ function textOf6(parts) {
|
|
|
5903
5801
|
var OpencodeAdapter = class {
|
|
5904
5802
|
harness = "opencode";
|
|
5905
5803
|
storage() {
|
|
5906
|
-
const base = process.env.XDG_DATA_HOME ??
|
|
5907
|
-
return
|
|
5804
|
+
const base = process.env.XDG_DATA_HOME ?? join9(homedir7(), ".local", "share");
|
|
5805
|
+
return join9(base, "opencode", "storage");
|
|
5908
5806
|
}
|
|
5909
5807
|
async locate(opts = {}) {
|
|
5910
|
-
const msgRoot =
|
|
5808
|
+
const msgRoot = join9(this.storage(), "message");
|
|
5911
5809
|
let sessionDirs;
|
|
5912
5810
|
try {
|
|
5913
|
-
sessionDirs = await
|
|
5811
|
+
sessionDirs = await readdir9(msgRoot);
|
|
5914
5812
|
} catch (error) {
|
|
5915
5813
|
if (isMissingPathError(error)) return [];
|
|
5916
5814
|
throw error;
|
|
5917
5815
|
}
|
|
5918
5816
|
const refs = [];
|
|
5919
5817
|
for (const sid of sessionDirs) {
|
|
5920
|
-
const dir =
|
|
5818
|
+
const dir = join9(msgRoot, sid);
|
|
5921
5819
|
let st;
|
|
5922
5820
|
try {
|
|
5923
|
-
st = await
|
|
5821
|
+
st = await stat7(dir);
|
|
5924
5822
|
} catch (error) {
|
|
5925
5823
|
if (isMissingPathError(error)) continue;
|
|
5926
5824
|
throw error;
|
|
@@ -5936,23 +5834,23 @@ var OpencodeAdapter = class {
|
|
|
5936
5834
|
const paths = [];
|
|
5937
5835
|
let step = 0;
|
|
5938
5836
|
const messages = await Promise.all((await listJsonFiles(ref.path)).map(async (file) => {
|
|
5939
|
-
const path =
|
|
5837
|
+
const path = join9(ref.path, file);
|
|
5940
5838
|
paths.push(path);
|
|
5941
5839
|
return readJsonFile(path);
|
|
5942
5840
|
}));
|
|
5943
5841
|
messages.sort((a, b) => (a.time?.created ?? 0) - (b.time?.created ?? 0));
|
|
5944
5842
|
for (const message of messages) {
|
|
5945
5843
|
const mid = message.id ?? `m${step}`;
|
|
5946
|
-
const directory =
|
|
5844
|
+
const directory = join9(this.storage(), "part", mid);
|
|
5947
5845
|
let files = [];
|
|
5948
5846
|
try {
|
|
5949
5847
|
files = await listJsonFiles(directory);
|
|
5950
5848
|
} catch (error) {
|
|
5951
5849
|
if (!isMissingJsonSource(error)) throw error;
|
|
5952
5850
|
}
|
|
5953
|
-
paths.push(...files.map((file) =>
|
|
5954
|
-
const parts = await Promise.all(files.map((file) => readJsonFile(
|
|
5955
|
-
if (message.role !== "user" ||
|
|
5851
|
+
paths.push(...files.map((file) => join9(directory, file)));
|
|
5852
|
+
const parts = await Promise.all(files.map((file) => readJsonFile(join9(directory, file))));
|
|
5853
|
+
if (message.role !== "user" || textOf5(parts)) step += 1;
|
|
5956
5854
|
step += parts.filter((part) => part.type === "tool" && part.tool).length;
|
|
5957
5855
|
}
|
|
5958
5856
|
return paths.sort();
|
|
@@ -5960,11 +5858,11 @@ var OpencodeAdapter = class {
|
|
|
5960
5858
|
async parse(ref, options = {}) {
|
|
5961
5859
|
const traceId = ref.sessionId;
|
|
5962
5860
|
const rootId = `root:${traceId}`;
|
|
5963
|
-
const partRoot =
|
|
5861
|
+
const partRoot = join9(this.storage(), "part");
|
|
5964
5862
|
const msgFiles = await listJsonFiles(ref.path);
|
|
5965
5863
|
const messages = [];
|
|
5966
5864
|
for (const f of msgFiles) {
|
|
5967
|
-
messages.push(await readJsonFile(
|
|
5865
|
+
messages.push(await readJsonFile(join9(ref.path, f), options));
|
|
5968
5866
|
}
|
|
5969
5867
|
messages.sort((a, b) => (a.time?.created ?? 0) - (b.time?.created ?? 0));
|
|
5970
5868
|
const spans = [
|
|
@@ -5976,15 +5874,15 @@ var OpencodeAdapter = class {
|
|
|
5976
5874
|
kind: "AGENT",
|
|
5977
5875
|
startTime: isoOf(messages[0]?.time?.created),
|
|
5978
5876
|
endTime: isoOf(messages.at(-1)?.time?.completed ?? messages.at(-1)?.time?.created),
|
|
5979
|
-
service:
|
|
5980
|
-
agent:
|
|
5877
|
+
service: SERVICE6,
|
|
5878
|
+
agent: SERVICE6
|
|
5981
5879
|
})
|
|
5982
5880
|
];
|
|
5983
5881
|
let step = 0;
|
|
5984
5882
|
for (const msg of messages) {
|
|
5985
5883
|
const mid = msg.id ?? `m${step}`;
|
|
5986
5884
|
const llmId = `llm:${mid}`;
|
|
5987
|
-
const pdir =
|
|
5885
|
+
const pdir = join9(partRoot, mid);
|
|
5988
5886
|
const parts = [];
|
|
5989
5887
|
let partFiles = [];
|
|
5990
5888
|
try {
|
|
@@ -5993,9 +5891,9 @@ var OpencodeAdapter = class {
|
|
|
5993
5891
|
if (!isMissingJsonSource(error)) throw error;
|
|
5994
5892
|
}
|
|
5995
5893
|
for (const pf of partFiles) {
|
|
5996
|
-
parts.push(await readJsonFile(
|
|
5894
|
+
parts.push(await readJsonFile(join9(pdir, pf), options));
|
|
5997
5895
|
}
|
|
5998
|
-
const turnText2 =
|
|
5896
|
+
const turnText2 = textOf5(parts);
|
|
5999
5897
|
const isUser = msg.role === "user";
|
|
6000
5898
|
if (isUser) {
|
|
6001
5899
|
if (turnText2) {
|
|
@@ -6005,8 +5903,8 @@ var OpencodeAdapter = class {
|
|
|
6005
5903
|
spanId: `${llmId}:user`,
|
|
6006
5904
|
parentSpanId: rootId,
|
|
6007
5905
|
startTime: isoOf(msg.time?.created),
|
|
6008
|
-
service:
|
|
6009
|
-
agent:
|
|
5906
|
+
service: SERVICE6,
|
|
5907
|
+
agent: SERVICE6,
|
|
6010
5908
|
step,
|
|
6011
5909
|
content: turnText2,
|
|
6012
5910
|
contentSource: parts.filter((part) => part.type === "text").flatMap((part) => {
|
|
@@ -6027,8 +5925,8 @@ var OpencodeAdapter = class {
|
|
|
6027
5925
|
kind: "LLM",
|
|
6028
5926
|
startTime: isoOf(msg.time?.created),
|
|
6029
5927
|
endTime: isoOf(msg.time?.completed ?? msg.time?.created),
|
|
6030
|
-
service:
|
|
6031
|
-
agent:
|
|
5928
|
+
service: SERVICE6,
|
|
5929
|
+
agent: SERVICE6,
|
|
6032
5930
|
model: msg.modelID ?? null,
|
|
6033
5931
|
inputTokens: msg.tokens?.input ?? null,
|
|
6034
5932
|
outputTokens: msg.tokens?.output ?? null,
|
|
@@ -6059,8 +5957,8 @@ var OpencodeAdapter = class {
|
|
|
6059
5957
|
endTime: isoOf(msg.time?.completed ?? msg.time?.created),
|
|
6060
5958
|
status: err ? "ERROR" : "OK",
|
|
6061
5959
|
statusMessage: err ? (part.state?.error ?? "").slice(0, 500) : void 0,
|
|
6062
|
-
service:
|
|
6063
|
-
agent:
|
|
5960
|
+
service: SERVICE6,
|
|
5961
|
+
agent: SERVICE6,
|
|
6064
5962
|
tool: part.tool,
|
|
6065
5963
|
step,
|
|
6066
5964
|
extra: toolIoAttributes({
|
|
@@ -6079,9 +5977,9 @@ var OpencodeAdapter = class {
|
|
|
6079
5977
|
};
|
|
6080
5978
|
|
|
6081
5979
|
// src/adapters/harness-sessions.ts
|
|
6082
|
-
import { homedir as
|
|
6083
|
-
import { open, stat as
|
|
6084
|
-
import { join as
|
|
5980
|
+
import { homedir as homedir8 } from "os";
|
|
5981
|
+
import { open, stat as stat8 } from "fs/promises";
|
|
5982
|
+
import { join as join10 } from "path";
|
|
6085
5983
|
import {
|
|
6086
5984
|
claudeCodeRefForFile,
|
|
6087
5985
|
codexRefForFile,
|
|
@@ -6105,7 +6003,7 @@ function nativeRef(harness, ref) {
|
|
|
6105
6003
|
case "pi":
|
|
6106
6004
|
return selected(piRefForFile(ref.path));
|
|
6107
6005
|
case "kimi-code":
|
|
6108
|
-
return selected(kimiRefForFile(ref.path.endsWith("wire.jsonl") ? ref.path :
|
|
6006
|
+
return selected(kimiRefForFile(ref.path.endsWith("wire.jsonl") ? ref.path : join10(ref.path, "wire.jsonl")));
|
|
6109
6007
|
case "factory-droids":
|
|
6110
6008
|
return selected(factoryRefForFile(ref.path));
|
|
6111
6009
|
case "opencode":
|
|
@@ -6316,7 +6214,7 @@ var HarnessSessionsAdapter = class {
|
|
|
6316
6214
|
scopedAdapter;
|
|
6317
6215
|
async locate(opts = {}) {
|
|
6318
6216
|
if (this.scopedAdapter) return this.scopedAdapter.locate(opts);
|
|
6319
|
-
const found = await this.reader.locate(
|
|
6217
|
+
const found = await this.reader.locate(homedir8(), { sinceMs: opts.sinceMs, cwd: opts.cwd });
|
|
6320
6218
|
const refs = found.filter((native) => this.nativeHarness !== "claude-code" || native.parentNativeSessionId === null).map((native) => {
|
|
6321
6219
|
const ref = tracesRef(native, this.harness);
|
|
6322
6220
|
this.refs.set(`${ref.sessionId}\0${ref.path}`, native);
|
|
@@ -6332,7 +6230,7 @@ var HarnessSessionsAdapter = class {
|
|
|
6332
6230
|
if (this.scopedAdapter instanceof ClaudeAdapter) {
|
|
6333
6231
|
return (await this.scopedAdapter.locate(opts)).filter((ref) => ref.sessionId === sessionId);
|
|
6334
6232
|
}
|
|
6335
|
-
const refs = await this.reader.locate(
|
|
6233
|
+
const refs = await this.reader.locate(homedir8(), { nativeSessionId: sessionId, sinceMs: opts.sinceMs, cwd: opts.cwd });
|
|
6336
6234
|
const selected = refs.map((native) => {
|
|
6337
6235
|
const ref = tracesRef(native, this.harness);
|
|
6338
6236
|
this.refs.set(`${ref.sessionId}\0${ref.path}`, native);
|
|
@@ -6350,7 +6248,7 @@ var HarnessSessionsAdapter = class {
|
|
|
6350
6248
|
const settings = ref.path.replace(/\.jsonl$/u, ".settings.json");
|
|
6351
6249
|
if (paths.includes(settings)) return paths;
|
|
6352
6250
|
try {
|
|
6353
|
-
await
|
|
6251
|
+
await stat8(settings);
|
|
6354
6252
|
return [...paths, settings];
|
|
6355
6253
|
} catch (error) {
|
|
6356
6254
|
if (error.code === "ENOENT") return paths;
|
|
@@ -6497,11 +6395,11 @@ var SHARED_SESSION_ADAPTERS = [
|
|
|
6497
6395
|
];
|
|
6498
6396
|
|
|
6499
6397
|
// src/adapters/qwen.ts
|
|
6500
|
-
import { readdir as
|
|
6501
|
-
import { homedir as
|
|
6502
|
-
import { basename as
|
|
6503
|
-
var
|
|
6504
|
-
function
|
|
6398
|
+
import { readdir as readdir10, stat as stat9 } from "fs/promises";
|
|
6399
|
+
import { homedir as homedir9 } from "os";
|
|
6400
|
+
import { basename as basename6, join as join11 } from "path";
|
|
6401
|
+
var SERVICE7 = "qwen";
|
|
6402
|
+
function textOf6(parts) {
|
|
6505
6403
|
if (!parts) return "";
|
|
6506
6404
|
return parts.filter((p) => typeof p.text === "string").map((p) => p.text).join("");
|
|
6507
6405
|
}
|
|
@@ -6509,23 +6407,23 @@ var QwenAdapter = class {
|
|
|
6509
6407
|
harness = "qwen";
|
|
6510
6408
|
aliases = ["qwen-code"];
|
|
6511
6409
|
root() {
|
|
6512
|
-
return
|
|
6410
|
+
return join11(homedir9(), ".qwen", "projects");
|
|
6513
6411
|
}
|
|
6514
6412
|
async locate(opts = {}) {
|
|
6515
6413
|
const root = this.root();
|
|
6516
6414
|
let projectDirs;
|
|
6517
6415
|
try {
|
|
6518
|
-
projectDirs = await
|
|
6416
|
+
projectDirs = await readdir10(root);
|
|
6519
6417
|
} catch (error) {
|
|
6520
6418
|
if (isMissingPathError(error)) return [];
|
|
6521
6419
|
throw error;
|
|
6522
6420
|
}
|
|
6523
6421
|
const refs = [];
|
|
6524
6422
|
for (const pd of projectDirs) {
|
|
6525
|
-
const chatsDir =
|
|
6423
|
+
const chatsDir = join11(root, pd, "chats");
|
|
6526
6424
|
let files;
|
|
6527
6425
|
try {
|
|
6528
|
-
files = await
|
|
6426
|
+
files = await readdir10(chatsDir);
|
|
6529
6427
|
} catch (error) {
|
|
6530
6428
|
if (isMissingPathError(error)) continue;
|
|
6531
6429
|
throw error;
|
|
@@ -6533,16 +6431,16 @@ var QwenAdapter = class {
|
|
|
6533
6431
|
if (opts.cwd) continue;
|
|
6534
6432
|
for (const f of files) {
|
|
6535
6433
|
if (!f.endsWith(".jsonl")) continue;
|
|
6536
|
-
const path =
|
|
6434
|
+
const path = join11(chatsDir, f);
|
|
6537
6435
|
let st;
|
|
6538
6436
|
try {
|
|
6539
|
-
st = await
|
|
6437
|
+
st = await stat9(path);
|
|
6540
6438
|
} catch (error) {
|
|
6541
6439
|
if (isMissingPathError(error)) continue;
|
|
6542
6440
|
throw error;
|
|
6543
6441
|
}
|
|
6544
6442
|
if (opts.sinceMs && st.mtimeMs < opts.sinceMs) continue;
|
|
6545
|
-
refs.push({ harness: this.harness, sessionId:
|
|
6443
|
+
refs.push({ harness: this.harness, sessionId: basename6(f, ".jsonl"), path, cwd: null, mtimeMs: st.mtimeMs });
|
|
6546
6444
|
}
|
|
6547
6445
|
}
|
|
6548
6446
|
return refs.sort((a, b) => b.mtimeMs - a.mtimeMs);
|
|
@@ -6576,13 +6474,13 @@ var QwenAdapter = class {
|
|
|
6576
6474
|
name: "llm.turn",
|
|
6577
6475
|
kind: "LLM",
|
|
6578
6476
|
startTime: ts,
|
|
6579
|
-
service:
|
|
6580
|
-
agent:
|
|
6477
|
+
service: SERVICE7,
|
|
6478
|
+
agent: SERVICE7,
|
|
6581
6479
|
model: r.model ?? null,
|
|
6582
6480
|
inputTokens: r.usageMetadata?.promptTokenCount ?? null,
|
|
6583
6481
|
outputTokens: r.usageMetadata?.candidatesTokenCount ?? null,
|
|
6584
6482
|
step,
|
|
6585
|
-
content: capText(
|
|
6483
|
+
content: capText(textOf6(r.message?.parts)) || null,
|
|
6586
6484
|
contentSource: textSources(r.message, "parts")
|
|
6587
6485
|
})
|
|
6588
6486
|
);
|
|
@@ -6597,8 +6495,8 @@ var QwenAdapter = class {
|
|
|
6597
6495
|
name: `tool.${name}`,
|
|
6598
6496
|
kind: "TOOL",
|
|
6599
6497
|
startTime: ts,
|
|
6600
|
-
service:
|
|
6601
|
-
agent:
|
|
6498
|
+
service: SERVICE7,
|
|
6499
|
+
agent: SERVICE7,
|
|
6602
6500
|
tool: name,
|
|
6603
6501
|
step,
|
|
6604
6502
|
extra: toolIoAttributes({ input: p.functionCall.args, inputSource: sourceOf(p.functionCall, "args") })
|
|
@@ -6610,7 +6508,7 @@ var QwenAdapter = class {
|
|
|
6610
6508
|
step += 1;
|
|
6611
6509
|
}
|
|
6612
6510
|
} else if (r.type === "user") {
|
|
6613
|
-
const prompt = capText(
|
|
6511
|
+
const prompt = capText(textOf6(r.message?.parts));
|
|
6614
6512
|
if (prompt) {
|
|
6615
6513
|
spans.push(
|
|
6616
6514
|
userPromptSpan({
|
|
@@ -6618,8 +6516,8 @@ var QwenAdapter = class {
|
|
|
6618
6516
|
spanId: `user:${r.uuid ?? step}`,
|
|
6619
6517
|
parentSpanId: sourceRootId,
|
|
6620
6518
|
startTime: ts,
|
|
6621
|
-
service:
|
|
6622
|
-
agent:
|
|
6519
|
+
service: SERVICE7,
|
|
6520
|
+
agent: SERVICE7,
|
|
6623
6521
|
step,
|
|
6624
6522
|
content: prompt,
|
|
6625
6523
|
contentSource: textSources(r.message, "parts")
|
|
@@ -6655,8 +6553,8 @@ var QwenAdapter = class {
|
|
|
6655
6553
|
kind: "AGENT",
|
|
6656
6554
|
startTime: firstTimestamp ?? (/* @__PURE__ */ new Date(0)).toISOString(),
|
|
6657
6555
|
endTime: lastTimestamp,
|
|
6658
|
-
service:
|
|
6659
|
-
agent:
|
|
6556
|
+
service: SERVICE7,
|
|
6557
|
+
agent: SERVICE7
|
|
6660
6558
|
});
|
|
6661
6559
|
return [root, ...spans];
|
|
6662
6560
|
}
|
|
@@ -6669,8 +6567,7 @@ var ADAPTERS = [
|
|
|
6669
6567
|
new GeminiAdapter(),
|
|
6670
6568
|
new QwenAdapter(),
|
|
6671
6569
|
new AmpAdapter(),
|
|
6672
|
-
new CopilotAdapter()
|
|
6673
|
-
new ForgeAdapter()
|
|
6570
|
+
new CopilotAdapter()
|
|
6674
6571
|
];
|
|
6675
6572
|
var BY_NAME = /* @__PURE__ */ new Map();
|
|
6676
6573
|
for (const a of ADAPTERS) {
|
|
@@ -6697,8 +6594,8 @@ function selectAdapters(opts) {
|
|
|
6697
6594
|
}
|
|
6698
6595
|
|
|
6699
6596
|
// src/repo.ts
|
|
6700
|
-
import { realpath as realpath2, stat as
|
|
6701
|
-
import { dirname as dirname4, isAbsolute as isAbsolute3, join as
|
|
6597
|
+
import { realpath as realpath2, stat as stat10 } from "fs/promises";
|
|
6598
|
+
import { dirname as dirname4, isAbsolute as isAbsolute3, join as join12, normalize, parse as parsePath } from "path";
|
|
6702
6599
|
function normalizeRemote(url) {
|
|
6703
6600
|
const raw = url.trim();
|
|
6704
6601
|
if (!raw) return null;
|
|
@@ -6722,7 +6619,7 @@ function normalizeRemote(url) {
|
|
|
6722
6619
|
return null;
|
|
6723
6620
|
}
|
|
6724
6621
|
async function readGit(cwd) {
|
|
6725
|
-
await
|
|
6622
|
+
await stat10(`${cwd}/.git`);
|
|
6726
6623
|
const { execFile } = await import("child_process");
|
|
6727
6624
|
const { promisify } = await import("util");
|
|
6728
6625
|
const run = promisify(execFile);
|
|
@@ -6815,7 +6712,7 @@ function cwdMatchesSelection(cwd, selections) {
|
|
|
6815
6712
|
}
|
|
6816
6713
|
async function pathStat(path) {
|
|
6817
6714
|
try {
|
|
6818
|
-
return await
|
|
6715
|
+
return await stat10(path);
|
|
6819
6716
|
} catch {
|
|
6820
6717
|
return null;
|
|
6821
6718
|
}
|
|
@@ -6839,7 +6736,7 @@ async function nearestExistingDir(path) {
|
|
|
6839
6736
|
async function findGitRoot(path) {
|
|
6840
6737
|
let cur = await nearestExistingDir(path);
|
|
6841
6738
|
while (cur) {
|
|
6842
|
-
if (await pathStat(
|
|
6739
|
+
if (await pathStat(join12(cur, ".git"))) return cur;
|
|
6843
6740
|
const parent = dirname4(cur);
|
|
6844
6741
|
if (parent === cur) return null;
|
|
6845
6742
|
cur = parent;
|
|
@@ -6857,7 +6754,7 @@ async function repairDashedPath(cwd) {
|
|
|
6857
6754
|
while (index < parts.length) {
|
|
6858
6755
|
const nextPart = parts[index];
|
|
6859
6756
|
if (!nextPart) break;
|
|
6860
|
-
const exact =
|
|
6757
|
+
const exact = join12(current, nextPart);
|
|
6861
6758
|
if (!await directoryExists(exact)) break;
|
|
6862
6759
|
current = exact;
|
|
6863
6760
|
index += 1;
|
|
@@ -6867,7 +6764,7 @@ async function repairDashedPath(cwd) {
|
|
|
6867
6764
|
let consumed = 0;
|
|
6868
6765
|
for (let n = parts.length - index; n >= 1; n -= 1) {
|
|
6869
6766
|
const segment = parts.slice(index, index + n).join("-");
|
|
6870
|
-
const candidate =
|
|
6767
|
+
const candidate = join12(current, segment);
|
|
6871
6768
|
if (await directoryExists(candidate)) {
|
|
6872
6769
|
match = candidate;
|
|
6873
6770
|
consumed = n;
|
|
@@ -6951,7 +6848,7 @@ function extractAbsolutePaths(spans) {
|
|
|
6951
6848
|
async function resolveRepoAttrs(cwd) {
|
|
6952
6849
|
if (!cwd) return {};
|
|
6953
6850
|
const attrs = { [ATTR.CWD]: cwd };
|
|
6954
|
-
const
|
|
6851
|
+
const basename15 = (() => {
|
|
6955
6852
|
const trimmed = cwd.replace(/\/+$/g, "");
|
|
6956
6853
|
const idx = trimmed.lastIndexOf("/");
|
|
6957
6854
|
const name = idx === -1 ? trimmed : trimmed.slice(idx + 1);
|
|
@@ -6973,7 +6870,7 @@ async function resolveRepoAttrs(cwd) {
|
|
|
6973
6870
|
if (commit) attrs[ATTR.GIT_COMMIT] = commit;
|
|
6974
6871
|
} catch {
|
|
6975
6872
|
}
|
|
6976
|
-
attrs[ATTR.SUBJECT_KEY] =
|
|
6873
|
+
attrs[ATTR.SUBJECT_KEY] = basename15;
|
|
6977
6874
|
return attrs;
|
|
6978
6875
|
}
|
|
6979
6876
|
async function repoCandidateForPath(path) {
|
|
@@ -7283,7 +7180,7 @@ function describeSessionRelationship(ref, spans) {
|
|
|
7283
7180
|
// src/evidence.ts
|
|
7284
7181
|
import { mkdtemp, writeFile as writeFile2 } from "fs/promises";
|
|
7285
7182
|
import { tmpdir as tmpdir2 } from "os";
|
|
7286
|
-
import { join as
|
|
7183
|
+
import { join as join13 } from "path";
|
|
7287
7184
|
import {
|
|
7288
7185
|
OPENINFERENCE_SPAN_KIND as OPENINFERENCE_SPAN_KIND3,
|
|
7289
7186
|
TOOL_NAME as TOOL_NAME4
|
|
@@ -7413,14 +7310,14 @@ function serializePolicyEvidence(records) {
|
|
|
7413
7310
|
`;
|
|
7414
7311
|
}
|
|
7415
7312
|
async function writePolicyEvidenceFile(records, outPath) {
|
|
7416
|
-
const path = outPath ??
|
|
7313
|
+
const path = outPath ?? join13(await mkdtemp(join13(tmpdir2(), "traces-evidence-")), "policy-evidence.jsonl");
|
|
7417
7314
|
await writeFile2(path, serializePolicyEvidence(records), "utf8");
|
|
7418
7315
|
return path;
|
|
7419
7316
|
}
|
|
7420
7317
|
|
|
7421
7318
|
// src/adoption.ts
|
|
7422
7319
|
import { readFile as readFile4 } from "fs/promises";
|
|
7423
|
-
import { join as
|
|
7320
|
+
import { join as join14 } from "path";
|
|
7424
7321
|
function toolName2(s) {
|
|
7425
7322
|
const n = s.attributes["tool.name"];
|
|
7426
7323
|
if (typeof n === "string") return n;
|
|
@@ -7540,7 +7437,7 @@ async function readLoopRuns(cwds, sessionIds) {
|
|
|
7540
7437
|
seenCwds.add(cwd);
|
|
7541
7438
|
const firstSourceByRun = /* @__PURE__ */ new Map();
|
|
7542
7439
|
for (const artifactDir of [".agent", ".evolve"]) {
|
|
7543
|
-
const path =
|
|
7440
|
+
const path = join14(cwd, artifactDir, "skill-runs.jsonl");
|
|
7544
7441
|
let raw;
|
|
7545
7442
|
try {
|
|
7546
7443
|
raw = await readFile4(path, "utf8");
|
|
@@ -8177,7 +8074,7 @@ var COMMAND_PREFIXES = /* @__PURE__ */ new Set([
|
|
|
8177
8074
|
var ASSIGNMENT = /^[A-Za-z_][A-Za-z0-9_]*=/;
|
|
8178
8075
|
var MAX_SHELL_DEPTH = 4;
|
|
8179
8076
|
var MAX_WORDS = 2e4;
|
|
8180
|
-
function
|
|
8077
|
+
function basename7(word) {
|
|
8181
8078
|
const cut = word.lastIndexOf("/");
|
|
8182
8079
|
return cut === -1 ? word : word.slice(cut + 1);
|
|
8183
8080
|
}
|
|
@@ -8276,7 +8173,7 @@ var ShellScanner = class {
|
|
|
8276
8173
|
let start = 0;
|
|
8277
8174
|
while (start < words.length) {
|
|
8278
8175
|
const word = words[start];
|
|
8279
|
-
if (ASSIGNMENT.test(word) || COMMAND_PREFIXES.has(
|
|
8176
|
+
if (ASSIGNMENT.test(word) || COMMAND_PREFIXES.has(basename7(word))) start += 1;
|
|
8280
8177
|
else break;
|
|
8281
8178
|
}
|
|
8282
8179
|
return start === 0 || start >= words.length ? words : words.slice(start);
|
|
@@ -8417,7 +8314,7 @@ function shellCommands(script, depth = 0) {
|
|
|
8417
8314
|
const out = [];
|
|
8418
8315
|
for (const words of commands) {
|
|
8419
8316
|
out.push(words);
|
|
8420
|
-
const name =
|
|
8317
|
+
const name = basename7(words[0] ?? "");
|
|
8421
8318
|
if (!SHELLS.has(name) || depth >= MAX_SHELL_DEPTH) continue;
|
|
8422
8319
|
for (let index = 1; index < words.length; index += 1) {
|
|
8423
8320
|
const word = words[index];
|
|
@@ -8445,7 +8342,7 @@ function commandTextFromInput(input) {
|
|
|
8445
8342
|
if (!Array.isArray(value) || value.length === 0) return void 0;
|
|
8446
8343
|
const words = value.filter((entry) => typeof entry === "string");
|
|
8447
8344
|
if (words.length !== value.length) return void 0;
|
|
8448
|
-
const head =
|
|
8345
|
+
const head = basename7(words[0] ?? "");
|
|
8449
8346
|
if (SHELLS.has(head)) {
|
|
8450
8347
|
const flag = words.findIndex((word, position) => position > 0 && /^-[a-z]*c$/.test(word));
|
|
8451
8348
|
if (flag !== -1 && words[flag + 1] !== void 0) return words[flag + 1];
|
|
@@ -8507,7 +8404,7 @@ function stringAttribute2(span2, key) {
|
|
|
8507
8404
|
const value = span2.attributes[key];
|
|
8508
8405
|
return typeof value === "string" ? value : null;
|
|
8509
8406
|
}
|
|
8510
|
-
function
|
|
8407
|
+
function basename8(word) {
|
|
8511
8408
|
const cut = word.lastIndexOf("/");
|
|
8512
8409
|
return cut === -1 ? word : word.slice(cut + 1);
|
|
8513
8410
|
}
|
|
@@ -8590,7 +8487,7 @@ function numbersInLine(line) {
|
|
|
8590
8487
|
function inferHeadBranch(commands, upTo, output) {
|
|
8591
8488
|
for (let index = upTo - 1; index >= 0; index -= 1) {
|
|
8592
8489
|
const words = commands[index];
|
|
8593
|
-
if (
|
|
8490
|
+
if (basename8(words[0] ?? "") !== "git" || words.length < 2) continue;
|
|
8594
8491
|
const sub = words[1];
|
|
8595
8492
|
const rest = words.slice(2);
|
|
8596
8493
|
if (sub === "push") {
|
|
@@ -8665,7 +8562,7 @@ function eventsFromRecord(record2, recordIndex) {
|
|
|
8665
8562
|
let createIndex = 0;
|
|
8666
8563
|
for (let index = 0; index < commands.length; index += 1) {
|
|
8667
8564
|
const words = commands[index];
|
|
8668
|
-
if (words.length < 3 || !GH_NAMES.has(
|
|
8565
|
+
if (words.length < 3 || !GH_NAMES.has(basename8(words[0])) || words[1] !== "pr") continue;
|
|
8669
8566
|
const action = words[2];
|
|
8670
8567
|
if (action === "create") {
|
|
8671
8568
|
const printedNumber = printed[createIndex] ?? null;
|
|
@@ -9634,17 +9531,17 @@ import { isUtf8 as isUtf82 } from "buffer";
|
|
|
9634
9531
|
import { createHash as createHash10 } from "crypto";
|
|
9635
9532
|
import { constants } from "fs";
|
|
9636
9533
|
import { lstat as lstat2, open as open2, realpath as realpath3 } from "fs/promises";
|
|
9637
|
-
import { dirname as dirname8, isAbsolute as isAbsolute4, join as
|
|
9534
|
+
import { dirname as dirname8, isAbsolute as isAbsolute4, join as join18, relative as relative5, resolve as resolve6, sep as sep2 } from "path";
|
|
9638
9535
|
|
|
9639
9536
|
// src/bundle.ts
|
|
9640
9537
|
import { createHash as createHash9 } from "crypto";
|
|
9641
|
-
import { copyFile, cp, lstat, mkdir as mkdir2, readdir as
|
|
9642
|
-
import { dirname as dirname7, join as
|
|
9538
|
+
import { copyFile, cp, lstat, mkdir as mkdir2, readdir as readdir13, readFile as readFile7, stat as stat12, writeFile as writeFile5 } from "fs/promises";
|
|
9539
|
+
import { dirname as dirname7, join as join17, relative as relative4, resolve as resolve5, sep } from "path";
|
|
9643
9540
|
|
|
9644
9541
|
// src/improvement.ts
|
|
9645
9542
|
import { access, mkdir, mkdtemp as mkdtemp2, writeFile as writeFile3 } from "fs/promises";
|
|
9646
9543
|
import { tmpdir as tmpdir3 } from "os";
|
|
9647
|
-
import { dirname as dirname5, join as
|
|
9544
|
+
import { dirname as dirname5, join as join15, resolve as resolve4 } from "path";
|
|
9648
9545
|
import { pathToFileURL } from "url";
|
|
9649
9546
|
import {
|
|
9650
9547
|
AnalystRegistry,
|
|
@@ -10151,7 +10048,7 @@ function formatFindingRejections(reasons) {
|
|
|
10151
10048
|
|
|
10152
10049
|
// src/external.ts
|
|
10153
10050
|
import { spawn } from "child_process";
|
|
10154
|
-
import { readdir as
|
|
10051
|
+
import { readdir as readdir11, readFile as readFile5 } from "fs/promises";
|
|
10155
10052
|
function forceKill(child) {
|
|
10156
10053
|
try {
|
|
10157
10054
|
child.kill("SIGKILL");
|
|
@@ -10256,14 +10153,14 @@ function readProcessTableWithPs() {
|
|
|
10256
10153
|
});
|
|
10257
10154
|
}
|
|
10258
10155
|
async function readLinuxProcProcessTable() {
|
|
10259
|
-
const entries = await
|
|
10156
|
+
const entries = await readdir11("/proc", { withFileTypes: true });
|
|
10260
10157
|
const rows = await Promise.all(
|
|
10261
10158
|
entries.filter((entry) => entry.isDirectory() && /^\d+$/.test(entry.name)).map(async (entry) => {
|
|
10262
10159
|
try {
|
|
10263
|
-
const
|
|
10264
|
-
const commandEnd =
|
|
10160
|
+
const stat18 = await readFile5(`/proc/${entry.name}/stat`, "utf8");
|
|
10161
|
+
const commandEnd = stat18.lastIndexOf(")");
|
|
10265
10162
|
if (commandEnd < 0) return void 0;
|
|
10266
|
-
const fields =
|
|
10163
|
+
const fields = stat18.slice(commandEnd + 1).trim().split(/\s+/);
|
|
10267
10164
|
const pid = Number(entry.name);
|
|
10268
10165
|
const parentPid = Number(fields[1]);
|
|
10269
10166
|
if (!Number.isSafeInteger(pid) || pid < 1 || !Number.isSafeInteger(parentPid) || parentPid < 0) {
|
|
@@ -11938,13 +11835,13 @@ async function runTraceStoreInvestigation(opts) {
|
|
|
11938
11835
|
};
|
|
11939
11836
|
}
|
|
11940
11837
|
async function writeTraceImprovementArtifacts(result, outDir) {
|
|
11941
|
-
const directory = outDir ? resolve4(outDir) : await mkdtemp2(
|
|
11838
|
+
const directory = outDir ? resolve4(outDir) : await mkdtemp2(join15(tmpdir3(), "traces-improvement-"));
|
|
11942
11839
|
await mkdir(directory, { recursive: true });
|
|
11943
11840
|
const paths = {
|
|
11944
11841
|
directory,
|
|
11945
|
-
result:
|
|
11946
|
-
evidence:
|
|
11947
|
-
report:
|
|
11842
|
+
result: join15(directory, "result.json"),
|
|
11843
|
+
evidence: join15(directory, "evidence.jsonl"),
|
|
11844
|
+
report: join15(directory, "report.md"),
|
|
11948
11845
|
traces: result.otlpPath
|
|
11949
11846
|
};
|
|
11950
11847
|
const { report, ...machineResult } = result;
|
|
@@ -11957,11 +11854,11 @@ async function writeTraceImprovementArtifacts(result, outDir) {
|
|
|
11957
11854
|
}
|
|
11958
11855
|
async function runTraceImprovement(opts) {
|
|
11959
11856
|
if (opts.sourceBundle && opts.outDir) await assertOutsideSourceBundle(opts.sourceBundle.path, opts.outDir);
|
|
11960
|
-
const directory = opts.outDir ? resolve4(opts.outDir) : await mkdtemp2(
|
|
11857
|
+
const directory = opts.outDir ? resolve4(opts.outDir) : await mkdtemp2(join15(tmpdir3(), "traces-improvement-"));
|
|
11961
11858
|
await mkdir(directory, { recursive: true });
|
|
11962
11859
|
const investigation = await runTraceInvestigation({
|
|
11963
11860
|
...opts,
|
|
11964
|
-
otlpOutPath: opts.otlpOutPath ??
|
|
11861
|
+
otlpOutPath: opts.otlpOutPath ?? join15(directory, "traces.otlp.jsonl")
|
|
11965
11862
|
});
|
|
11966
11863
|
const result = {
|
|
11967
11864
|
...investigation,
|
|
@@ -11978,9 +11875,9 @@ async function saveReport(path, report) {
|
|
|
11978
11875
|
}
|
|
11979
11876
|
|
|
11980
11877
|
// src/session-index.ts
|
|
11981
|
-
import { mkdtemp as mkdtemp3, readdir as
|
|
11878
|
+
import { mkdtemp as mkdtemp3, readdir as readdir12, readFile as readFile6, stat as stat11, writeFile as writeFile4 } from "fs/promises";
|
|
11982
11879
|
import { tmpdir as tmpdir4 } from "os";
|
|
11983
|
-
import { dirname as dirname6, join as
|
|
11880
|
+
import { dirname as dirname6, join as join16 } from "path";
|
|
11984
11881
|
function indexRow(record2) {
|
|
11985
11882
|
return {
|
|
11986
11883
|
session: record2.session,
|
|
@@ -12035,7 +11932,7 @@ function buildSessionIndex(records, opts = {}) {
|
|
|
12035
11932
|
}
|
|
12036
11933
|
async function pathStat2(path) {
|
|
12037
11934
|
try {
|
|
12038
|
-
return await
|
|
11935
|
+
return await stat11(path);
|
|
12039
11936
|
} catch {
|
|
12040
11937
|
return null;
|
|
12041
11938
|
}
|
|
@@ -12053,7 +11950,7 @@ async function findContextRoot(cwd) {
|
|
|
12053
11950
|
if (!s) return null;
|
|
12054
11951
|
if (!s.isDirectory()) current = dirname6(current);
|
|
12055
11952
|
for (; ; ) {
|
|
12056
|
-
if (await pathStat2(
|
|
11953
|
+
if (await pathStat2(join16(current, ".git")) || await dirExists(join16(current, ".evolve")) || await fileExists(join16(current, "AGENTS.md")) || await fileExists(join16(current, "CLAUDE.md"))) {
|
|
12057
11954
|
return current;
|
|
12058
11955
|
}
|
|
12059
11956
|
const parent = dirname6(current);
|
|
@@ -12115,13 +12012,13 @@ async function walkMarkdown(root, kind, maxFiles = 100) {
|
|
|
12115
12012
|
if (out.length >= maxFiles) return;
|
|
12116
12013
|
let entries;
|
|
12117
12014
|
try {
|
|
12118
|
-
entries = await
|
|
12015
|
+
entries = await readdir12(dir, { withFileTypes: true });
|
|
12119
12016
|
} catch {
|
|
12120
12017
|
return;
|
|
12121
12018
|
}
|
|
12122
12019
|
for (const entry of entries) {
|
|
12123
12020
|
if (out.length >= maxFiles) return;
|
|
12124
|
-
const path =
|
|
12021
|
+
const path = join16(dir, entry.name);
|
|
12125
12022
|
if (entry.isDirectory()) {
|
|
12126
12023
|
await walk(path);
|
|
12127
12024
|
} else if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
@@ -12136,33 +12033,33 @@ async function walkMarkdown(root, kind, maxFiles = 100) {
|
|
|
12136
12033
|
async function collectContextRoot(root) {
|
|
12137
12034
|
const files = [];
|
|
12138
12035
|
for (const name of ["AGENTS.md", "CLAUDE.md", "GEMINI.md"]) {
|
|
12139
|
-
const summary = await summarizeFile(
|
|
12036
|
+
const summary = await summarizeFile(join16(root, name), "instruction-doc");
|
|
12140
12037
|
if (summary) files.push(summary);
|
|
12141
12038
|
}
|
|
12142
|
-
const evolve =
|
|
12039
|
+
const evolve = join16(root, ".evolve");
|
|
12143
12040
|
for (const name of ["skill-runs.jsonl", "governor.jsonl", "experiments.jsonl"]) {
|
|
12144
|
-
const summary = await summarizeFile(
|
|
12041
|
+
const summary = await summarizeFile(join16(evolve, name), "evolve-jsonl");
|
|
12145
12042
|
if (summary) files.push(summary);
|
|
12146
12043
|
}
|
|
12147
12044
|
for (const name of ["scorecard.json", "current.json"]) {
|
|
12148
|
-
const summary = await summarizeFile(
|
|
12045
|
+
const summary = await summarizeFile(join16(evolve, name), "evolve-json");
|
|
12149
12046
|
if (summary) files.push(summary);
|
|
12150
12047
|
}
|
|
12151
|
-
files.push(...await walkMarkdown(
|
|
12152
|
-
files.push(...await walkMarkdown(
|
|
12048
|
+
files.push(...await walkMarkdown(join16(evolve, "reflections"), "reflection"));
|
|
12049
|
+
files.push(...await walkMarkdown(join16(evolve, "handoffs"), "handoff"));
|
|
12153
12050
|
for (const name of await listEvolveRootFiles(evolve)) {
|
|
12154
12051
|
if (/^handoff-.*\.md$/.test(name)) {
|
|
12155
|
-
const summary = await summarizeFile(
|
|
12052
|
+
const summary = await summarizeFile(join16(evolve, name), "handoff");
|
|
12156
12053
|
if (summary) files.push(summary);
|
|
12157
12054
|
}
|
|
12158
12055
|
}
|
|
12159
|
-
const progress2 = await summarizeFile(
|
|
12056
|
+
const progress2 = await summarizeFile(join16(evolve, "progress.md"), "other");
|
|
12160
12057
|
if (progress2) files.push(progress2);
|
|
12161
12058
|
return { root, files: files.sort((a, b) => a.path.localeCompare(b.path)) };
|
|
12162
12059
|
}
|
|
12163
12060
|
async function listEvolveRootFiles(evolve) {
|
|
12164
12061
|
try {
|
|
12165
|
-
const entries = await
|
|
12062
|
+
const entries = await readdir12(evolve, { withFileTypes: true });
|
|
12166
12063
|
return entries.filter((entry) => entry.isFile()).map((entry) => entry.name).sort();
|
|
12167
12064
|
} catch {
|
|
12168
12065
|
return [];
|
|
@@ -12211,7 +12108,7 @@ function serializeSessionIndex(index) {
|
|
|
12211
12108
|
`;
|
|
12212
12109
|
}
|
|
12213
12110
|
async function writeSessionIndexFile(index, outPath) {
|
|
12214
|
-
const path = outPath ??
|
|
12111
|
+
const path = outPath ?? join16(await mkdtemp3(join16(tmpdir4(), "traces-index-")), "session-index.json");
|
|
12215
12112
|
await writeFile4(path, serializeSessionIndex(index), "utf8");
|
|
12216
12113
|
return path;
|
|
12217
12114
|
}
|
|
@@ -12705,7 +12602,7 @@ function bundlePath(...parts) {
|
|
|
12705
12602
|
}
|
|
12706
12603
|
async function statOrNull(path) {
|
|
12707
12604
|
try {
|
|
12708
|
-
return await
|
|
12605
|
+
return await stat12(path);
|
|
12709
12606
|
} catch (error) {
|
|
12710
12607
|
if (isMissingPathError(error)) return null;
|
|
12711
12608
|
if (error.code === "ENOTDIR") return null;
|
|
@@ -12754,8 +12651,8 @@ async function listSessionBundleFiles(root) {
|
|
|
12754
12651
|
const pending = [resolve5(root)];
|
|
12755
12652
|
while (pending.length > 0) {
|
|
12756
12653
|
const dir = pending.pop();
|
|
12757
|
-
for (const entry of await
|
|
12758
|
-
const path =
|
|
12654
|
+
for (const entry of await readdir13(dir, { withFileTypes: true })) {
|
|
12655
|
+
const path = join17(dir, entry.name);
|
|
12759
12656
|
if (entry.isDirectory()) pending.push(path);
|
|
12760
12657
|
else if (entry.isFile()) out.push(relative4(resolve5(root), path).split(sep).join("/"));
|
|
12761
12658
|
}
|
|
@@ -12763,14 +12660,14 @@ async function listSessionBundleFiles(root) {
|
|
|
12763
12660
|
return out.sort();
|
|
12764
12661
|
}
|
|
12765
12662
|
async function sliceLedgerJsonl(ctx, name) {
|
|
12766
|
-
const source =
|
|
12663
|
+
const source = join17(ctx.evolveDir, name);
|
|
12767
12664
|
const s = await statOrNull(source);
|
|
12768
12665
|
if (!s?.isFile()) {
|
|
12769
12666
|
ctx.absent.push({ path: bundlePath("ledger", name), reason: `no ${name} at ${source}` });
|
|
12770
12667
|
return;
|
|
12771
12668
|
}
|
|
12772
12669
|
const text2 = await readFile7(source, "utf8");
|
|
12773
|
-
const target =
|
|
12670
|
+
const target = join17(ctx.ledgerDir, name);
|
|
12774
12671
|
if (ctx.windowStartMs === null || ctx.windowEndMs === null) {
|
|
12775
12672
|
await writeFile5(target, text2, "utf8");
|
|
12776
12673
|
ctx.slices.push({ path: bundlePath("ledger", name), source, rule: "copied-whole" });
|
|
@@ -12789,19 +12686,19 @@ async function sliceLedgerJsonl(ctx, name) {
|
|
|
12789
12686
|
});
|
|
12790
12687
|
}
|
|
12791
12688
|
async function copyLedgerWhole(ctx, name) {
|
|
12792
|
-
const source =
|
|
12689
|
+
const source = join17(ctx.evolveDir, name);
|
|
12793
12690
|
const s = await statOrNull(source);
|
|
12794
12691
|
if (!s?.isFile()) {
|
|
12795
12692
|
ctx.absent.push({ path: bundlePath("ledger", name), reason: `no ${name} at ${source}` });
|
|
12796
12693
|
return;
|
|
12797
12694
|
}
|
|
12798
|
-
await cp(source,
|
|
12695
|
+
await cp(source, join17(ctx.ledgerDir, name));
|
|
12799
12696
|
ctx.slices.push({ path: bundlePath("ledger", name), source, rule: "copied-whole" });
|
|
12800
12697
|
}
|
|
12801
12698
|
async function copyLatestHandoff(ctx) {
|
|
12802
12699
|
let names;
|
|
12803
12700
|
try {
|
|
12804
|
-
names = (await
|
|
12701
|
+
names = (await readdir13(ctx.evolveDir, { withFileTypes: true })).filter((entry) => entry.isFile() && /^handoff-.*\.md$/.test(entry.name)).map((entry) => entry.name).sort();
|
|
12805
12702
|
} catch {
|
|
12806
12703
|
names = [];
|
|
12807
12704
|
}
|
|
@@ -12813,12 +12710,12 @@ async function copyLatestHandoff(ctx) {
|
|
|
12813
12710
|
});
|
|
12814
12711
|
return;
|
|
12815
12712
|
}
|
|
12816
|
-
const source =
|
|
12817
|
-
await cp(source,
|
|
12713
|
+
const source = join17(ctx.evolveDir, latest);
|
|
12714
|
+
await cp(source, join17(ctx.ledgerDir, latest));
|
|
12818
12715
|
ctx.slices.push({ path: bundlePath("ledger", latest), source, rule: "latest-by-name" });
|
|
12819
12716
|
}
|
|
12820
12717
|
async function copyWindowReflections(ctx) {
|
|
12821
|
-
const reflectionsDir =
|
|
12718
|
+
const reflectionsDir = join17(ctx.evolveDir, "reflections");
|
|
12822
12719
|
const s = await statOrNull(reflectionsDir);
|
|
12823
12720
|
if (!s?.isDirectory()) {
|
|
12824
12721
|
ctx.absent.push({
|
|
@@ -12827,7 +12724,7 @@ async function copyWindowReflections(ctx) {
|
|
|
12827
12724
|
});
|
|
12828
12725
|
return;
|
|
12829
12726
|
}
|
|
12830
|
-
const names = (await
|
|
12727
|
+
const names = (await readdir13(reflectionsDir, { withFileTypes: true })).filter((entry) => entry.isFile() && entry.name.endsWith(".md")).map((entry) => entry.name).sort();
|
|
12831
12728
|
const windowed = ctx.windowStartMs === null || ctx.windowEndMs === null ? names : names.filter((name) => {
|
|
12832
12729
|
const date = name.match(/(\d{4}-\d{2}-\d{2})/)?.[1];
|
|
12833
12730
|
if (!date) return false;
|
|
@@ -12842,11 +12739,11 @@ async function copyWindowReflections(ctx) {
|
|
|
12842
12739
|
});
|
|
12843
12740
|
return;
|
|
12844
12741
|
}
|
|
12845
|
-
await mkdir2(
|
|
12742
|
+
await mkdir2(join17(ctx.ledgerDir, "reflections"), { recursive: true });
|
|
12846
12743
|
const rule = ctx.windowStartMs === null ? "copied-whole" : "session-window-dated-files";
|
|
12847
12744
|
for (const name of windowed) {
|
|
12848
|
-
const source =
|
|
12849
|
-
await cp(source,
|
|
12745
|
+
const source = join17(reflectionsDir, name);
|
|
12746
|
+
await cp(source, join17(ctx.ledgerDir, "reflections", name));
|
|
12850
12747
|
ctx.slices.push({ path: bundlePath("ledger", "reflections", name), source, rule });
|
|
12851
12748
|
}
|
|
12852
12749
|
}
|
|
@@ -12854,7 +12751,7 @@ async function assembleSessionBundle(opts) {
|
|
|
12854
12751
|
const { adapter, ref } = opts;
|
|
12855
12752
|
const generatedAt = opts.generatedAt ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
12856
12753
|
try {
|
|
12857
|
-
await
|
|
12754
|
+
await stat12(ref.path);
|
|
12858
12755
|
} catch (error) {
|
|
12859
12756
|
if (isMissingPathError(error)) {
|
|
12860
12757
|
throw new Error(`session transcript not found at ${ref.path} \u2014 a bundle cannot be assembled without its transcript`);
|
|
@@ -12870,17 +12767,17 @@ async function assembleSessionBundle(opts) {
|
|
|
12870
12767
|
const transcriptSha256 = row.sourceFiles.find((file) => resolve5(file.path) === resolve5(ref.path))?.sha256 ?? row.sourceSha256;
|
|
12871
12768
|
const outDir = resolve5(opts.outDir);
|
|
12872
12769
|
await mkdir2(outDir, { recursive: true });
|
|
12873
|
-
if ((await
|
|
12770
|
+
if ((await readdir13(outDir)).length > 0) {
|
|
12874
12771
|
throw new Error(
|
|
12875
12772
|
`bundle output directory ${outDir} is not empty \u2014 pass a new directory so one bundle holds exactly one session`
|
|
12876
12773
|
);
|
|
12877
12774
|
}
|
|
12878
12775
|
const absent = [];
|
|
12879
12776
|
const slices = [];
|
|
12880
|
-
await mkdir2(
|
|
12881
|
-
const subagentsSource =
|
|
12777
|
+
await mkdir2(join17(outDir, "session"), { recursive: true });
|
|
12778
|
+
const subagentsSource = join17(ref.path.replace(/\.jsonl$/, ""), "subagents");
|
|
12882
12779
|
if ((await statOrNull(subagentsSource))?.isDirectory()) {
|
|
12883
|
-
await cp(subagentsSource,
|
|
12780
|
+
await cp(subagentsSource, join17(outDir, "session", "subagents"), { recursive: true });
|
|
12884
12781
|
} else {
|
|
12885
12782
|
absent.push({ path: bundlePath("session", "subagents"), reason: `no subagents directory at ${subagentsSource}` });
|
|
12886
12783
|
}
|
|
@@ -12890,7 +12787,7 @@ async function assembleSessionBundle(opts) {
|
|
|
12890
12787
|
const sourceId = sourceFileId(file.path);
|
|
12891
12788
|
const subagentRelative = relative4(subagentsSource, file.path);
|
|
12892
12789
|
const path = resolve5(file.path) === resolve5(ref.path) ? bundlePath("session", "transcript.jsonl") : !subagentRelative.startsWith("..") && !subagentRelative.startsWith(sep) ? bundlePath("session", "subagents", subagentRelative) : bundlePath("session", "sources", `${sourceId}.jsonl`);
|
|
12893
|
-
const target =
|
|
12790
|
+
const target = join17(outDir, path);
|
|
12894
12791
|
await mkdir2(dirname7(target), { recursive: true });
|
|
12895
12792
|
await copyFile(file.path, target);
|
|
12896
12793
|
if (await fileSha256(target, opts.signal) !== file.sha256) {
|
|
@@ -12898,8 +12795,8 @@ async function assembleSessionBundle(opts) {
|
|
|
12898
12795
|
}
|
|
12899
12796
|
retainedSourceIds.set(path, sourceId);
|
|
12900
12797
|
}
|
|
12901
|
-
await mkdir2(
|
|
12902
|
-
const otlpPath =
|
|
12798
|
+
await mkdir2(join17(outDir, "derived"), { recursive: true });
|
|
12799
|
+
const otlpPath = join17(outDir, "derived", "trace.otlp.jsonl");
|
|
12903
12800
|
const investigation = await runTraceInvestigation({
|
|
12904
12801
|
spans,
|
|
12905
12802
|
harness: ref.harness,
|
|
@@ -12911,7 +12808,7 @@ async function assembleSessionBundle(opts) {
|
|
|
12911
12808
|
signal: opts.signal,
|
|
12912
12809
|
log: opts.log
|
|
12913
12810
|
});
|
|
12914
|
-
await writeFile5(
|
|
12811
|
+
await writeFile5(join17(outDir, "derived", "report.md"), investigation.report, "utf8");
|
|
12915
12812
|
const evidence3 = await buildPolicyEvidenceRecord(ref, spans, {
|
|
12916
12813
|
generatedAt,
|
|
12917
12814
|
minLoopOccurrences: opts.minLoopOccurrences,
|
|
@@ -12919,13 +12816,13 @@ async function assembleSessionBundle(opts) {
|
|
|
12919
12816
|
otlpPath: bundlePath("derived", "trace.otlp.jsonl"),
|
|
12920
12817
|
sourceSha256: transcriptSha256
|
|
12921
12818
|
});
|
|
12922
|
-
await writeFile5(
|
|
12819
|
+
await writeFile5(join17(outDir, "derived", "evidence.jsonl"), serializePolicyEvidence([evidence3]), "utf8");
|
|
12923
12820
|
const index = await buildSessionIndexFromRows([{ ref, spans }], {
|
|
12924
12821
|
generatedAt,
|
|
12925
12822
|
minLoopOccurrences: opts.minLoopOccurrences,
|
|
12926
12823
|
selection: { command: "bundle", harness: ref.harness, session: ref.sessionId }
|
|
12927
12824
|
});
|
|
12928
|
-
await writeFile5(
|
|
12825
|
+
await writeFile5(join17(outDir, "derived", "session-index.json"), serializeSessionIndex(index), "utf8");
|
|
12929
12826
|
const { firstSpanAt, lastSpanAt } = evidence3.metrics;
|
|
12930
12827
|
const windowStartMs = firstSpanAt !== null ? Date.parse(firstSpanAt) - SESSION_WINDOW_PAD_MS : null;
|
|
12931
12828
|
const windowEndMs = lastSpanAt !== null ? Date.parse(lastSpanAt) + SESSION_WINDOW_PAD_MS : null;
|
|
@@ -12933,11 +12830,11 @@ async function assembleSessionBundle(opts) {
|
|
|
12933
12830
|
if (!contextRoot) {
|
|
12934
12831
|
absent.push({ path: "ledger", reason: `no context root found from session cwd ${ref.cwd ?? "(unknown)"}` });
|
|
12935
12832
|
} else {
|
|
12936
|
-
const evolveDir =
|
|
12833
|
+
const evolveDir = join17(contextRoot, ".evolve");
|
|
12937
12834
|
if (!(await statOrNull(evolveDir))?.isDirectory()) {
|
|
12938
12835
|
absent.push({ path: "ledger", reason: `no .evolve ledger at ${evolveDir}` });
|
|
12939
12836
|
} else {
|
|
12940
|
-
const ledgerDir =
|
|
12837
|
+
const ledgerDir = join17(outDir, "ledger");
|
|
12941
12838
|
await mkdir2(ledgerDir, { recursive: true });
|
|
12942
12839
|
const ctx = { evolveDir, ledgerDir, windowStartMs, windowEndMs, slices, absent };
|
|
12943
12840
|
await sliceLedgerJsonl(ctx, "experiments.jsonl");
|
|
@@ -12957,8 +12854,8 @@ async function assembleSessionBundle(opts) {
|
|
|
12957
12854
|
} else {
|
|
12958
12855
|
const log = await runGitLog(ref.cwd, new Date(windowStartMs).toISOString(), new Date(windowEndMs).toISOString());
|
|
12959
12856
|
if (log.succeeded) {
|
|
12960
|
-
await mkdir2(
|
|
12961
|
-
await writeFile5(
|
|
12857
|
+
await mkdir2(join17(outDir, "repo"), { recursive: true });
|
|
12858
|
+
await writeFile5(join17(outDir, "repo", "git-log.txt"), log.stdout ? `${log.stdout}
|
|
12962
12859
|
` : "", "utf8");
|
|
12963
12860
|
} else {
|
|
12964
12861
|
absent.push({ path: gitLogPath, reason: `git log failed in ${ref.cwd}: ${log.error}` });
|
|
@@ -12997,20 +12894,20 @@ async function assembleSessionBundle(opts) {
|
|
|
12997
12894
|
async function hashSessionBundleFiles(root) {
|
|
12998
12895
|
const files = [];
|
|
12999
12896
|
for (const path of await listSessionBundleFiles(root)) {
|
|
13000
|
-
const filePath =
|
|
13001
|
-
const info = await
|
|
12897
|
+
const filePath = join17(root, path);
|
|
12898
|
+
const info = await stat12(filePath);
|
|
13002
12899
|
files.push({ path, bytes: info.size, sha256: await fileSha256(filePath) });
|
|
13003
12900
|
}
|
|
13004
12901
|
return files;
|
|
13005
12902
|
}
|
|
13006
12903
|
async function writeSessionBundleManifest(outDir, manifest) {
|
|
13007
|
-
const manifestPath =
|
|
12904
|
+
const manifestPath = join17(outDir, "manifest.json");
|
|
13008
12905
|
await writeFile5(manifestPath, `${JSON.stringify(manifest, null, 2)}
|
|
13009
12906
|
`, "utf8");
|
|
13010
12907
|
return manifestPath;
|
|
13011
12908
|
}
|
|
13012
12909
|
async function readSessionBundleManifest(bundleDir) {
|
|
13013
|
-
const path =
|
|
12910
|
+
const path = join17(resolve5(bundleDir), "manifest.json");
|
|
13014
12911
|
let text2;
|
|
13015
12912
|
try {
|
|
13016
12913
|
text2 = await readFile7(path, "utf8");
|
|
@@ -13054,8 +12951,8 @@ async function nonRegularEntries(root) {
|
|
|
13054
12951
|
const pending = [resolve5(root)];
|
|
13055
12952
|
while (pending.length > 0) {
|
|
13056
12953
|
const dir = pending.pop();
|
|
13057
|
-
for (const entry of await
|
|
13058
|
-
const path =
|
|
12954
|
+
for (const entry of await readdir13(dir, { withFileTypes: true })) {
|
|
12955
|
+
const path = join17(dir, entry.name);
|
|
13059
12956
|
if (entry.isDirectory()) pending.push(path);
|
|
13060
12957
|
else if (!entry.isFile()) out.push(relative4(resolve5(root), path).split(sep).join("/"));
|
|
13061
12958
|
}
|
|
@@ -13075,7 +12972,7 @@ async function verifySessionBundle(bundleDir) {
|
|
|
13075
12972
|
continue;
|
|
13076
12973
|
}
|
|
13077
12974
|
listed.add(file.path);
|
|
13078
|
-
const info = await lstat(
|
|
12975
|
+
const info = await lstat(join17(directory, file.path)).catch((error) => {
|
|
13079
12976
|
if (isMissingPathError(error)) return null;
|
|
13080
12977
|
throw error;
|
|
13081
12978
|
});
|
|
@@ -13084,7 +12981,7 @@ async function verifySessionBundle(bundleDir) {
|
|
|
13084
12981
|
continue;
|
|
13085
12982
|
}
|
|
13086
12983
|
if (!info.isFile()) continue;
|
|
13087
|
-
const sha2562 = await fileSha256(
|
|
12984
|
+
const sha2562 = await fileSha256(join17(directory, file.path));
|
|
13088
12985
|
if (info.size !== file.bytes || sha2562 !== file.sha256) {
|
|
13089
12986
|
issues.push({
|
|
13090
12987
|
kind: "mismatch",
|
|
@@ -13104,7 +13001,7 @@ async function verifySessionBundle(bundleDir) {
|
|
|
13104
13001
|
}
|
|
13105
13002
|
let source;
|
|
13106
13003
|
if (manifest.projection) {
|
|
13107
|
-
const sourceManifest =
|
|
13004
|
+
const sourceManifest = join17(manifest.projection.sourceDirectory, "manifest.json");
|
|
13108
13005
|
const bytes2 = await readFile7(sourceManifest).catch((error) => {
|
|
13109
13006
|
if (isMissingPathError(error)) return null;
|
|
13110
13007
|
throw error;
|
|
@@ -13142,7 +13039,7 @@ async function openBundleFile(root, file) {
|
|
|
13142
13039
|
const path = containedPath(root, file.path);
|
|
13143
13040
|
let current = root;
|
|
13144
13041
|
for (const part of relative5(root, path).split(sep2)) {
|
|
13145
|
-
current =
|
|
13042
|
+
current = join18(current, part);
|
|
13146
13043
|
if ((await lstat2(current)).isSymbolicLink()) throw new Error("bundle source symlinks are not permitted");
|
|
13147
13044
|
}
|
|
13148
13045
|
if (await realpath3(path) !== path) throw new Error("bundle source resolved outside its declared path");
|
|
@@ -13181,7 +13078,7 @@ async function createBundleSourceReader(directory, spans, options = {}) {
|
|
|
13181
13078
|
options.signal?.throwIfAborted();
|
|
13182
13079
|
if ((await lstat2(resolve6(directory))).isSymbolicLink()) throw new Error("bundle directory must not be a symlink");
|
|
13183
13080
|
const root = await realpath3(resolve6(directory));
|
|
13184
|
-
if ((await lstat2(
|
|
13081
|
+
if ((await lstat2(join18(root, "manifest.json"))).isSymbolicLink()) throw new Error("bundle manifest must not be a symlink");
|
|
13185
13082
|
const manifest = await readSessionBundleManifest(root);
|
|
13186
13083
|
if (manifest.view !== "full") throw new Error("original source reads require an explicitly authorized full bundle");
|
|
13187
13084
|
if (!Array.isArray(manifest.files)) throw new Error("bundle manifest has no file receipts");
|
|
@@ -13203,7 +13100,7 @@ async function createBundleSourceReader(directory, spans, options = {}) {
|
|
|
13203
13100
|
const traceFile = manifest.files.find((file) => file.path === TRACE_FILE);
|
|
13204
13101
|
if (!traceFile) throw new Error("bundle has no derived trace receipt");
|
|
13205
13102
|
await validateFile(root, traceFile, options.signal);
|
|
13206
|
-
const recorded = await readOtlpInput(
|
|
13103
|
+
const recorded = await readOtlpInput(join18(root, TRACE_FILE));
|
|
13207
13104
|
await validateFile(root, traceFile, options.signal);
|
|
13208
13105
|
const original = new Map(recorded.spans.map((span2) => [identity(span2), span2]));
|
|
13209
13106
|
const allowed = /* @__PURE__ */ new Map();
|
|
@@ -13601,7 +13498,7 @@ import {
|
|
|
13601
13498
|
readFile as readFile10,
|
|
13602
13499
|
rm as rm2
|
|
13603
13500
|
} from "fs/promises";
|
|
13604
|
-
import { basename as
|
|
13501
|
+
import { basename as basename10, dirname as dirname10, join as join21, resolve as resolve8 } from "path";
|
|
13605
13502
|
|
|
13606
13503
|
// src/codetracebench-files.ts
|
|
13607
13504
|
import { createHash as createHash12, randomUUID } from "crypto";
|
|
@@ -13614,18 +13511,18 @@ import {
|
|
|
13614
13511
|
rename as rename2,
|
|
13615
13512
|
rm,
|
|
13616
13513
|
rmdir,
|
|
13617
|
-
stat as
|
|
13514
|
+
stat as stat13,
|
|
13618
13515
|
unlink,
|
|
13619
13516
|
writeFile as writeFile6
|
|
13620
13517
|
} from "fs/promises";
|
|
13621
13518
|
import { hostname } from "os";
|
|
13622
|
-
import { basename as
|
|
13519
|
+
import { basename as basename9, dirname as dirname9, isAbsolute as isAbsolute5, join as join19, relative as relative6, resolve as resolve7, sep as sep3 } from "path";
|
|
13623
13520
|
async function claimImportLock(input) {
|
|
13624
13521
|
const claimId = randomUUID();
|
|
13625
13522
|
const path = `${input.outputDirectory}.lock`;
|
|
13626
|
-
const temporary =
|
|
13523
|
+
const temporary = join19(
|
|
13627
13524
|
dirname9(path),
|
|
13628
|
-
`.${
|
|
13525
|
+
`.${basename9(path)}.${claimId}.tmp`
|
|
13629
13526
|
);
|
|
13630
13527
|
const metadata = {
|
|
13631
13528
|
kind: "traces.codetracebench-import-lock",
|
|
@@ -13714,8 +13611,8 @@ async function publishStagedFiles(stagingDirectory, outputDirectory, files, sign
|
|
|
13714
13611
|
try {
|
|
13715
13612
|
for (const file of files) {
|
|
13716
13613
|
signal.throwIfAborted();
|
|
13717
|
-
const destination =
|
|
13718
|
-
await link(
|
|
13614
|
+
const destination = join19(outputDirectory, file);
|
|
13615
|
+
await link(join19(stagingDirectory, file), destination);
|
|
13719
13616
|
published.push(destination);
|
|
13720
13617
|
}
|
|
13721
13618
|
} catch (error) {
|
|
@@ -13745,7 +13642,7 @@ async function containedDirectory(path) {
|
|
|
13745
13642
|
cause: error
|
|
13746
13643
|
});
|
|
13747
13644
|
}
|
|
13748
|
-
const info = await
|
|
13645
|
+
const info = await stat13(canonical);
|
|
13749
13646
|
if (!info.isDirectory()) {
|
|
13750
13647
|
throw new TypeError(`CodeTraceBench trajectory path is not a directory: ${canonical}`);
|
|
13751
13648
|
}
|
|
@@ -13768,7 +13665,7 @@ async function optionalContainedFile(root, candidate) {
|
|
|
13768
13665
|
if (fromRoot === ".." || fromRoot.startsWith(`..${sep3}`) || isAbsolute5(fromRoot)) {
|
|
13769
13666
|
throw new Error(`CodeTraceBench trajectory file escapes its input directory: ${candidate}`);
|
|
13770
13667
|
}
|
|
13771
|
-
const info = await
|
|
13668
|
+
const info = await stat13(canonical);
|
|
13772
13669
|
if (!info.isFile()) {
|
|
13773
13670
|
throw new TypeError(`CodeTraceBench trajectory path is not a file: ${candidate}`);
|
|
13774
13671
|
}
|
|
@@ -13785,9 +13682,9 @@ async function assertPathMissing(path) {
|
|
|
13785
13682
|
}
|
|
13786
13683
|
async function atomicWriteFile(path, content, signal) {
|
|
13787
13684
|
signal.throwIfAborted();
|
|
13788
|
-
const temporary =
|
|
13685
|
+
const temporary = join19(
|
|
13789
13686
|
dirname9(path),
|
|
13790
|
-
`.${
|
|
13687
|
+
`.${basename9(path)}.${randomUUID()}.tmp`
|
|
13791
13688
|
);
|
|
13792
13689
|
try {
|
|
13793
13690
|
await writeFile6(temporary, content, {
|
|
@@ -13813,17 +13710,17 @@ function isErrno(error, code) {
|
|
|
13813
13710
|
|
|
13814
13711
|
// src/codetracebench-trajectory.ts
|
|
13815
13712
|
import { readFile as readFile9 } from "fs/promises";
|
|
13816
|
-
import { join as
|
|
13713
|
+
import { join as join20 } from "path";
|
|
13817
13714
|
var TRAJECTORY_ID = /^[A-Za-z0-9][A-Za-z0-9._-]{0,254}$/;
|
|
13818
13715
|
var LABEL_KEY = /\\?["'](?:incorrect_stages|incorrect_step_ids|unuseful_step_ids|annotation_relpath|incorrect_error_stage_count)\\?["']\s*:/i;
|
|
13819
13716
|
var LABEL_ARRAY = /\\?["']labels\\?["']\s*:\s*\[[^\]]*\\?["'](?:incorrect|unuseful)\\?["']/i;
|
|
13820
13717
|
var ANNOTATION_PATH = /(?:agent_failure_analysis|step_annotations(?:_all)?|merged_cleaned_step\d*)[\\/]/i;
|
|
13821
13718
|
async function importTrajectory(input) {
|
|
13822
13719
|
const { index, row, trajectoryDirectory, stagingDirectory, signal } = input;
|
|
13823
|
-
const caseDirectory =
|
|
13720
|
+
const caseDirectory = join20(trajectoryDirectory, row.trajId);
|
|
13824
13721
|
const stepsPath = await containedFile(
|
|
13825
13722
|
trajectoryDirectory,
|
|
13826
|
-
|
|
13723
|
+
join20(caseDirectory, "steps.json"),
|
|
13827
13724
|
`${row.trajId}: steps.json`
|
|
13828
13725
|
);
|
|
13829
13726
|
signal.throwIfAborted();
|
|
@@ -13864,7 +13761,7 @@ async function importTrajectory(input) {
|
|
|
13864
13761
|
const serialized = serializeSpans(spans);
|
|
13865
13762
|
assertNoLabelLeakInText(serialized, row, `${row.trajId}: serialized OTLP`);
|
|
13866
13763
|
const outputFile = `${row.trajId}.otlp.jsonl`;
|
|
13867
|
-
await atomicWriteFile(
|
|
13764
|
+
await atomicWriteFile(join20(stagingDirectory, outputFile), serialized, signal);
|
|
13868
13765
|
return {
|
|
13869
13766
|
index,
|
|
13870
13767
|
traceId: row.trajId,
|
|
@@ -14031,7 +13928,7 @@ function fileRef(value, label2) {
|
|
|
14031
13928
|
};
|
|
14032
13929
|
}
|
|
14033
13930
|
async function readOptionalTask(trajectoryDirectory, caseDirectory, row, signal) {
|
|
14034
|
-
const candidate =
|
|
13931
|
+
const candidate = join20(caseDirectory, "task.md");
|
|
14035
13932
|
const path = await optionalContainedFile(trajectoryDirectory, candidate);
|
|
14036
13933
|
if (!path) {
|
|
14037
13934
|
return {
|
|
@@ -14120,7 +14017,7 @@ async function importCodeTraceBench(options) {
|
|
|
14120
14017
|
const rowsPath = resolve8(options.rowsPath);
|
|
14121
14018
|
const trajectoryPath = resolve8(options.trajectoryDir);
|
|
14122
14019
|
const outputDirectory = resolve8(options.outDir);
|
|
14123
|
-
const outputBase =
|
|
14020
|
+
const outputBase = basename10(outputDirectory);
|
|
14124
14021
|
if (!outputBase || outputDirectory === dirname10(outputDirectory)) {
|
|
14125
14022
|
throw new Error("CodeTraceBench output directory must not be a filesystem root");
|
|
14126
14023
|
}
|
|
@@ -14164,7 +14061,7 @@ async function runCodeTraceBenchImport(input) {
|
|
|
14164
14061
|
const rows = parseRows(rowsBytes.toString("utf8"), rowsPath);
|
|
14165
14062
|
const sourceRows = validateRows(rows, rowsPath);
|
|
14166
14063
|
const stagingDirectory = await mkdtemp4(
|
|
14167
|
-
|
|
14064
|
+
join21(dirname10(outputDirectory), `.${outputBase}.tmp-`)
|
|
14168
14065
|
);
|
|
14169
14066
|
const stop = new AbortController();
|
|
14170
14067
|
const signal = outerSignal ? AbortSignal.any([outerSignal, stop.signal]) : stop.signal;
|
|
@@ -14224,10 +14121,10 @@ async function runCodeTraceBenchImport(input) {
|
|
|
14224
14121
|
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
14225
14122
|
input: {
|
|
14226
14123
|
revision,
|
|
14227
|
-
rowsFile:
|
|
14124
|
+
rowsFile: basename10(rowsPath),
|
|
14228
14125
|
rowsSha256,
|
|
14229
14126
|
rowsBytes: rowsBytes.byteLength,
|
|
14230
|
-
trajectoryDirectory:
|
|
14127
|
+
trajectoryDirectory: basename10(trajectoryDirectory),
|
|
14231
14128
|
sha256: inputSha256
|
|
14232
14129
|
},
|
|
14233
14130
|
settings: {
|
|
@@ -14250,7 +14147,7 @@ async function runCodeTraceBenchImport(input) {
|
|
|
14250
14147
|
};
|
|
14251
14148
|
const receiptFile = "codetracebench-import.json";
|
|
14252
14149
|
await atomicWriteFile(
|
|
14253
|
-
|
|
14150
|
+
join21(stagingDirectory, receiptFile),
|
|
14254
14151
|
`${JSON.stringify(receipt, null, 2)}
|
|
14255
14152
|
`,
|
|
14256
14153
|
signal
|
|
@@ -14265,7 +14162,7 @@ async function runCodeTraceBenchImport(input) {
|
|
|
14265
14162
|
await rm2(stagingDirectory, { recursive: true, force: true });
|
|
14266
14163
|
return {
|
|
14267
14164
|
directory: outputDirectory,
|
|
14268
|
-
receiptPath:
|
|
14165
|
+
receiptPath: join21(outputDirectory, receiptFile),
|
|
14269
14166
|
receipt
|
|
14270
14167
|
};
|
|
14271
14168
|
} catch (error) {
|
|
@@ -14693,20 +14590,20 @@ async function cmdVerifyFindings(argv) {
|
|
|
14693
14590
|
|
|
14694
14591
|
// src/hodoscope.ts
|
|
14695
14592
|
import { createHash as createHash13 } from "crypto";
|
|
14696
|
-
import { mkdir as mkdir5, mkdtemp as mkdtemp5, readFile as readFile11, readdir as
|
|
14593
|
+
import { mkdir as mkdir5, mkdtemp as mkdtemp5, readFile as readFile11, readdir as readdir14, writeFile as writeFile7 } from "fs/promises";
|
|
14697
14594
|
import { endianness, tmpdir as tmpdir5 } from "os";
|
|
14698
|
-
import { join as
|
|
14595
|
+
import { join as join22, resolve as resolve9 } from "path";
|
|
14699
14596
|
var HODOSCOPE_VERSION = "0.2.4";
|
|
14700
14597
|
async function writeHodoscopeInput(otlpPath, options = {}) {
|
|
14701
14598
|
const explicitDirectory = options.directory ? resolve9(options.directory) : void 0;
|
|
14702
|
-
const directory = explicitDirectory ?? await mkdtemp5(
|
|
14599
|
+
const directory = explicitDirectory ?? await mkdtemp5(join22(tmpdir5(), "traces-hodoscope-input-"));
|
|
14703
14600
|
if (explicitDirectory) {
|
|
14704
14601
|
await mkdir5(directory, { recursive: true });
|
|
14705
|
-
if ((await
|
|
14602
|
+
if ((await readdir14(directory)).length > 0) {
|
|
14706
14603
|
throw new Error(`Hodoscope explicit directory must be empty: ${directory}`);
|
|
14707
14604
|
}
|
|
14708
14605
|
}
|
|
14709
|
-
const samples =
|
|
14606
|
+
const samples = join22(directory, "samples");
|
|
14710
14607
|
await mkdir5(samples);
|
|
14711
14608
|
const rows = [];
|
|
14712
14609
|
for await (const value of readJsonl(otlpPath)) rows.push(parseOpenInferenceRow(value));
|
|
@@ -14732,7 +14629,7 @@ async function writeHodoscopeInput(otlpPath, options = {}) {
|
|
|
14732
14629
|
}
|
|
14733
14630
|
actionCount += actions;
|
|
14734
14631
|
const file = `${createHash13("sha256").update(traceId).digest("hex").slice(0, 24)}.json`;
|
|
14735
|
-
await writeFile7(
|
|
14632
|
+
await writeFile7(join22(samples, file), `${JSON.stringify(trajectory, null, 2)}
|
|
14736
14633
|
`, "utf8");
|
|
14737
14634
|
}
|
|
14738
14635
|
return {
|
|
@@ -14756,10 +14653,10 @@ function hodoscopeAnalyzer(options = {}) {
|
|
|
14756
14653
|
async analyze(otlpPath, runOptions2 = {}) {
|
|
14757
14654
|
const outputRoot = options.outputDir ? resolve9(options.outputDir) : tmpdir5();
|
|
14758
14655
|
await mkdir5(outputRoot, { recursive: true });
|
|
14759
|
-
const directory = await mkdtemp5(
|
|
14760
|
-
const input =
|
|
14761
|
-
const analysisFile =
|
|
14762
|
-
const samplesFile =
|
|
14656
|
+
const directory = await mkdtemp5(join22(outputRoot, "traces-hodoscope-"));
|
|
14657
|
+
const input = join22(directory, "input");
|
|
14658
|
+
const analysisFile = join22(directory, "analysis.hodoscope.json");
|
|
14659
|
+
const samplesFile = join22(directory, "samples.json");
|
|
14763
14660
|
try {
|
|
14764
14661
|
const prepared = await writeHodoscopeInput(otlpPath, {
|
|
14765
14662
|
directory: input,
|
|
@@ -15382,7 +15279,7 @@ function assertPositiveInteger(name, value) {
|
|
|
15382
15279
|
import { createHash as createHash14 } from "crypto";
|
|
15383
15280
|
import { request as httpRequest } from "http";
|
|
15384
15281
|
import { request as httpsRequest } from "https";
|
|
15385
|
-
import { join as
|
|
15282
|
+
import { join as join23 } from "path";
|
|
15386
15283
|
var DEFAULT_BRIDGE_URL = "http://localhost:4181";
|
|
15387
15284
|
var DEFAULT_MODEL = "prime/zai/glm-5.2";
|
|
15388
15285
|
var DEFAULT_TIMEOUT_MS = 12e5;
|
|
@@ -15396,12 +15293,12 @@ var ANALYST_ID = "prime";
|
|
|
15396
15293
|
var TRAJECTORY_FILE_NAME = "trajectory.otlp.jsonl";
|
|
15397
15294
|
async function fileDelivery(otlpPath, perAttributeCharCap, signal) {
|
|
15398
15295
|
signal?.throwIfAborted();
|
|
15399
|
-
const { copyFile: copyFile2, mkdtemp: mkdtemp8, stat:
|
|
15296
|
+
const { copyFile: copyFile2, mkdtemp: mkdtemp8, stat: stat18 } = await import("fs/promises");
|
|
15400
15297
|
const { tmpdir: tmpdir8 } = await import("os");
|
|
15401
|
-
const { join:
|
|
15402
|
-
const cwd = await mkdtemp8(
|
|
15403
|
-
await copyFile2(otlpPath,
|
|
15404
|
-
const artifactBytes = (await
|
|
15298
|
+
const { join: join35 } = await import("path");
|
|
15299
|
+
const cwd = await mkdtemp8(join35(tmpdir8(), "traces-prime-"));
|
|
15300
|
+
await copyFile2(otlpPath, join35(cwd, TRAJECTORY_FILE_NAME));
|
|
15301
|
+
const artifactBytes = (await stat18(otlpPath)).size;
|
|
15405
15302
|
return { mode: "file-cwd", perAttributeCharCap, renderedChars: artifactBytes, cwd, fileName: TRAJECTORY_FILE_NAME };
|
|
15406
15303
|
}
|
|
15407
15304
|
function positiveIntegerEnv(name) {
|
|
@@ -15429,8 +15326,8 @@ function normalizeUsage(raw) {
|
|
|
15429
15326
|
}
|
|
15430
15327
|
function mergeUsage(a, b) {
|
|
15431
15328
|
const calls = a.calls !== null && b.calls !== null ? a.calls + b.calls : null;
|
|
15432
|
-
const
|
|
15433
|
-
return { calls, tokens:
|
|
15329
|
+
const tokens2 = a.tokens !== null && b.tokens !== null && a.tokens.input !== null && b.tokens.input !== null && a.tokens.output !== null && b.tokens.output !== null ? { input: a.tokens.input + b.tokens.input, output: a.tokens.output + b.tokens.output } : null;
|
|
15330
|
+
return { calls, tokens: tokens2, estimated: a.estimated || b.estimated };
|
|
15434
15331
|
}
|
|
15435
15332
|
function renderUsage(usage) {
|
|
15436
15333
|
const calls = usage.calls === null ? "uncaptured" : String(usage.calls);
|
|
@@ -15638,11 +15535,11 @@ var FINDINGS_FILE_MAX_BYTES = 256 * 1024;
|
|
|
15638
15535
|
var FINDINGS_FILE_NAME = "findings.json";
|
|
15639
15536
|
async function readFindingsFile2(cwd, signal) {
|
|
15640
15537
|
signal?.throwIfAborted();
|
|
15641
|
-
const path =
|
|
15538
|
+
const path = join23(cwd, FINDINGS_FILE_NAME);
|
|
15642
15539
|
let raw;
|
|
15643
|
-
const { readFile: readFile21, stat:
|
|
15540
|
+
const { readFile: readFile21, stat: stat18 } = await import("fs/promises");
|
|
15644
15541
|
try {
|
|
15645
|
-
const size = (await
|
|
15542
|
+
const size = (await stat18(path)).size;
|
|
15646
15543
|
if (size > FINDINGS_FILE_MAX_BYTES) {
|
|
15647
15544
|
return { parsed: null, receipt: `${FINDINGS_FILE_NAME} is ${size} bytes (cap ${FINDINGS_FILE_MAX_BYTES}); refused` };
|
|
15648
15545
|
}
|
|
@@ -16054,7 +15951,7 @@ async function applyRedactor(spans, redactor) {
|
|
|
16054
15951
|
import { createHash as createHash15 } from "crypto";
|
|
16055
15952
|
import { mkdtemp as mkdtemp6, readFile as readFile12, writeFile as writeFile8 } from "fs/promises";
|
|
16056
15953
|
import { tmpdir as tmpdir6 } from "os";
|
|
16057
|
-
import { join as
|
|
15954
|
+
import { join as join24 } from "path";
|
|
16058
15955
|
import {
|
|
16059
15956
|
firstNumberAttr as firstNumberAttr2,
|
|
16060
15957
|
LLM_CACHED_TOKEN_ATTR_KEYS,
|
|
@@ -16725,7 +16622,7 @@ async function exportTraceEvidenceFile(inputPath, opts = {}) {
|
|
|
16725
16622
|
}
|
|
16726
16623
|
async function writeTraceEvidenceExportFile(inputPath, outPath, opts = {}) {
|
|
16727
16624
|
const result = await exportTraceEvidenceFile(inputPath, opts);
|
|
16728
|
-
const path = outPath ??
|
|
16625
|
+
const path = outPath ?? join24(await mkdtemp6(join24(tmpdir6(), "traces-export-")), "spans.openinference.jsonl");
|
|
16729
16626
|
await writeFile8(path, serializeSpans(result.spans), "utf8");
|
|
16730
16627
|
return { ...result, path };
|
|
16731
16628
|
}
|
|
@@ -16733,7 +16630,7 @@ async function writeTraceEvidenceExportFile(inputPath, outPath, opts = {}) {
|
|
|
16733
16630
|
// src/inspect.ts
|
|
16734
16631
|
import { mkdtemp as mkdtemp7, readFile as readFile13, writeFile as writeFile9 } from "fs/promises";
|
|
16735
16632
|
import { tmpdir as tmpdir7 } from "os";
|
|
16736
|
-
import { basename as
|
|
16633
|
+
import { basename as basename11, join as join25 } from "path";
|
|
16737
16634
|
var severityRank2 = {
|
|
16738
16635
|
high: 0,
|
|
16739
16636
|
medium: 1,
|
|
@@ -16833,7 +16730,7 @@ function addSessionFindings(index, findings) {
|
|
|
16833
16730
|
refs: errorSessions.slice(0, 5).map((row) => row.session.path)
|
|
16834
16731
|
});
|
|
16835
16732
|
}
|
|
16836
|
-
const largeSessions = sessions.map((row) => ({ row, tokens: row.metrics.inputTokens + row.metrics.outputTokens })).filter(({ tokens:
|
|
16733
|
+
const largeSessions = sessions.map((row) => ({ row, tokens: row.metrics.inputTokens + row.metrics.outputTokens })).filter(({ tokens: tokens2 }) => tokens2 >= 5e5).sort((a, b) => b.tokens - a.tokens);
|
|
16837
16734
|
if (largeSessions.length > 0) {
|
|
16838
16735
|
const largest = largeSessions[0]?.tokens ?? 0;
|
|
16839
16736
|
findings.push({
|
|
@@ -16842,7 +16739,7 @@ function addSessionFindings(index, findings) {
|
|
|
16842
16739
|
area: "session",
|
|
16843
16740
|
title: `${largeSessions.length} session(s) reported at least 500k summed tokens`,
|
|
16844
16741
|
impact: largest,
|
|
16845
|
-
evidence: largeSessions.slice(0, 5).map(({ row, tokens:
|
|
16742
|
+
evidence: largeSessions.slice(0, 5).map(({ row, tokens: tokens2 }) => `${sessionLabel(row)}: ${tokens2.toLocaleString()} reported summed tokens (${row.metrics.inputTokens.toLocaleString()} in, ${row.metrics.outputTokens.toLocaleString()} out)`),
|
|
16846
16743
|
next: "Check whether these sessions need shorter handoffs, smaller files, split tasks, or clearer token accounting before optimizing anything else.",
|
|
16847
16744
|
refs: largeSessions.slice(0, 5).map(({ row }) => row.session.path)
|
|
16848
16745
|
});
|
|
@@ -16916,7 +16813,7 @@ function addContextFindings(index, findings) {
|
|
|
16916
16813
|
refs: invalidJsonlFiles.slice(0, 5).map((file) => file.path)
|
|
16917
16814
|
});
|
|
16918
16815
|
}
|
|
16919
|
-
const skillRunFiles = files.filter((file) =>
|
|
16816
|
+
const skillRunFiles = files.filter((file) => basename11(file.path) === "skill-runs.jsonl" && (file.jsonl?.rows ?? 0) > 0).map((file) => {
|
|
16920
16817
|
const rows = file.jsonl?.rows ?? 0;
|
|
16921
16818
|
const keys = file.jsonl?.keys ?? {};
|
|
16922
16819
|
const linkKeyCounts = {
|
|
@@ -17022,7 +16919,7 @@ async function readSessionIndexFile(path) {
|
|
|
17022
16919
|
return parsed;
|
|
17023
16920
|
}
|
|
17024
16921
|
async function writeInspectionReportFile(report, outPath) {
|
|
17025
|
-
const path = outPath ??
|
|
16922
|
+
const path = outPath ?? join25(await mkdtemp7(join25(tmpdir7(), "traces-inspect-")), "inspection-report.md");
|
|
17026
16923
|
await writeFile9(path, renderInspectionReport(report), "utf8");
|
|
17027
16924
|
return path;
|
|
17028
16925
|
}
|
|
@@ -17455,8 +17352,8 @@ async function streamSessions(opts) {
|
|
|
17455
17352
|
}
|
|
17456
17353
|
|
|
17457
17354
|
// src/supervisor-run-context.ts
|
|
17458
|
-
import { readFile as readFile14, stat as
|
|
17459
|
-
import { basename as
|
|
17355
|
+
import { readFile as readFile14, stat as stat14 } from "fs/promises";
|
|
17356
|
+
import { basename as basename12, join as join26 } from "path";
|
|
17460
17357
|
import { materializeTreeView } from "@tangle-network/agent-runtime/kernel";
|
|
17461
17358
|
import {
|
|
17462
17359
|
readRuntimeSupervisorRun
|
|
@@ -17625,14 +17522,14 @@ function parseInstant(v) {
|
|
|
17625
17522
|
}
|
|
17626
17523
|
async function readFileRunContext(runDir, opts = {}) {
|
|
17627
17524
|
const sources = await readRuntimeSupervisorRun(runDir);
|
|
17628
|
-
const coordination = readCoordinationLog(await readMaybe(
|
|
17525
|
+
const coordination = readCoordinationLog(await readMaybe(join26(runDir, COORDINATION_LOG_FILE)));
|
|
17629
17526
|
return {
|
|
17630
17527
|
...sources,
|
|
17631
17528
|
instanceId: opts.instanceId !== void 0 ? opts.instanceId : sources.instanceId,
|
|
17632
|
-
arm: opts.arm !== void 0 ? opts.arm :
|
|
17529
|
+
arm: opts.arm !== void 0 ? opts.arm : basename12(runDir),
|
|
17633
17530
|
workers: sources.workers !== null && coordination.present ? workerSources(sources.workers, coordination) : sources.workers,
|
|
17634
17531
|
...sources.journal !== null ? {
|
|
17635
|
-
rootTranscriptRef:
|
|
17532
|
+
rootTranscriptRef: join26(runDir, SPAWN_JOURNAL_FILE),
|
|
17636
17533
|
traceCommand: `traces watch ${runDir}`
|
|
17637
17534
|
} : {}
|
|
17638
17535
|
};
|
|
@@ -17641,7 +17538,7 @@ function fileRunContextSupervisorRunReader(runDir, opts = {}) {
|
|
|
17641
17538
|
return { runRef: runDir, read: () => readFileRunContext(runDir, opts) };
|
|
17642
17539
|
}
|
|
17643
17540
|
async function isFileRunContextDir(runDir) {
|
|
17644
|
-
return
|
|
17541
|
+
return stat14(join26(runDir, SPAWN_JOURNAL_FILE)).then((s) => s.isFile()).catch(() => false);
|
|
17645
17542
|
}
|
|
17646
17543
|
function parseJsonObject(text2) {
|
|
17647
17544
|
if (text2 === null) return null;
|
|
@@ -17707,9 +17604,9 @@ function mergeRolls(a, b) {
|
|
|
17707
17604
|
};
|
|
17708
17605
|
}
|
|
17709
17606
|
async function readRunContextSnapshot(runDir) {
|
|
17710
|
-
const journal = readRunContextJournal(await readMaybe(
|
|
17711
|
-
const coordination = readCoordinationLog(await readMaybe(
|
|
17712
|
-
const resultText = await readMaybe(
|
|
17607
|
+
const journal = readRunContextJournal(await readMaybe(join26(runDir, SPAWN_JOURNAL_FILE)));
|
|
17608
|
+
const coordination = readCoordinationLog(await readMaybe(join26(runDir, COORDINATION_LOG_FILE)));
|
|
17609
|
+
const resultText = await readMaybe(join26(runDir, RESULT_FILE));
|
|
17713
17610
|
const result = parseResult(resultText);
|
|
17714
17611
|
const view = safeTreeView(journal.events);
|
|
17715
17612
|
const nodes = view === null ? [] : orderNodes(view, journal);
|
|
@@ -17843,7 +17740,7 @@ function usd(roll) {
|
|
|
17843
17740
|
function zeroPricedCost(roll) {
|
|
17844
17741
|
return roll.usdKnownRecords > 0 && roll.usd === 0 && roll.tokensIn + roll.tokensOut > 0;
|
|
17845
17742
|
}
|
|
17846
|
-
function
|
|
17743
|
+
function tokens(roll) {
|
|
17847
17744
|
return `in ${int(roll.tokensIn)} \xB7 out ${int(roll.tokensOut)}`;
|
|
17848
17745
|
}
|
|
17849
17746
|
var STATUS_MARK = {
|
|
@@ -17889,8 +17786,8 @@ function wrap(text2, indent) {
|
|
|
17889
17786
|
}
|
|
17890
17787
|
|
|
17891
17788
|
// src/run-span-tree.ts
|
|
17892
|
-
import { readdir as
|
|
17893
|
-
import { join as
|
|
17789
|
+
import { readdir as readdir15 } from "fs/promises";
|
|
17790
|
+
import { join as join27 } from "path";
|
|
17894
17791
|
import {
|
|
17895
17792
|
firstNumberAttr as firstNumberAttr3,
|
|
17896
17793
|
LLM_COST_ATTR_KEYS as LLM_COST_ATTR_KEYS2,
|
|
@@ -18105,8 +18002,8 @@ function renderSpanRunSnapshot(snapshot) {
|
|
|
18105
18002
|
` ${snapshot.nodes.length} node(s) \xB7 depth ${snapshot.maxDepth} \xB7 ${int(snapshot.spanCount)} span(s) \xB7 ${snapshot.traceIds.length} trace(s) \xB7 elapsed ${ms(snapshot.endMs === null || snapshot.startMs === null ? null : snapshot.endMs - snapshot.startMs)}`
|
|
18106
18003
|
);
|
|
18107
18004
|
const delegating = snapshot.nodes.some((node) => node.role === "driver");
|
|
18108
|
-
lines.push(` driver inference ${
|
|
18109
|
-
lines.push(` leaf inference ${
|
|
18005
|
+
lines.push(` driver inference ${tokens(totals.driver)} \xB7 ${usd(totals.driver)}`);
|
|
18006
|
+
lines.push(` leaf inference ${tokens(totals.leaves)} \xB7 ${usd(totals.leaves)}`);
|
|
18110
18007
|
if (!delegating) {
|
|
18111
18008
|
lines.push(" (no delegation in these spans: every turn belongs to one agent, so the driver half is empty)");
|
|
18112
18009
|
}
|
|
@@ -18129,11 +18026,11 @@ function renderSpanRunSnapshot(snapshot) {
|
|
|
18129
18026
|
].join(" ")
|
|
18130
18027
|
);
|
|
18131
18028
|
lines.push(
|
|
18132
|
-
`${detail}driver ${node.driver.records} turn(s) \xB7 ${
|
|
18029
|
+
`${detail}driver ${node.driver.records} turn(s) \xB7 ${tokens(node.driver)} \xB7 ${usd(node.driver)} \xB7 ${node.toolCalls} tool call(s)`
|
|
18133
18030
|
);
|
|
18134
18031
|
if (node.role === "driver") {
|
|
18135
18032
|
lines.push(
|
|
18136
|
-
`${detail}children ${node.children.records} turn(s) \xB7 ${
|
|
18033
|
+
`${detail}children ${node.children.records} turn(s) \xB7 ${tokens(node.children)} \xB7 ${usd(node.children)}`
|
|
18137
18034
|
);
|
|
18138
18035
|
}
|
|
18139
18036
|
for (const error of node.errors.slice(0, 3)) lines.push(`${detail}error ${error}`);
|
|
@@ -18163,25 +18060,25 @@ function renderSpanRunSnapshot(snapshot) {
|
|
|
18163
18060
|
var SPAN_FILE_PATTERN = /\.(?:otlp|spans|traces|openinference)\.(?:jsonl|ndjson)$|^traces?\.jsonl$|^spans\.jsonl$/i;
|
|
18164
18061
|
async function findSpanSourceFiles(dir) {
|
|
18165
18062
|
const found = [];
|
|
18166
|
-
const entries = await
|
|
18063
|
+
const entries = await readdir15(dir, { withFileTypes: true }).catch(() => []);
|
|
18167
18064
|
for (const entry of entries) {
|
|
18168
|
-
const child =
|
|
18065
|
+
const child = join27(dir, entry.name);
|
|
18169
18066
|
if (entry.isFile()) {
|
|
18170
18067
|
if (SPAN_FILE_PATTERN.test(entry.name)) found.push(child);
|
|
18171
18068
|
continue;
|
|
18172
18069
|
}
|
|
18173
18070
|
if (!entry.isDirectory()) continue;
|
|
18174
|
-
const nested = await
|
|
18071
|
+
const nested = await readdir15(child, { withFileTypes: true }).catch(() => []);
|
|
18175
18072
|
for (const inner of nested) {
|
|
18176
|
-
if (inner.isFile() && SPAN_FILE_PATTERN.test(inner.name)) found.push(
|
|
18073
|
+
if (inner.isFile() && SPAN_FILE_PATTERN.test(inner.name)) found.push(join27(child, inner.name));
|
|
18177
18074
|
}
|
|
18178
18075
|
}
|
|
18179
18076
|
return found.sort();
|
|
18180
18077
|
}
|
|
18181
18078
|
|
|
18182
18079
|
// src/supervisor-run-watch.ts
|
|
18183
|
-
import { readdir as
|
|
18184
|
-
import { join as
|
|
18080
|
+
import { readdir as readdir16 } from "fs/promises";
|
|
18081
|
+
import { join as join28 } from "path";
|
|
18185
18082
|
function budget(node) {
|
|
18186
18083
|
const parts = [`${int(node.budget.maxIterations)}it`, `${int(node.budget.maxTokens)}tok`];
|
|
18187
18084
|
if (node.budget.maxUsd !== void 0) parts.push(`$${node.budget.maxUsd.toFixed(2)}`);
|
|
@@ -18213,17 +18110,17 @@ function renderNode(node, lastAtDepth, lines) {
|
|
|
18213
18110
|
lines.push(head.join(" "));
|
|
18214
18111
|
if (node.driver.records > 0 || node.role === "supervisor") {
|
|
18215
18112
|
lines.push(
|
|
18216
|
-
`${detail}driver ${node.driver.records} turn(s) \xB7 ${
|
|
18113
|
+
`${detail}driver ${node.driver.records} turn(s) \xB7 ${tokens(node.driver)} \xB7 ${usd(node.driver)}` + budgetUse(node, node.driver)
|
|
18217
18114
|
);
|
|
18218
18115
|
}
|
|
18219
18116
|
if (node.children.records > 0 || node.role === "supervisor") {
|
|
18220
18117
|
lines.push(
|
|
18221
|
-
`${detail}children ${node.children.records} settled \xB7 ${
|
|
18118
|
+
`${detail}children ${node.children.records} settled \xB7 ${tokens(node.children)} \xB7 ${usd(node.children)}`
|
|
18222
18119
|
);
|
|
18223
18120
|
}
|
|
18224
18121
|
if (node.settled.records > 0) {
|
|
18225
18122
|
lines.push(
|
|
18226
|
-
`${detail}settled ${node.settled.iterations}it \xB7 ${
|
|
18123
|
+
`${detail}settled ${node.settled.iterations}it \xB7 ${tokens(node.settled)} \xB7 ${usd(node.settled)}` + budgetUse(node, node.settled)
|
|
18227
18124
|
);
|
|
18228
18125
|
}
|
|
18229
18126
|
if (node.cancelReason !== null) lines.push(`${detail}cancelled: ${node.cancelReason}`);
|
|
@@ -18247,8 +18144,8 @@ function renderRunContextSnapshot(snapshot) {
|
|
|
18247
18144
|
lines.push(
|
|
18248
18145
|
` ${snapshot.nodes.length} node(s) \xB7 depth ${snapshot.maxDepth} \xB7 elapsed ${ms(elapsed(snapshot))}${snapshot.terminal ? "" : " \xB7 live"}`
|
|
18249
18146
|
);
|
|
18250
|
-
lines.push(` driver total ${
|
|
18251
|
-
lines.push(` worker total ${
|
|
18147
|
+
lines.push(` driver total ${tokens(totals.driver)} \xB7 ${usd(totals.driver)}`);
|
|
18148
|
+
lines.push(` worker total ${tokens(totals.workers)} \xB7 ${usd(totals.workers)}`);
|
|
18252
18149
|
lines.push("");
|
|
18253
18150
|
if (snapshot.nodes.length === 0) lines.push(" (no node spawned yet)");
|
|
18254
18151
|
forEachTreeNode(
|
|
@@ -18323,12 +18220,12 @@ function elapsed(snapshot) {
|
|
|
18323
18220
|
}
|
|
18324
18221
|
async function resolveRunContextDir(dir) {
|
|
18325
18222
|
if (await isFileRunContextDir(dir)) return dir;
|
|
18326
|
-
const entries = await
|
|
18223
|
+
const entries = await readdir16(dir, { withFileTypes: true }).catch(() => null);
|
|
18327
18224
|
if (entries === null) throw new Error(`cannot read ${dir}`);
|
|
18328
18225
|
const candidates = [];
|
|
18329
18226
|
for (const entry of entries) {
|
|
18330
18227
|
if (!entry.isDirectory()) continue;
|
|
18331
|
-
const child =
|
|
18228
|
+
const child = join28(dir, entry.name);
|
|
18332
18229
|
if (await isFileRunContextDir(child)) candidates.push(child);
|
|
18333
18230
|
}
|
|
18334
18231
|
if (candidates.length === 1) return candidates[0];
|
|
@@ -18344,9 +18241,9 @@ async function resolveRunContextDir(dir) {
|
|
|
18344
18241
|
}
|
|
18345
18242
|
|
|
18346
18243
|
// src/run-watch.ts
|
|
18347
|
-
import { stat as
|
|
18244
|
+
import { stat as stat15 } from "fs/promises";
|
|
18348
18245
|
async function resolveRunWatchTarget(target) {
|
|
18349
|
-
const info = await
|
|
18246
|
+
const info = await stat15(target).catch(() => null);
|
|
18350
18247
|
if (info === null) throw new Error(`cannot read ${target}`);
|
|
18351
18248
|
if (info.isFile()) return { runDir: null, spanFiles: [target], requested: target };
|
|
18352
18249
|
const spanFiles = await findSpanSourceFiles(target);
|
|
@@ -18670,7 +18567,7 @@ function parseJsonAnswer(text2) {
|
|
|
18670
18567
|
|
|
18671
18568
|
// src/ask.ts
|
|
18672
18569
|
import { mkdir as mkdir6, readFile as readFile15, writeFile as writeFile10 } from "fs/promises";
|
|
18673
|
-
import { join as
|
|
18570
|
+
import { join as join29, resolve as resolve10 } from "path";
|
|
18674
18571
|
import { performance } from "perf_hooks";
|
|
18675
18572
|
import { CostCeilingReachedError, CostLedger } from "@tangle-network/agent-eval";
|
|
18676
18573
|
import {
|
|
@@ -19226,8 +19123,8 @@ async function writeTraceQuestionsArtifacts(result, outDir) {
|
|
|
19226
19123
|
await mkdir6(directory, { recursive: true });
|
|
19227
19124
|
const paths = {
|
|
19228
19125
|
directory,
|
|
19229
|
-
result:
|
|
19230
|
-
report:
|
|
19126
|
+
result: join29(directory, "answers.json"),
|
|
19127
|
+
report: join29(directory, "report.md"),
|
|
19231
19128
|
traces: result.otlpPath
|
|
19232
19129
|
};
|
|
19233
19130
|
const { report, ...machine } = result;
|
|
@@ -19290,8 +19187,8 @@ async function watchSessions(opts) {
|
|
|
19290
19187
|
|
|
19291
19188
|
// src/bundle-view.ts
|
|
19292
19189
|
import { createHash as createHash17 } from "crypto";
|
|
19293
|
-
import { mkdir as mkdir7, readdir as
|
|
19294
|
-
import { dirname as dirname11, join as
|
|
19190
|
+
import { mkdir as mkdir7, readdir as readdir17, readFile as readFile16, writeFile as writeFile11 } from "fs/promises";
|
|
19191
|
+
import { dirname as dirname11, join as join30, resolve as resolve11 } from "path";
|
|
19295
19192
|
var EVIDENCE_ONLY_ALLOW_LIST = [
|
|
19296
19193
|
{
|
|
19297
19194
|
path: "derived/session-index.json",
|
|
@@ -19415,7 +19312,7 @@ async function findSessionTextLeaks(opts) {
|
|
|
19415
19312
|
const index = /* @__PURE__ */ new Map();
|
|
19416
19313
|
const carried = [];
|
|
19417
19314
|
for (const path of opts.carriedPaths) {
|
|
19418
|
-
const signatures = sessionTextSignatures(await readFile16(
|
|
19315
|
+
const signatures = sessionTextSignatures(await readFile16(join30(opts.viewDir, path), "utf8"));
|
|
19419
19316
|
carried.push({ path, signatures: signatures.size });
|
|
19420
19317
|
for (const signature of signatures) if (!index.has(signature)) index.set(signature, path);
|
|
19421
19318
|
}
|
|
@@ -19423,7 +19320,7 @@ async function findSessionTextLeaks(opts) {
|
|
|
19423
19320
|
const comparedSources = [];
|
|
19424
19321
|
let sourceSignatures = 0;
|
|
19425
19322
|
for (const sourcePath of opts.excludedPaths) {
|
|
19426
|
-
const signatures = sessionTextSignatures(await readFile16(
|
|
19323
|
+
const signatures = sessionTextSignatures(await readFile16(join30(opts.sourceDir, sourcePath), "utf8"));
|
|
19427
19324
|
comparedSources.push(sourcePath);
|
|
19428
19325
|
sourceSignatures += signatures.size;
|
|
19429
19326
|
for (const signature of signatures) {
|
|
@@ -19470,7 +19367,7 @@ async function projectSessionBundle(opts) {
|
|
|
19470
19367
|
}
|
|
19471
19368
|
const outDir = resolve11(opts.outDir);
|
|
19472
19369
|
await mkdir7(outDir, { recursive: true });
|
|
19473
|
-
if ((await
|
|
19370
|
+
if ((await readdir17(outDir)).length > 0) {
|
|
19474
19371
|
throw new Error(
|
|
19475
19372
|
`view output directory ${outDir} is not empty \u2014 pass a new directory so one directory holds exactly one view`
|
|
19476
19373
|
);
|
|
@@ -19482,17 +19379,17 @@ async function projectSessionBundle(opts) {
|
|
|
19482
19379
|
const candidates = [];
|
|
19483
19380
|
for (const path of await listSessionBundleFiles(sourceDir)) {
|
|
19484
19381
|
if (path === "manifest.json") continue;
|
|
19485
|
-
const bytes2 = await readFile16(
|
|
19382
|
+
const bytes2 = await readFile16(join30(sourceDir, path));
|
|
19486
19383
|
const sha2562 = createHash17("sha256").update(bytes2).digest("hex");
|
|
19487
19384
|
const recorded = sourceHashes.get(path);
|
|
19488
19385
|
if (!recorded) {
|
|
19489
19386
|
throw new Error(
|
|
19490
|
-
`${
|
|
19387
|
+
`${join30(sourceDir, path)} is not listed in the bundle manifest \u2014 the bundle changed after assembly and cannot be projected; re-run \`traces bundle\``
|
|
19491
19388
|
);
|
|
19492
19389
|
}
|
|
19493
19390
|
if (recorded.sha256 !== sha2562) {
|
|
19494
19391
|
throw new Error(
|
|
19495
|
-
`${
|
|
19392
|
+
`${join30(sourceDir, path)} does not match its manifest hash (${recorded.sha256} recorded, ${sha2562} on disk) \u2014 the bundle changed after assembly and cannot be projected; re-run \`traces bundle\``
|
|
19496
19393
|
);
|
|
19497
19394
|
}
|
|
19498
19395
|
const verdict = classifyEvidenceOnlyPath(path);
|
|
@@ -19528,7 +19425,7 @@ async function projectSessionBundle(opts) {
|
|
|
19528
19425
|
});
|
|
19529
19426
|
continue;
|
|
19530
19427
|
}
|
|
19531
|
-
const target =
|
|
19428
|
+
const target = join30(outDir, candidate.path);
|
|
19532
19429
|
await mkdir7(dirname11(target), { recursive: true });
|
|
19533
19430
|
await writeFile11(target, candidate.bytes);
|
|
19534
19431
|
carriedPaths.push(candidate.path);
|
|
@@ -19545,7 +19442,7 @@ async function projectSessionBundle(opts) {
|
|
|
19545
19442
|
})),
|
|
19546
19443
|
matches: 0
|
|
19547
19444
|
};
|
|
19548
|
-
const sourceManifestBytes = await readFile16(
|
|
19445
|
+
const sourceManifestBytes = await readFile16(join30(sourceDir, "manifest.json"));
|
|
19549
19446
|
const manifest = {
|
|
19550
19447
|
schemaVersion: 2,
|
|
19551
19448
|
kind: "traces.session_bundle",
|
|
@@ -19568,14 +19465,14 @@ async function projectSessionBundle(opts) {
|
|
|
19568
19465
|
}
|
|
19569
19466
|
|
|
19570
19467
|
// src/diff.ts
|
|
19571
|
-
import { stat as
|
|
19468
|
+
import { stat as stat16 } from "fs/promises";
|
|
19572
19469
|
import { ATTR as ATTR5 } from "@tangle-network/agent-trace-contract";
|
|
19573
19470
|
import { ingestSpans as ingestSpans2 } from "@tangle-network/agent-eval/diagnosis";
|
|
19574
19471
|
import { diffSteps, diffStepsFromSpans } from "@tangle-network/agent-eval/pipelines";
|
|
19575
19472
|
async function readSpans(path) {
|
|
19576
19473
|
const otlp = await readOtlpInput(path);
|
|
19577
19474
|
if (otlp.spans.length > 0) return [...otlp.spans];
|
|
19578
|
-
if (!(await
|
|
19475
|
+
if (!(await stat16(path)).isFile()) {
|
|
19579
19476
|
throw new Error(`${path}: no OTLP spans found (${otlp.issues.length} unusable row(s))`);
|
|
19580
19477
|
}
|
|
19581
19478
|
return (await exportTraceEvidenceFile(path)).spans;
|
|
@@ -19732,12 +19629,12 @@ function renderRunDiff(report) {
|
|
|
19732
19629
|
|
|
19733
19630
|
// src/upload-state.ts
|
|
19734
19631
|
import { mkdir as mkdir8, readFile as readFile17, writeFile as writeFile12 } from "fs/promises";
|
|
19735
|
-
import { homedir as
|
|
19736
|
-
import { dirname as dirname12, join as
|
|
19632
|
+
import { homedir as homedir10 } from "os";
|
|
19633
|
+
import { dirname as dirname12, join as join31 } from "path";
|
|
19737
19634
|
import { contentHash } from "@tangle-network/agent-eval";
|
|
19738
19635
|
function stateFile() {
|
|
19739
|
-
const base = process.env.XDG_STATE_HOME ??
|
|
19740
|
-
return
|
|
19636
|
+
const base = process.env.XDG_STATE_HOME ?? join31(homedir10(), ".local", "state");
|
|
19637
|
+
return join31(base, "tangle-traces", "uploaded.json");
|
|
19741
19638
|
}
|
|
19742
19639
|
function uploadKey(harness, sessionId) {
|
|
19743
19640
|
return `${harness}:${sessionId}`;
|
|
@@ -19769,7 +19666,7 @@ function alreadyUploaded(state, harness, sessionId, hash2) {
|
|
|
19769
19666
|
import { readFile as readFile18 } from "fs/promises";
|
|
19770
19667
|
import { createRequire as createRequire2 } from "module";
|
|
19771
19668
|
import { hostname as hostname2 } from "os";
|
|
19772
|
-
import { basename as
|
|
19669
|
+
import { basename as basename13, join as join32 } from "path";
|
|
19773
19670
|
import { hostedClientFromEnv } from "@tangle-network/agent-eval/hosted";
|
|
19774
19671
|
import { assessShareSafety as assessShareSafety2, REDACTION_VERSION, redact as redact2, shareAllowed } from "@tangle-network/agent-eval/traces";
|
|
19775
19672
|
var require2 = createRequire2(import.meta.url);
|
|
@@ -19793,7 +19690,7 @@ async function planUpload(opts = {}) {
|
|
|
19793
19690
|
async function gitBranch(cwd) {
|
|
19794
19691
|
if (!cwd) return void 0;
|
|
19795
19692
|
try {
|
|
19796
|
-
const head = await readFile18(
|
|
19693
|
+
const head = await readFile18(join32(cwd, ".git", "HEAD"), "utf8");
|
|
19797
19694
|
const m = head.match(/^ref:\s*refs\/heads\/(.+)$/m);
|
|
19798
19695
|
return m?.[1]?.trim();
|
|
19799
19696
|
} catch {
|
|
@@ -19803,7 +19700,7 @@ async function gitBranch(cwd) {
|
|
|
19803
19700
|
async function sessionMeta(item) {
|
|
19804
19701
|
const meta = {
|
|
19805
19702
|
[ATTR.HARNESS]: item.ref.harness,
|
|
19806
|
-
[ATTR.SESSION_FILE]:
|
|
19703
|
+
[ATTR.SESSION_FILE]: basename13(item.ref.path),
|
|
19807
19704
|
[ATTR.HOST]: hostname2(),
|
|
19808
19705
|
[ATTR.UPLOADER]: `tangle-traces@${TRACES_VERSION}`,
|
|
19809
19706
|
[ATTR.REDACTION_VERSION]: REDACTION_VERSION,
|
|
@@ -19968,8 +19865,8 @@ async function executeUpload(plan, opts = {}) {
|
|
|
19968
19865
|
}
|
|
19969
19866
|
|
|
19970
19867
|
// src/verify-safe.ts
|
|
19971
|
-
import { lstat as lstat4, readdir as
|
|
19972
|
-
import { basename as
|
|
19868
|
+
import { lstat as lstat4, readdir as readdir18, readFile as readFile19 } from "fs/promises";
|
|
19869
|
+
import { basename as basename14, extname, join as join33, relative as relative7 } from "path";
|
|
19973
19870
|
import {
|
|
19974
19871
|
assessShareSafety as assessShareSafety3,
|
|
19975
19872
|
combineVerdicts as combineVerdicts2
|
|
@@ -19982,7 +19879,7 @@ async function verifySafe(target, options = {}) {
|
|
|
19982
19879
|
const unreadable = [];
|
|
19983
19880
|
const files = await listFiles(target, unreadable);
|
|
19984
19881
|
for (const file of files) {
|
|
19985
|
-
const label2 = relative7(target, file) ||
|
|
19882
|
+
const label2 = relative7(target, file) || basename14(file);
|
|
19986
19883
|
let bytes2;
|
|
19987
19884
|
try {
|
|
19988
19885
|
bytes2 = await readFile19(file);
|
|
@@ -20015,22 +19912,22 @@ async function verifySafe(target, options = {}) {
|
|
|
20015
19912
|
return { ...combineVerdicts2(profile, verdicts, unreadable), target, files: files.length };
|
|
20016
19913
|
}
|
|
20017
19914
|
async function listFiles(target, unreadable) {
|
|
20018
|
-
let
|
|
19915
|
+
let stat18;
|
|
20019
19916
|
try {
|
|
20020
|
-
|
|
19917
|
+
stat18 = await lstat4(target);
|
|
20021
19918
|
} catch (error) {
|
|
20022
19919
|
unreadable.push(`${target}: ${error instanceof Error ? error.message : String(error)}`);
|
|
20023
19920
|
return [];
|
|
20024
19921
|
}
|
|
20025
|
-
if (
|
|
20026
|
-
if (!
|
|
19922
|
+
if (stat18.isFile()) return [target];
|
|
19923
|
+
if (!stat18.isDirectory()) {
|
|
20027
19924
|
unreadable.push(`${target}: not a regular file or directory`);
|
|
20028
19925
|
return [];
|
|
20029
19926
|
}
|
|
20030
19927
|
const out = [];
|
|
20031
19928
|
const walk = async (dir) => {
|
|
20032
|
-
for (const entry of (await
|
|
20033
|
-
const path =
|
|
19929
|
+
for (const entry of (await readdir18(dir, { withFileTypes: true })).sort((a, b) => a.name.localeCompare(b.name))) {
|
|
19930
|
+
const path = join33(dir, entry.name);
|
|
20034
19931
|
if (entry.isDirectory()) await walk(path);
|
|
20035
19932
|
else if (entry.isFile()) out.push(path);
|
|
20036
19933
|
else unreadable.push(`${relative7(target, path)}: not a regular file`);
|
|
@@ -20082,9 +19979,9 @@ function formatVerdict(result) {
|
|
|
20082
19979
|
}
|
|
20083
19980
|
|
|
20084
19981
|
// src/skill-usage.ts
|
|
20085
|
-
import { mkdir as mkdir9, open as open3, readdir as
|
|
20086
|
-
import { homedir as
|
|
20087
|
-
import { dirname as dirname13, join as
|
|
19982
|
+
import { mkdir as mkdir9, open as open3, readdir as readdir19, readFile as readFile20, rename as rename3, stat as stat17, writeFile as writeFile13 } from "fs/promises";
|
|
19983
|
+
import { homedir as homedir11 } from "os";
|
|
19984
|
+
import { dirname as dirname13, join as join34 } from "path";
|
|
20088
19985
|
import { STORES } from "@tangle-network/harness-sessions/catalog";
|
|
20089
19986
|
var CHUNK_BYTES = 8 * 1024 * 1024;
|
|
20090
19987
|
var NEWLINE = 10;
|
|
@@ -20107,16 +20004,16 @@ var SKILL_READ_VERB = /(?:^|[\s;&|(`'"])(?:cat|sed|head|tail|less|more|awk|nl|ba
|
|
|
20107
20004
|
var SKILL_DOCUMENT = /(?:^|[\s'"=:(`])((?:[^\s'"`;|&()]*\/)?([A-Za-z0-9][A-Za-z0-9._-]*))\/SKILL\.md\b/g;
|
|
20108
20005
|
var SESSION_UUID = /([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\.jsonl$/;
|
|
20109
20006
|
function defaultSkillUsageSources() {
|
|
20110
|
-
const codexHome = process.env.CODEX_HOME ??
|
|
20007
|
+
const codexHome = process.env.CODEX_HOME ?? join34(homedir11(), ".codex");
|
|
20111
20008
|
return {
|
|
20112
|
-
claudeProjects:
|
|
20113
|
-
codexSessions: [
|
|
20114
|
-
kimiSessions:
|
|
20009
|
+
claudeProjects: join34(homedir11(), STORES["claude-code.projects-jsonl"].root),
|
|
20010
|
+
codexSessions: [join34(codexHome, ...STORES["codex.rollout-jsonl"].root.split("/").slice(1)), join34(codexHome, "archived_sessions")],
|
|
20011
|
+
kimiSessions: join34(homedir11(), STORES["kimi.session-dir"].root)
|
|
20115
20012
|
};
|
|
20116
20013
|
}
|
|
20117
20014
|
function defaultSkillUsageStorePath() {
|
|
20118
|
-
const state = process.env.XDG_STATE_HOME ??
|
|
20119
|
-
return
|
|
20015
|
+
const state = process.env.XDG_STATE_HOME ?? join34(homedir11(), ".local", "state");
|
|
20016
|
+
return join34(state, "traces", "skill-usage.json");
|
|
20120
20017
|
}
|
|
20121
20018
|
function eventKey(e) {
|
|
20122
20019
|
return `${e.harness}\0${e.id}`;
|
|
@@ -20200,7 +20097,7 @@ var SkillUsageStore = class _SkillUsageStore {
|
|
|
20200
20097
|
async refreshFile(harness, path) {
|
|
20201
20098
|
let info;
|
|
20202
20099
|
try {
|
|
20203
|
-
info = await
|
|
20100
|
+
info = await stat17(path);
|
|
20204
20101
|
} catch (error) {
|
|
20205
20102
|
if (error.code === "ENOENT") return null;
|
|
20206
20103
|
throw error;
|
|
@@ -20467,37 +20364,37 @@ async function jsonlFiles(roots, name) {
|
|
|
20467
20364
|
for (const root of roots) {
|
|
20468
20365
|
let entries;
|
|
20469
20366
|
try {
|
|
20470
|
-
entries = await
|
|
20367
|
+
entries = await readdir19(root, { recursive: true, withFileTypes: true });
|
|
20471
20368
|
} catch (error) {
|
|
20472
20369
|
if (error.code === "ENOENT") continue;
|
|
20473
20370
|
throw error;
|
|
20474
20371
|
}
|
|
20475
20372
|
for (const entry of entries) {
|
|
20476
|
-
if (entry.isFile() && (name ? entry.name === name : entry.name.endsWith(".jsonl"))) files.push(
|
|
20373
|
+
if (entry.isFile() && (name ? entry.name === name : entry.name.endsWith(".jsonl"))) files.push(join34(entry.parentPath, entry.name));
|
|
20477
20374
|
}
|
|
20478
20375
|
}
|
|
20479
20376
|
return files.sort();
|
|
20480
20377
|
}
|
|
20481
20378
|
function defaultSkillCatalogRoots() {
|
|
20482
|
-
const codexHome = process.env.CODEX_HOME ??
|
|
20379
|
+
const codexHome = process.env.CODEX_HOME ?? join34(homedir11(), ".codex");
|
|
20483
20380
|
return {
|
|
20484
|
-
claudeHome:
|
|
20485
|
-
codexSkillDirs: [
|
|
20381
|
+
claudeHome: join34(homedir11(), ".claude"),
|
|
20382
|
+
codexSkillDirs: [join34(codexHome, "skills"), join34(codexHome, "skills", ".system"), join34(homedir11(), ".agents", "skills")]
|
|
20486
20383
|
};
|
|
20487
20384
|
}
|
|
20488
20385
|
async function skillFolders(directory, prefix = "") {
|
|
20489
20386
|
let entries;
|
|
20490
20387
|
try {
|
|
20491
|
-
entries = await
|
|
20388
|
+
entries = await readdir19(directory);
|
|
20492
20389
|
} catch {
|
|
20493
20390
|
return [];
|
|
20494
20391
|
}
|
|
20495
20392
|
const found = [];
|
|
20496
20393
|
for (const entry of entries.sort()) {
|
|
20497
20394
|
if (entry.startsWith(".")) continue;
|
|
20498
|
-
const path =
|
|
20395
|
+
const path = join34(directory, entry);
|
|
20499
20396
|
try {
|
|
20500
|
-
await
|
|
20397
|
+
await stat17(join34(path, "SKILL.md"));
|
|
20501
20398
|
found.push({ name: `${prefix}${entry}`, path });
|
|
20502
20399
|
} catch {
|
|
20503
20400
|
}
|
|
@@ -20514,19 +20411,19 @@ async function readJsonObject(path) {
|
|
|
20514
20411
|
}
|
|
20515
20412
|
async function readInstalledSkills(roots = defaultSkillCatalogRoots()) {
|
|
20516
20413
|
const installed = [];
|
|
20517
|
-
for (const skill of await skillFolders(
|
|
20414
|
+
for (const skill of await skillFolders(join34(roots.claudeHome, "skills"))) {
|
|
20518
20415
|
installed.push({ ...skill, harness: "claude-code" });
|
|
20519
20416
|
}
|
|
20520
|
-
const settings = await readJsonObject(
|
|
20417
|
+
const settings = await readJsonObject(join34(roots.claudeHome, "settings.json"));
|
|
20521
20418
|
const enabled = settings?.enabledPlugins ?? {};
|
|
20522
|
-
const plugins = await readJsonObject(
|
|
20419
|
+
const plugins = await readJsonObject(join34(roots.claudeHome, "plugins", "installed_plugins.json"));
|
|
20523
20420
|
const pluginEntries = plugins?.plugins ?? {};
|
|
20524
20421
|
for (const [key, value] of Object.entries(pluginEntries)) {
|
|
20525
20422
|
if (enabled[key] !== true) continue;
|
|
20526
20423
|
const plugin = key.split("@", 1)[0];
|
|
20527
20424
|
for (const install of Array.isArray(value) ? value : [value]) {
|
|
20528
20425
|
if (typeof install?.installPath !== "string") continue;
|
|
20529
|
-
for (const skill of await skillFolders(
|
|
20426
|
+
for (const skill of await skillFolders(join34(install.installPath, "skills"), `${plugin}:`)) {
|
|
20530
20427
|
installed.push({ ...skill, harness: "claude-code" });
|
|
20531
20428
|
}
|
|
20532
20429
|
}
|
|
@@ -20699,7 +20596,6 @@ export {
|
|
|
20699
20596
|
CodexExecStreamError,
|
|
20700
20597
|
CodexExecAdapter,
|
|
20701
20598
|
CopilotAdapter,
|
|
20702
|
-
ForgeAdapter,
|
|
20703
20599
|
GeminiAdapter,
|
|
20704
20600
|
textIsSynthetic,
|
|
20705
20601
|
looksLikeAgentPrompt,
|
|
@@ -20869,7 +20765,7 @@ export {
|
|
|
20869
20765
|
ms,
|
|
20870
20766
|
usd,
|
|
20871
20767
|
zeroPricedCost,
|
|
20872
|
-
|
|
20768
|
+
tokens,
|
|
20873
20769
|
STATUS_MARK,
|
|
20874
20770
|
connectors,
|
|
20875
20771
|
forEachTreeNode,
|