@tangle-network/agent-app 0.45.49 → 0.45.50

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.
@@ -13,6 +13,9 @@ import {
13
13
  usePending,
14
14
  usePopover
15
15
  } from "./chunk-CJHIAZKK.js";
16
+ import {
17
+ AsyncView
18
+ } from "./chunk-3UBAO3N5.js";
16
19
  import {
17
20
  UNTITLED_SESSION_LABEL,
18
21
  mergeSessionPages,
@@ -37,7 +40,7 @@ import {
37
40
  } from "./chunk-YJMCRXQQ.js";
38
41
 
39
42
  // src/web-react/index.tsx
40
- import { useEffect as useEffect11, useMemo as useMemo7, useRef as useRef11, useState as useState14, memo } from "react";
43
+ import { useEffect as useEffect12, useMemo as useMemo7, useRef as useRef12, useState as useState15, memo } from "react";
41
44
  import { InlineToolItem } from "@tangle-network/ui/run";
42
45
 
43
46
  // src/web-react/smooth-text.ts
@@ -5243,8 +5246,597 @@ function DraftField({ column, id, value, invalid, describedBy, onValue }) {
5243
5246
  );
5244
5247
  }
5245
5248
 
5249
+ // src/web-react/class-names.ts
5250
+ function joinClasses(...parts) {
5251
+ const kept = [];
5252
+ for (const part of parts) {
5253
+ if (typeof part !== "string") continue;
5254
+ const trimmed = part.trim();
5255
+ if (trimmed.length > 0) kept.push(trimmed);
5256
+ }
5257
+ return kept.join(" ");
5258
+ }
5259
+
5260
+ // src/web-react/sparkline.tsx
5261
+ import { jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
5262
+ var DEFAULT_SPARKLINE_WIDTH = 96;
5263
+ var DEFAULT_SPARKLINE_HEIGHT = 24;
5264
+ var DEFAULT_INSET = 2.5;
5265
+ var STROKE_WIDTH = 1.5;
5266
+ var DOT_RADIUS = 1.75;
5267
+ var DEFAULT_SPARKLINE_LABEL = "Trend";
5268
+ var DEFAULT_SPARKLINE_EMPTY_LABEL = "No history yet";
5269
+ var DEFAULT_SPARKLINE_UNAVAILABLE_LABEL = "No readings available";
5270
+ var NUMBER_FORMAT = new Intl.NumberFormat("en-US", { maximumFractionDigits: 2 });
5271
+ function formatSparklineValue(value) {
5272
+ return NUMBER_FORMAT.format(value);
5273
+ }
5274
+ function isReading(value) {
5275
+ return typeof value === "number" && Number.isFinite(value);
5276
+ }
5277
+ function sparklineReadings(values) {
5278
+ return values.filter(isReading);
5279
+ }
5280
+ function round(value) {
5281
+ return Math.round(value * 100) / 100;
5282
+ }
5283
+ function sparklineGeometry(values, { width = DEFAULT_SPARKLINE_WIDTH, height = DEFAULT_SPARKLINE_HEIGHT, inset = DEFAULT_INSET } = {}) {
5284
+ const samples = values.length;
5285
+ const plotted = [];
5286
+ for (let index = 0; index < samples; index += 1) {
5287
+ const value = values[index];
5288
+ if (isReading(value)) plotted.push({ index, value });
5289
+ }
5290
+ const readings = plotted.map((entry) => entry.value);
5291
+ const gaps = samples - readings.length;
5292
+ if (readings.length === 0) {
5293
+ return { readings, points: [], segments: [], gaps, min: 0, max: 0, first: 0, last: 0, direction: "flat" };
5294
+ }
5295
+ let min = readings[0];
5296
+ let max = readings[0];
5297
+ for (const value of readings) {
5298
+ if (value < min) min = value;
5299
+ if (value > max) max = value;
5300
+ }
5301
+ const first = readings[0];
5302
+ const last = readings[readings.length - 1];
5303
+ const span = max - min;
5304
+ const top = inset;
5305
+ const bottom = height - inset;
5306
+ const left = inset;
5307
+ const right = width - inset;
5308
+ const points = plotted.map(({ index, value }) => ({
5309
+ // A series of ONE SAMPLE sits in the middle rather than at the left edge,
5310
+ // where it reads as the start of a line whose rest failed to render. A
5311
+ // single reading among several samples keeps its own position — that is the
5312
+ // one thing that says where in the window the reading is.
5313
+ x: round(samples <= 1 ? width / 2 : left + (right - left) * index / (samples - 1)),
5314
+ // `span === 0` is the stable metric. Mid-height is the honest render of it;
5315
+ // dividing by the span here is the NaN that erases the whole polyline.
5316
+ y: round(span === 0 ? height / 2 : bottom - (bottom - top) * (value - min) / span)
5317
+ }));
5318
+ const segments = [];
5319
+ let run = [];
5320
+ let previous = Number.NEGATIVE_INFINITY;
5321
+ plotted.forEach(({ index }, position) => {
5322
+ if (index !== previous + 1 && run.length > 0) {
5323
+ segments.push(run);
5324
+ run = [];
5325
+ }
5326
+ run.push(points[position]);
5327
+ previous = index;
5328
+ });
5329
+ if (run.length > 0) segments.push(run);
5330
+ return {
5331
+ readings,
5332
+ points,
5333
+ segments,
5334
+ gaps,
5335
+ min,
5336
+ max,
5337
+ first,
5338
+ last,
5339
+ direction: last > first ? "rising" : last < first ? "falling" : "flat"
5340
+ };
5341
+ }
5342
+ function sparklinePointsAttribute(points) {
5343
+ return points.map((point) => `${point.x},${point.y}`).join(" ");
5344
+ }
5345
+ function sparklineLabel(values, { label = DEFAULT_SPARKLINE_LABEL, format = formatSparklineValue } = {}) {
5346
+ const { readings, gaps, min, max, first, last, direction } = sparklineGeometry(values);
5347
+ const missing = gaps === 0 ? "" : `, ${gaps} not available`;
5348
+ if (readings.length === 0) return gaps === 0 ? `${label}: no readings yet` : `${label}: no readings${missing}`;
5349
+ if (readings.length === 1) return `${label}: one reading${missing}, ${format(first)}`;
5350
+ if (max === min) return `${label}: ${readings.length} readings${missing}, unchanged at ${format(first)}`;
5351
+ const movement = direction === "flat" ? "net unchanged" : direction;
5352
+ return `${label}: ${readings.length} readings${missing}, range ${format(min)} to ${format(max)}, ${movement} from ${format(first)} to ${format(last)}`;
5353
+ }
5354
+ function Sparkline({
5355
+ values,
5356
+ label = DEFAULT_SPARKLINE_LABEL,
5357
+ format = formatSparklineValue,
5358
+ width = DEFAULT_SPARKLINE_WIDTH,
5359
+ height = DEFAULT_SPARKLINE_HEIGHT,
5360
+ emptyLabel = DEFAULT_SPARKLINE_EMPTY_LABEL,
5361
+ unavailableLabel = DEFAULT_SPARKLINE_UNAVAILABLE_LABEL,
5362
+ className
5363
+ }) {
5364
+ const geometry = sparklineGeometry(values, { width, height });
5365
+ const accessibleName = sparklineLabel(values, { label, format });
5366
+ if (geometry.points.length === 0) {
5367
+ return /* @__PURE__ */ jsxs11(
5368
+ "span",
5369
+ {
5370
+ "data-sparkline": geometry.gaps > 0 ? "unavailable" : "empty",
5371
+ className: joinClasses("text-[11px] text-muted-foreground", className),
5372
+ children: [
5373
+ /* @__PURE__ */ jsx13("span", { className: "sr-only", children: accessibleName }),
5374
+ /* @__PURE__ */ jsx13("span", { "aria-hidden": "true", children: geometry.gaps > 0 ? unavailableLabel : emptyLabel })
5375
+ ]
5376
+ }
5377
+ );
5378
+ }
5379
+ const drawsLine = geometry.segments.some((segment) => segment.length > 1);
5380
+ const end = geometry.points[geometry.points.length - 1];
5381
+ return /* @__PURE__ */ jsxs11(
5382
+ "svg",
5383
+ {
5384
+ role: "img",
5385
+ "aria-label": accessibleName,
5386
+ "data-sparkline": drawsLine ? "line" : "point",
5387
+ "data-direction": geometry.direction,
5388
+ "data-gaps": geometry.gaps > 0 ? geometry.gaps : void 0,
5389
+ width,
5390
+ height,
5391
+ viewBox: `0 0 ${width} ${height}`,
5392
+ className,
5393
+ focusable: "false",
5394
+ children: [
5395
+ geometry.segments.map((segment, index) => {
5396
+ const key = `segment-${index}`;
5397
+ if (segment.length > 1) {
5398
+ return /* @__PURE__ */ jsx13(
5399
+ "polyline",
5400
+ {
5401
+ points: sparklinePointsAttribute(segment),
5402
+ fill: "none",
5403
+ stroke: "currentColor",
5404
+ strokeWidth: STROKE_WIDTH,
5405
+ strokeLinecap: "round",
5406
+ strokeLinejoin: "round",
5407
+ vectorEffect: "non-scaling-stroke"
5408
+ },
5409
+ key
5410
+ );
5411
+ }
5412
+ const only = segment[0];
5413
+ if (only.x === end.x && only.y === end.y) return null;
5414
+ return /* @__PURE__ */ jsx13("circle", { cx: only.x, cy: only.y, r: DOT_RADIUS, fill: "currentColor" }, key);
5415
+ }),
5416
+ /* @__PURE__ */ jsx13("circle", { cx: end.x, cy: end.y, r: DOT_RADIUS, fill: "currentColor" })
5417
+ ]
5418
+ }
5419
+ );
5420
+ }
5421
+
5422
+ // src/web-react/insight-card.tsx
5423
+ import {
5424
+ isValidElement as isValidElement2,
5425
+ useCallback as useCallback10,
5426
+ useEffect as useEffect11,
5427
+ useRef as useRef11,
5428
+ useState as useState14
5429
+ } from "react";
5430
+ import { Fragment as Fragment7, jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
5431
+ function insightDelta(value, previous) {
5432
+ if (typeof value !== "number" || !Number.isFinite(value)) return null;
5433
+ if (typeof previous !== "number" || !Number.isFinite(previous)) return null;
5434
+ const absolute = value - previous;
5435
+ return {
5436
+ previous,
5437
+ absolute,
5438
+ percent: previous === 0 ? null : absolute / previous,
5439
+ direction: absolute > 0 ? "up" : absolute < 0 ? "down" : "flat"
5440
+ };
5441
+ }
5442
+ function insightDeltaTone(direction, polarity = "neutral") {
5443
+ if (direction === "flat" || polarity === "neutral") return "neutral";
5444
+ const welcome = polarity === "higher-is-better" ? "up" : "down";
5445
+ return direction === welcome ? "positive" : "negative";
5446
+ }
5447
+ function formatInsightDelta(delta, format = formatSparklineValue) {
5448
+ const from = format(delta.previous);
5449
+ if (delta.direction === "flat") return `No change from ${from}`;
5450
+ const word = delta.direction === "up" ? "Up" : "Down";
5451
+ const magnitude = delta.percent === null ? format(Math.abs(delta.absolute)) : `${(Math.abs(delta.percent) * 100).toFixed(1)}%`;
5452
+ return `${word} ${magnitude} from ${from}`;
5453
+ }
5454
+ var TONE_CLASS = {
5455
+ positive: "text-success",
5456
+ negative: "text-destructive",
5457
+ neutral: "text-muted-foreground"
5458
+ };
5459
+ var DIRECTION_GLYPH = { up: "\u2191", down: "\u2193", flat: "\u2192" };
5460
+ var INSIGHT_UNAVAILABLE_GLYPH = "\u2014";
5461
+ var INSIGHT_UNAVAILABLE_LABEL = "Not available";
5462
+ function InsightCard({
5463
+ title,
5464
+ value,
5465
+ unit,
5466
+ previous,
5467
+ polarity = "neutral",
5468
+ format = formatSparklineValue,
5469
+ series,
5470
+ seriesLabel,
5471
+ description,
5472
+ action,
5473
+ live = false,
5474
+ liveLabel = "Updating",
5475
+ className,
5476
+ style
5477
+ }) {
5478
+ const delta = insightDelta(value, previous);
5479
+ const tone = delta ? insightDeltaTone(delta.direction, polarity) : "neutral";
5480
+ const unavailable = typeof value === "number" && !Number.isFinite(value);
5481
+ const shown = typeof value === "number" ? format(value) : value;
5482
+ return /* @__PURE__ */ jsxs12(
5483
+ "article",
5484
+ {
5485
+ "data-insight-card": "",
5486
+ "data-tone": tone,
5487
+ className: joinClasses("agent-arrive flex h-full flex-col rounded-xl border border-card-edge bg-card p-4", className),
5488
+ style,
5489
+ children: [
5490
+ /* @__PURE__ */ jsxs12("div", { className: "flex items-baseline justify-between gap-2", children: [
5491
+ /* @__PURE__ */ jsx14("h3", { className: "text-[13px] font-medium text-muted-foreground", children: title }),
5492
+ live ? (
5493
+ // No `data-motion` opt-out: the word is the signal and the sweep is
5494
+ // emphasis, so the reduced-motion floor reaches this like everything
5495
+ // else and leaves a static, legible label.
5496
+ /* @__PURE__ */ jsx14("span", { className: "agent-shimmer shrink-0 text-[11px] font-medium", "data-insight-live": "", children: liveLabel })
5497
+ ) : null
5498
+ ] }),
5499
+ /* @__PURE__ */ jsx14("p", { className: "mt-1 flex items-baseline gap-1", children: unavailable ? /* @__PURE__ */ jsxs12("span", { "data-insight-value": "unavailable", className: "text-xl font-semibold text-muted-foreground", children: [
5500
+ /* @__PURE__ */ jsx14("span", { "aria-hidden": "true", children: INSIGHT_UNAVAILABLE_GLYPH }),
5501
+ /* @__PURE__ */ jsx14("span", { className: "sr-only", children: INSIGHT_UNAVAILABLE_LABEL })
5502
+ ] }) : /* @__PURE__ */ jsxs12(Fragment7, { children: [
5503
+ /* @__PURE__ */ jsx14("span", { className: "text-xl font-semibold tabular-nums text-foreground", children: shown }),
5504
+ unit ? /* @__PURE__ */ jsx14("span", { className: "text-[11px] text-muted-foreground", children: unit }) : null
5505
+ ] }) }),
5506
+ delta ? /* @__PURE__ */ jsxs12("p", { "data-insight-delta": delta.direction, className: `mt-0.5 text-[11px] font-medium ${TONE_CLASS[tone]}`, children: [
5507
+ /* @__PURE__ */ jsxs12("span", { "aria-hidden": "true", children: [
5508
+ DIRECTION_GLYPH[delta.direction],
5509
+ " "
5510
+ ] }),
5511
+ formatInsightDelta(delta, format)
5512
+ ] }) : null,
5513
+ description ? /* @__PURE__ */ jsx14("p", { className: "mt-1 text-[11px] text-muted-foreground", children: description }) : null,
5514
+ series ? /* @__PURE__ */ jsx14("div", { className: "mt-2 text-muted-foreground", children: /* @__PURE__ */ jsx14(Sparkline, { values: series, label: seriesLabel ?? title, format }) }) : null,
5515
+ action ? /* @__PURE__ */ jsx14("div", { className: "mt-3", children: renderInsightAction(action) }) : null
5516
+ ]
5517
+ }
5518
+ );
5519
+ }
5520
+ function renderInsightAction(action) {
5521
+ if (isValidElement2(action)) return action;
5522
+ return /* @__PURE__ */ jsx14(
5523
+ "button",
5524
+ {
5525
+ type: "button",
5526
+ onClick: action.onClick,
5527
+ className: "h-8 rounded-md border border-border px-3 text-xs font-medium text-foreground transition hover:bg-accent",
5528
+ children: action.label
5529
+ }
5530
+ );
5531
+ }
5532
+ var DEFAULT_INSIGHT_PAGE_SIZE = 3;
5533
+ var MAX_PAGE_DOTS = 8;
5534
+ var PAGE_SIZE_FAULT_REASON = {
5535
+ "not-a-number": "A page size that is not a number cannot count cards at all.",
5536
+ "below-one": "A page size below one card gives the deck a page nothing fits on.",
5537
+ fractional: "A fractional page size hides cards on no page at all."
5538
+ };
5539
+ var MAX_NAMED_PAGE_SIZES = 8;
5540
+ var warnedPageSizes = {
5541
+ "not-a-number": { named: /* @__PURE__ */ new Set(), latched: false },
5542
+ "below-one": { named: /* @__PURE__ */ new Set(), latched: false },
5543
+ fractional: { named: /* @__PURE__ */ new Set(), latched: false }
5544
+ };
5545
+ function pageSizeFault(pageSize) {
5546
+ if (!Number.isFinite(pageSize)) return "not-a-number";
5547
+ if (pageSize < 1) return "below-one";
5548
+ return "fractional";
5549
+ }
5550
+ function warnPageSize(pageSize) {
5551
+ const fault = pageSizeFault(pageSize);
5552
+ const record = warnedPageSizes[fault];
5553
+ if (record.latched || record.named.has(pageSize)) return;
5554
+ record.named.add(pageSize);
5555
+ console.warn(
5556
+ `[insight-card] pageSize must be a whole number of cards, 1 or more \u2014 received ${String(pageSize)}. Using ${DEFAULT_INSIGHT_PAGE_SIZE}. ${PAGE_SIZE_FAULT_REASON[fault]}`
5557
+ );
5558
+ if (record.named.size >= MAX_NAMED_PAGE_SIZES) {
5559
+ record.named.clear();
5560
+ record.latched = true;
5561
+ console.warn(`[insight-card] further "${fault}" pageSize warnings are suppressed.`);
5562
+ }
5563
+ }
5564
+ function insightPageSize(pageSize = DEFAULT_INSIGHT_PAGE_SIZE) {
5565
+ if (Number.isInteger(pageSize) && pageSize >= 1) return pageSize;
5566
+ warnPageSize(pageSize);
5567
+ return DEFAULT_INSIGHT_PAGE_SIZE;
5568
+ }
5569
+ function insightPageCount(total, pageSize = DEFAULT_INSIGHT_PAGE_SIZE) {
5570
+ const size = insightPageSize(pageSize);
5571
+ const counted = Number.isFinite(total) && total > 0 ? total : 0;
5572
+ return Math.max(1, Math.ceil(counted / size));
5573
+ }
5574
+ function insightPageSlice(items, page, pageSize = DEFAULT_INSIGHT_PAGE_SIZE) {
5575
+ const size = insightPageSize(pageSize);
5576
+ const count = insightPageCount(items.length, size);
5577
+ const requested = Number.isFinite(page) ? Math.floor(page) : 0;
5578
+ const safe = Math.min(Math.max(requested, 0), count - 1);
5579
+ return items.slice(safe * size, safe * size + size);
5580
+ }
5581
+ function staggerStyle(index, base) {
5582
+ return { ...base, "--stagger-index": index };
5583
+ }
5584
+ function InsightDeck({
5585
+ state,
5586
+ empty,
5587
+ label = "Insights",
5588
+ pageSize = DEFAULT_INSIGHT_PAGE_SIZE,
5589
+ loadingLabel = "Loading insights\u2026",
5590
+ retryLabel,
5591
+ className,
5592
+ onPageChange
5593
+ }) {
5594
+ const [page, setPage] = useState14(0);
5595
+ const [held, setHeld] = useState14(null);
5596
+ const answered = state.status === "error" || state.status === "empty";
5597
+ const carried = state.status === "ready" ? state.value : answered ? null : held;
5598
+ if (carried !== held) setHeld(carried);
5599
+ const shown = carried !== null && state.status !== "ready" ? { status: "ready", value: carried, retry: state.retry } : state;
5600
+ const refreshing = shown !== state;
5601
+ const reported = useRef11(0);
5602
+ const settlePage = useCallback10(
5603
+ (next) => {
5604
+ if (reported.current === next) return;
5605
+ reported.current = next;
5606
+ onPageChange?.(next);
5607
+ },
5608
+ [onPageChange]
5609
+ );
5610
+ return /* @__PURE__ */ jsx14(
5611
+ AsyncView,
5612
+ {
5613
+ state: shown,
5614
+ empty,
5615
+ loadingLabel,
5616
+ retryLabel,
5617
+ className,
5618
+ children: (insights) => /* @__PURE__ */ jsx14(
5619
+ InsightPages,
5620
+ {
5621
+ insights,
5622
+ label,
5623
+ pageSize,
5624
+ className,
5625
+ page,
5626
+ busy: refreshing,
5627
+ onSelectPage: setPage,
5628
+ onPageSettled: settlePage
5629
+ }
5630
+ )
5631
+ }
5632
+ );
5633
+ }
5634
+ var EDITABLE_TAG = /^(INPUT|TEXTAREA|SELECT)$/;
5635
+ var ARROW_KEY_ROLES = /* @__PURE__ */ new Set([
5636
+ "application",
5637
+ "combobox",
5638
+ "grid",
5639
+ "gridcell",
5640
+ "listbox",
5641
+ "menu",
5642
+ "menubar",
5643
+ "menuitem",
5644
+ "menuitemcheckbox",
5645
+ "menuitemradio",
5646
+ "option",
5647
+ "radiogroup",
5648
+ "row",
5649
+ "scrollbar",
5650
+ "searchbox",
5651
+ "slider",
5652
+ "spinbutton",
5653
+ "tab",
5654
+ "tablist",
5655
+ "textbox",
5656
+ "tree",
5657
+ "treegrid",
5658
+ "treeitem"
5659
+ ]);
5660
+ function ownsArrowKeys(target, boundary) {
5661
+ let node = target instanceof Element ? target : null;
5662
+ while (node !== null && node !== boundary) {
5663
+ if (EDITABLE_TAG.test(node.tagName)) return true;
5664
+ if (node instanceof HTMLElement && node.isContentEditable) return true;
5665
+ const role = node.getAttribute("role");
5666
+ if (role !== null && role.split(/\s+/).some((token) => ARROW_KEY_ROLES.has(token))) return true;
5667
+ node = node.parentElement;
5668
+ }
5669
+ return false;
5670
+ }
5671
+ function InsightPages({
5672
+ insights,
5673
+ label,
5674
+ pageSize,
5675
+ className,
5676
+ page,
5677
+ busy,
5678
+ onSelectPage,
5679
+ onPageSettled
5680
+ }) {
5681
+ const size = insightPageSize(pageSize);
5682
+ const pageCount = insightPageCount(insights.length, size);
5683
+ const current = Math.min(Math.max(page, 0), pageCount - 1);
5684
+ const visible = insightPageSlice(insights, current, size);
5685
+ const sectionRef = useRef11(null);
5686
+ const listRef = useRef11(null);
5687
+ const recoverFocus = useRef11(false);
5688
+ useEffect11(() => {
5689
+ onPageSettled(current);
5690
+ }, [current, onPageSettled]);
5691
+ useEffect11(() => {
5692
+ if (!recoverFocus.current) return;
5693
+ recoverFocus.current = false;
5694
+ sectionRef.current?.focus();
5695
+ }, [current]);
5696
+ const goTo = useCallback10(
5697
+ (next) => {
5698
+ const clamped = Math.min(Math.max(next, 0), pageCount - 1);
5699
+ if (clamped === current) return false;
5700
+ const active = typeof document === "undefined" ? null : document.activeElement;
5701
+ recoverFocus.current = active instanceof Node && (listRef.current?.contains(active) ?? false);
5702
+ onSelectPage(clamped);
5703
+ return true;
5704
+ },
5705
+ [current, onSelectPage, pageCount]
5706
+ );
5707
+ const onKeyDown = (event) => {
5708
+ if (event.defaultPrevented) return;
5709
+ if (ownsArrowKeys(event.target, event.currentTarget)) return;
5710
+ let moved = false;
5711
+ switch (event.key) {
5712
+ case "ArrowRight":
5713
+ case "PageDown":
5714
+ moved = goTo(current + 1);
5715
+ break;
5716
+ case "ArrowLeft":
5717
+ case "PageUp":
5718
+ moved = goTo(current - 1);
5719
+ break;
5720
+ case "Home":
5721
+ moved = goTo(0);
5722
+ break;
5723
+ case "End":
5724
+ moved = goTo(pageCount - 1);
5725
+ break;
5726
+ default:
5727
+ return;
5728
+ }
5729
+ if (moved) event.preventDefault();
5730
+ };
5731
+ return /* @__PURE__ */ jsxs12(
5732
+ "section",
5733
+ {
5734
+ ref: sectionRef,
5735
+ "aria-label": label,
5736
+ "data-insight-deck": "",
5737
+ "aria-busy": busy,
5738
+ className: joinClasses("space-y-3", className),
5739
+ onKeyDown,
5740
+ tabIndex: pageCount > 1 ? 0 : void 0,
5741
+ "aria-keyshortcuts": pageCount > 1 ? "ArrowLeft ArrowRight PageUp PageDown Home End" : void 0,
5742
+ children: [
5743
+ /* @__PURE__ */ jsx14("ul", { ref: listRef, className: "grid gap-3 sm:grid-cols-2 lg:grid-cols-3", children: visible.map(({ id, style, ...card }, index) => (
5744
+ // The page index is in the key on purpose: a page turn is an arrival,
5745
+ // and reusing the node would swap the text under a card that never
5746
+ // moved. Remounting replays `.agent-arrive` with the new stagger.
5747
+ //
5748
+ // A REFRESH is the other case and the key is why it behaves the other
5749
+ // way: the page has not changed and the id is stable, so the key
5750
+ // matches, React keeps the node, and a card that was already settled
5751
+ // does not arrive a second time. The key does BOTH jobs — but only
5752
+ // because the deck now keeps this subtree mounted across a reload
5753
+ // (see `InsightDeck`); a key is never compared across a teardown.
5754
+ /* @__PURE__ */ jsx14("li", { children: /* @__PURE__ */ jsx14(InsightCard, { ...card, style: staggerStyle(index, style) }) }, `${current}:${id}`)
5755
+ )) }),
5756
+ /* @__PURE__ */ jsxs12("div", { className: pageCount > 1 ? "flex items-center justify-between gap-2" : void 0, children: [
5757
+ /* @__PURE__ */ jsxs12(
5758
+ "p",
5759
+ {
5760
+ role: "status",
5761
+ "aria-live": "polite",
5762
+ className: pageCount > 1 ? "text-[11px] text-muted-foreground" : "sr-only",
5763
+ children: [
5764
+ "Page ",
5765
+ current + 1,
5766
+ " of ",
5767
+ pageCount
5768
+ ]
5769
+ }
5770
+ ),
5771
+ pageCount > 1 ? /* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-1", children: [
5772
+ /* @__PURE__ */ jsx14(PagerButton, { label: "Previous insights", glyph: "\u2039", atEnd: current === 0, onClick: () => goTo(current - 1) }),
5773
+ pageCount <= MAX_PAGE_DOTS ? Array.from({ length: pageCount }, (_, index) => (
5774
+ // WCAG 2.2 SC 2.5.8 wants a 24x24 CSS px target. The dot stays
5775
+ // 8px because a 24px dot is a different control; the BUTTON
5776
+ // around it carries the target, so the padding is the hit area
5777
+ // and the span is the graphic. The Spacing exception cannot
5778
+ // rescue the bare dot — at a 12px pitch the 24px circle around
5779
+ // each centre overlaps its neighbour's.
5780
+ /* @__PURE__ */ jsx14(
5781
+ "button",
5782
+ {
5783
+ type: "button",
5784
+ "aria-label": `Page ${index + 1} of ${pageCount}`,
5785
+ "aria-current": index === current ? "page" : void 0,
5786
+ onClick: () => goTo(index),
5787
+ className: "group flex h-6 w-6 shrink-0 items-center justify-center rounded-full",
5788
+ children: /* @__PURE__ */ jsx14(
5789
+ "span",
5790
+ {
5791
+ "aria-hidden": "true",
5792
+ className: joinClasses(
5793
+ "block rounded-full transition",
5794
+ index === current ? "h-2 w-4 bg-foreground" : "h-2 w-2 bg-muted-foreground group-hover:bg-foreground"
5795
+ )
5796
+ }
5797
+ )
5798
+ },
5799
+ index
5800
+ )
5801
+ )) : null,
5802
+ /* @__PURE__ */ jsx14(
5803
+ PagerButton,
5804
+ {
5805
+ label: "Next insights",
5806
+ glyph: "\u203A",
5807
+ atEnd: current === pageCount - 1,
5808
+ onClick: () => goTo(current + 1)
5809
+ }
5810
+ )
5811
+ ] }) : null
5812
+ ] })
5813
+ ]
5814
+ }
5815
+ );
5816
+ }
5817
+ function PagerButton({
5818
+ label,
5819
+ glyph,
5820
+ atEnd,
5821
+ onClick
5822
+ }) {
5823
+ return /* @__PURE__ */ jsx14(
5824
+ "button",
5825
+ {
5826
+ type: "button",
5827
+ "aria-label": label,
5828
+ "aria-disabled": atEnd,
5829
+ onClick: () => {
5830
+ if (!atEnd) onClick();
5831
+ },
5832
+ className: `flex h-6 w-6 items-center justify-center rounded-md border border-border text-xs text-muted-foreground transition ${atEnd ? "opacity-40" : "hover:bg-accent hover:text-foreground"}`,
5833
+ children: /* @__PURE__ */ jsx14("span", { "aria-hidden": "true", children: glyph })
5834
+ }
5835
+ );
5836
+ }
5837
+
5246
5838
  // src/web-react/index.tsx
5247
- import { Fragment as Fragment7, jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
5839
+ import { Fragment as Fragment8, jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
5248
5840
  function formatModelCost(msg, models) {
5249
5841
  if (msg.promptTokens == null && msg.completionTokens == null) return null;
5250
5842
  const pricing = models.find((m) => m.id === msg.modelUsed)?.pricing;
@@ -5258,41 +5850,41 @@ function formatTokensPerSecond(msg) {
5258
5850
  return `${Math.round(msg.completionTokens / (msg.durationMs / 1e3))} tok/s`;
5259
5851
  }
5260
5852
  function RunDrillIn({ run, onClose }) {
5261
- return /* @__PURE__ */ jsxs11("div", { className: `fixed inset-y-0 right-0 z-50 flex w-[480px] max-w-full flex-col border-l border-card-edge bg-popover ${OVERLAY_SHADOW}`, children: [
5262
- /* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-2 border-b border-border px-4 py-3", children: [
5263
- /* @__PURE__ */ jsx13(
5853
+ return /* @__PURE__ */ jsxs13("div", { className: `fixed inset-y-0 right-0 z-50 flex w-[480px] max-w-full flex-col border-l border-card-edge bg-popover ${OVERLAY_SHADOW}`, children: [
5854
+ /* @__PURE__ */ jsxs13("div", { className: "flex items-center gap-2 border-b border-border px-4 py-3", children: [
5855
+ /* @__PURE__ */ jsx15(
5264
5856
  "span",
5265
5857
  {
5266
5858
  className: `h-2 w-2 shrink-0 rounded-full ${run.status === "running" ? "bg-warning" : run.status === "error" ? "bg-destructive" : "bg-success"}`
5267
5859
  }
5268
5860
  ),
5269
- /* @__PURE__ */ jsxs11("div", { className: "min-w-0 flex-1", children: [
5270
- /* @__PURE__ */ jsx13("p", { className: "truncate text-[15px] font-semibold", children: run.title }),
5271
- /* @__PURE__ */ jsx13("p", { className: "truncate font-mono text-xs text-muted-foreground", children: run.toolName })
5861
+ /* @__PURE__ */ jsxs13("div", { className: "min-w-0 flex-1", children: [
5862
+ /* @__PURE__ */ jsx15("p", { className: "truncate text-[15px] font-semibold", children: run.title }),
5863
+ /* @__PURE__ */ jsx15("p", { className: "truncate font-mono text-xs text-muted-foreground", children: run.toolName })
5272
5864
  ] }),
5273
- /* @__PURE__ */ jsx13(
5865
+ /* @__PURE__ */ jsx15(
5274
5866
  "button",
5275
5867
  {
5276
5868
  type: "button",
5277
5869
  onClick: onClose,
5278
5870
  "aria-label": "Close",
5279
5871
  className: "rounded-md p-1.5 text-muted-foreground transition hover:bg-accent hover:text-foreground",
5280
- children: /* @__PURE__ */ jsx13("svg", { className: "h-4 w-4", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", "aria-hidden": true, children: /* @__PURE__ */ jsx13("path", { d: "M18 6 6 18M6 6l12 12" }) })
5872
+ children: /* @__PURE__ */ jsx15("svg", { className: "h-4 w-4", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", "aria-hidden": true, children: /* @__PURE__ */ jsx15("path", { d: "M18 6 6 18M6 6l12 12" }) })
5281
5873
  }
5282
5874
  )
5283
5875
  ] }),
5284
- /* @__PURE__ */ jsxs11("div", { className: "flex-1 space-y-3 overflow-y-auto p-4", children: [
5285
- run.steps.length === 0 && /* @__PURE__ */ jsx13("p", { className: "text-sm text-muted-foreground", children: "No steps recorded yet." }),
5286
- run.steps.map((step, i) => /* @__PURE__ */ jsxs11("div", { className: "rounded-lg border border-card-edge bg-card", children: [
5287
- /* @__PURE__ */ jsxs11("div", { className: "flex items-baseline gap-2 border-b border-border px-3 py-1.5", children: [
5288
- /* @__PURE__ */ jsx13("span", { className: `font-mono text-xs ${step.status === "error" ? "text-destructive" : "text-muted-foreground"}`, children: step.status === "error" ? "\u2717" : "$" }),
5289
- /* @__PURE__ */ jsx13("code", { className: "min-w-0 flex-1 truncate font-mono text-xs", children: step.label }),
5290
- /* @__PURE__ */ jsx13("span", { className: "shrink-0 text-xs tabular-nums text-muted-foreground", children: new Date(step.at).toLocaleTimeString([], { hour: "numeric", minute: "2-digit" }) })
5876
+ /* @__PURE__ */ jsxs13("div", { className: "flex-1 space-y-3 overflow-y-auto p-4", children: [
5877
+ run.steps.length === 0 && /* @__PURE__ */ jsx15("p", { className: "text-sm text-muted-foreground", children: "No steps recorded yet." }),
5878
+ run.steps.map((step, i) => /* @__PURE__ */ jsxs13("div", { className: "rounded-lg border border-card-edge bg-card", children: [
5879
+ /* @__PURE__ */ jsxs13("div", { className: "flex items-baseline gap-2 border-b border-border px-3 py-1.5", children: [
5880
+ /* @__PURE__ */ jsx15("span", { className: `font-mono text-xs ${step.status === "error" ? "text-destructive" : "text-muted-foreground"}`, children: step.status === "error" ? "\u2717" : "$" }),
5881
+ /* @__PURE__ */ jsx15("code", { className: "min-w-0 flex-1 truncate font-mono text-xs", children: step.label }),
5882
+ /* @__PURE__ */ jsx15("span", { className: "shrink-0 text-xs tabular-nums text-muted-foreground", children: new Date(step.at).toLocaleTimeString([], { hour: "numeric", minute: "2-digit" }) })
5291
5883
  ] }),
5292
- step.detail && /* @__PURE__ */ jsx13("pre", { className: "max-h-48 overflow-auto whitespace-pre-wrap px-3 py-2 font-mono text-xs leading-relaxed text-muted-foreground", children: step.detail })
5884
+ step.detail && /* @__PURE__ */ jsx15("pre", { className: "max-h-48 overflow-auto whitespace-pre-wrap px-3 py-2 font-mono text-xs leading-relaxed text-muted-foreground", children: step.detail })
5293
5885
  ] }, i))
5294
5886
  ] }),
5295
- /* @__PURE__ */ jsx13("p", { className: "border-t border-border px-4 py-2 text-xs text-muted-foreground", children: "Read-only transcript \u2014 reply in the main chat." })
5887
+ /* @__PURE__ */ jsx15("p", { className: "border-t border-border px-4 py-2 text-xs text-muted-foreground", children: "Read-only transcript \u2014 reply in the main chat." })
5296
5888
  ] });
5297
5889
  }
5298
5890
  function pendingApprovalOf(call) {
@@ -5308,23 +5900,23 @@ function ChatEmptyState({
5308
5900
  }) {
5309
5901
  const doorCount = Math.min(doors?.length ?? 0, 3);
5310
5902
  const doorsGridClass = doorCount === 1 ? "mx-auto max-w-sm sm:grid-cols-1" : doorCount === 2 ? "sm:grid-cols-2" : "sm:grid-cols-3";
5311
- return /* @__PURE__ */ jsxs11("div", { className: "mx-auto flex w-full max-w-2xl flex-col items-center px-6 py-12 text-center sm:py-20", children: [
5312
- /* @__PURE__ */ jsx13("span", { className: "mb-5 inline-flex h-14 w-14 items-center justify-center rounded-2xl bg-primary/10 ring-1 ring-primary/15", children: /* @__PURE__ */ jsx13(BrandMark, { size: 32, className: "shrink-0" }) }),
5313
- /* @__PURE__ */ jsx13("p", { className: "text-xs font-semibold uppercase tracking-[0.05em] text-muted-foreground", children: productName }),
5314
- /* @__PURE__ */ jsx13("h2", { className: "mt-1.5 text-balance text-2xl font-semibold leading-tight text-foreground", children: headline }),
5315
- subline && /* @__PURE__ */ jsx13("p", { className: "mt-3 max-w-md text-[15px] leading-relaxed text-muted-foreground", children: subline }),
5316
- doors && doors.length > 0 && /* @__PURE__ */ jsx13("div", { className: `mt-7 grid w-full gap-2.5 ${doorsGridClass}`, children: doors.slice(0, 3).map((door, i) => /* @__PURE__ */ jsxs11(
5903
+ return /* @__PURE__ */ jsxs13("div", { className: "mx-auto flex w-full max-w-2xl flex-col items-center px-6 py-12 text-center sm:py-20", children: [
5904
+ /* @__PURE__ */ jsx15("span", { className: "mb-5 inline-flex h-14 w-14 items-center justify-center rounded-2xl bg-primary/10 ring-1 ring-primary/15", children: /* @__PURE__ */ jsx15(BrandMark, { size: 32, className: "shrink-0" }) }),
5905
+ /* @__PURE__ */ jsx15("p", { className: "text-xs font-semibold uppercase tracking-[0.05em] text-muted-foreground", children: productName }),
5906
+ /* @__PURE__ */ jsx15("h2", { className: "mt-1.5 text-balance text-2xl font-semibold leading-tight text-foreground", children: headline }),
5907
+ subline && /* @__PURE__ */ jsx15("p", { className: "mt-3 max-w-md text-[15px] leading-relaxed text-muted-foreground", children: subline }),
5908
+ doors && doors.length > 0 && /* @__PURE__ */ jsx15("div", { className: `mt-7 grid w-full gap-2.5 ${doorsGridClass}`, children: doors.slice(0, 3).map((door, i) => /* @__PURE__ */ jsxs13(
5317
5909
  "button",
5318
5910
  {
5319
5911
  type: "button",
5320
5912
  onClick: door.onSelect,
5321
5913
  className: "group flex min-h-[44px] flex-col items-start rounded-xl border border-border bg-card px-4 py-3 text-left transition hover:border-primary/40 hover:bg-accent",
5322
5914
  children: [
5323
- /* @__PURE__ */ jsxs11("span", { className: "flex items-center gap-2 text-sm font-semibold text-foreground", children: [
5915
+ /* @__PURE__ */ jsxs13("span", { className: "flex items-center gap-2 text-sm font-semibold text-foreground", children: [
5324
5916
  door.icon,
5325
5917
  door.label
5326
5918
  ] }),
5327
- door.description && /* @__PURE__ */ jsx13("span", { className: "mt-0.5 text-[12px] leading-snug text-muted-foreground", children: door.description })
5919
+ door.description && /* @__PURE__ */ jsx15("span", { className: "mt-0.5 text-[12px] leading-snug text-muted-foreground", children: door.description })
5328
5920
  ]
5329
5921
  },
5330
5922
  i
@@ -5333,26 +5925,26 @@ function ChatEmptyState({
5333
5925
  }
5334
5926
  function ToolGlyph({ name, className }) {
5335
5927
  if (name.startsWith("sandbox_")) {
5336
- return /* @__PURE__ */ jsxs11("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: [
5337
- /* @__PURE__ */ jsx13("polyline", { points: "4 17 10 11 4 5" }),
5338
- /* @__PURE__ */ jsx13("line", { x1: "12", y1: "19", x2: "20", y2: "19" })
5928
+ return /* @__PURE__ */ jsxs13("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: [
5929
+ /* @__PURE__ */ jsx15("polyline", { points: "4 17 10 11 4 5" }),
5930
+ /* @__PURE__ */ jsx15("line", { x1: "12", y1: "19", x2: "20", y2: "19" })
5339
5931
  ] });
5340
5932
  }
5341
5933
  if (name === "submit_proposal") {
5342
- return /* @__PURE__ */ jsxs11("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: [
5343
- /* @__PURE__ */ jsx13("path", { d: "M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" }),
5344
- /* @__PURE__ */ jsx13("path", { d: "M14 2v6h6M9 15l2 2 4-4" })
5934
+ return /* @__PURE__ */ jsxs13("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: [
5935
+ /* @__PURE__ */ jsx15("path", { d: "M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" }),
5936
+ /* @__PURE__ */ jsx15("path", { d: "M14 2v6h6M9 15l2 2 4-4" })
5345
5937
  ] });
5346
5938
  }
5347
5939
  if (name === "schedule_followup") {
5348
- return /* @__PURE__ */ jsxs11("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", "aria-hidden": true, children: [
5349
- /* @__PURE__ */ jsx13("circle", { cx: "12", cy: "12", r: "9" }),
5350
- /* @__PURE__ */ jsx13("path", { d: "M12 7v5l3 3" })
5940
+ return /* @__PURE__ */ jsxs13("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", "aria-hidden": true, children: [
5941
+ /* @__PURE__ */ jsx15("circle", { cx: "12", cy: "12", r: "9" }),
5942
+ /* @__PURE__ */ jsx15("path", { d: "M12 7v5l3 3" })
5351
5943
  ] });
5352
5944
  }
5353
- return /* @__PURE__ */ jsxs11("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: [
5354
- /* @__PURE__ */ jsx13("path", { d: "M12 3v3m0 12v3M3 12h3m12 0h3" }),
5355
- /* @__PURE__ */ jsx13("circle", { cx: "12", cy: "12", r: "4" })
5945
+ return /* @__PURE__ */ jsxs13("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: [
5946
+ /* @__PURE__ */ jsx15("path", { d: "M12 3v3m0 12v3M3 12h3m12 0h3" }),
5947
+ /* @__PURE__ */ jsx15("circle", { cx: "12", cy: "12", r: "4" })
5356
5948
  ] });
5357
5949
  }
5358
5950
  function toolOutcomeOf(call) {
@@ -5438,40 +6030,40 @@ function truncate(v, max = 240) {
5438
6030
  function KvRows({ data }) {
5439
6031
  const entries = Object.entries(data).filter(([, v]) => v !== void 0 && v !== null && v !== "");
5440
6032
  if (!entries.length) return null;
5441
- return /* @__PURE__ */ jsx13("dl", { className: "grid grid-cols-[auto_1fr] gap-x-3 gap-y-1", children: entries.map(([k, v]) => /* @__PURE__ */ jsxs11("div", { className: "contents", children: [
5442
- /* @__PURE__ */ jsx13("dt", { className: "font-mono text-xs text-muted-foreground", children: k }),
5443
- /* @__PURE__ */ jsx13("dd", { className: "min-w-0 whitespace-pre-wrap break-words font-mono text-xs text-muted-foreground", children: truncate(v) })
6033
+ return /* @__PURE__ */ jsx15("dl", { className: "grid grid-cols-[auto_1fr] gap-x-3 gap-y-1", children: entries.map(([k, v]) => /* @__PURE__ */ jsxs13("div", { className: "contents", children: [
6034
+ /* @__PURE__ */ jsx15("dt", { className: "font-mono text-xs text-muted-foreground", children: k }),
6035
+ /* @__PURE__ */ jsx15("dd", { className: "min-w-0 whitespace-pre-wrap break-words font-mono text-xs text-muted-foreground", children: truncate(v) })
5444
6036
  ] }, k)) });
5445
6037
  }
5446
6038
  function ShellDetail({ call }) {
5447
6039
  const outcome = toolOutcomeOf(call);
5448
6040
  const r = outcome?.result ?? {};
5449
- return /* @__PURE__ */ jsxs11("div", { className: "overflow-hidden rounded-md bg-zinc-900 font-mono text-xs leading-relaxed", children: [
5450
- /* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-2 px-3 pt-2 text-zinc-400", children: [
5451
- /* @__PURE__ */ jsx13("span", { className: "select-none text-zinc-500", children: "$" }),
5452
- /* @__PURE__ */ jsx13("span", { className: "min-w-0 flex-1 truncate text-zinc-200", children: String(call.args?.command ?? "") }),
5453
- r.exitCode != null && /* @__PURE__ */ jsxs11("span", { className: r.exitCode === 0 ? "text-success" : "text-destructive", children: [
6041
+ return /* @__PURE__ */ jsxs13("div", { className: "overflow-hidden rounded-md bg-zinc-900 font-mono text-xs leading-relaxed", children: [
6042
+ /* @__PURE__ */ jsxs13("div", { className: "flex items-center gap-2 px-3 pt-2 text-zinc-400", children: [
6043
+ /* @__PURE__ */ jsx15("span", { className: "select-none text-zinc-500", children: "$" }),
6044
+ /* @__PURE__ */ jsx15("span", { className: "min-w-0 flex-1 truncate text-zinc-200", children: String(call.args?.command ?? "") }),
6045
+ r.exitCode != null && /* @__PURE__ */ jsxs13("span", { className: r.exitCode === 0 ? "text-success" : "text-destructive", children: [
5454
6046
  "exit ",
5455
6047
  r.exitCode
5456
6048
  ] })
5457
6049
  ] }),
5458
- /* @__PURE__ */ jsx13("pre", { className: "max-h-56 overflow-auto whitespace-pre-wrap px-3 pb-2.5 pt-1.5 text-zinc-300", children: outcome?.ok === false ? outcome.message ?? "failed" : [r.stdout, r.stderr].filter(Boolean).join("\n") || "(no output)" })
6050
+ /* @__PURE__ */ jsx15("pre", { className: "max-h-56 overflow-auto whitespace-pre-wrap px-3 pb-2.5 pt-1.5 text-zinc-300", children: outcome?.ok === false ? outcome.message ?? "failed" : [r.stdout, r.stderr].filter(Boolean).join("\n") || "(no output)" })
5459
6051
  ] });
5460
6052
  }
5461
6053
  function DefaultToolDetail({ call }) {
5462
6054
  const result = call.result;
5463
6055
  const envelope = typeof result === "object" && result !== null ? result : null;
5464
- return /* @__PURE__ */ jsxs11("div", { className: "space-y-2", children: [
5465
- call.args && Object.keys(call.args).length > 0 && /* @__PURE__ */ jsxs11("div", { children: [
5466
- /* @__PURE__ */ jsx13("p", { className: "mb-1 text-xs font-semibold uppercase tracking-wide text-muted-foreground", children: "Called with" }),
5467
- /* @__PURE__ */ jsx13(KvRows, { data: call.args })
6056
+ return /* @__PURE__ */ jsxs13("div", { className: "space-y-2", children: [
6057
+ call.args && Object.keys(call.args).length > 0 && /* @__PURE__ */ jsxs13("div", { children: [
6058
+ /* @__PURE__ */ jsx15("p", { className: "mb-1 text-xs font-semibold uppercase tracking-wide text-muted-foreground", children: "Called with" }),
6059
+ /* @__PURE__ */ jsx15(KvRows, { data: call.args })
5468
6060
  ] }),
5469
- envelope ? /* @__PURE__ */ jsxs11("div", { children: [
5470
- /* @__PURE__ */ jsx13("p", { className: "mb-1 text-xs font-semibold uppercase tracking-wide text-muted-foreground", children: envelope.ok === false ? "Failed" : "Result" }),
5471
- envelope.ok === false ? /* @__PURE__ */ jsx13("p", { className: "text-xs text-destructive", children: envelope.message ?? "Tool failed" }) : envelope.result && typeof envelope.result === "object" ? /* @__PURE__ */ jsx13(KvRows, { data: envelope.result }) : envelope.result != null ? /* @__PURE__ */ jsx13("p", { className: "font-mono text-xs text-muted-foreground", children: truncate(envelope.result) }) : null
5472
- ] }) : result != null ? /* @__PURE__ */ jsxs11("div", { children: [
5473
- /* @__PURE__ */ jsx13("p", { className: "mb-1 text-xs font-semibold uppercase tracking-wide text-muted-foreground", children: "Result" }),
5474
- /* @__PURE__ */ jsx13("p", { className: "font-mono text-xs text-muted-foreground", children: truncate(result) })
6061
+ envelope ? /* @__PURE__ */ jsxs13("div", { children: [
6062
+ /* @__PURE__ */ jsx15("p", { className: "mb-1 text-xs font-semibold uppercase tracking-wide text-muted-foreground", children: envelope.ok === false ? "Failed" : "Result" }),
6063
+ envelope.ok === false ? /* @__PURE__ */ jsx15("p", { className: "text-xs text-destructive", children: envelope.message ?? "Tool failed" }) : envelope.result && typeof envelope.result === "object" ? /* @__PURE__ */ jsx15(KvRows, { data: envelope.result }) : envelope.result != null ? /* @__PURE__ */ jsx15("p", { className: "font-mono text-xs text-muted-foreground", children: truncate(envelope.result) }) : null
6064
+ ] }) : result != null ? /* @__PURE__ */ jsxs13("div", { children: [
6065
+ /* @__PURE__ */ jsx15("p", { className: "mb-1 text-xs font-semibold uppercase tracking-wide text-muted-foreground", children: "Result" }),
6066
+ /* @__PURE__ */ jsx15("p", { className: "font-mono text-xs text-muted-foreground", children: truncate(result) })
5475
6067
  ] }) : null
5476
6068
  ] });
5477
6069
  }
@@ -5482,24 +6074,24 @@ function ProposalCard({
5482
6074
  approval,
5483
6075
  renderers
5484
6076
  }) {
5485
- const [expanded, setExpanded] = useState14(false);
6077
+ const [expanded, setExpanded] = useState15(false);
5486
6078
  const { summary, meta, typeSlug } = proposalPreview(call);
5487
6079
  const custom = renderers?.[call.name]?.(call, message);
5488
6080
  const { pending: deciding, run: decide } = usePending();
5489
- return /* @__PURE__ */ jsxs11("div", { className: "w-full max-w-full rounded-xl border border-warning/50 bg-warning/[0.06] text-sm shadow-sm ring-1 ring-warning/10", children: [
5490
- /* @__PURE__ */ jsxs11("div", { className: "flex items-start gap-2.5 px-4 pt-3.5", children: [
5491
- /* @__PURE__ */ jsx13("span", { className: "mt-0.5 inline-flex h-6 w-6 shrink-0 items-center justify-center rounded-full bg-warning/15 text-warning", children: /* @__PURE__ */ jsx13(ToolGlyph, { name: call.name, className: "h-3.5 w-3.5" }) }),
5492
- /* @__PURE__ */ jsxs11("div", { className: "min-w-0 flex-1", children: [
5493
- /* @__PURE__ */ jsx13("p", { className: "text-xs font-semibold uppercase tracking-[0.05em] text-warning-strong", children: approval ? "Needs your approval" : "Awaiting approval" }),
5494
- /* @__PURE__ */ jsx13("p", { className: "mt-0.5 text-[15px] font-semibold leading-snug text-foreground", children: friendlyToolTitle(call) }),
5495
- summary && /* @__PURE__ */ jsx13("p", { className: "mt-1 text-xs leading-relaxed text-muted-foreground", children: summary }),
5496
- typeSlug && /* @__PURE__ */ jsx13("p", { className: "mt-1 font-mono text-xs text-muted-foreground", children: typeSlug }),
5497
- meta.length > 0 && /* @__PURE__ */ jsx13("div", { className: "mt-1.5 flex flex-wrap items-center gap-1.5", children: meta.map((m, i) => /* @__PURE__ */ jsx13("span", { className: "rounded-full bg-secondary px-2 py-0.5 text-xs font-medium text-muted-foreground", children: m }, i)) })
6081
+ return /* @__PURE__ */ jsxs13("div", { className: "w-full max-w-full rounded-xl border border-warning/50 bg-warning/[0.06] text-sm shadow-sm ring-1 ring-warning/10", children: [
6082
+ /* @__PURE__ */ jsxs13("div", { className: "flex items-start gap-2.5 px-4 pt-3.5", children: [
6083
+ /* @__PURE__ */ jsx15("span", { className: "mt-0.5 inline-flex h-6 w-6 shrink-0 items-center justify-center rounded-full bg-warning/15 text-warning", children: /* @__PURE__ */ jsx15(ToolGlyph, { name: call.name, className: "h-3.5 w-3.5" }) }),
6084
+ /* @__PURE__ */ jsxs13("div", { className: "min-w-0 flex-1", children: [
6085
+ /* @__PURE__ */ jsx15("p", { className: "text-xs font-semibold uppercase tracking-[0.05em] text-warning-strong", children: approval ? "Needs your approval" : "Awaiting approval" }),
6086
+ /* @__PURE__ */ jsx15("p", { className: "mt-0.5 text-[15px] font-semibold leading-snug text-foreground", children: friendlyToolTitle(call) }),
6087
+ summary && /* @__PURE__ */ jsx15("p", { className: "mt-1 text-xs leading-relaxed text-muted-foreground", children: summary }),
6088
+ typeSlug && /* @__PURE__ */ jsx15("p", { className: "mt-1 font-mono text-xs text-muted-foreground", children: typeSlug }),
6089
+ meta.length > 0 && /* @__PURE__ */ jsx15("div", { className: "mt-1.5 flex flex-wrap items-center gap-1.5", children: meta.map((m, i) => /* @__PURE__ */ jsx15("span", { className: "rounded-full bg-secondary px-2 py-0.5 text-xs font-medium text-muted-foreground", children: m }, i)) })
5498
6090
  ] })
5499
6091
  ] }),
5500
- /* @__PURE__ */ jsxs11("div", { className: "flex flex-wrap items-center gap-2 px-4 pb-3.5 pt-3", children: [
5501
- approval && /* @__PURE__ */ jsxs11(Fragment7, { children: [
5502
- /* @__PURE__ */ jsx13(
6092
+ /* @__PURE__ */ jsxs13("div", { className: "flex flex-wrap items-center gap-2 px-4 pb-3.5 pt-3", children: [
6093
+ approval && /* @__PURE__ */ jsxs13(Fragment8, { children: [
6094
+ /* @__PURE__ */ jsx15(
5503
6095
  "button",
5504
6096
  {
5505
6097
  type: "button",
@@ -5509,7 +6101,7 @@ function ProposalCard({
5509
6101
  children: "Approve & run"
5510
6102
  }
5511
6103
  ),
5512
- /* @__PURE__ */ jsx13(
6104
+ /* @__PURE__ */ jsx15(
5513
6105
  "button",
5514
6106
  {
5515
6107
  type: "button",
@@ -5520,7 +6112,7 @@ function ProposalCard({
5520
6112
  }
5521
6113
  )
5522
6114
  ] }),
5523
- /* @__PURE__ */ jsxs11(
6115
+ /* @__PURE__ */ jsxs13(
5524
6116
  "button",
5525
6117
  {
5526
6118
  type: "button",
@@ -5529,12 +6121,12 @@ function ProposalCard({
5529
6121
  className: "ml-auto inline-flex items-center gap-1 rounded text-[12px] font-medium text-muted-foreground transition hover:text-foreground",
5530
6122
  children: [
5531
6123
  expanded ? "Hide details" : "View details",
5532
- /* @__PURE__ */ jsx13(ChevronDown, { className: `h-3 w-3 transition-transform ${expanded ? "rotate-180" : ""}` })
6124
+ /* @__PURE__ */ jsx15(ChevronDown, { className: `h-3 w-3 transition-transform ${expanded ? "rotate-180" : ""}` })
5533
6125
  ]
5534
6126
  }
5535
6127
  )
5536
6128
  ] }),
5537
- expanded && /* @__PURE__ */ jsx13("div", { className: "border-t border-warning/20 px-4 py-3 text-xs", children: custom ?? /* @__PURE__ */ jsx13(DefaultToolDetail, { call }) })
6129
+ expanded && /* @__PURE__ */ jsx15("div", { className: "border-t border-warning/20 px-4 py-3 text-xs", children: custom ?? /* @__PURE__ */ jsx15(DefaultToolDetail, { call }) })
5538
6130
  ] });
5539
6131
  }
5540
6132
  function formatFollowupWhen(when) {
@@ -5549,14 +6141,14 @@ function FollowupCard({ call }) {
5549
6141
  const when = typeof a.when === "string" ? a.when : typeof a.at === "string" ? a.at : typeof a.schedule === "string" ? a.schedule : null;
5550
6142
  const failed = toolCallFailed(call);
5551
6143
  const errorText = failed ? toolOutcomeOf(call)?.message ?? "Scheduling failed" : null;
5552
- return /* @__PURE__ */ jsx13("div", { className: "flex items-start gap-2", children: /* @__PURE__ */ jsxs11("div", { className: "min-w-0 flex-1 overflow-hidden rounded-[var(--radius-lg)] border border-[var(--border-subtle)] bg-[var(--md3-surface-container)]", children: [
5553
- /* @__PURE__ */ jsxs11("div", { className: "flex w-full items-center gap-2.5 px-3 py-2", children: [
5554
- /* @__PURE__ */ jsx13("span", { className: "flex h-6 w-6 shrink-0 items-center justify-center rounded-[var(--radius-sm)] border border-border bg-muted text-muted-foreground", children: /* @__PURE__ */ jsx13(ToolGlyph, { name: call.name, className: "h-3.5 w-3.5" }) }),
5555
- /* @__PURE__ */ jsx13("span", { className: "shrink-0 whitespace-nowrap text-xs font-medium text-foreground", children: friendlyToolTitle(call) }),
5556
- when && /* @__PURE__ */ jsx13("span", { title: when, className: "hidden min-w-0 flex-1 truncate font-mono text-xs tabular-nums text-muted-foreground sm:inline", children: formatFollowupWhen(when) }),
5557
- /* @__PURE__ */ jsx13("span", { className: "ml-auto flex shrink-0 items-center gap-1.5", children: call.status === "running" ? /* @__PURE__ */ jsx13("svg", { className: "h-3 w-3 shrink-0 animate-spin text-[var(--accent-text)]", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", "aria-hidden": true, children: /* @__PURE__ */ jsx13("path", { d: "M21 12a9 9 0 1 1-6.219-8.56", strokeLinecap: "round" }) }) : /* @__PURE__ */ jsx13("span", { className: `h-1.5 w-1.5 shrink-0 rounded-full ${failed ? "bg-[var(--surface-danger-text)]" : "bg-[var(--surface-success-text)]"}` }) })
6144
+ return /* @__PURE__ */ jsx15("div", { className: "flex items-start gap-2", children: /* @__PURE__ */ jsxs13("div", { className: "min-w-0 flex-1 overflow-hidden rounded-[var(--radius-lg)] border border-[var(--border-subtle)] bg-[var(--md3-surface-container)]", children: [
6145
+ /* @__PURE__ */ jsxs13("div", { className: "flex w-full items-center gap-2.5 px-3 py-2", children: [
6146
+ /* @__PURE__ */ jsx15("span", { className: "flex h-6 w-6 shrink-0 items-center justify-center rounded-[var(--radius-sm)] border border-border bg-muted text-muted-foreground", children: /* @__PURE__ */ jsx15(ToolGlyph, { name: call.name, className: "h-3.5 w-3.5" }) }),
6147
+ /* @__PURE__ */ jsx15("span", { className: "shrink-0 whitespace-nowrap text-xs font-medium text-foreground", children: friendlyToolTitle(call) }),
6148
+ when && /* @__PURE__ */ jsx15("span", { title: when, className: "hidden min-w-0 flex-1 truncate font-mono text-xs tabular-nums text-muted-foreground sm:inline", children: formatFollowupWhen(when) }),
6149
+ /* @__PURE__ */ jsx15("span", { className: "ml-auto flex shrink-0 items-center gap-1.5", children: call.status === "running" ? /* @__PURE__ */ jsx15("svg", { className: "h-3 w-3 shrink-0 animate-spin text-[var(--accent-text)]", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", "aria-hidden": true, children: /* @__PURE__ */ jsx15("path", { d: "M21 12a9 9 0 1 1-6.219-8.56", strokeLinecap: "round" }) }) : /* @__PURE__ */ jsx15("span", { className: `h-1.5 w-1.5 shrink-0 rounded-full ${failed ? "bg-[var(--surface-danger-text)]" : "bg-[var(--surface-success-text)]"}` }) })
5558
6150
  ] }),
5559
- errorText && /* @__PURE__ */ jsx13("div", { className: "border-t border-border px-3 py-2 text-xs text-[var(--surface-danger-text)]", children: errorText })
6151
+ errorText && /* @__PURE__ */ jsx15("div", { className: "border-t border-border px-3 py-2 text-xs text-[var(--surface-danger-text)]", children: errorText })
5560
6152
  ] }) });
5561
6153
  }
5562
6154
  function toolRowTitle(call) {
@@ -5578,7 +6170,7 @@ function ToolCallCard({
5578
6170
  const pending = call.status === "done" ? pendingApprovalOf(call) : null;
5579
6171
  const kind = blockKindOf(call);
5580
6172
  if (pending) {
5581
- return /* @__PURE__ */ jsx13(
6173
+ return /* @__PURE__ */ jsx15(
5582
6174
  ProposalCard,
5583
6175
  {
5584
6176
  call,
@@ -5590,17 +6182,17 @@ function ToolCallCard({
5590
6182
  );
5591
6183
  }
5592
6184
  if (kind === "followup") {
5593
- return /* @__PURE__ */ jsx13(FollowupCard, { call });
6185
+ return /* @__PURE__ */ jsx15(FollowupCard, { call });
5594
6186
  }
5595
6187
  const custom = renderers?.[call.name]?.(call, message);
5596
- return /* @__PURE__ */ jsx13(
6188
+ return /* @__PURE__ */ jsx15(
5597
6189
  InlineToolItem,
5598
6190
  {
5599
6191
  part: chatToolCallPart(call),
5600
6192
  title: toolRowTitle(call),
5601
6193
  description: toolRowDescription(call),
5602
- renderToolDetail: () => custom ?? (call.name === "sandbox_run_command" ? /* @__PURE__ */ jsx13(ShellDetail, { call }) : /* @__PURE__ */ jsx13(DefaultToolDetail, { call })),
5603
- actions: onOpenRun && call.name.startsWith("sandbox_") ? /* @__PURE__ */ jsx13(
6194
+ renderToolDetail: () => custom ?? (call.name === "sandbox_run_command" ? /* @__PURE__ */ jsx15(ShellDetail, { call }) : /* @__PURE__ */ jsx15(DefaultToolDetail, { call })),
6195
+ actions: onOpenRun && call.name.startsWith("sandbox_") ? /* @__PURE__ */ jsx15(
5604
6196
  "button",
5605
6197
  {
5606
6198
  type: "button",
@@ -5608,9 +6200,9 @@ function ToolCallCard({
5608
6200
  "aria-label": "Open full transcript",
5609
6201
  title: "Open full transcript",
5610
6202
  className: "rounded-md p-1.5 text-muted-foreground transition hover:bg-accent hover:text-foreground",
5611
- children: /* @__PURE__ */ jsxs11("svg", { className: "h-3.5 w-3.5", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: [
5612
- /* @__PURE__ */ jsx13("path", { d: "M7 17 17 7" }),
5613
- /* @__PURE__ */ jsx13("path", { d: "M7 7h10v10" })
6203
+ children: /* @__PURE__ */ jsxs13("svg", { className: "h-3.5 w-3.5", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: [
6204
+ /* @__PURE__ */ jsx15("path", { d: "M7 17 17 7" }),
6205
+ /* @__PURE__ */ jsx15("path", { d: "M7 7h10v10" })
5614
6206
  ] })
5615
6207
  }
5616
6208
  ) : void 0
@@ -5618,7 +6210,7 @@ function ToolCallCard({
5618
6210
  );
5619
6211
  }
5620
6212
  function StreamingCaret() {
5621
- return /* @__PURE__ */ jsx13(
6213
+ return /* @__PURE__ */ jsx15(
5622
6214
  "span",
5623
6215
  {
5624
6216
  className: "ml-0.5 inline-block h-[1.1em] w-[3px] translate-y-[2px] animate-[agent-caret_1s_step-end_infinite] rounded-sm bg-foreground/70",
@@ -5643,9 +6235,9 @@ function SegmentText({
5643
6235
  // the container on top of that makes the paragraph shimmer while it types.
5644
6236
  // The distinction is what separates "the answer materialised" from "the
5645
6237
  // log was appended to".
5646
- /* @__PURE__ */ jsxs11("div", { className: `${messageClassName}${streaming ? "" : " agent-stream-in"}`, children: [
6238
+ /* @__PURE__ */ jsxs13("div", { className: `${messageClassName}${streaming ? "" : " agent-stream-in"}`, children: [
5647
6239
  body,
5648
- showCaret && /* @__PURE__ */ jsx13(StreamingCaret, {})
6240
+ showCaret && /* @__PURE__ */ jsx15(StreamingCaret, {})
5649
6241
  ] })
5650
6242
  );
5651
6243
  }
@@ -5670,7 +6262,7 @@ function SegmentedBody({
5670
6262
  const leftoverToolCalls = (msg.toolCalls ?? []).filter(
5671
6263
  (tc) => !segmentToolIds.has(tc.id)
5672
6264
  );
5673
- const renderToolCard = (call) => /* @__PURE__ */ jsx13(
6265
+ const renderToolCard = (call) => /* @__PURE__ */ jsx15(
5674
6266
  ToolCallCard,
5675
6267
  {
5676
6268
  call,
@@ -5693,9 +6285,9 @@ function SegmentedBody({
5693
6285
  else groups.push({ kind: "tools", index: i, calls: [seg.call] });
5694
6286
  }
5695
6287
  }
5696
- return /* @__PURE__ */ jsxs11("div", { className: "flex flex-col gap-2", children: [
6288
+ return /* @__PURE__ */ jsxs13("div", { className: "flex flex-col gap-2", children: [
5697
6289
  groups.map(
5698
- (g) => g.kind === "text" ? /* @__PURE__ */ jsx13(
6290
+ (g) => g.kind === "text" ? /* @__PURE__ */ jsx15(
5699
6291
  SegmentText,
5700
6292
  {
5701
6293
  content: g.content,
@@ -5708,18 +6300,18 @@ function SegmentedBody({
5708
6300
  ) : !streaming && g.calls.length >= COLLAPSE_TOOL_RUN_AT && !g.calls.some(isImportantTool) ? (
5709
6301
  // The fold is a quiet disclosure line, not a filled box — the
5710
6302
  // canonical rows inside it carry the row chrome.
5711
- /* @__PURE__ */ jsxs11("details", { children: [
5712
- /* @__PURE__ */ jsxs11("summary", { className: "cursor-pointer select-none rounded-md py-0.5 text-xs font-medium text-muted-foreground transition-colors hover:text-foreground", children: [
6303
+ /* @__PURE__ */ jsxs13("details", { children: [
6304
+ /* @__PURE__ */ jsxs13("summary", { className: "cursor-pointer select-none rounded-md py-0.5 text-xs font-medium text-muted-foreground transition-colors hover:text-foreground", children: [
5713
6305
  "Worked through ",
5714
6306
  g.calls.length,
5715
6307
  " steps"
5716
6308
  ] }),
5717
- /* @__PURE__ */ jsx13("div", { className: "mt-1.5 flex flex-col gap-1.5", children: g.calls.map(renderToolCard) })
6309
+ /* @__PURE__ */ jsx15("div", { className: "mt-1.5 flex flex-col gap-1.5", children: g.calls.map(renderToolCard) })
5718
6310
  ] }, `tools-${g.index}`)
5719
- ) : /* @__PURE__ */ jsx13("div", { className: "flex flex-col gap-2", children: g.calls.map(renderToolCard) }, `tools-${g.index}`)
6311
+ ) : /* @__PURE__ */ jsx15("div", { className: "flex flex-col gap-2", children: g.calls.map(renderToolCard) }, `tools-${g.index}`)
5720
6312
  ),
5721
6313
  leftoverToolCalls.map(renderToolCard),
5722
- streaming && segments[lastIndex]?.kind === "tool" && /* @__PURE__ */ jsx13(StreamingCaret, {})
6314
+ streaming && segments[lastIndex]?.kind === "tool" && /* @__PURE__ */ jsx15(StreamingCaret, {})
5723
6315
  ] });
5724
6316
  }
5725
6317
  var QUIET_META_LANE_CLASS = "mt-1 flex h-[18px] items-center gap-2 text-xs tabular-nums text-muted-foreground opacity-0 transition-opacity duration-150 group-hover:opacity-100 group-focus-within:opacity-100 motion-reduce:transition-none [@media(hover:none)]:opacity-100";
@@ -5729,9 +6321,9 @@ function copyTextOf(msg) {
5729
6321
  return msg.content;
5730
6322
  }
5731
6323
  function CopyMessageButton({ text }) {
5732
- const [copied, setCopied] = useState14(false);
5733
- const timerRef = useRef11(null);
5734
- useEffect11(
6324
+ const [copied, setCopied] = useState15(false);
6325
+ const timerRef = useRef12(null);
6326
+ useEffect12(
5735
6327
  () => () => {
5736
6328
  if (timerRef.current !== null) clearTimeout(timerRef.current);
5737
6329
  },
@@ -5750,7 +6342,7 @@ function CopyMessageButton({ text }) {
5750
6342
  }
5751
6343
  );
5752
6344
  };
5753
- return /* @__PURE__ */ jsx13(
6345
+ return /* @__PURE__ */ jsx15(
5754
6346
  "button",
5755
6347
  {
5756
6348
  type: "button",
@@ -5758,9 +6350,9 @@ function CopyMessageButton({ text }) {
5758
6350
  "aria-label": "Copy message",
5759
6351
  title: "Copy message",
5760
6352
  className: "rounded p-0.5 text-muted-foreground transition hover:bg-accent hover:text-foreground focus:outline-none focus-visible:ring-2 focus-visible:ring-ring",
5761
- children: copied ? /* @__PURE__ */ jsx13("svg", { className: "h-3.5 w-3.5", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: /* @__PURE__ */ jsx13("polyline", { points: "20 6 9 17 4 12" }) }) : /* @__PURE__ */ jsxs11("svg", { className: "h-3.5 w-3.5", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: [
5762
- /* @__PURE__ */ jsx13("rect", { x: "9", y: "9", width: "13", height: "13", rx: "2" }),
5763
- /* @__PURE__ */ jsx13("path", { d: "M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" })
6353
+ children: copied ? /* @__PURE__ */ jsx15("svg", { className: "h-3.5 w-3.5", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: /* @__PURE__ */ jsx15("polyline", { points: "20 6 9 17 4 12" }) }) : /* @__PURE__ */ jsxs13("svg", { className: "h-3.5 w-3.5", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: [
6354
+ /* @__PURE__ */ jsx15("rect", { x: "9", y: "9", width: "13", height: "13", rx: "2" }),
6355
+ /* @__PURE__ */ jsx15("path", { d: "M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" })
5764
6356
  ] })
5765
6357
  }
5766
6358
  );
@@ -5786,16 +6378,16 @@ function AssistantMessageImpl({
5786
6378
  const body = useMemo7(() => renderBody(content), [renderBody, content]);
5787
6379
  const segments = msg.segments;
5788
6380
  const hasAnswerText = content !== "" || (segments?.some((s) => s.kind === "text" && s.content.trim() !== "") ?? false);
5789
- const reasoningScrollRef = useRef11(null);
5790
- const thinkStartRef = useRef11(null);
5791
- const thinkMsRef = useRef11(null);
6381
+ const reasoningScrollRef = useRef12(null);
6382
+ const thinkStartRef = useRef12(null);
6383
+ const thinkMsRef = useRef12(null);
5792
6384
  if (streaming && reasoning && !hasAnswerText && thinkStartRef.current === null) {
5793
6385
  thinkStartRef.current = performance.now();
5794
6386
  }
5795
6387
  if (hasAnswerText && thinkStartRef.current !== null && thinkMsRef.current === null) {
5796
6388
  thinkMsRef.current = performance.now() - thinkStartRef.current;
5797
6389
  }
5798
- useEffect11(() => {
6390
+ useEffect12(() => {
5799
6391
  const el = reasoningScrollRef.current;
5800
6392
  if (el && streaming && !hasAnswerText) el.scrollTop = el.scrollHeight;
5801
6393
  }, [reasoning, streaming, hasAnswerText]);
@@ -5803,29 +6395,29 @@ function AssistantMessageImpl({
5803
6395
  streaming && !!reasoning && !hasAnswerText
5804
6396
  );
5805
6397
  const quiet = chrome === "quiet";
5806
- return /* @__PURE__ */ jsxs11("div", { className: `mx-auto w-full max-w-3xl px-6 ${quiet ? "group pb-1 pt-3" : "py-3"}`, children: [
5807
- !quiet && /* @__PURE__ */ jsxs11("div", { className: "mb-1 flex items-baseline gap-2 text-xs tabular-nums text-muted-foreground", children: [
5808
- /* @__PURE__ */ jsx13("span", { className: "font-semibold uppercase tracking-[0.05em]", children: agentLabel }),
5809
- msg.modelUsed && /* @__PURE__ */ jsx13("span", { className: "font-mono normal-case", children: msg.modelUsed }),
5810
- formatTokensPerSecond(msg) && /* @__PURE__ */ jsx13("span", { children: formatTokensPerSecond(msg) }),
5811
- formatModelCost(msg, models) && /* @__PURE__ */ jsx13("span", { children: formatModelCost(msg, models) })
6398
+ return /* @__PURE__ */ jsxs13("div", { className: `mx-auto w-full max-w-3xl px-6 ${quiet ? "group pb-1 pt-3" : "py-3"}`, children: [
6399
+ !quiet && /* @__PURE__ */ jsxs13("div", { className: "mb-1 flex items-baseline gap-2 text-xs tabular-nums text-muted-foreground", children: [
6400
+ /* @__PURE__ */ jsx15("span", { className: "font-semibold uppercase tracking-[0.05em]", children: agentLabel }),
6401
+ msg.modelUsed && /* @__PURE__ */ jsx15("span", { className: "font-mono normal-case", children: msg.modelUsed }),
6402
+ formatTokensPerSecond(msg) && /* @__PURE__ */ jsx15("span", { children: formatTokensPerSecond(msg) }),
6403
+ formatModelCost(msg, models) && /* @__PURE__ */ jsx15("span", { children: formatModelCost(msg, models) })
5812
6404
  ] }),
5813
- reasoning && /* @__PURE__ */ jsxs11("details", { className: "mb-2 rounded-lg border-l-2 border-border bg-secondary px-3 py-2", open: !hasAnswerText, children: [
5814
- /* @__PURE__ */ jsx13("summary", { className: "cursor-pointer select-none text-xs font-medium text-muted-foreground", children: !hasAnswerText ? (
6405
+ reasoning && /* @__PURE__ */ jsxs13("details", { className: "mb-2 rounded-lg border-l-2 border-border bg-secondary px-3 py-2", open: !hasAnswerText, children: [
6406
+ /* @__PURE__ */ jsx15("summary", { className: "cursor-pointer select-none text-xs font-medium text-muted-foreground", children: !hasAnswerText ? (
5815
6407
  // A pulse dims the whole word on a loop, which is the same cue a
5816
6408
  // skeleton placeholder uses — it reads as "nothing here yet". A
5817
6409
  // sweep travels THROUGH the glyphs, which reads as work in
5818
6410
  // flight, and the elapsed seconds say how much. `essential`
5819
6411
  // because it is the only signal separating a working agent from
5820
6412
  // a stuck one, and reduced-motion still collapses its duration.
5821
- /* @__PURE__ */ jsxs11("span", { className: "agent-shimmer", "data-motion": "essential", children: [
6413
+ /* @__PURE__ */ jsxs13("span", { className: "agent-shimmer", "data-motion": "essential", children: [
5822
6414
  "Thinking",
5823
6415
  thinkingSeconds >= 1 ? ` \xB7 ${thinkingSeconds}s` : "\u2026"
5824
6416
  ] })
5825
6417
  ) : thinkMsRef.current != null ? `Thought for ${Math.max(1, Math.round(thinkMsRef.current / 1e3))}s` : "Thought process" }),
5826
- /* @__PURE__ */ jsx13("div", { ref: reasoningScrollRef, className: "mt-2 max-h-48 overflow-y-auto whitespace-pre-wrap text-xs leading-relaxed text-muted-foreground", children: reasoning })
6418
+ /* @__PURE__ */ jsx15("div", { ref: reasoningScrollRef, className: "mt-2 max-h-48 overflow-y-auto whitespace-pre-wrap text-xs leading-relaxed text-muted-foreground", children: reasoning })
5827
6419
  ] }),
5828
- segments && segments.length > 0 ? /* @__PURE__ */ jsx13(
6420
+ segments && segments.length > 0 ? /* @__PURE__ */ jsx15(
5829
6421
  SegmentedBody,
5830
6422
  {
5831
6423
  segments,
@@ -5837,12 +6429,12 @@ function AssistantMessageImpl({
5837
6429
  toolRenderers,
5838
6430
  messageClassName
5839
6431
  }
5840
- ) : /* @__PURE__ */ jsxs11(Fragment7, { children: [
5841
- /* @__PURE__ */ jsxs11("div", { className: messageClassName, children: [
6432
+ ) : /* @__PURE__ */ jsxs13(Fragment8, { children: [
6433
+ /* @__PURE__ */ jsxs13("div", { className: messageClassName, children: [
5842
6434
  body,
5843
- streaming && content && !msg.toolCalls?.length && /* @__PURE__ */ jsx13(StreamingCaret, {})
6435
+ streaming && content && !msg.toolCalls?.length && /* @__PURE__ */ jsx15(StreamingCaret, {})
5844
6436
  ] }),
5845
- msg.toolCalls && msg.toolCalls.length > 0 && /* @__PURE__ */ jsx13("div", { className: "mt-2 flex flex-col gap-1.5", children: msg.toolCalls.map((tc) => /* @__PURE__ */ jsx13(
6437
+ msg.toolCalls && msg.toolCalls.length > 0 && /* @__PURE__ */ jsx15("div", { className: "mt-2 flex flex-col gap-1.5", children: msg.toolCalls.map((tc) => /* @__PURE__ */ jsx15(
5846
6438
  ToolCallCard,
5847
6439
  {
5848
6440
  call: tc,
@@ -5854,7 +6446,7 @@ function AssistantMessageImpl({
5854
6446
  tc.id
5855
6447
  )) })
5856
6448
  ] }),
5857
- durableCards && msg.parts && /* @__PURE__ */ jsx13(
6449
+ durableCards && msg.parts && /* @__PURE__ */ jsx15(
5858
6450
  DurableChatCards,
5859
6451
  {
5860
6452
  ...durableCards,
@@ -5863,7 +6455,7 @@ function AssistantMessageImpl({
5863
6455
  className: "mt-3"
5864
6456
  }
5865
6457
  ),
5866
- workProductCards && workProductPartsFromMessageParts(msg.parts).map((part) => /* @__PURE__ */ jsx13(
6458
+ workProductCards && workProductPartsFromMessageParts(msg.parts).map((part) => /* @__PURE__ */ jsx15(
5867
6459
  WorkProductCard,
5868
6460
  {
5869
6461
  part,
@@ -5873,7 +6465,7 @@ function AssistantMessageImpl({
5873
6465
  `${part.ref.id}:${part.ref.version}`
5874
6466
  )),
5875
6467
  renderExtras?.(msg),
5876
- resolveAttachmentUrl && attachmentPartsFromMessageParts(msg.parts).length > 0 && /* @__PURE__ */ jsx13("div", { className: "mt-2", children: /* @__PURE__ */ jsx13(
6468
+ resolveAttachmentUrl && attachmentPartsFromMessageParts(msg.parts).length > 0 && /* @__PURE__ */ jsx15("div", { className: "mt-2", children: /* @__PURE__ */ jsx15(
5877
6469
  MessageAttachments,
5878
6470
  {
5879
6471
  parts: attachmentPartsFromMessageParts(msg.parts),
@@ -5881,18 +6473,18 @@ function AssistantMessageImpl({
5881
6473
  justify: "start"
5882
6474
  }
5883
6475
  ) }),
5884
- quiet && /* @__PURE__ */ jsxs11("div", { "data-testid": "message-meta-lane", className: QUIET_META_LANE_CLASS, children: [
5885
- /* @__PURE__ */ jsx13(CopyMessageButton, { text: copyTextOf(msg) }),
5886
- msg.modelUsed && /* @__PURE__ */ jsx13("span", { className: "font-mono", children: msg.modelUsed }),
5887
- formatTokensPerSecond(msg) && /* @__PURE__ */ jsx13("span", { children: formatTokensPerSecond(msg) }),
5888
- formatModelCost(msg, models) && /* @__PURE__ */ jsx13("span", { children: formatModelCost(msg, models) })
6476
+ quiet && /* @__PURE__ */ jsxs13("div", { "data-testid": "message-meta-lane", className: QUIET_META_LANE_CLASS, children: [
6477
+ /* @__PURE__ */ jsx15(CopyMessageButton, { text: copyTextOf(msg) }),
6478
+ msg.modelUsed && /* @__PURE__ */ jsx15("span", { className: "font-mono", children: msg.modelUsed }),
6479
+ formatTokensPerSecond(msg) && /* @__PURE__ */ jsx15("span", { children: formatTokensPerSecond(msg) }),
6480
+ formatModelCost(msg, models) && /* @__PURE__ */ jsx15("span", { children: formatModelCost(msg, models) })
5889
6481
  ] })
5890
6482
  ] });
5891
6483
  }
5892
6484
  var AssistantMessage = memo(AssistantMessageImpl);
5893
6485
  function useThinkingSeconds(active) {
5894
- const [seconds, setSeconds] = useState14(0);
5895
- useEffect11(() => {
6486
+ const [seconds, setSeconds] = useState15(0);
6487
+ useEffect12(() => {
5896
6488
  if (!active) return;
5897
6489
  setSeconds(0);
5898
6490
  const id = setInterval(() => setSeconds((s) => s + 1), 1e3);
@@ -5902,23 +6494,23 @@ function useThinkingSeconds(active) {
5902
6494
  }
5903
6495
  function ThinkingRow({ agentLabel, chrome = "labeled" }) {
5904
6496
  const seconds = useThinkingSeconds(true);
5905
- return /* @__PURE__ */ jsxs11("div", { className: "mx-auto w-full max-w-3xl px-6 py-3", children: [
5906
- chrome !== "quiet" && /* @__PURE__ */ jsx13("p", { className: "mb-1 text-xs font-semibold uppercase tracking-[0.05em] text-muted-foreground", children: agentLabel }),
5907
- /* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-2 text-[15px] text-muted-foreground", children: [
5908
- /* @__PURE__ */ jsx13("svg", { className: "h-4 w-4 animate-spin", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", "aria-hidden": true, children: /* @__PURE__ */ jsx13("path", { d: "M21 12a9 9 0 1 1-6.219-8.56", strokeLinecap: "round" }) }),
6497
+ return /* @__PURE__ */ jsxs13("div", { className: "mx-auto w-full max-w-3xl px-6 py-3", children: [
6498
+ chrome !== "quiet" && /* @__PURE__ */ jsx15("p", { className: "mb-1 text-xs font-semibold uppercase tracking-[0.05em] text-muted-foreground", children: agentLabel }),
6499
+ /* @__PURE__ */ jsxs13("div", { className: "flex items-center gap-2 text-[15px] text-muted-foreground", children: [
6500
+ /* @__PURE__ */ jsx15("svg", { className: "h-4 w-4 animate-spin", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", "aria-hidden": true, children: /* @__PURE__ */ jsx15("path", { d: "M21 12a9 9 0 1 1-6.219-8.56", strokeLinecap: "round" }) }),
5909
6501
  "Thinking",
5910
6502
  seconds >= 3 ? ` \xB7 ${seconds}s` : "..."
5911
6503
  ] })
5912
6504
  ] });
5913
6505
  }
5914
6506
  function StreamErrorRow({ message, onRetry }) {
5915
- return /* @__PURE__ */ jsx13("div", { className: "mx-auto w-full max-w-3xl px-6 py-3", children: /* @__PURE__ */ jsxs11("div", { role: "alert", className: "flex items-start gap-2.5 rounded-lg border border-destructive/40 bg-destructive/5 px-3 py-2.5 text-sm text-destructive", children: [
5916
- /* @__PURE__ */ jsxs11("svg", { className: "mt-0.5 h-4 w-4 shrink-0", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: [
5917
- /* @__PURE__ */ jsx13("circle", { cx: "12", cy: "12", r: "9" }),
5918
- /* @__PURE__ */ jsx13("path", { d: "M12 8v4m0 4h.01" })
6507
+ return /* @__PURE__ */ jsx15("div", { className: "mx-auto w-full max-w-3xl px-6 py-3", children: /* @__PURE__ */ jsxs13("div", { role: "alert", className: "flex items-start gap-2.5 rounded-lg border border-destructive/40 bg-destructive/5 px-3 py-2.5 text-sm text-destructive", children: [
6508
+ /* @__PURE__ */ jsxs13("svg", { className: "mt-0.5 h-4 w-4 shrink-0", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: [
6509
+ /* @__PURE__ */ jsx15("circle", { cx: "12", cy: "12", r: "9" }),
6510
+ /* @__PURE__ */ jsx15("path", { d: "M12 8v4m0 4h.01" })
5919
6511
  ] }),
5920
- /* @__PURE__ */ jsx13("span", { className: "min-w-0 flex-1 break-words", children: message }),
5921
- onRetry && /* @__PURE__ */ jsx13(
6512
+ /* @__PURE__ */ jsx15("span", { className: "min-w-0 flex-1 break-words", children: message }),
6513
+ onRetry && /* @__PURE__ */ jsx15(
5922
6514
  "button",
5923
6515
  {
5924
6516
  type: "button",
@@ -5953,32 +6545,32 @@ function ChatMessages({
5953
6545
  }) {
5954
6546
  const messageClassName = messageSize === "large" ? "agent-app-message-copy text-[17px] leading-[1.6]" : "agent-app-message-copy text-base leading-[1.6]";
5955
6547
  const renderBody = useMemo7(
5956
- () => renderMarkdown ?? ((content) => /* @__PURE__ */ jsx13("p", { className: "whitespace-pre-wrap", children: content })),
6548
+ () => renderMarkdown ?? ((content) => /* @__PURE__ */ jsx15("p", { className: "whitespace-pre-wrap", children: content })),
5957
6549
  [renderMarkdown]
5958
6550
  );
5959
6551
  const lastIsUser = messages[messages.length - 1]?.role === "user";
5960
6552
  const quiet = chrome === "quiet";
5961
6553
  if (messages.length === 0 && !loading && !error) {
5962
- const empty = renderEmpty ? renderEmpty() : /* @__PURE__ */ jsx13(ChatEmptyState, { ...emptyState });
5963
- return /* @__PURE__ */ jsxs11(Fragment7, { children: [
6554
+ const empty = renderEmpty ? renderEmpty() : /* @__PURE__ */ jsx15(ChatEmptyState, { ...emptyState });
6555
+ return /* @__PURE__ */ jsxs13(Fragment8, { children: [
5964
6556
  header,
5965
6557
  empty
5966
6558
  ] });
5967
6559
  }
5968
- return /* @__PURE__ */ jsxs11(Fragment7, { children: [
6560
+ return /* @__PURE__ */ jsxs13(Fragment8, { children: [
5969
6561
  header,
5970
6562
  messages.map(
5971
- (msg) => msg.role === "user" ? /* @__PURE__ */ jsxs11("div", { className: `mx-auto w-full max-w-3xl px-6 ${quiet ? "group pb-1 pt-3" : "py-3"}`, children: [
5972
- /* @__PURE__ */ jsxs11("div", { className: `ml-auto w-fit ${quiet ? "max-w-[72%]" : "max-w-[85%]"}`, children: [
5973
- !quiet && /* @__PURE__ */ jsx13("p", { className: "mb-1 text-right text-xs font-semibold uppercase tracking-[0.05em] text-muted-foreground", children: userLabel }),
5974
- /* @__PURE__ */ jsx13(
6563
+ (msg) => msg.role === "user" ? /* @__PURE__ */ jsxs13("div", { className: `mx-auto w-full max-w-3xl px-6 ${quiet ? "group pb-1 pt-3" : "py-3"}`, children: [
6564
+ /* @__PURE__ */ jsxs13("div", { className: `ml-auto w-fit ${quiet ? "max-w-[72%]" : "max-w-[85%]"}`, children: [
6565
+ !quiet && /* @__PURE__ */ jsx15("p", { className: "mb-1 text-right text-xs font-semibold uppercase tracking-[0.05em] text-muted-foreground", children: userLabel }),
6566
+ /* @__PURE__ */ jsx15(
5975
6567
  "div",
5976
6568
  {
5977
6569
  className: quiet ? `rounded-2xl bg-[color-mix(in_srgb,hsl(var(--secondary))_65%,hsl(var(--background)))] px-4 py-2.5 ${messageClassName}` : `rounded-2xl rounded-tr-md bg-primary/10 px-4 py-2.5 ${messageClassName}`,
5978
- children: /* @__PURE__ */ jsx13("p", { className: "whitespace-pre-wrap", children: msg.content })
6570
+ children: /* @__PURE__ */ jsx15("p", { className: "whitespace-pre-wrap", children: msg.content })
5979
6571
  }
5980
6572
  ),
5981
- resolveAttachmentUrl && attachmentPartsFromMessageParts(msg.parts).length > 0 && /* @__PURE__ */ jsx13("div", { className: "mt-1.5", children: /* @__PURE__ */ jsx13(
6573
+ resolveAttachmentUrl && attachmentPartsFromMessageParts(msg.parts).length > 0 && /* @__PURE__ */ jsx15("div", { className: "mt-1.5", children: /* @__PURE__ */ jsx15(
5982
6574
  MessageAttachments,
5983
6575
  {
5984
6576
  parts: attachmentPartsFromMessageParts(msg.parts),
@@ -5987,8 +6579,8 @@ function ChatMessages({
5987
6579
  }
5988
6580
  ) })
5989
6581
  ] }),
5990
- quiet && /* @__PURE__ */ jsx13("div", { "data-testid": "message-meta-lane", className: `${QUIET_META_LANE_CLASS} justify-end`, children: /* @__PURE__ */ jsx13(CopyMessageButton, { text: msg.content }) })
5991
- ] }, msg.id) : /* @__PURE__ */ jsx13(
6582
+ quiet && /* @__PURE__ */ jsx15("div", { "data-testid": "message-meta-lane", className: `${QUIET_META_LANE_CLASS} justify-end`, children: /* @__PURE__ */ jsx15(CopyMessageButton, { text: msg.content }) })
6583
+ ] }, msg.id) : /* @__PURE__ */ jsx15(
5992
6584
  AssistantMessage,
5993
6585
  {
5994
6586
  msg,
@@ -6009,8 +6601,8 @@ function ChatMessages({
6009
6601
  msg.id
6010
6602
  )
6011
6603
  ),
6012
- loading && lastIsUser && /* @__PURE__ */ jsx13(ThinkingRow, { agentLabel, chrome }),
6013
- error && !loading && /* @__PURE__ */ jsx13(StreamErrorRow, { message: error, onRetry })
6604
+ loading && lastIsUser && /* @__PURE__ */ jsx15(ThinkingRow, { agentLabel, chrome }),
6605
+ error && !loading && /* @__PURE__ */ jsx15(StreamErrorRow, { message: error, onRetry })
6014
6606
  ] });
6015
6607
  }
6016
6608
 
@@ -6119,6 +6711,26 @@ export {
6119
6711
  withoutRecordGridRemoved,
6120
6712
  pruneRecordGridOverlay,
6121
6713
  RecordGrid,
6714
+ DEFAULT_SPARKLINE_WIDTH,
6715
+ DEFAULT_SPARKLINE_HEIGHT,
6716
+ DEFAULT_SPARKLINE_LABEL,
6717
+ DEFAULT_SPARKLINE_EMPTY_LABEL,
6718
+ DEFAULT_SPARKLINE_UNAVAILABLE_LABEL,
6719
+ formatSparklineValue,
6720
+ sparklineReadings,
6721
+ sparklineGeometry,
6722
+ sparklinePointsAttribute,
6723
+ sparklineLabel,
6724
+ Sparkline,
6725
+ insightDelta,
6726
+ insightDeltaTone,
6727
+ formatInsightDelta,
6728
+ InsightCard,
6729
+ DEFAULT_INSIGHT_PAGE_SIZE,
6730
+ insightPageSize,
6731
+ insightPageCount,
6732
+ insightPageSlice,
6733
+ InsightDeck,
6122
6734
  formatModelCost,
6123
6735
  formatTokensPerSecond,
6124
6736
  RunDrillIn,
@@ -6128,4 +6740,4 @@ export {
6128
6740
  useThinkingSeconds,
6129
6741
  ChatMessages
6130
6742
  };
6131
- //# sourceMappingURL=chunk-ZAKKG6WI.js.map
6743
+ //# sourceMappingURL=chunk-7HY4LX7O.js.map