@tangle-network/agent-app 0.46.3 → 0.46.5
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/dist/assistant/index.js +6 -3
- package/dist/assistant/index.js.map +1 -1
- package/dist/chat-react/index.d.ts +10 -24
- package/dist/chat-react/index.js +6 -127
- package/dist/chat-react/index.js.map +1 -1
- package/dist/chunk-3HUFJ5LO.js +24 -0
- package/dist/chunk-3HUFJ5LO.js.map +1 -0
- package/dist/chunk-5SSUCLBW.js +1896 -0
- package/dist/chunk-5SSUCLBW.js.map +1 -0
- package/dist/{chunk-RZ6MYWMJ.js → chunk-JAYKCWW4.js} +625 -1551
- package/dist/chunk-JAYKCWW4.js.map +1 -0
- package/dist/chunk-L7MB2LLM.js +15 -0
- package/dist/chunk-L7MB2LLM.js.map +1 -0
- package/dist/mention-editor-WW7UVZMR.js +523 -0
- package/dist/mention-editor-WW7UVZMR.js.map +1 -0
- package/dist/teams/drizzle/invitations-schema.d.ts +1 -1
- package/dist/teams/drizzle/schema.d.ts +1 -1
- package/dist/web-react/chat-composer.d.ts +24 -4
- package/dist/{chat-react → web-react}/composer-mode-controls.d.ts +11 -1
- package/dist/{chat-react → web-react}/entry-composer.d.ts +11 -8
- package/dist/web-react/index.d.ts +3 -0
- package/dist/web-react/index.js +17 -8
- package/dist/web-react/mention-boundaries.d.ts +33 -0
- package/dist/web-react/mention-editor.d.ts +84 -0
- package/dist/web-react/mention-list.d.ts +35 -0
- package/dist/web-react/mention-pill.d.ts +10 -0
- package/dist/web-react/mention-serialize.d.ts +44 -0
- package/dist/web-react/use-file-mentions.d.ts +28 -14
- package/package.json +32 -1
- package/dist/chat-react/types.d.ts +0 -11
- package/dist/chunk-DINGA2MO.js +0 -718
- package/dist/chunk-DINGA2MO.js.map +0 -1
- package/dist/chunk-RZ6MYWMJ.js.map +0 -1
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
import {
|
|
2
|
+
PATH_CONTINUATION_CHAR,
|
|
3
|
+
WORD_CHAR,
|
|
4
|
+
charAt,
|
|
5
|
+
charBefore
|
|
6
|
+
} from "./chunk-3HUFJ5LO.js";
|
|
1
7
|
import {
|
|
2
8
|
stepActivityFlowTrace
|
|
3
9
|
} from "./chunk-FBVLEGEG.js";
|
|
@@ -6,9 +12,8 @@ import {
|
|
|
6
12
|
workProductPartsFromMessageParts
|
|
7
13
|
} from "./chunk-ENLRJYVW.js";
|
|
8
14
|
import {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
} from "./chunk-DINGA2MO.js";
|
|
15
|
+
joinClasses
|
|
16
|
+
} from "./chunk-L7MB2LLM.js";
|
|
12
17
|
import {
|
|
13
18
|
BrainGlyph,
|
|
14
19
|
ChevronDown,
|
|
@@ -45,7 +50,7 @@ import {
|
|
|
45
50
|
} from "./chunk-YJMCRXQQ.js";
|
|
46
51
|
|
|
47
52
|
// src/web-react/index.tsx
|
|
48
|
-
import { useEffect as
|
|
53
|
+
import { useEffect as useEffect11, useMemo as useMemo7, useRef as useRef11, useState as useState15, memo } from "react";
|
|
49
54
|
import { InlineToolItem, RunRowShell } from "@tangle-network/ui/run";
|
|
50
55
|
|
|
51
56
|
// src/web-react/smooth-text.ts
|
|
@@ -1410,921 +1415,8 @@ async function streamChatTurn(opts) {
|
|
|
1410
1415
|
}
|
|
1411
1416
|
}
|
|
1412
1417
|
|
|
1413
|
-
// src/web-react/chat-composer.tsx
|
|
1414
|
-
import {
|
|
1415
|
-
useCallback as useCallback3,
|
|
1416
|
-
useEffect as useEffect6,
|
|
1417
|
-
useMemo as useMemo3,
|
|
1418
|
-
useId,
|
|
1419
|
-
useRef as useRef6,
|
|
1420
|
-
useState as useState8
|
|
1421
|
-
} from "react";
|
|
1422
|
-
|
|
1423
|
-
// src/web-react/use-dictation.ts
|
|
1424
|
-
import { useCallback as useCallback2, useEffect as useEffect5, useRef as useRef5, useState as useState7 } from "react";
|
|
1425
|
-
var PREFERRED_MIME_TYPES = ["audio/webm;codecs=opus", "audio/webm", "audio/mp4"];
|
|
1426
|
-
function pickDictationMimeType() {
|
|
1427
|
-
if (typeof MediaRecorder === "undefined" || typeof MediaRecorder.isTypeSupported !== "function") {
|
|
1428
|
-
return void 0;
|
|
1429
|
-
}
|
|
1430
|
-
for (const type of PREFERRED_MIME_TYPES) {
|
|
1431
|
-
if (MediaRecorder.isTypeSupported(type)) return type;
|
|
1432
|
-
}
|
|
1433
|
-
return void 0;
|
|
1434
|
-
}
|
|
1435
|
-
function detectDictationSupport() {
|
|
1436
|
-
return typeof navigator !== "undefined" && typeof navigator.mediaDevices?.getUserMedia === "function" && typeof MediaRecorder !== "undefined";
|
|
1437
|
-
}
|
|
1438
|
-
function dictationErrorMessage(error) {
|
|
1439
|
-
if (error instanceof DOMException) {
|
|
1440
|
-
if (error.name === "NotAllowedError") return "Microphone access was denied \u2014 allow it in the browser to dictate.";
|
|
1441
|
-
if (error.name === "NotFoundError") return "No microphone found on this device.";
|
|
1442
|
-
}
|
|
1443
|
-
return "Could not start recording.";
|
|
1444
|
-
}
|
|
1445
|
-
function formatDictationElapsed(totalSeconds) {
|
|
1446
|
-
const safe = Number.isFinite(totalSeconds) && totalSeconds > 0 ? Math.floor(totalSeconds) : 0;
|
|
1447
|
-
const minutes = Math.floor(safe / 60);
|
|
1448
|
-
const seconds = safe % 60;
|
|
1449
|
-
return `${minutes}:${String(seconds).padStart(2, "0")}`;
|
|
1450
|
-
}
|
|
1451
|
-
function releaseStream(stream) {
|
|
1452
|
-
for (const track of stream.getTracks()) track.stop();
|
|
1453
|
-
}
|
|
1454
|
-
function useDictation({ onDictate, onError }) {
|
|
1455
|
-
const [supported] = useState7(detectDictationSupport);
|
|
1456
|
-
const [recording, setRecording] = useState7(false);
|
|
1457
|
-
const [elapsedSeconds, setElapsedSeconds] = useState7(0);
|
|
1458
|
-
const sessionRef = useRef5(null);
|
|
1459
|
-
const cancelPendingStartRef = useRef5(null);
|
|
1460
|
-
const callbacksRef = useRef5({ onDictate, onError });
|
|
1461
|
-
callbacksRef.current = { onDictate, onError };
|
|
1462
|
-
useEffect5(() => {
|
|
1463
|
-
if (!recording) return;
|
|
1464
|
-
setElapsedSeconds(0);
|
|
1465
|
-
const id = setInterval(() => setElapsedSeconds((s) => s + 1), 1e3);
|
|
1466
|
-
return () => clearInterval(id);
|
|
1467
|
-
}, [recording]);
|
|
1468
|
-
const teardown = useCallback2((cancelled) => {
|
|
1469
|
-
const session = sessionRef.current;
|
|
1470
|
-
if (session === null) return;
|
|
1471
|
-
session.cancelled = session.cancelled || cancelled;
|
|
1472
|
-
sessionRef.current = null;
|
|
1473
|
-
releaseStream(session.stream);
|
|
1474
|
-
setRecording(false);
|
|
1475
|
-
}, []);
|
|
1476
|
-
const stop = useCallback2(() => {
|
|
1477
|
-
cancelPendingStartRef.current?.();
|
|
1478
|
-
cancelPendingStartRef.current = null;
|
|
1479
|
-
const session = sessionRef.current;
|
|
1480
|
-
if (session === null || session.cancelled) return;
|
|
1481
|
-
if (session.recorder.state !== "inactive") session.recorder.stop();
|
|
1482
|
-
}, []);
|
|
1483
|
-
const start = useCallback2(() => {
|
|
1484
|
-
if (!supported) return;
|
|
1485
|
-
if (sessionRef.current !== null || cancelPendingStartRef.current !== null) return;
|
|
1486
|
-
let pendingCancelled = false;
|
|
1487
|
-
cancelPendingStartRef.current = () => {
|
|
1488
|
-
pendingCancelled = true;
|
|
1489
|
-
};
|
|
1490
|
-
navigator.mediaDevices.getUserMedia({ audio: true }).then(
|
|
1491
|
-
(stream) => {
|
|
1492
|
-
cancelPendingStartRef.current = null;
|
|
1493
|
-
if (pendingCancelled) {
|
|
1494
|
-
releaseStream(stream);
|
|
1495
|
-
return;
|
|
1496
|
-
}
|
|
1497
|
-
const mimeType = pickDictationMimeType();
|
|
1498
|
-
const recorder = new MediaRecorder(stream, mimeType === void 0 ? void 0 : { mimeType });
|
|
1499
|
-
const session = {
|
|
1500
|
-
stream,
|
|
1501
|
-
recorder,
|
|
1502
|
-
chunks: [],
|
|
1503
|
-
mimeType: recorder.mimeType || mimeType || "",
|
|
1504
|
-
startedAt: Date.now(),
|
|
1505
|
-
cancelled: false
|
|
1506
|
-
};
|
|
1507
|
-
sessionRef.current = session;
|
|
1508
|
-
recorder.ondataavailable = (event) => {
|
|
1509
|
-
if (event.data.size > 0) session.chunks.push(event.data);
|
|
1510
|
-
};
|
|
1511
|
-
recorder.onstop = () => {
|
|
1512
|
-
teardown(session.cancelled);
|
|
1513
|
-
if (session.cancelled) return;
|
|
1514
|
-
const blob = new Blob(session.chunks, { type: session.mimeType });
|
|
1515
|
-
if (blob.size === 0) {
|
|
1516
|
-
callbacksRef.current.onError?.("Nothing was recorded.");
|
|
1517
|
-
return;
|
|
1518
|
-
}
|
|
1519
|
-
const durationSeconds = Math.max(0, Math.round((Date.now() - session.startedAt) / 1e3));
|
|
1520
|
-
callbacksRef.current.onDictate({ blob, mimeType: session.mimeType, durationSeconds });
|
|
1521
|
-
};
|
|
1522
|
-
recorder.onerror = () => {
|
|
1523
|
-
teardown(true);
|
|
1524
|
-
callbacksRef.current.onError?.("Recording stopped unexpectedly.");
|
|
1525
|
-
};
|
|
1526
|
-
recorder.start();
|
|
1527
|
-
setRecording(true);
|
|
1528
|
-
},
|
|
1529
|
-
(error) => {
|
|
1530
|
-
cancelPendingStartRef.current = null;
|
|
1531
|
-
if (pendingCancelled) return;
|
|
1532
|
-
callbacksRef.current.onError?.(dictationErrorMessage(error));
|
|
1533
|
-
}
|
|
1534
|
-
);
|
|
1535
|
-
}, [supported, teardown]);
|
|
1536
|
-
useEffect5(
|
|
1537
|
-
() => () => {
|
|
1538
|
-
cancelPendingStartRef.current?.();
|
|
1539
|
-
cancelPendingStartRef.current = null;
|
|
1540
|
-
const session = sessionRef.current;
|
|
1541
|
-
if (session === null) return;
|
|
1542
|
-
session.cancelled = true;
|
|
1543
|
-
sessionRef.current = null;
|
|
1544
|
-
try {
|
|
1545
|
-
if (session.recorder.state !== "inactive") session.recorder.stop();
|
|
1546
|
-
} finally {
|
|
1547
|
-
releaseStream(session.stream);
|
|
1548
|
-
}
|
|
1549
|
-
},
|
|
1550
|
-
[]
|
|
1551
|
-
);
|
|
1552
|
-
return { supported, recording, elapsedSeconds, start, stop };
|
|
1553
|
-
}
|
|
1554
|
-
|
|
1555
|
-
// src/web-react/chat-composer.tsx
|
|
1556
|
-
import { Fragment as Fragment2, jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
1557
|
-
var IS_APPLE_PLATFORM = typeof navigator !== "undefined" && /Mac|iPhone|iPad|iPod/i.test(navigator.platform);
|
|
1558
|
-
function SendGlyph({ className }) {
|
|
1559
|
-
return /* @__PURE__ */ jsx7("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: /* @__PURE__ */ jsx7("path", { d: "M22 2 11 13M22 2l-7 20-4-9-9-4 20-7z" }) });
|
|
1560
|
-
}
|
|
1561
|
-
function StopGlyph({ className }) {
|
|
1562
|
-
return /* @__PURE__ */ jsx7("svg", { className, viewBox: "0 0 24 24", fill: "currentColor", "aria-hidden": true, children: /* @__PURE__ */ jsx7("rect", { x: "6", y: "6", width: "12", height: "12", rx: "2" }) });
|
|
1563
|
-
}
|
|
1564
|
-
function ArrowUpGlyph({ className }) {
|
|
1565
|
-
return /* @__PURE__ */ jsx7("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: /* @__PURE__ */ jsx7("path", { d: "M12 19V5M5 12l7-7 7 7" }) });
|
|
1566
|
-
}
|
|
1567
|
-
function PaperclipGlyph({ className }) {
|
|
1568
|
-
return /* @__PURE__ */ jsx7("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: /* @__PURE__ */ jsx7("path", { d: "m21.44 11.05-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48" }) });
|
|
1569
|
-
}
|
|
1570
|
-
function FolderGlyph({ className }) {
|
|
1571
|
-
return /* @__PURE__ */ jsxs5("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: [
|
|
1572
|
-
/* @__PURE__ */ jsx7("path", { d: "M4 20h16a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.93a2 2 0 0 1-1.66-.9l-.82-1.2A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13c0 1.1.9 2 2 2Z" }),
|
|
1573
|
-
/* @__PURE__ */ jsx7("path", { d: "M12 10v6m-3-3h6" })
|
|
1574
|
-
] });
|
|
1575
|
-
}
|
|
1576
|
-
function CloseGlyph({ className }) {
|
|
1577
|
-
return /* @__PURE__ */ jsx7("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", "aria-hidden": true, children: /* @__PURE__ */ jsx7("path", { d: "M18 6 6 18M6 6l12 12" }) });
|
|
1578
|
-
}
|
|
1579
|
-
function RetryGlyph({ className }) {
|
|
1580
|
-
return /* @__PURE__ */ jsxs5("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: [
|
|
1581
|
-
/* @__PURE__ */ jsx7("path", { d: "M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8" }),
|
|
1582
|
-
/* @__PURE__ */ jsx7("path", { d: "M3 3v5h5" })
|
|
1583
|
-
] });
|
|
1584
|
-
}
|
|
1585
|
-
function UploadGlyph({ className }) {
|
|
1586
|
-
return /* @__PURE__ */ jsx7("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: /* @__PURE__ */ jsx7("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4M17 8l-5-5-5 5M12 3v12" }) });
|
|
1587
|
-
}
|
|
1588
|
-
function MicGlyph({ className }) {
|
|
1589
|
-
return /* @__PURE__ */ jsxs5("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: [
|
|
1590
|
-
/* @__PURE__ */ jsx7("rect", { x: "9", y: "2", width: "6", height: "12", rx: "3" }),
|
|
1591
|
-
/* @__PURE__ */ jsx7("path", { d: "M5 10v1a7 7 0 0 0 14 0v-1M12 18v4" })
|
|
1592
|
-
] });
|
|
1593
|
-
}
|
|
1594
|
-
var DEFAULT_MAX_HEIGHT = 168;
|
|
1595
|
-
var LINE_HEIGHT = 24;
|
|
1596
|
-
var TEXTAREA_PADDING_Y = 8;
|
|
1597
|
-
var DEFAULT_SEND_FAILURE = "Message not sent. Your draft is still here \u2014 try again.";
|
|
1598
|
-
function isRejectedOutcome(outcome) {
|
|
1599
|
-
return typeof outcome === "object" && outcome !== null && outcome.ok === false;
|
|
1600
|
-
}
|
|
1601
|
-
function isPromise(value) {
|
|
1602
|
-
return typeof value?.then === "function";
|
|
1603
|
-
}
|
|
1604
|
-
function sendFailureText(error, fallback) {
|
|
1605
|
-
if (typeof error === "object" && error !== null && "ok" in error) {
|
|
1606
|
-
const named = error.error;
|
|
1607
|
-
if (typeof named === "string" && named.trim() !== "") return named;
|
|
1608
|
-
return fallback;
|
|
1609
|
-
}
|
|
1610
|
-
if (typeof error === "string" && error.trim() !== "") return error;
|
|
1611
|
-
if (error instanceof Error && error.message.trim() !== "") return error.message;
|
|
1612
|
-
return fallback;
|
|
1613
|
-
}
|
|
1614
|
-
function ChatComposer({
|
|
1615
|
-
onSend,
|
|
1616
|
-
onSendParts,
|
|
1617
|
-
onSendFailed,
|
|
1618
|
-
sendFailureMessage = DEFAULT_SEND_FAILURE,
|
|
1619
|
-
onCancel,
|
|
1620
|
-
isStreaming = false,
|
|
1621
|
-
disabled = false,
|
|
1622
|
-
placeholder = "Message the agent\u2026",
|
|
1623
|
-
value,
|
|
1624
|
-
onValueChange,
|
|
1625
|
-
initialValue,
|
|
1626
|
-
seed,
|
|
1627
|
-
onSeedApplied,
|
|
1628
|
-
controls,
|
|
1629
|
-
controlsPlacement = "inline",
|
|
1630
|
-
onAttach,
|
|
1631
|
-
onAttachFolder,
|
|
1632
|
-
pendingFiles = [],
|
|
1633
|
-
onRemoveFile,
|
|
1634
|
-
onRetryFile,
|
|
1635
|
-
accept,
|
|
1636
|
-
onRejectFiles,
|
|
1637
|
-
dropTitle = "Drop files to add context",
|
|
1638
|
-
dropDescription = "They attach to your next message.",
|
|
1639
|
-
contextItems = [],
|
|
1640
|
-
canSubmitAttachmentsOnly = false,
|
|
1641
|
-
attachmentsNotReadyMessage,
|
|
1642
|
-
canSubmitWhileBusy = false,
|
|
1643
|
-
autoFocus,
|
|
1644
|
-
minRows = 2,
|
|
1645
|
-
maxHeight = DEFAULT_MAX_HEIGHT,
|
|
1646
|
-
trailing,
|
|
1647
|
-
slashCommands,
|
|
1648
|
-
onDictate,
|
|
1649
|
-
onDictateError,
|
|
1650
|
-
focusShortcut = true,
|
|
1651
|
-
floating = false,
|
|
1652
|
-
sendLabel = "Send",
|
|
1653
|
-
sendVariant = "pill",
|
|
1654
|
-
className
|
|
1655
|
-
}) {
|
|
1656
|
-
const isControlled = value !== void 0;
|
|
1657
|
-
const [internal, setInternal] = useState8(initialValue ?? "");
|
|
1658
|
-
const text = isControlled ? value : internal;
|
|
1659
|
-
const textRef = useRef6(text);
|
|
1660
|
-
textRef.current = text;
|
|
1661
|
-
const textareaRef = useRef6(null);
|
|
1662
|
-
const fileInputRef = useRef6(null);
|
|
1663
|
-
const folderInputRef = useRef6(null);
|
|
1664
|
-
const [dragOver, setDragOver] = useState8(false);
|
|
1665
|
-
const dragDepth = useRef6(0);
|
|
1666
|
-
const pastedImageCount = useRef6(0);
|
|
1667
|
-
const setText = useCallback3(
|
|
1668
|
-
(next) => {
|
|
1669
|
-
if (!isControlled) setInternal(next);
|
|
1670
|
-
onValueChange?.(next);
|
|
1671
|
-
},
|
|
1672
|
-
[isControlled, onValueChange]
|
|
1673
|
-
);
|
|
1674
|
-
const [dictateError, setDictateError] = useState8(null);
|
|
1675
|
-
const handleDictated = useCallback3(
|
|
1676
|
-
(audio) => {
|
|
1677
|
-
setDictateError(null);
|
|
1678
|
-
onDictate?.(audio);
|
|
1679
|
-
},
|
|
1680
|
-
[onDictate]
|
|
1681
|
-
);
|
|
1682
|
-
const handleDictateError = useCallback3(
|
|
1683
|
-
(message) => {
|
|
1684
|
-
setDictateError(message);
|
|
1685
|
-
onDictateError?.(message);
|
|
1686
|
-
},
|
|
1687
|
-
[onDictateError]
|
|
1688
|
-
);
|
|
1689
|
-
const dictation = useDictation({ onDictate: handleDictated, onError: handleDictateError });
|
|
1690
|
-
useEffect6(() => {
|
|
1691
|
-
const el = textareaRef.current;
|
|
1692
|
-
if (!el) return;
|
|
1693
|
-
el.style.height = "auto";
|
|
1694
|
-
el.style.height = `${Math.min(el.scrollHeight, maxHeight)}px`;
|
|
1695
|
-
}, [text, maxHeight, minRows]);
|
|
1696
|
-
const prevSeedRef = useRef6(null);
|
|
1697
|
-
const pendingCaretRef = useRef6(null);
|
|
1698
|
-
useEffect6(() => {
|
|
1699
|
-
const prev = prevSeedRef.current;
|
|
1700
|
-
prevSeedRef.current = seed ?? null;
|
|
1701
|
-
if (seed == null || seed === prev || isControlled) return;
|
|
1702
|
-
setText(seed);
|
|
1703
|
-
onSeedApplied?.();
|
|
1704
|
-
const el = textareaRef.current;
|
|
1705
|
-
if (el && el.value === seed) {
|
|
1706
|
-
el.focus();
|
|
1707
|
-
el.setSelectionRange(seed.length, seed.length);
|
|
1708
|
-
} else {
|
|
1709
|
-
pendingCaretRef.current = seed;
|
|
1710
|
-
}
|
|
1711
|
-
}, [seed, setText, onSeedApplied, isControlled]);
|
|
1712
|
-
useEffect6(() => {
|
|
1713
|
-
if (pendingCaretRef.current == null || pendingCaretRef.current !== text)
|
|
1714
|
-
return;
|
|
1715
|
-
pendingCaretRef.current = null;
|
|
1716
|
-
const el = textareaRef.current;
|
|
1717
|
-
if (!el) return;
|
|
1718
|
-
el.focus();
|
|
1719
|
-
el.setSelectionRange(text.length, text.length);
|
|
1720
|
-
}, [text]);
|
|
1721
|
-
const restoreCaretRef = useRef6(null);
|
|
1722
|
-
useEffect6(() => {
|
|
1723
|
-
const pending = restoreCaretRef.current;
|
|
1724
|
-
if (!pending || pending.text !== text) return;
|
|
1725
|
-
restoreCaretRef.current = null;
|
|
1726
|
-
const el = textareaRef.current;
|
|
1727
|
-
if (!el) return;
|
|
1728
|
-
el.focus();
|
|
1729
|
-
const start = Math.min(pending.start, text.length);
|
|
1730
|
-
const end = Math.min(pending.end, text.length);
|
|
1731
|
-
el.setSelectionRange(start, end);
|
|
1732
|
-
}, [text]);
|
|
1733
|
-
useEffect6(() => {
|
|
1734
|
-
if (!focusShortcut || disabled) return;
|
|
1735
|
-
function onKeyDown(e) {
|
|
1736
|
-
if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === "l") {
|
|
1737
|
-
e.preventDefault();
|
|
1738
|
-
textareaRef.current?.focus();
|
|
1739
|
-
}
|
|
1740
|
-
}
|
|
1741
|
-
document.addEventListener("keydown", onKeyDown);
|
|
1742
|
-
return () => document.removeEventListener("keydown", onKeyDown);
|
|
1743
|
-
}, [focusShortcut, disabled]);
|
|
1744
|
-
const sendableFiles = canSubmitAttachmentsOnly ? pendingFiles : pendingFiles.filter((f) => f.status === "ready");
|
|
1745
|
-
const hasSendable = text.trim().length > 0 || sendableFiles.length > 0;
|
|
1746
|
-
const sendBlockedByStream = isStreaming && !canSubmitWhileBusy;
|
|
1747
|
-
const canSend = hasSendable && !sendBlockedByStream && !disabled;
|
|
1748
|
-
const [failedSend, setFailedSend] = useState8(null);
|
|
1749
|
-
const failSend = useCallback3(
|
|
1750
|
-
(error, draft, trimmed, parts, caret) => {
|
|
1751
|
-
const message = sendFailureText(error, sendFailureMessage);
|
|
1752
|
-
const restored = textRef.current === "";
|
|
1753
|
-
if (restored) {
|
|
1754
|
-
const el = textareaRef.current;
|
|
1755
|
-
setText(draft);
|
|
1756
|
-
if (el && el.value === draft) {
|
|
1757
|
-
el.focus();
|
|
1758
|
-
el.setSelectionRange(Math.min(caret.start, draft.length), Math.min(caret.end, draft.length));
|
|
1759
|
-
} else {
|
|
1760
|
-
restoreCaretRef.current = { text: draft, start: caret.start, end: caret.end };
|
|
1761
|
-
}
|
|
1762
|
-
}
|
|
1763
|
-
setFailedSend({ message, text: draft, trimmed, parts, restored });
|
|
1764
|
-
onSendFailed?.({ message, text: draft, parts, error, restored });
|
|
1765
|
-
},
|
|
1766
|
-
[onSendFailed, sendFailureMessage, setText]
|
|
1767
|
-
);
|
|
1768
|
-
const dispatchSend = useCallback3(
|
|
1769
|
-
(draft, trimmed, parts, caret) => {
|
|
1770
|
-
let outcome;
|
|
1771
|
-
try {
|
|
1772
|
-
outcome = onSendParts ? onSendParts(trimmed, parts) : onSend?.(trimmed);
|
|
1773
|
-
} catch (error) {
|
|
1774
|
-
failSend(error, draft, trimmed, parts, caret);
|
|
1775
|
-
return;
|
|
1776
|
-
}
|
|
1777
|
-
if (isPromise(outcome)) {
|
|
1778
|
-
void outcome.then(
|
|
1779
|
-
(settled) => {
|
|
1780
|
-
if (isRejectedOutcome(settled)) failSend(settled, draft, trimmed, parts, caret);
|
|
1781
|
-
},
|
|
1782
|
-
(error) => failSend(error, draft, trimmed, parts, caret)
|
|
1783
|
-
);
|
|
1784
|
-
return;
|
|
1785
|
-
}
|
|
1786
|
-
if (isRejectedOutcome(outcome)) failSend(outcome, draft, trimmed, parts, caret);
|
|
1787
|
-
},
|
|
1788
|
-
[onSend, onSendParts, failSend]
|
|
1789
|
-
);
|
|
1790
|
-
const send = useCallback3(() => {
|
|
1791
|
-
const trimmed = text.trim();
|
|
1792
|
-
if (sendBlockedByStream || disabled) return;
|
|
1793
|
-
const readyFiles = pendingFiles.filter((f) => f.status === "ready");
|
|
1794
|
-
const sendable = canSubmitAttachmentsOnly ? pendingFiles : readyFiles;
|
|
1795
|
-
if (!trimmed && sendable.length === 0) return;
|
|
1796
|
-
if (!trimmed && readyFiles.length === 0) {
|
|
1797
|
-
const message = attachmentsNotReadyMessage ?? (pendingFiles.some((f) => f.status === "error") ? "Retry or remove the failed attachment before sending." : "Wait for the attachment to finish uploading.");
|
|
1798
|
-
setFailedSend({ message, text: "", trimmed: "", parts: [], restored: true });
|
|
1799
|
-
return;
|
|
1800
|
-
}
|
|
1801
|
-
const parts = onSendParts ? readyFiles.filter((f) => f.part).map((f) => f.part) : [];
|
|
1802
|
-
const el = textareaRef.current;
|
|
1803
|
-
const caret = { start: el?.selectionStart ?? text.length, end: el?.selectionEnd ?? text.length };
|
|
1804
|
-
setFailedSend(null);
|
|
1805
|
-
setText("");
|
|
1806
|
-
textRef.current = "";
|
|
1807
|
-
dispatchSend(text, trimmed, parts, caret);
|
|
1808
|
-
}, [
|
|
1809
|
-
text,
|
|
1810
|
-
sendBlockedByStream,
|
|
1811
|
-
disabled,
|
|
1812
|
-
canSubmitAttachmentsOnly,
|
|
1813
|
-
attachmentsNotReadyMessage,
|
|
1814
|
-
onSendParts,
|
|
1815
|
-
pendingFiles,
|
|
1816
|
-
setText,
|
|
1817
|
-
dispatchSend
|
|
1818
|
-
]);
|
|
1819
|
-
const retryFailedSend = useCallback3(() => {
|
|
1820
|
-
const failure = failedSend;
|
|
1821
|
-
if (!failure || sendBlockedByStream || disabled) return;
|
|
1822
|
-
setFailedSend(null);
|
|
1823
|
-
const caret = { start: failure.text.length, end: failure.text.length };
|
|
1824
|
-
dispatchSend(failure.text, failure.trimmed, failure.parts, caret);
|
|
1825
|
-
}, [failedSend, sendBlockedByStream, disabled, dispatchSend]);
|
|
1826
|
-
const slashPanelRef = useRef6(null);
|
|
1827
|
-
const cardRef = useRef6(null);
|
|
1828
|
-
const slashListId = useId();
|
|
1829
|
-
const [slashActive, setSlashActive] = useState8(0);
|
|
1830
|
-
const [slashDismissedFor, setSlashDismissedFor] = useState8(null);
|
|
1831
|
-
const slashToken = slashCommands && slashCommands.length > 0 ? /^\/(\S*)$/.exec(text)?.[1] : void 0;
|
|
1832
|
-
const slashOpen = slashToken !== void 0 && text !== slashDismissedFor;
|
|
1833
|
-
const slashItems = useMemo3(
|
|
1834
|
-
() => (slashCommands ?? []).map((command) => ({
|
|
1835
|
-
id: command.name,
|
|
1836
|
-
group: "Commands",
|
|
1837
|
-
label: `/${command.name}`,
|
|
1838
|
-
description: command.description,
|
|
1839
|
-
keywords: [command.name, command.description]
|
|
1840
|
-
})),
|
|
1841
|
-
[slashCommands]
|
|
1842
|
-
);
|
|
1843
|
-
const slashFiltered = useMemo3(
|
|
1844
|
-
() => slashToken === void 0 ? [] : filterCommandPaletteItems(slashItems, slashToken),
|
|
1845
|
-
[slashItems, slashToken]
|
|
1846
|
-
);
|
|
1847
|
-
const slashActiveIndex = slashFiltered.length === 0 ? 0 : Math.min(slashActive, slashFiltered.length - 1);
|
|
1848
|
-
useEffect6(() => {
|
|
1849
|
-
setSlashActive(0);
|
|
1850
|
-
}, [slashToken]);
|
|
1851
|
-
useEffect6(() => {
|
|
1852
|
-
if (!slashOpen) return;
|
|
1853
|
-
document.getElementById(`${slashListId}-${slashActiveIndex}`)?.scrollIntoView?.({ block: "nearest" });
|
|
1854
|
-
}, [slashOpen, slashActiveIndex, slashListId]);
|
|
1855
|
-
useEffect6(() => {
|
|
1856
|
-
if (!slashOpen) return;
|
|
1857
|
-
function onMouseDown(e) {
|
|
1858
|
-
const target = e.target;
|
|
1859
|
-
if (cardRef.current?.contains(target)) return;
|
|
1860
|
-
if (slashPanelRef.current?.contains(target)) return;
|
|
1861
|
-
setSlashDismissedFor(textRef.current);
|
|
1862
|
-
}
|
|
1863
|
-
document.addEventListener("mousedown", onMouseDown);
|
|
1864
|
-
return () => document.removeEventListener("mousedown", onMouseDown);
|
|
1865
|
-
}, [slashOpen]);
|
|
1866
|
-
const pickSlash = useCallback3(
|
|
1867
|
-
(name) => {
|
|
1868
|
-
const command = slashCommands?.find((c) => c.name === name);
|
|
1869
|
-
setText("");
|
|
1870
|
-
setSlashDismissedFor(null);
|
|
1871
|
-
command?.run();
|
|
1872
|
-
},
|
|
1873
|
-
[slashCommands, setText]
|
|
1874
|
-
);
|
|
1875
|
-
const handleKeyDown = (e) => {
|
|
1876
|
-
if (e.nativeEvent.isComposing) return;
|
|
1877
|
-
if (slashOpen) {
|
|
1878
|
-
if (e.key === "ArrowDown") {
|
|
1879
|
-
e.preventDefault();
|
|
1880
|
-
if (slashFiltered.length > 0) setSlashActive((slashActiveIndex + 1) % slashFiltered.length);
|
|
1881
|
-
return;
|
|
1882
|
-
}
|
|
1883
|
-
if (e.key === "ArrowUp") {
|
|
1884
|
-
e.preventDefault();
|
|
1885
|
-
if (slashFiltered.length > 0)
|
|
1886
|
-
setSlashActive((slashActiveIndex - 1 + slashFiltered.length) % slashFiltered.length);
|
|
1887
|
-
return;
|
|
1888
|
-
}
|
|
1889
|
-
if (e.key === "Enter" && !e.shiftKey || e.key === "Tab") {
|
|
1890
|
-
const item = slashFiltered[slashActiveIndex];
|
|
1891
|
-
if (item) {
|
|
1892
|
-
e.preventDefault();
|
|
1893
|
-
pickSlash(item.id);
|
|
1894
|
-
return;
|
|
1895
|
-
}
|
|
1896
|
-
}
|
|
1897
|
-
if (e.key === "Escape") {
|
|
1898
|
-
e.preventDefault();
|
|
1899
|
-
setSlashDismissedFor(text);
|
|
1900
|
-
return;
|
|
1901
|
-
}
|
|
1902
|
-
}
|
|
1903
|
-
if (e.key === "Enter" && !e.shiftKey) {
|
|
1904
|
-
e.preventDefault();
|
|
1905
|
-
send();
|
|
1906
|
-
}
|
|
1907
|
-
};
|
|
1908
|
-
const deliverFiles = useCallback3(
|
|
1909
|
-
(files, original) => {
|
|
1910
|
-
if (!onAttach || files.length === 0) return;
|
|
1911
|
-
const { accepted, rejected } = filterAcceptedFiles(files, accept);
|
|
1912
|
-
if (rejected.length > 0) onRejectFiles?.(rejected);
|
|
1913
|
-
if (accepted.length === 0) return;
|
|
1914
|
-
const unchanged = accepted.length === original.length && accepted.every((file, i) => file === original[i]);
|
|
1915
|
-
if (unchanged) {
|
|
1916
|
-
onAttach(original);
|
|
1917
|
-
return;
|
|
1918
|
-
}
|
|
1919
|
-
const transfer = new DataTransfer();
|
|
1920
|
-
for (const file of accepted) transfer.items.add(file);
|
|
1921
|
-
onAttach(transfer.files);
|
|
1922
|
-
},
|
|
1923
|
-
[onAttach, onRejectFiles, accept]
|
|
1924
|
-
);
|
|
1925
|
-
const handleFileChange = (e) => {
|
|
1926
|
-
if (e.target.files?.length) deliverFiles(Array.from(e.target.files), e.target.files);
|
|
1927
|
-
e.target.value = "";
|
|
1928
|
-
};
|
|
1929
|
-
const handlePaste = (e) => {
|
|
1930
|
-
if (!onAttach) return;
|
|
1931
|
-
const clipboardFiles = e.clipboardData?.files;
|
|
1932
|
-
if (!clipboardFiles || clipboardFiles.length === 0) return;
|
|
1933
|
-
e.preventDefault();
|
|
1934
|
-
const { files, nextIndex } = renamePastedImages(
|
|
1935
|
-
Array.from(clipboardFiles),
|
|
1936
|
-
pastedImageCount.current,
|
|
1937
|
-
pendingFiles.map((f) => f.name)
|
|
1938
|
-
);
|
|
1939
|
-
pastedImageCount.current = nextIndex;
|
|
1940
|
-
deliverFiles(files, clipboardFiles);
|
|
1941
|
-
};
|
|
1942
|
-
const handleFolderChange = (e) => {
|
|
1943
|
-
if (e.target.files?.length) (onAttachFolder ?? onAttach)?.(e.target.files);
|
|
1944
|
-
e.target.value = "";
|
|
1945
|
-
};
|
|
1946
|
-
const handleDragEnter = useCallback3((e) => {
|
|
1947
|
-
e.preventDefault();
|
|
1948
|
-
e.stopPropagation();
|
|
1949
|
-
dragDepth.current++;
|
|
1950
|
-
if (e.dataTransfer?.types.includes("Files")) setDragOver(true);
|
|
1951
|
-
}, []);
|
|
1952
|
-
const handleDragLeave = useCallback3((e) => {
|
|
1953
|
-
e.preventDefault();
|
|
1954
|
-
e.stopPropagation();
|
|
1955
|
-
dragDepth.current--;
|
|
1956
|
-
if (dragDepth.current <= 0) {
|
|
1957
|
-
dragDepth.current = 0;
|
|
1958
|
-
setDragOver(false);
|
|
1959
|
-
}
|
|
1960
|
-
}, []);
|
|
1961
|
-
const handleDragOver = useCallback3((e) => {
|
|
1962
|
-
e.preventDefault();
|
|
1963
|
-
e.stopPropagation();
|
|
1964
|
-
if (e.dataTransfer) e.dataTransfer.dropEffect = "copy";
|
|
1965
|
-
}, []);
|
|
1966
|
-
const handleDrop = useCallback3(
|
|
1967
|
-
(e) => {
|
|
1968
|
-
e.preventDefault();
|
|
1969
|
-
e.stopPropagation();
|
|
1970
|
-
dragDepth.current = 0;
|
|
1971
|
-
setDragOver(false);
|
|
1972
|
-
const files = e.dataTransfer?.files;
|
|
1973
|
-
if (files?.length) deliverFiles(Array.from(files), files);
|
|
1974
|
-
},
|
|
1975
|
-
[deliverFiles]
|
|
1976
|
-
);
|
|
1977
|
-
const folderChips = pendingFiles.filter((f) => f.kind === "folder");
|
|
1978
|
-
const fileChips = pendingFiles.filter((f) => f.kind !== "folder");
|
|
1979
|
-
const showAbove = controls != null && controlsPlacement === "above";
|
|
1980
|
-
const showInline = controls != null && !showAbove;
|
|
1981
|
-
return /* @__PURE__ */ jsxs5(
|
|
1982
|
-
"div",
|
|
1983
|
-
{
|
|
1984
|
-
className: `relative ${className ?? ""}`,
|
|
1985
|
-
onDragEnter: onAttach ? handleDragEnter : void 0,
|
|
1986
|
-
onDragLeave: onAttach ? handleDragLeave : void 0,
|
|
1987
|
-
onDragOver: onAttach ? handleDragOver : void 0,
|
|
1988
|
-
onDrop: onAttach ? handleDrop : void 0,
|
|
1989
|
-
children: [
|
|
1990
|
-
dragOver && /* @__PURE__ */ jsx7("div", { className: "pointer-events-none absolute inset-0 z-10 flex items-center justify-center rounded-2xl border-2 border-dashed border-primary/50 bg-card", children: /* @__PURE__ */ jsxs5("div", { className: "text-center", children: [
|
|
1991
|
-
/* @__PURE__ */ jsx7("span", { className: "mx-auto mb-2 flex h-11 w-11 items-center justify-center rounded-xl bg-primary/10 text-primary", children: /* @__PURE__ */ jsx7(UploadGlyph, { className: "h-5 w-5" }) }),
|
|
1992
|
-
/* @__PURE__ */ jsx7("p", { className: "text-sm font-semibold text-foreground", children: dropTitle }),
|
|
1993
|
-
/* @__PURE__ */ jsx7("p", { className: "mt-0.5 text-xs text-muted-foreground", children: dropDescription })
|
|
1994
|
-
] }) }),
|
|
1995
|
-
showAbove && /* @__PURE__ */ jsx7("div", { className: "mb-1.5 flex flex-wrap items-center gap-1.5 px-1", children: controls }),
|
|
1996
|
-
dictateError && /* @__PURE__ */ jsxs5(
|
|
1997
|
-
"div",
|
|
1998
|
-
{
|
|
1999
|
-
role: "alert",
|
|
2000
|
-
"data-testid": "composer-dictate-error",
|
|
2001
|
-
className: "mb-2 flex items-start gap-2 rounded-xl border border-destructive/40 bg-destructive/10 px-3 py-2 text-xs text-destructive",
|
|
2002
|
-
children: [
|
|
2003
|
-
/* @__PURE__ */ jsx7("span", { className: "min-w-0 flex-1", children: dictateError }),
|
|
2004
|
-
/* @__PURE__ */ jsx7(
|
|
2005
|
-
"button",
|
|
2006
|
-
{
|
|
2007
|
-
type: "button",
|
|
2008
|
-
"aria-label": "Dismiss dictation error",
|
|
2009
|
-
onClick: () => setDictateError(null),
|
|
2010
|
-
className: "shrink-0 font-medium underline-offset-2 hover:underline focus:outline-none focus-visible:ring-2 focus-visible:ring-destructive/50",
|
|
2011
|
-
children: "Dismiss"
|
|
2012
|
-
}
|
|
2013
|
-
)
|
|
2014
|
-
]
|
|
2015
|
-
}
|
|
2016
|
-
),
|
|
2017
|
-
failedSend && /* @__PURE__ */ jsxs5(
|
|
2018
|
-
"div",
|
|
2019
|
-
{
|
|
2020
|
-
role: "alert",
|
|
2021
|
-
"data-testid": "composer-send-error",
|
|
2022
|
-
className: "mb-2 rounded-xl border border-destructive/40 bg-destructive/10 px-3 py-2 text-xs text-destructive",
|
|
2023
|
-
children: [
|
|
2024
|
-
/* @__PURE__ */ jsxs5("div", { className: "flex items-start gap-2", children: [
|
|
2025
|
-
/* @__PURE__ */ jsx7("span", { className: "min-w-0 flex-1", children: failedSend.message }),
|
|
2026
|
-
/* @__PURE__ */ jsx7(
|
|
2027
|
-
"button",
|
|
2028
|
-
{
|
|
2029
|
-
type: "button",
|
|
2030
|
-
"aria-label": "Dismiss send error",
|
|
2031
|
-
onClick: () => setFailedSend(null),
|
|
2032
|
-
className: "shrink-0 font-medium underline-offset-2 hover:underline focus:outline-none focus-visible:ring-2 focus-visible:ring-destructive/50",
|
|
2033
|
-
children: "Dismiss"
|
|
2034
|
-
}
|
|
2035
|
-
)
|
|
2036
|
-
] }),
|
|
2037
|
-
!failedSend.restored && /* @__PURE__ */ jsxs5("div", { className: "mt-1.5", children: [
|
|
2038
|
-
/* @__PURE__ */ jsx7(
|
|
2039
|
-
"p",
|
|
2040
|
-
{
|
|
2041
|
-
"data-testid": "composer-unsent-draft",
|
|
2042
|
-
className: "max-h-20 overflow-y-auto whitespace-pre-wrap rounded-lg border border-destructive/30 bg-card px-2 py-1 text-foreground",
|
|
2043
|
-
children: failedSend.text
|
|
2044
|
-
}
|
|
2045
|
-
),
|
|
2046
|
-
/* @__PURE__ */ jsx7(
|
|
2047
|
-
"button",
|
|
2048
|
-
{
|
|
2049
|
-
type: "button",
|
|
2050
|
-
"aria-label": "Retry sending the unsent message",
|
|
2051
|
-
onClick: retryFailedSend,
|
|
2052
|
-
disabled: sendBlockedByStream || disabled,
|
|
2053
|
-
className: "mt-1.5 font-medium underline-offset-2 hover:underline disabled:cursor-not-allowed disabled:opacity-50 focus:outline-none focus-visible:ring-2 focus-visible:ring-destructive/50",
|
|
2054
|
-
children: "Retry"
|
|
2055
|
-
}
|
|
2056
|
-
)
|
|
2057
|
-
] })
|
|
2058
|
-
]
|
|
2059
|
-
}
|
|
2060
|
-
),
|
|
2061
|
-
contextItems.length > 0 && /* @__PURE__ */ jsx7("div", { "aria-label": "Message context", className: "mb-2 flex min-w-0 flex-wrap gap-1.5", children: contextItems.map((item) => /* @__PURE__ */ jsxs5(
|
|
2062
|
-
"span",
|
|
2063
|
-
{
|
|
2064
|
-
className: "inline-flex min-w-0 max-w-full items-center gap-1.5 rounded-md border border-primary/30 bg-primary/10 px-2.5 py-1 text-xs text-primary",
|
|
2065
|
-
children: [
|
|
2066
|
-
item.icon && /* @__PURE__ */ jsx7("span", { className: "shrink-0", "aria-hidden": true, children: item.icon }),
|
|
2067
|
-
/* @__PURE__ */ jsx7("span", { className: "min-w-0 truncate", children: item.label }),
|
|
2068
|
-
item.onRemove && /* @__PURE__ */ jsx7(
|
|
2069
|
-
"button",
|
|
2070
|
-
{
|
|
2071
|
-
type: "button",
|
|
2072
|
-
"aria-label": `Remove context ${item.label}`,
|
|
2073
|
-
onClick: item.onRemove,
|
|
2074
|
-
className: "shrink-0 rounded p-0.5 text-primary/70 transition hover:text-primary focus:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
2075
|
-
children: /* @__PURE__ */ jsx7(CloseGlyph, { className: "h-3 w-3" })
|
|
2076
|
-
}
|
|
2077
|
-
)
|
|
2078
|
-
]
|
|
2079
|
-
},
|
|
2080
|
-
item.id
|
|
2081
|
-
)) }),
|
|
2082
|
-
pendingFiles.length > 0 && /* @__PURE__ */ jsx7("div", { className: "mb-2 flex flex-wrap gap-1.5", children: [...folderChips, ...fileChips].map((f) => {
|
|
2083
|
-
const isError = f.status === "error";
|
|
2084
|
-
return /* @__PURE__ */ jsxs5(
|
|
2085
|
-
"span",
|
|
2086
|
-
{
|
|
2087
|
-
title: isError ? f.errorMessage : void 0,
|
|
2088
|
-
className: `inline-flex items-center gap-1.5 rounded-full border px-2.5 py-1 text-xs ${isError ? "border-destructive/40 text-destructive" : "border-border bg-secondary text-foreground"} ${f.status === "pending" ? "opacity-60" : ""}`,
|
|
2089
|
-
children: [
|
|
2090
|
-
f.kind !== "folder" && f.previewUrl ? /* @__PURE__ */ jsx7("img", { src: f.previewUrl, alt: "", className: "h-8 w-8 shrink-0 rounded object-cover" }) : f.kind === "folder" ? /* @__PURE__ */ jsx7(FolderGlyph, { className: "h-3 w-3 shrink-0" }) : /* @__PURE__ */ jsx7(PaperclipGlyph, { className: "h-3 w-3 shrink-0" }),
|
|
2091
|
-
/* @__PURE__ */ jsx7("span", { className: "max-w-[150px] truncate", children: f.name }),
|
|
2092
|
-
f.fileCount !== void 0 && /* @__PURE__ */ jsxs5("span", { className: "text-muted-foreground", children: [
|
|
2093
|
-
"(",
|
|
2094
|
-
f.fileCount,
|
|
2095
|
-
")"
|
|
2096
|
-
] }),
|
|
2097
|
-
f.status === "uploading" && /* @__PURE__ */ jsx7("span", { className: "h-3 w-3 animate-spin rounded-full border-2 border-primary border-t-transparent" }),
|
|
2098
|
-
isError && f.errorMessage && /* @__PURE__ */ jsx7("span", { className: "max-w-[150px] truncate text-destructive/80", children: f.errorMessage }),
|
|
2099
|
-
isError && onRetryFile && /* @__PURE__ */ jsx7(
|
|
2100
|
-
"button",
|
|
2101
|
-
{
|
|
2102
|
-
type: "button",
|
|
2103
|
-
"aria-label": `Retry upload ${f.name}`,
|
|
2104
|
-
onClick: () => onRetryFile(f.id),
|
|
2105
|
-
className: "rounded p-0.5 text-muted-foreground transition hover:text-foreground focus:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
2106
|
-
children: /* @__PURE__ */ jsx7(RetryGlyph, { className: "h-3 w-3" })
|
|
2107
|
-
}
|
|
2108
|
-
),
|
|
2109
|
-
onRemoveFile && /* @__PURE__ */ jsx7(
|
|
2110
|
-
"button",
|
|
2111
|
-
{
|
|
2112
|
-
type: "button",
|
|
2113
|
-
"aria-label": `Remove ${f.name}`,
|
|
2114
|
-
onClick: () => onRemoveFile(f.id),
|
|
2115
|
-
className: "rounded p-0.5 text-muted-foreground transition hover:text-foreground focus:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
2116
|
-
children: /* @__PURE__ */ jsx7(CloseGlyph, { className: "h-3 w-3" })
|
|
2117
|
-
}
|
|
2118
|
-
)
|
|
2119
|
-
]
|
|
2120
|
-
},
|
|
2121
|
-
f.id
|
|
2122
|
-
);
|
|
2123
|
-
}) }),
|
|
2124
|
-
/* @__PURE__ */ jsxs5(
|
|
2125
|
-
"div",
|
|
2126
|
-
{
|
|
2127
|
-
ref: cardRef,
|
|
2128
|
-
"data-testid": "composer-card",
|
|
2129
|
-
className: `flex flex-col gap-1.5 rounded-2xl border border-card-edge bg-card px-3 py-2.5 transition focus-within:border-primary/40 focus-within:ring-2 focus-within:ring-primary/15 ${floating ? "shadow-raised" : ""}`,
|
|
2130
|
-
children: [
|
|
2131
|
-
/* @__PURE__ */ jsx7(
|
|
2132
|
-
"textarea",
|
|
2133
|
-
{
|
|
2134
|
-
ref: textareaRef,
|
|
2135
|
-
value: text,
|
|
2136
|
-
onChange: (e) => setText(e.target.value),
|
|
2137
|
-
onKeyDown: handleKeyDown,
|
|
2138
|
-
onPaste: onAttach ? handlePaste : void 0,
|
|
2139
|
-
placeholder,
|
|
2140
|
-
disabled,
|
|
2141
|
-
autoFocus,
|
|
2142
|
-
rows: minRows,
|
|
2143
|
-
style: { minHeight: minRows * LINE_HEIGHT + TEXTAREA_PADDING_Y, maxHeight },
|
|
2144
|
-
"aria-label": "Message input",
|
|
2145
|
-
className: "w-full resize-none bg-transparent px-1.5 py-1 text-base leading-6 text-foreground outline-none placeholder:text-muted-foreground disabled:opacity-50"
|
|
2146
|
-
}
|
|
2147
|
-
),
|
|
2148
|
-
/* @__PURE__ */ jsxs5("div", { className: "flex items-end gap-2", children: [
|
|
2149
|
-
onAttach && /* @__PURE__ */ jsxs5(Fragment2, { children: [
|
|
2150
|
-
/* @__PURE__ */ jsx7(
|
|
2151
|
-
"button",
|
|
2152
|
-
{
|
|
2153
|
-
type: "button",
|
|
2154
|
-
onClick: () => fileInputRef.current?.click(),
|
|
2155
|
-
disabled,
|
|
2156
|
-
"aria-label": "Attach files",
|
|
2157
|
-
title: "Attach files",
|
|
2158
|
-
className: "shrink-0 rounded-lg p-2 text-muted-foreground transition hover:bg-accent hover:text-foreground disabled:opacity-50 focus:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
2159
|
-
children: /* @__PURE__ */ jsx7(PaperclipGlyph, { className: "h-4 w-4" })
|
|
2160
|
-
}
|
|
2161
|
-
),
|
|
2162
|
-
/* @__PURE__ */ jsx7("input", { ref: fileInputRef, type: "file", multiple: true, className: "hidden", accept, onChange: handleFileChange })
|
|
2163
|
-
] }),
|
|
2164
|
-
onAttachFolder && /* @__PURE__ */ jsxs5(Fragment2, { children: [
|
|
2165
|
-
/* @__PURE__ */ jsx7(
|
|
2166
|
-
"button",
|
|
2167
|
-
{
|
|
2168
|
-
type: "button",
|
|
2169
|
-
onClick: () => folderInputRef.current?.click(),
|
|
2170
|
-
disabled,
|
|
2171
|
-
"aria-label": "Attach folder",
|
|
2172
|
-
title: "Attach folder",
|
|
2173
|
-
className: "shrink-0 rounded-lg p-2 text-muted-foreground transition hover:bg-accent hover:text-foreground disabled:opacity-50 focus:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
2174
|
-
children: /* @__PURE__ */ jsx7(FolderGlyph, { className: "h-4 w-4" })
|
|
2175
|
-
}
|
|
2176
|
-
),
|
|
2177
|
-
/* @__PURE__ */ jsx7(
|
|
2178
|
-
"input",
|
|
2179
|
-
{
|
|
2180
|
-
ref: folderInputRef,
|
|
2181
|
-
type: "file",
|
|
2182
|
-
multiple: true,
|
|
2183
|
-
className: "hidden",
|
|
2184
|
-
onChange: handleFolderChange,
|
|
2185
|
-
...{ webkitdirectory: "" }
|
|
2186
|
-
}
|
|
2187
|
-
)
|
|
2188
|
-
] }),
|
|
2189
|
-
/* @__PURE__ */ jsx7(
|
|
2190
|
-
"div",
|
|
2191
|
-
{
|
|
2192
|
-
"data-testid": "composer-controls",
|
|
2193
|
-
className: "flex min-w-0 flex-1 flex-wrap items-center gap-1.5",
|
|
2194
|
-
children: showInline && controls
|
|
2195
|
-
}
|
|
2196
|
-
),
|
|
2197
|
-
trailing && /* @__PURE__ */ jsx7("div", { "data-testid": "composer-trailing", className: "flex shrink-0 items-center gap-1.5", children: trailing }),
|
|
2198
|
-
onDictate && dictation.supported ? dictation.recording ? /* @__PURE__ */ jsxs5("div", { className: "flex shrink-0 items-center gap-1.5", children: [
|
|
2199
|
-
/* @__PURE__ */ jsx7("span", { "aria-hidden": "true", className: "h-2 w-2 animate-pulse rounded-full bg-destructive" }),
|
|
2200
|
-
/* @__PURE__ */ jsx7(
|
|
2201
|
-
"span",
|
|
2202
|
-
{
|
|
2203
|
-
"aria-hidden": "true",
|
|
2204
|
-
"data-testid": "composer-dictate-elapsed",
|
|
2205
|
-
className: "text-xs tabular-nums text-muted-foreground",
|
|
2206
|
-
children: formatDictationElapsed(dictation.elapsedSeconds)
|
|
2207
|
-
}
|
|
2208
|
-
),
|
|
2209
|
-
/* @__PURE__ */ jsx7("span", { role: "status", className: "sr-only", children: "Recording" }),
|
|
2210
|
-
/* @__PURE__ */ jsx7(
|
|
2211
|
-
"button",
|
|
2212
|
-
{
|
|
2213
|
-
type: "button",
|
|
2214
|
-
onClick: dictation.stop,
|
|
2215
|
-
"aria-label": "Stop dictation",
|
|
2216
|
-
title: "Stop dictation",
|
|
2217
|
-
className: "shrink-0 rounded-lg p-2 text-destructive transition hover:bg-accent focus:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
2218
|
-
children: /* @__PURE__ */ jsx7(StopGlyph, { className: "h-4 w-4" })
|
|
2219
|
-
}
|
|
2220
|
-
)
|
|
2221
|
-
] }) : /* @__PURE__ */ jsx7(
|
|
2222
|
-
"button",
|
|
2223
|
-
{
|
|
2224
|
-
type: "button",
|
|
2225
|
-
onClick: dictation.start,
|
|
2226
|
-
disabled,
|
|
2227
|
-
"aria-label": "Dictate message",
|
|
2228
|
-
title: "Dictate message",
|
|
2229
|
-
className: "shrink-0 rounded-lg p-2 text-muted-foreground transition hover:bg-accent hover:text-foreground disabled:opacity-50 focus:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
2230
|
-
children: /* @__PURE__ */ jsx7(MicGlyph, { className: "h-4 w-4" })
|
|
2231
|
-
}
|
|
2232
|
-
) : null,
|
|
2233
|
-
isStreaming ? sendVariant === "icon" ? /* @__PURE__ */ jsx7(
|
|
2234
|
-
"button",
|
|
2235
|
-
{
|
|
2236
|
-
type: "button",
|
|
2237
|
-
onClick: onCancel,
|
|
2238
|
-
"aria-label": "Stop response",
|
|
2239
|
-
title: "Stop",
|
|
2240
|
-
className: "inline-flex h-[34px] w-[34px] shrink-0 items-center justify-center rounded-full border border-border bg-transparent text-foreground transition hover:bg-accent focus:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
2241
|
-
children: /* @__PURE__ */ jsx7(StopGlyph, { className: "h-3 w-3" })
|
|
2242
|
-
}
|
|
2243
|
-
) : /* @__PURE__ */ jsxs5(
|
|
2244
|
-
"button",
|
|
2245
|
-
{
|
|
2246
|
-
type: "button",
|
|
2247
|
-
onClick: onCancel,
|
|
2248
|
-
"aria-label": "Stop response",
|
|
2249
|
-
className: "inline-flex shrink-0 items-center gap-1.5 rounded-full bg-destructive/15 px-3.5 py-2 text-sm font-medium text-destructive transition hover:bg-destructive/25 focus:outline-none focus-visible:ring-2 focus-visible:ring-destructive/50",
|
|
2250
|
-
children: [
|
|
2251
|
-
/* @__PURE__ */ jsx7(StopGlyph, { className: "h-3.5 w-3.5" }),
|
|
2252
|
-
/* @__PURE__ */ jsx7("span", { children: "Stop" })
|
|
2253
|
-
]
|
|
2254
|
-
}
|
|
2255
|
-
) : sendVariant === "icon" ? /* @__PURE__ */ jsx7(
|
|
2256
|
-
"button",
|
|
2257
|
-
{
|
|
2258
|
-
type: "button",
|
|
2259
|
-
onClick: send,
|
|
2260
|
-
disabled: !canSend,
|
|
2261
|
-
"aria-label": sendLabel,
|
|
2262
|
-
title: sendLabel,
|
|
2263
|
-
className: "inline-flex h-[34px] w-[34px] shrink-0 items-center justify-center rounded-full bg-foreground text-background transition hover:opacity-90 disabled:cursor-not-allowed disabled:opacity-40 focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:ring-offset-card",
|
|
2264
|
-
children: /* @__PURE__ */ jsx7(ArrowUpGlyph, { className: "h-4 w-4" })
|
|
2265
|
-
}
|
|
2266
|
-
) : /* @__PURE__ */ jsxs5(
|
|
2267
|
-
"button",
|
|
2268
|
-
{
|
|
2269
|
-
type: "button",
|
|
2270
|
-
onClick: send,
|
|
2271
|
-
disabled: !canSend,
|
|
2272
|
-
"aria-label": sendLabel,
|
|
2273
|
-
className: "inline-flex shrink-0 items-center gap-1.5 rounded-full bg-primary px-3.5 py-2 text-sm font-medium text-primary-foreground shadow-sm transition hover:bg-primary/90 disabled:cursor-not-allowed disabled:opacity-40 focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:ring-offset-card",
|
|
2274
|
-
children: [
|
|
2275
|
-
/* @__PURE__ */ jsx7(SendGlyph, { className: "h-3.5 w-3.5" }),
|
|
2276
|
-
/* @__PURE__ */ jsx7("span", { children: sendLabel })
|
|
2277
|
-
]
|
|
2278
|
-
}
|
|
2279
|
-
)
|
|
2280
|
-
] })
|
|
2281
|
-
]
|
|
2282
|
-
}
|
|
2283
|
-
),
|
|
2284
|
-
/* @__PURE__ */ jsxs5(
|
|
2285
|
-
PopoverSurface,
|
|
2286
|
-
{
|
|
2287
|
-
open: slashOpen,
|
|
2288
|
-
id: slashListId,
|
|
2289
|
-
role: "listbox",
|
|
2290
|
-
triggerRef: textareaRef,
|
|
2291
|
-
panelRef: slashPanelRef,
|
|
2292
|
-
className: `w-80 overflow-y-auto rounded-xl border border-card-edge bg-popover p-1 ${OVERLAY_SHADOW}`,
|
|
2293
|
-
children: [
|
|
2294
|
-
slashFiltered.length === 0 && /* @__PURE__ */ jsx7("div", { className: "px-3 py-4 text-center text-sm text-muted-foreground", children: "No matching commands" }),
|
|
2295
|
-
slashFiltered.map((item, index) => /* @__PURE__ */ jsxs5(
|
|
2296
|
-
"button",
|
|
2297
|
-
{
|
|
2298
|
-
type: "button",
|
|
2299
|
-
role: "option",
|
|
2300
|
-
"aria-selected": index === slashActiveIndex,
|
|
2301
|
-
id: `${slashListId}-${index}`,
|
|
2302
|
-
onMouseDown: (e) => e.preventDefault(),
|
|
2303
|
-
onMouseMove: () => setSlashActive(index),
|
|
2304
|
-
onClick: () => pickSlash(item.id),
|
|
2305
|
-
className: `flex w-full items-center gap-2.5 rounded-md px-3 py-2.5 text-left text-sm transition ${POPOVER_OPTION_FOCUS} ${index === slashActiveIndex ? "bg-accent" : "hover:bg-accent"}`,
|
|
2306
|
-
children: [
|
|
2307
|
-
/* @__PURE__ */ jsx7("span", { className: "shrink-0 font-medium text-foreground", children: item.label }),
|
|
2308
|
-
/* @__PURE__ */ jsx7("span", { className: "truncate text-xs text-muted-foreground", children: item.description })
|
|
2309
|
-
]
|
|
2310
|
-
},
|
|
2311
|
-
item.id
|
|
2312
|
-
))
|
|
2313
|
-
]
|
|
2314
|
-
}
|
|
2315
|
-
),
|
|
2316
|
-
focusShortcut && /* @__PURE__ */ jsx7("div", { className: "mt-1.5 flex justify-end px-1", children: /* @__PURE__ */ jsxs5("span", { className: "text-xs text-muted-foreground", children: [
|
|
2317
|
-
/* @__PURE__ */ jsx7("kbd", { className: "rounded border border-border bg-background px-1 py-0.5 text-xs", children: IS_APPLE_PLATFORM ? "Cmd" : "Ctrl" }),
|
|
2318
|
-
/* @__PURE__ */ jsx7("kbd", { className: "ml-0.5 rounded border border-border bg-background px-1 py-0.5 text-xs", children: "L" }),
|
|
2319
|
-
/* @__PURE__ */ jsx7("span", { className: "ml-1", children: "to focus" })
|
|
2320
|
-
] }) })
|
|
2321
|
-
]
|
|
2322
|
-
}
|
|
2323
|
-
);
|
|
2324
|
-
}
|
|
2325
|
-
|
|
2326
1418
|
// src/web-react/durable-plan-flow.ts
|
|
2327
|
-
import { useCallback as
|
|
1419
|
+
import { useCallback as useCallback2, useEffect as useEffect5, useRef as useRef5, useState as useState7 } from "react";
|
|
2328
1420
|
var DurablePlanClientError = class extends Error {
|
|
2329
1421
|
constructor(message, status, code, currentPlan) {
|
|
2330
1422
|
super(message);
|
|
@@ -2411,14 +1503,14 @@ function createDurablePlanDecisionClient(options) {
|
|
|
2411
1503
|
};
|
|
2412
1504
|
}
|
|
2413
1505
|
function useDurablePlanFlow(options) {
|
|
2414
|
-
const [plan, setPlan] =
|
|
2415
|
-
const [deciding, setDeciding] =
|
|
2416
|
-
const [restoring, setRestoring] =
|
|
2417
|
-
const [error, setError] =
|
|
2418
|
-
const attachments =
|
|
2419
|
-
const decisionInFlight =
|
|
2420
|
-
|
|
2421
|
-
const apply =
|
|
1506
|
+
const [plan, setPlan] = useState7(options.plan);
|
|
1507
|
+
const [deciding, setDeciding] = useState7(null);
|
|
1508
|
+
const [restoring, setRestoring] = useState7(false);
|
|
1509
|
+
const [error, setError] = useState7(null);
|
|
1510
|
+
const attachments = useRef5(/* @__PURE__ */ new Map());
|
|
1511
|
+
const decisionInFlight = useRef5(false);
|
|
1512
|
+
useEffect5(() => setPlan(options.plan), [options.plan]);
|
|
1513
|
+
const apply = useCallback2(async (result) => {
|
|
2422
1514
|
setPlan(result.plan);
|
|
2423
1515
|
options.onUpdated?.(result.plan);
|
|
2424
1516
|
const receipt = result.followUp;
|
|
@@ -2431,7 +1523,7 @@ function useDurablePlanFlow(options) {
|
|
|
2431
1523
|
}
|
|
2432
1524
|
await pending;
|
|
2433
1525
|
}, [options.attachFollowUp, options.onUpdated]);
|
|
2434
|
-
const decide =
|
|
1526
|
+
const decide = useCallback2(async (decision, feedback) => {
|
|
2435
1527
|
if (decisionInFlight.current) return null;
|
|
2436
1528
|
decisionInFlight.current = true;
|
|
2437
1529
|
setDeciding(decision);
|
|
@@ -2457,7 +1549,7 @@ function useDurablePlanFlow(options) {
|
|
|
2457
1549
|
setDeciding(null);
|
|
2458
1550
|
}
|
|
2459
1551
|
}, [apply, options.client, options.onUpdated, plan.planId, plan.revision]);
|
|
2460
|
-
const restore =
|
|
1552
|
+
const restore = useCallback2(async () => {
|
|
2461
1553
|
setRestoring(true);
|
|
2462
1554
|
setError(null);
|
|
2463
1555
|
try {
|
|
@@ -2586,7 +1678,7 @@ function createDurableInteractionAnswerSubmitter(options) {
|
|
|
2586
1678
|
}
|
|
2587
1679
|
|
|
2588
1680
|
// src/web-react/use-chat-interactions.ts
|
|
2589
|
-
import { useCallback as
|
|
1681
|
+
import { useCallback as useCallback3, useMemo as useMemo3, useState as useState8 } from "react";
|
|
2590
1682
|
function hasPendingContentDuplicate(list, interaction) {
|
|
2591
1683
|
if (interaction.status !== "pending") return false;
|
|
2592
1684
|
const signature = questionInteractionContentSignature(interaction);
|
|
@@ -2665,34 +1757,34 @@ function hydrateChatInteractions(list, persisted) {
|
|
|
2665
1757
|
return persisted.reduce(upsertChatInteraction, list);
|
|
2666
1758
|
}
|
|
2667
1759
|
function useChatInteractions(options = {}) {
|
|
2668
|
-
const [interactions, setInteractions] =
|
|
2669
|
-
const upsert =
|
|
1760
|
+
const [interactions, setInteractions] = useState8([]);
|
|
1761
|
+
const upsert = useCallback3((interaction) => {
|
|
2670
1762
|
setInteractions((prev) => upsertChatInteraction(prev, interaction));
|
|
2671
1763
|
}, []);
|
|
2672
|
-
const applyCancel =
|
|
1764
|
+
const applyCancel = useCallback3((cancel) => {
|
|
2673
1765
|
setInteractions((prev) => cancelChatInteraction(prev, cancel));
|
|
2674
1766
|
}, []);
|
|
2675
|
-
const markResolved =
|
|
1767
|
+
const markResolved = useCallback3((id, status, answers) => {
|
|
2676
1768
|
setInteractions((prev) => resolveChatInteraction(prev, id, status, answers));
|
|
2677
1769
|
}, []);
|
|
2678
|
-
const restore =
|
|
1770
|
+
const restore = useCallback3((outstanding, restoreOptions) => {
|
|
2679
1771
|
setInteractions((prev) => restoreChatInteractions(prev, outstanding, {
|
|
2680
1772
|
mode: restoreOptions?.mode ?? options.mode
|
|
2681
1773
|
}));
|
|
2682
1774
|
}, [options.mode]);
|
|
2683
|
-
const hydrate =
|
|
1775
|
+
const hydrate = useCallback3((persisted) => {
|
|
2684
1776
|
setInteractions((prev) => hydrateChatInteractions(prev, persisted));
|
|
2685
1777
|
}, []);
|
|
2686
|
-
const terminalizePending =
|
|
1778
|
+
const terminalizePending = useCallback3((status) => {
|
|
2687
1779
|
setInteractions((prev) => terminalizePendingChatInteractions(prev, status));
|
|
2688
1780
|
}, []);
|
|
2689
|
-
const reset =
|
|
2690
|
-
const pending =
|
|
1781
|
+
const reset = useCallback3(() => setInteractions([]), []);
|
|
1782
|
+
const pending = useMemo3(() => interactions.filter((item) => item.status === "pending"), [interactions]);
|
|
2691
1783
|
return { interactions, pending, upsert, applyCancel, markResolved, restore, hydrate, terminalizePending, reset };
|
|
2692
1784
|
}
|
|
2693
1785
|
|
|
2694
1786
|
// src/web-react/use-file-mentions.ts
|
|
2695
|
-
import { useCallback as
|
|
1787
|
+
import { useCallback as useCallback4, useMemo as useMemo4, useRef as useRef6, useState as useState9 } from "react";
|
|
2696
1788
|
var FILE_MENTION_KIND = "file";
|
|
2697
1789
|
function toMentionItem(file) {
|
|
2698
1790
|
return { id: file.path, label: file.name, detail: file.path, kind: FILE_MENTION_KIND };
|
|
@@ -2750,12 +1842,12 @@ function useFileMentions(options) {
|
|
|
2750
1842
|
emptyText = DEFAULT_MENTION_EMPTY_TEXT
|
|
2751
1843
|
} = options;
|
|
2752
1844
|
const fetchImpl = options.fetchImpl ?? fetch;
|
|
2753
|
-
const [state, setState] =
|
|
2754
|
-
const stateRef =
|
|
1845
|
+
const [state, setState] = useState9({ kind: "idle" });
|
|
1846
|
+
const stateRef = useRef6(state);
|
|
2755
1847
|
stateRef.current = state;
|
|
2756
|
-
const inFlightRef =
|
|
2757
|
-
const [mentions, setMentions] =
|
|
2758
|
-
const load =
|
|
1848
|
+
const inFlightRef = useRef6(null);
|
|
1849
|
+
const [mentions, setMentions] = useState9([]);
|
|
1850
|
+
const load = useCallback4(() => {
|
|
2759
1851
|
if (inFlightRef.current) return inFlightRef.current;
|
|
2760
1852
|
if (stateRef.current.kind === "idle") {
|
|
2761
1853
|
stateRef.current = { kind: "loading" };
|
|
@@ -2787,10 +1879,10 @@ function useFileMentions(options) {
|
|
|
2787
1879
|
inFlightRef.current = attempt;
|
|
2788
1880
|
return attempt;
|
|
2789
1881
|
}, [fetchImpl, indexUrl]);
|
|
2790
|
-
const refresh =
|
|
1882
|
+
const refresh = useCallback4(async () => {
|
|
2791
1883
|
await load();
|
|
2792
1884
|
}, [load]);
|
|
2793
|
-
const fetchItems =
|
|
1885
|
+
const fetchItems = useCallback4(
|
|
2794
1886
|
async (query) => {
|
|
2795
1887
|
let current = stateRef.current;
|
|
2796
1888
|
if (current.kind === "idle" || current.kind === "loading") {
|
|
@@ -2805,11 +1897,11 @@ function useFileMentions(options) {
|
|
|
2805
1897
|
},
|
|
2806
1898
|
[load, limit, refreshAfterMs]
|
|
2807
1899
|
);
|
|
2808
|
-
const onMentionsChange =
|
|
1900
|
+
const onMentionsChange = useCallback4((items) => {
|
|
2809
1901
|
setMentions(items.filter((item) => item.kind === void 0 || item.kind === FILE_MENTION_KIND).map(toFileMention));
|
|
2810
1902
|
}, []);
|
|
2811
|
-
const clearMentions =
|
|
2812
|
-
const mention =
|
|
1903
|
+
const clearMentions = useCallback4(() => setMentions([]), []);
|
|
1904
|
+
const mention = useMemo4(
|
|
2813
1905
|
() => ({
|
|
2814
1906
|
fetchItems,
|
|
2815
1907
|
onMentionsChange,
|
|
@@ -2821,8 +1913,6 @@ function useFileMentions(options) {
|
|
|
2821
1913
|
}
|
|
2822
1914
|
|
|
2823
1915
|
// src/web-react/chat-mentions.ts
|
|
2824
|
-
var PATH_CONTINUATION_CHAR = /[\p{L}\p{N}._\-/]/u;
|
|
2825
|
-
var WORD_CHAR = /[\p{L}\p{N}]/u;
|
|
2826
1916
|
function segmentMentionContent(content, parts) {
|
|
2827
1917
|
const matched = /* @__PURE__ */ new Set();
|
|
2828
1918
|
if (!content) return { segments: [], matched };
|
|
@@ -2836,7 +1926,7 @@ function segmentMentionContent(content, parts) {
|
|
|
2836
1926
|
cursor += 1;
|
|
2837
1927
|
continue;
|
|
2838
1928
|
}
|
|
2839
|
-
const prevChar =
|
|
1929
|
+
const prevChar = charBefore(content, cursor);
|
|
2840
1930
|
if (prevChar && WORD_CHAR.test(prevChar)) {
|
|
2841
1931
|
cursor += 1;
|
|
2842
1932
|
continue;
|
|
@@ -2847,7 +1937,7 @@ function segmentMentionContent(content, parts) {
|
|
|
2847
1937
|
continue;
|
|
2848
1938
|
}
|
|
2849
1939
|
const endIdx = cursor + candidate.token.length;
|
|
2850
|
-
const nextChar =
|
|
1940
|
+
const nextChar = charAt(content, endIdx);
|
|
2851
1941
|
if (nextChar && PATH_CONTINUATION_CHAR.test(nextChar)) {
|
|
2852
1942
|
cursor += 1;
|
|
2853
1943
|
continue;
|
|
@@ -2863,8 +1953,8 @@ function segmentMentionContent(content, parts) {
|
|
|
2863
1953
|
}
|
|
2864
1954
|
|
|
2865
1955
|
// src/web-react/mission-activity.tsx
|
|
2866
|
-
import { useCallback as
|
|
2867
|
-
import { Fragment as
|
|
1956
|
+
import { useCallback as useCallback5, useEffect as useEffect6, useState as useState10 } from "react";
|
|
1957
|
+
import { Fragment as Fragment2, jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
2868
1958
|
var LIVE_STATUSES = /* @__PURE__ */ new Set(["pending", "running"]);
|
|
2869
1959
|
var OK_STATUSES = /* @__PURE__ */ new Set(["completed", "done", "succeeded"]);
|
|
2870
1960
|
var ERROR_STATUSES = /* @__PURE__ */ new Set(["failed", "error", "cancelled", "aborted"]);
|
|
@@ -2911,20 +2001,20 @@ function waterfallLayout(trace) {
|
|
|
2911
2001
|
});
|
|
2912
2002
|
}
|
|
2913
2003
|
function ChevronGlyph({ className }) {
|
|
2914
|
-
return /* @__PURE__ */
|
|
2004
|
+
return /* @__PURE__ */ jsx7("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: /* @__PURE__ */ jsx7("path", { d: "m6 9 6 6 6-6" }) });
|
|
2915
2005
|
}
|
|
2916
2006
|
function RefreshGlyph({ className }) {
|
|
2917
|
-
return /* @__PURE__ */
|
|
2007
|
+
return /* @__PURE__ */ jsx7("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: /* @__PURE__ */ jsx7("path", { d: "M21 12a9 9 0 1 1-2.64-6.36M21 3v6h-6" }) });
|
|
2918
2008
|
}
|
|
2919
2009
|
function CopyGlyph({ className }) {
|
|
2920
|
-
return /* @__PURE__ */
|
|
2921
|
-
/* @__PURE__ */
|
|
2922
|
-
/* @__PURE__ */
|
|
2010
|
+
return /* @__PURE__ */ jsxs5("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: [
|
|
2011
|
+
/* @__PURE__ */ jsx7("rect", { x: "9", y: "9", width: "13", height: "13", rx: "2" }),
|
|
2012
|
+
/* @__PURE__ */ jsx7("path", { d: "M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" })
|
|
2923
2013
|
] });
|
|
2924
2014
|
}
|
|
2925
2015
|
function TraceIdCopy({ traceId }) {
|
|
2926
|
-
const [copied, setCopied] =
|
|
2927
|
-
const copy =
|
|
2016
|
+
const [copied, setCopied] = useState10(false);
|
|
2017
|
+
const copy = useCallback5(() => {
|
|
2928
2018
|
void navigator.clipboard?.writeText(traceId).then(
|
|
2929
2019
|
() => {
|
|
2930
2020
|
setCopied(true);
|
|
@@ -2934,7 +2024,7 @@ function TraceIdCopy({ traceId }) {
|
|
|
2934
2024
|
}
|
|
2935
2025
|
);
|
|
2936
2026
|
}, [traceId]);
|
|
2937
|
-
return /* @__PURE__ */
|
|
2027
|
+
return /* @__PURE__ */ jsxs5(
|
|
2938
2028
|
"button",
|
|
2939
2029
|
{
|
|
2940
2030
|
type: "button",
|
|
@@ -2943,29 +2033,29 @@ function TraceIdCopy({ traceId }) {
|
|
|
2943
2033
|
"aria-label": "Copy trace id",
|
|
2944
2034
|
className: "inline-flex min-w-0 items-center gap-1.5 rounded text-left font-mono text-muted-foreground transition hover:text-foreground",
|
|
2945
2035
|
children: [
|
|
2946
|
-
/* @__PURE__ */
|
|
2947
|
-
/* @__PURE__ */
|
|
2948
|
-
copied && /* @__PURE__ */
|
|
2036
|
+
/* @__PURE__ */ jsx7("span", { className: "truncate", children: traceId }),
|
|
2037
|
+
/* @__PURE__ */ jsx7(CopyGlyph, { className: "h-3 w-3 shrink-0" }),
|
|
2038
|
+
copied && /* @__PURE__ */ jsx7("span", { className: "shrink-0 not-italic text-success", children: "copied" })
|
|
2949
2039
|
]
|
|
2950
2040
|
}
|
|
2951
2041
|
);
|
|
2952
2042
|
}
|
|
2953
2043
|
function StatusDot({ tone }) {
|
|
2954
|
-
return /* @__PURE__ */
|
|
2955
|
-
/* @__PURE__ */
|
|
2044
|
+
return /* @__PURE__ */ jsxs5("span", { className: "inline-flex items-center", children: [
|
|
2045
|
+
/* @__PURE__ */ jsx7(
|
|
2956
2046
|
"span",
|
|
2957
2047
|
{
|
|
2958
2048
|
"aria-hidden": true,
|
|
2959
2049
|
className: `h-2 w-2 shrink-0 rounded-full ${tone === "live" ? "bg-warning" : tone === "ok" ? "bg-success" : tone === "error" ? "bg-destructive" : "bg-muted-foreground/40"}`
|
|
2960
2050
|
}
|
|
2961
2051
|
),
|
|
2962
|
-
/* @__PURE__ */
|
|
2052
|
+
/* @__PURE__ */ jsx7("span", { className: "sr-only", children: tone })
|
|
2963
2053
|
] });
|
|
2964
2054
|
}
|
|
2965
2055
|
function RunLabel({ tool, detail, live }) {
|
|
2966
|
-
return /* @__PURE__ */
|
|
2967
|
-
/* @__PURE__ */
|
|
2968
|
-
/* @__PURE__ */
|
|
2056
|
+
return /* @__PURE__ */ jsxs5("span", { className: "min-w-0 flex-1 truncate", children: [
|
|
2057
|
+
/* @__PURE__ */ jsx7("span", { className: live ? "agent-shimmer font-medium" : "font-medium", "data-motion": live ? "essential" : void 0, children: tool }),
|
|
2058
|
+
/* @__PURE__ */ jsxs5("span", { className: "text-muted-foreground", children: [
|
|
2969
2059
|
" \u2014 ",
|
|
2970
2060
|
detail
|
|
2971
2061
|
] })
|
|
@@ -2980,19 +2070,19 @@ function FlowWaterfall({ trace }) {
|
|
|
2980
2070
|
const rows = waterfallLayout(trace);
|
|
2981
2071
|
if (rows.length === 0) return null;
|
|
2982
2072
|
const cost = formatActivityCost(trace.costUsd);
|
|
2983
|
-
return /* @__PURE__ */
|
|
2984
|
-
rows.map((row, i) => /* @__PURE__ */
|
|
2985
|
-
/* @__PURE__ */
|
|
2986
|
-
/* @__PURE__ */
|
|
2073
|
+
return /* @__PURE__ */ jsxs5("div", { className: "space-y-1", children: [
|
|
2074
|
+
rows.map((row, i) => /* @__PURE__ */ jsxs5("div", { className: "grid grid-cols-[minmax(0,2fr)_minmax(0,3fr)_auto] items-center gap-2", children: [
|
|
2075
|
+
/* @__PURE__ */ jsx7("span", { className: "truncate font-mono text-xs text-muted-foreground", title: row.name, children: row.name }),
|
|
2076
|
+
/* @__PURE__ */ jsx7("div", { className: "relative h-2 rounded-sm bg-secondary", children: /* @__PURE__ */ jsx7(
|
|
2987
2077
|
"div",
|
|
2988
2078
|
{
|
|
2989
2079
|
className: `absolute inset-y-0 rounded-sm ${row.ok ? BAR_CLASS[row.kind] : "bg-destructive/80"} ${row.approx ? "opacity-70" : ""}`,
|
|
2990
2080
|
style: { left: `${row.offsetPct}%`, width: `${row.widthPct}%` }
|
|
2991
2081
|
}
|
|
2992
2082
|
) }),
|
|
2993
|
-
/* @__PURE__ */
|
|
2083
|
+
/* @__PURE__ */ jsx7("span", { className: "shrink-0 font-mono text-xs tabular-nums text-muted-foreground/70", children: row.durationLabel })
|
|
2994
2084
|
] }, i)),
|
|
2995
|
-
/* @__PURE__ */
|
|
2085
|
+
/* @__PURE__ */ jsxs5("p", { className: "pt-0.5 text-right font-mono text-xs tabular-nums text-muted-foreground/60", children: [
|
|
2996
2086
|
(trace.totalMs / 1e3).toFixed(1),
|
|
2997
2087
|
"s",
|
|
2998
2088
|
cost ? ` \xB7 ${cost}` : ""
|
|
@@ -3004,35 +2094,35 @@ function LaneRow({ run, staggerIndex }) {
|
|
|
3004
2094
|
const tone = activityTone(run.status);
|
|
3005
2095
|
const cost = formatActivityCost(run.costUsd);
|
|
3006
2096
|
const duration = formatActivityDuration(run.durationMs);
|
|
3007
|
-
return /* @__PURE__ */
|
|
3008
|
-
/* @__PURE__ */
|
|
3009
|
-
/* @__PURE__ */
|
|
3010
|
-
tone === "live" && (run.iteration !== void 0 || run.phase !== void 0) && /* @__PURE__ */
|
|
3011
|
-
/* @__PURE__ */
|
|
3012
|
-
tone !== "live" && tone !== "ok" && /* @__PURE__ */
|
|
3013
|
-
cost && /* @__PURE__ */
|
|
3014
|
-
duration && /* @__PURE__ */
|
|
2097
|
+
return /* @__PURE__ */ jsxs5("div", { className: "agent-arrive flex items-center gap-2 py-1 text-xs", style: arrival, children: [
|
|
2098
|
+
/* @__PURE__ */ jsx7(StatusDot, { tone }),
|
|
2099
|
+
/* @__PURE__ */ jsx7(RunLabel, { tool: run.tool, detail: run.detail, live: tone === "live" }),
|
|
2100
|
+
tone === "live" && (run.iteration !== void 0 || run.phase !== void 0) && /* @__PURE__ */ jsx7("span", { className: "shrink-0 rounded-full bg-warning/10 px-1.5 py-0.5 font-mono text-xs text-warning", children: [run.iteration !== void 0 ? `iter ${run.iteration}` : null, run.phase ?? null].filter(Boolean).join(" \xB7 ") }),
|
|
2101
|
+
/* @__PURE__ */ jsxs5("span", { className: "flex shrink-0 items-center gap-1.5 font-mono text-xs tabular-nums text-muted-foreground/70", children: [
|
|
2102
|
+
tone !== "live" && tone !== "ok" && /* @__PURE__ */ jsx7("span", { children: run.status }),
|
|
2103
|
+
cost && /* @__PURE__ */ jsx7("span", { children: cost }),
|
|
2104
|
+
duration && /* @__PURE__ */ jsx7("span", { children: duration })
|
|
3015
2105
|
] })
|
|
3016
2106
|
] });
|
|
3017
2107
|
}
|
|
3018
2108
|
function MissionActivityLane({ activity, startedAt, nowMs }) {
|
|
3019
|
-
const [expanded, setExpanded] =
|
|
2109
|
+
const [expanded, setExpanded] = useState10(false);
|
|
3020
2110
|
if (activity.length === 0) return null;
|
|
3021
|
-
return /* @__PURE__ */
|
|
3022
|
-
activity.map((run, index) => /* @__PURE__ */
|
|
3023
|
-
/* @__PURE__ */
|
|
2111
|
+
return /* @__PURE__ */ jsxs5("div", { className: "mt-1 border-l border-border pl-3", children: [
|
|
2112
|
+
activity.map((run, index) => /* @__PURE__ */ jsx7(LaneRow, { run, staggerIndex: index }, run.taskId)),
|
|
2113
|
+
/* @__PURE__ */ jsxs5(
|
|
3024
2114
|
"button",
|
|
3025
2115
|
{
|
|
3026
2116
|
type: "button",
|
|
3027
2117
|
onClick: () => setExpanded((v) => !v),
|
|
3028
2118
|
className: "flex items-center gap-1 py-0.5 text-xs font-medium text-muted-foreground/70 transition hover:text-foreground",
|
|
3029
2119
|
children: [
|
|
3030
|
-
/* @__PURE__ */
|
|
2120
|
+
/* @__PURE__ */ jsx7(ChevronGlyph, { className: `h-3 w-3 transition-transform ${expanded ? "rotate-180" : ""}` }),
|
|
3031
2121
|
"timeline"
|
|
3032
2122
|
]
|
|
3033
2123
|
}
|
|
3034
2124
|
),
|
|
3035
|
-
expanded && /* @__PURE__ */
|
|
2125
|
+
expanded && /* @__PURE__ */ jsx7("div", { className: "rounded-md border border-border bg-secondary p-2", children: /* @__PURE__ */ jsx7(
|
|
3036
2126
|
FlowWaterfall,
|
|
3037
2127
|
{
|
|
3038
2128
|
trace: stepActivityFlowTrace(activity, {
|
|
@@ -3049,39 +2139,39 @@ function ActivityRow({
|
|
|
3049
2139
|
staggerIndex
|
|
3050
2140
|
}) {
|
|
3051
2141
|
const arrival = useArrivalStyle(staggerIndex);
|
|
3052
|
-
const [open, setOpen] =
|
|
2142
|
+
const [open, setOpen] = useState10(false);
|
|
3053
2143
|
const tone = activityTone(record.status);
|
|
3054
2144
|
const cost = formatActivityCost(record.costUsd);
|
|
3055
2145
|
const duration = formatActivityDuration(record.durationMs);
|
|
3056
|
-
return /* @__PURE__ */
|
|
3057
|
-
/* @__PURE__ */
|
|
3058
|
-
/* @__PURE__ */
|
|
3059
|
-
/* @__PURE__ */
|
|
3060
|
-
tone === "live" && (record.iteration !== void 0 || record.phase !== void 0) && /* @__PURE__ */
|
|
3061
|
-
/* @__PURE__ */
|
|
2146
|
+
return /* @__PURE__ */ jsxs5("div", { className: "agent-arrive rounded-lg border border-card-edge bg-card", style: arrival, children: [
|
|
2147
|
+
/* @__PURE__ */ jsxs5("button", { type: "button", onClick: () => setOpen((v) => !v), className: "flex w-full items-center gap-2.5 px-3 py-2 text-left text-sm", children: [
|
|
2148
|
+
/* @__PURE__ */ jsx7(StatusDot, { tone }),
|
|
2149
|
+
/* @__PURE__ */ jsx7(RunLabel, { tool: record.tool, detail: record.detail, live: tone === "live" }),
|
|
2150
|
+
tone === "live" && (record.iteration !== void 0 || record.phase !== void 0) && /* @__PURE__ */ jsx7("span", { className: "shrink-0 rounded-full bg-warning/10 px-2 py-0.5 font-mono text-xs text-warning", children: [record.iteration !== void 0 ? `iter ${record.iteration}` : null, record.phase ?? null].filter(Boolean).join(" \xB7 ") }),
|
|
2151
|
+
/* @__PURE__ */ jsx7(
|
|
3062
2152
|
"span",
|
|
3063
2153
|
{
|
|
3064
2154
|
className: `shrink-0 rounded-full px-2 py-0.5 text-xs font-medium ${tone === "ok" ? "bg-success/10 text-success" : tone === "error" ? "bg-destructive/10 text-destructive" : tone === "live" ? "bg-warning/10 text-warning" : "bg-secondary text-muted-foreground"}`,
|
|
3065
2155
|
children: record.status
|
|
3066
2156
|
}
|
|
3067
2157
|
),
|
|
3068
|
-
cost && /* @__PURE__ */
|
|
3069
|
-
/* @__PURE__ */
|
|
2158
|
+
cost && /* @__PURE__ */ jsx7("span", { className: "shrink-0 font-mono text-xs tabular-nums text-muted-foreground", children: cost }),
|
|
2159
|
+
/* @__PURE__ */ jsx7(ChevronGlyph, { className: `h-3 w-3 shrink-0 text-muted-foreground transition-transform ${open ? "rotate-180" : ""}` })
|
|
3070
2160
|
] }),
|
|
3071
|
-
open && /* @__PURE__ */
|
|
3072
|
-
record.durationMs !== void 0 && /* @__PURE__ */
|
|
3073
|
-
/* @__PURE__ */
|
|
3074
|
-
/* @__PURE__ */
|
|
3075
|
-
/* @__PURE__ */
|
|
3076
|
-
/* @__PURE__ */
|
|
3077
|
-
/* @__PURE__ */
|
|
3078
|
-
duration && /* @__PURE__ */
|
|
3079
|
-
/* @__PURE__ */
|
|
3080
|
-
/* @__PURE__ */
|
|
2161
|
+
open && /* @__PURE__ */ jsxs5("div", { className: "space-y-2.5 border-t border-border px-3 py-2.5", children: [
|
|
2162
|
+
record.durationMs !== void 0 && /* @__PURE__ */ jsx7("div", { className: "rounded-md border border-border bg-secondary p-2", children: /* @__PURE__ */ jsx7(FlowWaterfall, { trace: stepActivityFlowTrace([record]) }) }),
|
|
2163
|
+
/* @__PURE__ */ jsxs5("dl", { className: "grid grid-cols-[auto_1fr] gap-x-3 gap-y-1 font-mono text-xs", children: [
|
|
2164
|
+
/* @__PURE__ */ jsx7("dt", { className: "text-muted-foreground/60", children: "task" }),
|
|
2165
|
+
/* @__PURE__ */ jsx7("dd", { className: "truncate text-muted-foreground", children: record.taskId }),
|
|
2166
|
+
/* @__PURE__ */ jsx7("dt", { className: "text-muted-foreground/60", children: "started" }),
|
|
2167
|
+
/* @__PURE__ */ jsx7("dd", { className: "text-muted-foreground", children: new Date(record.startedAt).toLocaleString() }),
|
|
2168
|
+
duration && /* @__PURE__ */ jsxs5(Fragment2, { children: [
|
|
2169
|
+
/* @__PURE__ */ jsx7("dt", { className: "text-muted-foreground/60", children: "duration" }),
|
|
2170
|
+
/* @__PURE__ */ jsx7("dd", { className: "text-muted-foreground", children: duration })
|
|
3081
2171
|
] }),
|
|
3082
|
-
record.traceId && /* @__PURE__ */
|
|
3083
|
-
/* @__PURE__ */
|
|
3084
|
-
/* @__PURE__ */
|
|
2172
|
+
record.traceId && /* @__PURE__ */ jsxs5(Fragment2, { children: [
|
|
2173
|
+
/* @__PURE__ */ jsx7("dt", { className: "text-muted-foreground/60", children: "trace" }),
|
|
2174
|
+
/* @__PURE__ */ jsx7("dd", { className: "min-w-0", children: /* @__PURE__ */ jsx7(TraceIdCopy, { traceId: record.traceId }) })
|
|
3085
2175
|
] })
|
|
3086
2176
|
] }),
|
|
3087
2177
|
record.missionRef && renderMissionRef?.(record.missionRef, record)
|
|
@@ -3089,11 +2179,11 @@ function ActivityRow({
|
|
|
3089
2179
|
] });
|
|
3090
2180
|
}
|
|
3091
2181
|
function AgentActivityPanel({ fetchActivity, renderMissionRef, title = "Agent activity", emptyLabel = "No agent runs yet." }) {
|
|
3092
|
-
const [rows, setRows] =
|
|
3093
|
-
const [cursor, setCursor] =
|
|
3094
|
-
const [status, setStatus] =
|
|
3095
|
-
const [error, setError] =
|
|
3096
|
-
const load =
|
|
2182
|
+
const [rows, setRows] = useState10([]);
|
|
2183
|
+
const [cursor, setCursor] = useState10(void 0);
|
|
2184
|
+
const [status, setStatus] = useState10("loading");
|
|
2185
|
+
const [error, setError] = useState10(null);
|
|
2186
|
+
const load = useCallback5(
|
|
3097
2187
|
async (from) => {
|
|
3098
2188
|
setStatus("loading");
|
|
3099
2189
|
setError(null);
|
|
@@ -3109,14 +2199,14 @@ function AgentActivityPanel({ fetchActivity, renderMissionRef, title = "Agent ac
|
|
|
3109
2199
|
},
|
|
3110
2200
|
[fetchActivity]
|
|
3111
2201
|
);
|
|
3112
|
-
|
|
2202
|
+
useEffect6(() => {
|
|
3113
2203
|
void load();
|
|
3114
2204
|
}, [load]);
|
|
3115
2205
|
const loading = status === "loading";
|
|
3116
|
-
return /* @__PURE__ */
|
|
3117
|
-
/* @__PURE__ */
|
|
3118
|
-
/* @__PURE__ */
|
|
3119
|
-
/* @__PURE__ */
|
|
2206
|
+
return /* @__PURE__ */ jsxs5("div", { className: "space-y-2", children: [
|
|
2207
|
+
/* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-2", children: [
|
|
2208
|
+
/* @__PURE__ */ jsx7("h2", { className: "flex-1 text-sm font-semibold", children: title }),
|
|
2209
|
+
/* @__PURE__ */ jsx7(
|
|
3120
2210
|
"button",
|
|
3121
2211
|
{
|
|
3122
2212
|
type: "button",
|
|
@@ -3124,15 +2214,15 @@ function AgentActivityPanel({ fetchActivity, renderMissionRef, title = "Agent ac
|
|
|
3124
2214
|
disabled: loading,
|
|
3125
2215
|
"aria-label": "Refresh",
|
|
3126
2216
|
className: "rounded-md p-1.5 text-muted-foreground transition hover:bg-accent hover:text-foreground disabled:opacity-50",
|
|
3127
|
-
children: /* @__PURE__ */
|
|
2217
|
+
children: /* @__PURE__ */ jsx7(RefreshGlyph, { className: `h-3.5 w-3.5 ${loading ? "animate-spin" : ""}` })
|
|
3128
2218
|
}
|
|
3129
2219
|
)
|
|
3130
2220
|
] }),
|
|
3131
|
-
status === "error" && /* @__PURE__ */
|
|
3132
|
-
status === "ready" && rows.length === 0 && /* @__PURE__ */
|
|
3133
|
-
/* @__PURE__ */
|
|
3134
|
-
/* @__PURE__ */
|
|
3135
|
-
cursor && /* @__PURE__ */
|
|
2221
|
+
status === "error" && /* @__PURE__ */ jsx7("p", { role: "alert", className: "rounded-md border border-destructive/40 bg-destructive/5 px-3 py-2 text-xs text-destructive", children: error }),
|
|
2222
|
+
status === "ready" && rows.length === 0 && /* @__PURE__ */ jsx7("p", { className: "px-1 text-sm text-muted-foreground", children: emptyLabel }),
|
|
2223
|
+
/* @__PURE__ */ jsx7("span", { role: "status", "aria-live": "polite", "aria-busy": loading, className: "sr-only", children: loading ? "Loading activity\u2026" : "" }),
|
|
2224
|
+
/* @__PURE__ */ jsx7("div", { className: "space-y-1.5", "aria-busy": loading, children: rows.map((record, index) => /* @__PURE__ */ jsx7(ActivityRow, { record, renderMissionRef, staggerIndex: index }, record.taskId)) }),
|
|
2225
|
+
cursor && /* @__PURE__ */ jsx7(
|
|
3136
2226
|
"button",
|
|
3137
2227
|
{
|
|
3138
2228
|
type: "button",
|
|
@@ -3146,7 +2236,7 @@ function AgentActivityPanel({ fetchActivity, renderMissionRef, title = "Agent ac
|
|
|
3146
2236
|
}
|
|
3147
2237
|
|
|
3148
2238
|
// src/web-react/provenance.tsx
|
|
3149
|
-
import { useCallback as
|
|
2239
|
+
import { useCallback as useCallback6, useEffect as useEffect7, useId, useRef as useRef7, useState as useState11 } from "react";
|
|
3150
2240
|
|
|
3151
2241
|
// src/web-react/provenance-model.ts
|
|
3152
2242
|
var PROVENANCE_BASES = ["extracted", "entered", "computed", "asserted"];
|
|
@@ -3306,7 +2396,7 @@ function provenanceTriggerLabel(record, standing) {
|
|
|
3306
2396
|
}
|
|
3307
2397
|
|
|
3308
2398
|
// src/web-react/provenance.tsx
|
|
3309
|
-
import { jsx as
|
|
2399
|
+
import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
3310
2400
|
var BASIS_TONES = {
|
|
3311
2401
|
extracted: "border-primary/30 bg-primary/10 text-primary",
|
|
3312
2402
|
entered: "border-success/30 bg-success/10 text-success",
|
|
@@ -3331,27 +2421,27 @@ function BasisGlyph({ basis, className }) {
|
|
|
3331
2421
|
};
|
|
3332
2422
|
switch (basis) {
|
|
3333
2423
|
case "extracted":
|
|
3334
|
-
return /* @__PURE__ */
|
|
3335
|
-
/* @__PURE__ */
|
|
3336
|
-
/* @__PURE__ */
|
|
3337
|
-
/* @__PURE__ */
|
|
2424
|
+
return /* @__PURE__ */ jsxs6("svg", { ...shared, children: [
|
|
2425
|
+
/* @__PURE__ */ jsx8("path", { d: "M14 3H7a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V8z" }),
|
|
2426
|
+
/* @__PURE__ */ jsx8("polyline", { points: "14 3 14 8 19 8" }),
|
|
2427
|
+
/* @__PURE__ */ jsx8("line", { x1: "9", y1: "13", x2: "15", y2: "13" })
|
|
3338
2428
|
] });
|
|
3339
2429
|
case "entered":
|
|
3340
|
-
return /* @__PURE__ */
|
|
3341
|
-
/* @__PURE__ */
|
|
3342
|
-
/* @__PURE__ */
|
|
2430
|
+
return /* @__PURE__ */ jsxs6("svg", { ...shared, children: [
|
|
2431
|
+
/* @__PURE__ */ jsx8("path", { d: "M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2" }),
|
|
2432
|
+
/* @__PURE__ */ jsx8("circle", { cx: "12", cy: "7", r: "4" })
|
|
3343
2433
|
] });
|
|
3344
2434
|
case "computed":
|
|
3345
|
-
return /* @__PURE__ */
|
|
3346
|
-
/* @__PURE__ */
|
|
3347
|
-
/* @__PURE__ */
|
|
3348
|
-
/* @__PURE__ */
|
|
3349
|
-
/* @__PURE__ */
|
|
2435
|
+
return /* @__PURE__ */ jsxs6("svg", { ...shared, children: [
|
|
2436
|
+
/* @__PURE__ */ jsx8("line", { x1: "4", y1: "9", x2: "20", y2: "9" }),
|
|
2437
|
+
/* @__PURE__ */ jsx8("line", { x1: "4", y1: "15", x2: "20", y2: "15" }),
|
|
2438
|
+
/* @__PURE__ */ jsx8("line", { x1: "10", y1: "3", x2: "8", y2: "21" }),
|
|
2439
|
+
/* @__PURE__ */ jsx8("line", { x1: "16", y1: "3", x2: "14", y2: "21" })
|
|
3350
2440
|
] });
|
|
3351
2441
|
case "asserted":
|
|
3352
|
-
return /* @__PURE__ */
|
|
3353
|
-
/* @__PURE__ */
|
|
3354
|
-
/* @__PURE__ */
|
|
2442
|
+
return /* @__PURE__ */ jsxs6("svg", { ...shared, children: [
|
|
2443
|
+
/* @__PURE__ */ jsx8("path", { d: "M12 3v3M12 18v3M3 12h3M18 12h3M5.6 5.6l2.1 2.1M16.3 16.3l2.1 2.1M18.4 5.6l-2.1 2.1M7.7 16.3l-2.1 2.1" }),
|
|
2444
|
+
/* @__PURE__ */ jsx8("circle", { cx: "12", cy: "12", r: "3.2" })
|
|
3355
2445
|
] });
|
|
3356
2446
|
}
|
|
3357
2447
|
}
|
|
@@ -3371,11 +2461,11 @@ function SourceRow({
|
|
|
3371
2461
|
const status = source.status ?? "ready";
|
|
3372
2462
|
const statusLine = describeProvenanceSourceStatus(source);
|
|
3373
2463
|
const openable = status === "ready" && (onOpenSource !== void 0 || source.href !== void 0);
|
|
3374
|
-
return /* @__PURE__ */
|
|
3375
|
-
/* @__PURE__ */
|
|
3376
|
-
/* @__PURE__ */
|
|
3377
|
-
source.locator && /* @__PURE__ */
|
|
3378
|
-
openable && (onOpenSource ? /* @__PURE__ */
|
|
2464
|
+
return /* @__PURE__ */ jsxs6("li", { className: "rounded-md border border-card-edge bg-card px-2.5 py-2", children: [
|
|
2465
|
+
/* @__PURE__ */ jsxs6("div", { className: "flex flex-wrap items-baseline gap-x-2 gap-y-1", children: [
|
|
2466
|
+
/* @__PURE__ */ jsx8("span", { className: "text-sm font-medium text-foreground", children: source.label }),
|
|
2467
|
+
source.locator && /* @__PURE__ */ jsx8("span", { className: "text-xs text-muted-foreground", children: source.locator }),
|
|
2468
|
+
openable && (onOpenSource ? /* @__PURE__ */ jsxs6(
|
|
3379
2469
|
"button",
|
|
3380
2470
|
{
|
|
3381
2471
|
type: "button",
|
|
@@ -3386,7 +2476,7 @@ function SourceRow({
|
|
|
3386
2476
|
source.label
|
|
3387
2477
|
]
|
|
3388
2478
|
}
|
|
3389
|
-
) : /* @__PURE__ */
|
|
2479
|
+
) : /* @__PURE__ */ jsxs6(
|
|
3390
2480
|
"a",
|
|
3391
2481
|
{
|
|
3392
2482
|
href: source.href,
|
|
@@ -3400,7 +2490,7 @@ function SourceRow({
|
|
|
3400
2490
|
}
|
|
3401
2491
|
))
|
|
3402
2492
|
] }),
|
|
3403
|
-
source.quote && /* @__PURE__ */
|
|
2493
|
+
source.quote && /* @__PURE__ */ jsxs6("blockquote", { className: "mt-1 border-l-2 border-primary/50 pl-2 text-[12px] italic leading-snug text-foreground", children: [
|
|
3404
2494
|
"\u201C",
|
|
3405
2495
|
source.quote,
|
|
3406
2496
|
"\u201D"
|
|
@@ -3409,14 +2499,14 @@ function SourceRow({
|
|
|
3409
2499
|
// update is theirs to read, not an interruption. Either way it is TEXT
|
|
3410
2500
|
// — a spinner alone and a greyed row alone both render as "nothing
|
|
3411
2501
|
// here".
|
|
3412
|
-
/* @__PURE__ */
|
|
2502
|
+
/* @__PURE__ */ jsxs6(
|
|
3413
2503
|
"p",
|
|
3414
2504
|
{
|
|
3415
2505
|
role: "status",
|
|
3416
2506
|
className: `mt-1 text-xs ${status === "unavailable" ? "text-destructive" : "text-muted-foreground"}`,
|
|
3417
2507
|
children: [
|
|
3418
2508
|
statusLine,
|
|
3419
|
-
status === "unavailable" && onRetrySource && /* @__PURE__ */
|
|
2509
|
+
status === "unavailable" && onRetrySource && /* @__PURE__ */ jsx8(
|
|
3420
2510
|
"button",
|
|
3421
2511
|
{
|
|
3422
2512
|
type: "button",
|
|
@@ -3440,10 +2530,10 @@ function ProvenanceValue({
|
|
|
3440
2530
|
missingValueLabel = DEFAULT_MISSING_VALUE_LABEL,
|
|
3441
2531
|
className
|
|
3442
2532
|
}) {
|
|
3443
|
-
const [open, setOpen] =
|
|
3444
|
-
const triggerRef =
|
|
3445
|
-
const rootRef =
|
|
3446
|
-
const panelId =
|
|
2533
|
+
const [open, setOpen] = useState11(defaultOpen);
|
|
2534
|
+
const triggerRef = useRef7(null);
|
|
2535
|
+
const rootRef = useRef7(null);
|
|
2536
|
+
const panelId = useId();
|
|
3447
2537
|
const standing = rollUpProvenanceStanding(record, confidencePolicy);
|
|
3448
2538
|
const basisMeta = provenanceBasisMeta(record.basis);
|
|
3449
2539
|
const standingMeta = provenanceStandingMeta(standing);
|
|
@@ -3452,7 +2542,7 @@ function ProvenanceValue({
|
|
|
3452
2542
|
const sources = record.sources ?? [];
|
|
3453
2543
|
const inputs = record.inputs ?? [];
|
|
3454
2544
|
const hasValue = record.display.trim() !== "";
|
|
3455
|
-
const onKeyDown =
|
|
2545
|
+
const onKeyDown = useCallback6(
|
|
3456
2546
|
(event) => {
|
|
3457
2547
|
if (event.key !== "Escape" || !open) return;
|
|
3458
2548
|
event.stopPropagation();
|
|
@@ -3461,11 +2551,11 @@ function ProvenanceValue({
|
|
|
3461
2551
|
},
|
|
3462
2552
|
[open]
|
|
3463
2553
|
);
|
|
3464
|
-
const onToggle =
|
|
2554
|
+
const onToggle = useCallback6(() => {
|
|
3465
2555
|
if (!open) closeTrailsOutside(rootRef.current);
|
|
3466
2556
|
setOpen(!open);
|
|
3467
2557
|
}, [open]);
|
|
3468
|
-
|
|
2558
|
+
useEffect7(() => {
|
|
3469
2559
|
const root = rootRef.current;
|
|
3470
2560
|
if (!open || root === null) return;
|
|
3471
2561
|
const entry = { root, close: () => setOpen(false) };
|
|
@@ -3483,12 +2573,12 @@ function ProvenanceValue({
|
|
|
3483
2573
|
document.removeEventListener("touchstart", onPointerDown, true);
|
|
3484
2574
|
};
|
|
3485
2575
|
}, [open]);
|
|
3486
|
-
const summary = /* @__PURE__ */
|
|
3487
|
-
record.label && /* @__PURE__ */
|
|
3488
|
-
/* @__PURE__ */
|
|
2576
|
+
const summary = /* @__PURE__ */ jsxs6("span", { className: "inline-flex flex-wrap items-baseline gap-x-1.5", children: [
|
|
2577
|
+
record.label && /* @__PURE__ */ jsx8("span", { className: "text-xs text-muted-foreground", children: record.label }),
|
|
2578
|
+
/* @__PURE__ */ jsx8("span", { className: hasValue ? "text-sm text-foreground" : "text-sm italic text-muted-foreground", children: hasValue ? record.display : missingValueLabel })
|
|
3489
2579
|
] });
|
|
3490
2580
|
if (maxDepth <= 0) {
|
|
3491
|
-
return /* @__PURE__ */
|
|
2581
|
+
return /* @__PURE__ */ jsxs6(
|
|
3492
2582
|
"div",
|
|
3493
2583
|
{
|
|
3494
2584
|
className: `inline-block max-w-full ${className ?? ""}`,
|
|
@@ -3496,22 +2586,22 @@ function ProvenanceValue({
|
|
|
3496
2586
|
"data-provenance-standing": standing,
|
|
3497
2587
|
children: [
|
|
3498
2588
|
summary,
|
|
3499
|
-
/* @__PURE__ */
|
|
2589
|
+
/* @__PURE__ */ jsxs6(
|
|
3500
2590
|
"span",
|
|
3501
2591
|
{
|
|
3502
2592
|
className: `ml-1.5 inline-flex items-center gap-1 rounded-full border px-1.5 py-0.5 text-xs font-medium ${BASIS_TONES[record.basis]}`,
|
|
3503
2593
|
children: [
|
|
3504
|
-
/* @__PURE__ */
|
|
2594
|
+
/* @__PURE__ */ jsx8(BasisGlyph, { basis: record.basis, className: "h-3 w-3" }),
|
|
3505
2595
|
basisMeta.label
|
|
3506
2596
|
]
|
|
3507
2597
|
}
|
|
3508
2598
|
),
|
|
3509
|
-
/* @__PURE__ */
|
|
2599
|
+
/* @__PURE__ */ jsx8("span", { className: "mt-0.5 block text-xs text-muted-foreground", children: describeProvenance(record) })
|
|
3510
2600
|
]
|
|
3511
2601
|
}
|
|
3512
2602
|
);
|
|
3513
2603
|
}
|
|
3514
|
-
return /* @__PURE__ */
|
|
2604
|
+
return /* @__PURE__ */ jsxs6(
|
|
3515
2605
|
"div",
|
|
3516
2606
|
{
|
|
3517
2607
|
ref: rootRef,
|
|
@@ -3520,9 +2610,9 @@ function ProvenanceValue({
|
|
|
3520
2610
|
"data-provenance-basis": record.basis,
|
|
3521
2611
|
"data-provenance-standing": standing,
|
|
3522
2612
|
children: [
|
|
3523
|
-
/* @__PURE__ */
|
|
2613
|
+
/* @__PURE__ */ jsxs6("span", { className: "inline-flex flex-wrap items-baseline gap-1.5", children: [
|
|
3524
2614
|
summary,
|
|
3525
|
-
/* @__PURE__ */
|
|
2615
|
+
/* @__PURE__ */ jsxs6(
|
|
3526
2616
|
"button",
|
|
3527
2617
|
{
|
|
3528
2618
|
ref: triggerRef,
|
|
@@ -3533,17 +2623,17 @@ function ProvenanceValue({
|
|
|
3533
2623
|
"aria-label": provenanceTriggerLabel(record, standing),
|
|
3534
2624
|
className: `inline-flex items-center gap-1 rounded-full border px-1.5 py-0.5 text-xs font-medium transition hover:brightness-105 focus:outline-none focus-visible:ring-2 focus-visible:ring-ring ${BASIS_TONES[record.basis]}`,
|
|
3535
2625
|
children: [
|
|
3536
|
-
/* @__PURE__ */
|
|
3537
|
-
/* @__PURE__ */
|
|
2626
|
+
/* @__PURE__ */ jsx8(BasisGlyph, { basis: record.basis, className: "h-3 w-3" }),
|
|
2627
|
+
/* @__PURE__ */ jsx8("span", { "aria-hidden": true, children: basisMeta.label })
|
|
3538
2628
|
]
|
|
3539
2629
|
}
|
|
3540
2630
|
),
|
|
3541
2631
|
standing !== "settled" && // Legible at rest: what to do about the value does not wait for
|
|
3542
2632
|
// someone to open the panel. `aria-hidden` because the trigger's
|
|
3543
2633
|
// accessible name already carries it — this is the visual half.
|
|
3544
|
-
/* @__PURE__ */
|
|
2634
|
+
/* @__PURE__ */ jsx8("span", { "aria-hidden": true, className: `text-xs font-medium ${STANDING_TONES[standing]}`, children: standingMeta.label })
|
|
3545
2635
|
] }),
|
|
3546
|
-
open && /* @__PURE__ */
|
|
2636
|
+
open && /* @__PURE__ */ jsxs6(
|
|
3547
2637
|
"div",
|
|
3548
2638
|
{
|
|
3549
2639
|
id: panelId,
|
|
@@ -3551,19 +2641,19 @@ function ProvenanceValue({
|
|
|
3551
2641
|
"aria-label": provenanceTriggerLabel(record, standing),
|
|
3552
2642
|
className: "mt-1.5 w-full min-w-0 space-y-2 rounded-lg border border-border bg-card px-3 py-2.5 text-left",
|
|
3553
2643
|
children: [
|
|
3554
|
-
/* @__PURE__ */
|
|
3555
|
-
/* @__PURE__ */
|
|
3556
|
-
/* @__PURE__ */
|
|
2644
|
+
/* @__PURE__ */ jsxs6("div", { children: [
|
|
2645
|
+
/* @__PURE__ */ jsx8("p", { className: "text-[12px] leading-snug text-foreground", children: describeProvenance(record) }),
|
|
2646
|
+
/* @__PURE__ */ jsxs6("p", { className: `mt-0.5 text-xs leading-snug ${STANDING_TONES[standing]}`, children: [
|
|
3557
2647
|
standingMeta.label,
|
|
3558
2648
|
" \u2014 ",
|
|
3559
2649
|
provenanceNextMove(record, standing, confidencePolicy)
|
|
3560
2650
|
] }),
|
|
3561
|
-
basisMeta.checkableAgainst === null && /* @__PURE__ */
|
|
2651
|
+
basisMeta.checkableAgainst === null && /* @__PURE__ */ jsxs6("p", { className: "mt-0.5 text-xs leading-snug text-muted-foreground", children: [
|
|
3562
2652
|
basisMeta.meaning,
|
|
3563
2653
|
" There is nothing outside the model to check it against."
|
|
3564
2654
|
] })
|
|
3565
2655
|
] }),
|
|
3566
|
-
sources.length > 0 && /* @__PURE__ */
|
|
2656
|
+
sources.length > 0 && /* @__PURE__ */ jsx8("ul", { className: "space-y-1.5", children: sources.map((source, index) => /* @__PURE__ */ jsx8(
|
|
3567
2657
|
SourceRow,
|
|
3568
2658
|
{
|
|
3569
2659
|
source,
|
|
@@ -3576,12 +2666,12 @@ function ProvenanceValue({
|
|
|
3576
2666
|
gaps.filter((gap) => gap.kind !== "unavailable-source").map((gap) => (
|
|
3577
2667
|
// An unavailable source already states itself on its own row; a
|
|
3578
2668
|
// structural gap has no row to state it, so it gets one here.
|
|
3579
|
-
/* @__PURE__ */
|
|
2669
|
+
/* @__PURE__ */ jsx8("p", { className: "rounded-md bg-destructive/10 px-2 py-1.5 text-xs leading-snug text-destructive", children: gap.message }, gap.kind)
|
|
3580
2670
|
)),
|
|
3581
|
-
loading.length > 0 && sources.length === 0 && /* @__PURE__ */
|
|
3582
|
-
inputs.length > 0 && /* @__PURE__ */
|
|
3583
|
-
/* @__PURE__ */
|
|
3584
|
-
/* @__PURE__ */
|
|
2671
|
+
loading.length > 0 && sources.length === 0 && /* @__PURE__ */ jsx8("p", { role: "status", className: "text-xs text-muted-foreground", children: "Looking up where this came from\u2026" }),
|
|
2672
|
+
inputs.length > 0 && /* @__PURE__ */ jsxs6("div", { className: "border-t border-border pt-2", children: [
|
|
2673
|
+
/* @__PURE__ */ jsx8("p", { className: "text-xs font-medium uppercase tracking-[0.05em] text-muted-foreground", children: record.derivation ? `Computed from ${record.derivation}` : "Computed from" }),
|
|
2674
|
+
/* @__PURE__ */ jsx8("ul", { className: "mt-1.5 space-y-1.5", children: inputs.map((input, index) => /* @__PURE__ */ jsx8("li", { children: /* @__PURE__ */ jsx8(
|
|
3585
2675
|
ProvenanceValue,
|
|
3586
2676
|
{
|
|
3587
2677
|
record: input,
|
|
@@ -3602,26 +2692,26 @@ function ProvenanceValue({
|
|
|
3602
2692
|
}
|
|
3603
2693
|
function ProvenanceLegend({ bases, className }) {
|
|
3604
2694
|
if (bases.length === 0) return null;
|
|
3605
|
-
return /* @__PURE__ */
|
|
2695
|
+
return /* @__PURE__ */ jsx8("ul", { className: `flex flex-wrap items-center gap-x-3 gap-y-1.5 ${className ?? ""}`, children: bases.map((basis) => {
|
|
3606
2696
|
const meta = provenanceBasisMeta(basis);
|
|
3607
|
-
return /* @__PURE__ */
|
|
3608
|
-
/* @__PURE__ */
|
|
2697
|
+
return /* @__PURE__ */ jsxs6("li", { className: "flex items-center gap-1.5 text-xs text-muted-foreground", children: [
|
|
2698
|
+
/* @__PURE__ */ jsxs6(
|
|
3609
2699
|
"span",
|
|
3610
2700
|
{
|
|
3611
2701
|
className: `inline-flex items-center gap-1 rounded-full border px-1.5 py-0.5 text-xs font-medium ${BASIS_TONES[basis]}`,
|
|
3612
2702
|
children: [
|
|
3613
|
-
/* @__PURE__ */
|
|
2703
|
+
/* @__PURE__ */ jsx8(BasisGlyph, { basis, className: "h-3 w-3" }),
|
|
3614
2704
|
meta.label
|
|
3615
2705
|
]
|
|
3616
2706
|
}
|
|
3617
2707
|
),
|
|
3618
|
-
/* @__PURE__ */
|
|
2708
|
+
/* @__PURE__ */ jsx8("span", { children: meta.meaning })
|
|
3619
2709
|
] }, basis);
|
|
3620
2710
|
}) });
|
|
3621
2711
|
}
|
|
3622
2712
|
|
|
3623
2713
|
// src/web-react/seat-paywall.tsx
|
|
3624
|
-
import { Fragment as
|
|
2714
|
+
import { Fragment as Fragment3, jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
3625
2715
|
function usd(cents) {
|
|
3626
2716
|
return new Intl.NumberFormat("en-US", {
|
|
3627
2717
|
style: "currency",
|
|
@@ -3631,7 +2721,7 @@ function usd(cents) {
|
|
|
3631
2721
|
}).format(cents / 100);
|
|
3632
2722
|
}
|
|
3633
2723
|
function CheckGlyph3() {
|
|
3634
|
-
return /* @__PURE__ */
|
|
2724
|
+
return /* @__PURE__ */ jsx9(
|
|
3635
2725
|
"svg",
|
|
3636
2726
|
{
|
|
3637
2727
|
className: "h-4 w-4 shrink-0 text-primary",
|
|
@@ -3642,14 +2732,14 @@ function CheckGlyph3() {
|
|
|
3642
2732
|
strokeLinecap: "round",
|
|
3643
2733
|
strokeLinejoin: "round",
|
|
3644
2734
|
"aria-hidden": true,
|
|
3645
|
-
children: /* @__PURE__ */
|
|
2735
|
+
children: /* @__PURE__ */ jsx9("path", { d: "M20 6 9 17l-5-5" })
|
|
3646
2736
|
}
|
|
3647
2737
|
);
|
|
3648
2738
|
}
|
|
3649
2739
|
function Benefit({ children }) {
|
|
3650
|
-
return /* @__PURE__ */
|
|
3651
|
-
/* @__PURE__ */
|
|
3652
|
-
/* @__PURE__ */
|
|
2740
|
+
return /* @__PURE__ */ jsxs7("li", { className: "flex items-start gap-2.5 text-sm text-foreground", children: [
|
|
2741
|
+
/* @__PURE__ */ jsx9("span", { className: "mt-0.5", children: /* @__PURE__ */ jsx9(CheckGlyph3, {}) }),
|
|
2742
|
+
/* @__PURE__ */ jsx9("span", { children })
|
|
3653
2743
|
] });
|
|
3654
2744
|
}
|
|
3655
2745
|
function SeatPaywall({
|
|
@@ -3667,45 +2757,45 @@ function SeatPaywall({
|
|
|
3667
2757
|
const recurringPrice = offer ? usd(offer.recurring.priceCents) : `$${priceUsd}`;
|
|
3668
2758
|
const recurringUsage = offer ? usd(offer.recurring.includedCreditsCents) : `$${includedUsageUsd}`;
|
|
3669
2759
|
const introductory = offer?.introductory ?? null;
|
|
3670
|
-
return /* @__PURE__ */
|
|
3671
|
-
/* @__PURE__ */
|
|
3672
|
-
/* @__PURE__ */
|
|
2760
|
+
return /* @__PURE__ */ jsx9("div", { className: "flex min-h-[60vh] w-full items-center justify-center p-6", children: /* @__PURE__ */ jsxs7("div", { className: "w-full max-w-md rounded-2xl border border-card-edge bg-card p-8", children: [
|
|
2761
|
+
/* @__PURE__ */ jsx9("p", { className: "text-xs font-semibold uppercase tracking-[0.05em] text-muted-foreground", children: product }),
|
|
2762
|
+
/* @__PURE__ */ jsxs7("h1", { className: "mt-2 text-2xl font-semibold tracking-tight text-foreground", children: [
|
|
3673
2763
|
"Unlock ",
|
|
3674
2764
|
product
|
|
3675
2765
|
] }),
|
|
3676
|
-
tagline && /* @__PURE__ */
|
|
3677
|
-
introductory ? /* @__PURE__ */
|
|
3678
|
-
/* @__PURE__ */
|
|
3679
|
-
/* @__PURE__ */
|
|
3680
|
-
/* @__PURE__ */
|
|
2766
|
+
tagline && /* @__PURE__ */ jsx9("p", { className: "mt-2 text-sm text-muted-foreground", children: tagline }),
|
|
2767
|
+
introductory ? /* @__PURE__ */ jsxs7(Fragment3, { children: [
|
|
2768
|
+
/* @__PURE__ */ jsxs7("div", { className: "mt-6 flex items-baseline gap-1.5", children: [
|
|
2769
|
+
/* @__PURE__ */ jsx9("span", { className: "text-3xl font-semibold text-foreground", children: usd(introductory.priceCents) }),
|
|
2770
|
+
/* @__PURE__ */ jsx9("span", { className: "text-sm text-muted-foreground", children: "first month" })
|
|
3681
2771
|
] }),
|
|
3682
|
-
/* @__PURE__ */
|
|
2772
|
+
/* @__PURE__ */ jsxs7("p", { className: "mt-1 text-sm text-muted-foreground", children: [
|
|
3683
2773
|
"Includes ",
|
|
3684
2774
|
usd(introductory.includedCreditsCents),
|
|
3685
2775
|
" of AI usage in your first month"
|
|
3686
2776
|
] }),
|
|
3687
|
-
/* @__PURE__ */
|
|
2777
|
+
/* @__PURE__ */ jsxs7("p", { className: "mt-1 text-sm text-muted-foreground", children: [
|
|
3688
2778
|
"Then ",
|
|
3689
2779
|
recurringPrice,
|
|
3690
2780
|
"/mo \xB7 includes ",
|
|
3691
2781
|
recurringUsage,
|
|
3692
2782
|
"/mo of AI usage"
|
|
3693
2783
|
] })
|
|
3694
|
-
] }) : /* @__PURE__ */
|
|
3695
|
-
/* @__PURE__ */
|
|
3696
|
-
/* @__PURE__ */
|
|
3697
|
-
/* @__PURE__ */
|
|
2784
|
+
] }) : /* @__PURE__ */ jsxs7(Fragment3, { children: [
|
|
2785
|
+
/* @__PURE__ */ jsxs7("div", { className: "mt-6 flex items-baseline gap-1.5", children: [
|
|
2786
|
+
/* @__PURE__ */ jsx9("span", { className: "text-3xl font-semibold text-foreground", children: recurringPrice }),
|
|
2787
|
+
/* @__PURE__ */ jsx9("span", { className: "text-sm text-muted-foreground", children: "/mo" })
|
|
3698
2788
|
] }),
|
|
3699
|
-
/* @__PURE__ */
|
|
2789
|
+
/* @__PURE__ */ jsxs7("p", { className: "mt-1 text-sm text-muted-foreground", children: [
|
|
3700
2790
|
"Includes ",
|
|
3701
2791
|
recurringUsage,
|
|
3702
2792
|
"/mo of AI usage"
|
|
3703
2793
|
] })
|
|
3704
2794
|
] }),
|
|
3705
|
-
/* @__PURE__ */
|
|
2795
|
+
/* @__PURE__ */ jsx9("ul", { className: "mt-6 space-y-2.5", children: (benefits ?? [
|
|
3706
2796
|
`Full access to ${product}`
|
|
3707
|
-
]).map((benefit, i) => /* @__PURE__ */
|
|
3708
|
-
/* @__PURE__ */
|
|
2797
|
+
]).map((benefit, i) => /* @__PURE__ */ jsx9(Benefit, { children: benefit }, i)) }),
|
|
2798
|
+
/* @__PURE__ */ jsx9(
|
|
3709
2799
|
"button",
|
|
3710
2800
|
{
|
|
3711
2801
|
type: "button",
|
|
@@ -3715,20 +2805,20 @@ function SeatPaywall({
|
|
|
3715
2805
|
children: pending ? "Opening checkout\u2026" : ctaLabel ?? "Continue to checkout"
|
|
3716
2806
|
}
|
|
3717
2807
|
),
|
|
3718
|
-
footnote && /* @__PURE__ */
|
|
2808
|
+
footnote && /* @__PURE__ */ jsx9("p", { className: "mt-3 text-center text-xs text-muted-foreground/70", children: footnote })
|
|
3719
2809
|
] }) });
|
|
3720
2810
|
}
|
|
3721
2811
|
|
|
3722
2812
|
// src/web-react/record-grid.tsx
|
|
3723
2813
|
import {
|
|
3724
|
-
Fragment as
|
|
2814
|
+
Fragment as Fragment4,
|
|
3725
2815
|
isValidElement,
|
|
3726
|
-
useCallback as
|
|
3727
|
-
useEffect as
|
|
3728
|
-
useId as
|
|
3729
|
-
useMemo as
|
|
3730
|
-
useRef as
|
|
3731
|
-
useState as
|
|
2816
|
+
useCallback as useCallback7,
|
|
2817
|
+
useEffect as useEffect8,
|
|
2818
|
+
useId as useId2,
|
|
2819
|
+
useMemo as useMemo5,
|
|
2820
|
+
useRef as useRef8,
|
|
2821
|
+
useState as useState12
|
|
3732
2822
|
} from "react";
|
|
3733
2823
|
|
|
3734
2824
|
// src/web-react/record-grid-model.ts
|
|
@@ -4084,7 +3174,7 @@ function pruneRecordGridOverlay(rows, overlay) {
|
|
|
4084
3174
|
}
|
|
4085
3175
|
|
|
4086
3176
|
// src/web-react/record-grid.tsx
|
|
4087
|
-
import { jsx as
|
|
3177
|
+
import { jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
4088
3178
|
var EMPTY_RECORD_GRID_ROWS = [];
|
|
4089
3179
|
var CELL_KEY_SEPARATOR = "\0";
|
|
4090
3180
|
function cellKey(rowId, columnId) {
|
|
@@ -4143,57 +3233,57 @@ function RecordGrid({
|
|
|
4143
3233
|
loadingRowCount = 3,
|
|
4144
3234
|
className
|
|
4145
3235
|
}) {
|
|
4146
|
-
const fieldPrefix =
|
|
4147
|
-
const [overlay, setOverlay] =
|
|
4148
|
-
const [editing, setEditingState] =
|
|
4149
|
-
const [cellErrors, setCellErrors] =
|
|
4150
|
-
const [rowErrors, setRowErrors] =
|
|
4151
|
-
const [pendingRows, setPendingRows] =
|
|
4152
|
-
const [focus, setFocus] =
|
|
4153
|
-
const [openSource, setOpenSource] =
|
|
4154
|
-
const [confirmDelete, setConfirmDelete] =
|
|
4155
|
-
const [adding, setAdding] =
|
|
4156
|
-
const [draft, setDraft] =
|
|
4157
|
-
const [draftErrors, setDraftErrors] =
|
|
4158
|
-
const [draftError, setDraftError] =
|
|
4159
|
-
const [creating, setCreating] =
|
|
4160
|
-
const cellRefs =
|
|
4161
|
-
const settling =
|
|
4162
|
-
const draftCounter =
|
|
4163
|
-
const editingRef =
|
|
4164
|
-
const setEditing =
|
|
3236
|
+
const fieldPrefix = useId2();
|
|
3237
|
+
const [overlay, setOverlay] = useState12(EMPTY_RECORD_GRID_OVERLAY);
|
|
3238
|
+
const [editing, setEditingState] = useState12(null);
|
|
3239
|
+
const [cellErrors, setCellErrors] = useState12({});
|
|
3240
|
+
const [rowErrors, setRowErrors] = useState12({});
|
|
3241
|
+
const [pendingRows, setPendingRows] = useState12({});
|
|
3242
|
+
const [focus, setFocus] = useState12(null);
|
|
3243
|
+
const [openSource, setOpenSource] = useState12(null);
|
|
3244
|
+
const [confirmDelete, setConfirmDelete] = useState12(null);
|
|
3245
|
+
const [adding, setAdding] = useState12(false);
|
|
3246
|
+
const [draft, setDraft] = useState12({ ...newRowDefaults ?? {} });
|
|
3247
|
+
const [draftErrors, setDraftErrors] = useState12({});
|
|
3248
|
+
const [draftError, setDraftError] = useState12(null);
|
|
3249
|
+
const [creating, setCreating] = useState12(false);
|
|
3250
|
+
const cellRefs = useRef8(/* @__PURE__ */ new Map());
|
|
3251
|
+
const settling = useRef8(false);
|
|
3252
|
+
const draftCounter = useRef8(0);
|
|
3253
|
+
const editingRef = useRef8(null);
|
|
3254
|
+
const setEditing = useCallback7((next) => {
|
|
4165
3255
|
editingRef.current = next;
|
|
4166
3256
|
setEditingState(next);
|
|
4167
3257
|
}, []);
|
|
4168
3258
|
const callerRows = state.status === "ready" || state.status === "empty" ? state.value : EMPTY_RECORD_GRID_ROWS;
|
|
4169
|
-
|
|
3259
|
+
useEffect8(() => {
|
|
4170
3260
|
setOverlay((current) => pruneRecordGridOverlay(callerRows, current));
|
|
4171
3261
|
}, [callerRows]);
|
|
4172
|
-
const visibleRows =
|
|
4173
|
-
const diffs =
|
|
3262
|
+
const visibleRows = useMemo5(() => projectRecordGridRows(callerRows, overlay), [callerRows, overlay]);
|
|
3263
|
+
const diffs = useMemo5(
|
|
4174
3264
|
() => proposed === void 0 ? null : diffRecordGridProposal(visibleRows, proposed),
|
|
4175
3265
|
[proposed, visibleRows]
|
|
4176
3266
|
);
|
|
4177
3267
|
const reviewing = diffs !== null && diffs.length > 0;
|
|
4178
|
-
const diffByRow =
|
|
4179
|
-
const diffCellByKey =
|
|
3268
|
+
const diffByRow = useMemo5(() => new Map((diffs ?? []).map((diff) => [diff.rowId, diff])), [diffs]);
|
|
3269
|
+
const diffCellByKey = useMemo5(() => {
|
|
4180
3270
|
const map = /* @__PURE__ */ new Map();
|
|
4181
3271
|
for (const diff of diffs ?? []) {
|
|
4182
3272
|
for (const cell of diff.cells) map.set(cellKey(diff.rowId, cell.columnId), cell);
|
|
4183
3273
|
}
|
|
4184
3274
|
return map;
|
|
4185
3275
|
}, [diffs]);
|
|
4186
|
-
const addedRows =
|
|
3276
|
+
const addedRows = useMemo5(
|
|
4187
3277
|
() => (diffs ?? []).filter((diff) => diff.kind === "added").map((diff) => diff.row),
|
|
4188
3278
|
[diffs]
|
|
4189
3279
|
);
|
|
4190
|
-
const activeFocus =
|
|
3280
|
+
const activeFocus = useMemo5(() => {
|
|
4191
3281
|
if (focus === null) return null;
|
|
4192
3282
|
if (!visibleRows.some((row) => row.id === focus.rowId)) return null;
|
|
4193
3283
|
if (!columns.some((column) => column.id === focus.columnId)) return null;
|
|
4194
3284
|
return focus;
|
|
4195
3285
|
}, [columns, focus, visibleRows]);
|
|
4196
|
-
const setCellError =
|
|
3286
|
+
const setCellError = useCallback7((key, message) => {
|
|
4197
3287
|
setCellErrors((current) => {
|
|
4198
3288
|
if (message === null) {
|
|
4199
3289
|
if (!(key in current)) return current;
|
|
@@ -4205,7 +3295,7 @@ function RecordGrid({
|
|
|
4205
3295
|
return { ...current, [key]: message };
|
|
4206
3296
|
});
|
|
4207
3297
|
}, []);
|
|
4208
|
-
const setRowError =
|
|
3298
|
+
const setRowError = useCallback7((rowId, message) => {
|
|
4209
3299
|
setRowErrors((current) => {
|
|
4210
3300
|
if (message === null) {
|
|
4211
3301
|
if (!(rowId in current)) return current;
|
|
@@ -4216,7 +3306,7 @@ function RecordGrid({
|
|
|
4216
3306
|
return { ...current, [rowId]: message };
|
|
4217
3307
|
});
|
|
4218
3308
|
}, []);
|
|
4219
|
-
const setRowPending =
|
|
3309
|
+
const setRowPending = useCallback7((rowId, pending) => {
|
|
4220
3310
|
setPendingRows((current) => {
|
|
4221
3311
|
if (pending) return rowId in current ? current : { ...current, [rowId]: true };
|
|
4222
3312
|
if (!(rowId in current)) return current;
|
|
@@ -4225,11 +3315,11 @@ function RecordGrid({
|
|
|
4225
3315
|
return next;
|
|
4226
3316
|
});
|
|
4227
3317
|
}, []);
|
|
4228
|
-
const focusCell =
|
|
3318
|
+
const focusCell = useCallback7((rowId, columnId) => {
|
|
4229
3319
|
setFocus({ rowId, columnId });
|
|
4230
3320
|
cellRefs.current.get(cellKey(rowId, columnId))?.focus();
|
|
4231
3321
|
}, []);
|
|
4232
|
-
const beginEdit =
|
|
3322
|
+
const beginEdit = useCallback7(
|
|
4233
3323
|
(row, column) => {
|
|
4234
3324
|
setCellError(cellKey(row.id, column.id), null);
|
|
4235
3325
|
setEditing({
|
|
@@ -4240,7 +3330,7 @@ function RecordGrid({
|
|
|
4240
3330
|
},
|
|
4241
3331
|
[setCellError, setEditing]
|
|
4242
3332
|
);
|
|
4243
|
-
const applyCellWrite =
|
|
3333
|
+
const applyCellWrite = useCallback7(
|
|
4244
3334
|
async (row, column, value) => {
|
|
4245
3335
|
if (!onUpdate) return;
|
|
4246
3336
|
const values = { ...row.values, [column.id]: value };
|
|
@@ -4268,7 +3358,7 @@ function RecordGrid({
|
|
|
4268
3358
|
},
|
|
4269
3359
|
[locale, onUpdate, setRowError, setRowPending]
|
|
4270
3360
|
);
|
|
4271
|
-
const commitEdit =
|
|
3361
|
+
const commitEdit = useCallback7(
|
|
4272
3362
|
async (row, column, text) => {
|
|
4273
3363
|
const open = editingRef.current;
|
|
4274
3364
|
if (open === null || open.rowId !== row.id || open.columnId !== column.id) return;
|
|
@@ -4292,7 +3382,7 @@ function RecordGrid({
|
|
|
4292
3382
|
},
|
|
4293
3383
|
[applyCellWrite, setCellError, setEditing]
|
|
4294
3384
|
);
|
|
4295
|
-
const cancelEdit =
|
|
3385
|
+
const cancelEdit = useCallback7(
|
|
4296
3386
|
(row, column) => {
|
|
4297
3387
|
setCellError(cellKey(row.id, column.id), null);
|
|
4298
3388
|
setEditing(null);
|
|
@@ -4300,7 +3390,7 @@ function RecordGrid({
|
|
|
4300
3390
|
},
|
|
4301
3391
|
[focusCell, setCellError, setEditing]
|
|
4302
3392
|
);
|
|
4303
|
-
const performDelete =
|
|
3393
|
+
const performDelete = useCallback7(
|
|
4304
3394
|
async (row) => {
|
|
4305
3395
|
if (!onDelete) return;
|
|
4306
3396
|
setConfirmDelete(null);
|
|
@@ -4318,16 +3408,16 @@ function RecordGrid({
|
|
|
4318
3408
|
},
|
|
4319
3409
|
[columns, onDelete, setRowError]
|
|
4320
3410
|
);
|
|
4321
|
-
const resetDraft =
|
|
3411
|
+
const resetDraft = useCallback7(() => {
|
|
4322
3412
|
setDraft({ ...newRowDefaults ?? {} });
|
|
4323
3413
|
setDraftErrors({});
|
|
4324
3414
|
setDraftError(null);
|
|
4325
3415
|
}, [newRowDefaults]);
|
|
4326
|
-
const openAdd =
|
|
3416
|
+
const openAdd = useCallback7(() => {
|
|
4327
3417
|
resetDraft();
|
|
4328
3418
|
setAdding(true);
|
|
4329
3419
|
}, [resetDraft]);
|
|
4330
|
-
const submitDraft =
|
|
3420
|
+
const submitDraft = useCallback7(async () => {
|
|
4331
3421
|
if (!onCreate) return;
|
|
4332
3422
|
const validated = validateRecordGridRow(columns, draft);
|
|
4333
3423
|
if (!validated.succeeded) {
|
|
@@ -4357,7 +3447,7 @@ function RecordGrid({
|
|
|
4357
3447
|
setOverlay((current) => withoutRecordGridCreated(current, draftId));
|
|
4358
3448
|
setDraftError(outcome.error);
|
|
4359
3449
|
}, [columns, draft, fieldPrefix, onCreate, resetDraft]);
|
|
4360
|
-
const handleGridKeyDown =
|
|
3450
|
+
const handleGridKeyDown = useCallback7(
|
|
4361
3451
|
(event) => {
|
|
4362
3452
|
if (editing !== null) return;
|
|
4363
3453
|
const target = event.target;
|
|
@@ -4396,9 +3486,9 @@ function RecordGrid({
|
|
|
4396
3486
|
[beginEdit, columns, editing, focusCell, onUpdate, reviewing, visibleRows]
|
|
4397
3487
|
);
|
|
4398
3488
|
if (state.status === "idle" || state.status === "loading") {
|
|
4399
|
-
return /* @__PURE__ */
|
|
3489
|
+
return /* @__PURE__ */ jsxs8("div", { className: `space-y-3 ${className ?? ""}`, children: [
|
|
4400
3490
|
toolbar,
|
|
4401
|
-
/* @__PURE__ */
|
|
3491
|
+
/* @__PURE__ */ jsxs8(
|
|
4402
3492
|
"div",
|
|
4403
3493
|
{
|
|
4404
3494
|
role: "status",
|
|
@@ -4406,22 +3496,22 @@ function RecordGrid({
|
|
|
4406
3496
|
"aria-live": "polite",
|
|
4407
3497
|
className: "space-y-2 rounded-xl border border-card-edge bg-card p-4",
|
|
4408
3498
|
children: [
|
|
4409
|
-
/* @__PURE__ */
|
|
3499
|
+
/* @__PURE__ */ jsxs8("span", { className: "sr-only", children: [
|
|
4410
3500
|
"Loading ",
|
|
4411
3501
|
caption
|
|
4412
3502
|
] }),
|
|
4413
|
-
Array.from({ length: Math.max(1, loadingRowCount) }, (_, index) => /* @__PURE__ */
|
|
3503
|
+
Array.from({ length: Math.max(1, loadingRowCount) }, (_, index) => /* @__PURE__ */ jsx10("div", { className: "h-8 animate-pulse rounded-md bg-secondary", "aria-hidden": true }, index))
|
|
4414
3504
|
]
|
|
4415
3505
|
}
|
|
4416
3506
|
)
|
|
4417
3507
|
] });
|
|
4418
3508
|
}
|
|
4419
3509
|
if (state.status === "error") {
|
|
4420
|
-
return /* @__PURE__ */
|
|
3510
|
+
return /* @__PURE__ */ jsxs8("div", { className: `space-y-3 ${className ?? ""}`, children: [
|
|
4421
3511
|
toolbar,
|
|
4422
|
-
/* @__PURE__ */
|
|
4423
|
-
/* @__PURE__ */
|
|
4424
|
-
/* @__PURE__ */
|
|
3512
|
+
/* @__PURE__ */ jsxs8("div", { role: "alert", className: "rounded-xl border border-destructive/40 bg-destructive/10 px-4 py-4", children: [
|
|
3513
|
+
/* @__PURE__ */ jsx10("p", { className: "text-sm font-medium text-destructive", children: state.message }),
|
|
3514
|
+
/* @__PURE__ */ jsx10(
|
|
4425
3515
|
"button",
|
|
4426
3516
|
{
|
|
4427
3517
|
type: "button",
|
|
@@ -4433,7 +3523,7 @@ function RecordGrid({
|
|
|
4433
3523
|
] })
|
|
4434
3524
|
] });
|
|
4435
3525
|
}
|
|
4436
|
-
const addForm = adding && onCreate && !reviewing ? /* @__PURE__ */
|
|
3526
|
+
const addForm = adding && onCreate && !reviewing ? /* @__PURE__ */ jsx10(
|
|
4437
3527
|
AddRecordForm,
|
|
4438
3528
|
{
|
|
4439
3529
|
columns,
|
|
@@ -4452,13 +3542,13 @@ function RecordGrid({
|
|
|
4452
3542
|
}
|
|
4453
3543
|
) : null;
|
|
4454
3544
|
if (visibleRows.length === 0 && !reviewing) {
|
|
4455
|
-
return /* @__PURE__ */
|
|
3545
|
+
return /* @__PURE__ */ jsxs8("div", { className: `space-y-3 ${className ?? ""}`, children: [
|
|
4456
3546
|
toolbar,
|
|
4457
|
-
addForm ?? /* @__PURE__ */
|
|
4458
|
-
/* @__PURE__ */
|
|
4459
|
-
empty.description && /* @__PURE__ */
|
|
4460
|
-
/* @__PURE__ */
|
|
4461
|
-
empty.action && (isValidElement(empty.action) ? empty.action : /* @__PURE__ */
|
|
3547
|
+
addForm ?? /* @__PURE__ */ jsxs8("div", { className: "rounded-xl border border-dashed border-border px-6 py-10 text-center", children: [
|
|
3548
|
+
/* @__PURE__ */ jsx10("p", { className: "text-sm font-medium text-foreground", children: empty.title }),
|
|
3549
|
+
empty.description && /* @__PURE__ */ jsx10("p", { className: "mx-auto mt-1 max-w-md text-sm text-muted-foreground", children: empty.description }),
|
|
3550
|
+
/* @__PURE__ */ jsxs8("div", { className: "mt-4 flex flex-wrap items-center justify-center gap-2", children: [
|
|
3551
|
+
empty.action && (isValidElement(empty.action) ? empty.action : /* @__PURE__ */ jsx10(
|
|
4462
3552
|
"button",
|
|
4463
3553
|
{
|
|
4464
3554
|
type: "button",
|
|
@@ -4467,7 +3557,7 @@ function RecordGrid({
|
|
|
4467
3557
|
children: empty.action.label
|
|
4468
3558
|
}
|
|
4469
3559
|
)),
|
|
4470
|
-
onCreate && /* @__PURE__ */
|
|
3560
|
+
onCreate && /* @__PURE__ */ jsx10(
|
|
4471
3561
|
"button",
|
|
4472
3562
|
{
|
|
4473
3563
|
type: "button",
|
|
@@ -4492,18 +3582,18 @@ function RecordGrid({
|
|
|
4492
3582
|
addedCount > 0 ? `${addedCount} added` : null,
|
|
4493
3583
|
removedCount > 0 ? `${removedCount} removed` : null
|
|
4494
3584
|
].filter((part) => part !== null).join(" \xB7 ");
|
|
4495
|
-
const reviewBar = reviewing ? /* @__PURE__ */
|
|
3585
|
+
const reviewBar = reviewing ? /* @__PURE__ */ jsxs8(
|
|
4496
3586
|
"div",
|
|
4497
3587
|
{
|
|
4498
3588
|
"data-record-grid-review": "",
|
|
4499
3589
|
className: "flex flex-wrap items-center justify-between gap-3 rounded-xl border border-card-edge bg-card px-4 py-2.5",
|
|
4500
3590
|
children: [
|
|
4501
|
-
/* @__PURE__ */
|
|
4502
|
-
/* @__PURE__ */
|
|
4503
|
-
/* @__PURE__ */
|
|
3591
|
+
/* @__PURE__ */ jsxs8("div", { className: "min-w-0", children: [
|
|
3592
|
+
/* @__PURE__ */ jsx10("p", { className: "text-[11px] font-semibold uppercase tracking-[0.05em] text-muted-foreground", children: "Proposed changes" }),
|
|
3593
|
+
/* @__PURE__ */ jsx10("p", { className: "mt-0.5 text-xs tabular-nums text-muted-foreground", children: reviewSummary })
|
|
4504
3594
|
] }),
|
|
4505
|
-
(onAcceptAll || onRejectAll) && /* @__PURE__ */
|
|
4506
|
-
onRejectAll && /* @__PURE__ */
|
|
3595
|
+
(onAcceptAll || onRejectAll) && /* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-2", children: [
|
|
3596
|
+
onRejectAll && /* @__PURE__ */ jsx10(
|
|
4507
3597
|
"button",
|
|
4508
3598
|
{
|
|
4509
3599
|
type: "button",
|
|
@@ -4513,7 +3603,7 @@ function RecordGrid({
|
|
|
4513
3603
|
children: "Reject all"
|
|
4514
3604
|
}
|
|
4515
3605
|
),
|
|
4516
|
-
onAcceptAll && /* @__PURE__ */
|
|
3606
|
+
onAcceptAll && /* @__PURE__ */ jsx10(
|
|
4517
3607
|
"button",
|
|
4518
3608
|
{
|
|
4519
3609
|
type: "button",
|
|
@@ -4527,10 +3617,10 @@ function RecordGrid({
|
|
|
4527
3617
|
]
|
|
4528
3618
|
}
|
|
4529
3619
|
) : null;
|
|
4530
|
-
return /* @__PURE__ */
|
|
3620
|
+
return /* @__PURE__ */ jsxs8("div", { className: `space-y-3 ${className ?? ""}`, children: [
|
|
4531
3621
|
toolbar,
|
|
4532
3622
|
reviewBar,
|
|
4533
|
-
/* @__PURE__ */
|
|
3623
|
+
/* @__PURE__ */ jsx10("div", { className: "overflow-x-auto rounded-xl border border-card-edge bg-card", children: /* @__PURE__ */ jsxs8(
|
|
4534
3624
|
"table",
|
|
4535
3625
|
{
|
|
4536
3626
|
role: "grid",
|
|
@@ -4538,8 +3628,8 @@ function RecordGrid({
|
|
|
4538
3628
|
className: "w-full border-collapse text-left text-sm",
|
|
4539
3629
|
onKeyDown: handleGridKeyDown,
|
|
4540
3630
|
children: [
|
|
4541
|
-
/* @__PURE__ */
|
|
4542
|
-
columns.map((column) => /* @__PURE__ */
|
|
3631
|
+
/* @__PURE__ */ jsx10("thead", { children: /* @__PURE__ */ jsxs8("tr", { role: "row", className: "border-b border-border text-xs uppercase tracking-[0.05em] text-muted-foreground", children: [
|
|
3632
|
+
columns.map((column) => /* @__PURE__ */ jsx10(
|
|
4543
3633
|
"th",
|
|
4544
3634
|
{
|
|
4545
3635
|
role: "columnheader",
|
|
@@ -4549,17 +3639,17 @@ function RecordGrid({
|
|
|
4549
3639
|
},
|
|
4550
3640
|
column.id
|
|
4551
3641
|
)),
|
|
4552
|
-
showActionsColumn && /* @__PURE__ */
|
|
3642
|
+
showActionsColumn && /* @__PURE__ */ jsx10("th", { role: "columnheader", scope: "col", className: "w-px px-3 py-2 font-medium", children: /* @__PURE__ */ jsx10("span", { className: "sr-only", children: reviewing ? "Review" : "Row actions" }) })
|
|
4553
3643
|
] }) }),
|
|
4554
|
-
/* @__PURE__ */
|
|
3644
|
+
/* @__PURE__ */ jsxs8("tbody", { children: [
|
|
4555
3645
|
visibleRows.map((row) => {
|
|
4556
3646
|
const rowLabel = recordGridRowLabel(columns, row);
|
|
4557
3647
|
const pending = row.id in pendingRows;
|
|
4558
3648
|
const rowError = rowErrors[row.id];
|
|
4559
3649
|
const rowDiff = reviewing ? diffByRow.get(row.id) : void 0;
|
|
4560
3650
|
const removedRow = rowDiff?.kind === "removed";
|
|
4561
|
-
return /* @__PURE__ */
|
|
4562
|
-
/* @__PURE__ */
|
|
3651
|
+
return /* @__PURE__ */ jsxs8(Fragment4, { children: [
|
|
3652
|
+
/* @__PURE__ */ jsxs8(
|
|
4563
3653
|
"tr",
|
|
4564
3654
|
{
|
|
4565
3655
|
role: "row",
|
|
@@ -4579,8 +3669,8 @@ function RecordGrid({
|
|
|
4579
3669
|
const errorId = `${fieldPrefix}-cell-error-${row.id}-${column.id}`;
|
|
4580
3670
|
const cellDiff = rowDiff?.kind === "changed" ? diffCellByKey.get(key) : void 0;
|
|
4581
3671
|
if (isEditing && editable) {
|
|
4582
|
-
return /* @__PURE__ */
|
|
4583
|
-
/* @__PURE__ */
|
|
3672
|
+
return /* @__PURE__ */ jsxs8("td", { role: "gridcell", className: `px-3 py-1.5 ${alignmentClass(column)}`, children: [
|
|
3673
|
+
/* @__PURE__ */ jsx10(
|
|
4584
3674
|
CellEditor,
|
|
4585
3675
|
{
|
|
4586
3676
|
column,
|
|
@@ -4593,11 +3683,11 @@ function RecordGrid({
|
|
|
4593
3683
|
onCancel: () => cancelEdit(row, column)
|
|
4594
3684
|
}
|
|
4595
3685
|
),
|
|
4596
|
-
cellError !== void 0 && /* @__PURE__ */
|
|
3686
|
+
cellError !== void 0 && /* @__PURE__ */ jsx10("p", { id: errorId, role: "alert", className: "mt-1 text-xs leading-snug text-destructive", children: cellError })
|
|
4597
3687
|
] }, column.id);
|
|
4598
3688
|
}
|
|
4599
3689
|
if (column.kind === "boolean" && editable) {
|
|
4600
|
-
return /* @__PURE__ */
|
|
3690
|
+
return /* @__PURE__ */ jsx10("td", { role: "gridcell", className: `px-3 py-2 ${alignmentClass(column)}`, children: /* @__PURE__ */ jsx10(
|
|
4601
3691
|
"input",
|
|
4602
3692
|
{
|
|
4603
3693
|
type: "checkbox",
|
|
@@ -4616,7 +3706,7 @@ function RecordGrid({
|
|
|
4616
3706
|
) }, column.id);
|
|
4617
3707
|
}
|
|
4618
3708
|
const display = applicable ? formatRecordGridValue(column, value, locale) : "";
|
|
4619
|
-
return /* @__PURE__ */
|
|
3709
|
+
return /* @__PURE__ */ jsx10(
|
|
4620
3710
|
"td",
|
|
4621
3711
|
{
|
|
4622
3712
|
role: "gridcell",
|
|
@@ -4634,20 +3724,20 @@ function RecordGrid({
|
|
|
4634
3724
|
className: `px-3 py-2 outline-none focus:ring-2 focus:ring-inset focus:ring-primary/50 ${alignmentClass(
|
|
4635
3725
|
column
|
|
4636
3726
|
)} ${editable ? "cursor-text" : ""}`,
|
|
4637
|
-
children: /* @__PURE__ */
|
|
4638
|
-
column.id === columns[0]?.id && removedRow && /* @__PURE__ */
|
|
4639
|
-
cellDiff ? /* @__PURE__ */
|
|
4640
|
-
/* @__PURE__ */
|
|
4641
|
-
/* @__PURE__ */
|
|
4642
|
-
/* @__PURE__ */
|
|
4643
|
-
] }) : /* @__PURE__ */
|
|
3727
|
+
children: /* @__PURE__ */ jsxs8("span", { className: "inline-flex max-w-full items-center gap-1.5", children: [
|
|
3728
|
+
column.id === columns[0]?.id && removedRow && /* @__PURE__ */ jsx10("span", { className: "inline-flex shrink-0 rounded border border-destructive/60 px-1 py-px text-[11px] font-semibold uppercase tracking-[0.05em] text-destructive", children: "Remove" }),
|
|
3729
|
+
cellDiff ? /* @__PURE__ */ jsxs8("span", { className: "inline-flex max-w-full flex-wrap items-baseline gap-x-1.5", children: [
|
|
3730
|
+
/* @__PURE__ */ jsx10("span", { className: "tabular-nums text-destructive line-through decoration-destructive/60", children: formatRecordGridValue(column, cellDiff.before, locale) || "\u2014" }),
|
|
3731
|
+
/* @__PURE__ */ jsx10("span", { "aria-hidden": "true", className: "text-muted-foreground", children: "\u2192" }),
|
|
3732
|
+
/* @__PURE__ */ jsx10("span", { className: "tabular-nums font-medium text-success", children: formatRecordGridValue(column, cellDiff.after, locale) || "\u2014" })
|
|
3733
|
+
] }) : /* @__PURE__ */ jsx10(
|
|
4644
3734
|
"span",
|
|
4645
3735
|
{
|
|
4646
3736
|
className: removedRow ? "truncate text-destructive line-through decoration-destructive/60" : display === "" ? "text-muted-foreground" : "truncate text-foreground",
|
|
4647
3737
|
children: display === "" ? applicable ? "\u2014" : "n/a" : display
|
|
4648
3738
|
}
|
|
4649
3739
|
),
|
|
4650
|
-
source && /* @__PURE__ */
|
|
3740
|
+
source && /* @__PURE__ */ jsx10(
|
|
4651
3741
|
SourceMarker,
|
|
4652
3742
|
{
|
|
4653
3743
|
panelId: `${fieldPrefix}-source-${row.id}-${column.id}`,
|
|
@@ -4663,7 +3753,7 @@ function RecordGrid({
|
|
|
4663
3753
|
column.id
|
|
4664
3754
|
);
|
|
4665
3755
|
}),
|
|
4666
|
-
showActionsColumn && /* @__PURE__ */
|
|
3756
|
+
showActionsColumn && /* @__PURE__ */ jsx10("td", { role: "gridcell", className: "px-3 py-2 text-right", children: reviewing ? rowDiff && /* @__PURE__ */ jsx10(
|
|
4667
3757
|
ReviewActions,
|
|
4668
3758
|
{
|
|
4669
3759
|
rowId: row.id,
|
|
@@ -4672,8 +3762,8 @@ function RecordGrid({
|
|
|
4672
3762
|
onAccept: onAcceptRow,
|
|
4673
3763
|
onReject: onRejectRow
|
|
4674
3764
|
}
|
|
4675
|
-
) : row.readOnly === true ? null : confirmDelete === row.id ? /* @__PURE__ */
|
|
4676
|
-
/* @__PURE__ */
|
|
3765
|
+
) : row.readOnly === true ? null : confirmDelete === row.id ? /* @__PURE__ */ jsxs8("span", { className: "inline-flex items-center gap-1.5", children: [
|
|
3766
|
+
/* @__PURE__ */ jsx10(
|
|
4677
3767
|
"button",
|
|
4678
3768
|
{
|
|
4679
3769
|
type: "button",
|
|
@@ -4683,7 +3773,7 @@ function RecordGrid({
|
|
|
4683
3773
|
children: "Delete"
|
|
4684
3774
|
}
|
|
4685
3775
|
),
|
|
4686
|
-
/* @__PURE__ */
|
|
3776
|
+
/* @__PURE__ */ jsx10(
|
|
4687
3777
|
"button",
|
|
4688
3778
|
{
|
|
4689
3779
|
type: "button",
|
|
@@ -4693,14 +3783,14 @@ function RecordGrid({
|
|
|
4693
3783
|
children: "Cancel"
|
|
4694
3784
|
}
|
|
4695
3785
|
)
|
|
4696
|
-
] }) : /* @__PURE__ */
|
|
3786
|
+
] }) : /* @__PURE__ */ jsx10(
|
|
4697
3787
|
"button",
|
|
4698
3788
|
{
|
|
4699
3789
|
type: "button",
|
|
4700
3790
|
"aria-label": `Delete ${rowLabel}`,
|
|
4701
3791
|
onClick: () => setConfirmDelete(row.id),
|
|
4702
3792
|
className: "rounded-md p-1.5 text-muted-foreground transition hover:bg-destructive/10 hover:text-destructive",
|
|
4703
|
-
children: /* @__PURE__ */
|
|
3793
|
+
children: /* @__PURE__ */ jsxs8(
|
|
4704
3794
|
"svg",
|
|
4705
3795
|
{
|
|
4706
3796
|
viewBox: "0 0 24 24",
|
|
@@ -4712,8 +3802,8 @@ function RecordGrid({
|
|
|
4712
3802
|
strokeLinejoin: "round",
|
|
4713
3803
|
"aria-hidden": true,
|
|
4714
3804
|
children: [
|
|
4715
|
-
/* @__PURE__ */
|
|
4716
|
-
/* @__PURE__ */
|
|
3805
|
+
/* @__PURE__ */ jsx10("polyline", { points: "3 6 5 6 21 6" }),
|
|
3806
|
+
/* @__PURE__ */ jsx10("path", { d: "M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" })
|
|
4717
3807
|
]
|
|
4718
3808
|
}
|
|
4719
3809
|
)
|
|
@@ -4722,12 +3812,12 @@ function RecordGrid({
|
|
|
4722
3812
|
]
|
|
4723
3813
|
}
|
|
4724
3814
|
),
|
|
4725
|
-
rowError !== void 0 && /* @__PURE__ */
|
|
3815
|
+
rowError !== void 0 && /* @__PURE__ */ jsx10("tr", { role: "row", className: "border-b border-border", children: /* @__PURE__ */ jsx10("td", { role: "gridcell", colSpan: columnSpan, className: "px-3 pb-2", children: /* @__PURE__ */ jsx10("p", { role: "alert", className: "rounded-md bg-destructive/10 px-2.5 py-1.5 text-xs text-destructive", children: rowError }) }) })
|
|
4726
3816
|
] }, row.id);
|
|
4727
3817
|
}),
|
|
4728
3818
|
reviewing && addedRows.map((row) => {
|
|
4729
3819
|
const rowLabel = recordGridRowLabel(columns, row);
|
|
4730
|
-
return /* @__PURE__ */
|
|
3820
|
+
return /* @__PURE__ */ jsxs8(
|
|
4731
3821
|
"tr",
|
|
4732
3822
|
{
|
|
4733
3823
|
role: "row",
|
|
@@ -4738,9 +3828,9 @@ function RecordGrid({
|
|
|
4738
3828
|
const applicable = isRecordGridCellApplicable(column, row.values);
|
|
4739
3829
|
const value = row.values[column.id] ?? null;
|
|
4740
3830
|
const display = applicable ? formatRecordGridValue(column, value, locale) : "";
|
|
4741
|
-
return /* @__PURE__ */
|
|
4742
|
-
columnIndex === 0 && /* @__PURE__ */
|
|
4743
|
-
/* @__PURE__ */
|
|
3831
|
+
return /* @__PURE__ */ jsx10("td", { role: "gridcell", className: `px-3 py-2 ${alignmentClass(column)}`, children: /* @__PURE__ */ jsxs8("span", { className: "inline-flex max-w-full items-center gap-1.5", children: [
|
|
3832
|
+
columnIndex === 0 && /* @__PURE__ */ jsx10("span", { className: "inline-flex shrink-0 rounded border border-success/60 px-1 py-px text-[11px] font-semibold uppercase tracking-[0.05em] text-success", children: "New" }),
|
|
3833
|
+
/* @__PURE__ */ jsx10(
|
|
4744
3834
|
"span",
|
|
4745
3835
|
{
|
|
4746
3836
|
className: `tabular-nums ${display === "" ? "text-muted-foreground" : "truncate text-foreground"}`,
|
|
@@ -4749,7 +3839,7 @@ function RecordGrid({
|
|
|
4749
3839
|
)
|
|
4750
3840
|
] }) }, column.id);
|
|
4751
3841
|
}),
|
|
4752
|
-
/* @__PURE__ */
|
|
3842
|
+
/* @__PURE__ */ jsx10("td", { role: "gridcell", className: "px-3 py-2 text-right", children: /* @__PURE__ */ jsx10(
|
|
4753
3843
|
ReviewActions,
|
|
4754
3844
|
{
|
|
4755
3845
|
rowId: row.id,
|
|
@@ -4765,8 +3855,8 @@ function RecordGrid({
|
|
|
4765
3855
|
);
|
|
4766
3856
|
})
|
|
4767
3857
|
] }),
|
|
4768
|
-
hasFooter && /* @__PURE__ */
|
|
4769
|
-
columns.map((column) => /* @__PURE__ */
|
|
3858
|
+
hasFooter && /* @__PURE__ */ jsx10("tfoot", { children: /* @__PURE__ */ jsxs8("tr", { role: "row", className: "border-t-2 border-border", children: [
|
|
3859
|
+
columns.map((column) => /* @__PURE__ */ jsx10(
|
|
4770
3860
|
"td",
|
|
4771
3861
|
{
|
|
4772
3862
|
role: "gridcell",
|
|
@@ -4775,19 +3865,19 @@ function RecordGrid({
|
|
|
4775
3865
|
},
|
|
4776
3866
|
column.id
|
|
4777
3867
|
)),
|
|
4778
|
-
showActionsColumn && /* @__PURE__ */
|
|
3868
|
+
showActionsColumn && /* @__PURE__ */ jsx10("td", { role: "gridcell" })
|
|
4779
3869
|
] }) })
|
|
4780
3870
|
]
|
|
4781
3871
|
}
|
|
4782
3872
|
) }),
|
|
4783
|
-
onCreate && !reviewing && (addForm ?? /* @__PURE__ */
|
|
3873
|
+
onCreate && !reviewing && (addForm ?? /* @__PURE__ */ jsxs8(
|
|
4784
3874
|
"button",
|
|
4785
3875
|
{
|
|
4786
3876
|
type: "button",
|
|
4787
3877
|
onClick: openAdd,
|
|
4788
3878
|
className: "inline-flex items-center gap-1.5 rounded-md border border-border px-3 py-1.5 text-sm font-medium text-foreground transition hover:bg-accent",
|
|
4789
3879
|
children: [
|
|
4790
|
-
/* @__PURE__ */
|
|
3880
|
+
/* @__PURE__ */ jsxs8(
|
|
4791
3881
|
"svg",
|
|
4792
3882
|
{
|
|
4793
3883
|
viewBox: "0 0 24 24",
|
|
@@ -4799,8 +3889,8 @@ function RecordGrid({
|
|
|
4799
3889
|
strokeLinejoin: "round",
|
|
4800
3890
|
"aria-hidden": true,
|
|
4801
3891
|
children: [
|
|
4802
|
-
/* @__PURE__ */
|
|
4803
|
-
/* @__PURE__ */
|
|
3892
|
+
/* @__PURE__ */ jsx10("line", { x1: "12", y1: "5", x2: "12", y2: "19" }),
|
|
3893
|
+
/* @__PURE__ */ jsx10("line", { x1: "5", y1: "12", x2: "19", y2: "12" })
|
|
4804
3894
|
]
|
|
4805
3895
|
}
|
|
4806
3896
|
),
|
|
@@ -4812,8 +3902,8 @@ function RecordGrid({
|
|
|
4812
3902
|
}
|
|
4813
3903
|
function ReviewActions({ rowId, kind, rowLabel, onAccept, onReject }) {
|
|
4814
3904
|
const noun = kind === "changed" ? `proposed change to ${rowLabel}` : kind === "added" ? `new row ${rowLabel}` : `removal of ${rowLabel}`;
|
|
4815
|
-
return /* @__PURE__ */
|
|
4816
|
-
onReject && /* @__PURE__ */
|
|
3905
|
+
return /* @__PURE__ */ jsxs8("span", { className: "inline-flex items-center gap-1.5", children: [
|
|
3906
|
+
onReject && /* @__PURE__ */ jsx10(
|
|
4817
3907
|
"button",
|
|
4818
3908
|
{
|
|
4819
3909
|
type: "button",
|
|
@@ -4823,7 +3913,7 @@ function ReviewActions({ rowId, kind, rowLabel, onAccept, onReject }) {
|
|
|
4823
3913
|
children: "Reject"
|
|
4824
3914
|
}
|
|
4825
3915
|
),
|
|
4826
|
-
onAccept && /* @__PURE__ */
|
|
3916
|
+
onAccept && /* @__PURE__ */ jsx10(
|
|
4827
3917
|
"button",
|
|
4828
3918
|
{
|
|
4829
3919
|
type: "button",
|
|
@@ -4844,7 +3934,7 @@ function CellEditor({ column, rowLabel, text, invalid, describedBy, onText, onCo
|
|
|
4844
3934
|
className: INPUT_CLASS
|
|
4845
3935
|
};
|
|
4846
3936
|
if (column.kind === "select") {
|
|
4847
|
-
return /* @__PURE__ */
|
|
3937
|
+
return /* @__PURE__ */ jsxs8(
|
|
4848
3938
|
"select",
|
|
4849
3939
|
{
|
|
4850
3940
|
...shared,
|
|
@@ -4861,8 +3951,8 @@ function CellEditor({ column, rowLabel, text, invalid, describedBy, onText, onCo
|
|
|
4861
3951
|
},
|
|
4862
3952
|
onBlur: () => onCommit(text),
|
|
4863
3953
|
children: [
|
|
4864
|
-
/* @__PURE__ */
|
|
4865
|
-
column.options.map((option) => /* @__PURE__ */
|
|
3954
|
+
/* @__PURE__ */ jsx10("option", { value: "", children: "\u2014" }),
|
|
3955
|
+
column.options.map((option) => /* @__PURE__ */ jsx10("option", { value: option.value, children: option.label }, option.value))
|
|
4866
3956
|
]
|
|
4867
3957
|
}
|
|
4868
3958
|
);
|
|
@@ -4880,7 +3970,7 @@ function CellEditor({ column, rowLabel, text, invalid, describedBy, onText, onCo
|
|
|
4880
3970
|
}
|
|
4881
3971
|
};
|
|
4882
3972
|
if (column.kind === "text" && column.multiline === true) {
|
|
4883
|
-
return /* @__PURE__ */
|
|
3973
|
+
return /* @__PURE__ */ jsx10(
|
|
4884
3974
|
"textarea",
|
|
4885
3975
|
{
|
|
4886
3976
|
...shared,
|
|
@@ -4892,7 +3982,7 @@ function CellEditor({ column, rowLabel, text, invalid, describedBy, onText, onCo
|
|
|
4892
3982
|
}
|
|
4893
3983
|
);
|
|
4894
3984
|
}
|
|
4895
|
-
return /* @__PURE__ */
|
|
3985
|
+
return /* @__PURE__ */ jsx10(
|
|
4896
3986
|
"input",
|
|
4897
3987
|
{
|
|
4898
3988
|
...shared,
|
|
@@ -4907,15 +3997,15 @@ function CellEditor({ column, rowLabel, text, invalid, describedBy, onText, onCo
|
|
|
4907
3997
|
}
|
|
4908
3998
|
function SourceMarker({ panelId, columnHeader, rowLabel, source, open, onToggle }) {
|
|
4909
3999
|
const basis = source.basis ?? "asserted";
|
|
4910
|
-
const setOpen =
|
|
4000
|
+
const setOpen = useCallback7(
|
|
4911
4001
|
(next) => {
|
|
4912
4002
|
if (!next) onToggle();
|
|
4913
4003
|
},
|
|
4914
4004
|
[onToggle]
|
|
4915
4005
|
);
|
|
4916
4006
|
const { containerRef, triggerRef, panelRef, triggerProps } = usePopover(open, setOpen);
|
|
4917
|
-
return /* @__PURE__ */
|
|
4918
|
-
/* @__PURE__ */
|
|
4007
|
+
return /* @__PURE__ */ jsxs8("span", { ref: containerRef, className: "relative inline-flex", children: [
|
|
4008
|
+
/* @__PURE__ */ jsx10(
|
|
4919
4009
|
"button",
|
|
4920
4010
|
{
|
|
4921
4011
|
type: "button",
|
|
@@ -4928,7 +4018,7 @@ function SourceMarker({ panelId, columnHeader, rowLabel, source, open, onToggle
|
|
|
4928
4018
|
onToggle();
|
|
4929
4019
|
},
|
|
4930
4020
|
className: `inline-flex h-4 w-4 shrink-0 items-center justify-center rounded-full border ${BASIS_TONES2[basis]}`,
|
|
4931
|
-
children: /* @__PURE__ */
|
|
4021
|
+
children: /* @__PURE__ */ jsx10(
|
|
4932
4022
|
"svg",
|
|
4933
4023
|
{
|
|
4934
4024
|
viewBox: "0 0 24 24",
|
|
@@ -4938,12 +4028,12 @@ function SourceMarker({ panelId, columnHeader, rowLabel, source, open, onToggle
|
|
|
4938
4028
|
strokeWidth: "2.5",
|
|
4939
4029
|
strokeLinecap: "round",
|
|
4940
4030
|
"aria-hidden": true,
|
|
4941
|
-
children: /* @__PURE__ */
|
|
4031
|
+
children: /* @__PURE__ */ jsx10("path", { d: "M9 8h6M9 12h6M9 16h3" })
|
|
4942
4032
|
}
|
|
4943
4033
|
)
|
|
4944
4034
|
}
|
|
4945
4035
|
),
|
|
4946
|
-
/* @__PURE__ */
|
|
4036
|
+
/* @__PURE__ */ jsxs8(
|
|
4947
4037
|
PopoverSurface,
|
|
4948
4038
|
{
|
|
4949
4039
|
open,
|
|
@@ -4953,17 +4043,17 @@ function SourceMarker({ panelId, columnHeader, rowLabel, source, open, onToggle
|
|
|
4953
4043
|
panelRef,
|
|
4954
4044
|
className: `w-64 rounded-lg border border-card-edge bg-popover p-3 text-left ${OVERLAY_SHADOW}`,
|
|
4955
4045
|
children: [
|
|
4956
|
-
source.quote && /* @__PURE__ */
|
|
4046
|
+
source.quote && /* @__PURE__ */ jsxs8("span", { className: "block border-l-2 border-primary/50 pl-2 text-xs italic leading-snug text-foreground", children: [
|
|
4957
4047
|
"\u201C",
|
|
4958
4048
|
source.quote,
|
|
4959
4049
|
"\u201D"
|
|
4960
4050
|
] }),
|
|
4961
|
-
/* @__PURE__ */
|
|
4051
|
+
/* @__PURE__ */ jsxs8("span", { className: "mt-2 block text-xs text-muted-foreground", children: [
|
|
4962
4052
|
source.label ?? "Source",
|
|
4963
4053
|
source.locator ? ` \xB7 ${source.locator}` : "",
|
|
4964
4054
|
` \xB7 ${BASIS_TITLES[basis]}`
|
|
4965
4055
|
] }),
|
|
4966
|
-
source.href && /* @__PURE__ */
|
|
4056
|
+
source.href && /* @__PURE__ */ jsx10(
|
|
4967
4057
|
"a",
|
|
4968
4058
|
{
|
|
4969
4059
|
href: source.href,
|
|
@@ -4991,8 +4081,8 @@ function AddRecordForm({
|
|
|
4991
4081
|
onSubmit,
|
|
4992
4082
|
onCancel
|
|
4993
4083
|
}) {
|
|
4994
|
-
const groups =
|
|
4995
|
-
return /* @__PURE__ */
|
|
4084
|
+
const groups = useMemo5(() => groupColumns(columns), [columns]);
|
|
4085
|
+
return /* @__PURE__ */ jsxs8(
|
|
4996
4086
|
"form",
|
|
4997
4087
|
{
|
|
4998
4088
|
noValidate: true,
|
|
@@ -5003,31 +4093,31 @@ function AddRecordForm({
|
|
|
5003
4093
|
},
|
|
5004
4094
|
className: "space-y-4 rounded-xl border border-card-edge bg-card p-4",
|
|
5005
4095
|
children: [
|
|
5006
|
-
/* @__PURE__ */
|
|
5007
|
-
formError !== null && /* @__PURE__ */
|
|
4096
|
+
/* @__PURE__ */ jsx10("h3", { className: "text-sm font-semibold text-foreground", children: label }),
|
|
4097
|
+
formError !== null && /* @__PURE__ */ jsx10("p", { role: "alert", className: "rounded-md bg-destructive/10 px-3 py-2 text-xs text-destructive", children: formError }),
|
|
5008
4098
|
groups.map((group) => {
|
|
5009
4099
|
const fields = group.columns.filter((column) => isRecordGridCellApplicable(column, draft));
|
|
5010
4100
|
if (fields.length === 0) return null;
|
|
5011
|
-
return /* @__PURE__ */
|
|
4101
|
+
return /* @__PURE__ */ jsxs8(
|
|
5012
4102
|
"fieldset",
|
|
5013
4103
|
{
|
|
5014
4104
|
className: group.label === null ? "min-w-0" : "min-w-0 rounded-lg border border-card-edge p-3",
|
|
5015
4105
|
children: [
|
|
5016
|
-
group.label !== null && /* @__PURE__ */
|
|
5017
|
-
/* @__PURE__ */
|
|
4106
|
+
group.label !== null && /* @__PURE__ */ jsx10("legend", { className: "px-1 text-xs font-medium text-muted-foreground", children: group.label }),
|
|
4107
|
+
/* @__PURE__ */ jsx10("div", { className: "grid gap-3 sm:grid-cols-2", children: fields.map((column) => {
|
|
5018
4108
|
const fieldId = `${fieldPrefix}-${column.id}`;
|
|
5019
4109
|
const errorId = `${fieldId}-error`;
|
|
5020
4110
|
const message = errors[column.id];
|
|
5021
|
-
return /* @__PURE__ */
|
|
4111
|
+
return /* @__PURE__ */ jsxs8(
|
|
5022
4112
|
"div",
|
|
5023
4113
|
{
|
|
5024
4114
|
className: column.kind === "text" && column.multiline === true ? "sm:col-span-2" : "",
|
|
5025
4115
|
children: [
|
|
5026
|
-
/* @__PURE__ */
|
|
4116
|
+
/* @__PURE__ */ jsxs8("label", { htmlFor: fieldId, className: "mb-1 block text-xs font-medium text-muted-foreground", children: [
|
|
5027
4117
|
column.header,
|
|
5028
|
-
column.required === true && /* @__PURE__ */
|
|
4118
|
+
column.required === true && /* @__PURE__ */ jsx10("span", { className: "ml-0.5 text-destructive", children: "*" })
|
|
5029
4119
|
] }),
|
|
5030
|
-
/* @__PURE__ */
|
|
4120
|
+
/* @__PURE__ */ jsx10(
|
|
5031
4121
|
DraftField,
|
|
5032
4122
|
{
|
|
5033
4123
|
column,
|
|
@@ -5038,8 +4128,8 @@ function AddRecordForm({
|
|
|
5038
4128
|
onValue: (next) => setDraft({ ...draft, [column.id]: next })
|
|
5039
4129
|
}
|
|
5040
4130
|
),
|
|
5041
|
-
column.hint && /* @__PURE__ */
|
|
5042
|
-
message !== void 0 && /* @__PURE__ */
|
|
4131
|
+
column.hint && /* @__PURE__ */ jsx10("p", { className: "mt-1 text-xs text-muted-foreground", children: column.hint }),
|
|
4132
|
+
message !== void 0 && /* @__PURE__ */ jsx10("p", { id: errorId, role: "alert", className: "mt-1 text-xs text-destructive", children: message })
|
|
5043
4133
|
]
|
|
5044
4134
|
},
|
|
5045
4135
|
column.id
|
|
@@ -5050,8 +4140,8 @@ function AddRecordForm({
|
|
|
5050
4140
|
group.label ?? "_"
|
|
5051
4141
|
);
|
|
5052
4142
|
}),
|
|
5053
|
-
/* @__PURE__ */
|
|
5054
|
-
/* @__PURE__ */
|
|
4143
|
+
/* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-2", children: [
|
|
4144
|
+
/* @__PURE__ */ jsx10(
|
|
5055
4145
|
"button",
|
|
5056
4146
|
{
|
|
5057
4147
|
type: "submit",
|
|
@@ -5060,7 +4150,7 @@ function AddRecordForm({
|
|
|
5060
4150
|
children: busy ? "Saving\u2026" : "Save"
|
|
5061
4151
|
}
|
|
5062
4152
|
),
|
|
5063
|
-
/* @__PURE__ */
|
|
4153
|
+
/* @__PURE__ */ jsx10(
|
|
5064
4154
|
"button",
|
|
5065
4155
|
{
|
|
5066
4156
|
type: "button",
|
|
@@ -5081,7 +4171,7 @@ function DraftField({ column, id, value, invalid, describedBy, onValue }) {
|
|
|
5081
4171
|
"aria-describedby": describedBy
|
|
5082
4172
|
};
|
|
5083
4173
|
if (column.kind === "boolean") {
|
|
5084
|
-
return /* @__PURE__ */
|
|
4174
|
+
return /* @__PURE__ */ jsx10(
|
|
5085
4175
|
"input",
|
|
5086
4176
|
{
|
|
5087
4177
|
...shared,
|
|
@@ -5093,7 +4183,7 @@ function DraftField({ column, id, value, invalid, describedBy, onValue }) {
|
|
|
5093
4183
|
);
|
|
5094
4184
|
}
|
|
5095
4185
|
if (column.kind === "select") {
|
|
5096
|
-
return /* @__PURE__ */
|
|
4186
|
+
return /* @__PURE__ */ jsxs8(
|
|
5097
4187
|
"select",
|
|
5098
4188
|
{
|
|
5099
4189
|
...shared,
|
|
@@ -5101,14 +4191,14 @@ function DraftField({ column, id, value, invalid, describedBy, onValue }) {
|
|
|
5101
4191
|
value: typeof value === "string" ? value : "",
|
|
5102
4192
|
onChange: (event) => onValue(event.target.value === "" ? null : event.target.value),
|
|
5103
4193
|
children: [
|
|
5104
|
-
/* @__PURE__ */
|
|
5105
|
-
column.options.map((option) => /* @__PURE__ */
|
|
4194
|
+
/* @__PURE__ */ jsx10("option", { value: "", children: "\u2014" }),
|
|
4195
|
+
column.options.map((option) => /* @__PURE__ */ jsx10("option", { value: option.value, children: option.label }, option.value))
|
|
5106
4196
|
]
|
|
5107
4197
|
}
|
|
5108
4198
|
);
|
|
5109
4199
|
}
|
|
5110
4200
|
if (column.kind === "text" && column.multiline === true) {
|
|
5111
|
-
return /* @__PURE__ */
|
|
4201
|
+
return /* @__PURE__ */ jsx10(
|
|
5112
4202
|
"textarea",
|
|
5113
4203
|
{
|
|
5114
4204
|
...shared,
|
|
@@ -5120,7 +4210,7 @@ function DraftField({ column, id, value, invalid, describedBy, onValue }) {
|
|
|
5120
4210
|
);
|
|
5121
4211
|
}
|
|
5122
4212
|
if (column.kind === "number" || column.kind === "currency") {
|
|
5123
|
-
return /* @__PURE__ */
|
|
4213
|
+
return /* @__PURE__ */ jsx10(
|
|
5124
4214
|
"input",
|
|
5125
4215
|
{
|
|
5126
4216
|
...shared,
|
|
@@ -5140,7 +4230,7 @@ function DraftField({ column, id, value, invalid, describedBy, onValue }) {
|
|
|
5140
4230
|
}
|
|
5141
4231
|
);
|
|
5142
4232
|
}
|
|
5143
|
-
return /* @__PURE__ */
|
|
4233
|
+
return /* @__PURE__ */ jsx10(
|
|
5144
4234
|
"input",
|
|
5145
4235
|
{
|
|
5146
4236
|
...shared,
|
|
@@ -5154,19 +4244,19 @@ function DraftField({ column, id, value, invalid, describedBy, onValue }) {
|
|
|
5154
4244
|
|
|
5155
4245
|
// src/web-react/command-palette.tsx
|
|
5156
4246
|
import {
|
|
5157
|
-
useCallback as
|
|
5158
|
-
useEffect as
|
|
5159
|
-
useId as
|
|
5160
|
-
useMemo as
|
|
5161
|
-
useRef as
|
|
5162
|
-
useState as
|
|
4247
|
+
useCallback as useCallback8,
|
|
4248
|
+
useEffect as useEffect9,
|
|
4249
|
+
useId as useId3,
|
|
4250
|
+
useMemo as useMemo6,
|
|
4251
|
+
useRef as useRef9,
|
|
4252
|
+
useState as useState13
|
|
5163
4253
|
} from "react";
|
|
5164
4254
|
import { createPortal } from "react-dom";
|
|
5165
|
-
import { Fragment as
|
|
4255
|
+
import { Fragment as Fragment5, jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
5166
4256
|
function SearchGlyph({ className }) {
|
|
5167
|
-
return /* @__PURE__ */
|
|
5168
|
-
/* @__PURE__ */
|
|
5169
|
-
/* @__PURE__ */
|
|
4257
|
+
return /* @__PURE__ */ jsxs9("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: [
|
|
4258
|
+
/* @__PURE__ */ jsx11("circle", { cx: "11", cy: "11", r: "8" }),
|
|
4259
|
+
/* @__PURE__ */ jsx11("path", { d: "m21 21-4.3-4.3" })
|
|
5170
4260
|
] });
|
|
5171
4261
|
}
|
|
5172
4262
|
function CommandPalette({
|
|
@@ -5181,25 +4271,25 @@ function CommandPalette({
|
|
|
5181
4271
|
emptyMessage,
|
|
5182
4272
|
label = "Command palette"
|
|
5183
4273
|
}) {
|
|
5184
|
-
const [internalOpen, setInternalOpen] =
|
|
4274
|
+
const [internalOpen, setInternalOpen] = useState13(false);
|
|
5185
4275
|
const open = controlledOpen ?? internalOpen;
|
|
5186
|
-
const setOpen =
|
|
4276
|
+
const setOpen = useCallback8(
|
|
5187
4277
|
(next) => {
|
|
5188
4278
|
if (controlledOpen === void 0) setInternalOpen(next);
|
|
5189
4279
|
onOpenChange?.(next);
|
|
5190
4280
|
},
|
|
5191
4281
|
[controlledOpen, onOpenChange]
|
|
5192
4282
|
);
|
|
5193
|
-
const [query, setQuery] =
|
|
5194
|
-
const [active, setActive] =
|
|
5195
|
-
const inputRef =
|
|
5196
|
-
const surfaceId =
|
|
4283
|
+
const [query, setQuery] = useState13(initialQuery ?? "");
|
|
4284
|
+
const [active, setActive] = useState13(0);
|
|
4285
|
+
const inputRef = useRef9(null);
|
|
4286
|
+
const surfaceId = useId3();
|
|
5197
4287
|
const listId = `${surfaceId}-list`;
|
|
5198
|
-
const flat =
|
|
5199
|
-
const sections =
|
|
4288
|
+
const flat = useMemo6(() => filterCommandPaletteItems(items, query), [items, query]);
|
|
4289
|
+
const sections = useMemo6(() => groupCommandPaletteItems(flat), [flat]);
|
|
5200
4290
|
const activeIndex = flat.length === 0 ? 0 : Math.min(active, flat.length - 1);
|
|
5201
4291
|
const activeId = flat.length > 0 ? `${listId}-${activeIndex}` : void 0;
|
|
5202
|
-
|
|
4292
|
+
useEffect9(() => {
|
|
5203
4293
|
if (!hotkey) return;
|
|
5204
4294
|
function onKeyDown(e) {
|
|
5205
4295
|
if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === "k") {
|
|
@@ -5210,8 +4300,8 @@ function CommandPalette({
|
|
|
5210
4300
|
document.addEventListener("keydown", onKeyDown);
|
|
5211
4301
|
return () => document.removeEventListener("keydown", onKeyDown);
|
|
5212
4302
|
}, [hotkey, open, setOpen]);
|
|
5213
|
-
const restoreFocusRef =
|
|
5214
|
-
|
|
4303
|
+
const restoreFocusRef = useRef9(null);
|
|
4304
|
+
useEffect9(() => {
|
|
5215
4305
|
if (open) {
|
|
5216
4306
|
restoreFocusRef.current = document.activeElement;
|
|
5217
4307
|
inputRef.current?.focus();
|
|
@@ -5223,11 +4313,11 @@ function CommandPalette({
|
|
|
5223
4313
|
restoreFocusRef.current = null;
|
|
5224
4314
|
if (restore instanceof HTMLElement) restore.focus();
|
|
5225
4315
|
}, [open]);
|
|
5226
|
-
|
|
4316
|
+
useEffect9(() => {
|
|
5227
4317
|
if (!open || !activeId) return;
|
|
5228
4318
|
document.getElementById(activeId)?.scrollIntoView?.({ block: "nearest" });
|
|
5229
4319
|
}, [open, activeId]);
|
|
5230
|
-
const choose =
|
|
4320
|
+
const choose = useCallback8(
|
|
5231
4321
|
(item) => {
|
|
5232
4322
|
onSelect(item);
|
|
5233
4323
|
setOpen(false);
|
|
@@ -5253,8 +4343,8 @@ function CommandPalette({
|
|
|
5253
4343
|
if (!open || typeof document === "undefined") return null;
|
|
5254
4344
|
let rowIndex = -1;
|
|
5255
4345
|
return createPortal(
|
|
5256
|
-
/* @__PURE__ */
|
|
5257
|
-
/* @__PURE__ */
|
|
4346
|
+
/* @__PURE__ */ jsxs9(Fragment5, { children: [
|
|
4347
|
+
/* @__PURE__ */ jsx11(
|
|
5258
4348
|
"div",
|
|
5259
4349
|
{
|
|
5260
4350
|
"aria-hidden": true,
|
|
@@ -5263,7 +4353,7 @@ function CommandPalette({
|
|
|
5263
4353
|
className: "fixed inset-0 z-[999] bg-background/80"
|
|
5264
4354
|
}
|
|
5265
4355
|
),
|
|
5266
|
-
/* @__PURE__ */
|
|
4356
|
+
/* @__PURE__ */ jsx11("div", { className: "pointer-events-none fixed inset-x-0 top-[15%] z-[1000] flex justify-center px-4", children: /* @__PURE__ */ jsxs9(
|
|
5267
4357
|
"div",
|
|
5268
4358
|
{
|
|
5269
4359
|
role: "dialog",
|
|
@@ -5272,9 +4362,9 @@ function CommandPalette({
|
|
|
5272
4362
|
...{ [POPOVER_SURFACE_ATTR]: surfaceId },
|
|
5273
4363
|
className: `agent-pop-in pointer-events-auto flex max-h-[70vh] w-[560px] max-w-full flex-col overflow-hidden rounded-xl border border-card-edge bg-popover ${OVERLAY_SHADOW}`,
|
|
5274
4364
|
children: [
|
|
5275
|
-
/* @__PURE__ */
|
|
5276
|
-
/* @__PURE__ */
|
|
5277
|
-
/* @__PURE__ */
|
|
4365
|
+
/* @__PURE__ */ jsxs9("div", { className: "flex shrink-0 items-center gap-2 border-b border-border px-3 py-2.5", children: [
|
|
4366
|
+
/* @__PURE__ */ jsx11(SearchGlyph, { className: "h-4 w-4 shrink-0 text-muted-foreground" }),
|
|
4367
|
+
/* @__PURE__ */ jsx11(
|
|
5278
4368
|
"input",
|
|
5279
4369
|
{
|
|
5280
4370
|
ref: inputRef,
|
|
@@ -5295,15 +4385,15 @@ function CommandPalette({
|
|
|
5295
4385
|
}
|
|
5296
4386
|
)
|
|
5297
4387
|
] }),
|
|
5298
|
-
/* @__PURE__ */
|
|
5299
|
-
loading && /* @__PURE__ */
|
|
5300
|
-
!loading && flat.length === 0 && /* @__PURE__ */
|
|
5301
|
-
!loading && sections.map((section) => /* @__PURE__ */
|
|
5302
|
-
/* @__PURE__ */
|
|
4388
|
+
/* @__PURE__ */ jsxs9("div", { role: "listbox", id: listId, className: "min-h-0 flex-1 overflow-y-auto p-1 pb-2", children: [
|
|
4389
|
+
loading && /* @__PURE__ */ jsx11("div", { className: "px-3 py-4 text-center text-sm text-muted-foreground", children: "Loading\u2026" }),
|
|
4390
|
+
!loading && flat.length === 0 && /* @__PURE__ */ jsx11("div", { className: "px-3 py-4 text-center text-sm text-muted-foreground", children: emptyMessage ?? (query.trim() ? `No results for \u201C${query.trim()}\u201D` : "Nothing here yet") }),
|
|
4391
|
+
!loading && sections.map((section) => /* @__PURE__ */ jsxs9("div", { children: [
|
|
4392
|
+
/* @__PURE__ */ jsx11("div", { className: "px-3 pb-1 pt-3 text-xs font-semibold uppercase tracking-wide text-muted-foreground", children: section.group }),
|
|
5303
4393
|
section.items.map((item) => {
|
|
5304
4394
|
rowIndex += 1;
|
|
5305
4395
|
const index = rowIndex;
|
|
5306
|
-
return /* @__PURE__ */
|
|
4396
|
+
return /* @__PURE__ */ jsxs9(
|
|
5307
4397
|
"div",
|
|
5308
4398
|
{
|
|
5309
4399
|
id: `${listId}-${index}`,
|
|
@@ -5313,9 +4403,9 @@ function CommandPalette({
|
|
|
5313
4403
|
onClick: () => choose(item),
|
|
5314
4404
|
className: `flex w-full cursor-pointer items-center gap-2.5 rounded-md px-3 py-2.5 text-left text-sm ${index === activeIndex ? "bg-accent" : ""}`,
|
|
5315
4405
|
children: [
|
|
5316
|
-
/* @__PURE__ */
|
|
5317
|
-
item.description && /* @__PURE__ */
|
|
5318
|
-
item.hint && /* @__PURE__ */
|
|
4406
|
+
/* @__PURE__ */ jsx11("span", { className: "truncate text-foreground", children: item.label }),
|
|
4407
|
+
item.description && /* @__PURE__ */ jsx11("span", { className: "truncate text-xs text-muted-foreground", children: item.description }),
|
|
4408
|
+
item.hint && /* @__PURE__ */ jsx11("span", { className: "ml-auto shrink-0 text-xs tabular-nums text-muted-foreground", children: item.hint })
|
|
5319
4409
|
]
|
|
5320
4410
|
},
|
|
5321
4411
|
item.id
|
|
@@ -5323,15 +4413,15 @@ function CommandPalette({
|
|
|
5323
4413
|
})
|
|
5324
4414
|
] }, section.group))
|
|
5325
4415
|
] }),
|
|
5326
|
-
/* @__PURE__ */
|
|
5327
|
-
/* @__PURE__ */
|
|
5328
|
-
/* @__PURE__ */
|
|
5329
|
-
/* @__PURE__ */
|
|
5330
|
-
/* @__PURE__ */
|
|
5331
|
-
/* @__PURE__ */
|
|
5332
|
-
/* @__PURE__ */
|
|
5333
|
-
/* @__PURE__ */
|
|
5334
|
-
/* @__PURE__ */
|
|
4416
|
+
/* @__PURE__ */ jsxs9("div", { className: "flex shrink-0 items-center justify-between border-t border-border px-3 py-2 text-xs text-muted-foreground", children: [
|
|
4417
|
+
/* @__PURE__ */ jsx11("span", { className: "tabular-nums", children: query.trim() ? `${flat.length} of ${items.length}` : `${items.length} items` }),
|
|
4418
|
+
/* @__PURE__ */ jsxs9("span", { className: "flex items-center gap-1.5", children: [
|
|
4419
|
+
/* @__PURE__ */ jsx11("kbd", { className: "rounded border border-border bg-background px-1 py-0.5", children: "\u2191\u2193" }),
|
|
4420
|
+
/* @__PURE__ */ jsx11("span", { children: "navigate" }),
|
|
4421
|
+
/* @__PURE__ */ jsx11("kbd", { className: "ml-1.5 rounded border border-border bg-background px-1 py-0.5", children: "\u21B5" }),
|
|
4422
|
+
/* @__PURE__ */ jsx11("span", { children: "select" }),
|
|
4423
|
+
/* @__PURE__ */ jsx11("kbd", { className: "ml-1.5 rounded border border-border bg-background px-1 py-0.5", children: "esc" }),
|
|
4424
|
+
/* @__PURE__ */ jsx11("span", { children: "close" })
|
|
5335
4425
|
] })
|
|
5336
4426
|
] })
|
|
5337
4427
|
]
|
|
@@ -5342,19 +4432,8 @@ function CommandPalette({
|
|
|
5342
4432
|
);
|
|
5343
4433
|
}
|
|
5344
4434
|
|
|
5345
|
-
// src/web-react/class-names.ts
|
|
5346
|
-
function joinClasses(...parts) {
|
|
5347
|
-
const kept = [];
|
|
5348
|
-
for (const part of parts) {
|
|
5349
|
-
if (typeof part !== "string") continue;
|
|
5350
|
-
const trimmed = part.trim();
|
|
5351
|
-
if (trimmed.length > 0) kept.push(trimmed);
|
|
5352
|
-
}
|
|
5353
|
-
return kept.join(" ");
|
|
5354
|
-
}
|
|
5355
|
-
|
|
5356
4435
|
// src/web-react/sparkline.tsx
|
|
5357
|
-
import { jsx as
|
|
4436
|
+
import { jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
5358
4437
|
var DEFAULT_SPARKLINE_WIDTH = 96;
|
|
5359
4438
|
var DEFAULT_SPARKLINE_HEIGHT = 24;
|
|
5360
4439
|
var DEFAULT_INSET = 2.5;
|
|
@@ -5460,21 +4539,21 @@ function Sparkline({
|
|
|
5460
4539
|
const geometry = sparklineGeometry(values, { width, height });
|
|
5461
4540
|
const accessibleName = sparklineLabel(values, { label, format });
|
|
5462
4541
|
if (geometry.points.length === 0) {
|
|
5463
|
-
return /* @__PURE__ */
|
|
4542
|
+
return /* @__PURE__ */ jsxs10(
|
|
5464
4543
|
"span",
|
|
5465
4544
|
{
|
|
5466
4545
|
"data-sparkline": geometry.gaps > 0 ? "unavailable" : "empty",
|
|
5467
4546
|
className: joinClasses("text-[11px] text-muted-foreground", className),
|
|
5468
4547
|
children: [
|
|
5469
|
-
/* @__PURE__ */
|
|
5470
|
-
/* @__PURE__ */
|
|
4548
|
+
/* @__PURE__ */ jsx12("span", { className: "sr-only", children: accessibleName }),
|
|
4549
|
+
/* @__PURE__ */ jsx12("span", { "aria-hidden": "true", children: geometry.gaps > 0 ? unavailableLabel : emptyLabel })
|
|
5471
4550
|
]
|
|
5472
4551
|
}
|
|
5473
4552
|
);
|
|
5474
4553
|
}
|
|
5475
4554
|
const drawsLine = geometry.segments.some((segment) => segment.length > 1);
|
|
5476
4555
|
const end = geometry.points[geometry.points.length - 1];
|
|
5477
|
-
return /* @__PURE__ */
|
|
4556
|
+
return /* @__PURE__ */ jsxs10(
|
|
5478
4557
|
"svg",
|
|
5479
4558
|
{
|
|
5480
4559
|
role: "img",
|
|
@@ -5491,7 +4570,7 @@ function Sparkline({
|
|
|
5491
4570
|
geometry.segments.map((segment, index) => {
|
|
5492
4571
|
const key = `segment-${index}`;
|
|
5493
4572
|
if (segment.length > 1) {
|
|
5494
|
-
return /* @__PURE__ */
|
|
4573
|
+
return /* @__PURE__ */ jsx12(
|
|
5495
4574
|
"polyline",
|
|
5496
4575
|
{
|
|
5497
4576
|
points: sparklinePointsAttribute(segment),
|
|
@@ -5507,9 +4586,9 @@ function Sparkline({
|
|
|
5507
4586
|
}
|
|
5508
4587
|
const only = segment[0];
|
|
5509
4588
|
if (only.x === end.x && only.y === end.y) return null;
|
|
5510
|
-
return /* @__PURE__ */
|
|
4589
|
+
return /* @__PURE__ */ jsx12("circle", { cx: only.x, cy: only.y, r: DOT_RADIUS, fill: "currentColor" }, key);
|
|
5511
4590
|
}),
|
|
5512
|
-
/* @__PURE__ */
|
|
4591
|
+
/* @__PURE__ */ jsx12("circle", { cx: end.x, cy: end.y, r: DOT_RADIUS, fill: "currentColor" })
|
|
5513
4592
|
]
|
|
5514
4593
|
}
|
|
5515
4594
|
);
|
|
@@ -5518,12 +4597,12 @@ function Sparkline({
|
|
|
5518
4597
|
// src/web-react/insight-card.tsx
|
|
5519
4598
|
import {
|
|
5520
4599
|
isValidElement as isValidElement2,
|
|
5521
|
-
useCallback as
|
|
5522
|
-
useEffect as
|
|
5523
|
-
useRef as
|
|
5524
|
-
useState as
|
|
4600
|
+
useCallback as useCallback9,
|
|
4601
|
+
useEffect as useEffect10,
|
|
4602
|
+
useRef as useRef10,
|
|
4603
|
+
useState as useState14
|
|
5525
4604
|
} from "react";
|
|
5526
|
-
import { Fragment as
|
|
4605
|
+
import { Fragment as Fragment6, jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
5527
4606
|
function insightDelta(value, previous) {
|
|
5528
4607
|
if (typeof value !== "number" || !Number.isFinite(value)) return null;
|
|
5529
4608
|
if (typeof previous !== "number" || !Number.isFinite(previous)) return null;
|
|
@@ -5576,7 +4655,7 @@ function InsightCard({
|
|
|
5576
4655
|
const tone = delta ? insightDeltaTone(delta.direction, polarity) : "neutral";
|
|
5577
4656
|
const unavailable = typeof value === "number" && !Number.isFinite(value);
|
|
5578
4657
|
const shown = typeof value === "number" ? format(value) : value;
|
|
5579
|
-
return /* @__PURE__ */
|
|
4658
|
+
return /* @__PURE__ */ jsxs11(
|
|
5580
4659
|
"article",
|
|
5581
4660
|
{
|
|
5582
4661
|
"data-insight-card": "",
|
|
@@ -5584,40 +4663,40 @@ function InsightCard({
|
|
|
5584
4663
|
className: joinClasses("agent-arrive flex h-full flex-col rounded-xl border border-card-edge bg-card p-4", className),
|
|
5585
4664
|
style,
|
|
5586
4665
|
children: [
|
|
5587
|
-
eyebrow ? /* @__PURE__ */
|
|
5588
|
-
/* @__PURE__ */
|
|
5589
|
-
/* @__PURE__ */
|
|
4666
|
+
eyebrow ? /* @__PURE__ */ jsx13("p", { "data-insight-eyebrow": "", className: "mb-0.5 text-[11px] font-semibold uppercase tracking-[0.05em] text-muted-foreground", children: eyebrow }) : null,
|
|
4667
|
+
/* @__PURE__ */ jsxs11("div", { className: "flex items-baseline justify-between gap-2", children: [
|
|
4668
|
+
/* @__PURE__ */ jsx13("h3", { className: "text-[13px] font-medium text-muted-foreground", children: title }),
|
|
5590
4669
|
live ? (
|
|
5591
4670
|
// No `data-motion` opt-out: the word is the signal and the sweep is
|
|
5592
4671
|
// emphasis, so the reduced-motion floor reaches this like everything
|
|
5593
4672
|
// else and leaves a static, legible label.
|
|
5594
|
-
/* @__PURE__ */
|
|
4673
|
+
/* @__PURE__ */ jsx13("span", { className: "agent-shimmer shrink-0 text-[11px] font-medium", "data-insight-live": "", children: liveLabel })
|
|
5595
4674
|
) : null
|
|
5596
4675
|
] }),
|
|
5597
|
-
/* @__PURE__ */
|
|
5598
|
-
/* @__PURE__ */
|
|
5599
|
-
/* @__PURE__ */
|
|
5600
|
-
] }) : /* @__PURE__ */
|
|
5601
|
-
/* @__PURE__ */
|
|
5602
|
-
unit ? /* @__PURE__ */
|
|
4676
|
+
/* @__PURE__ */ jsx13("p", { className: "mt-1 flex items-baseline gap-1", children: unavailable ? /* @__PURE__ */ jsxs11("span", { "data-insight-value": "unavailable", className: "text-xl font-semibold text-muted-foreground", children: [
|
|
4677
|
+
/* @__PURE__ */ jsx13("span", { "aria-hidden": "true", children: INSIGHT_UNAVAILABLE_GLYPH }),
|
|
4678
|
+
/* @__PURE__ */ jsx13("span", { className: "sr-only", children: INSIGHT_UNAVAILABLE_LABEL })
|
|
4679
|
+
] }) : /* @__PURE__ */ jsxs11(Fragment6, { children: [
|
|
4680
|
+
/* @__PURE__ */ jsx13("span", { className: "text-xl font-semibold tabular-nums text-foreground", children: shown }),
|
|
4681
|
+
unit ? /* @__PURE__ */ jsx13("span", { className: "text-[11px] text-muted-foreground", children: unit }) : null
|
|
5603
4682
|
] }) }),
|
|
5604
|
-
delta ? /* @__PURE__ */
|
|
5605
|
-
/* @__PURE__ */
|
|
4683
|
+
delta ? /* @__PURE__ */ jsxs11("p", { "data-insight-delta": delta.direction, className: `mt-0.5 text-[11px] font-medium ${TONE_CLASS[tone]}`, children: [
|
|
4684
|
+
/* @__PURE__ */ jsxs11("span", { "aria-hidden": "true", children: [
|
|
5606
4685
|
DIRECTION_GLYPH[delta.direction],
|
|
5607
4686
|
" "
|
|
5608
4687
|
] }),
|
|
5609
4688
|
formatInsightDelta(delta, format)
|
|
5610
4689
|
] }) : null,
|
|
5611
|
-
description ? /* @__PURE__ */
|
|
5612
|
-
series ? /* @__PURE__ */
|
|
5613
|
-
action ? /* @__PURE__ */
|
|
4690
|
+
description ? /* @__PURE__ */ jsx13("p", { className: "mt-1 text-[11px] text-muted-foreground", children: description }) : null,
|
|
4691
|
+
series ? /* @__PURE__ */ jsx13("div", { className: "mt-2 text-muted-foreground", children: /* @__PURE__ */ jsx13(Sparkline, { values: series, label: seriesLabel ?? title, format }) }) : null,
|
|
4692
|
+
action ? /* @__PURE__ */ jsx13("div", { className: "mt-3", children: renderInsightAction(action) }) : null
|
|
5614
4693
|
]
|
|
5615
4694
|
}
|
|
5616
4695
|
);
|
|
5617
4696
|
}
|
|
5618
4697
|
function renderInsightAction(action) {
|
|
5619
4698
|
if (isValidElement2(action)) return action;
|
|
5620
|
-
return /* @__PURE__ */
|
|
4699
|
+
return /* @__PURE__ */ jsx13(
|
|
5621
4700
|
"button",
|
|
5622
4701
|
{
|
|
5623
4702
|
type: "button",
|
|
@@ -5686,15 +4765,15 @@ function InsightDeck({
|
|
|
5686
4765
|
className,
|
|
5687
4766
|
onPageChange
|
|
5688
4767
|
}) {
|
|
5689
|
-
const [page, setPage] =
|
|
5690
|
-
const [held, setHeld] =
|
|
4768
|
+
const [page, setPage] = useState14(0);
|
|
4769
|
+
const [held, setHeld] = useState14(null);
|
|
5691
4770
|
const answered = state.status === "error" || state.status === "empty";
|
|
5692
4771
|
const carried = state.status === "ready" ? state.value : answered ? null : held;
|
|
5693
4772
|
if (carried !== held) setHeld(carried);
|
|
5694
4773
|
const shown = carried !== null && state.status !== "ready" ? { status: "ready", value: carried, retry: state.retry } : state;
|
|
5695
4774
|
const refreshing = shown !== state;
|
|
5696
|
-
const reported =
|
|
5697
|
-
const settlePage =
|
|
4775
|
+
const reported = useRef10(0);
|
|
4776
|
+
const settlePage = useCallback9(
|
|
5698
4777
|
(next) => {
|
|
5699
4778
|
if (reported.current === next) return;
|
|
5700
4779
|
reported.current = next;
|
|
@@ -5702,7 +4781,7 @@ function InsightDeck({
|
|
|
5702
4781
|
},
|
|
5703
4782
|
[onPageChange]
|
|
5704
4783
|
);
|
|
5705
|
-
return /* @__PURE__ */
|
|
4784
|
+
return /* @__PURE__ */ jsx13(
|
|
5706
4785
|
AsyncView,
|
|
5707
4786
|
{
|
|
5708
4787
|
state: shown,
|
|
@@ -5710,7 +4789,7 @@ function InsightDeck({
|
|
|
5710
4789
|
loadingLabel,
|
|
5711
4790
|
retryLabel,
|
|
5712
4791
|
className,
|
|
5713
|
-
children: (insights) => /* @__PURE__ */
|
|
4792
|
+
children: (insights) => /* @__PURE__ */ jsx13(
|
|
5714
4793
|
InsightPages,
|
|
5715
4794
|
{
|
|
5716
4795
|
insights,
|
|
@@ -5777,18 +4856,18 @@ function InsightPages({
|
|
|
5777
4856
|
const pageCount = insightPageCount(insights.length, size);
|
|
5778
4857
|
const current = Math.min(Math.max(page, 0), pageCount - 1);
|
|
5779
4858
|
const visible = insightPageSlice(insights, current, size);
|
|
5780
|
-
const sectionRef =
|
|
5781
|
-
const listRef =
|
|
5782
|
-
const recoverFocus =
|
|
5783
|
-
|
|
4859
|
+
const sectionRef = useRef10(null);
|
|
4860
|
+
const listRef = useRef10(null);
|
|
4861
|
+
const recoverFocus = useRef10(false);
|
|
4862
|
+
useEffect10(() => {
|
|
5784
4863
|
onPageSettled(current);
|
|
5785
4864
|
}, [current, onPageSettled]);
|
|
5786
|
-
|
|
4865
|
+
useEffect10(() => {
|
|
5787
4866
|
if (!recoverFocus.current) return;
|
|
5788
4867
|
recoverFocus.current = false;
|
|
5789
4868
|
sectionRef.current?.focus();
|
|
5790
4869
|
}, [current]);
|
|
5791
|
-
const goTo =
|
|
4870
|
+
const goTo = useCallback9(
|
|
5792
4871
|
(next) => {
|
|
5793
4872
|
const clamped = Math.min(Math.max(next, 0), pageCount - 1);
|
|
5794
4873
|
if (clamped === current) return false;
|
|
@@ -5823,7 +4902,7 @@ function InsightPages({
|
|
|
5823
4902
|
}
|
|
5824
4903
|
if (moved) event.preventDefault();
|
|
5825
4904
|
};
|
|
5826
|
-
return /* @__PURE__ */
|
|
4905
|
+
return /* @__PURE__ */ jsxs11(
|
|
5827
4906
|
"section",
|
|
5828
4907
|
{
|
|
5829
4908
|
ref: sectionRef,
|
|
@@ -5835,7 +4914,7 @@ function InsightPages({
|
|
|
5835
4914
|
tabIndex: pageCount > 1 ? 0 : void 0,
|
|
5836
4915
|
"aria-keyshortcuts": pageCount > 1 ? "ArrowLeft ArrowRight PageUp PageDown Home End" : void 0,
|
|
5837
4916
|
children: [
|
|
5838
|
-
/* @__PURE__ */
|
|
4917
|
+
/* @__PURE__ */ jsx13("ul", { ref: listRef, className: "grid gap-3 sm:grid-cols-2 lg:grid-cols-3", children: visible.map(({ id, style, ...card }, index) => (
|
|
5839
4918
|
// The page index is in the key on purpose: a page turn is an arrival,
|
|
5840
4919
|
// and reusing the node would swap the text under a card that never
|
|
5841
4920
|
// moved. Remounting replays `.agent-arrive` with the new stagger.
|
|
@@ -5846,10 +4925,10 @@ function InsightPages({
|
|
|
5846
4925
|
// does not arrive a second time. The key does BOTH jobs — but only
|
|
5847
4926
|
// because the deck now keeps this subtree mounted across a reload
|
|
5848
4927
|
// (see `InsightDeck`); a key is never compared across a teardown.
|
|
5849
|
-
/* @__PURE__ */
|
|
4928
|
+
/* @__PURE__ */ jsx13("li", { children: /* @__PURE__ */ jsx13(InsightCard, { ...card, style: staggerStyle(index, style) }) }, `${current}:${id}`)
|
|
5850
4929
|
)) }),
|
|
5851
|
-
/* @__PURE__ */
|
|
5852
|
-
/* @__PURE__ */
|
|
4930
|
+
/* @__PURE__ */ jsxs11("div", { className: pageCount > 1 ? "flex items-center justify-between gap-2" : void 0, children: [
|
|
4931
|
+
/* @__PURE__ */ jsxs11(
|
|
5853
4932
|
"p",
|
|
5854
4933
|
{
|
|
5855
4934
|
role: "status",
|
|
@@ -5863,8 +4942,8 @@ function InsightPages({
|
|
|
5863
4942
|
]
|
|
5864
4943
|
}
|
|
5865
4944
|
),
|
|
5866
|
-
pageCount > 1 ? /* @__PURE__ */
|
|
5867
|
-
/* @__PURE__ */
|
|
4945
|
+
pageCount > 1 ? /* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-1", children: [
|
|
4946
|
+
/* @__PURE__ */ jsx13(PagerButton, { label: "Previous insights", glyph: "\u2039", atEnd: current === 0, onClick: () => goTo(current - 1) }),
|
|
5868
4947
|
pageCount <= MAX_PAGE_DOTS ? Array.from({ length: pageCount }, (_, index) => (
|
|
5869
4948
|
// WCAG 2.2 SC 2.5.8 wants a 24x24 CSS px target. The dot stays
|
|
5870
4949
|
// 8px because a 24px dot is a different control; the BUTTON
|
|
@@ -5872,7 +4951,7 @@ function InsightPages({
|
|
|
5872
4951
|
// and the span is the graphic. The Spacing exception cannot
|
|
5873
4952
|
// rescue the bare dot — at a 12px pitch the 24px circle around
|
|
5874
4953
|
// each centre overlaps its neighbour's.
|
|
5875
|
-
/* @__PURE__ */
|
|
4954
|
+
/* @__PURE__ */ jsx13(
|
|
5876
4955
|
"button",
|
|
5877
4956
|
{
|
|
5878
4957
|
type: "button",
|
|
@@ -5880,7 +4959,7 @@ function InsightPages({
|
|
|
5880
4959
|
"aria-current": index === current ? "page" : void 0,
|
|
5881
4960
|
onClick: () => goTo(index),
|
|
5882
4961
|
className: "group flex h-6 w-6 shrink-0 items-center justify-center rounded-full",
|
|
5883
|
-
children: /* @__PURE__ */
|
|
4962
|
+
children: /* @__PURE__ */ jsx13(
|
|
5884
4963
|
"span",
|
|
5885
4964
|
{
|
|
5886
4965
|
"aria-hidden": "true",
|
|
@@ -5894,7 +4973,7 @@ function InsightPages({
|
|
|
5894
4973
|
index
|
|
5895
4974
|
)
|
|
5896
4975
|
)) : null,
|
|
5897
|
-
/* @__PURE__ */
|
|
4976
|
+
/* @__PURE__ */ jsx13(
|
|
5898
4977
|
PagerButton,
|
|
5899
4978
|
{
|
|
5900
4979
|
label: "Next insights",
|
|
@@ -5915,7 +4994,7 @@ function PagerButton({
|
|
|
5915
4994
|
atEnd,
|
|
5916
4995
|
onClick
|
|
5917
4996
|
}) {
|
|
5918
|
-
return /* @__PURE__ */
|
|
4997
|
+
return /* @__PURE__ */ jsx13(
|
|
5919
4998
|
"button",
|
|
5920
4999
|
{
|
|
5921
5000
|
type: "button",
|
|
@@ -5925,13 +5004,13 @@ function PagerButton({
|
|
|
5925
5004
|
if (!atEnd) onClick();
|
|
5926
5005
|
},
|
|
5927
5006
|
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"}`,
|
|
5928
|
-
children: /* @__PURE__ */
|
|
5007
|
+
children: /* @__PURE__ */ jsx13("span", { "aria-hidden": "true", children: glyph })
|
|
5929
5008
|
}
|
|
5930
5009
|
);
|
|
5931
5010
|
}
|
|
5932
5011
|
|
|
5933
5012
|
// src/web-react/index.tsx
|
|
5934
|
-
import { Fragment as
|
|
5013
|
+
import { Fragment as Fragment7, jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
5935
5014
|
function formatModelCost(msg, models) {
|
|
5936
5015
|
if (msg.promptTokens == null && msg.completionTokens == null) return null;
|
|
5937
5016
|
const pricing = models.find((m) => m.id === msg.modelUsed)?.pricing;
|
|
@@ -5950,41 +5029,41 @@ function formatTokensPerSecond(msg) {
|
|
|
5950
5029
|
return `${Math.round(msg.completionTokens / (msg.durationMs / 1e3))} tok/s`;
|
|
5951
5030
|
}
|
|
5952
5031
|
function RunDrillIn({ run, onClose }) {
|
|
5953
|
-
return /* @__PURE__ */
|
|
5954
|
-
/* @__PURE__ */
|
|
5955
|
-
/* @__PURE__ */
|
|
5032
|
+
return /* @__PURE__ */ jsxs12("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: [
|
|
5033
|
+
/* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-2 border-b border-border px-4 py-3", children: [
|
|
5034
|
+
/* @__PURE__ */ jsx14(
|
|
5956
5035
|
"span",
|
|
5957
5036
|
{
|
|
5958
5037
|
className: `h-2 w-2 shrink-0 rounded-full ${run.status === "running" ? "bg-warning" : run.status === "error" ? "bg-destructive" : "bg-success"}`
|
|
5959
5038
|
}
|
|
5960
5039
|
),
|
|
5961
|
-
/* @__PURE__ */
|
|
5962
|
-
/* @__PURE__ */
|
|
5963
|
-
/* @__PURE__ */
|
|
5040
|
+
/* @__PURE__ */ jsxs12("div", { className: "min-w-0 flex-1", children: [
|
|
5041
|
+
/* @__PURE__ */ jsx14("p", { className: "truncate text-[15px] font-semibold", children: run.title }),
|
|
5042
|
+
/* @__PURE__ */ jsx14("p", { className: "truncate font-mono text-xs text-muted-foreground", children: run.toolName })
|
|
5964
5043
|
] }),
|
|
5965
|
-
/* @__PURE__ */
|
|
5044
|
+
/* @__PURE__ */ jsx14(
|
|
5966
5045
|
"button",
|
|
5967
5046
|
{
|
|
5968
5047
|
type: "button",
|
|
5969
5048
|
onClick: onClose,
|
|
5970
5049
|
"aria-label": "Close",
|
|
5971
5050
|
className: "rounded-md p-1.5 text-muted-foreground transition hover:bg-accent hover:text-foreground",
|
|
5972
|
-
children: /* @__PURE__ */
|
|
5051
|
+
children: /* @__PURE__ */ jsx14("svg", { className: "h-4 w-4", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", "aria-hidden": true, children: /* @__PURE__ */ jsx14("path", { d: "M18 6 6 18M6 6l12 12" }) })
|
|
5973
5052
|
}
|
|
5974
5053
|
)
|
|
5975
5054
|
] }),
|
|
5976
|
-
/* @__PURE__ */
|
|
5977
|
-
run.steps.length === 0 && /* @__PURE__ */
|
|
5978
|
-
run.steps.map((step, i) => /* @__PURE__ */
|
|
5979
|
-
/* @__PURE__ */
|
|
5980
|
-
/* @__PURE__ */
|
|
5981
|
-
/* @__PURE__ */
|
|
5982
|
-
/* @__PURE__ */
|
|
5055
|
+
/* @__PURE__ */ jsxs12("div", { className: "flex-1 space-y-3 overflow-y-auto p-4", children: [
|
|
5056
|
+
run.steps.length === 0 && /* @__PURE__ */ jsx14("p", { className: "text-sm text-muted-foreground", children: "No steps recorded yet." }),
|
|
5057
|
+
run.steps.map((step, i) => /* @__PURE__ */ jsxs12("div", { className: "rounded-lg border border-card-edge bg-card", children: [
|
|
5058
|
+
/* @__PURE__ */ jsxs12("div", { className: "flex items-baseline gap-2 border-b border-border px-3 py-1.5", children: [
|
|
5059
|
+
/* @__PURE__ */ jsx14("span", { className: `font-mono text-xs ${step.status === "error" ? "text-destructive" : "text-muted-foreground"}`, children: step.status === "error" ? "\u2717" : "$" }),
|
|
5060
|
+
/* @__PURE__ */ jsx14("code", { className: "min-w-0 flex-1 truncate font-mono text-xs", children: step.label }),
|
|
5061
|
+
/* @__PURE__ */ jsx14("span", { className: "shrink-0 text-xs tabular-nums text-muted-foreground", children: new Date(step.at).toLocaleTimeString([], { hour: "numeric", minute: "2-digit" }) })
|
|
5983
5062
|
] }),
|
|
5984
|
-
step.detail && /* @__PURE__ */
|
|
5063
|
+
step.detail && /* @__PURE__ */ jsx14("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 })
|
|
5985
5064
|
] }, i))
|
|
5986
5065
|
] }),
|
|
5987
|
-
/* @__PURE__ */
|
|
5066
|
+
/* @__PURE__ */ jsx14("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." })
|
|
5988
5067
|
] });
|
|
5989
5068
|
}
|
|
5990
5069
|
function pendingApprovalOf(call) {
|
|
@@ -6000,23 +5079,23 @@ function ChatEmptyState({
|
|
|
6000
5079
|
}) {
|
|
6001
5080
|
const doorCount = Math.min(doors?.length ?? 0, 3);
|
|
6002
5081
|
const doorsGridClass = doorCount === 1 ? "mx-auto max-w-sm sm:grid-cols-1" : doorCount === 2 ? "sm:grid-cols-2" : "sm:grid-cols-3";
|
|
6003
|
-
return /* @__PURE__ */
|
|
6004
|
-
/* @__PURE__ */
|
|
6005
|
-
/* @__PURE__ */
|
|
6006
|
-
/* @__PURE__ */
|
|
6007
|
-
subline && /* @__PURE__ */
|
|
6008
|
-
doors && doors.length > 0 && /* @__PURE__ */
|
|
5082
|
+
return /* @__PURE__ */ jsxs12("div", { className: "mx-auto flex w-full max-w-2xl flex-col items-center px-6 py-12 text-center sm:py-20", children: [
|
|
5083
|
+
/* @__PURE__ */ jsx14("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__ */ jsx14(BrandMark, { size: 32, className: "shrink-0" }) }),
|
|
5084
|
+
/* @__PURE__ */ jsx14("p", { className: "text-xs font-semibold uppercase tracking-[0.05em] text-muted-foreground", children: productName }),
|
|
5085
|
+
/* @__PURE__ */ jsx14("h2", { className: "mt-1.5 text-balance text-2xl font-semibold leading-tight text-foreground", children: headline }),
|
|
5086
|
+
subline && /* @__PURE__ */ jsx14("p", { className: "mt-3 max-w-md text-[15px] leading-relaxed text-muted-foreground", children: subline }),
|
|
5087
|
+
doors && doors.length > 0 && /* @__PURE__ */ jsx14("div", { className: `mt-7 grid w-full gap-2.5 ${doorsGridClass}`, children: doors.slice(0, 3).map((door, i) => /* @__PURE__ */ jsxs12(
|
|
6009
5088
|
"button",
|
|
6010
5089
|
{
|
|
6011
5090
|
type: "button",
|
|
6012
5091
|
onClick: door.onSelect,
|
|
6013
5092
|
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",
|
|
6014
5093
|
children: [
|
|
6015
|
-
/* @__PURE__ */
|
|
5094
|
+
/* @__PURE__ */ jsxs12("span", { className: "flex items-center gap-2 text-sm font-semibold text-foreground", children: [
|
|
6016
5095
|
door.icon,
|
|
6017
5096
|
door.label
|
|
6018
5097
|
] }),
|
|
6019
|
-
door.description && /* @__PURE__ */
|
|
5098
|
+
door.description && /* @__PURE__ */ jsx14("span", { className: "mt-0.5 text-[12px] leading-snug text-muted-foreground", children: door.description })
|
|
6020
5099
|
]
|
|
6021
5100
|
},
|
|
6022
5101
|
i
|
|
@@ -6025,26 +5104,26 @@ function ChatEmptyState({
|
|
|
6025
5104
|
}
|
|
6026
5105
|
function ToolGlyph({ name, className }) {
|
|
6027
5106
|
if (name.startsWith("sandbox_")) {
|
|
6028
|
-
return /* @__PURE__ */
|
|
6029
|
-
/* @__PURE__ */
|
|
6030
|
-
/* @__PURE__ */
|
|
5107
|
+
return /* @__PURE__ */ jsxs12("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: [
|
|
5108
|
+
/* @__PURE__ */ jsx14("polyline", { points: "4 17 10 11 4 5" }),
|
|
5109
|
+
/* @__PURE__ */ jsx14("line", { x1: "12", y1: "19", x2: "20", y2: "19" })
|
|
6031
5110
|
] });
|
|
6032
5111
|
}
|
|
6033
5112
|
if (name === "submit_proposal") {
|
|
6034
|
-
return /* @__PURE__ */
|
|
6035
|
-
/* @__PURE__ */
|
|
6036
|
-
/* @__PURE__ */
|
|
5113
|
+
return /* @__PURE__ */ jsxs12("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: [
|
|
5114
|
+
/* @__PURE__ */ jsx14("path", { d: "M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" }),
|
|
5115
|
+
/* @__PURE__ */ jsx14("path", { d: "M14 2v6h6M9 15l2 2 4-4" })
|
|
6037
5116
|
] });
|
|
6038
5117
|
}
|
|
6039
5118
|
if (name === "schedule_followup") {
|
|
6040
|
-
return /* @__PURE__ */
|
|
6041
|
-
/* @__PURE__ */
|
|
6042
|
-
/* @__PURE__ */
|
|
5119
|
+
return /* @__PURE__ */ jsxs12("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", "aria-hidden": true, children: [
|
|
5120
|
+
/* @__PURE__ */ jsx14("circle", { cx: "12", cy: "12", r: "9" }),
|
|
5121
|
+
/* @__PURE__ */ jsx14("path", { d: "M12 7v5l3 3" })
|
|
6043
5122
|
] });
|
|
6044
5123
|
}
|
|
6045
|
-
return /* @__PURE__ */
|
|
6046
|
-
/* @__PURE__ */
|
|
6047
|
-
/* @__PURE__ */
|
|
5124
|
+
return /* @__PURE__ */ jsxs12("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: [
|
|
5125
|
+
/* @__PURE__ */ jsx14("path", { d: "M12 3v3m0 12v3M3 12h3m12 0h3" }),
|
|
5126
|
+
/* @__PURE__ */ jsx14("circle", { cx: "12", cy: "12", r: "4" })
|
|
6048
5127
|
] });
|
|
6049
5128
|
}
|
|
6050
5129
|
function toolOutcomeOf(call) {
|
|
@@ -6130,40 +5209,40 @@ function truncate(v, max = 240) {
|
|
|
6130
5209
|
function KvRows({ data }) {
|
|
6131
5210
|
const entries = Object.entries(data).filter(([, v]) => v !== void 0 && v !== null && v !== "");
|
|
6132
5211
|
if (!entries.length) return null;
|
|
6133
|
-
return /* @__PURE__ */
|
|
6134
|
-
/* @__PURE__ */
|
|
6135
|
-
/* @__PURE__ */
|
|
5212
|
+
return /* @__PURE__ */ jsx14("dl", { className: "grid grid-cols-[auto_1fr] gap-x-3 gap-y-1", children: entries.map(([k, v]) => /* @__PURE__ */ jsxs12("div", { className: "contents", children: [
|
|
5213
|
+
/* @__PURE__ */ jsx14("dt", { className: "font-mono text-xs text-muted-foreground", children: k }),
|
|
5214
|
+
/* @__PURE__ */ jsx14("dd", { className: "min-w-0 whitespace-pre-wrap break-words font-mono text-xs text-muted-foreground", children: truncate(v) })
|
|
6136
5215
|
] }, k)) });
|
|
6137
5216
|
}
|
|
6138
5217
|
function ShellDetail({ call }) {
|
|
6139
5218
|
const outcome = toolOutcomeOf(call);
|
|
6140
5219
|
const r = outcome?.result ?? {};
|
|
6141
|
-
return /* @__PURE__ */
|
|
6142
|
-
/* @__PURE__ */
|
|
6143
|
-
/* @__PURE__ */
|
|
6144
|
-
/* @__PURE__ */
|
|
6145
|
-
r.exitCode != null && /* @__PURE__ */
|
|
5220
|
+
return /* @__PURE__ */ jsxs12("div", { className: "overflow-hidden rounded-md bg-zinc-900 font-mono text-xs leading-relaxed", children: [
|
|
5221
|
+
/* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-2 px-3 pt-2 text-zinc-400", children: [
|
|
5222
|
+
/* @__PURE__ */ jsx14("span", { className: "select-none text-zinc-500", children: "$" }),
|
|
5223
|
+
/* @__PURE__ */ jsx14("span", { className: "min-w-0 flex-1 truncate text-zinc-200", children: String(call.args?.command ?? "") }),
|
|
5224
|
+
r.exitCode != null && /* @__PURE__ */ jsxs12("span", { className: r.exitCode === 0 ? "text-success" : "text-destructive", children: [
|
|
6146
5225
|
"exit ",
|
|
6147
5226
|
r.exitCode
|
|
6148
5227
|
] })
|
|
6149
5228
|
] }),
|
|
6150
|
-
/* @__PURE__ */
|
|
5229
|
+
/* @__PURE__ */ jsx14("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)" })
|
|
6151
5230
|
] });
|
|
6152
5231
|
}
|
|
6153
5232
|
function DefaultToolDetail({ call }) {
|
|
6154
5233
|
const result = call.result;
|
|
6155
5234
|
const envelope = typeof result === "object" && result !== null ? result : null;
|
|
6156
|
-
return /* @__PURE__ */
|
|
6157
|
-
call.args && Object.keys(call.args).length > 0 && /* @__PURE__ */
|
|
6158
|
-
/* @__PURE__ */
|
|
6159
|
-
/* @__PURE__ */
|
|
5235
|
+
return /* @__PURE__ */ jsxs12("div", { className: "space-y-2", children: [
|
|
5236
|
+
call.args && Object.keys(call.args).length > 0 && /* @__PURE__ */ jsxs12("div", { children: [
|
|
5237
|
+
/* @__PURE__ */ jsx14("p", { className: "mb-1 text-xs font-semibold uppercase tracking-wide text-muted-foreground", children: "Called with" }),
|
|
5238
|
+
/* @__PURE__ */ jsx14(KvRows, { data: call.args })
|
|
6160
5239
|
] }),
|
|
6161
|
-
envelope ? /* @__PURE__ */
|
|
6162
|
-
/* @__PURE__ */
|
|
6163
|
-
envelope.ok === false ? /* @__PURE__ */
|
|
6164
|
-
] }) : result != null ? /* @__PURE__ */
|
|
6165
|
-
/* @__PURE__ */
|
|
6166
|
-
/* @__PURE__ */
|
|
5240
|
+
envelope ? /* @__PURE__ */ jsxs12("div", { children: [
|
|
5241
|
+
/* @__PURE__ */ jsx14("p", { className: "mb-1 text-xs font-semibold uppercase tracking-wide text-muted-foreground", children: envelope.ok === false ? "Failed" : "Result" }),
|
|
5242
|
+
envelope.ok === false ? /* @__PURE__ */ jsx14("p", { className: "text-xs text-destructive", children: envelope.message ?? "Tool failed" }) : envelope.result && typeof envelope.result === "object" ? /* @__PURE__ */ jsx14(KvRows, { data: envelope.result }) : envelope.result != null ? /* @__PURE__ */ jsx14("p", { className: "font-mono text-xs text-muted-foreground", children: truncate(envelope.result) }) : null
|
|
5243
|
+
] }) : result != null ? /* @__PURE__ */ jsxs12("div", { children: [
|
|
5244
|
+
/* @__PURE__ */ jsx14("p", { className: "mb-1 text-xs font-semibold uppercase tracking-wide text-muted-foreground", children: "Result" }),
|
|
5245
|
+
/* @__PURE__ */ jsx14("p", { className: "font-mono text-xs text-muted-foreground", children: truncate(result) })
|
|
6167
5246
|
] }) : null
|
|
6168
5247
|
] });
|
|
6169
5248
|
}
|
|
@@ -6174,24 +5253,24 @@ function ProposalCard({
|
|
|
6174
5253
|
approval,
|
|
6175
5254
|
renderers
|
|
6176
5255
|
}) {
|
|
6177
|
-
const [expanded, setExpanded] =
|
|
5256
|
+
const [expanded, setExpanded] = useState15(false);
|
|
6178
5257
|
const { summary, meta, typeSlug } = proposalPreview(call);
|
|
6179
5258
|
const custom = renderers?.[call.name]?.(call, message);
|
|
6180
5259
|
const { pending: deciding, run: decide } = usePending();
|
|
6181
|
-
return /* @__PURE__ */
|
|
6182
|
-
/* @__PURE__ */
|
|
6183
|
-
/* @__PURE__ */
|
|
6184
|
-
/* @__PURE__ */
|
|
6185
|
-
/* @__PURE__ */
|
|
6186
|
-
/* @__PURE__ */
|
|
6187
|
-
summary && /* @__PURE__ */
|
|
6188
|
-
typeSlug && /* @__PURE__ */
|
|
6189
|
-
meta.length > 0 && /* @__PURE__ */
|
|
5260
|
+
return /* @__PURE__ */ jsxs12("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: [
|
|
5261
|
+
/* @__PURE__ */ jsxs12("div", { className: "flex items-start gap-2.5 px-4 pt-3.5", children: [
|
|
5262
|
+
/* @__PURE__ */ jsx14("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__ */ jsx14(ToolGlyph, { name: call.name, className: "h-3.5 w-3.5" }) }),
|
|
5263
|
+
/* @__PURE__ */ jsxs12("div", { className: "min-w-0 flex-1", children: [
|
|
5264
|
+
/* @__PURE__ */ jsx14("p", { className: "text-xs font-semibold uppercase tracking-[0.05em] text-warning-strong", children: approval ? "Needs your approval" : "Awaiting approval" }),
|
|
5265
|
+
/* @__PURE__ */ jsx14("p", { className: "mt-0.5 text-[15px] font-semibold leading-snug text-foreground", children: friendlyToolTitle(call) }),
|
|
5266
|
+
summary && /* @__PURE__ */ jsx14("p", { className: "mt-1 text-xs leading-relaxed text-muted-foreground", children: summary }),
|
|
5267
|
+
typeSlug && /* @__PURE__ */ jsx14("p", { className: "mt-1 font-mono text-xs text-muted-foreground", children: typeSlug }),
|
|
5268
|
+
meta.length > 0 && /* @__PURE__ */ jsx14("div", { className: "mt-1.5 flex flex-wrap items-center gap-1.5", children: meta.map((m, i) => /* @__PURE__ */ jsx14("span", { className: "rounded-full bg-secondary px-2 py-0.5 text-xs font-medium text-muted-foreground", children: m }, i)) })
|
|
6190
5269
|
] })
|
|
6191
5270
|
] }),
|
|
6192
|
-
/* @__PURE__ */
|
|
6193
|
-
approval && /* @__PURE__ */
|
|
6194
|
-
/* @__PURE__ */
|
|
5271
|
+
/* @__PURE__ */ jsxs12("div", { className: "flex flex-wrap items-center gap-2 px-4 pb-3.5 pt-3", children: [
|
|
5272
|
+
approval && /* @__PURE__ */ jsxs12(Fragment7, { children: [
|
|
5273
|
+
/* @__PURE__ */ jsx14(
|
|
6195
5274
|
"button",
|
|
6196
5275
|
{
|
|
6197
5276
|
type: "button",
|
|
@@ -6201,7 +5280,7 @@ function ProposalCard({
|
|
|
6201
5280
|
children: "Approve & run"
|
|
6202
5281
|
}
|
|
6203
5282
|
),
|
|
6204
|
-
/* @__PURE__ */
|
|
5283
|
+
/* @__PURE__ */ jsx14(
|
|
6205
5284
|
"button",
|
|
6206
5285
|
{
|
|
6207
5286
|
type: "button",
|
|
@@ -6212,7 +5291,7 @@ function ProposalCard({
|
|
|
6212
5291
|
}
|
|
6213
5292
|
)
|
|
6214
5293
|
] }),
|
|
6215
|
-
/* @__PURE__ */
|
|
5294
|
+
/* @__PURE__ */ jsxs12(
|
|
6216
5295
|
"button",
|
|
6217
5296
|
{
|
|
6218
5297
|
type: "button",
|
|
@@ -6221,12 +5300,12 @@ function ProposalCard({
|
|
|
6221
5300
|
className: "ml-auto inline-flex items-center gap-1 rounded text-[12px] font-medium text-muted-foreground transition hover:text-foreground",
|
|
6222
5301
|
children: [
|
|
6223
5302
|
expanded ? "Hide details" : "View details",
|
|
6224
|
-
/* @__PURE__ */
|
|
5303
|
+
/* @__PURE__ */ jsx14(ChevronDown, { className: `h-3 w-3 transition-transform ${expanded ? "rotate-180" : ""}` })
|
|
6225
5304
|
]
|
|
6226
5305
|
}
|
|
6227
5306
|
)
|
|
6228
5307
|
] }),
|
|
6229
|
-
expanded && /* @__PURE__ */
|
|
5308
|
+
expanded && /* @__PURE__ */ jsx14("div", { className: "border-t border-warning/20 px-4 py-3 text-xs", children: custom ?? /* @__PURE__ */ jsx14(DefaultToolDetail, { call }) })
|
|
6230
5309
|
] });
|
|
6231
5310
|
}
|
|
6232
5311
|
function formatFollowupWhen(when) {
|
|
@@ -6241,14 +5320,14 @@ function FollowupCard({ call }) {
|
|
|
6241
5320
|
const when = typeof a.when === "string" ? a.when : typeof a.at === "string" ? a.at : typeof a.schedule === "string" ? a.schedule : null;
|
|
6242
5321
|
const failed = toolCallFailed(call);
|
|
6243
5322
|
const errorText = failed ? toolOutcomeOf(call)?.message ?? "Scheduling failed" : null;
|
|
6244
|
-
return /* @__PURE__ */
|
|
6245
|
-
/* @__PURE__ */
|
|
6246
|
-
/* @__PURE__ */
|
|
6247
|
-
/* @__PURE__ */
|
|
6248
|
-
when && /* @__PURE__ */
|
|
6249
|
-
/* @__PURE__ */
|
|
5323
|
+
return /* @__PURE__ */ jsx14("div", { className: "flex items-start gap-2", children: /* @__PURE__ */ jsxs12("div", { className: "min-w-0 flex-1 overflow-hidden rounded-[var(--radius-lg)] border border-[var(--border-subtle)] bg-[var(--md3-surface-container)]", children: [
|
|
5324
|
+
/* @__PURE__ */ jsxs12("div", { className: "flex w-full items-center gap-2.5 px-3 py-2", children: [
|
|
5325
|
+
/* @__PURE__ */ jsx14("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__ */ jsx14(ToolGlyph, { name: call.name, className: "h-3.5 w-3.5" }) }),
|
|
5326
|
+
/* @__PURE__ */ jsx14("span", { className: "shrink-0 whitespace-nowrap text-xs font-medium text-foreground", children: friendlyToolTitle(call) }),
|
|
5327
|
+
when && /* @__PURE__ */ jsx14("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) }),
|
|
5328
|
+
/* @__PURE__ */ jsx14("span", { className: "ml-auto flex shrink-0 items-center gap-1.5", children: call.status === "running" ? /* @__PURE__ */ jsx14("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__ */ jsx14("path", { d: "M21 12a9 9 0 1 1-6.219-8.56", strokeLinecap: "round" }) }) : /* @__PURE__ */ jsx14("span", { className: `h-1.5 w-1.5 shrink-0 rounded-full ${failed ? "bg-[var(--surface-danger-text)]" : "bg-[var(--surface-success-text)]"}` }) })
|
|
6250
5329
|
] }),
|
|
6251
|
-
errorText && /* @__PURE__ */
|
|
5330
|
+
errorText && /* @__PURE__ */ jsx14("div", { className: "border-t border-border px-3 py-2 text-xs text-[var(--surface-danger-text)]", children: errorText })
|
|
6252
5331
|
] }) });
|
|
6253
5332
|
}
|
|
6254
5333
|
function toolRowTitle(call) {
|
|
@@ -6271,10 +5350,10 @@ function ToolCallCard({
|
|
|
6271
5350
|
const arrival = useArrivalStyle(staggerIndex ?? 0);
|
|
6272
5351
|
const pending = call.status === "done" ? pendingApprovalOf(call) : null;
|
|
6273
5352
|
const kind = blockKindOf(call);
|
|
6274
|
-
const arrive = (row) => /* @__PURE__ */
|
|
5353
|
+
const arrive = (row) => /* @__PURE__ */ jsx14("div", { className: "agent-arrive", style: arrival, children: row });
|
|
6275
5354
|
if (pending) {
|
|
6276
5355
|
return arrive(
|
|
6277
|
-
/* @__PURE__ */
|
|
5356
|
+
/* @__PURE__ */ jsx14(
|
|
6278
5357
|
ProposalCard,
|
|
6279
5358
|
{
|
|
6280
5359
|
call,
|
|
@@ -6287,18 +5366,18 @@ function ToolCallCard({
|
|
|
6287
5366
|
);
|
|
6288
5367
|
}
|
|
6289
5368
|
if (kind === "followup") {
|
|
6290
|
-
return arrive(/* @__PURE__ */
|
|
5369
|
+
return arrive(/* @__PURE__ */ jsx14(FollowupCard, { call }));
|
|
6291
5370
|
}
|
|
6292
5371
|
const custom = renderers?.[call.name]?.(call, message);
|
|
6293
5372
|
return arrive(
|
|
6294
|
-
/* @__PURE__ */
|
|
5373
|
+
/* @__PURE__ */ jsx14(
|
|
6295
5374
|
InlineToolItem,
|
|
6296
5375
|
{
|
|
6297
5376
|
part: chatToolCallPart(call),
|
|
6298
5377
|
title: toolRowTitle(call),
|
|
6299
5378
|
description: toolRowDescription(call),
|
|
6300
|
-
renderToolDetail: () => custom ?? (call.name === "sandbox_run_command" ? /* @__PURE__ */
|
|
6301
|
-
actions: onOpenRun && call.name.startsWith("sandbox_") ? /* @__PURE__ */
|
|
5379
|
+
renderToolDetail: () => custom ?? (call.name === "sandbox_run_command" ? /* @__PURE__ */ jsx14(ShellDetail, { call }) : /* @__PURE__ */ jsx14(DefaultToolDetail, { call })),
|
|
5380
|
+
actions: onOpenRun && call.name.startsWith("sandbox_") ? /* @__PURE__ */ jsx14(
|
|
6302
5381
|
"button",
|
|
6303
5382
|
{
|
|
6304
5383
|
type: "button",
|
|
@@ -6306,9 +5385,9 @@ function ToolCallCard({
|
|
|
6306
5385
|
"aria-label": "Open full transcript",
|
|
6307
5386
|
title: "Open full transcript",
|
|
6308
5387
|
className: "rounded-md p-1.5 text-muted-foreground transition hover:bg-accent hover:text-foreground",
|
|
6309
|
-
children: /* @__PURE__ */
|
|
6310
|
-
/* @__PURE__ */
|
|
6311
|
-
/* @__PURE__ */
|
|
5388
|
+
children: /* @__PURE__ */ jsxs12("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: [
|
|
5389
|
+
/* @__PURE__ */ jsx14("path", { d: "M7 17 17 7" }),
|
|
5390
|
+
/* @__PURE__ */ jsx14("path", { d: "M7 7h10v10" })
|
|
6312
5391
|
] })
|
|
6313
5392
|
}
|
|
6314
5393
|
) : void 0
|
|
@@ -6317,7 +5396,7 @@ function ToolCallCard({
|
|
|
6317
5396
|
);
|
|
6318
5397
|
}
|
|
6319
5398
|
function StreamingCaret() {
|
|
6320
|
-
return /* @__PURE__ */
|
|
5399
|
+
return /* @__PURE__ */ jsx14(
|
|
6321
5400
|
"span",
|
|
6322
5401
|
{
|
|
6323
5402
|
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",
|
|
@@ -6334,7 +5413,7 @@ function SegmentText({
|
|
|
6334
5413
|
messageClassName
|
|
6335
5414
|
}) {
|
|
6336
5415
|
const text = useSmoothText(content, streaming);
|
|
6337
|
-
const body =
|
|
5416
|
+
const body = useMemo7(() => renderBody(text), [renderBody, text]);
|
|
6338
5417
|
if (!content.trim() && !showCaret) return null;
|
|
6339
5418
|
return (
|
|
6340
5419
|
// A settled run arrives from a short blur; the LIVE run does not, because
|
|
@@ -6342,9 +5421,9 @@ function SegmentText({
|
|
|
6342
5421
|
// the container on top of that makes the paragraph shimmer while it types.
|
|
6343
5422
|
// The distinction is what separates "the answer materialised" from "the
|
|
6344
5423
|
// log was appended to".
|
|
6345
|
-
/* @__PURE__ */
|
|
5424
|
+
/* @__PURE__ */ jsxs12("div", { className: `${messageClassName}${streaming ? "" : " agent-stream-in"}`, children: [
|
|
6346
5425
|
body,
|
|
6347
|
-
showCaret && /* @__PURE__ */
|
|
5426
|
+
showCaret && /* @__PURE__ */ jsx14(StreamingCaret, {})
|
|
6348
5427
|
] })
|
|
6349
5428
|
);
|
|
6350
5429
|
}
|
|
@@ -6369,7 +5448,7 @@ function SegmentedBody({
|
|
|
6369
5448
|
const leftoverToolCalls = (msg.toolCalls ?? []).filter(
|
|
6370
5449
|
(tc) => !segmentToolIds.has(tc.id)
|
|
6371
5450
|
);
|
|
6372
|
-
const renderToolCard = (call, index) => /* @__PURE__ */
|
|
5451
|
+
const renderToolCard = (call, index) => /* @__PURE__ */ jsx14(
|
|
6373
5452
|
ToolCallCard,
|
|
6374
5453
|
{
|
|
6375
5454
|
call,
|
|
@@ -6397,7 +5476,7 @@ function SegmentedBody({
|
|
|
6397
5476
|
for (const g of groups) {
|
|
6398
5477
|
if (g.kind === "text") {
|
|
6399
5478
|
children.push(
|
|
6400
|
-
/* @__PURE__ */
|
|
5479
|
+
/* @__PURE__ */ jsx14(
|
|
6401
5480
|
SegmentText,
|
|
6402
5481
|
{
|
|
6403
5482
|
content: g.content,
|
|
@@ -6413,13 +5492,13 @@ function SegmentedBody({
|
|
|
6413
5492
|
}
|
|
6414
5493
|
if (!streaming && g.calls.length >= COLLAPSE_TOOL_RUN_AT && !g.calls.some(isImportantTool)) {
|
|
6415
5494
|
children.push(
|
|
6416
|
-
/* @__PURE__ */
|
|
6417
|
-
/* @__PURE__ */
|
|
5495
|
+
/* @__PURE__ */ jsxs12("details", { children: [
|
|
5496
|
+
/* @__PURE__ */ jsxs12("summary", { className: "cursor-pointer select-none rounded-md py-0.5 text-xs font-medium text-muted-foreground [transition:color_var(--motion-control)] hover:text-foreground", children: [
|
|
6418
5497
|
"Worked through ",
|
|
6419
5498
|
g.calls.length,
|
|
6420
5499
|
" steps"
|
|
6421
5500
|
] }),
|
|
6422
|
-
/* @__PURE__ */
|
|
5501
|
+
/* @__PURE__ */ jsx14("div", { className: "mt-1.5 flex flex-col gap-1.5", children: g.calls.map(renderToolCard) })
|
|
6423
5502
|
] }, `tools-fold-${g.index}`)
|
|
6424
5503
|
);
|
|
6425
5504
|
continue;
|
|
@@ -6428,9 +5507,9 @@ function SegmentedBody({
|
|
|
6428
5507
|
}
|
|
6429
5508
|
leftoverToolCalls.forEach((call, index) => children.push(renderToolCard(call, index)));
|
|
6430
5509
|
if (streaming && segments[lastIndex]?.kind === "tool") {
|
|
6431
|
-
children.push(/* @__PURE__ */
|
|
5510
|
+
children.push(/* @__PURE__ */ jsx14(StreamingCaret, {}, "streaming-caret"));
|
|
6432
5511
|
}
|
|
6433
|
-
return /* @__PURE__ */
|
|
5512
|
+
return /* @__PURE__ */ jsx14("div", { className: "flex flex-col gap-2", children });
|
|
6434
5513
|
}
|
|
6435
5514
|
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";
|
|
6436
5515
|
function copyTextOf(msg) {
|
|
@@ -6439,9 +5518,9 @@ function copyTextOf(msg) {
|
|
|
6439
5518
|
return msg.content;
|
|
6440
5519
|
}
|
|
6441
5520
|
function CopyMessageButton({ text }) {
|
|
6442
|
-
const [copied, setCopied] =
|
|
6443
|
-
const timerRef =
|
|
6444
|
-
|
|
5521
|
+
const [copied, setCopied] = useState15(false);
|
|
5522
|
+
const timerRef = useRef11(null);
|
|
5523
|
+
useEffect11(
|
|
6445
5524
|
() => () => {
|
|
6446
5525
|
if (timerRef.current !== null) clearTimeout(timerRef.current);
|
|
6447
5526
|
},
|
|
@@ -6460,7 +5539,7 @@ function CopyMessageButton({ text }) {
|
|
|
6460
5539
|
}
|
|
6461
5540
|
);
|
|
6462
5541
|
};
|
|
6463
|
-
return /* @__PURE__ */
|
|
5542
|
+
return /* @__PURE__ */ jsx14(
|
|
6464
5543
|
"button",
|
|
6465
5544
|
{
|
|
6466
5545
|
type: "button",
|
|
@@ -6468,9 +5547,9 @@ function CopyMessageButton({ text }) {
|
|
|
6468
5547
|
"aria-label": "Copy message",
|
|
6469
5548
|
title: "Copy message",
|
|
6470
5549
|
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",
|
|
6471
|
-
children: copied ? /* @__PURE__ */
|
|
6472
|
-
/* @__PURE__ */
|
|
6473
|
-
/* @__PURE__ */
|
|
5550
|
+
children: copied ? /* @__PURE__ */ jsx14("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__ */ jsx14("polyline", { points: "20 6 9 17 4 12" }) }) : /* @__PURE__ */ jsxs12("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: [
|
|
5551
|
+
/* @__PURE__ */ jsx14("rect", { x: "9", y: "9", width: "13", height: "13", rx: "2" }),
|
|
5552
|
+
/* @__PURE__ */ jsx14("path", { d: "M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" })
|
|
6474
5553
|
] })
|
|
6475
5554
|
}
|
|
6476
5555
|
);
|
|
@@ -6493,34 +5572,34 @@ function AssistantMessageImpl({
|
|
|
6493
5572
|
}) {
|
|
6494
5573
|
const content = useSmoothText(msg.content, streaming);
|
|
6495
5574
|
const reasoning = useSmoothText(msg.reasoning ?? "", streaming);
|
|
6496
|
-
const body =
|
|
5575
|
+
const body = useMemo7(() => renderBody(content), [renderBody, content]);
|
|
6497
5576
|
const segments = msg.segments;
|
|
6498
5577
|
const hasAnswerText = content !== "" || (segments?.some((s) => s.kind === "text" && s.content.trim() !== "") ?? false);
|
|
6499
|
-
const reasoningScrollRef =
|
|
6500
|
-
const thinkStartRef =
|
|
6501
|
-
const thinkMsRef =
|
|
5578
|
+
const reasoningScrollRef = useRef11(null);
|
|
5579
|
+
const thinkStartRef = useRef11(null);
|
|
5580
|
+
const thinkMsRef = useRef11(null);
|
|
6502
5581
|
if (streaming && reasoning && !hasAnswerText && thinkStartRef.current === null) {
|
|
6503
5582
|
thinkStartRef.current = performance.now();
|
|
6504
5583
|
}
|
|
6505
5584
|
if (hasAnswerText && thinkStartRef.current !== null && thinkMsRef.current === null) {
|
|
6506
5585
|
thinkMsRef.current = performance.now() - thinkStartRef.current;
|
|
6507
5586
|
}
|
|
6508
|
-
|
|
5587
|
+
useEffect11(() => {
|
|
6509
5588
|
const el = reasoningScrollRef.current;
|
|
6510
5589
|
if (el && streaming && !hasAnswerText) el.scrollTop = el.scrollHeight;
|
|
6511
5590
|
}, [reasoning, streaming, hasAnswerText]);
|
|
6512
5591
|
const thinkingSeconds = useThinkingSeconds(
|
|
6513
5592
|
streaming && !!reasoning && !hasAnswerText
|
|
6514
5593
|
);
|
|
6515
|
-
const [reasoningToggled, setReasoningToggled] =
|
|
5594
|
+
const [reasoningToggled, setReasoningToggled] = useState15(null);
|
|
6516
5595
|
const reasoningOpen = reasoningToggled ?? !hasAnswerText;
|
|
6517
5596
|
const quiet = chrome === "quiet";
|
|
6518
|
-
return /* @__PURE__ */
|
|
6519
|
-
!quiet && /* @__PURE__ */
|
|
6520
|
-
/* @__PURE__ */
|
|
6521
|
-
msg.modelUsed && /* @__PURE__ */
|
|
6522
|
-
formatTokensPerSecond(msg) && /* @__PURE__ */
|
|
6523
|
-
formatModelCost(msg, models) && /* @__PURE__ */
|
|
5597
|
+
return /* @__PURE__ */ jsxs12("div", { className: `mx-auto w-full max-w-3xl px-6 ${quiet ? "group pb-1 pt-3" : "py-3"}`, children: [
|
|
5598
|
+
!quiet && /* @__PURE__ */ jsxs12("div", { className: "mb-1 flex items-baseline gap-2 text-xs tabular-nums text-muted-foreground", children: [
|
|
5599
|
+
/* @__PURE__ */ jsx14("span", { className: "font-semibold uppercase tracking-[0.05em]", children: agentLabel }),
|
|
5600
|
+
msg.modelUsed && /* @__PURE__ */ jsx14("span", { className: "font-mono normal-case", children: msg.modelUsed }),
|
|
5601
|
+
formatTokensPerSecond(msg) && /* @__PURE__ */ jsx14("span", { children: formatTokensPerSecond(msg) }),
|
|
5602
|
+
formatModelCost(msg, models) && /* @__PURE__ */ jsx14("span", { children: formatModelCost(msg, models) })
|
|
6524
5603
|
] }),
|
|
6525
5604
|
reasoning && // The canonical run-row grammar (RunRowShell — the same shell the tool
|
|
6526
5605
|
// rows compose): one family of rows instead of a bespoke disclosure per
|
|
@@ -6530,12 +5609,12 @@ function AssistantMessageImpl({
|
|
|
6530
5609
|
// and a click outranks the default from then on — the contract the old
|
|
6531
5610
|
// hand-rolled disclosure had, now enforced through the shell's
|
|
6532
5611
|
// controlled `open`.
|
|
6533
|
-
/* @__PURE__ */
|
|
5612
|
+
/* @__PURE__ */ jsx14(
|
|
6534
5613
|
RunRowShell,
|
|
6535
5614
|
{
|
|
6536
5615
|
className: "mb-2",
|
|
6537
|
-
icon: /* @__PURE__ */
|
|
6538
|
-
title: !hasAnswerText ? /* @__PURE__ */
|
|
5616
|
+
icon: /* @__PURE__ */ jsx14(BrainGlyph, { className: "h-3.5 w-3.5" }),
|
|
5617
|
+
title: !hasAnswerText ? /* @__PURE__ */ jsxs12("span", { className: "agent-shimmer", "data-motion": "essential", children: [
|
|
6539
5618
|
"Thinking",
|
|
6540
5619
|
thinkingSeconds >= 1 ? ` \xB7 ${thinkingSeconds}s` : "\u2026"
|
|
6541
5620
|
] }) : thinkMsRef.current != null ? (
|
|
@@ -6550,7 +5629,7 @@ function AssistantMessageImpl({
|
|
|
6550
5629
|
status: hasAnswerText ? "idle" : "running",
|
|
6551
5630
|
open: reasoningOpen,
|
|
6552
5631
|
onOpenChange: (next) => setReasoningToggled(next),
|
|
6553
|
-
children: /* @__PURE__ */
|
|
5632
|
+
children: /* @__PURE__ */ jsx14(
|
|
6554
5633
|
"div",
|
|
6555
5634
|
{
|
|
6556
5635
|
ref: reasoningScrollRef,
|
|
@@ -6560,7 +5639,7 @@ function AssistantMessageImpl({
|
|
|
6560
5639
|
)
|
|
6561
5640
|
}
|
|
6562
5641
|
),
|
|
6563
|
-
segments && segments.length > 0 ? /* @__PURE__ */
|
|
5642
|
+
segments && segments.length > 0 ? /* @__PURE__ */ jsx14(
|
|
6564
5643
|
SegmentedBody,
|
|
6565
5644
|
{
|
|
6566
5645
|
segments,
|
|
@@ -6572,12 +5651,12 @@ function AssistantMessageImpl({
|
|
|
6572
5651
|
toolRenderers,
|
|
6573
5652
|
messageClassName
|
|
6574
5653
|
}
|
|
6575
|
-
) : /* @__PURE__ */
|
|
6576
|
-
/* @__PURE__ */
|
|
5654
|
+
) : /* @__PURE__ */ jsxs12(Fragment7, { children: [
|
|
5655
|
+
/* @__PURE__ */ jsxs12("div", { className: messageClassName, children: [
|
|
6577
5656
|
body,
|
|
6578
|
-
streaming && content && !msg.toolCalls?.length && /* @__PURE__ */
|
|
5657
|
+
streaming && content && !msg.toolCalls?.length && /* @__PURE__ */ jsx14(StreamingCaret, {})
|
|
6579
5658
|
] }),
|
|
6580
|
-
msg.toolCalls && msg.toolCalls.length > 0 && /* @__PURE__ */
|
|
5659
|
+
msg.toolCalls && msg.toolCalls.length > 0 && /* @__PURE__ */ jsx14("div", { className: "mt-2 flex flex-col gap-1.5", children: msg.toolCalls.map((tc, index) => /* @__PURE__ */ jsx14(
|
|
6581
5660
|
ToolCallCard,
|
|
6582
5661
|
{
|
|
6583
5662
|
call: tc,
|
|
@@ -6590,7 +5669,7 @@ function AssistantMessageImpl({
|
|
|
6590
5669
|
tc.id
|
|
6591
5670
|
)) })
|
|
6592
5671
|
] }),
|
|
6593
|
-
durableCards && msg.parts && /* @__PURE__ */
|
|
5672
|
+
durableCards && msg.parts && /* @__PURE__ */ jsx14(
|
|
6594
5673
|
DurableChatCards,
|
|
6595
5674
|
{
|
|
6596
5675
|
...durableCards,
|
|
@@ -6599,7 +5678,7 @@ function AssistantMessageImpl({
|
|
|
6599
5678
|
className: "mt-3"
|
|
6600
5679
|
}
|
|
6601
5680
|
),
|
|
6602
|
-
workProductCards && workProductPartsFromMessageParts(msg.parts).map((part) => /* @__PURE__ */
|
|
5681
|
+
workProductCards && workProductPartsFromMessageParts(msg.parts).map((part) => /* @__PURE__ */ jsx14(
|
|
6603
5682
|
WorkProductCard,
|
|
6604
5683
|
{
|
|
6605
5684
|
part,
|
|
@@ -6609,7 +5688,7 @@ function AssistantMessageImpl({
|
|
|
6609
5688
|
`${part.ref.id}:${part.ref.version}`
|
|
6610
5689
|
)),
|
|
6611
5690
|
renderExtras?.(msg),
|
|
6612
|
-
resolveAttachmentUrl && attachmentPartsFromMessageParts(msg.parts).length > 0 && /* @__PURE__ */
|
|
5691
|
+
resolveAttachmentUrl && attachmentPartsFromMessageParts(msg.parts).length > 0 && /* @__PURE__ */ jsx14("div", { className: "mt-2", children: /* @__PURE__ */ jsx14(
|
|
6613
5692
|
MessageAttachments,
|
|
6614
5693
|
{
|
|
6615
5694
|
parts: attachmentPartsFromMessageParts(msg.parts),
|
|
@@ -6617,18 +5696,18 @@ function AssistantMessageImpl({
|
|
|
6617
5696
|
justify: "start"
|
|
6618
5697
|
}
|
|
6619
5698
|
) }),
|
|
6620
|
-
quiet && /* @__PURE__ */
|
|
6621
|
-
/* @__PURE__ */
|
|
6622
|
-
msg.modelUsed && /* @__PURE__ */
|
|
6623
|
-
formatTokensPerSecond(msg) && /* @__PURE__ */
|
|
6624
|
-
formatModelCost(msg, models) && /* @__PURE__ */
|
|
5699
|
+
quiet && /* @__PURE__ */ jsxs12("div", { "data-testid": "message-meta-lane", className: QUIET_META_LANE_CLASS, children: [
|
|
5700
|
+
/* @__PURE__ */ jsx14(CopyMessageButton, { text: copyTextOf(msg) }),
|
|
5701
|
+
msg.modelUsed && /* @__PURE__ */ jsx14("span", { className: "font-mono", children: msg.modelUsed }),
|
|
5702
|
+
formatTokensPerSecond(msg) && /* @__PURE__ */ jsx14("span", { children: formatTokensPerSecond(msg) }),
|
|
5703
|
+
formatModelCost(msg, models) && /* @__PURE__ */ jsx14("span", { children: formatModelCost(msg, models) })
|
|
6625
5704
|
] })
|
|
6626
5705
|
] });
|
|
6627
5706
|
}
|
|
6628
5707
|
var AssistantMessage = memo(AssistantMessageImpl);
|
|
6629
5708
|
function useThinkingSeconds(active) {
|
|
6630
|
-
const [seconds, setSeconds] =
|
|
6631
|
-
|
|
5709
|
+
const [seconds, setSeconds] = useState15(0);
|
|
5710
|
+
useEffect11(() => {
|
|
6632
5711
|
if (!active) return;
|
|
6633
5712
|
setSeconds(0);
|
|
6634
5713
|
const id = setInterval(() => setSeconds((s) => s + 1), 1e3);
|
|
@@ -6638,23 +5717,23 @@ function useThinkingSeconds(active) {
|
|
|
6638
5717
|
}
|
|
6639
5718
|
function ThinkingRow({ agentLabel, chrome = "labeled" }) {
|
|
6640
5719
|
const seconds = useThinkingSeconds(true);
|
|
6641
|
-
return /* @__PURE__ */
|
|
6642
|
-
chrome !== "quiet" && /* @__PURE__ */
|
|
6643
|
-
/* @__PURE__ */
|
|
6644
|
-
/* @__PURE__ */
|
|
5720
|
+
return /* @__PURE__ */ jsxs12("div", { className: "mx-auto w-full max-w-3xl px-6 py-3", children: [
|
|
5721
|
+
chrome !== "quiet" && /* @__PURE__ */ jsx14("p", { className: "mb-1 text-xs font-semibold uppercase tracking-[0.05em] text-muted-foreground", children: agentLabel }),
|
|
5722
|
+
/* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-2 text-[15px] text-muted-foreground", children: [
|
|
5723
|
+
/* @__PURE__ */ jsx14("svg", { className: "h-4 w-4 animate-spin", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", "aria-hidden": true, children: /* @__PURE__ */ jsx14("path", { d: "M21 12a9 9 0 1 1-6.219-8.56", strokeLinecap: "round" }) }),
|
|
6645
5724
|
"Thinking",
|
|
6646
5725
|
seconds >= 3 ? ` \xB7 ${seconds}s` : "..."
|
|
6647
5726
|
] })
|
|
6648
5727
|
] });
|
|
6649
5728
|
}
|
|
6650
5729
|
function StreamErrorRow({ message, onRetry }) {
|
|
6651
|
-
return /* @__PURE__ */
|
|
6652
|
-
/* @__PURE__ */
|
|
6653
|
-
/* @__PURE__ */
|
|
6654
|
-
/* @__PURE__ */
|
|
5730
|
+
return /* @__PURE__ */ jsx14("div", { className: "mx-auto w-full max-w-3xl px-6 py-3", children: /* @__PURE__ */ jsxs12("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: [
|
|
5731
|
+
/* @__PURE__ */ jsxs12("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: [
|
|
5732
|
+
/* @__PURE__ */ jsx14("circle", { cx: "12", cy: "12", r: "9" }),
|
|
5733
|
+
/* @__PURE__ */ jsx14("path", { d: "M12 8v4m0 4h.01" })
|
|
6655
5734
|
] }),
|
|
6656
|
-
/* @__PURE__ */
|
|
6657
|
-
onRetry && /* @__PURE__ */
|
|
5735
|
+
/* @__PURE__ */ jsx14("span", { className: "min-w-0 flex-1 break-words", children: message }),
|
|
5736
|
+
onRetry && /* @__PURE__ */ jsx14(
|
|
6658
5737
|
"button",
|
|
6659
5738
|
{
|
|
6660
5739
|
type: "button",
|
|
@@ -6688,33 +5767,33 @@ function ChatMessages({
|
|
|
6688
5767
|
workProductCards
|
|
6689
5768
|
}) {
|
|
6690
5769
|
const messageClassName = messageSize === "large" ? "agent-app-message-copy text-[17px] leading-[1.6]" : "agent-app-message-copy text-base leading-[1.6]";
|
|
6691
|
-
const renderBody =
|
|
6692
|
-
() => renderMarkdown ?? ((content) => /* @__PURE__ */
|
|
5770
|
+
const renderBody = useMemo7(
|
|
5771
|
+
() => renderMarkdown ?? ((content) => /* @__PURE__ */ jsx14("p", { className: "whitespace-pre-wrap", children: content })),
|
|
6693
5772
|
[renderMarkdown]
|
|
6694
5773
|
);
|
|
6695
5774
|
const lastIsUser = messages[messages.length - 1]?.role === "user";
|
|
6696
5775
|
const quiet = chrome === "quiet";
|
|
6697
5776
|
if (messages.length === 0 && !loading && !error) {
|
|
6698
|
-
const empty = renderEmpty ? renderEmpty() : /* @__PURE__ */
|
|
6699
|
-
return /* @__PURE__ */
|
|
5777
|
+
const empty = renderEmpty ? renderEmpty() : /* @__PURE__ */ jsx14(ChatEmptyState, { ...emptyState });
|
|
5778
|
+
return /* @__PURE__ */ jsxs12(Fragment7, { children: [
|
|
6700
5779
|
header,
|
|
6701
5780
|
empty
|
|
6702
5781
|
] });
|
|
6703
5782
|
}
|
|
6704
|
-
return /* @__PURE__ */
|
|
5783
|
+
return /* @__PURE__ */ jsxs12(Fragment7, { children: [
|
|
6705
5784
|
header,
|
|
6706
5785
|
messages.map(
|
|
6707
|
-
(msg) => msg.role === "user" ? /* @__PURE__ */
|
|
6708
|
-
/* @__PURE__ */
|
|
6709
|
-
!quiet && /* @__PURE__ */
|
|
6710
|
-
/* @__PURE__ */
|
|
5786
|
+
(msg) => msg.role === "user" ? /* @__PURE__ */ jsxs12("div", { className: `mx-auto w-full max-w-3xl px-6 ${quiet ? "group pb-1 pt-3" : "py-3"}`, children: [
|
|
5787
|
+
/* @__PURE__ */ jsxs12("div", { className: `ml-auto w-fit ${quiet ? "max-w-[72%]" : "max-w-[85%]"}`, children: [
|
|
5788
|
+
!quiet && /* @__PURE__ */ jsx14("p", { className: "mb-1 text-right text-xs font-semibold uppercase tracking-[0.05em] text-muted-foreground", children: userLabel }),
|
|
5789
|
+
/* @__PURE__ */ jsx14(
|
|
6711
5790
|
"div",
|
|
6712
5791
|
{
|
|
6713
5792
|
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}`,
|
|
6714
|
-
children: /* @__PURE__ */
|
|
5793
|
+
children: /* @__PURE__ */ jsx14("p", { className: "whitespace-pre-wrap", children: msg.content })
|
|
6715
5794
|
}
|
|
6716
5795
|
),
|
|
6717
|
-
resolveAttachmentUrl && attachmentPartsFromMessageParts(msg.parts).length > 0 && /* @__PURE__ */
|
|
5796
|
+
resolveAttachmentUrl && attachmentPartsFromMessageParts(msg.parts).length > 0 && /* @__PURE__ */ jsx14("div", { className: "mt-1.5", children: /* @__PURE__ */ jsx14(
|
|
6718
5797
|
MessageAttachments,
|
|
6719
5798
|
{
|
|
6720
5799
|
parts: attachmentPartsFromMessageParts(msg.parts),
|
|
@@ -6723,8 +5802,8 @@ function ChatMessages({
|
|
|
6723
5802
|
}
|
|
6724
5803
|
) })
|
|
6725
5804
|
] }),
|
|
6726
|
-
quiet && /* @__PURE__ */
|
|
6727
|
-
] }, msg.id) : /* @__PURE__ */
|
|
5805
|
+
quiet && /* @__PURE__ */ jsx14("div", { "data-testid": "message-meta-lane", className: `${QUIET_META_LANE_CLASS} justify-end`, children: /* @__PURE__ */ jsx14(CopyMessageButton, { text: msg.content }) })
|
|
5806
|
+
] }, msg.id) : /* @__PURE__ */ jsx14(
|
|
6728
5807
|
AssistantMessage,
|
|
6729
5808
|
{
|
|
6730
5809
|
msg,
|
|
@@ -6745,8 +5824,8 @@ function ChatMessages({
|
|
|
6745
5824
|
msg.id
|
|
6746
5825
|
)
|
|
6747
5826
|
),
|
|
6748
|
-
loading && lastIsUser && /* @__PURE__ */
|
|
6749
|
-
error && !loading && /* @__PURE__ */
|
|
5827
|
+
loading && lastIsUser && /* @__PURE__ */ jsx14(ThinkingRow, { agentLabel, chrome }),
|
|
5828
|
+
error && !loading && /* @__PURE__ */ jsx14(StreamErrorRow, { message: error, onRetry })
|
|
6750
5829
|
] });
|
|
6751
5830
|
}
|
|
6752
5831
|
|
|
@@ -6781,11 +5860,6 @@ export {
|
|
|
6781
5860
|
dispatchChatStreamLine,
|
|
6782
5861
|
consumeChatStream,
|
|
6783
5862
|
streamChatTurn,
|
|
6784
|
-
pickDictationMimeType,
|
|
6785
|
-
dictationErrorMessage,
|
|
6786
|
-
formatDictationElapsed,
|
|
6787
|
-
useDictation,
|
|
6788
|
-
ChatComposer,
|
|
6789
5863
|
DurablePlanClientError,
|
|
6790
5864
|
createDurablePlanDecisionClient,
|
|
6791
5865
|
useDurablePlanFlow,
|
|
@@ -6885,4 +5959,4 @@ export {
|
|
|
6885
5959
|
useThinkingSeconds,
|
|
6886
5960
|
ChatMessages
|
|
6887
5961
|
};
|
|
6888
|
-
//# sourceMappingURL=chunk-
|
|
5962
|
+
//# sourceMappingURL=chunk-JAYKCWW4.js.map
|