@tangle-network/traces 0.9.15 → 0.9.17
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 +27 -0
- package/dist/{chunk-CLJJ5YFI.js → chunk-I4W6DECY.js} +32 -1
- package/dist/cli.js +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +1 -1
- package/package.json +4 -2
- package/skills/build-trace-analyst/SKILL.md +60 -0
- package/skills/build-trace-analyst/agents/openai.yaml +4 -0
- package/skills/inspect-agent-traces/SKILL.md +60 -0
- package/skills/inspect-agent-traces/agents/openai.yaml +4 -0
package/README.md
CHANGED
|
@@ -23,6 +23,7 @@ It reads the transcripts your harness leaves on disk, reconstructs the run as sp
|
|
|
23
23
|
- [Policy-mining evidence](#policy-mining-evidence)
|
|
24
24
|
- [Upload to the Intelligence Platform](#upload-to-the-intelligence-platform)
|
|
25
25
|
- [Trace analysts](#trace-analysts)
|
|
26
|
+
- [Agent skills](#agent-skills)
|
|
26
27
|
- [Library (SDK)](#library-sdk)
|
|
27
28
|
- [Examples](#examples)
|
|
28
29
|
- [Develop](#develop)
|
|
@@ -373,6 +374,32 @@ See [`examples/external-engines.ts`](./examples/external-engines.ts).
|
|
|
373
374
|
|
|
374
375
|
> For the built-in agentic analysts (`--llm`), set `OPENAI_API_KEY`, or point at any OpenAI-compatible gateway with `OPENAI_BASE_URL` (e.g. an internal router) to use a non-OpenAI key.
|
|
375
376
|
|
|
377
|
+
## Agent skills
|
|
378
|
+
|
|
379
|
+
The npm package ships two AgentProfile-ready skills:
|
|
380
|
+
|
|
381
|
+
| Skill | Use |
|
|
382
|
+
|---|---|
|
|
383
|
+
| [`inspect-agent-traces`](./skills/inspect-agent-traces/SKILL.md) | select workflows and export deterministic findings |
|
|
384
|
+
| [`build-trace-analyst`](./skills/build-trace-analyst/SKILL.md) | write and calibrate a custom analyst |
|
|
385
|
+
|
|
386
|
+
Load both from GitHub:
|
|
387
|
+
|
|
388
|
+
```ts
|
|
389
|
+
import { defineGitHubResource } from '@tangle-network/agent-interface'
|
|
390
|
+
|
|
391
|
+
const ref = process.env.TRACES_SKILLS_REF
|
|
392
|
+
if (!ref) throw new Error('TRACES_SKILLS_REF must be an immutable commit')
|
|
393
|
+
|
|
394
|
+
const names = ['inspect-agent-traces', 'build-trace-analyst']
|
|
395
|
+
const skills = names.map((name) => defineGitHubResource(`skills/${name}/SKILL.md`, {
|
|
396
|
+
repository: 'tangle-network/traces',
|
|
397
|
+
ref,
|
|
398
|
+
name,
|
|
399
|
+
}))
|
|
400
|
+
const profile = { name: 'trace-reviewer', resources: { skills } }
|
|
401
|
+
```
|
|
402
|
+
|
|
376
403
|
## Release automation
|
|
377
404
|
|
|
378
405
|
Merging to `main` publishes a patch release automatically:
|
|
@@ -4180,6 +4180,24 @@ import { readdir as readdir11, stat as stat9 } from "fs/promises";
|
|
|
4180
4180
|
import { homedir as homedir10 } from "os";
|
|
4181
4181
|
import { basename as basename8, join as join10 } from "path";
|
|
4182
4182
|
var SERVICE9 = "pi";
|
|
4183
|
+
function terminalStatus(message) {
|
|
4184
|
+
const stopReason = message?.stopReason ?? "missing";
|
|
4185
|
+
if (message?.role === "assistant" && stopReason === "stop") {
|
|
4186
|
+
return { status: "OK", stopReason };
|
|
4187
|
+
}
|
|
4188
|
+
if (message?.role === "assistant" && (stopReason === "error" || message.errorMessage)) {
|
|
4189
|
+
return {
|
|
4190
|
+
status: "ERROR",
|
|
4191
|
+
statusMessage: message.errorMessage?.slice(0, 500) ?? "Pi assistant stopped with an error",
|
|
4192
|
+
stopReason
|
|
4193
|
+
};
|
|
4194
|
+
}
|
|
4195
|
+
return {
|
|
4196
|
+
status: "UNSET",
|
|
4197
|
+
statusMessage: message === void 0 ? "Pi session contained no messages" : `Pi session ended after ${message.role} with stopReason "${stopReason}"`,
|
|
4198
|
+
stopReason
|
|
4199
|
+
};
|
|
4200
|
+
}
|
|
4183
4201
|
function isToolBlock(b) {
|
|
4184
4202
|
return typeof b.type === "string" && /tool[_-]?call|tool[_-]?use|^tool$/i.test(b.type);
|
|
4185
4203
|
}
|
|
@@ -4255,6 +4273,7 @@ var PiAdapter = class {
|
|
|
4255
4273
|
let firstTimestamp;
|
|
4256
4274
|
let lastTimestamp;
|
|
4257
4275
|
let sessionLine;
|
|
4276
|
+
let terminalMessage;
|
|
4258
4277
|
let sawLine = false;
|
|
4259
4278
|
let step = 0;
|
|
4260
4279
|
for await (const l of readJsonl(ref.path, sessionJsonlOptions(ref, options))) {
|
|
@@ -4270,6 +4289,11 @@ var PiAdapter = class {
|
|
|
4270
4289
|
const ts = l.timestamp ?? (/* @__PURE__ */ new Date(0)).toISOString();
|
|
4271
4290
|
const mid = l.id ?? `m${step}`;
|
|
4272
4291
|
const msg = l.message;
|
|
4292
|
+
terminalMessage = {
|
|
4293
|
+
role: msg.role ?? "unknown",
|
|
4294
|
+
stopReason: msg.stopReason,
|
|
4295
|
+
errorMessage: msg.errorMessage
|
|
4296
|
+
};
|
|
4273
4297
|
const llmId = `llm:${mid}`;
|
|
4274
4298
|
if (msg.role === "toolResult") {
|
|
4275
4299
|
const callId = msg.toolCallId ?? `${mid}:result`;
|
|
@@ -4324,6 +4348,9 @@ var PiAdapter = class {
|
|
|
4324
4348
|
model: msg.model ?? null,
|
|
4325
4349
|
inputTokens: msg.usage?.input ?? null,
|
|
4326
4350
|
outputTokens: msg.usage?.output ?? null,
|
|
4351
|
+
reasoningTokens: msg.usage?.reasoning ?? null,
|
|
4352
|
+
cachedInputTokens: msg.usage?.cacheRead ?? null,
|
|
4353
|
+
cacheWriteInputTokens: msg.usage?.cacheWrite ?? null,
|
|
4327
4354
|
step,
|
|
4328
4355
|
content: textOf8(msg.content) || null
|
|
4329
4356
|
})
|
|
@@ -4393,6 +4420,7 @@ var PiAdapter = class {
|
|
|
4393
4420
|
}
|
|
4394
4421
|
const traceId = sessionLine?.id ?? sourceTraceId;
|
|
4395
4422
|
const rootId = `root:${traceId}`;
|
|
4423
|
+
const terminal = terminalStatus(terminalMessage);
|
|
4396
4424
|
for (const item of spans) {
|
|
4397
4425
|
item.trace_id = traceId;
|
|
4398
4426
|
if (item.parent_span_id === sourceRootId) item.parent_span_id = rootId;
|
|
@@ -4405,8 +4433,11 @@ var PiAdapter = class {
|
|
|
4405
4433
|
kind: "AGENT",
|
|
4406
4434
|
startTime: sessionLine?.timestamp ?? firstTimestamp ?? (/* @__PURE__ */ new Date(0)).toISOString(),
|
|
4407
4435
|
endTime: lastTimestamp,
|
|
4436
|
+
status: terminal.status,
|
|
4437
|
+
statusMessage: terminal.statusMessage,
|
|
4408
4438
|
service: SERVICE9,
|
|
4409
|
-
agent: SERVICE9
|
|
4439
|
+
agent: SERVICE9,
|
|
4440
|
+
extra: { "traces.pi.stop_reason": terminal.stopReason }
|
|
4410
4441
|
});
|
|
4411
4442
|
return [root, ...spans];
|
|
4412
4443
|
}
|
package/dist/cli.js
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -712,7 +712,8 @@ declare class FactoryAdapter implements HarnessTraceAdapter {
|
|
|
712
712
|
*
|
|
713
713
|
* Line types: `session` (id + cwd), `model_change`, `thinking_level_change`,
|
|
714
714
|
* and `message`. A `message` line wraps `message.{role, model, provider,
|
|
715
|
-
* content[], usage.{input,output}, stopReason,
|
|
715
|
+
* content[], usage.{input,output,reasoning,cacheRead,cacheWrite}, stopReason,
|
|
716
|
+
* errorMessage}`. Tool calls
|
|
716
717
|
* ride inside assistant `message.content[]` blocks; their completions are
|
|
717
718
|
* separate `role: "toolResult"` messages keyed by `message.toolCallId`.
|
|
718
719
|
*/
|
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tangle-network/traces",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.17",
|
|
4
4
|
"description": "Point it at your coding-agent session traces (Claude Code, Codex, OpenCode, Gemini, Pi, …) and get failure-mode + efficiency findings. CLI + SDK over the @tangle-network/agent-eval analyst suite — observe live sessions, run your own analysts, redact, and upload to the Tangle Intelligence Platform.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -29,7 +29,8 @@
|
|
|
29
29
|
"types": "./dist/index.d.ts",
|
|
30
30
|
"import": "./dist/index.js"
|
|
31
31
|
},
|
|
32
|
-
"./package.json": "./package.json"
|
|
32
|
+
"./package.json": "./package.json",
|
|
33
|
+
"./skills/*": "./skills/*"
|
|
33
34
|
},
|
|
34
35
|
"bin": {
|
|
35
36
|
"traces": "dist/cli.js"
|
|
@@ -38,6 +39,7 @@
|
|
|
38
39
|
"dist",
|
|
39
40
|
"docs",
|
|
40
41
|
"examples",
|
|
42
|
+
"skills",
|
|
41
43
|
"install.sh",
|
|
42
44
|
"README.md"
|
|
43
45
|
],
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: build-trace-analyst
|
|
3
|
+
description: Write and calibrate a custom agent-eval trace analyst on real and labeled workflows.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Build a trace analyst
|
|
7
|
+
|
|
8
|
+
Implement one measurable finding that existing analysts do not provide.
|
|
9
|
+
|
|
10
|
+
## Check coverage
|
|
11
|
+
|
|
12
|
+
1. Run maintained analysis on one positive and one clean case.
|
|
13
|
+
2. Call `buildDefaultAnalystRegistry().list()` for batch analysts.
|
|
14
|
+
Check live analysts separately only for `traces stream`.
|
|
15
|
+
3. Search source or public docs once for the target behavior, then decide.
|
|
16
|
+
|
|
17
|
+
Extend an existing analyst when it already emits the target with usable evidence.
|
|
18
|
+
Do not inspect bundled `dist` or `node_modules`.
|
|
19
|
+
|
|
20
|
+
## Implement
|
|
21
|
+
|
|
22
|
+
- Use `Analyst`, `AnalystRegistry`, `TraceAnalysisStore`, and `makeFinding` from `@tangle-network/traces`.
|
|
23
|
+
- Start with `getOverview`; narrow with `queryTraces`, `viewSpans`, or `searchTrace`.
|
|
24
|
+
- Pass `context.signal` through reads and model calls.
|
|
25
|
+
- Return stable `analyst_id`, `area`, `subject`, and `id_basis` values.
|
|
26
|
+
- Cite exact spans as `trace://<trace-id>/span/<span-id>`.
|
|
27
|
+
- Return no finding when evidence is absent.
|
|
28
|
+
- Use `cost.kind: 'deterministic'` only without model calls.
|
|
29
|
+
- For `cost.kind: 'llm'`, use the injected chat client, budget, cancellation, and usage recording.
|
|
30
|
+
- Extend `buildDefaultAnalystRegistry()` unless full replacement is intentional.
|
|
31
|
+
|
|
32
|
+
Use the [custom analyst](../../examples/custom-analyst.ts) and [config](../../examples/improvement-config.mjs) examples rather than adding a wrapper.
|
|
33
|
+
|
|
34
|
+
## Run
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
pnpm tsx examples/custom-analyst.ts --fixture
|
|
38
|
+
pnpm tsx examples/custom-analyst.ts --good-fixture
|
|
39
|
+
traces improve --harness codex --current --latest-turn --workflow \
|
|
40
|
+
--config traces.config.mjs --dir .traces/custom-analyst
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Inspect every finding and cited span.
|
|
44
|
+
|
|
45
|
+
## Calibrate
|
|
46
|
+
|
|
47
|
+
Use `runAnalystBenchmark` with `registryBenchmarkRunner` from `@tangle-network/agent-eval/analyst`.
|
|
48
|
+
Use AgentRx or CodeTraceBench labels when they match the finding.
|
|
49
|
+
Compare the candidate with a no-findings baseline and relevant maintained or external analysts on identical cases and limits.
|
|
50
|
+
|
|
51
|
+
Use at least 20 independent cases before comparative statistics.
|
|
52
|
+
Retain every case row and report exact-step recall, precision, F1, root-step accuracy when labeled, citation coverage and validity, clean-case false positives, repeat agreement, failures, latency, calls, all token fields, and known or missing cost.
|
|
53
|
+
|
|
54
|
+
Do not claim quality from fixtures alone.
|
|
55
|
+
Require a fresh task comparison before using findings to change an agent or knowledge base.
|
|
56
|
+
|
|
57
|
+
## Then consider
|
|
58
|
+
|
|
59
|
+
- Use `inspect-agent-traces` to investigate a miss or false positive on its original workflow.
|
|
60
|
+
- Use `calibrate-before-measure` before trusting a new label set or scoring rule.
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: inspect-agent-traces
|
|
3
|
+
description: Inspect real agent workflows with the published Traces CLI and export cited local findings.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Inspect agent traces
|
|
7
|
+
|
|
8
|
+
Use the deterministic CLI first.
|
|
9
|
+
Keep inspection local and read-only.
|
|
10
|
+
|
|
11
|
+
## Select the workflow
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
traces --version
|
|
15
|
+
traces list --harness codex --cwd "$PWD"
|
|
16
|
+
traces analyze --harness codex --current --latest-turn --workflow \
|
|
17
|
+
--out .traces/current.md
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
- Use `--current` for the active Codex session.
|
|
21
|
+
- Use `--session <id-or-path>` to pin a listed session.
|
|
22
|
+
- Use `--latest-turn` for the current task in a resumed Codex or Claude Code session.
|
|
23
|
+
- Use `--workflow` to include workers linked by stable parent and child IDs.
|
|
24
|
+
- Use `--max-workflow-sessions <n>` only when the default 100-file bound is insufficient.
|
|
25
|
+
- For Claude Code, use `--harness claude-code --session <path> --latest-turn`; nested subagents are included.
|
|
26
|
+
|
|
27
|
+
Never join agents by display name or timestamp when Traces reports missing or conflicting IDs.
|
|
28
|
+
|
|
29
|
+
## Export
|
|
30
|
+
|
|
31
|
+
Write normalized OpenInference spans for another tool:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
traces convert --harness codex --current --latest-turn --workflow \
|
|
35
|
+
--otlp .traces/current.otlp.jsonl
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Write the complete deterministic review packet:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
traces improve --harness codex --current --latest-turn --workflow \
|
|
42
|
+
--dir .traces/improvement
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
`improve` writes findings, evidence, a report, and spans.
|
|
46
|
+
It does not edit an agent, repository, memory store, or knowledge base.
|
|
47
|
+
|
|
48
|
+
## Report
|
|
49
|
+
|
|
50
|
+
- State the harness, selected task boundary, session and span counts, and integrity warnings.
|
|
51
|
+
- Cite each finding with its exact `trace://` reference.
|
|
52
|
+
- Mark missing outcome, cost, token, skill, or relationship data as unknown.
|
|
53
|
+
- Do not infer task success from a completion message.
|
|
54
|
+
- Do not infer skill use from reading a `SKILL.md`.
|
|
55
|
+
- Do not upload traces unless explicitly requested.
|
|
56
|
+
|
|
57
|
+
## Then consider
|
|
58
|
+
|
|
59
|
+
- Use `build-trace-analyst` when deterministic findings cannot answer a repeated trace question.
|
|
60
|
+
- Use `autopsy` when the result is empty, surprising, or suspiciously strong.
|