@tangle-network/charts 0.21.22 → 0.21.23
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.
|
@@ -366,8 +366,11 @@ interface FlowPause {
|
|
|
366
366
|
}
|
|
367
367
|
/** A host verdict: `label` is the legend text, `tone` the status color. */
|
|
368
368
|
interface FlowOutcome {
|
|
369
|
-
|
|
369
|
+
/** `live` is a running agent: the one running hue the host uses for every live mark. */
|
|
370
|
+
tone: 'ok' | 'live' | 'neutral' | 'failed' | 'warn';
|
|
370
371
|
label: string;
|
|
372
|
+
/** A hollow ring in the tone instead of a filled dot: a second outcome on the same tone (Done beside Shipped, Stopped beside a plain end). */
|
|
373
|
+
ring?: boolean;
|
|
371
374
|
}
|
|
372
375
|
/** A labelled instant on the trace clock, such as a release or an alert; drawn as a line across the rows. */
|
|
373
376
|
interface FlowMarker {
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { A as BreakdownInput, B as Refusal, C as MarkKind, D as YScale, E as XCategory, F as Figure, H as Tier, I as Interval, L as IntervalMethod, M as CostBasis, N as Estimate, O as YTarget, P as Exclusion, R as MatrixCell, S as ChartMark, T as MarkerShape, U as TierCounts, V as Setup, W as isRefusal, _ as checkerColor, a as TimelineLane, b as BandKind, c as TimelineTick, d as ENDING_COLORS, f as ENDING_ORDER, g as TickOutcome, h as RunEnding, i as FlowTrace, j as ComparisonRow, k as YTick, l as timeline, m as OUTCOME_ORDER, n as FlowOutcome, o as TimelineOptions, p as OUTCOME_COLORS, r as FlowSpan, s as TimelineSpan, t as FlowMarker, u as CHECKER_HUES, v as PointFields, w as MarkVerdict, x as ChartBand, y as PointGlyph, z as RateRow } from "./flow-trace-
|
|
1
|
+
import { A as BreakdownInput, B as Refusal, C as MarkKind, D as YScale, E as XCategory, F as Figure, H as Tier, I as Interval, L as IntervalMethod, M as CostBasis, N as Estimate, O as YTarget, P as Exclusion, R as MatrixCell, S as ChartMark, T as MarkerShape, U as TierCounts, V as Setup, W as isRefusal, _ as checkerColor, a as TimelineLane, b as BandKind, c as TimelineTick, d as ENDING_COLORS, f as ENDING_ORDER, g as TickOutcome, h as RunEnding, i as FlowTrace, j as ComparisonRow, k as YTick, l as timeline, m as OUTCOME_ORDER, n as FlowOutcome, o as TimelineOptions, p as OUTCOME_COLORS, r as FlowSpan, s as TimelineSpan, t as FlowMarker, u as CHECKER_HUES, v as PointFields, w as MarkVerdict, x as ChartBand, y as PointGlyph, z as RateRow } from "./flow-trace-KGCtujbr.js";
|
|
2
2
|
//#region src/block.d.ts
|
|
3
3
|
interface RenderFigureOptions {
|
|
4
4
|
/** Chart uses a closed data disclosure; plot keeps only the SVG and accessible data. */
|
|
@@ -21,6 +21,8 @@
|
|
|
21
21
|
--fw-failed: var(--surface-danger-text);
|
|
22
22
|
--fw-ok: var(--surface-success-text);
|
|
23
23
|
--fw-amber: var(--surface-warning-text);
|
|
24
|
+
/* The running hue: a live agent's dot, outcome and pill. The host sets it to the one running ink its other pages use. */
|
|
25
|
+
--fw-live: var(--fw-accent);
|
|
24
26
|
/* Step kinds inside an agent bar: the chart accent and a categorical hue, far from the outcome greens and reds. */
|
|
25
27
|
--fw-kind-model: var(--chart-accent);
|
|
26
28
|
--fw-kind-tool: var(--tone-cyan-icon);
|
|
@@ -85,10 +87,10 @@
|
|
|
85
87
|
.fw-root .fw-title { font-size: 14px; line-height: 20px; font-weight: 600; letter-spacing: -.005em; white-space: nowrap; }
|
|
86
88
|
.fw-root .fw-state { display: inline-flex; align-items: center; gap: 8px; height: 20px; padding: 0 8px; border-radius: var(--radius-pill); font-size: 14px; font-weight: 600; color: var(--fw-muted); background: var(--fw-well); flex-shrink: 0; }
|
|
87
89
|
.fw-root .fw-state::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
|
|
88
|
-
.fw-root .fw-state-live { color: var(--fw-
|
|
90
|
+
.fw-root .fw-state-live { color: var(--fw-live); background: color-mix(in oklab, var(--fw-live) 12%, transparent); }
|
|
89
91
|
.fw-root .fw-state-live::before { animation: fw-pulse 1.6s var(--fw-ease) infinite; }
|
|
90
|
-
.fw-root .fw-headline { color: var(--fw-muted);
|
|
91
|
-
.fw-root .fw-
|
|
92
|
+
.fw-root .fw-headline { color: var(--fw-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
|
|
93
|
+
.fw-root .fw-headline::before { content: "·"; margin-right: 8px; }
|
|
92
94
|
.fw-root .fw-tools { display: flex; align-items: center; gap: 8px; }
|
|
93
95
|
.fw-root .fw-views { display: inline-flex; padding: 4px; border-radius: var(--radius-md); background: var(--fw-well); border: 1px solid var(--fw-border); }
|
|
94
96
|
.fw-root .fw-view-button { appearance: none; border: 0; background: transparent; height: 24px; padding: 0 12px; border-radius: var(--radius-sm); font-size: 14px; color: var(--fw-muted); cursor: pointer; transition: background-color 120ms var(--fw-ease), color 120ms var(--fw-ease); }
|
|
@@ -208,6 +210,8 @@
|
|
|
208
210
|
.fw-root .fw-agent-dot { flex: 0 0 8px; width: 8px; height: 8px; border-radius: 50%; background: var(--line, var(--fw-muted)); }
|
|
209
211
|
/* The dot is outcome only (critique P0 #3): an agent with no recorded outcome gets a hollow ring, never its lane hue. */
|
|
210
212
|
.fw-root .fw-row:not([data-outcome]) .fw-agent-dot:not([data-outcome]) { background: transparent; box-shadow: inset 0 0 0 1.5px var(--fw-muted); }
|
|
213
|
+
.fw-root :is(.fw-agent-dot, .fw-legend .fw-swatch)[data-ring] { background: transparent; box-shadow: inset 0 0 0 2px var(--line, var(--fw-muted)); }
|
|
214
|
+
.fw-root :is(.fw-agent-dot, .fw-legend .fw-swatch)[data-outcome="live"]:not([data-ring]) { box-shadow: 0 0 0 3px color-mix(in oklab, var(--fw-live) 22%, transparent); }
|
|
211
215
|
|
|
212
216
|
/* Lanes and marks */
|
|
213
217
|
.fw-root .fw-lane { position: relative; overflow: hidden; min-width: 0; }
|
|
@@ -234,9 +238,9 @@
|
|
|
234
238
|
/* While searching, ancestors shown only for context recede and the matching names stand out. */
|
|
235
239
|
.fw-root .fw-row[data-search="context"] .fw-label { opacity: 0.55; }
|
|
236
240
|
.fw-root .fw-row[data-search="match"] .fw-name-text { font-weight: 600; }
|
|
237
|
-
/* A restart:
|
|
241
|
+
/* A restart: a notch in the failure ink through the bar at that moment (the run overview's ✕); the bar keeps its own state. */
|
|
238
242
|
.fw-root .fw-mark { position: absolute; z-index: 2; left: calc(var(--x0) - 1px); width: 2px; top: calc(50% + var(--fw-bar-shift) - var(--fw-bar-h) / 2 - 4px); height: calc(var(--fw-bar-h) + 8px);
|
|
239
|
-
border-radius: 2px; background: var(--fw-
|
|
243
|
+
border-radius: 2px; background: var(--fw-failed); box-shadow: 0 0 0 1px var(--fw-surface); pointer-events: auto; }
|
|
240
244
|
/* Centered by top, not a negative margin, so measured spacing stays on the grid. */
|
|
241
245
|
.fw-root :is(.fw-bar, .fw-seg) { top: calc(50% + var(--fw-bar-shift) - var(--fw-bar-h) / 2); height: var(--fw-bar-h); width: max(var(--w), calc(var(--on) * 3px)); border-radius: var(--radius-tag); cursor: pointer; display: flex; align-items: center; justify-content: center; overflow: hidden; }
|
|
242
246
|
.fw-root .fw-bar { background: var(--fill); box-shadow: inset 0 0 0 1px var(--line); }
|
|
@@ -263,10 +267,10 @@
|
|
|
263
267
|
failure keeps its red glyph, so color only ever means state. */
|
|
264
268
|
.fw-root.fw-fill-muted .fw-view-agents [data-tone] { --tone: var(--fw-h0); }
|
|
265
269
|
/* With per-agent hues the slowest agent keeps its own hue and says so with the amber pill (round 27: an amber-brown bar read "muddy"). */
|
|
266
|
-
.fw-root.fw-fill-muted .fw-view-agents .fw-row[data-slowest], .fw-root.fw-fill-muted .fw-view-agents .fw-row[data-slowest] [data-tone] { --tone: var(--fw-amber); }
|
|
267
270
|
.fw-root [data-outcome="ok"], .fw-root [data-outcome="ok"] [data-tone] { --tone: var(--fw-ok); }
|
|
268
271
|
.fw-root [data-outcome="failed"], .fw-root [data-outcome="failed"] [data-tone] { --tone: var(--fw-failed); }
|
|
269
272
|
.fw-root [data-outcome="warn"], .fw-root [data-outcome="warn"] [data-tone] { --tone: var(--fw-amber); }
|
|
273
|
+
.fw-root [data-outcome="live"], .fw-root [data-outcome="live"] [data-tone] { --tone: var(--fw-live); }
|
|
270
274
|
.fw-root [data-outcome="neutral"], .fw-root [data-outcome="neutral"] [data-tone] { --tone: var(--fw-muted); }
|
|
271
275
|
.fw-root .fw-legend { display: flex; flex-wrap: wrap; gap: 4px 16px; margin: 8px 0 0; padding: 0; list-style: none; color: var(--fw-muted); font-size: 14px; line-height: 18px; }
|
|
272
276
|
.fw-root .fw-legend li { display: inline-flex; align-items: center; gap: 8px; }
|
|
@@ -279,6 +283,7 @@
|
|
|
279
283
|
.fw-root.fw-fill-agent .fw-kinds .fw-swatch-tool { background: light-dark(oklch(0.80 0 0), oklch(0.64 0 0)); }
|
|
280
284
|
.fw-root .fw-kinds .fw-swatch-tool { width: 12px; height: 8px; border-radius: 2px; background: var(--fw-kind-tool); }
|
|
281
285
|
.fw-root .fw-kinds .fw-swatch-wait { width: 12px; height: 8px; border-radius: 2px; background: color-mix(in oklab, var(--fw-text) 12%, transparent); box-shadow: inset 0 0 0 1px color-mix(in oklab, var(--fw-text) 18%, transparent); }
|
|
286
|
+
.fw-root .fw-kinds .fw-swatch-event { width: 8px; height: 8px; border-radius: 50%; background: var(--fw-muted); box-shadow: 0 0 0 2px var(--fw-surface); }
|
|
282
287
|
.fw-root .fw-kinds .fw-swatch-handoff { width: 10px; height: 8px; border-left: 1.5px solid var(--fw-muted); border-bottom: 1.5px solid var(--fw-muted); border-bottom-left-radius: 3px; }
|
|
283
288
|
.fw-root .fw-description { margin: 0; color: var(--fw-muted); font-size: 14px; line-height: 20px; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
284
289
|
.fw-root .fw-legend .fw-swatch { width: 8px; height: 8px; border-radius: 50%; background: var(--line); }
|
|
@@ -317,9 +322,9 @@
|
|
|
317
322
|
.fw-root .fw-seg-chip { padding: 0 4px; border-radius: var(--radius-pill); background: color-mix(in oklab, currentColor 18%, transparent); font-weight: 600; font-variant-numeric: tabular-nums; }
|
|
318
323
|
.fw-root .fw-seg-meta { font-variant-numeric: tabular-nums; }
|
|
319
324
|
@container (max-width: 24px) { .fw-root :is(.fw-seg-label, .fw-view-agents .fw-seg .fw-glyph) { display: none; } }
|
|
320
|
-
/* Fail and retry read as filled chips inside the bar
|
|
325
|
+
/* Fail and retry read as filled chips inside the bar: red, and a quiet grey for a retry that recovered. */
|
|
321
326
|
.fw-root .fw-view-agents .fw-seg .fw-glyph { flex: none; margin-left: 6px; display: grid; place-items: center; width: 14px; height: 14px; border-radius: 50%; background: var(--fw-failed); color: light-dark(var(--fw-surface), hsl(var(--hsl-background))); }
|
|
322
|
-
.fw-root .fw-view-agents .fw-seg .fw-glyph[data-glyph="retry"] { background: var(--fw-
|
|
327
|
+
.fw-root .fw-view-agents .fw-seg .fw-glyph[data-glyph="retry"] { background: var(--fw-muted); }
|
|
323
328
|
.fw-root .fw-view-agents .fw-seg .fw-glyph svg { width: 9px; height: 9px; stroke-width: 2.5; }
|
|
324
329
|
.fw-root:is(.fw-fill-muted, .fw-fill-outcome) .fw-view-agents :is(.fw-seg-alt.fw-seg-model, .fw-seg-alt.fw-seg-tool) { filter: brightness(.88); }
|
|
325
330
|
.fw-root .fw-seg-failed { background: color-mix(in oklab, var(--fw-failed) 18%, var(--fw-surface)); box-shadow: inset 0 0 0 1px color-mix(in oklab, var(--fw-failed) 70%, transparent); color: var(--fw-failed); }
|
|
@@ -335,7 +340,7 @@
|
|
|
335
340
|
background: linear-gradient(var(--fw-tint, transparent) 0 0), var(--fw-surface); white-space: nowrap; pointer-events: none; }
|
|
336
341
|
.fw-root .fw-duration { font-size: 14px; color: var(--fw-muted); font-variant-numeric: tabular-nums; }
|
|
337
342
|
.fw-root .fw-k-failed ~ .fw-end .fw-duration { color: var(--fw-failed); }
|
|
338
|
-
.fw-root .fw-badge { height:
|
|
343
|
+
.fw-root .fw-badge { height: 20px; padding: 0 8px; border-radius: var(--radius-pill); font-size: 14px; line-height: 20px; font-weight: 500; color: var(--fw-muted); background: transparent; box-shadow: inset 0 0 0 1px var(--fw-border); }
|
|
339
344
|
|
|
340
345
|
/* Handoff elbows: 1.5 px stroke, 6 px radius, a 5 px dot where the handoff leaves its sender. */
|
|
341
346
|
/* Under the rows (which follow it), so end labels and badges always sit above the connectors. */
|
|
@@ -364,7 +369,7 @@
|
|
|
364
369
|
/* The playhead: a round knob on a thin neutral track, visible at rest without outweighing the chart. */
|
|
365
370
|
.fw-root.fw-root-agents .fw-slider::-webkit-slider-thumb { width: 14px; height: 14px; border-radius: 50%; background: var(--fw-text); box-shadow: 0 0 0 3px var(--fw-surface); }
|
|
366
371
|
.fw-root.fw-root-agents .fw-slider::-moz-range-thumb { width: 14px; height: 14px; border-radius: 50%; background: var(--fw-text); box-shadow: 0 0 0 3px var(--fw-surface); }
|
|
367
|
-
.fw-root .fw-card { position: absolute; z-index: 20; width: min(320px, calc(100% - 16px)); padding: 12px; border-radius: var(--radius-xl); background: var(--fw-raised); border: 1px solid var(--fw-border);
|
|
372
|
+
.fw-root .fw-card { position: absolute; z-index: 20; width: min(320px, calc(100% - 16px)); max-height: min(60vh, 560px); overflow-y: auto; overscroll-behavior: contain; padding: 12px; border-radius: var(--radius-xl); background: var(--fw-raised); border: 1px solid var(--fw-border);
|
|
368
373
|
box-shadow: var(--shadow-dropdown); animation: fw-arrive 140ms var(--fw-ease); }
|
|
369
374
|
/* A hover card never covers the next mark: only a pinned card (a dialog) takes the pointer. */
|
|
370
375
|
.fw-root .fw-card[role="tooltip"] { pointer-events: none; }
|
|
@@ -377,7 +382,7 @@
|
|
|
377
382
|
.fw-root .fw-card-name { flex: 1; min-width: 0; font-size: 14px; line-height: 20px; font-weight: 600; overflow-wrap: anywhere; }
|
|
378
383
|
.fw-root .fw-pill { flex-shrink: 0; height: 20px; padding: 0 8px; border-radius: var(--radius-pill); font-size: 14px; line-height: 20px; font-weight: 600; }
|
|
379
384
|
.fw-root .fw-pill-done { color: var(--fw-ok); background: color-mix(in oklab, var(--fw-ok) 13%, transparent); }
|
|
380
|
-
.fw-root .fw-pill-running { color: var(--fw-
|
|
385
|
+
.fw-root .fw-pill-running { color: var(--fw-live); background: color-mix(in oklab, var(--fw-live) 13%, transparent); }
|
|
381
386
|
.fw-root .fw-pill-failed { color: var(--fw-failed); background: color-mix(in oklab, var(--fw-failed) 13%, transparent); }
|
|
382
387
|
.fw-root .fw-icon-button { appearance: none; display: inline-grid; place-items: center; width: 28px; height: 28px; padding: 0; border: 0; border-radius: var(--radius-md); background: transparent; color: var(--fw-muted); cursor: pointer; flex-shrink: 0; }
|
|
383
388
|
.fw-root .fw-icon-button:hover:not(:disabled) { background: var(--fw-hover); color: var(--fw-text); }
|
|
@@ -390,7 +395,8 @@
|
|
|
390
395
|
/* A value of several parts wraps between parts, never inside one ("4.0M" / "cached"). */
|
|
391
396
|
.fw-root .fw-card-parts { display: flex; flex-wrap: wrap; column-gap: 4px; }
|
|
392
397
|
.fw-root .fw-card-parts > * { white-space: nowrap; }
|
|
393
|
-
.fw-root .fw-card-parts > * + *::before { content: "· "; color: var(--fw-muted); }
|
|
398
|
+
.fw-root .fw-card-parts:not(.fw-card-stack) > * + *::before { content: "· "; color: var(--fw-muted); }
|
|
399
|
+
.fw-root .fw-card-stack { flex-direction: column; }
|
|
394
400
|
.fw-root .fw-card-tools { display: grid; grid-template-columns: minmax(0, max-content) max-content; justify-content: start; column-gap: 16px; margin-top: 4px; color: var(--fw-muted); font-weight: 400; }
|
|
395
401
|
.fw-root .fw-card-tools > span { display: contents; }
|
|
396
402
|
.fw-root .fw-card-tools > span > :first-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
package/dist/react/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { B as Refusal, C as MarkKind, D as YScale, E as XCategory, F as Figure, O as YTarget, S as ChartMark, T as MarkerShape, a as TimelineLane, b as BandKind, c as TimelineTick, g as TickOutcome, i as FlowTrace, k as YTick, o as TimelineOptions, r as FlowSpan, s as TimelineSpan, t as FlowMarker, v as PointFields, w as MarkVerdict, x as ChartBand, y as PointGlyph } from "../flow-trace-
|
|
1
|
+
import { B as Refusal, C as MarkKind, D as YScale, E as XCategory, F as Figure, O as YTarget, S as ChartMark, T as MarkerShape, a as TimelineLane, b as BandKind, c as TimelineTick, g as TickOutcome, i as FlowTrace, k as YTick, o as TimelineOptions, r as FlowSpan, s as TimelineSpan, t as FlowMarker, v as PointFields, w as MarkVerdict, x as ChartBand, y as PointGlyph } from "../flow-trace-KGCtujbr.js";
|
|
2
2
|
import { CSSProperties, ReactElement, ReactNode } from "react";
|
|
3
3
|
//#region src/react/sparkline.d.ts
|
|
4
4
|
type SparklineDirection = "rising" | "falling" | "flat";
|
package/dist/react/index.js
CHANGED
|
@@ -2450,7 +2450,7 @@ function formatCost(usd) {
|
|
|
2450
2450
|
/** 9.8k, 754.4k, 1.2M with the exact count left to a title. */
|
|
2451
2451
|
function formatCount(n) {
|
|
2452
2452
|
if (n < 1e3) return String(n);
|
|
2453
|
-
if (n < 1e6) return `${(n / 1e3).toFixed(1)}
|
|
2453
|
+
if (n < 1e6) return `${(n / 1e3).toFixed(1)}K`;
|
|
2454
2454
|
return `${(n / 1e6).toFixed(1)}M`;
|
|
2455
2455
|
}
|
|
2456
2456
|
/** Merge marks closer than `gapMs` so a dense row stays a readable strip of at most `cap` marks. Marks narrower
|
|
@@ -2859,7 +2859,7 @@ function agentFamilies(agents, open) {
|
|
|
2859
2859
|
const running = members.some((row) => spanRunning(row.span));
|
|
2860
2860
|
const known = members.map((row) => row.span.costUsd ?? row.rollupCostUsd).filter((cost) => cost !== void 0);
|
|
2861
2861
|
const failed = members.filter((row) => row.span.outcome ? row.span.outcome.tone === "failed" : !row.ok).length;
|
|
2862
|
-
const outcome = members.every((row) => row.span.outcome && row.span.outcome.tone === members[0].span.outcome?.tone) ? members[0].span.outcome : void 0;
|
|
2862
|
+
const outcome = members.every((row) => row.span.outcome && row.span.outcome.tone === members[0].span.outcome?.tone && !row.span.outcome.ring === !members[0].span.outcome?.ring) ? members[0].span.outcome : void 0;
|
|
2863
2863
|
out.push({
|
|
2864
2864
|
costFloor: known.length < members.length || members.some((row) => row.costFloor),
|
|
2865
2865
|
id,
|
|
@@ -2913,7 +2913,7 @@ function agentFamilies(agents, open) {
|
|
|
2913
2913
|
}
|
|
2914
2914
|
return out;
|
|
2915
2915
|
}
|
|
2916
|
-
/** The second line of an agent row in parts: how it ended and how much it did (failed, 3
|
|
2916
|
+
/** The second line of an agent row in parts: how it ended and how much it did (failed, 3 model calls, 412 tool calls; 6 agents, 4 failed).
|
|
2917
2917
|
* The row shows the parts in order and drops the last ones whole when the line is full, never half a word. */
|
|
2918
2918
|
function agentSummary(row) {
|
|
2919
2919
|
if (row.id.startsWith("family:")) {
|
|
@@ -2928,7 +2928,7 @@ function agentSummary(row) {
|
|
|
2928
2928
|
const tools = row.counts?.tool ?? 0;
|
|
2929
2929
|
return [
|
|
2930
2930
|
row.span.outcome?.label ?? (spanRunning(row.span) ? "running" : !row.ok ? "failed" : row.kind === "pipeline" ? "" : "done"),
|
|
2931
|
-
calls ? `${calls}
|
|
2931
|
+
calls ? `${calls} model ${calls === 1 ? "call" : "calls"}` : "",
|
|
2932
2932
|
tools ? `${tools} tool ${tools === 1 ? "call" : "calls"}` : ""
|
|
2933
2933
|
].filter(Boolean);
|
|
2934
2934
|
}
|
|
@@ -3170,7 +3170,7 @@ const FitGlyph = () => svg(/* @__PURE__ */ jsx("path", { d: "M2.5 6V3.5a1 1 0 0
|
|
|
3170
3170
|
const keepWords = (name) => name.replace(/-/g, "‑");
|
|
3171
3171
|
const KIND_LABEL = {
|
|
3172
3172
|
pipeline: "Agent",
|
|
3173
|
-
model: "
|
|
3173
|
+
model: "Model call",
|
|
3174
3174
|
tool: "Tool call",
|
|
3175
3175
|
waiting: "Waiting",
|
|
3176
3176
|
handoff: "Handoff"
|
|
@@ -3203,19 +3203,19 @@ function metrics(row, clockMs, full) {
|
|
|
3203
3203
|
["cached", "cached"]
|
|
3204
3204
|
].flatMap(([key, unit]) => tokens[key] === void 0 ? [] : [count(tokens[key], unit)]);
|
|
3205
3205
|
out.push(["Tokens", /* @__PURE__ */ jsx("span", {
|
|
3206
|
-
className:
|
|
3206
|
+
className: `fw-card-parts${parts.length > 2 ? " fw-card-stack" : ""}`,
|
|
3207
3207
|
children: parts.map((part, i) => /* @__PURE__ */ jsx("span", { children: part }, i))
|
|
3208
3208
|
})]);
|
|
3209
3209
|
}
|
|
3210
3210
|
const latency = row.modelMs;
|
|
3211
|
-
if (latency?.length) out.push(["
|
|
3211
|
+
if (latency?.length) out.push(["Model latency", /* @__PURE__ */ jsxs("span", {
|
|
3212
3212
|
className: "fw-card-parts",
|
|
3213
3213
|
children: [/* @__PURE__ */ jsxs("span", { children: [formatSpanDuration(percentile(latency, .5)), " median"] }), latency.length >= 10 && /* @__PURE__ */ jsxs("span", { children: [formatSpanDuration(percentile(latency, .95)), " p95"] })]
|
|
3214
3214
|
})]);
|
|
3215
3215
|
const cost = span.costUsd ?? row.rollupCostUsd;
|
|
3216
3216
|
if (cost !== void 0) out.push(["Cost", rowCostText(row, cost)]);
|
|
3217
3217
|
const counts = row.counts;
|
|
3218
|
-
if (counts?.model) out.push(["
|
|
3218
|
+
if (counts?.model) out.push(["Model calls", counts.model.toLocaleString()]);
|
|
3219
3219
|
if (counts?.tool) {
|
|
3220
3220
|
const tools = Object.entries(counts.tools).sort(([a, x], [b, y]) => y - x || a.localeCompare(b));
|
|
3221
3221
|
const rest = tools.length - TOOLS_SHOWN;
|
|
@@ -3285,6 +3285,7 @@ function SpanCard({ id, row, agent, clockMs, left, top, pinned, onClose, renderI
|
|
|
3285
3285
|
children: [
|
|
3286
3286
|
/* @__PURE__ */ jsx("span", {
|
|
3287
3287
|
className: "fw-agent-dot",
|
|
3288
|
+
"data-ring": outcome?.ring || void 0,
|
|
3288
3289
|
"aria-hidden": true
|
|
3289
3290
|
}),
|
|
3290
3291
|
/* @__PURE__ */ jsx("span", {
|
|
@@ -3547,13 +3548,14 @@ const FlowRow = memo(function FlowRow(props) {
|
|
|
3547
3548
|
className: "fw-agent-dot",
|
|
3548
3549
|
"data-tone": "0",
|
|
3549
3550
|
"data-outcome": span.outcome.tone,
|
|
3551
|
+
"data-ring": span.outcome.ring || void 0,
|
|
3550
3552
|
title: span.outcome.label,
|
|
3551
3553
|
"aria-hidden": true
|
|
3552
3554
|
}) : agentView && !step && /* @__PURE__ */ jsx("span", {
|
|
3553
3555
|
className: "fw-agent-dot",
|
|
3554
3556
|
"aria-hidden": true
|
|
3555
3557
|
}),
|
|
3556
|
-
running && /* @__PURE__ */ jsx("span", {
|
|
3558
|
+
running && !(fillByAgent && isAgent && span.outcome) && /* @__PURE__ */ jsx("span", {
|
|
3557
3559
|
className: "fw-spinner",
|
|
3558
3560
|
role: "status",
|
|
3559
3561
|
"aria-label": "running"
|
|
@@ -4550,9 +4552,9 @@ function summaryCells(trace, at, durationMs) {
|
|
|
4550
4552
|
`${tokens.toLocaleString()} tokens`
|
|
4551
4553
|
],
|
|
4552
4554
|
[
|
|
4553
|
-
"
|
|
4555
|
+
"Model calls",
|
|
4554
4556
|
modelCalls === void 0 ? "—" : modelCalls.toLocaleString(),
|
|
4555
|
-
modelCalls === void 0 ? "Model output windows do not establish the number of
|
|
4557
|
+
modelCalls === void 0 ? "Model output windows do not establish the number of model requests" : void 0
|
|
4556
4558
|
],
|
|
4557
4559
|
[
|
|
4558
4560
|
"Tool calls",
|
|
@@ -4565,6 +4567,7 @@ function summaryCells(trace, at, durationMs) {
|
|
|
4565
4567
|
}
|
|
4566
4568
|
/** One legend item per outcome label the agents carry, with its count; nothing when no agent has an outcome. */
|
|
4567
4569
|
const TONE_ORDER = [
|
|
4570
|
+
"live",
|
|
4568
4571
|
"ok",
|
|
4569
4572
|
"warn",
|
|
4570
4573
|
"failed",
|
|
@@ -4589,6 +4592,25 @@ function KindLegend({ rows }) {
|
|
|
4589
4592
|
}), name] }, kind))
|
|
4590
4593
|
});
|
|
4591
4594
|
}
|
|
4595
|
+
/** The axis dots and the dashed lines they drop: one key naming what they mark (a release, or the kinds the host gave). */
|
|
4596
|
+
function MarkerLegend({ markers }) {
|
|
4597
|
+
if (!markers?.length) return null;
|
|
4598
|
+
const kinds = [...new Set(markers.map((marker) => marker.kind ?? "event"))];
|
|
4599
|
+
const name = kinds.length === 1 ? `${kinds[0][0].toUpperCase()}${kinds[0].slice(1)}` : "Event";
|
|
4600
|
+
return /* @__PURE__ */ jsx("ul", {
|
|
4601
|
+
className: "fw-legend fw-kinds",
|
|
4602
|
+
"aria-label": "Markers",
|
|
4603
|
+
children: /* @__PURE__ */ jsxs("li", { children: [
|
|
4604
|
+
/* @__PURE__ */ jsx("span", {
|
|
4605
|
+
className: "fw-swatch-event",
|
|
4606
|
+
"aria-hidden": true
|
|
4607
|
+
}),
|
|
4608
|
+
name,
|
|
4609
|
+
" ",
|
|
4610
|
+
/* @__PURE__ */ jsx("b", { children: markers.length })
|
|
4611
|
+
] })
|
|
4612
|
+
});
|
|
4613
|
+
}
|
|
4592
4614
|
function OutcomeLegend({ agents }) {
|
|
4593
4615
|
const items = /* @__PURE__ */ new Map();
|
|
4594
4616
|
for (const row of agents) {
|
|
@@ -4596,6 +4618,7 @@ function OutcomeLegend({ agents }) {
|
|
|
4596
4618
|
if (!outcome) continue;
|
|
4597
4619
|
const item = items.get(outcome.label) ?? {
|
|
4598
4620
|
tone: outcome.tone,
|
|
4621
|
+
ring: outcome.ring,
|
|
4599
4622
|
count: 0
|
|
4600
4623
|
};
|
|
4601
4624
|
item.count += 1;
|
|
@@ -4611,6 +4634,7 @@ function OutcomeLegend({ agents }) {
|
|
|
4611
4634
|
className: "fw-swatch",
|
|
4612
4635
|
"data-tone": "0",
|
|
4613
4636
|
"data-outcome": item.tone,
|
|
4637
|
+
"data-ring": item.ring || void 0,
|
|
4614
4638
|
"aria-hidden": true
|
|
4615
4639
|
}),
|
|
4616
4640
|
label,
|
|
@@ -4873,11 +4897,13 @@ function FlowWaterfall({ trace, live, startedAt, label = "Trace waterfall", defa
|
|
|
4873
4897
|
const preferred = card.above ? room.above : room.below;
|
|
4874
4898
|
const other = card.above ? room.below : room.above;
|
|
4875
4899
|
const above = box.height <= preferred || box.height > other && preferred >= other ? card.above : !card.above;
|
|
4900
|
+
const floor = globalThis.innerHeight - hostTop - 8 - box.height;
|
|
4901
|
+
const top = Math.max(Math.min(above ? card.anchorTop - 8 - box.height : card.anchorBottom + 8, floor), Math.max(8, 8 - hostTop));
|
|
4876
4902
|
setCard({
|
|
4877
4903
|
...card,
|
|
4878
4904
|
fitted: true,
|
|
4879
4905
|
above,
|
|
4880
|
-
top
|
|
4906
|
+
top
|
|
4881
4907
|
});
|
|
4882
4908
|
}, [card, cardId]);
|
|
4883
4909
|
latest.current.inspect = (target, element, x) => {
|
|
@@ -4994,51 +5020,47 @@ function FlowWaterfall({ trace, live, startedAt, label = "Trace waterfall", defa
|
|
|
4994
5020
|
className: "fw-heading",
|
|
4995
5021
|
children: [/* @__PURE__ */ jsxs("div", {
|
|
4996
5022
|
className: "fw-title-block",
|
|
4997
|
-
children: [
|
|
4998
|
-
|
|
4999
|
-
|
|
5000
|
-
|
|
5001
|
-
|
|
5002
|
-
|
|
5003
|
-
|
|
5004
|
-
|
|
5005
|
-
|
|
5006
|
-
|
|
5007
|
-
|
|
5008
|
-
|
|
5009
|
-
|
|
5010
|
-
|
|
5011
|
-
|
|
5012
|
-
|
|
5013
|
-
|
|
5014
|
-
|
|
5015
|
-
|
|
5016
|
-
|
|
5017
|
-
|
|
5018
|
-
|
|
5019
|
-
|
|
5020
|
-
|
|
5021
|
-
|
|
5022
|
-
|
|
5023
|
-
|
|
5024
|
-
|
|
5025
|
-
|
|
5026
|
-
|
|
5027
|
-
|
|
5028
|
-
|
|
5029
|
-
|
|
5030
|
-
|
|
5031
|
-
|
|
5032
|
-
|
|
5033
|
-
|
|
5034
|
-
|
|
5035
|
-
|
|
5036
|
-
|
|
5037
|
-
|
|
5038
|
-
className: "fw-legends",
|
|
5039
|
-
children: [/* @__PURE__ */ jsx(OutcomeLegend, { agents }), view === "agents" && /* @__PURE__ */ jsx(KindLegend, { rows })]
|
|
5040
|
-
})
|
|
5041
|
-
]
|
|
5023
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
5024
|
+
className: "fw-title-line",
|
|
5025
|
+
children: [
|
|
5026
|
+
/* @__PURE__ */ jsx("span", {
|
|
5027
|
+
className: "fw-title-glyph",
|
|
5028
|
+
"aria-hidden": true,
|
|
5029
|
+
children: /* @__PURE__ */ jsx(TraceGlyph, {})
|
|
5030
|
+
}),
|
|
5031
|
+
/* @__PURE__ */ jsx("h3", {
|
|
5032
|
+
className: "fw-title",
|
|
5033
|
+
children: label
|
|
5034
|
+
}),
|
|
5035
|
+
description && /* @__PURE__ */ jsx("p", {
|
|
5036
|
+
className: "fw-description",
|
|
5037
|
+
title: description,
|
|
5038
|
+
children: description
|
|
5039
|
+
}),
|
|
5040
|
+
view === "agents" && /* @__PURE__ */ jsxs("p", {
|
|
5041
|
+
className: "fw-headline",
|
|
5042
|
+
"aria-live": "polite",
|
|
5043
|
+
children: [
|
|
5044
|
+
agents.length,
|
|
5045
|
+
" ",
|
|
5046
|
+
agents.length === 1 ? "agent" : "agents",
|
|
5047
|
+
sharedDetail ? ` · ${agents.every((row) => row.span.detail === sharedDetail) ? "" : "mostly "}${sharedDetail}` : "",
|
|
5048
|
+
done && speedup >= 1.05 ? ` · ${speedup.toFixed(1)}x parallel` : ""
|
|
5049
|
+
]
|
|
5050
|
+
}),
|
|
5051
|
+
isLive && /* @__PURE__ */ jsx("span", {
|
|
5052
|
+
className: "fw-state fw-state-live",
|
|
5053
|
+
children: "Live"
|
|
5054
|
+
})
|
|
5055
|
+
]
|
|
5056
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
5057
|
+
className: "fw-legends",
|
|
5058
|
+
children: [
|
|
5059
|
+
/* @__PURE__ */ jsx(OutcomeLegend, { agents }),
|
|
5060
|
+
view === "agents" && /* @__PURE__ */ jsx(KindLegend, { rows }),
|
|
5061
|
+
/* @__PURE__ */ jsx(MarkerLegend, { markers })
|
|
5062
|
+
]
|
|
5063
|
+
})]
|
|
5042
5064
|
}), /* @__PURE__ */ jsxs("div", {
|
|
5043
5065
|
className: "fw-tools",
|
|
5044
5066
|
children: [/* @__PURE__ */ jsx("div", {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tangle-network/charts",
|
|
3
|
-
"version": "0.21.
|
|
3
|
+
"version": "0.21.23",
|
|
4
4
|
"description": "Static SVG and HTML figures for benchmarks and operational timing. Draws from producer data and refuses what it cannot draw honestly.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|