@tangle-network/charts 0.16.0 → 0.17.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md
CHANGED
|
@@ -335,7 +335,7 @@ const trace = otlpFlowTrace(spans, { price: catalogPrice(await (await fetch(cata
|
|
|
335
335
|
<FlowWaterfall trace={trace} live={running} defaultView="agents" renderIcon={brandMark} />;
|
|
336
336
|
```
|
|
337
337
|
|
|
338
|
-
`defaultView="agents"` opens the agent timeline: one row per agent with its model, thinking and tool marks, hatched waiting while it delegates, elbow connectors to each agent it spawned and back, retry and failure glyphs, and a headline with the measured speedup over sequential (agent busy time over wall time). Expanding an agent opens the span view with that agent unfolded. The span view virtualizes rows (5,000 spans scroll at 58+ fps in headless Chromium), pins ancestors while their children scroll, and labels each bar with its duration and recorded cost. Hover shows a span card; click pins it and zooms the axis to a span too narrow to read. Ctrl/Cmd+wheel or `+`/`-`/`0` zoom, Shift+wheel pans, the scrub track under the controls shows the whole trace, and arrow keys walk the tree.
|
|
338
|
+
`defaultView="agents"` opens the agent timeline: one row per agent with its model, thinking and tool marks, hatched waiting while it delegates, elbow connectors to each agent it spawned and back, retry and failure glyphs, and a headline with the measured speedup over sequential (agent busy time over wall time). Expanding an agent opens the span view with that agent unfolded. The span view virtualizes rows (5,000 spans scroll at 58+ fps in headless Chromium), pins ancestors while their children scroll, and labels each bar with its duration and recorded cost. Hover shows a span card; click pins it and zooms the axis to a span too narrow to read. `onSelect(span)` hears each opened row and pinned bar, so a host can open its own drill-down; `markers={[{ at, label, tone }]}` draws labelled instants, such as releases, across the rows. Ctrl/Cmd+wheel or `+`/`-`/`0` zoom, Shift+wheel pans, the scrub track under the controls shows the whole trace, and arrow keys walk the tree.
|
|
339
339
|
|
|
340
340
|
Live views append spans as they arrive: `traces watch <id|run-dir> --format jsonl --spans` emits a `traces.stream.span` event per new or changed span, and `otlpFlowTrace` keeps the last span per `span_id`. Running agent spans grow to the clock between deltas without React renders (CSS variables carry the clock). Search supports Cmd/Ctrl+F and keeps ancestor context. Missing cost and authoritative LLM counts stay Unknown; a cost priced from a catalog is labelled list price. Invalid intervals retain a per-row `—` timing mark. The static phase waterfall remains a separate chart for disjoint phases.
|
|
341
341
|
|
|
@@ -334,6 +334,13 @@ interface FlowSpan {
|
|
|
334
334
|
handoffTo?: string;
|
|
335
335
|
meta?: Record<string, unknown>;
|
|
336
336
|
}
|
|
337
|
+
/** A labelled instant on the trace clock, such as a release or an alert; drawn as a line across the rows. */
|
|
338
|
+
interface FlowMarker {
|
|
339
|
+
/** Trace-relative milliseconds, on the same clock as span startMs. */
|
|
340
|
+
at: number;
|
|
341
|
+
label: string;
|
|
342
|
+
tone?: 'neutral' | 'ok' | 'failed';
|
|
343
|
+
}
|
|
337
344
|
/** Describe the structure of a flow trace including spans, timing, tokens, cost, and tool calls */
|
|
338
345
|
interface FlowTrace {
|
|
339
346
|
spans: FlowSpan[];
|
|
@@ -350,4 +357,4 @@ interface FlowTrace {
|
|
|
350
357
|
errors?: number;
|
|
351
358
|
}
|
|
352
359
|
//#endregion
|
|
353
|
-
export {
|
|
360
|
+
export { ComparisonRow as A, Setup as B, MarkVerdict as C, YTarget as D, YScale as E, Interval as F, TierCounts as H, IntervalMethod as I, MatrixCell as L, Estimate as M, Exclusion as N, YTick as O, Figure as P, RateRow as R, MarkKind as S, XCategory as T, isRefusal as U, Tier as V, PointFields as _, TimelineOptions as a, ChartBand as b, timeline as c, ENDING_ORDER as d, OUTCOME_COLORS as f, checkerColor as g, TickOutcome as h, TimelineLane as i, CostBasis as j, BreakdownInput as k, CHECKER_HUES as l, RunEnding as m, FlowSpan as n, TimelineSpan as o, OUTCOME_ORDER as p, FlowTrace as r, TimelineTick as s, FlowMarker as t, ENDING_COLORS as u, PointGlyph as v, MarkerShape as w, ChartMark as x, BandKind as y, Refusal as z };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { A as
|
|
1
|
+
import { A as ComparisonRow, B as Setup, C as MarkVerdict, D as YTarget, E as YScale, F as Interval, H as TierCounts, I as IntervalMethod, L as MatrixCell, M as Estimate, N as Exclusion, O as YTick, P as Figure, R as RateRow, S as MarkKind, T as XCategory, U as isRefusal, V as Tier, _ as PointFields, a as TimelineOptions, b as ChartBand, c as timeline, d as ENDING_ORDER, f as OUTCOME_COLORS, g as checkerColor, h as TickOutcome, i as TimelineLane, j as CostBasis, k as BreakdownInput, l as CHECKER_HUES, m as RunEnding, n as FlowSpan, o as TimelineSpan, p as OUTCOME_ORDER, r as FlowTrace, s as TimelineTick, t as FlowMarker, u as ENDING_COLORS, v as PointGlyph, w as MarkerShape, x as ChartMark, y as BandKind, z as Refusal } from "./flow-trace-Cti_6fZP.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. */
|
|
@@ -398,4 +398,4 @@ export declare function otlpFlowTrace(input: OtlpSpan[], options?: OtlpTraceOpti
|
|
|
398
398
|
omitted: number;
|
|
399
399
|
};
|
|
400
400
|
//#endregion
|
|
401
|
-
export { type BandKind, type BreakdownInput, type BreakdownOptions, CHECKER_HUES, type ChartBand, type ChartMark, type ComparisonIntervalsOptions, type ComparisonRow, type CostBasis, type CostFrontierOptions, type DotGroup, type DotGroupRect, ENDING_COLORS, ENDING_ORDER, type Estimate, type Exclusion, type Figure, type FlowSpan, type FlowTrace, type HeatmapCell, type HeatmapColumn, type HeatmapOptions, type HeatmapRow, type HeatmapStatus, type Interval, type IntervalMethod, type LatencyRangeOptions, type LatencyRangeRow, type MarkKind, type MarkVerdict, type MatrixCell, type MetricBarsOptions, type MetricRow, type MultiplePanel, OUTCOME_COLORS, OUTCOME_ORDER, type Observations, type OtlpSpan, type OtlpTraceOptions, type PhaseWaterfallOptions, type PointFields, type PointGlyph, type RankedRatesOptions, type RateIdentity, type RateRow, type Refusal, type RenderFigureOptions, type RunEnding, type Setup, type SmallMultiplesOptions, type TaskMatrixOptions, type TickOutcome, type Tier, type TierCounts, type TimePoint, type TimeSeriesOptions, type TimeSeriesRow, type TimelineLane, type TimelineOptions, type TimelineSpan, type TimelineTick, type UnitDotLayout, type UnitDotOptions, type WaterfallPhase, type XCategory, type YScale, type YTarget, type YTick, checkerColor, isRefusal, timeline };
|
|
401
|
+
export { type BandKind, type BreakdownInput, type BreakdownOptions, CHECKER_HUES, type ChartBand, type ChartMark, type ComparisonIntervalsOptions, type ComparisonRow, type CostBasis, type CostFrontierOptions, type DotGroup, type DotGroupRect, ENDING_COLORS, ENDING_ORDER, type Estimate, type Exclusion, type Figure, type FlowMarker, type FlowSpan, type FlowTrace, type HeatmapCell, type HeatmapColumn, type HeatmapOptions, type HeatmapRow, type HeatmapStatus, type Interval, type IntervalMethod, type LatencyRangeOptions, type LatencyRangeRow, type MarkKind, type MarkVerdict, type MatrixCell, type MetricBarsOptions, type MetricRow, type MultiplePanel, OUTCOME_COLORS, OUTCOME_ORDER, type Observations, type OtlpSpan, type OtlpTraceOptions, type PhaseWaterfallOptions, type PointFields, type PointGlyph, type RankedRatesOptions, type RateIdentity, type RateRow, type Refusal, type RenderFigureOptions, type RunEnding, type Setup, type SmallMultiplesOptions, type TaskMatrixOptions, type TickOutcome, type Tier, type TierCounts, type TimePoint, type TimeSeriesOptions, type TimeSeriesRow, type TimelineLane, type TimelineOptions, type TimelineSpan, type TimelineTick, type UnitDotLayout, type UnitDotOptions, type WaterfallPhase, type XCategory, type YScale, type YTarget, type YTick, checkerColor, isRefusal, timeline };
|
|
@@ -29,6 +29,9 @@
|
|
|
29
29
|
--fw-h5: light-dark(#6d44c7, #ab8cf7);
|
|
30
30
|
--fw-ease: cubic-bezier(.2, .8, .2, 1);
|
|
31
31
|
--fw-bar-h: 16px;
|
|
32
|
+
/* One label column for rows, axis and every lane layer; the agent view caps it lower and drops it on phones. */
|
|
33
|
+
--fw-label-col: min(var(--fw-name-w), 42%);
|
|
34
|
+
--fw-bar-shift: 0px;
|
|
32
35
|
position: relative;
|
|
33
36
|
container-type: inline-size;
|
|
34
37
|
min-width: 0;
|
|
@@ -37,12 +40,12 @@
|
|
|
37
40
|
border: 1px solid var(--fw-border);
|
|
38
41
|
border-radius: 12px;
|
|
39
42
|
font-family: var(--font-sans, Inter, ui-sans-serif, system-ui, sans-serif);
|
|
40
|
-
font-size:
|
|
43
|
+
font-size: 14px;
|
|
41
44
|
line-height: 20px;
|
|
42
45
|
font-feature-settings: "tnum" 1, "cv11" 1;
|
|
43
46
|
-webkit-font-smoothing: antialiased;
|
|
44
47
|
}
|
|
45
|
-
.fw-root-agents { --fw-bar-h: 20px; border-radius: 16px; }
|
|
48
|
+
.fw-root-agents { --fw-bar-h: 20px; --fw-label-col: min(var(--fw-name-w), 28%); border-radius: 16px; }
|
|
46
49
|
.fw-root *, .fw-root *::before, .fw-root *::after { box-sizing: border-box; }
|
|
47
50
|
.fw-root :is(p, dl, dd, h3, ul) { margin: 0; padding: 0; }
|
|
48
51
|
.fw-root :is(button, input, select) { font: inherit; color: inherit; }
|
|
@@ -63,23 +66,23 @@
|
|
|
63
66
|
|
|
64
67
|
/* Header */
|
|
65
68
|
.fw-root .fw-heading { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 12px 16px; border-bottom: 1px solid var(--fw-border); flex-wrap: wrap; }
|
|
66
|
-
.fw-root .fw-title-block { min-width: 0; display: grid; gap:
|
|
69
|
+
.fw-root .fw-title-block { min-width: 0; display: grid; gap: 4px; }
|
|
67
70
|
.fw-root .fw-title-line { display: flex; align-items: center; gap: 8px; min-width: 0; }
|
|
68
71
|
.fw-root .fw-title-glyph { display: inline-flex; color: var(--fw-accent); }
|
|
69
72
|
.fw-root .fw-title { font-size: 14px; line-height: 20px; font-weight: 600; letter-spacing: -.005em; white-space: nowrap; }
|
|
70
|
-
.fw-root .fw-state { display: inline-flex; align-items: center; gap:
|
|
73
|
+
.fw-root .fw-state { display: inline-flex; align-items: center; gap: 8px; height: 20px; padding: 0 8px; border-radius: 999px; font-size: 12px; font-weight: 600; color: var(--fw-muted); background: var(--fw-well); flex-shrink: 0; }
|
|
71
74
|
.fw-root .fw-state::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
|
|
72
75
|
.fw-root .fw-state-live { color: var(--fw-accent); background: color-mix(in oklab, var(--fw-accent) 12%, transparent); }
|
|
73
76
|
.fw-root .fw-state-live::before { animation: fw-pulse 1.6s var(--fw-ease) infinite; }
|
|
74
|
-
.fw-root .fw-headline { color: var(--fw-muted); font-variant-numeric: tabular-nums; display: flex; align-items: center; gap:
|
|
75
|
-
.fw-root .fw-done-mark { display: inline-grid; place-items: center; width: 16px; height: 16px; border-radius: 50%; border: 1.5px solid var(--fw-ok); color: var(--fw-ok); font-size:
|
|
77
|
+
.fw-root .fw-headline { color: var(--fw-muted); font-variant-numeric: tabular-nums; display: flex; align-items: center; gap: 8px; }
|
|
78
|
+
.fw-root .fw-done-mark { display: inline-grid; place-items: center; width: 16px; height: 16px; border-radius: 50%; border: 1.5px solid var(--fw-ok); color: var(--fw-ok); font-size: 12px; line-height: 1; }
|
|
76
79
|
.fw-root .fw-tools { display: flex; align-items: center; gap: 8px; }
|
|
77
|
-
.fw-root .fw-views { display: inline-flex; padding:
|
|
78
|
-
.fw-root .fw-view-button { appearance: none; border: 0; background: transparent; height: 24px; padding: 0
|
|
80
|
+
.fw-root .fw-views { display: inline-flex; padding: 4px; border-radius: 8px; background: var(--fw-well); border: 1px solid var(--fw-border); }
|
|
81
|
+
.fw-root .fw-view-button { appearance: none; border: 0; background: transparent; height: 24px; padding: 0 12px; border-radius: 6px; font-size: 14px; color: var(--fw-muted); cursor: pointer; transition: background-color 120ms var(--fw-ease), color 120ms var(--fw-ease); }
|
|
79
82
|
.fw-root .fw-view-button[aria-checked="true"] { background: var(--fw-surface); color: var(--fw-text); box-shadow: 0 1px 2px rgb(0 0 0 / .12), 0 0 0 1px var(--fw-border); }
|
|
80
83
|
.fw-root .fw-search { position: relative; display: flex; align-items: center; }
|
|
81
84
|
.fw-root .fw-search-glyph { position: absolute; left: 8px; display: inline-flex; color: var(--fw-muted); pointer-events: none; }
|
|
82
|
-
.fw-root .fw-search-input { appearance: none; width: 200px; height: 32px; padding: 0
|
|
85
|
+
.fw-root .fw-search-input { appearance: none; width: 200px; height: 32px; padding: 0 12px 0 28px; border: 1px solid var(--fw-border); border-radius: 8px; background: var(--fw-well); font-size: 14px; }
|
|
83
86
|
.fw-root .fw-search-input::placeholder { color: var(--fw-muted); }
|
|
84
87
|
.fw-root .fw-search-input::-webkit-search-cancel-button { display: none; }
|
|
85
88
|
|
|
@@ -87,18 +90,18 @@
|
|
|
87
90
|
.fw-root .fw-summary { display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); border-bottom: 1px solid var(--fw-border); }
|
|
88
91
|
.fw-root .fw-summary > div { padding: 12px 16px; min-width: 0; }
|
|
89
92
|
.fw-root .fw-summary > div + div { border-left: 1px solid var(--fw-border); }
|
|
90
|
-
.fw-root .fw-summary dt { font-size:
|
|
91
|
-
.fw-root .fw-value { margin-top: 4px; font-size:
|
|
93
|
+
.fw-root .fw-summary dt { font-size: 12px; line-height: 16px; color: var(--fw-muted); }
|
|
94
|
+
.fw-root .fw-value { margin-top: 4px; font-size: 18px; line-height: 24px; font-weight: 600; letter-spacing: -.01em; font-variant-numeric: tabular-nums; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
92
95
|
.fw-root .fw-has-errors .fw-value { color: var(--fw-failed); }
|
|
93
96
|
|
|
94
97
|
/* Axis */
|
|
95
|
-
.fw-root .fw-axis { display: grid; grid-template-columns:
|
|
98
|
+
.fw-root .fw-axis { display: grid; grid-template-columns: var(--fw-label-col) minmax(0, 1fr); height: 32px; color: var(--fw-muted); font-size: 12px; }
|
|
96
99
|
.fw-root .fw-axis-top { border-bottom: 1px solid var(--fw-border); }
|
|
97
100
|
.fw-root .fw-axis-bottom { height: 28px; border-top: 1px solid var(--fw-border); }
|
|
98
|
-
.fw-root .fw-axis-label { position: relative; display: flex; align-items: center; gap:
|
|
101
|
+
.fw-root .fw-axis-label { position: relative; display: flex; align-items: center; gap: 8px; padding: 0 12px 0 16px; border-right: 1px solid var(--fw-border); min-width: 0; }
|
|
99
102
|
.fw-root .fw-axis-bottom .fw-axis-label { border-right-color: transparent; }
|
|
100
|
-
.fw-root .fw-branch-controls { margin-left: auto; display: flex; gap:
|
|
101
|
-
.fw-root .fw-text-button { appearance: none; border: 0; background: transparent; height: 24px; padding: 0
|
|
103
|
+
.fw-root .fw-branch-controls { margin-left: auto; display: flex; gap: 4px; }
|
|
104
|
+
.fw-root .fw-text-button { appearance: none; border: 0; background: transparent; height: 24px; padding: 0 8px; border-radius: 6px; font-size: 12px; color: var(--fw-muted); cursor: pointer; white-space: nowrap; }
|
|
102
105
|
.fw-root .fw-text-button:hover { background: var(--fw-hover); color: var(--fw-text); }
|
|
103
106
|
.fw-root .fw-resize { position: absolute; top: 0; right: -4px; width: 8px; height: 100%; cursor: col-resize; z-index: 2; }
|
|
104
107
|
.fw-root .fw-resize:hover, .fw-root .fw-resize:focus-visible { background: linear-gradient(90deg, transparent 3px, var(--fw-accent) 3px 5px, transparent 5px); outline: 0; }
|
|
@@ -111,21 +114,26 @@
|
|
|
111
114
|
.fw-root .fw-viewport { position: relative; }
|
|
112
115
|
.fw-root .fw-scroller { position: relative; overflow-y: auto; overflow-x: hidden; overscroll-behavior: contain; scrollbar-width: thin; outline: 0; }
|
|
113
116
|
.fw-root .fw-canvas { position: relative; }
|
|
114
|
-
.fw-root .fw-gridlayer, .fw-root .fw-cursor-layer { position: absolute; top: 0; bottom: 0; left:
|
|
117
|
+
.fw-root .fw-gridlayer, .fw-root .fw-cursor-layer { position: absolute; top: 0; bottom: 0; left: var(--fw-label-col); right: 0; overflow: hidden; pointer-events: none; }
|
|
115
118
|
.fw-root .fw-gridline { position: absolute; top: 0; bottom: 0; width: 1px; background: var(--fw-grid); left: calc(var(--fw-pad) + (var(--s) - var(--fw-v0)) * var(--fw-k) * 1px); }
|
|
116
119
|
.fw-root .fw-cursor-layer { z-index: 3; }
|
|
120
|
+
.fw-root .fw-marker-layer { position: absolute; top: 0; bottom: 0; left: var(--fw-label-col); right: 0; overflow: hidden; pointer-events: none; z-index: 2; }
|
|
121
|
+
.fw-root .fw-marker { --fw-marker: var(--fw-muted); position: absolute; top: 0; bottom: 0; width: 0; border-left: 1px dashed var(--fw-marker); left: calc(var(--fw-pad) + (var(--s) - var(--fw-v0)) * var(--fw-k) * 1px); }
|
|
122
|
+
.fw-root .fw-marker[data-tone="ok"] { --fw-marker: var(--fw-ok); }
|
|
123
|
+
.fw-root .fw-marker[data-tone="failed"] { --fw-marker: var(--fw-failed); }
|
|
124
|
+
.fw-root .fw-marker-label { position: absolute; top: 2px; left: 3px; max-width: 160px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; padding: 0 4px; border-radius: 4px; font-size: 12px; line-height: 16px; color: var(--fw-marker); background: var(--fw-surface); box-shadow: inset 0 0 0 1px color-mix(in oklab, var(--fw-marker) 40%, transparent); }
|
|
117
125
|
.fw-root .fw-cursor { position: absolute; top: 0; bottom: 0; width: 1px; background: color-mix(in oklab, var(--fw-text) 70%, transparent); left: calc(var(--fw-pad) + (var(--fw-t) - var(--fw-v0)) * var(--fw-k) * 1px); }
|
|
118
126
|
.fw-root .fw-empty { padding: 40px 16px; text-align: center; color: var(--fw-muted); }
|
|
119
127
|
.fw-root .fw-sticky { position: absolute; top: 0; left: 0; right: 0; z-index: 2; background: var(--fw-surface); box-shadow: 0 1px 0 var(--fw-border), 0 6px 12px -8px rgb(0 0 0 / .35); }
|
|
120
128
|
|
|
121
129
|
/* Rows */
|
|
122
|
-
.fw-root .fw-row { position: absolute; top: 0; left: 0; right: 0; height: var(--fw-row-h); display: grid; grid-template-columns:
|
|
130
|
+
.fw-root .fw-row { position: absolute; top: 0; left: 0; right: 0; height: var(--fw-row-h); display: grid; grid-template-columns: var(--fw-label-col) minmax(0, 1fr); outline: 0; contain: layout style; }
|
|
123
131
|
.fw-root .fw-row:hover { background: var(--fw-hover); }
|
|
124
132
|
.fw-root .fw-row.fw-active { background: color-mix(in oklab, var(--fw-accent) 7%, transparent); }
|
|
125
133
|
.fw-root .fw-row[aria-selected="true"] { background: color-mix(in oklab, var(--fw-accent) 11%, transparent); }
|
|
126
134
|
.fw-root .fw-row:focus-visible { box-shadow: inset 2px 0 0 var(--fw-accent); }
|
|
127
135
|
.fw-root .fw-sticky-row { background: var(--fw-surface); }
|
|
128
|
-
.fw-root .fw-label { position: relative; display: flex; align-items: center; gap:
|
|
136
|
+
.fw-root .fw-label { position: relative; display: flex; align-items: center; gap: 8px; min-width: 0; padding: 0 12px 0 calc(12px + var(--depth) * 16px); border-right: 1px solid var(--fw-border); }
|
|
129
137
|
.fw-root .fw-guides { position: absolute; top: 0; bottom: 0; left: 20px; width: calc(var(--depth) * 16px); background: repeating-linear-gradient(90deg, var(--fw-guide) 0 1px, transparent 1px 16px); }
|
|
130
138
|
.fw-root .fw-toggle, .fw-root .fw-toggle-space { flex: 0 0 16px; width: 16px; height: 16px; }
|
|
131
139
|
.fw-root .fw-toggle { appearance: none; display: grid; place-items: center; padding: 0; border: 0; border-radius: 4px; background: transparent; color: var(--fw-muted); cursor: pointer; }
|
|
@@ -135,24 +143,24 @@
|
|
|
135
143
|
.fw-root .fw-icon-tile { flex: 0 0 20px; display: grid; place-items: center; width: 20px; height: 20px; border-radius: 6px; border: 1px solid var(--fw-border); background: var(--fw-surface); color: var(--line, var(--fw-muted)); }
|
|
136
144
|
.fw-root .fw-icon-tile :is(svg, img) { width: 13px; height: 13px; }
|
|
137
145
|
.fw-root .fw-row .fw-names { font-size: 14px; }
|
|
138
|
-
.fw-root .fw-names { display: flex; align-items: baseline; gap:
|
|
139
|
-
.fw-root .fw-span-name { display: inline-flex; align-items: center; gap:
|
|
146
|
+
.fw-root .fw-names { display: flex; align-items: baseline; gap: 8px; min-width: 0; overflow: hidden; white-space: nowrap; }
|
|
147
|
+
.fw-root .fw-span-name { display: inline-flex; align-items: center; gap: 8px; overflow: hidden; flex-shrink: 0; max-width: 100%; min-width: 0; }
|
|
140
148
|
.fw-root .fw-name-text { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
|
|
141
149
|
.fw-root .fw-strong { font-weight: 600; }
|
|
142
150
|
.fw-root .fw-detail { color: var(--fw-muted); overflow: hidden; min-width: 0; display: inline-flex; align-items: center; gap: 4px; max-width: 100%; }
|
|
143
151
|
.fw-root .fw-detail-icon { display: inline-flex; }
|
|
144
152
|
.fw-root .fw-detail-icon :is(svg, img) { width: 12px; height: 12px; }
|
|
145
|
-
.fw-root .fw-count { flex-shrink: 0; height: 18px; padding: 0
|
|
153
|
+
.fw-root .fw-count { flex-shrink: 0; height: 18px; padding: 0 8px; border-radius: 999px; background: var(--fw-well); border: 1px solid var(--fw-border); color: var(--fw-muted); font-size: 12px; line-height: 16px; font-variant-numeric: tabular-nums; }
|
|
146
154
|
.fw-root .fw-alert { display: inline-flex; color: var(--fw-failed); flex-shrink: 0; }
|
|
147
155
|
.fw-root .fw-alert svg { width: 13px; height: 13px; }
|
|
148
156
|
.fw-root .fw-spinner { width: 10px; height: 10px; border-radius: 50%; border: 1.5px solid color-mix(in oklab, var(--fw-accent) 30%, transparent); border-top-color: var(--fw-accent); animation: fw-spin .8s linear infinite; flex-shrink: 0; }
|
|
149
157
|
|
|
150
158
|
/* Agent rows: a dot, the agent and its model on a second line. */
|
|
151
|
-
.fw-root .fw-view-agents .fw-label { padding-left: 16px; gap:
|
|
159
|
+
.fw-root .fw-view-agents .fw-label { padding-left: 16px; gap: 12px; border-right: 0; }
|
|
152
160
|
.fw-root .fw-view-agents .fw-names { flex-direction: column; align-items: flex-start; gap: 0; }
|
|
153
|
-
.fw-root .fw-view-agents .fw-span-name { font-weight:
|
|
154
|
-
.fw-root .fw-view-agents .fw-detail { font-size:
|
|
155
|
-
.fw-root .fw-agent-dot { flex: 0 0 8px; width: 8px; height: 8px; border-radius: 50%; background: var(--line, var(--fw-muted)); align-self: flex-start; margin-top: calc((var(--fw-row-h) - 34px) / 2 +
|
|
161
|
+
.fw-root .fw-view-agents .fw-span-name { font-weight: 600; line-height: 18px; }
|
|
162
|
+
.fw-root .fw-view-agents .fw-detail { font-size: 12px; line-height: 16px; }
|
|
163
|
+
.fw-root .fw-agent-dot { flex: 0 0 8px; width: 8px; height: 8px; border-radius: 50%; background: var(--line, var(--fw-muted)); align-self: flex-start; margin-top: calc((var(--fw-row-h) - 34px) / 2 + 8px); }
|
|
156
164
|
|
|
157
165
|
/* Lanes and marks */
|
|
158
166
|
.fw-root .fw-lane { position: relative; overflow: hidden; min-width: 0; }
|
|
@@ -166,11 +174,13 @@
|
|
|
166
174
|
left: var(--x0);
|
|
167
175
|
opacity: var(--on);
|
|
168
176
|
}
|
|
169
|
-
.fw-root :is(.fw-bar, .fw-seg) { height: var(--fw-bar-h); margin-top: calc(var(--fw-bar-h) / -2); width: max(var(--w), calc(var(--on) * 3px)); border-radius: 4px; cursor: pointer; display: flex; align-items: center; justify-content: center; overflow: hidden; }
|
|
177
|
+
.fw-root :is(.fw-bar, .fw-seg) { height: var(--fw-bar-h); margin-top: calc(var(--fw-bar-h) / -2 + var(--fw-bar-shift)); width: max(var(--w), calc(var(--on) * 3px)); border-radius: 4px; cursor: pointer; display: flex; align-items: center; justify-content: center; overflow: hidden; }
|
|
170
178
|
.fw-root .fw-bar { background: var(--fill); box-shadow: inset 0 0 0 1px var(--line); }
|
|
179
|
+
/* The mark under the pointer lifts: a brighter fill and a ring in its own tone. */
|
|
180
|
+
.fw-root :is(.fw-bar, .fw-seg):hover { filter: brightness(1.18); box-shadow: inset 0 0 0 1px var(--line), 0 0 0 2px color-mix(in oklab, var(--line) 55%, transparent); z-index: 1; }
|
|
171
181
|
.fw-root .fw-bar.fw-k-tool { background: var(--dim); box-shadow: inset 0 0 0 1px var(--dim-line); }
|
|
172
182
|
/* A handoff is a moment: a slim pill in the receiving tone, not a block of work. */
|
|
173
|
-
.fw-root .fw-bar.fw-k-handoff { background: var(--line); height: 6px; margin-top: -
|
|
183
|
+
.fw-root .fw-bar.fw-k-handoff { background: var(--line); height: 6px; margin-top: -4px; box-shadow: none; }
|
|
174
184
|
.fw-root .fw-bar.fw-k-waiting { background: repeating-linear-gradient(-45deg, var(--fw-hatch) 0 1px, transparent 1px 5px); box-shadow: inset 0 0 0 1px var(--fw-hatch); }
|
|
175
185
|
.fw-root .fw-bar.fw-k-failed { background: color-mix(in oklab, var(--fw-failed) 22%, var(--fw-surface)); box-shadow: inset 0 0 0 1px var(--fw-failed); color: var(--fw-failed); }
|
|
176
186
|
.fw-root .fw-bar.fw-k-pipeline { background: linear-gradient(90deg, var(--fw-neutral-bar), color-mix(in oklab, var(--fw-neutral-bar) 55%, var(--fw-surface))); box-shadow: inset 0 0 0 1px color-mix(in oklab, var(--fw-text) 12%, transparent); }
|
|
@@ -186,16 +196,16 @@
|
|
|
186
196
|
.fw-root .fw-glyph { display: inline-flex; color: currentColor; }
|
|
187
197
|
.fw-root .fw-glyph svg { width: 11px; height: 11px; stroke-width: 2; }
|
|
188
198
|
.fw-root .fw-seg-model .fw-glyph, .fw-root .fw-k-model .fw-glyph { color: light-dark(var(--tone), #fff); }
|
|
189
|
-
.fw-root .fw-end { display: inline-flex; align-items: center; gap: 8px; margin-top: -
|
|
190
|
-
.fw-root .fw-duration { font-size:
|
|
199
|
+
.fw-root .fw-end { display: inline-flex; align-items: center; gap: 8px; margin-top: -12px; height: 20px; left: calc(var(--x0) + max(var(--w), 3px) + 8px); white-space: nowrap; pointer-events: none; }
|
|
200
|
+
.fw-root .fw-duration { font-size: 12px; color: var(--fw-muted); font-variant-numeric: tabular-nums; }
|
|
191
201
|
.fw-root .fw-k-failed ~ .fw-end .fw-duration { color: var(--fw-failed); }
|
|
192
|
-
.fw-root .fw-badge { height: 18px; padding: 0
|
|
202
|
+
.fw-root .fw-badge { height: 18px; padding: 0 8px; border-radius: 999px; font-size: 12px; line-height: 16px; font-weight: 600; color: var(--fw-amber); background: color-mix(in oklab, var(--fw-amber) 13%, transparent); border: 1px solid color-mix(in oklab, var(--fw-amber) 28%, transparent); }
|
|
193
203
|
|
|
194
204
|
/* Handoff elbows: 1.5 px stroke, 6 px radius, a 5 px dot where the handoff leaves its sender. */
|
|
195
|
-
.fw-root .fw-links { position: absolute; top: 0; bottom: 0; left:
|
|
205
|
+
.fw-root .fw-links { position: absolute; top: 0; bottom: 0; left: var(--fw-label-col); right: 0; overflow: hidden; pointer-events: none; z-index: 1; }
|
|
196
206
|
.fw-root .fw-link {
|
|
197
207
|
--x: calc(var(--fw-pad) + (var(--s) - var(--fw-v0)) * var(--fw-k) * 1px);
|
|
198
|
-
position: absolute; width: 8px; border: 0 solid var(--line); border-bottom-width: 1.5px;
|
|
208
|
+
position: absolute; width: 8px; border: 0 solid var(--line); border-bottom-width: 1.5px; translate: 0 var(--fw-bar-shift);
|
|
199
209
|
opacity: clamp(0, (var(--fw-t) - var(--s)) * 1000, 1);
|
|
200
210
|
}
|
|
201
211
|
.fw-root .fw-view-spans .fw-link { opacity: calc(clamp(0, (var(--fw-t) - var(--s)) * 1000, 1) * .7); }
|
|
@@ -210,7 +220,7 @@
|
|
|
210
220
|
.fw-root .fw-card { position: absolute; z-index: 20; width: 320px; padding: 12px; border-radius: 12px; background: var(--fw-raised); border: 1px solid var(--fw-border);
|
|
211
221
|
box-shadow: 0 12px 32px -8px rgb(0 0 0 / .28), 0 2px 6px rgb(0 0 0 / .08); animation: fw-arrive 140ms var(--fw-ease); }
|
|
212
222
|
.fw-root .fw-card-above .fw-card { transform: translateY(-100%); animation-name: fw-arrive-above; }
|
|
213
|
-
.fw-root .fw-card-agent { display: flex; align-items: center; gap:
|
|
223
|
+
.fw-root .fw-card-agent { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; font-size: 12px; font-weight: 600; }
|
|
214
224
|
.fw-root .fw-card-agent .fw-agent-dot { margin-top: 0; align-self: center; }
|
|
215
225
|
.fw-root .fw-card-head { display: flex; align-items: flex-start; gap: 8px; }
|
|
216
226
|
.fw-root .fw-card-head .fw-icon-tile { flex-basis: 28px; width: 28px; height: 28px; border-radius: 8px; }
|
|
@@ -218,32 +228,33 @@
|
|
|
218
228
|
.fw-root .fw-card-title { flex: 1; min-width: 0; }
|
|
219
229
|
.fw-root .fw-card-name { font-size: 14px; line-height: 20px; font-weight: 600; overflow-wrap: anywhere; }
|
|
220
230
|
.fw-root .fw-muted { color: var(--fw-muted); }
|
|
221
|
-
.fw-root .fw-pill { flex-shrink: 0; height: 20px; padding: 0 8px; border-radius: 999px; font-size:
|
|
231
|
+
.fw-root .fw-pill { flex-shrink: 0; height: 20px; padding: 0 8px; border-radius: 999px; font-size: 12px; line-height: 20px; font-weight: 600; }
|
|
222
232
|
.fw-root .fw-pill-done { color: var(--fw-ok); background: color-mix(in oklab, var(--fw-ok) 13%, transparent); }
|
|
223
233
|
.fw-root .fw-pill-running { color: var(--fw-accent); background: color-mix(in oklab, var(--fw-accent) 13%, transparent); }
|
|
224
234
|
.fw-root .fw-pill-failed { color: var(--fw-failed); background: color-mix(in oklab, var(--fw-failed) 13%, transparent); }
|
|
225
235
|
.fw-root .fw-icon-button { appearance: none; display: inline-grid; place-items: center; width: 28px; height: 28px; padding: 0; border: 0; border-radius: 8px; background: transparent; color: var(--fw-muted); cursor: pointer; flex-shrink: 0; }
|
|
226
236
|
.fw-root .fw-icon-button:hover:not(:disabled) { background: var(--fw-hover); color: var(--fw-text); }
|
|
227
|
-
.fw-root .fw-card-head .fw-icon-button { width: 20px; height: 20px; margin: 0 -4px 0 -
|
|
237
|
+
.fw-root .fw-card-head .fw-icon-button { width: 20px; height: 20px; margin: 0 -4px 0 -4px; }
|
|
228
238
|
.fw-root .fw-card-stats { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px 8px; margin-top: 12px; padding: 12px; border-radius: 8px; background: var(--fw-well); }
|
|
229
|
-
.fw-root .fw-card-stats dt, .fw-root .fw-card-label { font-size:
|
|
239
|
+
.fw-root .fw-card-stats dt, .fw-root .fw-card-label { font-size: 12px; line-height: 16px; color: var(--fw-muted); }
|
|
230
240
|
.fw-root .fw-card-stats dd { font-size: 14px; line-height: 20px; font-weight: 600; font-variant-numeric: tabular-nums; }
|
|
231
241
|
.fw-root .fw-unknown { color: var(--fw-muted); font-weight: 400; }
|
|
232
242
|
.fw-root .fw-card-text { margin-top: 12px; }
|
|
233
|
-
.fw-root .fw-card-compact { width: 280px; padding:
|
|
234
|
-
.fw-root .fw-card-compact .fw-card-agent { margin-bottom:
|
|
235
|
-
.fw-root .fw-card-
|
|
236
|
-
.fw-root .fw-card-
|
|
237
|
-
.fw-root .fw-card-
|
|
238
|
-
.fw-root .fw-card-
|
|
239
|
-
.fw-root .fw-card-
|
|
243
|
+
.fw-root .fw-card-compact { width: 280px; padding: 12px; }
|
|
244
|
+
.fw-root .fw-card-compact .fw-card-agent { margin-bottom: 8px; font-size: 14px; line-height: 20px; }
|
|
245
|
+
.fw-root .fw-card-who { min-width: 0; flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
246
|
+
.fw-root .fw-card-cells { display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); gap: 8px; padding: 8px 12px; border-radius: 8px; background: var(--fw-well); }
|
|
247
|
+
.fw-root .fw-card-cells dt { font-size: 12px; line-height: 16px; color: var(--fw-muted); }
|
|
248
|
+
.fw-root .fw-card-cells dd { font-size: 14px; line-height: 20px; font-weight: 600; font-variant-numeric: tabular-nums; white-space: nowrap; }
|
|
249
|
+
.fw-root .fw-card-result { margin-top: 8px; font-size: 14px; line-height: 20px; overflow-wrap: anywhere; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
|
|
250
|
+
.fw-root .fw-card-text p { margin-top: 4px; color: var(--fw-text); overflow-wrap: anywhere; display: -webkit-box; -webkit-line-clamp: 4; -webkit-box-orient: vertical; overflow: hidden; }
|
|
240
251
|
|
|
241
252
|
/* Playback */
|
|
242
|
-
.fw-root .fw-playback { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; padding:
|
|
253
|
+
.fw-root .fw-playback { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; padding: 12px 16px; border-top: 1px solid var(--fw-border); }
|
|
243
254
|
.fw-root .fw-round-button { appearance: none; display: grid; place-items: center; width: 32px; height: 32px; padding: 0; border-radius: 50%; border: 1px solid var(--fw-border); background: var(--fw-well); color: var(--fw-text); cursor: pointer; transition: background-color 120ms var(--fw-ease), transform 120ms var(--fw-ease); }
|
|
244
255
|
.fw-root .fw-round-button:hover:not(:disabled) { background: var(--fw-hover); }
|
|
245
256
|
.fw-root .fw-round-button:active:not(:disabled) { transform: scale(.94); }
|
|
246
|
-
.fw-root .fw-speed select { appearance: none; height: 28px; padding: 0 24px 0
|
|
257
|
+
.fw-root .fw-speed select { appearance: none; height: 28px; padding: 0 24px 0 12px; border-radius: 8px; border: 1px solid var(--fw-border); background: var(--fw-well) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 10 10'%3E%3Cpath d='m2 3.5 3 3 3-3' fill='none' stroke='%23888' stroke-width='1.4' stroke-linecap='round'/%3E%3C/svg%3E") no-repeat right 8px center; font-size: 14px; font-variant-numeric: tabular-nums; cursor: pointer; }
|
|
247
258
|
.fw-root .fw-overview { position: relative; flex: 1 1 160px; min-width: 120px; height: 28px; }
|
|
248
259
|
.fw-root .fw-overview-marks { position: absolute; left: 0; right: 0; top: 8px; height: 12px; border-radius: 4px; background: var(--fw-well); overflow: hidden; box-shadow: inset 0 0 0 1px var(--fw-border); }
|
|
249
260
|
.fw-root .fw-ov { position: absolute; top: 2px; bottom: 2px; border-radius: 1px; }
|
|
@@ -254,7 +265,7 @@
|
|
|
254
265
|
.fw-root .fw-slider { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; appearance: none; -webkit-appearance: none; background: linear-gradient(90deg, transparent var(--fw-progress), color-mix(in oklab, var(--fw-surface) 55%, transparent) var(--fw-progress)) 0 8px / 100% 12px no-repeat; cursor: pointer; }
|
|
255
266
|
.fw-root .fw-slider::-webkit-slider-thumb { -webkit-appearance: none; width: 4px; height: 22px; border-radius: 2px; background: var(--fw-text); box-shadow: 0 0 0 2px var(--fw-surface); }
|
|
256
267
|
.fw-root .fw-slider::-moz-range-thumb { width: 4px; height: 22px; border: 0; border-radius: 2px; background: var(--fw-text); box-shadow: 0 0 0 2px var(--fw-surface); }
|
|
257
|
-
.fw-root .fw-time { min-width: 48px; font-size:
|
|
268
|
+
.fw-root .fw-time { min-width: 48px; font-size: 14px; color: var(--fw-muted); font-variant-numeric: tabular-nums; }
|
|
258
269
|
.fw-root .fw-zoom { display: inline-flex; gap: 0; }
|
|
259
270
|
.fw-root .fw-sr-only { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0; }
|
|
260
271
|
|
|
@@ -295,6 +306,21 @@
|
|
|
295
306
|
/* The agent view keeps scrubbing on a hairline track; the lanes above already show the activity. */
|
|
296
307
|
.fw-root-agents .fw-overview-marks { top: 13px; height: 2px; box-shadow: none; }
|
|
297
308
|
.fw-root-agents .fw-overview-marks > * { display: none; }
|
|
298
|
-
.fw-root .fw-segmented { display: inline-flex; padding:
|
|
299
|
-
.fw-root .fw-segmented button { appearance: none; border: 0; background: transparent; height: 26px; min-width: 36px; padding: 0
|
|
309
|
+
.fw-root .fw-segmented { display: inline-flex; padding: 4px; border-radius: 10px; background: var(--fw-well); border: 1px solid var(--fw-border); }
|
|
310
|
+
.fw-root .fw-segmented button { appearance: none; border: 0; background: transparent; height: 26px; min-width: 36px; padding: 0 12px; border-radius: 8px; font-size: 14px; color: var(--fw-muted); cursor: pointer; font-variant-numeric: tabular-nums; transition: background-color 120ms var(--fw-ease), color 120ms var(--fw-ease); }
|
|
300
311
|
.fw-root .fw-segmented button[aria-checked="true"] { background: var(--fw-surface); color: var(--fw-text); box-shadow: 0 1px 2px rgb(0 0 0 / .14), 0 0 0 1px var(--fw-border); }
|
|
312
|
+
|
|
313
|
+
/* Below 900 px the agent's name takes its own line above a full-width lane: nothing truncates and the bar keeps the width.
|
|
314
|
+
(At 768 px a 28% column cut 15 of 17 names on a real 17-agent run.) */
|
|
315
|
+
@container (max-width: 899px) {
|
|
316
|
+
/* The root is the queried container, so the variables go on its children. */
|
|
317
|
+
.fw-root-agents > * { --fw-label-col: 0px; --fw-bar-shift: 8px; }
|
|
318
|
+
.fw-root-agents .fw-view-agents .fw-label { position: absolute; z-index: 2; top: 4px; left: 0; right: 0; height: 18px; padding: 0 var(--fw-pad); gap: 8px; align-items: center; pointer-events: none; overflow: hidden; }
|
|
319
|
+
.fw-root-agents .fw-view-agents .fw-names { flex-direction: row; align-items: baseline; gap: 8px; min-width: 0; }
|
|
320
|
+
.fw-root-agents .fw-view-agents .fw-agent-dot { align-self: center; margin-top: 0; }
|
|
321
|
+
/* The label leaves the grid flow, so the lane must claim the track column itself. */
|
|
322
|
+
.fw-root-agents .fw-view-agents .fw-lane { grid-column: 2; }
|
|
323
|
+
/* Elbows pass behind the name, not through its letters. */
|
|
324
|
+
.fw-root-agents .fw-view-agents .fw-names { padding-right: 4px; border-radius: 4px; background: var(--fw-surface); }
|
|
325
|
+
.fw-root-agents .fw-view-agents .fw-row:hover .fw-names { background: transparent; }
|
|
326
|
+
}
|
package/dist/react/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C as
|
|
1
|
+
import { C as MarkVerdict, D as YTarget, E as YScale, O as YTick, P as Figure, S as MarkKind, T as XCategory, _ as PointFields, a as TimelineOptions, b as ChartBand, h as TickOutcome, i as TimelineLane, n as FlowSpan, o as TimelineSpan, r as FlowTrace, s as TimelineTick, t as FlowMarker, v as PointGlyph, w as MarkerShape, x as ChartMark, y as BandKind, z as Refusal } from "../flow-trace-Cti_6fZP.js";
|
|
2
2
|
import { CSSProperties, ReactElement, ReactNode } from "react";
|
|
3
3
|
//#region src/react/sparkline.d.ts
|
|
4
4
|
type SparklineDirection = "rising" | "falling" | "flat";
|
|
@@ -367,9 +367,13 @@ interface FlowWaterfallProps {
|
|
|
367
367
|
renderIcon?: (span: FlowSpan) => ReactNode;
|
|
368
368
|
/** Scroll height of the rows; the tree is virtualized beyond it. */
|
|
369
369
|
maxHeight?: number;
|
|
370
|
+
/** Called when a row is opened or a bar is pinned, with that row's span; the built-in behavior still runs. */
|
|
371
|
+
onSelect?: (span: FlowSpan) => void;
|
|
372
|
+
/** Labelled instants, such as releases, drawn across the rows on the trace clock. */
|
|
373
|
+
markers?: FlowMarker[];
|
|
370
374
|
}
|
|
371
375
|
/** Shared trace inspector: the agent timeline and the span waterfall over one clock.
|
|
372
376
|
* Data remains producer-owned; playback, zoom and folding change presentation only. */
|
|
373
|
-
export declare function FlowWaterfall({ trace, live, startedAt, label, defaultCollapsed, defaultView, renderIcon, maxHeight }: FlowWaterfallProps): import("react").JSX.Element;
|
|
377
|
+
export declare function FlowWaterfall({ trace, live, startedAt, label, defaultCollapsed, defaultView, renderIcon, maxHeight, onSelect, markers }: FlowWaterfallProps): import("react").JSX.Element;
|
|
374
378
|
//#endregion
|
|
375
379
|
export type { BandKind, ChartBand, ChartMark, DotMapLabel, DotMapProps, DotMapRect, Figure, FigureAtWidth, FigureViewProps, FlowWaterfallProps, LineSeries, MarkKind, MarkVerdict, MarkerShape, MeterSegment, PointFields, PointGlyph, Refusal, SparklineDirection, SparklineGeometry, SparklineGeometryOptions, SparklineLabelOptions, SparklinePoint, SparklineProps, SparklineValues, StackedBarBucket, StackedBarChartProps, StackedBarSegment, StackedBarSeries, TickOutcome, TimelineLane, TimelineOptions, TimelineSpan, TimelineTick, TimelineViewProps, WaterfallBarProps, WaterfallHeaderProps, WaterfallRowProps, WaterfallSpanGeometry, WaterfallTimeAxisProps, WaterfallWindow, XCategory, YScale, YTarget, YTick };
|
package/dist/react/index.js
CHANGED
|
@@ -2634,7 +2634,6 @@ const ZoomOutGlyph = () => svg(/* @__PURE__ */ jsxs(Fragment, { children: [/* @_
|
|
|
2634
2634
|
r: "4.25"
|
|
2635
2635
|
}), /* @__PURE__ */ jsx("path", { d: "m10.25 10.25 3.25 3.25M5 7h4" })] }));
|
|
2636
2636
|
const FitGlyph = () => svg(/* @__PURE__ */ jsx("path", { d: "M2.5 6V3.5a1 1 0 0 1 1-1H6M10 2.5h2.5a1 1 0 0 1 1 1V6M13.5 10v2.5a1 1 0 0 1-1 1H10M6 13.5H3.5a1 1 0 0 1-1-1V10" }));
|
|
2637
|
-
const ReturnGlyph = () => svg(/* @__PURE__ */ jsx("path", { d: "M6 3.5 3 6.5l3 3M3 6.5h6.5a3.5 3.5 0 0 1 3.5 3.5v2" }));
|
|
2638
2637
|
//#endregion
|
|
2639
2638
|
//#region src/react/flow-waterfall-card.tsx
|
|
2640
2639
|
const KIND_LABEL = {
|
|
@@ -2665,12 +2664,9 @@ function SpanCard({ id, row, agent, clockMs, left, top, pinned, onClose, renderI
|
|
|
2665
2664
|
if (compact) {
|
|
2666
2665
|
const who = owner ?? row;
|
|
2667
2666
|
const tokenCount = span.promptTokens !== void 0 || span.completionTokens !== void 0 ? (span.promptTokens ?? 0) + (span.completionTokens ?? 0) : void 0;
|
|
2668
|
-
const
|
|
2669
|
-
|
|
2670
|
-
|
|
2671
|
-
tokenCount !== void 0 ? `${tokenCount.toLocaleString()} tokens` : void 0,
|
|
2672
|
-
span.costUsd !== void 0 ? formatCost(span.costUsd) : void 0
|
|
2673
|
-
];
|
|
2667
|
+
const cells = [[span.kind === "model" ? "Thinking" : KIND_LABEL[span.kind], duration]];
|
|
2668
|
+
if (tokenCount !== void 0) cells.push(["Tokens", count(tokenCount)]);
|
|
2669
|
+
if (span.costUsd !== void 0) cells.push(["Cost", formatCost(span.costUsd)]);
|
|
2674
2670
|
return /* @__PURE__ */ jsxs("div", {
|
|
2675
2671
|
id,
|
|
2676
2672
|
role: pinned ? "dialog" : "tooltip",
|
|
@@ -2695,21 +2691,18 @@ function SpanCard({ id, row, agent, clockMs, left, top, pinned, onClose, renderI
|
|
|
2695
2691
|
className: "fw-agent-dot",
|
|
2696
2692
|
"aria-hidden": true
|
|
2697
2693
|
}),
|
|
2698
|
-
|
|
2699
|
-
|
|
2700
|
-
|
|
2701
|
-
children: [" ", who.span.detail]
|
|
2694
|
+
/* @__PURE__ */ jsx("span", {
|
|
2695
|
+
className: "fw-card-who",
|
|
2696
|
+
children: who.name
|
|
2702
2697
|
}),
|
|
2703
|
-
|
|
2704
|
-
className:
|
|
2705
|
-
|
|
2706
|
-
children: "Failed"
|
|
2698
|
+
/* @__PURE__ */ jsx("span", {
|
|
2699
|
+
className: `fw-pill fw-pill-${status.toLowerCase()}`,
|
|
2700
|
+
children: status
|
|
2707
2701
|
}),
|
|
2708
2702
|
pinned && /* @__PURE__ */ jsx("button", {
|
|
2709
2703
|
type: "button",
|
|
2710
2704
|
className: "fw-icon-button",
|
|
2711
2705
|
style: {
|
|
2712
|
-
marginLeft: row.ok ? "auto" : 0,
|
|
2713
2706
|
width: 20,
|
|
2714
2707
|
height: 20
|
|
2715
2708
|
},
|
|
@@ -2720,17 +2713,13 @@ function SpanCard({ id, row, agent, clockMs, left, top, pinned, onClose, renderI
|
|
|
2720
2713
|
})
|
|
2721
2714
|
]
|
|
2722
2715
|
}),
|
|
2723
|
-
/* @__PURE__ */ jsx("
|
|
2716
|
+
/* @__PURE__ */ jsx("dl", {
|
|
2717
|
+
className: "fw-card-cells",
|
|
2718
|
+
children: cells.map(([name, value]) => /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("dt", { children: name }), /* @__PURE__ */ jsx("dd", { children: value })] }, name))
|
|
2719
|
+
}),
|
|
2720
|
+
/* @__PURE__ */ jsx("p", {
|
|
2724
2721
|
className: "fw-card-result",
|
|
2725
2722
|
children: span.output ?? span.name
|
|
2726
|
-
}),
|
|
2727
|
-
/* @__PURE__ */ jsx("div", {
|
|
2728
|
-
className: "fw-card-meta",
|
|
2729
|
-
children: meta.filter(Boolean).join(" · ")
|
|
2730
|
-
}),
|
|
2731
|
-
span.input && /* @__PURE__ */ jsxs("div", {
|
|
2732
|
-
className: "fw-card-message",
|
|
2733
|
-
children: [/* @__PURE__ */ jsx(ReturnGlyph, {}), /* @__PURE__ */ jsx("span", { children: span.input })]
|
|
2734
2723
|
})
|
|
2735
2724
|
]
|
|
2736
2725
|
});
|
|
@@ -3404,6 +3393,18 @@ function FlowBody(props) {
|
|
|
3404
3393
|
rowHeight,
|
|
3405
3394
|
render: row
|
|
3406
3395
|
}),
|
|
3396
|
+
props.markers?.length ? /* @__PURE__ */ jsx("div", {
|
|
3397
|
+
className: "fw-marker-layer",
|
|
3398
|
+
children: props.markers.map((marker) => /* @__PURE__ */ jsx("span", {
|
|
3399
|
+
className: "fw-marker",
|
|
3400
|
+
"data-tone": marker.tone ?? "neutral",
|
|
3401
|
+
style: { "--s": marker.at },
|
|
3402
|
+
children: /* @__PURE__ */ jsx("span", {
|
|
3403
|
+
className: "fw-marker-label",
|
|
3404
|
+
children: marker.label
|
|
3405
|
+
})
|
|
3406
|
+
}, `${marker.at}-${marker.label}`))
|
|
3407
|
+
}) : null,
|
|
3407
3408
|
showCursor && /* @__PURE__ */ jsx("div", {
|
|
3408
3409
|
className: "fw-cursor-layer",
|
|
3409
3410
|
"aria-hidden": true,
|
|
@@ -3685,7 +3686,7 @@ const NAME_WIDTH = {
|
|
|
3685
3686
|
const headlineSeconds = (ms) => ms < 6e4 ? `${(ms / 1e3).toFixed(1)}s` : formatSpanDuration(ms);
|
|
3686
3687
|
/** Shared trace inspector: the agent timeline and the span waterfall over one clock.
|
|
3687
3688
|
* Data remains producer-owned; playback, zoom and folding change presentation only. */
|
|
3688
|
-
function FlowWaterfall({ trace, live, startedAt, label = "Trace waterfall", defaultCollapsed = false, defaultView = "spans", renderIcon, maxHeight = 640 }) {
|
|
3689
|
+
function FlowWaterfall({ trace, live, startedAt, label = "Trace waterfall", defaultCollapsed = false, defaultView = "spans", renderIcon, maxHeight = 640, onSelect, markers }) {
|
|
3689
3690
|
const root = useRef(null);
|
|
3690
3691
|
const search = useRef(null);
|
|
3691
3692
|
const slider = useRef(null);
|
|
@@ -3766,6 +3767,16 @@ function FlowWaterfall({ trace, live, startedAt, label = "Trace waterfall", defa
|
|
|
3766
3767
|
collapsed
|
|
3767
3768
|
]);
|
|
3768
3769
|
const slowest = view === "spans" ? slowestRow(rows, clockMs) : void 0;
|
|
3770
|
+
const resized = useRef(false);
|
|
3771
|
+
useLayoutEffect(() => {
|
|
3772
|
+
if (view !== "agents" || resized.current || !root.current) return;
|
|
3773
|
+
let widest = 0;
|
|
3774
|
+
for (const text of root.current.querySelectorAll(".fw-view-agents .fw-row:not(.fw-sticky-row) .fw-name-text")) {
|
|
3775
|
+
const label = text.closest(".fw-label");
|
|
3776
|
+
if (label) widest = Math.max(widest, text.scrollWidth + label.clientWidth - text.clientWidth);
|
|
3777
|
+
}
|
|
3778
|
+
if (widest > 0) setNameWidth(Math.max(140, Math.min(560, Math.ceil(widest) + 16)));
|
|
3779
|
+
}, [view, agents]);
|
|
3769
3780
|
useEffect(() => {
|
|
3770
3781
|
const keydown = (event) => {
|
|
3771
3782
|
const active = document.activeElement;
|
|
@@ -3844,6 +3855,7 @@ function FlowWaterfall({ trace, live, startedAt, label = "Trace waterfall", defa
|
|
|
3844
3855
|
inspect: (_target, _element) => {}
|
|
3845
3856
|
});
|
|
3846
3857
|
const toggleNow = (row) => {
|
|
3858
|
+
onSelect?.(row.span);
|
|
3847
3859
|
if (view === "agents") {
|
|
3848
3860
|
const keep = /* @__PURE__ */ new Set();
|
|
3849
3861
|
for (let cursor = row; cursor; cursor = cursor.parentId ? byId.get(cursor.parentId) : void 0) keep.add(cursor.id);
|
|
@@ -3896,7 +3908,10 @@ function FlowWaterfall({ trace, live, startedAt, label = "Trace waterfall", defa
|
|
|
3896
3908
|
latest.current.pin = (target, element) => {
|
|
3897
3909
|
place(target, element, true);
|
|
3898
3910
|
const row = byId.get(target);
|
|
3899
|
-
if (row)
|
|
3911
|
+
if (row) {
|
|
3912
|
+
onSelect?.(row.span);
|
|
3913
|
+
zoomTo(row);
|
|
3914
|
+
}
|
|
3900
3915
|
};
|
|
3901
3916
|
const pin = useCallback((target, element) => latest.current.pin(target, element), []);
|
|
3902
3917
|
const closeCard = () => {
|
|
@@ -4093,6 +4108,7 @@ function FlowWaterfall({ trace, live, startedAt, label = "Trace waterfall", defa
|
|
|
4093
4108
|
window: win,
|
|
4094
4109
|
trackPx,
|
|
4095
4110
|
showCursor,
|
|
4111
|
+
markers,
|
|
4096
4112
|
zoomed: zoom !== null,
|
|
4097
4113
|
renderIcon,
|
|
4098
4114
|
emptyText: rows.length === 0 ? "No spans yet. Waiting for trace events." : `No matching steps for “${query}”.`,
|
|
@@ -4106,7 +4122,10 @@ function FlowWaterfall({ trace, live, startedAt, label = "Trace waterfall", defa
|
|
|
4106
4122
|
onZoom: zoomBy,
|
|
4107
4123
|
onPan: pan,
|
|
4108
4124
|
nameWidth,
|
|
4109
|
-
onNameWidth: (px) =>
|
|
4125
|
+
onNameWidth: (px) => {
|
|
4126
|
+
resized.current = true;
|
|
4127
|
+
setNameWidth(Math.max(140, Math.min(560, px)));
|
|
4128
|
+
},
|
|
4110
4129
|
onTrack: setLaneElement,
|
|
4111
4130
|
onExpandAll: rows.some((row) => row.hasChildren) ? () => setCollapsed(/* @__PURE__ */ new Set()) : void 0,
|
|
4112
4131
|
onCollapseAll: () => setCollapsed(new Set(rows.filter((row) => row.hasChildren).map((row) => row.id)))
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tangle-network/charts",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.17.1",
|
|
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",
|