@tangle-network/agent-app 0.10.1 → 0.11.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.
@@ -1,3 +1,6 @@
1
+ import { S as StepAgentActivity } from '../agent-activity-C8ZG0F0M.js';
2
+ export { W as WithAgentActivity, s as stepAgentActivity } from '../agent-activity-C8ZG0F0M.js';
3
+
1
4
  /**
2
5
  * Durable mission state — the guarded status machine for a multi-step agent run.
3
6
  *
@@ -130,7 +133,11 @@ interface MissionAuditEvent {
130
133
  */
131
134
  interface MissionStorePort {
132
135
  load(id: string): Promise<MissionRecord | null>;
133
- insert(record: MissionRecord): Promise<MissionRecord>;
136
+ /** `extras` are the opaque product-column values from
137
+ * `CreateMissionInput.extras` — write them in the SAME statement as the
138
+ * record (single-write creation) or ignore them if the table has no extra
139
+ * columns. */
140
+ insert(record: MissionRecord, extras?: Record<string, unknown>): Promise<MissionRecord>;
134
141
  update(id: string, guard: MissionUpdateGuard, patch: MissionUpdatePatch): Promise<MissionRecord | null>;
135
142
  appendEvent(event: MissionAuditEvent): Promise<void>;
136
143
  }
@@ -160,6 +167,13 @@ interface CreateMissionInput {
160
167
  * model). Read back via `mission.metadata`; the engine only reads
161
168
  * `stopRequested` from it. */
162
169
  metadata?: Record<string, unknown> | null;
170
+ /**
171
+ * Opaque product-column values handed VERBATIM to `MissionStorePort.insert`
172
+ * (e.g. a `workflowId` FK on the product's mission table), so creation is a
173
+ * single write — no post-insert stamp. The service never reads, validates,
174
+ * or persists them itself; they exist only on the insert call.
175
+ */
176
+ extras?: Record<string, unknown>;
163
177
  }
164
178
  interface SetStepStatusPatch {
165
179
  sublabel?: string;
@@ -204,8 +218,14 @@ interface MissionServiceOptions {
204
218
  store: MissionStorePort;
205
219
  /** Injectable clock (epoch ms). Default `Date.now`. */
206
220
  now?: () => number;
207
- /** Row-id generator when `CreateMissionInput.id` is omitted.
208
- * Default `crypto.randomUUID`. */
221
+ /**
222
+ * Row-id generator when `CreateMissionInput.id` is omitted. Default
223
+ * `crypto.randomUUID()` — a 36-char dashed UUID. Inject your own when your
224
+ * mission table already has an id shape (e.g. 32-hex matching D1 row
225
+ * defaults): the service stamps the generated id verbatim onto the inserted
226
+ * record, so a mismatch with the rest of your schema surfaces only at the
227
+ * product layer. Keep id shape parity here, not in the store.
228
+ */
209
229
  generateId?: () => string;
210
230
  }
211
231
  declare function createMissionService(options: MissionServiceOptions): MissionService;
@@ -243,6 +263,7 @@ declare function createInMemoryMissionStore(): InMemoryMissionStore;
243
263
  * idempotent + order-tolerant, so a re-sent or duplicated event converges.
244
264
  * The sink itself does no dedupe.
245
265
  */
266
+
246
267
  interface MissionEventSink {
247
268
  emit(event: MissionStreamEvent): void;
248
269
  }
@@ -291,7 +312,14 @@ type MissionStreamEvent = {
291
312
  missionId: string;
292
313
  at: number;
293
314
  stepId: string;
294
- sublabel: string;
315
+ sublabel?: string;
316
+ /**
317
+ * Full CURRENT snapshot of the step's delegated runs — never a delta.
318
+ * The reducer replaces the whole lane (latest snapshot wins by `at`), so
319
+ * emitters re-send everything they know each time and at-least-once /
320
+ * out-of-order delivery converges.
321
+ */
322
+ agentActivity?: StepAgentActivity[];
295
323
  } | {
296
324
  type: 'step.completed';
297
325
  missionId: string;
@@ -360,6 +388,11 @@ interface MissionStepState {
360
388
  sublabel?: string;
361
389
  reason?: string;
362
390
  durationMs?: number;
391
+ /** Latest delegated-run snapshot for the step (see `step.updated`). */
392
+ agentActivity?: StepAgentActivity[];
393
+ /** The `at` of the snapshot currently held — an older snapshot arriving
394
+ * late never replaces a newer one. */
395
+ agentActivityAt?: number;
363
396
  }
364
397
  /** Live per-mission view the reducer folds events into. */
365
398
  interface MissionState {
@@ -695,4 +728,4 @@ declare function parseMissionBlocks(fullContent: string, options?: ParseMissionB
695
728
  */
696
729
  declare function buildAgentMissionPlan(steps: ParsedMissionStep[]): MissionStep[];
697
730
 
698
- export { type CompleteMissionInput, type CreateMissionInput, DEFAULT_MISSION_STEP_KINDS, type InMemoryMissionStore, MISSION_CONTROL_CHANNEL_ID, type MissionApprovalsPort, type MissionAuditEvent, MissionConcurrencyError, type MissionCostLedger, type MissionEngine, type MissionEngineOptions, type MissionEventSink, type MissionGateKind, type MissionGateOptions, type MissionGateProposal, type MissionOutcome, type MissionPlanRunOptions, type MissionProposalResolution, type MissionRecord, type MissionService, type MissionServiceOptions, type MissionState, type MissionStatus, type MissionStep, type MissionStepState, type MissionStepStatus, type MissionStorePort, type MissionStreamEvent, type MissionStreamStatus, type MissionStreamStep, type MissionStreamStepStatus, type MissionUpdateGuard, type MissionUpdatePatch, type ParseMissionBlocksOptions, type ParsedMission, type ParsedMissionStep, type PlanOutcome, RetryableStepError, type SandboxDispatch, type SandboxDispatchDoneResult, type SandboxDispatchInProgressResult, type SandboxDispatchInput, type SandboxDispatchResult, type SetStepStatusPatch, type StepGateClassification, type StepOutcome, applyMissionEvent, asMissionStreamEvent, budgetGateProposalId, buildAgentMissionPlan, createInMemoryMissionStore, createMissionEngine, createMissionService, isMissionStopRequested, isMissionTerminal, mergeMissionState, noopEventSink, parseMissionBlocks, parseSessionStreamEnvelope, reduceMissionEvents, stepGateProposalId, volumeGateProposalId };
731
+ export { type CompleteMissionInput, type CreateMissionInput, DEFAULT_MISSION_STEP_KINDS, type InMemoryMissionStore, MISSION_CONTROL_CHANNEL_ID, type MissionApprovalsPort, type MissionAuditEvent, MissionConcurrencyError, type MissionCostLedger, type MissionEngine, type MissionEngineOptions, type MissionEventSink, type MissionGateKind, type MissionGateOptions, type MissionGateProposal, type MissionOutcome, type MissionPlanRunOptions, type MissionProposalResolution, type MissionRecord, type MissionService, type MissionServiceOptions, type MissionState, type MissionStatus, type MissionStep, type MissionStepState, type MissionStepStatus, type MissionStorePort, type MissionStreamEvent, type MissionStreamStatus, type MissionStreamStep, type MissionStreamStepStatus, type MissionUpdateGuard, type MissionUpdatePatch, type ParseMissionBlocksOptions, type ParsedMission, type ParsedMissionStep, type PlanOutcome, RetryableStepError, type SandboxDispatch, type SandboxDispatchDoneResult, type SandboxDispatchInProgressResult, type SandboxDispatchInput, type SandboxDispatchResult, type SetStepStatusPatch, StepAgentActivity, type StepGateClassification, type StepOutcome, applyMissionEvent, asMissionStreamEvent, budgetGateProposalId, buildAgentMissionPlan, createInMemoryMissionStore, createMissionEngine, createMissionService, isMissionStopRequested, isMissionTerminal, mergeMissionState, noopEventSink, parseMissionBlocks, parseSessionStreamEnvelope, reduceMissionEvents, stepGateProposalId, volumeGateProposalId };
@@ -17,9 +17,10 @@ import {
17
17
  parseMissionBlocks,
18
18
  parseSessionStreamEnvelope,
19
19
  reduceMissionEvents,
20
+ stepAgentActivity,
20
21
  stepGateProposalId,
21
22
  volumeGateProposalId
22
- } from "../chunk-UIWB2F6N.js";
23
+ } from "../chunk-UDXMR3AD.js";
23
24
  export {
24
25
  DEFAULT_MISSION_STEP_KINDS,
25
26
  MISSION_CONTROL_CHANNEL_ID,
@@ -39,6 +40,7 @@ export {
39
40
  parseMissionBlocks,
40
41
  parseSessionStreamEnvelope,
41
42
  reduceMissionEvents,
43
+ stepAgentActivity,
42
44
  stepGateProposalId,
43
45
  volumeGateProposalId
44
46
  };
@@ -1,3 +1,138 @@
1
+ import { S as StepAgentActivity } from '../agent-activity-C8ZG0F0M.js';
2
+
3
+ /**
4
+ * Mission trace context — mint + thread the trace ids that join a mission's
5
+ * step attempts and its delegated agent runs into ONE trace tree.
6
+ *
7
+ * ID formats are byte-compatible with agent-runtime's trace propagation
8
+ * (`readTraceContextFromEnv` / OTLP export): 32 lowercase hex chars for a
9
+ * trace id (16 bytes), 16 for a span id (8 bytes). The env pair from
10
+ * {@link traceEnv} is exactly what agent-runtime's MCP subprocess reads at
11
+ * startup (`TRACE_ID` + `PARENT_SPAN_ID`), so a delegation dispatched with it
12
+ * parents its loop→round→iteration spans under the mission's step span.
13
+ *
14
+ * Pure functions, no deps. Ids are DETERMINISTIC when a key is supplied
15
+ * (missionId / step-attempt seed) so a crashed driver re-mints the identical
16
+ * context on re-dispatch and the re-run joins the same trace instead of
17
+ * forking a new one; without a key they are random.
18
+ */
19
+ interface MissionTraceContext {
20
+ /** 32-hex trace id shared by every span in the mission's tree. */
21
+ traceId: string;
22
+ /** 16-hex span id of the mission root — the parent of every step span. */
23
+ rootSpanId: string;
24
+ }
25
+ interface StepSpanContext {
26
+ traceId: string;
27
+ /** 16-hex span id of this step attempt (or any nested unit of work). */
28
+ spanId: string;
29
+ /** The span this one nests under. */
30
+ parentSpanId: string;
31
+ }
32
+ /**
33
+ * Mint a mission's trace context. With `missionId` the ids are a pure
34
+ * function of it; omitted, both ids are random.
35
+ */
36
+ declare function createMissionTraceContext(missionId?: string): MissionTraceContext;
37
+ /**
38
+ * Derive a child span context under `parent` — one per step attempt (seed
39
+ * e.g. `"${stepId}#${attempt}"`), or nested under another step span. With a
40
+ * seed the span id is deterministic for the same parent + seed; omitted, it
41
+ * is random.
42
+ */
43
+ declare function childSpanContext(parent: MissionTraceContext | StepSpanContext, seed?: string): StepSpanContext;
44
+ /**
45
+ * The env pair a delegation subprocess inherits — agent-runtime's
46
+ * `readTraceContextFromEnv` reads exactly these names. `PARENT_SPAN_ID` is
47
+ * the span the dispatched work nests under: the root for a mission context,
48
+ * the step-attempt span for a step context.
49
+ */
50
+ declare function traceEnv(ctx: MissionTraceContext | StepSpanContext): {
51
+ TRACE_ID: string;
52
+ PARENT_SPAN_ID: string;
53
+ };
54
+
55
+ /**
56
+ * Delegation → FlowSpan converters — render what a mission's delegated agent
57
+ * runs actually did as ONE FlowTrace, drawable by the existing
58
+ * `renderWaterfall` (or any viewer that consumes FlowSpans).
59
+ *
60
+ * Two fidelities, one tree:
61
+ * - COARSE: `delegationActivityToFlowSpans` draws one 'tool' span per
62
+ * delegation from the StepAgentActivity snapshot (startedAt/durationMs) —
63
+ * available live, from the step's journaled lane.
64
+ * - FINE: `loopTraceEventsToFlowSpans` reconstructs agent-runtime's
65
+ * loop → round → iteration hierarchy from the LoopTraceEvent journal a
66
+ * delegation persists. FlowSpans carry no parent ids, so nesting rides the
67
+ * span NAME (`loop ▸ round 0 ▸ iter 1 (coder)`), matching how the ASCII
68
+ * waterfall reads.
69
+ *
70
+ * `composeMissionFlowTrace` lays a whole mission out: one 'pipeline' span per
71
+ * step, each step's delegations beneath it. Pure data transforms — the
72
+ * structural `LoopTraceEventLike` keeps this module free of the optional
73
+ * agent-runtime peer.
74
+ */
75
+
76
+ /** Structural mirror of agent-runtime's `LoopTraceEvent` — same fields, no
77
+ * import, so journals parsed from JSON feed straight in. */
78
+ interface LoopTraceEventLike {
79
+ kind: string;
80
+ runId: string;
81
+ /** Epoch ms. */
82
+ timestamp: number;
83
+ payload: object;
84
+ }
85
+ /**
86
+ * One 'tool' FlowSpan per delegation, positioned relative to `turnStartMs`
87
+ * (the epoch-ms origin of the trace — usually the step or mission start).
88
+ * A row whose `startedAt` does not parse cannot be placed on a timeline and
89
+ * is omitted from the WATERFALL (it stays in the lane itself). A run without
90
+ * `durationMs` is still in flight: its span extends to `opts.nowMs` when
91
+ * given, else renders as a point — `approx` flags both.
92
+ */
93
+ declare function delegationActivityToFlowSpans(activity: StepAgentActivity[], turnStartMs: number, opts?: {
94
+ nowMs?: number;
95
+ }): FlowSpan[];
96
+ /**
97
+ * Reconstruct one delegation's loop → round → iteration tree from its
98
+ * journaled LoopTraceEvents, as FlowSpans relative to `loop.started` (or the
99
+ * first event). Mirrors agent-runtime's `buildLoopOtelSpans` topology:
100
+ * rounds open on `loop.plan` and flush on the next plan / `loop.decision` /
101
+ * `loop.ended`; iterations span `loop.iteration.started` → `.ended`.
102
+ */
103
+ declare function loopTraceEventsToFlowSpans(events: LoopTraceEventLike[]): FlowSpan[];
104
+ /**
105
+ * A single step's activity lane as its own FlowTrace — what a per-step
106
+ * drill-in renders. Origin defaults to the earliest delegation start so the
107
+ * waterfall begins at the lane's first run.
108
+ */
109
+ declare function stepActivityFlowTrace(activity: StepAgentActivity[], opts?: {
110
+ startedAt?: number;
111
+ nowMs?: number;
112
+ }): FlowTrace;
113
+ interface MissionFlowStep {
114
+ id: string;
115
+ intent: string;
116
+ status?: string;
117
+ /** Epoch ms the step attempt started. Absent → laid out sequentially after
118
+ * the previous step (missions run steps in order), `approx` flagged. */
119
+ startedAt?: number;
120
+ durationMs?: number;
121
+ }
122
+ /**
123
+ * Compose a mission-wide FlowTrace: one 'pipeline' span per step, the step's
124
+ * delegated runs ('tool' spans, from `activity[stepId]`) beneath it. A step
125
+ * span always covers its delegations' extent. Cost is the sum of delegation
126
+ * `costUsd`; token counts are not knowable from the activity lane and stay 0.
127
+ */
128
+ declare function composeMissionFlowTrace(input: {
129
+ steps: MissionFlowStep[];
130
+ /** Delegated-run snapshots keyed by step id (the step's `agentActivity`). */
131
+ activity?: Record<string, StepAgentActivity[]>;
132
+ /** Epoch-ms origin. Default: the earliest known step/delegation start. */
133
+ startedAt?: number;
134
+ }): FlowTrace;
135
+
1
136
  /**
2
137
  * `@tangle-network/agent-app/trace` — flow observability for agent turns.
3
138
  *
@@ -13,6 +148,7 @@
13
148
  * pump's flush window and the reader's poll cadence (~100–400ms); spans
14
149
  * carry `approx: true` to keep reports honest about that.
15
150
  */
151
+
16
152
  interface TimedEvent {
17
153
  /** ms since turn start (`_t` stamped by pumpBufferedTurn). */
18
154
  t: number;
@@ -68,4 +204,4 @@ declare function renderHistogram(values: number[], opts?: {
68
204
  format?: (v: number) => string;
69
205
  }): string;
70
206
 
71
- export { type DistributionSummary, type FlowSpan, type FlowTrace, type TimedEvent, buildFlowTrace, renderHistogram, renderWaterfall, summarize, timedEventsFromLines };
207
+ export { type DistributionSummary, type FlowSpan, type FlowTrace, type LoopTraceEventLike, type MissionFlowStep, type MissionTraceContext, type StepSpanContext, type TimedEvent, buildFlowTrace, childSpanContext, composeMissionFlowTrace, createMissionTraceContext, delegationActivityToFlowSpans, loopTraceEventsToFlowSpans, renderHistogram, renderWaterfall, stepActivityFlowTrace, summarize, timedEventsFromLines, traceEnv };
@@ -1,145 +1,31 @@
1
- // src/trace/index.ts
2
- function timedEventsFromLines(lines) {
3
- const out = [];
4
- for (const line of lines) {
5
- try {
6
- const parsed = JSON.parse(line);
7
- if (typeof parsed._t === "number") out.push({ t: parsed._t, event: parsed });
8
- } catch {
9
- }
10
- }
11
- return out.sort((a, b) => a.t - b.t);
12
- }
13
- function innerOf(e) {
14
- return (e.kind === "event" ? e.event : e) ?? {};
15
- }
16
- function buildFlowTrace(events, opts) {
17
- const spans = [];
18
- let promptTokens = 0;
19
- let completionTokens = 0;
20
- let toolCalls = 0;
21
- const first = events[0]?.t ?? 0;
22
- if (first > 0) {
23
- spans.push({ kind: "pipeline", name: "dispatch \u2192 first event", startMs: 0, endMs: first });
24
- }
25
- let segStart = null;
26
- let segEnd = 0;
27
- let segKinds = /* @__PURE__ */ new Set();
28
- let lastDeltaT = first;
29
- const openCalls = /* @__PURE__ */ new Map();
30
- const closeSegment = () => {
31
- if (segStart !== null) {
32
- spans.push({
33
- kind: "model",
34
- name: segKinds.has("reasoning") ? "model turn (reasoning + text)" : "model turn",
35
- startMs: segStart,
36
- endMs: segEnd,
37
- approx: true
38
- });
39
- segStart = null;
40
- segKinds = /* @__PURE__ */ new Set();
41
- }
42
- };
43
- for (const { t, event } of events) {
44
- const inner = innerOf(event);
45
- const type = String(event.kind === "tool_result" ? "tool_result" : inner.type ?? "");
46
- if (type === "text" || type === "reasoning") {
47
- if (segStart === null) segStart = t;
48
- segEnd = t;
49
- segKinds.add(type);
50
- lastDeltaT = t;
51
- } else if (type === "tool_call") {
52
- closeSegment();
53
- toolCalls++;
54
- const call = inner.call ?? inner;
55
- const id = String(call.toolCallId ?? `call_${toolCalls}`);
56
- openCalls.set(id, { name: String(call.toolName ?? "tool"), emitT: t, lastDeltaT });
57
- } else if (type === "tool_result") {
58
- const id = String(event.toolCallId ?? inner.toolCallId ?? "");
59
- const open = openCalls.get(id);
60
- if (open) {
61
- spans.push({
62
- kind: "tool",
63
- name: open.name,
64
- // Execution happens between the end of the model turn that emitted
65
- // the call and the result landing in the buffer.
66
- startMs: open.lastDeltaT,
67
- endMs: t,
68
- approx: true,
69
- meta: { ok: (event.outcome ?? inner.outcome)?.ok }
70
- });
71
- openCalls.delete(id);
72
- }
73
- } else if (type === "usage") {
74
- const u = inner.usage ?? {};
75
- promptTokens += u.promptTokens ?? 0;
76
- completionTokens += u.completionTokens ?? 0;
77
- }
78
- }
79
- closeSegment();
80
- const totalMs = events.length ? events[events.length - 1].t : 0;
81
- const trace = { spans, totalMs, promptTokens, completionTokens, toolCalls };
82
- const p = opts?.pricing;
83
- if (p && (p.prompt != null || p.completion != null)) {
84
- trace.costUsd = promptTokens * Number(p.prompt ?? 0) + completionTokens * Number(p.completion ?? 0);
85
- }
86
- return trace;
87
- }
88
- var fmtS = (ms) => `${(ms / 1e3).toFixed(1)}s`;
89
- function renderWaterfall(trace, opts) {
90
- const width = opts?.width ?? 40;
91
- const scale = trace.totalMs > 0 ? width / trace.totalMs : 0;
92
- const lines = [];
93
- const spans = [...trace.spans].sort((a, b) => a.startMs - b.startMs);
94
- for (let i = 0; i < spans.length; i++) {
95
- const s = spans[i];
96
- const offset = Math.round(s.startMs * scale);
97
- const len = Math.max(1, Math.round((s.endMs - s.startMs) * scale));
98
- const bar = " ".repeat(offset) + (s.kind === "tool" ? "\u2593" : s.kind === "pipeline" ? "\u2591" : "\u2588").repeat(len);
99
- const branch = i === spans.length - 1 ? "\u2514\u2500" : "\u251C\u2500";
100
- const dur = `${fmtS(s.endMs - s.startMs)}${s.approx ? "~" : ""}`;
101
- lines.push(`${fmtS(s.startMs).padStart(7)} ${branch} ${bar.padEnd(width + 2)} ${s.name} (${dur})`);
102
- }
103
- const cost = trace.costUsd != null ? ` $${trace.costUsd.toFixed(trace.costUsd < 0.01 ? 6 : 4)}` : "";
104
- lines.push(
105
- `${fmtS(trace.totalMs).padStart(7)} \u2500\u2500 total \xB7 ${trace.promptTokens}p + ${trace.completionTokens}c tok \xB7 ${trace.toolCalls} tool calls${cost}`
106
- );
107
- return lines.join("\n");
108
- }
109
- function summarize(values) {
110
- const sorted = [...values].sort((a, b) => a - b);
111
- const q = (p) => sorted[Math.min(sorted.length - 1, Math.floor(p * sorted.length))] ?? 0;
112
- return { n: sorted.length, min: sorted[0] ?? 0, p50: q(0.5), p90: q(0.9), max: sorted[sorted.length - 1] ?? 0 };
113
- }
114
- function renderHistogram(values, opts) {
115
- if (!values.length) return "(no samples)";
116
- const buckets = opts?.buckets ?? 6;
117
- const width = opts?.width ?? 24;
118
- const fmt = opts?.format ?? ((v) => `${Math.round(v)}${opts?.unit ?? ""}`);
119
- const s = summarize(values);
120
- const lo = s.min;
121
- const hi = s.max === s.min ? s.min + 1 : s.max;
122
- const counts = new Array(buckets).fill(0);
123
- for (const v of values) {
124
- counts[Math.min(buckets - 1, Math.floor((v - lo) / (hi - lo) * buckets))]++;
125
- }
126
- const maxCount = Math.max(...counts);
127
- const lines = [
128
- `n=${s.n} min=${fmt(s.min)} p50=${fmt(s.p50)} p90=${fmt(s.p90)} max=${fmt(s.max)}`
129
- ];
130
- for (let i = 0; i < buckets; i++) {
131
- const a = lo + (hi - lo) * i / buckets;
132
- const b = lo + (hi - lo) * (i + 1) / buckets;
133
- const bar = "\u2588".repeat(Math.max(counts[i] > 0 ? 1 : 0, Math.round(counts[i] / maxCount * width)));
134
- lines.push(`${fmt(a).padStart(8)}-${fmt(b).padEnd(8)} ${bar} ${counts[i]}`);
135
- }
136
- return lines.join("\n");
137
- }
1
+ import {
2
+ buildFlowTrace,
3
+ childSpanContext,
4
+ createMissionTraceContext,
5
+ renderHistogram,
6
+ renderWaterfall,
7
+ summarize,
8
+ timedEventsFromLines,
9
+ traceEnv
10
+ } from "../chunk-5RT6KY4G.js";
11
+ import {
12
+ composeMissionFlowTrace,
13
+ delegationActivityToFlowSpans,
14
+ loopTraceEventsToFlowSpans,
15
+ stepActivityFlowTrace
16
+ } from "../chunk-AFDROJ64.js";
138
17
  export {
139
18
  buildFlowTrace,
19
+ childSpanContext,
20
+ composeMissionFlowTrace,
21
+ createMissionTraceContext,
22
+ delegationActivityToFlowSpans,
23
+ loopTraceEventsToFlowSpans,
140
24
  renderHistogram,
141
25
  renderWaterfall,
26
+ stepActivityFlowTrace,
142
27
  summarize,
143
- timedEventsFromLines
28
+ timedEventsFromLines,
29
+ traceEnv
144
30
  };
145
31
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/trace/index.ts"],"sourcesContent":["/**\n * `@tangle-network/agent-app/trace` — flow observability for agent turns.\n *\n * The turn buffer stamps `_t` (ms since turn start) on every event, so any\n * live stream OR any historical turn replayed from a TurnEventStore can be\n * reconstructed into a span trace: pipeline overhead, model segments (with\n * thinking TTFT), tool executions, token usage, and cost. Renderers turn\n * traces and multi-run samples into ASCII waterfalls and histograms — the\n * default artifact for \"how did this run actually behave\" questions across\n * evals, hill-climbs, and production debugging.\n *\n * Span boundaries derived from a buffered stream are quantized by the\n * pump's flush window and the reader's poll cadence (~100–400ms); spans\n * carry `approx: true` to keep reports honest about that.\n */\n\nexport interface TimedEvent {\n /** ms since turn start (`_t` stamped by pumpBufferedTurn). */\n t: number\n event: Record<string, unknown>\n}\n\nexport interface FlowSpan {\n kind: 'pipeline' | 'model' | 'tool'\n name: string\n startMs: number\n endMs: number\n approx?: boolean\n meta?: Record<string, unknown>\n}\n\nexport interface FlowTrace {\n spans: FlowSpan[]\n totalMs: number\n promptTokens: number\n completionTokens: number\n /** Computed when per-token pricing is supplied. */\n costUsd?: number\n toolCalls: number\n}\n\n/** Parse stored turn-event lines (JSON strings with `_t`) into TimedEvents. */\nexport function timedEventsFromLines(lines: string[]): TimedEvent[] {\n const out: TimedEvent[] = []\n for (const line of lines) {\n try {\n const parsed = JSON.parse(line) as Record<string, unknown>\n if (typeof parsed._t === 'number') out.push({ t: parsed._t, event: parsed })\n } catch {\n /* skip torn lines */\n }\n }\n return out.sort((a, b) => a.t - b.t)\n}\n\nfunction innerOf(e: Record<string, unknown>): Record<string, unknown> {\n return (e.kind === 'event' ? (e.event as Record<string, unknown>) : e) ?? {}\n}\n\n/**\n * Derive a span trace from timestamped turn events. Model segments are runs\n * of text/reasoning deltas; a tool span opens at the last delta before its\n * tool_call emission and closes at the matching tool_result.\n */\nexport function buildFlowTrace(\n events: TimedEvent[],\n opts?: { pricing?: { prompt?: string | number; completion?: string | number } },\n): FlowTrace {\n const spans: FlowSpan[] = []\n let promptTokens = 0\n let completionTokens = 0\n let toolCalls = 0\n\n const first = events[0]?.t ?? 0\n if (first > 0) {\n spans.push({ kind: 'pipeline', name: 'dispatch → first event', startMs: 0, endMs: first })\n }\n\n let segStart: number | null = null\n let segEnd = 0\n let segKinds = new Set<string>()\n let lastDeltaT = first\n const openCalls = new Map<string, { name: string; emitT: number; lastDeltaT: number }>()\n\n const closeSegment = () => {\n if (segStart !== null) {\n spans.push({\n kind: 'model',\n name: segKinds.has('reasoning') ? 'model turn (reasoning + text)' : 'model turn',\n startMs: segStart,\n endMs: segEnd,\n approx: true,\n })\n segStart = null\n segKinds = new Set()\n }\n }\n\n for (const { t, event } of events) {\n const inner = innerOf(event)\n const type = String(event.kind === 'tool_result' ? 'tool_result' : (inner.type ?? ''))\n\n if (type === 'text' || type === 'reasoning') {\n if (segStart === null) segStart = t\n segEnd = t\n segKinds.add(type)\n lastDeltaT = t\n } else if (type === 'tool_call') {\n closeSegment()\n toolCalls++\n const call = (inner.call ?? inner) as Record<string, unknown>\n const id = String(call.toolCallId ?? `call_${toolCalls}`)\n openCalls.set(id, { name: String(call.toolName ?? 'tool'), emitT: t, lastDeltaT })\n } else if (type === 'tool_result') {\n const id = String(event.toolCallId ?? inner.toolCallId ?? '')\n const open = openCalls.get(id)\n if (open) {\n spans.push({\n kind: 'tool',\n name: open.name,\n // Execution happens between the end of the model turn that emitted\n // the call and the result landing in the buffer.\n startMs: open.lastDeltaT,\n endMs: t,\n approx: true,\n meta: { ok: ((event.outcome ?? inner.outcome) as { ok?: boolean } | undefined)?.ok },\n })\n openCalls.delete(id)\n }\n } else if (type === 'usage') {\n const u = (inner.usage ?? {}) as { promptTokens?: number; completionTokens?: number }\n promptTokens += u.promptTokens ?? 0\n completionTokens += u.completionTokens ?? 0\n }\n }\n closeSegment()\n\n const totalMs = events.length ? events[events.length - 1]!.t : 0\n const trace: FlowTrace = { spans, totalMs, promptTokens, completionTokens, toolCalls }\n const p = opts?.pricing\n if (p && (p.prompt != null || p.completion != null)) {\n trace.costUsd = promptTokens * Number(p.prompt ?? 0) + completionTokens * Number(p.completion ?? 0)\n }\n return trace\n}\n\nconst fmtS = (ms: number) => `${(ms / 1000).toFixed(1)}s`\n\n/** ASCII waterfall cascade — the default artifact for explaining a flow. */\nexport function renderWaterfall(trace: FlowTrace, opts?: { width?: number }): string {\n const width = opts?.width ?? 40\n const scale = trace.totalMs > 0 ? width / trace.totalMs : 0\n const lines: string[] = []\n const spans = [...trace.spans].sort((a, b) => a.startMs - b.startMs)\n for (let i = 0; i < spans.length; i++) {\n const s = spans[i]!\n const offset = Math.round(s.startMs * scale)\n const len = Math.max(1, Math.round((s.endMs - s.startMs) * scale))\n const bar = ' '.repeat(offset) + (s.kind === 'tool' ? '▓' : s.kind === 'pipeline' ? '░' : '█').repeat(len)\n const branch = i === spans.length - 1 ? '└─' : '├─'\n const dur = `${fmtS(s.endMs - s.startMs)}${s.approx ? '~' : ''}`\n lines.push(`${fmtS(s.startMs).padStart(7)} ${branch} ${bar.padEnd(width + 2)} ${s.name} (${dur})`)\n }\n const cost = trace.costUsd != null ? ` $${trace.costUsd.toFixed(trace.costUsd < 0.01 ? 6 : 4)}` : ''\n lines.push(\n `${fmtS(trace.totalMs).padStart(7)} ── total · ${trace.promptTokens}p + ${trace.completionTokens}c tok · ${trace.toolCalls} tool calls${cost}`,\n )\n return lines.join('\\n')\n}\n\nexport interface DistributionSummary {\n n: number\n min: number\n p50: number\n p90: number\n max: number\n}\n\nexport function summarize(values: number[]): DistributionSummary {\n const sorted = [...values].sort((a, b) => a - b)\n const q = (p: number) => sorted[Math.min(sorted.length - 1, Math.floor(p * sorted.length))] ?? 0\n return { n: sorted.length, min: sorted[0] ?? 0, p50: q(0.5), p90: q(0.9), max: sorted[sorted.length - 1] ?? 0 }\n}\n\n/** ASCII histogram for multi-run samples (eval latencies, costs, scores). */\nexport function renderHistogram(\n values: number[],\n opts?: { buckets?: number; width?: number; unit?: string; format?: (v: number) => string },\n): string {\n if (!values.length) return '(no samples)'\n const buckets = opts?.buckets ?? 6\n const width = opts?.width ?? 24\n const fmt = opts?.format ?? ((v: number) => `${Math.round(v)}${opts?.unit ?? ''}`)\n const s = summarize(values)\n const lo = s.min\n const hi = s.max === s.min ? s.min + 1 : s.max\n const counts = new Array<number>(buckets).fill(0)\n for (const v of values) {\n counts[Math.min(buckets - 1, Math.floor(((v - lo) / (hi - lo)) * buckets))]!++\n }\n const maxCount = Math.max(...counts)\n const lines = [\n `n=${s.n} min=${fmt(s.min)} p50=${fmt(s.p50)} p90=${fmt(s.p90)} max=${fmt(s.max)}`,\n ]\n for (let i = 0; i < buckets; i++) {\n const a = lo + ((hi - lo) * i) / buckets\n const b = lo + ((hi - lo) * (i + 1)) / buckets\n const bar = '█'.repeat(Math.max(counts[i]! > 0 ? 1 : 0, Math.round((counts[i]! / maxCount) * width)))\n lines.push(`${fmt(a).padStart(8)}-${fmt(b).padEnd(8)} ${bar} ${counts[i]}`)\n }\n return lines.join('\\n')\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -1,5 +1,7 @@
1
1
  import * as react from 'react';
2
2
  import { ReactNode } from 'react';
3
+ import { S as StepAgentActivity } from '../agent-activity-C8ZG0F0M.js';
4
+ import { FlowTrace } from '../trace/index.js';
3
5
  import { C as CatalogModel } from '../model-catalog-BEAEVDaa.js';
4
6
 
5
7
  /**
@@ -119,6 +121,82 @@ declare function nextRevealCount(shown: number, targetLength: number, dtMs: numb
119
121
  */
120
122
  declare function useSmoothText(target: string, enabled: boolean, opts?: SmoothRevealOptions): string;
121
123
 
124
+ type ActivityTone = 'live' | 'ok' | 'error' | 'neutral';
125
+ /** Map a delegation status (free-form string on the wire) to a render tone. */
126
+ declare function activityTone(status: string): ActivityTone;
127
+ /** "$0.4000" under a cent shows 4 decimals; null when unknown/zero. */
128
+ declare function formatActivityCost(costUsd?: number): string | null;
129
+ /** "8s" / "2m 05s" / "1h 12m"; null when unknown. */
130
+ declare function formatActivityDuration(durationMs?: number): string | null;
131
+ /** A delegation record on the cross-context surface; `missionRef` links a
132
+ * promoted delegation back to the mission/step that spawned it. */
133
+ interface AgentActivityRecord extends StepAgentActivity {
134
+ missionRef?: {
135
+ missionId: string;
136
+ stepId?: string;
137
+ label?: string;
138
+ };
139
+ }
140
+ interface AgentActivityPage {
141
+ items: AgentActivityRecord[];
142
+ /** Opaque continuation token; absent ⇒ no further pages. */
143
+ nextCursor?: string;
144
+ }
145
+ /**
146
+ * Fold a fetched page into the held rows: dedupe by `taskId` with the
147
+ * incoming row winning (a refresh re-fetches the head page, so newer
148
+ * snapshots of in-flight runs replace stale ones), newest `startedAt` first.
149
+ */
150
+ declare function mergeActivityPages(existing: AgentActivityRecord[], incoming: AgentActivityRecord[]): AgentActivityRecord[];
151
+ interface WaterfallRow {
152
+ name: string;
153
+ kind: 'pipeline' | 'model' | 'tool';
154
+ /** Bar geometry as percentages of the trace's total span. */
155
+ offsetPct: number;
156
+ widthPct: number;
157
+ durationLabel: string;
158
+ approx: boolean;
159
+ /** False only when the span's meta carries an explicit failure. */
160
+ ok: boolean;
161
+ }
162
+ /** Project a FlowTrace into proportional bar geometry for {@link FlowWaterfall}. */
163
+ declare function waterfallLayout(trace: FlowTrace): WaterfallRow[];
164
+ interface FlowWaterfallProps {
165
+ trace: FlowTrace;
166
+ }
167
+ /** Compact proportional waterfall over a FlowTrace — span name, bar, duration
168
+ * per row; total + cost in the footer. */
169
+ declare function FlowWaterfall({ trace }: FlowWaterfallProps): react.JSX.Element | null;
170
+ interface MissionActivityLaneProps {
171
+ /** The step's delegated-run snapshot (`MissionStepState.agentActivity`). */
172
+ activity: StepAgentActivity[];
173
+ /** Epoch ms origin for the expanded waterfall — usually the step start. */
174
+ startedAt?: number;
175
+ /** Wall clock for extending in-flight runs on the waterfall. */
176
+ nowMs?: number;
177
+ }
178
+ /**
179
+ * Collapsed sub-rows under a mission step — one row per delegated run —
180
+ * expanding to the step's waterfall. Renders nothing for an empty lane.
181
+ */
182
+ declare function MissionActivityLane({ activity, startedAt, nowMs }: MissionActivityLaneProps): react.JSX.Element | null;
183
+ interface AgentActivityPanelProps {
184
+ /** Data port — page through the product's delegation records. Called with
185
+ * no cursor on mount/refresh, with `nextCursor` for older pages. */
186
+ fetchActivity: (cursor?: string) => Promise<AgentActivityPage>;
187
+ /** Render the mission link for a promoted delegation (chip, anchor, router
188
+ * Link — the product's routing, not ours). */
189
+ renderMissionRef?: (ref: NonNullable<AgentActivityRecord['missionRef']>, record: AgentActivityRecord) => ReactNode;
190
+ title?: string;
191
+ emptyLabel?: string;
192
+ }
193
+ /**
194
+ * The standalone cross-context delegation surface: every agent run the
195
+ * product journaled, mission-spawned or not, with status, cost, drill-in, and
196
+ * a mission link slot for promoted delegations.
197
+ */
198
+ declare function AgentActivityPanel({ fetchActivity, renderMissionRef, title, emptyLabel }: AgentActivityPanelProps): react.JSX.Element;
199
+
122
200
  interface ChatMessageMetrics {
123
201
  modelUsed?: string;
124
202
  promptTokens?: number;
@@ -239,4 +317,4 @@ type ToolDetailRenderers = Record<string, (call: ChatToolCallInfo, message: Chat
239
317
  */
240
318
  declare function ChatMessages({ messages, models, renderMarkdown, renderExtras, userLabel, agentLabel, loading, approval, onToolCallClick, toolRenderers, }: ChatMessagesProps): react.JSX.Element;
241
319
 
242
- export { type ChatMessageMetrics, ChatMessages, type ChatMessagesProps, type ChatStreamCallbacks, type ChatStreamToolCall, type ChatStreamToolResult, type ChatToolCallInfo, type ChatUiMessage, type ConsumeChatStreamResult, EffortPicker, type EffortPickerProps, ModelPicker, type ModelPickerProps, type ProposalApprovalHandlers, ProviderLogo, type ProviderLogoProps, RunDrillIn, type RunDrillInProps, type SmoothRevealOptions, type StreamChatOptions, type ToolDetailRenderers, type ToolRunRecord, type ToolRunStep, consumeChatStream, dispatchChatStreamLine, formatModelCost, formatTokensPerSecond, nextRevealCount, pendingApprovalOf, streamChatTurn, useSmoothText };
320
+ export { type ActivityTone, type AgentActivityPage, AgentActivityPanel, type AgentActivityPanelProps, type AgentActivityRecord, type ChatMessageMetrics, ChatMessages, type ChatMessagesProps, type ChatStreamCallbacks, type ChatStreamToolCall, type ChatStreamToolResult, type ChatToolCallInfo, type ChatUiMessage, type ConsumeChatStreamResult, EffortPicker, type EffortPickerProps, FlowWaterfall, type FlowWaterfallProps, MissionActivityLane, type MissionActivityLaneProps, ModelPicker, type ModelPickerProps, type ProposalApprovalHandlers, ProviderLogo, type ProviderLogoProps, RunDrillIn, type RunDrillInProps, type SmoothRevealOptions, type StreamChatOptions, type ToolDetailRenderers, type ToolRunRecord, type ToolRunStep, type WaterfallRow, activityTone, consumeChatStream, dispatchChatStreamLine, formatActivityCost, formatActivityDuration, formatModelCost, formatTokensPerSecond, mergeActivityPages, nextRevealCount, pendingApprovalOf, streamChatTurn, useSmoothText, waterfallLayout };