@tangle-network/agent-app 0.46.4 → 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 -4
- 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-RLOHIX5Y.js → chunk-3HUFJ5LO.js} +1 -13
- 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-YTEUZXX2.js → chunk-JAYKCWW4.js} +619 -1671
- 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-GVLG3W7C.js → mention-editor-WW7UVZMR.js} +5 -3
- package/dist/{mention-editor-GVLG3W7C.js.map → mention-editor-WW7UVZMR.js.map} +1 -1
- 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 +2 -0
- package/dist/web-react/index.js +14 -9
- package/package.json +1 -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-RLOHIX5Y.js.map +0 -1
- package/dist/chunk-YTEUZXX2.js.map +0 -1
|
@@ -2,9 +2,8 @@ import {
|
|
|
2
2
|
PATH_CONTINUATION_CHAR,
|
|
3
3
|
WORD_CHAR,
|
|
4
4
|
charAt,
|
|
5
|
-
charBefore
|
|
6
|
-
|
|
7
|
-
} from "./chunk-RLOHIX5Y.js";
|
|
5
|
+
charBefore
|
|
6
|
+
} from "./chunk-3HUFJ5LO.js";
|
|
8
7
|
import {
|
|
9
8
|
stepActivityFlowTrace
|
|
10
9
|
} from "./chunk-FBVLEGEG.js";
|
|
@@ -13,9 +12,8 @@ import {
|
|
|
13
12
|
workProductPartsFromMessageParts
|
|
14
13
|
} from "./chunk-ENLRJYVW.js";
|
|
15
14
|
import {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
} from "./chunk-DINGA2MO.js";
|
|
15
|
+
joinClasses
|
|
16
|
+
} from "./chunk-L7MB2LLM.js";
|
|
19
17
|
import {
|
|
20
18
|
BrainGlyph,
|
|
21
19
|
ChevronDown,
|
|
@@ -52,7 +50,7 @@ import {
|
|
|
52
50
|
} from "./chunk-YJMCRXQQ.js";
|
|
53
51
|
|
|
54
52
|
// src/web-react/index.tsx
|
|
55
|
-
import { useEffect as
|
|
53
|
+
import { useEffect as useEffect11, useMemo as useMemo7, useRef as useRef11, useState as useState15, memo } from "react";
|
|
56
54
|
import { InlineToolItem, RunRowShell } from "@tangle-network/ui/run";
|
|
57
55
|
|
|
58
56
|
// src/web-react/smooth-text.ts
|
|
@@ -1417,1053 +1415,8 @@ async function streamChatTurn(opts) {
|
|
|
1417
1415
|
}
|
|
1418
1416
|
}
|
|
1419
1417
|
|
|
1420
|
-
// src/web-react/chat-composer.tsx
|
|
1421
|
-
import {
|
|
1422
|
-
Component,
|
|
1423
|
-
lazy as lazy2,
|
|
1424
|
-
Suspense as Suspense2,
|
|
1425
|
-
useCallback as useCallback3,
|
|
1426
|
-
useEffect as useEffect6,
|
|
1427
|
-
useMemo as useMemo3,
|
|
1428
|
-
useId,
|
|
1429
|
-
useRef as useRef6,
|
|
1430
|
-
useState as useState8
|
|
1431
|
-
} from "react";
|
|
1432
|
-
|
|
1433
|
-
// src/web-react/use-dictation.ts
|
|
1434
|
-
import { useCallback as useCallback2, useEffect as useEffect5, useRef as useRef5, useState as useState7 } from "react";
|
|
1435
|
-
var PREFERRED_MIME_TYPES = ["audio/webm;codecs=opus", "audio/webm", "audio/mp4"];
|
|
1436
|
-
function pickDictationMimeType() {
|
|
1437
|
-
if (typeof MediaRecorder === "undefined" || typeof MediaRecorder.isTypeSupported !== "function") {
|
|
1438
|
-
return void 0;
|
|
1439
|
-
}
|
|
1440
|
-
for (const type of PREFERRED_MIME_TYPES) {
|
|
1441
|
-
if (MediaRecorder.isTypeSupported(type)) return type;
|
|
1442
|
-
}
|
|
1443
|
-
return void 0;
|
|
1444
|
-
}
|
|
1445
|
-
function detectDictationSupport() {
|
|
1446
|
-
return typeof navigator !== "undefined" && typeof navigator.mediaDevices?.getUserMedia === "function" && typeof MediaRecorder !== "undefined";
|
|
1447
|
-
}
|
|
1448
|
-
function dictationErrorMessage(error) {
|
|
1449
|
-
if (error instanceof DOMException) {
|
|
1450
|
-
if (error.name === "NotAllowedError") return "Microphone access was denied \u2014 allow it in the browser to dictate.";
|
|
1451
|
-
if (error.name === "NotFoundError") return "No microphone found on this device.";
|
|
1452
|
-
}
|
|
1453
|
-
return "Could not start recording.";
|
|
1454
|
-
}
|
|
1455
|
-
function formatDictationElapsed(totalSeconds) {
|
|
1456
|
-
const safe = Number.isFinite(totalSeconds) && totalSeconds > 0 ? Math.floor(totalSeconds) : 0;
|
|
1457
|
-
const minutes = Math.floor(safe / 60);
|
|
1458
|
-
const seconds = safe % 60;
|
|
1459
|
-
return `${minutes}:${String(seconds).padStart(2, "0")}`;
|
|
1460
|
-
}
|
|
1461
|
-
function releaseStream(stream) {
|
|
1462
|
-
for (const track of stream.getTracks()) track.stop();
|
|
1463
|
-
}
|
|
1464
|
-
function useDictation({ onDictate, onError }) {
|
|
1465
|
-
const [supported] = useState7(detectDictationSupport);
|
|
1466
|
-
const [recording, setRecording] = useState7(false);
|
|
1467
|
-
const [elapsedSeconds, setElapsedSeconds] = useState7(0);
|
|
1468
|
-
const sessionRef = useRef5(null);
|
|
1469
|
-
const cancelPendingStartRef = useRef5(null);
|
|
1470
|
-
const callbacksRef = useRef5({ onDictate, onError });
|
|
1471
|
-
callbacksRef.current = { onDictate, onError };
|
|
1472
|
-
useEffect5(() => {
|
|
1473
|
-
if (!recording) return;
|
|
1474
|
-
setElapsedSeconds(0);
|
|
1475
|
-
const id = setInterval(() => setElapsedSeconds((s) => s + 1), 1e3);
|
|
1476
|
-
return () => clearInterval(id);
|
|
1477
|
-
}, [recording]);
|
|
1478
|
-
const teardown = useCallback2((cancelled) => {
|
|
1479
|
-
const session = sessionRef.current;
|
|
1480
|
-
if (session === null) return;
|
|
1481
|
-
session.cancelled = session.cancelled || cancelled;
|
|
1482
|
-
sessionRef.current = null;
|
|
1483
|
-
releaseStream(session.stream);
|
|
1484
|
-
setRecording(false);
|
|
1485
|
-
}, []);
|
|
1486
|
-
const stop = useCallback2(() => {
|
|
1487
|
-
cancelPendingStartRef.current?.();
|
|
1488
|
-
cancelPendingStartRef.current = null;
|
|
1489
|
-
const session = sessionRef.current;
|
|
1490
|
-
if (session === null || session.cancelled) return;
|
|
1491
|
-
if (session.recorder.state !== "inactive") session.recorder.stop();
|
|
1492
|
-
}, []);
|
|
1493
|
-
const start = useCallback2(() => {
|
|
1494
|
-
if (!supported) return;
|
|
1495
|
-
if (sessionRef.current !== null || cancelPendingStartRef.current !== null) return;
|
|
1496
|
-
let pendingCancelled = false;
|
|
1497
|
-
cancelPendingStartRef.current = () => {
|
|
1498
|
-
pendingCancelled = true;
|
|
1499
|
-
};
|
|
1500
|
-
navigator.mediaDevices.getUserMedia({ audio: true }).then(
|
|
1501
|
-
(stream) => {
|
|
1502
|
-
cancelPendingStartRef.current = null;
|
|
1503
|
-
if (pendingCancelled) {
|
|
1504
|
-
releaseStream(stream);
|
|
1505
|
-
return;
|
|
1506
|
-
}
|
|
1507
|
-
const mimeType = pickDictationMimeType();
|
|
1508
|
-
const recorder = new MediaRecorder(stream, mimeType === void 0 ? void 0 : { mimeType });
|
|
1509
|
-
const session = {
|
|
1510
|
-
stream,
|
|
1511
|
-
recorder,
|
|
1512
|
-
chunks: [],
|
|
1513
|
-
mimeType: recorder.mimeType || mimeType || "",
|
|
1514
|
-
startedAt: Date.now(),
|
|
1515
|
-
cancelled: false
|
|
1516
|
-
};
|
|
1517
|
-
sessionRef.current = session;
|
|
1518
|
-
recorder.ondataavailable = (event) => {
|
|
1519
|
-
if (event.data.size > 0) session.chunks.push(event.data);
|
|
1520
|
-
};
|
|
1521
|
-
recorder.onstop = () => {
|
|
1522
|
-
teardown(session.cancelled);
|
|
1523
|
-
if (session.cancelled) return;
|
|
1524
|
-
const blob = new Blob(session.chunks, { type: session.mimeType });
|
|
1525
|
-
if (blob.size === 0) {
|
|
1526
|
-
callbacksRef.current.onError?.("Nothing was recorded.");
|
|
1527
|
-
return;
|
|
1528
|
-
}
|
|
1529
|
-
const durationSeconds = Math.max(0, Math.round((Date.now() - session.startedAt) / 1e3));
|
|
1530
|
-
callbacksRef.current.onDictate({ blob, mimeType: session.mimeType, durationSeconds });
|
|
1531
|
-
};
|
|
1532
|
-
recorder.onerror = () => {
|
|
1533
|
-
teardown(true);
|
|
1534
|
-
callbacksRef.current.onError?.("Recording stopped unexpectedly.");
|
|
1535
|
-
};
|
|
1536
|
-
recorder.start();
|
|
1537
|
-
setRecording(true);
|
|
1538
|
-
},
|
|
1539
|
-
(error) => {
|
|
1540
|
-
cancelPendingStartRef.current = null;
|
|
1541
|
-
if (pendingCancelled) return;
|
|
1542
|
-
callbacksRef.current.onError?.(dictationErrorMessage(error));
|
|
1543
|
-
}
|
|
1544
|
-
);
|
|
1545
|
-
}, [supported, teardown]);
|
|
1546
|
-
useEffect5(
|
|
1547
|
-
() => () => {
|
|
1548
|
-
cancelPendingStartRef.current?.();
|
|
1549
|
-
cancelPendingStartRef.current = null;
|
|
1550
|
-
const session = sessionRef.current;
|
|
1551
|
-
if (session === null) return;
|
|
1552
|
-
session.cancelled = true;
|
|
1553
|
-
sessionRef.current = null;
|
|
1554
|
-
try {
|
|
1555
|
-
if (session.recorder.state !== "inactive") session.recorder.stop();
|
|
1556
|
-
} finally {
|
|
1557
|
-
releaseStream(session.stream);
|
|
1558
|
-
}
|
|
1559
|
-
},
|
|
1560
|
-
[]
|
|
1561
|
-
);
|
|
1562
|
-
return { supported, recording, elapsedSeconds, start, stop };
|
|
1563
|
-
}
|
|
1564
|
-
|
|
1565
|
-
// src/web-react/chat-composer.tsx
|
|
1566
|
-
import { Fragment as Fragment2, jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
1567
|
-
function createLazyMentionEditor() {
|
|
1568
|
-
return lazy2(() => import("./mention-editor-GVLG3W7C.js").then((m) => m.loadMentionEditor()));
|
|
1569
|
-
}
|
|
1570
|
-
var MentionEditorBoundary = class extends Component {
|
|
1571
|
-
state = { error: null };
|
|
1572
|
-
static getDerivedStateFromError(error) {
|
|
1573
|
-
return { error };
|
|
1574
|
-
}
|
|
1575
|
-
componentDidCatch() {
|
|
1576
|
-
this.props.onFailed();
|
|
1577
|
-
}
|
|
1578
|
-
render() {
|
|
1579
|
-
if (this.state.error === null) return this.props.children;
|
|
1580
|
-
const message = this.state.error instanceof Error ? this.state.error.message : String(this.state.error);
|
|
1581
|
-
return /* @__PURE__ */ jsxs5(
|
|
1582
|
-
"div",
|
|
1583
|
-
{
|
|
1584
|
-
role: "alert",
|
|
1585
|
-
"data-testid": "composer-mention-editor-error",
|
|
1586
|
-
className: "rounded-xl border border-destructive/40 bg-destructive/10 px-3 py-2 text-xs text-destructive",
|
|
1587
|
-
children: [
|
|
1588
|
-
/* @__PURE__ */ jsxs5("div", { className: "flex items-start gap-2", children: [
|
|
1589
|
-
/* @__PURE__ */ jsxs5("span", { className: "min-w-0 flex-1", children: [
|
|
1590
|
-
"The mention input failed to load: ",
|
|
1591
|
-
message
|
|
1592
|
-
] }),
|
|
1593
|
-
/* @__PURE__ */ jsx7(
|
|
1594
|
-
"button",
|
|
1595
|
-
{
|
|
1596
|
-
type: "button",
|
|
1597
|
-
"aria-label": "Retry loading the mention input",
|
|
1598
|
-
onClick: this.props.onRetry,
|
|
1599
|
-
className: "shrink-0 font-medium underline-offset-2 hover:underline focus:outline-none focus-visible:ring-2 focus-visible:ring-destructive/50",
|
|
1600
|
-
children: "Retry"
|
|
1601
|
-
}
|
|
1602
|
-
)
|
|
1603
|
-
] }),
|
|
1604
|
-
this.props.draft.trim() !== "" && /* @__PURE__ */ jsx7(
|
|
1605
|
-
"p",
|
|
1606
|
-
{
|
|
1607
|
-
"data-testid": "composer-error-held-draft",
|
|
1608
|
-
className: "mt-1.5 max-h-20 overflow-y-auto whitespace-pre-wrap rounded-lg border border-destructive/30 bg-card px-2 py-1 text-foreground",
|
|
1609
|
-
children: this.props.draft
|
|
1610
|
-
}
|
|
1611
|
-
)
|
|
1612
|
-
]
|
|
1613
|
-
}
|
|
1614
|
-
);
|
|
1615
|
-
}
|
|
1616
|
-
};
|
|
1617
|
-
var IS_APPLE_PLATFORM = typeof navigator !== "undefined" && /Mac|iPhone|iPad|iPod/i.test(navigator.platform);
|
|
1618
|
-
function SendGlyph({ className }) {
|
|
1619
|
-
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" }) });
|
|
1620
|
-
}
|
|
1621
|
-
function StopGlyph({ className }) {
|
|
1622
|
-
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" }) });
|
|
1623
|
-
}
|
|
1624
|
-
function ArrowUpGlyph({ className }) {
|
|
1625
|
-
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" }) });
|
|
1626
|
-
}
|
|
1627
|
-
function PaperclipGlyph({ className }) {
|
|
1628
|
-
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" }) });
|
|
1629
|
-
}
|
|
1630
|
-
function FolderGlyph({ className }) {
|
|
1631
|
-
return /* @__PURE__ */ jsxs5("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: [
|
|
1632
|
-
/* @__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" }),
|
|
1633
|
-
/* @__PURE__ */ jsx7("path", { d: "M12 10v6m-3-3h6" })
|
|
1634
|
-
] });
|
|
1635
|
-
}
|
|
1636
|
-
function CloseGlyph({ className }) {
|
|
1637
|
-
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" }) });
|
|
1638
|
-
}
|
|
1639
|
-
function RetryGlyph({ className }) {
|
|
1640
|
-
return /* @__PURE__ */ jsxs5("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: [
|
|
1641
|
-
/* @__PURE__ */ jsx7("path", { d: "M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8" }),
|
|
1642
|
-
/* @__PURE__ */ jsx7("path", { d: "M3 3v5h5" })
|
|
1643
|
-
] });
|
|
1644
|
-
}
|
|
1645
|
-
function UploadGlyph({ className }) {
|
|
1646
|
-
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" }) });
|
|
1647
|
-
}
|
|
1648
|
-
function MicGlyph({ className }) {
|
|
1649
|
-
return /* @__PURE__ */ jsxs5("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: [
|
|
1650
|
-
/* @__PURE__ */ jsx7("rect", { x: "9", y: "2", width: "6", height: "12", rx: "3" }),
|
|
1651
|
-
/* @__PURE__ */ jsx7("path", { d: "M5 10v1a7 7 0 0 0 14 0v-1M12 18v4" })
|
|
1652
|
-
] });
|
|
1653
|
-
}
|
|
1654
|
-
var DEFAULT_MAX_HEIGHT = 168;
|
|
1655
|
-
var LINE_HEIGHT = 24;
|
|
1656
|
-
var TEXTAREA_PADDING_Y = 8;
|
|
1657
|
-
var DEFAULT_SEND_FAILURE = "Message not sent. Your draft is still here \u2014 try again.";
|
|
1658
|
-
function isRejectedOutcome(outcome) {
|
|
1659
|
-
return typeof outcome === "object" && outcome !== null && outcome.ok === false;
|
|
1660
|
-
}
|
|
1661
|
-
function isPromise(value) {
|
|
1662
|
-
return typeof value?.then === "function";
|
|
1663
|
-
}
|
|
1664
|
-
function sendFailureText(error, fallback) {
|
|
1665
|
-
if (typeof error === "object" && error !== null && "ok" in error) {
|
|
1666
|
-
const named = error.error;
|
|
1667
|
-
if (typeof named === "string" && named.trim() !== "") return named;
|
|
1668
|
-
return fallback;
|
|
1669
|
-
}
|
|
1670
|
-
if (typeof error === "string" && error.trim() !== "") return error;
|
|
1671
|
-
if (error instanceof Error && error.message.trim() !== "") return error.message;
|
|
1672
|
-
return fallback;
|
|
1673
|
-
}
|
|
1674
|
-
function ChatComposer({
|
|
1675
|
-
onSend,
|
|
1676
|
-
onSendParts,
|
|
1677
|
-
onSendFailed,
|
|
1678
|
-
sendFailureMessage = DEFAULT_SEND_FAILURE,
|
|
1679
|
-
onCancel,
|
|
1680
|
-
isStreaming = false,
|
|
1681
|
-
disabled = false,
|
|
1682
|
-
placeholder = "Message the agent\u2026",
|
|
1683
|
-
value,
|
|
1684
|
-
onValueChange,
|
|
1685
|
-
initialValue,
|
|
1686
|
-
seed,
|
|
1687
|
-
onSeedApplied,
|
|
1688
|
-
controls,
|
|
1689
|
-
controlsPlacement = "inline",
|
|
1690
|
-
onAttach,
|
|
1691
|
-
onAttachFolder,
|
|
1692
|
-
pendingFiles = [],
|
|
1693
|
-
onRemoveFile,
|
|
1694
|
-
onRetryFile,
|
|
1695
|
-
accept,
|
|
1696
|
-
onRejectFiles,
|
|
1697
|
-
dropTitle = "Drop files to add context",
|
|
1698
|
-
dropDescription = "They attach to your next message.",
|
|
1699
|
-
contextItems = [],
|
|
1700
|
-
canSubmitAttachmentsOnly = false,
|
|
1701
|
-
attachmentsNotReadyMessage,
|
|
1702
|
-
canSubmitWhileBusy = false,
|
|
1703
|
-
autoFocus,
|
|
1704
|
-
minRows = 2,
|
|
1705
|
-
maxHeight = DEFAULT_MAX_HEIGHT,
|
|
1706
|
-
trailing,
|
|
1707
|
-
mention,
|
|
1708
|
-
slashCommands,
|
|
1709
|
-
onDictate,
|
|
1710
|
-
onDictateError,
|
|
1711
|
-
focusShortcut = true,
|
|
1712
|
-
floating = false,
|
|
1713
|
-
sendLabel = "Send",
|
|
1714
|
-
sendVariant = "pill",
|
|
1715
|
-
className
|
|
1716
|
-
}) {
|
|
1717
|
-
const isControlled = value !== void 0;
|
|
1718
|
-
const [internal, setInternal] = useState8(initialValue ?? "");
|
|
1719
|
-
const text = isControlled ? value : internal;
|
|
1720
|
-
const textRef = useRef6(text);
|
|
1721
|
-
textRef.current = text;
|
|
1722
|
-
const textareaRef = useRef6(null);
|
|
1723
|
-
const richFocusRef = useRef6(null);
|
|
1724
|
-
const registerRichFocus = useCallback3((focus) => {
|
|
1725
|
-
richFocusRef.current = focus;
|
|
1726
|
-
}, []);
|
|
1727
|
-
const [editorEpoch, setEditorEpoch] = useState8(0);
|
|
1728
|
-
const MentionEditor = useMemo3(createLazyMentionEditor, [editorEpoch]);
|
|
1729
|
-
const [editorFailed, setEditorFailed] = useState8(false);
|
|
1730
|
-
const fileInputRef = useRef6(null);
|
|
1731
|
-
const folderInputRef = useRef6(null);
|
|
1732
|
-
const [dragOver, setDragOver] = useState8(false);
|
|
1733
|
-
const dragDepth = useRef6(0);
|
|
1734
|
-
const pastedImageCount = useRef6(0);
|
|
1735
|
-
const setText = useCallback3(
|
|
1736
|
-
(next) => {
|
|
1737
|
-
if (!isControlled) setInternal(next);
|
|
1738
|
-
onValueChange?.(next);
|
|
1739
|
-
},
|
|
1740
|
-
[isControlled, onValueChange]
|
|
1741
|
-
);
|
|
1742
|
-
const [dictateError, setDictateError] = useState8(null);
|
|
1743
|
-
const handleDictated = useCallback3(
|
|
1744
|
-
(audio) => {
|
|
1745
|
-
setDictateError(null);
|
|
1746
|
-
onDictate?.(audio);
|
|
1747
|
-
},
|
|
1748
|
-
[onDictate]
|
|
1749
|
-
);
|
|
1750
|
-
const handleDictateError = useCallback3(
|
|
1751
|
-
(message) => {
|
|
1752
|
-
setDictateError(message);
|
|
1753
|
-
onDictateError?.(message);
|
|
1754
|
-
},
|
|
1755
|
-
[onDictateError]
|
|
1756
|
-
);
|
|
1757
|
-
const dictation = useDictation({ onDictate: handleDictated, onError: handleDictateError });
|
|
1758
|
-
useEffect6(() => {
|
|
1759
|
-
const el = textareaRef.current;
|
|
1760
|
-
if (!el) return;
|
|
1761
|
-
el.style.height = "auto";
|
|
1762
|
-
el.style.height = `${Math.min(el.scrollHeight, maxHeight)}px`;
|
|
1763
|
-
}, [text, maxHeight, minRows]);
|
|
1764
|
-
const prevSeedRef = useRef6(null);
|
|
1765
|
-
const pendingCaretRef = useRef6(null);
|
|
1766
|
-
useEffect6(() => {
|
|
1767
|
-
const prev = prevSeedRef.current;
|
|
1768
|
-
prevSeedRef.current = seed ?? null;
|
|
1769
|
-
if (seed == null || seed === prev || isControlled) return;
|
|
1770
|
-
setText(seed);
|
|
1771
|
-
onSeedApplied?.();
|
|
1772
|
-
const el = textareaRef.current;
|
|
1773
|
-
if (el && el.value === seed) {
|
|
1774
|
-
el.focus();
|
|
1775
|
-
el.setSelectionRange(seed.length, seed.length);
|
|
1776
|
-
} else {
|
|
1777
|
-
pendingCaretRef.current = seed;
|
|
1778
|
-
}
|
|
1779
|
-
}, [seed, setText, onSeedApplied, isControlled]);
|
|
1780
|
-
useEffect6(() => {
|
|
1781
|
-
if (pendingCaretRef.current == null || pendingCaretRef.current !== text)
|
|
1782
|
-
return;
|
|
1783
|
-
pendingCaretRef.current = null;
|
|
1784
|
-
const el = textareaRef.current;
|
|
1785
|
-
if (!el) return;
|
|
1786
|
-
el.focus();
|
|
1787
|
-
el.setSelectionRange(text.length, text.length);
|
|
1788
|
-
}, [text]);
|
|
1789
|
-
const restoreCaretRef = useRef6(null);
|
|
1790
|
-
useEffect6(() => {
|
|
1791
|
-
const pending = restoreCaretRef.current;
|
|
1792
|
-
if (!pending || pending.text !== text) return;
|
|
1793
|
-
restoreCaretRef.current = null;
|
|
1794
|
-
const el = textareaRef.current;
|
|
1795
|
-
if (!el) return;
|
|
1796
|
-
el.focus();
|
|
1797
|
-
const start = Math.min(pending.start, text.length);
|
|
1798
|
-
const end = Math.min(pending.end, text.length);
|
|
1799
|
-
el.setSelectionRange(start, end);
|
|
1800
|
-
}, [text]);
|
|
1801
|
-
const mentionEnabled = mention != null;
|
|
1802
|
-
useEffect6(() => {
|
|
1803
|
-
if (!focusShortcut || disabled) return;
|
|
1804
|
-
function onKeyDown(e) {
|
|
1805
|
-
if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === "l") {
|
|
1806
|
-
if (mentionEnabled) {
|
|
1807
|
-
const focus = richFocusRef.current;
|
|
1808
|
-
if (!focus) return;
|
|
1809
|
-
e.preventDefault();
|
|
1810
|
-
focus();
|
|
1811
|
-
} else {
|
|
1812
|
-
e.preventDefault();
|
|
1813
|
-
textareaRef.current?.focus();
|
|
1814
|
-
}
|
|
1815
|
-
}
|
|
1816
|
-
}
|
|
1817
|
-
document.addEventListener("keydown", onKeyDown);
|
|
1818
|
-
return () => document.removeEventListener("keydown", onKeyDown);
|
|
1819
|
-
}, [focusShortcut, disabled, mentionEnabled]);
|
|
1820
|
-
const sendableFiles = canSubmitAttachmentsOnly ? pendingFiles : pendingFiles.filter((f) => f.status === "ready");
|
|
1821
|
-
const hasSendable = text.trim().length > 0 || sendableFiles.length > 0;
|
|
1822
|
-
const sendBlockedByStream = isStreaming && !canSubmitWhileBusy;
|
|
1823
|
-
const editorInputLost = mention != null && editorFailed;
|
|
1824
|
-
const canSend = hasSendable && !sendBlockedByStream && !disabled && !editorInputLost;
|
|
1825
|
-
const [failedSend, setFailedSend] = useState8(null);
|
|
1826
|
-
const failSend = useCallback3(
|
|
1827
|
-
(error, draft, trimmed, parts, caret) => {
|
|
1828
|
-
const message = sendFailureText(error, sendFailureMessage);
|
|
1829
|
-
const restored = textRef.current === "";
|
|
1830
|
-
if (restored) {
|
|
1831
|
-
const el = textareaRef.current;
|
|
1832
|
-
setText(draft);
|
|
1833
|
-
if (el && el.value === draft) {
|
|
1834
|
-
el.focus();
|
|
1835
|
-
el.setSelectionRange(Math.min(caret.start, draft.length), Math.min(caret.end, draft.length));
|
|
1836
|
-
} else {
|
|
1837
|
-
restoreCaretRef.current = { text: draft, start: caret.start, end: caret.end };
|
|
1838
|
-
}
|
|
1839
|
-
}
|
|
1840
|
-
setFailedSend({ message, text: draft, trimmed, parts, restored });
|
|
1841
|
-
onSendFailed?.({ message, text: draft, parts, error, restored });
|
|
1842
|
-
},
|
|
1843
|
-
[onSendFailed, sendFailureMessage, setText]
|
|
1844
|
-
);
|
|
1845
|
-
const dispatchSend = useCallback3(
|
|
1846
|
-
(draft, trimmed, parts, caret) => {
|
|
1847
|
-
let outcome;
|
|
1848
|
-
try {
|
|
1849
|
-
outcome = onSendParts ? onSendParts(trimmed, parts) : onSend?.(trimmed);
|
|
1850
|
-
} catch (error) {
|
|
1851
|
-
failSend(error, draft, trimmed, parts, caret);
|
|
1852
|
-
return;
|
|
1853
|
-
}
|
|
1854
|
-
if (isPromise(outcome)) {
|
|
1855
|
-
void outcome.then(
|
|
1856
|
-
(settled) => {
|
|
1857
|
-
if (isRejectedOutcome(settled)) failSend(settled, draft, trimmed, parts, caret);
|
|
1858
|
-
},
|
|
1859
|
-
(error) => failSend(error, draft, trimmed, parts, caret)
|
|
1860
|
-
);
|
|
1861
|
-
return;
|
|
1862
|
-
}
|
|
1863
|
-
if (isRejectedOutcome(outcome)) failSend(outcome, draft, trimmed, parts, caret);
|
|
1864
|
-
},
|
|
1865
|
-
[onSend, onSendParts, failSend]
|
|
1866
|
-
);
|
|
1867
|
-
const send = useCallback3(() => {
|
|
1868
|
-
const trimmed = text.trim();
|
|
1869
|
-
if (sendBlockedByStream || disabled || editorInputLost) return;
|
|
1870
|
-
const readyFiles = pendingFiles.filter((f) => f.status === "ready");
|
|
1871
|
-
const sendable = canSubmitAttachmentsOnly ? pendingFiles : readyFiles;
|
|
1872
|
-
if (!trimmed && sendable.length === 0) return;
|
|
1873
|
-
if (!trimmed && readyFiles.length === 0) {
|
|
1874
|
-
const message = attachmentsNotReadyMessage ?? (pendingFiles.some((f) => f.status === "error") ? "Retry or remove the failed attachment before sending." : "Wait for the attachment to finish uploading.");
|
|
1875
|
-
setFailedSend({ message, text: "", trimmed: "", parts: [], restored: true });
|
|
1876
|
-
return;
|
|
1877
|
-
}
|
|
1878
|
-
const parts = onSendParts ? readyFiles.filter((f) => f.part).map((f) => f.part) : [];
|
|
1879
|
-
const el = textareaRef.current;
|
|
1880
|
-
const caret = { start: el?.selectionStart ?? text.length, end: el?.selectionEnd ?? text.length };
|
|
1881
|
-
setFailedSend(null);
|
|
1882
|
-
setText("");
|
|
1883
|
-
textRef.current = "";
|
|
1884
|
-
dispatchSend(text, trimmed, parts, caret);
|
|
1885
|
-
}, [
|
|
1886
|
-
text,
|
|
1887
|
-
sendBlockedByStream,
|
|
1888
|
-
disabled,
|
|
1889
|
-
editorInputLost,
|
|
1890
|
-
canSubmitAttachmentsOnly,
|
|
1891
|
-
attachmentsNotReadyMessage,
|
|
1892
|
-
onSendParts,
|
|
1893
|
-
pendingFiles,
|
|
1894
|
-
setText,
|
|
1895
|
-
dispatchSend
|
|
1896
|
-
]);
|
|
1897
|
-
const retryFailedSend = useCallback3(() => {
|
|
1898
|
-
const failure = failedSend;
|
|
1899
|
-
if (!failure || sendBlockedByStream || disabled) return;
|
|
1900
|
-
setFailedSend(null);
|
|
1901
|
-
const caret = { start: failure.text.length, end: failure.text.length };
|
|
1902
|
-
dispatchSend(failure.text, failure.trimmed, failure.parts, caret);
|
|
1903
|
-
}, [failedSend, sendBlockedByStream, disabled, dispatchSend]);
|
|
1904
|
-
const slashPanelRef = useRef6(null);
|
|
1905
|
-
const cardRef = useRef6(null);
|
|
1906
|
-
const slashListId = useId();
|
|
1907
|
-
const [slashActive, setSlashActive] = useState8(0);
|
|
1908
|
-
const [slashDismissedFor, setSlashDismissedFor] = useState8(null);
|
|
1909
|
-
const slashToken = !mention && slashCommands && slashCommands.length > 0 ? /^\/(\S*)$/.exec(text)?.[1] : void 0;
|
|
1910
|
-
const slashOpen = slashToken !== void 0 && text !== slashDismissedFor;
|
|
1911
|
-
const slashItems = useMemo3(
|
|
1912
|
-
() => (slashCommands ?? []).map((command) => ({
|
|
1913
|
-
id: command.name,
|
|
1914
|
-
group: "Commands",
|
|
1915
|
-
label: `/${command.name}`,
|
|
1916
|
-
description: command.description,
|
|
1917
|
-
keywords: [command.name, command.description]
|
|
1918
|
-
})),
|
|
1919
|
-
[slashCommands]
|
|
1920
|
-
);
|
|
1921
|
-
const slashFiltered = useMemo3(
|
|
1922
|
-
() => slashToken === void 0 ? [] : filterCommandPaletteItems(slashItems, slashToken),
|
|
1923
|
-
[slashItems, slashToken]
|
|
1924
|
-
);
|
|
1925
|
-
const slashActiveIndex = slashFiltered.length === 0 ? 0 : Math.min(slashActive, slashFiltered.length - 1);
|
|
1926
|
-
useEffect6(() => {
|
|
1927
|
-
setSlashActive(0);
|
|
1928
|
-
}, [slashToken]);
|
|
1929
|
-
useEffect6(() => {
|
|
1930
|
-
if (!slashOpen) return;
|
|
1931
|
-
document.getElementById(`${slashListId}-${slashActiveIndex}`)?.scrollIntoView?.({ block: "nearest" });
|
|
1932
|
-
}, [slashOpen, slashActiveIndex, slashListId]);
|
|
1933
|
-
useEffect6(() => {
|
|
1934
|
-
if (!slashOpen) return;
|
|
1935
|
-
function onMouseDown(e) {
|
|
1936
|
-
const target = e.target;
|
|
1937
|
-
if (cardRef.current?.contains(target)) return;
|
|
1938
|
-
if (slashPanelRef.current?.contains(target)) return;
|
|
1939
|
-
setSlashDismissedFor(textRef.current);
|
|
1940
|
-
}
|
|
1941
|
-
document.addEventListener("mousedown", onMouseDown);
|
|
1942
|
-
return () => document.removeEventListener("mousedown", onMouseDown);
|
|
1943
|
-
}, [slashOpen]);
|
|
1944
|
-
const pickSlash = useCallback3(
|
|
1945
|
-
(name) => {
|
|
1946
|
-
const command = slashCommands?.find((c) => c.name === name);
|
|
1947
|
-
setText("");
|
|
1948
|
-
setSlashDismissedFor(null);
|
|
1949
|
-
command?.run();
|
|
1950
|
-
},
|
|
1951
|
-
[slashCommands, setText]
|
|
1952
|
-
);
|
|
1953
|
-
const handleKeyDown = (e) => {
|
|
1954
|
-
if (e.nativeEvent.isComposing) return;
|
|
1955
|
-
if (slashOpen) {
|
|
1956
|
-
if (e.key === "ArrowDown") {
|
|
1957
|
-
e.preventDefault();
|
|
1958
|
-
if (slashFiltered.length > 0) setSlashActive((slashActiveIndex + 1) % slashFiltered.length);
|
|
1959
|
-
return;
|
|
1960
|
-
}
|
|
1961
|
-
if (e.key === "ArrowUp") {
|
|
1962
|
-
e.preventDefault();
|
|
1963
|
-
if (slashFiltered.length > 0)
|
|
1964
|
-
setSlashActive((slashActiveIndex - 1 + slashFiltered.length) % slashFiltered.length);
|
|
1965
|
-
return;
|
|
1966
|
-
}
|
|
1967
|
-
if (e.key === "Enter" && !e.shiftKey || e.key === "Tab") {
|
|
1968
|
-
const item = slashFiltered[slashActiveIndex];
|
|
1969
|
-
if (item) {
|
|
1970
|
-
e.preventDefault();
|
|
1971
|
-
pickSlash(item.id);
|
|
1972
|
-
return;
|
|
1973
|
-
}
|
|
1974
|
-
}
|
|
1975
|
-
if (e.key === "Escape") {
|
|
1976
|
-
e.preventDefault();
|
|
1977
|
-
setSlashDismissedFor(text);
|
|
1978
|
-
return;
|
|
1979
|
-
}
|
|
1980
|
-
}
|
|
1981
|
-
if (e.key === "Enter" && !e.shiftKey) {
|
|
1982
|
-
e.preventDefault();
|
|
1983
|
-
send();
|
|
1984
|
-
}
|
|
1985
|
-
};
|
|
1986
|
-
const deliverFiles = useCallback3(
|
|
1987
|
-
(files, original) => {
|
|
1988
|
-
if (!onAttach || files.length === 0) return;
|
|
1989
|
-
const { accepted, rejected } = filterAcceptedFiles(files, accept);
|
|
1990
|
-
if (rejected.length > 0) onRejectFiles?.(rejected);
|
|
1991
|
-
if (accepted.length === 0) return;
|
|
1992
|
-
const unchanged = accepted.length === original.length && accepted.every((file, i) => file === original[i]);
|
|
1993
|
-
if (unchanged) {
|
|
1994
|
-
onAttach(original);
|
|
1995
|
-
return;
|
|
1996
|
-
}
|
|
1997
|
-
const transfer = new DataTransfer();
|
|
1998
|
-
for (const file of accepted) transfer.items.add(file);
|
|
1999
|
-
onAttach(transfer.files);
|
|
2000
|
-
},
|
|
2001
|
-
[onAttach, onRejectFiles, accept]
|
|
2002
|
-
);
|
|
2003
|
-
const handleFileChange = (e) => {
|
|
2004
|
-
if (e.target.files?.length) deliverFiles(Array.from(e.target.files), e.target.files);
|
|
2005
|
-
e.target.value = "";
|
|
2006
|
-
};
|
|
2007
|
-
const ingestPastedFiles = (clipboardFiles) => {
|
|
2008
|
-
if (!onAttach || clipboardFiles.length === 0) return false;
|
|
2009
|
-
const { files, nextIndex } = renamePastedImages(
|
|
2010
|
-
Array.from(clipboardFiles),
|
|
2011
|
-
pastedImageCount.current,
|
|
2012
|
-
pendingFiles.map((f) => f.name)
|
|
2013
|
-
);
|
|
2014
|
-
pastedImageCount.current = nextIndex;
|
|
2015
|
-
deliverFiles(files, clipboardFiles);
|
|
2016
|
-
return true;
|
|
2017
|
-
};
|
|
2018
|
-
const handlePaste = (e) => {
|
|
2019
|
-
const clipboardFiles = e.clipboardData?.files;
|
|
2020
|
-
if (!clipboardFiles || clipboardFiles.length === 0) return;
|
|
2021
|
-
if (ingestPastedFiles(clipboardFiles)) e.preventDefault();
|
|
2022
|
-
};
|
|
2023
|
-
const handleFolderChange = (e) => {
|
|
2024
|
-
if (e.target.files?.length) (onAttachFolder ?? onAttach)?.(e.target.files);
|
|
2025
|
-
e.target.value = "";
|
|
2026
|
-
};
|
|
2027
|
-
const handleDragEnter = useCallback3((e) => {
|
|
2028
|
-
e.preventDefault();
|
|
2029
|
-
e.stopPropagation();
|
|
2030
|
-
dragDepth.current++;
|
|
2031
|
-
if (e.dataTransfer?.types.includes("Files")) setDragOver(true);
|
|
2032
|
-
}, []);
|
|
2033
|
-
const handleDragLeave = useCallback3((e) => {
|
|
2034
|
-
e.preventDefault();
|
|
2035
|
-
e.stopPropagation();
|
|
2036
|
-
dragDepth.current--;
|
|
2037
|
-
if (dragDepth.current <= 0) {
|
|
2038
|
-
dragDepth.current = 0;
|
|
2039
|
-
setDragOver(false);
|
|
2040
|
-
}
|
|
2041
|
-
}, []);
|
|
2042
|
-
const handleDragOver = useCallback3((e) => {
|
|
2043
|
-
e.preventDefault();
|
|
2044
|
-
e.stopPropagation();
|
|
2045
|
-
if (e.dataTransfer) e.dataTransfer.dropEffect = "copy";
|
|
2046
|
-
}, []);
|
|
2047
|
-
const handleDrop = useCallback3(
|
|
2048
|
-
(e) => {
|
|
2049
|
-
e.preventDefault();
|
|
2050
|
-
e.stopPropagation();
|
|
2051
|
-
dragDepth.current = 0;
|
|
2052
|
-
setDragOver(false);
|
|
2053
|
-
const files = e.dataTransfer?.files;
|
|
2054
|
-
if (files?.length) deliverFiles(Array.from(files), files);
|
|
2055
|
-
},
|
|
2056
|
-
[deliverFiles]
|
|
2057
|
-
);
|
|
2058
|
-
const folderChips = pendingFiles.filter((f) => f.kind === "folder");
|
|
2059
|
-
const fileChips = pendingFiles.filter((f) => f.kind !== "folder");
|
|
2060
|
-
const showAbove = controls != null && controlsPlacement === "above";
|
|
2061
|
-
const showInline = controls != null && !showAbove;
|
|
2062
|
-
const inputMinHeight = minRows * LINE_HEIGHT + TEXTAREA_PADDING_Y;
|
|
2063
|
-
return /* @__PURE__ */ jsxs5(
|
|
2064
|
-
"div",
|
|
2065
|
-
{
|
|
2066
|
-
className: `relative ${className ?? ""}`,
|
|
2067
|
-
onDragEnter: onAttach ? handleDragEnter : void 0,
|
|
2068
|
-
onDragLeave: onAttach ? handleDragLeave : void 0,
|
|
2069
|
-
onDragOver: onAttach ? handleDragOver : void 0,
|
|
2070
|
-
onDrop: onAttach ? handleDrop : void 0,
|
|
2071
|
-
children: [
|
|
2072
|
-
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: [
|
|
2073
|
-
/* @__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" }) }),
|
|
2074
|
-
/* @__PURE__ */ jsx7("p", { className: "text-sm font-semibold text-foreground", children: dropTitle }),
|
|
2075
|
-
/* @__PURE__ */ jsx7("p", { className: "mt-0.5 text-xs text-muted-foreground", children: dropDescription })
|
|
2076
|
-
] }) }),
|
|
2077
|
-
showAbove && /* @__PURE__ */ jsx7("div", { className: "mb-1.5 flex flex-wrap items-center gap-1.5 px-1", children: controls }),
|
|
2078
|
-
dictateError && /* @__PURE__ */ jsxs5(
|
|
2079
|
-
"div",
|
|
2080
|
-
{
|
|
2081
|
-
role: "alert",
|
|
2082
|
-
"data-testid": "composer-dictate-error",
|
|
2083
|
-
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",
|
|
2084
|
-
children: [
|
|
2085
|
-
/* @__PURE__ */ jsx7("span", { className: "min-w-0 flex-1", children: dictateError }),
|
|
2086
|
-
/* @__PURE__ */ jsx7(
|
|
2087
|
-
"button",
|
|
2088
|
-
{
|
|
2089
|
-
type: "button",
|
|
2090
|
-
"aria-label": "Dismiss dictation error",
|
|
2091
|
-
onClick: () => setDictateError(null),
|
|
2092
|
-
className: "shrink-0 font-medium underline-offset-2 hover:underline focus:outline-none focus-visible:ring-2 focus-visible:ring-destructive/50",
|
|
2093
|
-
children: "Dismiss"
|
|
2094
|
-
}
|
|
2095
|
-
)
|
|
2096
|
-
]
|
|
2097
|
-
}
|
|
2098
|
-
),
|
|
2099
|
-
failedSend && /* @__PURE__ */ jsxs5(
|
|
2100
|
-
"div",
|
|
2101
|
-
{
|
|
2102
|
-
role: "alert",
|
|
2103
|
-
"data-testid": "composer-send-error",
|
|
2104
|
-
className: "mb-2 rounded-xl border border-destructive/40 bg-destructive/10 px-3 py-2 text-xs text-destructive",
|
|
2105
|
-
children: [
|
|
2106
|
-
/* @__PURE__ */ jsxs5("div", { className: "flex items-start gap-2", children: [
|
|
2107
|
-
/* @__PURE__ */ jsx7("span", { className: "min-w-0 flex-1", children: failedSend.message }),
|
|
2108
|
-
/* @__PURE__ */ jsx7(
|
|
2109
|
-
"button",
|
|
2110
|
-
{
|
|
2111
|
-
type: "button",
|
|
2112
|
-
"aria-label": "Dismiss send error",
|
|
2113
|
-
onClick: () => setFailedSend(null),
|
|
2114
|
-
className: "shrink-0 font-medium underline-offset-2 hover:underline focus:outline-none focus-visible:ring-2 focus-visible:ring-destructive/50",
|
|
2115
|
-
children: "Dismiss"
|
|
2116
|
-
}
|
|
2117
|
-
)
|
|
2118
|
-
] }),
|
|
2119
|
-
!failedSend.restored && /* @__PURE__ */ jsxs5("div", { className: "mt-1.5", children: [
|
|
2120
|
-
/* @__PURE__ */ jsx7(
|
|
2121
|
-
"p",
|
|
2122
|
-
{
|
|
2123
|
-
"data-testid": "composer-unsent-draft",
|
|
2124
|
-
className: "max-h-20 overflow-y-auto whitespace-pre-wrap rounded-lg border border-destructive/30 bg-card px-2 py-1 text-foreground",
|
|
2125
|
-
children: failedSend.text
|
|
2126
|
-
}
|
|
2127
|
-
),
|
|
2128
|
-
/* @__PURE__ */ jsx7(
|
|
2129
|
-
"button",
|
|
2130
|
-
{
|
|
2131
|
-
type: "button",
|
|
2132
|
-
"aria-label": "Retry sending the unsent message",
|
|
2133
|
-
onClick: retryFailedSend,
|
|
2134
|
-
disabled: sendBlockedByStream || disabled,
|
|
2135
|
-
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",
|
|
2136
|
-
children: "Retry"
|
|
2137
|
-
}
|
|
2138
|
-
)
|
|
2139
|
-
] })
|
|
2140
|
-
]
|
|
2141
|
-
}
|
|
2142
|
-
),
|
|
2143
|
-
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(
|
|
2144
|
-
"span",
|
|
2145
|
-
{
|
|
2146
|
-
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",
|
|
2147
|
-
children: [
|
|
2148
|
-
item.icon && /* @__PURE__ */ jsx7("span", { className: "shrink-0", "aria-hidden": true, children: item.icon }),
|
|
2149
|
-
/* @__PURE__ */ jsx7("span", { className: "min-w-0 truncate", children: item.label }),
|
|
2150
|
-
item.onRemove && /* @__PURE__ */ jsx7(
|
|
2151
|
-
"button",
|
|
2152
|
-
{
|
|
2153
|
-
type: "button",
|
|
2154
|
-
"aria-label": `Remove context ${item.label}`,
|
|
2155
|
-
onClick: item.onRemove,
|
|
2156
|
-
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",
|
|
2157
|
-
children: /* @__PURE__ */ jsx7(CloseGlyph, { className: "h-3 w-3" })
|
|
2158
|
-
}
|
|
2159
|
-
)
|
|
2160
|
-
]
|
|
2161
|
-
},
|
|
2162
|
-
item.id
|
|
2163
|
-
)) }),
|
|
2164
|
-
pendingFiles.length > 0 && /* @__PURE__ */ jsx7("div", { className: "mb-2 flex flex-wrap gap-1.5", children: [...folderChips, ...fileChips].map((f) => {
|
|
2165
|
-
const isError = f.status === "error";
|
|
2166
|
-
return /* @__PURE__ */ jsxs5(
|
|
2167
|
-
"span",
|
|
2168
|
-
{
|
|
2169
|
-
title: isError ? f.errorMessage : void 0,
|
|
2170
|
-
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" : ""}`,
|
|
2171
|
-
children: [
|
|
2172
|
-
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" }),
|
|
2173
|
-
/* @__PURE__ */ jsx7("span", { className: "max-w-[150px] truncate", children: f.name }),
|
|
2174
|
-
f.fileCount !== void 0 && /* @__PURE__ */ jsxs5("span", { className: "text-muted-foreground", children: [
|
|
2175
|
-
"(",
|
|
2176
|
-
f.fileCount,
|
|
2177
|
-
")"
|
|
2178
|
-
] }),
|
|
2179
|
-
f.status === "uploading" && /* @__PURE__ */ jsx7("span", { className: "h-3 w-3 animate-spin rounded-full border-2 border-primary border-t-transparent" }),
|
|
2180
|
-
isError && f.errorMessage && /* @__PURE__ */ jsx7("span", { className: "max-w-[150px] truncate text-destructive/80", children: f.errorMessage }),
|
|
2181
|
-
isError && onRetryFile && /* @__PURE__ */ jsx7(
|
|
2182
|
-
"button",
|
|
2183
|
-
{
|
|
2184
|
-
type: "button",
|
|
2185
|
-
"aria-label": `Retry upload ${f.name}`,
|
|
2186
|
-
onClick: () => onRetryFile(f.id),
|
|
2187
|
-
className: "rounded p-0.5 text-muted-foreground transition hover:text-foreground focus:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
2188
|
-
children: /* @__PURE__ */ jsx7(RetryGlyph, { className: "h-3 w-3" })
|
|
2189
|
-
}
|
|
2190
|
-
),
|
|
2191
|
-
onRemoveFile && /* @__PURE__ */ jsx7(
|
|
2192
|
-
"button",
|
|
2193
|
-
{
|
|
2194
|
-
type: "button",
|
|
2195
|
-
"aria-label": `Remove ${f.name}`,
|
|
2196
|
-
onClick: () => onRemoveFile(f.id),
|
|
2197
|
-
className: "rounded p-0.5 text-muted-foreground transition hover:text-foreground focus:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
2198
|
-
children: /* @__PURE__ */ jsx7(CloseGlyph, { className: "h-3 w-3" })
|
|
2199
|
-
}
|
|
2200
|
-
)
|
|
2201
|
-
]
|
|
2202
|
-
},
|
|
2203
|
-
f.id
|
|
2204
|
-
);
|
|
2205
|
-
}) }),
|
|
2206
|
-
/* @__PURE__ */ jsxs5(
|
|
2207
|
-
"div",
|
|
2208
|
-
{
|
|
2209
|
-
ref: cardRef,
|
|
2210
|
-
"data-testid": "composer-card",
|
|
2211
|
-
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" : ""}`,
|
|
2212
|
-
children: [
|
|
2213
|
-
mention ? (
|
|
2214
|
-
// The editor arrives as a lazy chunk; until it lands, a read-only
|
|
2215
|
-
// textarea with the same metrics holds the layout so the card
|
|
2216
|
-
// doesn't jump. The boundary contains a failed load (e.g. the
|
|
2217
|
-
// missing-peer error) to the input area instead of unmounting the
|
|
2218
|
-
// host's region.
|
|
2219
|
-
/* @__PURE__ */ jsx7(
|
|
2220
|
-
MentionEditorBoundary,
|
|
2221
|
-
{
|
|
2222
|
-
onRetry: () => {
|
|
2223
|
-
setEditorFailed(false);
|
|
2224
|
-
setEditorEpoch((epoch) => epoch + 1);
|
|
2225
|
-
},
|
|
2226
|
-
onFailed: () => setEditorFailed(true),
|
|
2227
|
-
draft: text,
|
|
2228
|
-
children: /* @__PURE__ */ jsx7(
|
|
2229
|
-
Suspense2,
|
|
2230
|
-
{
|
|
2231
|
-
fallback: /* @__PURE__ */ jsx7(
|
|
2232
|
-
"textarea",
|
|
2233
|
-
{
|
|
2234
|
-
rows: minRows,
|
|
2235
|
-
value: text,
|
|
2236
|
-
readOnly: true,
|
|
2237
|
-
disabled: true,
|
|
2238
|
-
placeholder,
|
|
2239
|
-
"aria-label": "Message input",
|
|
2240
|
-
style: { minHeight: inputMinHeight, maxHeight },
|
|
2241
|
-
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"
|
|
2242
|
-
}
|
|
2243
|
-
),
|
|
2244
|
-
children: /* @__PURE__ */ jsx7(
|
|
2245
|
-
MentionEditor,
|
|
2246
|
-
{
|
|
2247
|
-
value: text,
|
|
2248
|
-
onChange: setText,
|
|
2249
|
-
onSubmit: send,
|
|
2250
|
-
placeholder,
|
|
2251
|
-
disabled,
|
|
2252
|
-
autoFocus,
|
|
2253
|
-
minHeight: inputMinHeight,
|
|
2254
|
-
maxHeight,
|
|
2255
|
-
mention,
|
|
2256
|
-
registerFocus: registerRichFocus,
|
|
2257
|
-
onPasteFiles: onAttach ? ingestPastedFiles : void 0
|
|
2258
|
-
}
|
|
2259
|
-
)
|
|
2260
|
-
}
|
|
2261
|
-
)
|
|
2262
|
-
},
|
|
2263
|
-
editorEpoch
|
|
2264
|
-
)
|
|
2265
|
-
) : (
|
|
2266
|
-
// Focus: `outline-none` is safe because the card above draws the
|
|
2267
|
-
// keyboard indicator through `focus-within:` — one ring for
|
|
2268
|
-
// whichever input mode is mounted.
|
|
2269
|
-
/* @__PURE__ */ jsx7(
|
|
2270
|
-
"textarea",
|
|
2271
|
-
{
|
|
2272
|
-
ref: textareaRef,
|
|
2273
|
-
value: text,
|
|
2274
|
-
onChange: (e) => setText(e.target.value),
|
|
2275
|
-
onKeyDown: handleKeyDown,
|
|
2276
|
-
onPaste: onAttach ? handlePaste : void 0,
|
|
2277
|
-
placeholder,
|
|
2278
|
-
disabled,
|
|
2279
|
-
autoFocus,
|
|
2280
|
-
rows: minRows,
|
|
2281
|
-
style: { minHeight: inputMinHeight, maxHeight },
|
|
2282
|
-
"aria-label": "Message input",
|
|
2283
|
-
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"
|
|
2284
|
-
}
|
|
2285
|
-
)
|
|
2286
|
-
),
|
|
2287
|
-
/* @__PURE__ */ jsxs5("div", { className: "flex items-end gap-2", children: [
|
|
2288
|
-
onAttach && /* @__PURE__ */ jsxs5(Fragment2, { children: [
|
|
2289
|
-
/* @__PURE__ */ jsx7(
|
|
2290
|
-
"button",
|
|
2291
|
-
{
|
|
2292
|
-
type: "button",
|
|
2293
|
-
onClick: () => fileInputRef.current?.click(),
|
|
2294
|
-
disabled,
|
|
2295
|
-
"aria-label": "Attach files",
|
|
2296
|
-
title: "Attach files",
|
|
2297
|
-
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",
|
|
2298
|
-
children: /* @__PURE__ */ jsx7(PaperclipGlyph, { className: "h-4 w-4" })
|
|
2299
|
-
}
|
|
2300
|
-
),
|
|
2301
|
-
/* @__PURE__ */ jsx7("input", { ref: fileInputRef, type: "file", multiple: true, className: "hidden", accept, onChange: handleFileChange })
|
|
2302
|
-
] }),
|
|
2303
|
-
onAttachFolder && /* @__PURE__ */ jsxs5(Fragment2, { children: [
|
|
2304
|
-
/* @__PURE__ */ jsx7(
|
|
2305
|
-
"button",
|
|
2306
|
-
{
|
|
2307
|
-
type: "button",
|
|
2308
|
-
onClick: () => folderInputRef.current?.click(),
|
|
2309
|
-
disabled,
|
|
2310
|
-
"aria-label": "Attach folder",
|
|
2311
|
-
title: "Attach folder",
|
|
2312
|
-
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",
|
|
2313
|
-
children: /* @__PURE__ */ jsx7(FolderGlyph, { className: "h-4 w-4" })
|
|
2314
|
-
}
|
|
2315
|
-
),
|
|
2316
|
-
/* @__PURE__ */ jsx7(
|
|
2317
|
-
"input",
|
|
2318
|
-
{
|
|
2319
|
-
ref: folderInputRef,
|
|
2320
|
-
type: "file",
|
|
2321
|
-
multiple: true,
|
|
2322
|
-
className: "hidden",
|
|
2323
|
-
onChange: handleFolderChange,
|
|
2324
|
-
...{ webkitdirectory: "" }
|
|
2325
|
-
}
|
|
2326
|
-
)
|
|
2327
|
-
] }),
|
|
2328
|
-
/* @__PURE__ */ jsx7(
|
|
2329
|
-
"div",
|
|
2330
|
-
{
|
|
2331
|
-
"data-testid": "composer-controls",
|
|
2332
|
-
className: "flex min-w-0 flex-1 flex-wrap items-center gap-1.5",
|
|
2333
|
-
children: showInline && controls
|
|
2334
|
-
}
|
|
2335
|
-
),
|
|
2336
|
-
trailing && /* @__PURE__ */ jsx7("div", { "data-testid": "composer-trailing", className: "flex shrink-0 items-center gap-1.5", children: trailing }),
|
|
2337
|
-
onDictate && dictation.supported ? dictation.recording ? /* @__PURE__ */ jsxs5("div", { className: "flex shrink-0 items-center gap-1.5", children: [
|
|
2338
|
-
/* @__PURE__ */ jsx7("span", { "aria-hidden": "true", className: "h-2 w-2 animate-pulse rounded-full bg-destructive" }),
|
|
2339
|
-
/* @__PURE__ */ jsx7(
|
|
2340
|
-
"span",
|
|
2341
|
-
{
|
|
2342
|
-
"aria-hidden": "true",
|
|
2343
|
-
"data-testid": "composer-dictate-elapsed",
|
|
2344
|
-
className: "text-xs tabular-nums text-muted-foreground",
|
|
2345
|
-
children: formatDictationElapsed(dictation.elapsedSeconds)
|
|
2346
|
-
}
|
|
2347
|
-
),
|
|
2348
|
-
/* @__PURE__ */ jsx7("span", { role: "status", className: "sr-only", children: "Recording" }),
|
|
2349
|
-
/* @__PURE__ */ jsx7(
|
|
2350
|
-
"button",
|
|
2351
|
-
{
|
|
2352
|
-
type: "button",
|
|
2353
|
-
onClick: dictation.stop,
|
|
2354
|
-
"aria-label": "Stop dictation",
|
|
2355
|
-
title: "Stop dictation",
|
|
2356
|
-
className: "shrink-0 rounded-lg p-2 text-destructive transition hover:bg-accent focus:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
2357
|
-
children: /* @__PURE__ */ jsx7(StopGlyph, { className: "h-4 w-4" })
|
|
2358
|
-
}
|
|
2359
|
-
)
|
|
2360
|
-
] }) : /* @__PURE__ */ jsx7(
|
|
2361
|
-
"button",
|
|
2362
|
-
{
|
|
2363
|
-
type: "button",
|
|
2364
|
-
onClick: dictation.start,
|
|
2365
|
-
disabled,
|
|
2366
|
-
"aria-label": "Dictate message",
|
|
2367
|
-
title: "Dictate message",
|
|
2368
|
-
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",
|
|
2369
|
-
children: /* @__PURE__ */ jsx7(MicGlyph, { className: "h-4 w-4" })
|
|
2370
|
-
}
|
|
2371
|
-
) : null,
|
|
2372
|
-
isStreaming ? sendVariant === "icon" ? /* @__PURE__ */ jsx7(
|
|
2373
|
-
"button",
|
|
2374
|
-
{
|
|
2375
|
-
type: "button",
|
|
2376
|
-
onClick: onCancel,
|
|
2377
|
-
"aria-label": "Stop response",
|
|
2378
|
-
title: "Stop",
|
|
2379
|
-
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",
|
|
2380
|
-
children: /* @__PURE__ */ jsx7(StopGlyph, { className: "h-3 w-3" })
|
|
2381
|
-
}
|
|
2382
|
-
) : /* @__PURE__ */ jsxs5(
|
|
2383
|
-
"button",
|
|
2384
|
-
{
|
|
2385
|
-
type: "button",
|
|
2386
|
-
onClick: onCancel,
|
|
2387
|
-
"aria-label": "Stop response",
|
|
2388
|
-
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",
|
|
2389
|
-
children: [
|
|
2390
|
-
/* @__PURE__ */ jsx7(StopGlyph, { className: "h-3.5 w-3.5" }),
|
|
2391
|
-
/* @__PURE__ */ jsx7("span", { children: "Stop" })
|
|
2392
|
-
]
|
|
2393
|
-
}
|
|
2394
|
-
) : sendVariant === "icon" ? /* @__PURE__ */ jsx7(
|
|
2395
|
-
"button",
|
|
2396
|
-
{
|
|
2397
|
-
type: "button",
|
|
2398
|
-
onClick: send,
|
|
2399
|
-
disabled: !canSend,
|
|
2400
|
-
"aria-label": sendLabel,
|
|
2401
|
-
title: sendLabel,
|
|
2402
|
-
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",
|
|
2403
|
-
children: /* @__PURE__ */ jsx7(ArrowUpGlyph, { className: "h-4 w-4" })
|
|
2404
|
-
}
|
|
2405
|
-
) : /* @__PURE__ */ jsxs5(
|
|
2406
|
-
"button",
|
|
2407
|
-
{
|
|
2408
|
-
type: "button",
|
|
2409
|
-
onClick: send,
|
|
2410
|
-
disabled: !canSend,
|
|
2411
|
-
"aria-label": sendLabel,
|
|
2412
|
-
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",
|
|
2413
|
-
children: [
|
|
2414
|
-
/* @__PURE__ */ jsx7(SendGlyph, { className: "h-3.5 w-3.5" }),
|
|
2415
|
-
/* @__PURE__ */ jsx7("span", { children: sendLabel })
|
|
2416
|
-
]
|
|
2417
|
-
}
|
|
2418
|
-
)
|
|
2419
|
-
] })
|
|
2420
|
-
]
|
|
2421
|
-
}
|
|
2422
|
-
),
|
|
2423
|
-
/* @__PURE__ */ jsxs5(
|
|
2424
|
-
PopoverSurface,
|
|
2425
|
-
{
|
|
2426
|
-
open: slashOpen,
|
|
2427
|
-
id: slashListId,
|
|
2428
|
-
role: "listbox",
|
|
2429
|
-
triggerRef: textareaRef,
|
|
2430
|
-
panelRef: slashPanelRef,
|
|
2431
|
-
className: `w-80 overflow-y-auto rounded-xl border border-card-edge bg-popover p-1 ${OVERLAY_SHADOW}`,
|
|
2432
|
-
children: [
|
|
2433
|
-
slashFiltered.length === 0 && /* @__PURE__ */ jsx7("div", { className: "px-3 py-4 text-center text-sm text-muted-foreground", children: "No matching commands" }),
|
|
2434
|
-
slashFiltered.map((item, index) => /* @__PURE__ */ jsxs5(
|
|
2435
|
-
"button",
|
|
2436
|
-
{
|
|
2437
|
-
type: "button",
|
|
2438
|
-
role: "option",
|
|
2439
|
-
"aria-selected": index === slashActiveIndex,
|
|
2440
|
-
id: `${slashListId}-${index}`,
|
|
2441
|
-
onMouseDown: (e) => e.preventDefault(),
|
|
2442
|
-
onMouseMove: () => setSlashActive(index),
|
|
2443
|
-
onClick: () => pickSlash(item.id),
|
|
2444
|
-
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"}`,
|
|
2445
|
-
children: [
|
|
2446
|
-
/* @__PURE__ */ jsx7("span", { className: "shrink-0 font-medium text-foreground", children: item.label }),
|
|
2447
|
-
/* @__PURE__ */ jsx7("span", { className: "truncate text-xs text-muted-foreground", children: item.description })
|
|
2448
|
-
]
|
|
2449
|
-
},
|
|
2450
|
-
item.id
|
|
2451
|
-
))
|
|
2452
|
-
]
|
|
2453
|
-
}
|
|
2454
|
-
),
|
|
2455
|
-
focusShortcut && /* @__PURE__ */ jsx7("div", { className: "mt-1.5 flex justify-end px-1", children: /* @__PURE__ */ jsxs5("span", { className: "text-xs text-muted-foreground", children: [
|
|
2456
|
-
/* @__PURE__ */ jsx7("kbd", { className: "rounded border border-border bg-background px-1 py-0.5 text-xs", children: IS_APPLE_PLATFORM ? "Cmd" : "Ctrl" }),
|
|
2457
|
-
/* @__PURE__ */ jsx7("kbd", { className: "ml-0.5 rounded border border-border bg-background px-1 py-0.5 text-xs", children: "L" }),
|
|
2458
|
-
/* @__PURE__ */ jsx7("span", { className: "ml-1", children: "to focus" })
|
|
2459
|
-
] }) })
|
|
2460
|
-
]
|
|
2461
|
-
}
|
|
2462
|
-
);
|
|
2463
|
-
}
|
|
2464
|
-
|
|
2465
1418
|
// src/web-react/durable-plan-flow.ts
|
|
2466
|
-
import { useCallback as
|
|
1419
|
+
import { useCallback as useCallback2, useEffect as useEffect5, useRef as useRef5, useState as useState7 } from "react";
|
|
2467
1420
|
var DurablePlanClientError = class extends Error {
|
|
2468
1421
|
constructor(message, status, code, currentPlan) {
|
|
2469
1422
|
super(message);
|
|
@@ -2550,14 +1503,14 @@ function createDurablePlanDecisionClient(options) {
|
|
|
2550
1503
|
};
|
|
2551
1504
|
}
|
|
2552
1505
|
function useDurablePlanFlow(options) {
|
|
2553
|
-
const [plan, setPlan] =
|
|
2554
|
-
const [deciding, setDeciding] =
|
|
2555
|
-
const [restoring, setRestoring] =
|
|
2556
|
-
const [error, setError] =
|
|
2557
|
-
const attachments =
|
|
2558
|
-
const decisionInFlight =
|
|
2559
|
-
|
|
2560
|
-
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) => {
|
|
2561
1514
|
setPlan(result.plan);
|
|
2562
1515
|
options.onUpdated?.(result.plan);
|
|
2563
1516
|
const receipt = result.followUp;
|
|
@@ -2570,7 +1523,7 @@ function useDurablePlanFlow(options) {
|
|
|
2570
1523
|
}
|
|
2571
1524
|
await pending;
|
|
2572
1525
|
}, [options.attachFollowUp, options.onUpdated]);
|
|
2573
|
-
const decide =
|
|
1526
|
+
const decide = useCallback2(async (decision, feedback) => {
|
|
2574
1527
|
if (decisionInFlight.current) return null;
|
|
2575
1528
|
decisionInFlight.current = true;
|
|
2576
1529
|
setDeciding(decision);
|
|
@@ -2596,7 +1549,7 @@ function useDurablePlanFlow(options) {
|
|
|
2596
1549
|
setDeciding(null);
|
|
2597
1550
|
}
|
|
2598
1551
|
}, [apply, options.client, options.onUpdated, plan.planId, plan.revision]);
|
|
2599
|
-
const restore =
|
|
1552
|
+
const restore = useCallback2(async () => {
|
|
2600
1553
|
setRestoring(true);
|
|
2601
1554
|
setError(null);
|
|
2602
1555
|
try {
|
|
@@ -2725,7 +1678,7 @@ function createDurableInteractionAnswerSubmitter(options) {
|
|
|
2725
1678
|
}
|
|
2726
1679
|
|
|
2727
1680
|
// src/web-react/use-chat-interactions.ts
|
|
2728
|
-
import { useCallback as
|
|
1681
|
+
import { useCallback as useCallback3, useMemo as useMemo3, useState as useState8 } from "react";
|
|
2729
1682
|
function hasPendingContentDuplicate(list, interaction) {
|
|
2730
1683
|
if (interaction.status !== "pending") return false;
|
|
2731
1684
|
const signature = questionInteractionContentSignature(interaction);
|
|
@@ -2804,34 +1757,34 @@ function hydrateChatInteractions(list, persisted) {
|
|
|
2804
1757
|
return persisted.reduce(upsertChatInteraction, list);
|
|
2805
1758
|
}
|
|
2806
1759
|
function useChatInteractions(options = {}) {
|
|
2807
|
-
const [interactions, setInteractions] =
|
|
2808
|
-
const upsert =
|
|
1760
|
+
const [interactions, setInteractions] = useState8([]);
|
|
1761
|
+
const upsert = useCallback3((interaction) => {
|
|
2809
1762
|
setInteractions((prev) => upsertChatInteraction(prev, interaction));
|
|
2810
1763
|
}, []);
|
|
2811
|
-
const applyCancel =
|
|
1764
|
+
const applyCancel = useCallback3((cancel) => {
|
|
2812
1765
|
setInteractions((prev) => cancelChatInteraction(prev, cancel));
|
|
2813
1766
|
}, []);
|
|
2814
|
-
const markResolved =
|
|
1767
|
+
const markResolved = useCallback3((id, status, answers) => {
|
|
2815
1768
|
setInteractions((prev) => resolveChatInteraction(prev, id, status, answers));
|
|
2816
1769
|
}, []);
|
|
2817
|
-
const restore =
|
|
1770
|
+
const restore = useCallback3((outstanding, restoreOptions) => {
|
|
2818
1771
|
setInteractions((prev) => restoreChatInteractions(prev, outstanding, {
|
|
2819
1772
|
mode: restoreOptions?.mode ?? options.mode
|
|
2820
1773
|
}));
|
|
2821
1774
|
}, [options.mode]);
|
|
2822
|
-
const hydrate =
|
|
1775
|
+
const hydrate = useCallback3((persisted) => {
|
|
2823
1776
|
setInteractions((prev) => hydrateChatInteractions(prev, persisted));
|
|
2824
1777
|
}, []);
|
|
2825
|
-
const terminalizePending =
|
|
1778
|
+
const terminalizePending = useCallback3((status) => {
|
|
2826
1779
|
setInteractions((prev) => terminalizePendingChatInteractions(prev, status));
|
|
2827
1780
|
}, []);
|
|
2828
|
-
const reset =
|
|
2829
|
-
const pending =
|
|
1781
|
+
const reset = useCallback3(() => setInteractions([]), []);
|
|
1782
|
+
const pending = useMemo3(() => interactions.filter((item) => item.status === "pending"), [interactions]);
|
|
2830
1783
|
return { interactions, pending, upsert, applyCancel, markResolved, restore, hydrate, terminalizePending, reset };
|
|
2831
1784
|
}
|
|
2832
1785
|
|
|
2833
1786
|
// src/web-react/use-file-mentions.ts
|
|
2834
|
-
import { useCallback as
|
|
1787
|
+
import { useCallback as useCallback4, useMemo as useMemo4, useRef as useRef6, useState as useState9 } from "react";
|
|
2835
1788
|
var FILE_MENTION_KIND = "file";
|
|
2836
1789
|
function toMentionItem(file) {
|
|
2837
1790
|
return { id: file.path, label: file.name, detail: file.path, kind: FILE_MENTION_KIND };
|
|
@@ -2889,12 +1842,12 @@ function useFileMentions(options) {
|
|
|
2889
1842
|
emptyText = DEFAULT_MENTION_EMPTY_TEXT
|
|
2890
1843
|
} = options;
|
|
2891
1844
|
const fetchImpl = options.fetchImpl ?? fetch;
|
|
2892
|
-
const [state, setState] =
|
|
2893
|
-
const stateRef =
|
|
1845
|
+
const [state, setState] = useState9({ kind: "idle" });
|
|
1846
|
+
const stateRef = useRef6(state);
|
|
2894
1847
|
stateRef.current = state;
|
|
2895
|
-
const inFlightRef =
|
|
2896
|
-
const [mentions, setMentions] =
|
|
2897
|
-
const load =
|
|
1848
|
+
const inFlightRef = useRef6(null);
|
|
1849
|
+
const [mentions, setMentions] = useState9([]);
|
|
1850
|
+
const load = useCallback4(() => {
|
|
2898
1851
|
if (inFlightRef.current) return inFlightRef.current;
|
|
2899
1852
|
if (stateRef.current.kind === "idle") {
|
|
2900
1853
|
stateRef.current = { kind: "loading" };
|
|
@@ -2926,10 +1879,10 @@ function useFileMentions(options) {
|
|
|
2926
1879
|
inFlightRef.current = attempt;
|
|
2927
1880
|
return attempt;
|
|
2928
1881
|
}, [fetchImpl, indexUrl]);
|
|
2929
|
-
const refresh =
|
|
1882
|
+
const refresh = useCallback4(async () => {
|
|
2930
1883
|
await load();
|
|
2931
1884
|
}, [load]);
|
|
2932
|
-
const fetchItems =
|
|
1885
|
+
const fetchItems = useCallback4(
|
|
2933
1886
|
async (query) => {
|
|
2934
1887
|
let current = stateRef.current;
|
|
2935
1888
|
if (current.kind === "idle" || current.kind === "loading") {
|
|
@@ -2944,11 +1897,11 @@ function useFileMentions(options) {
|
|
|
2944
1897
|
},
|
|
2945
1898
|
[load, limit, refreshAfterMs]
|
|
2946
1899
|
);
|
|
2947
|
-
const onMentionsChange =
|
|
1900
|
+
const onMentionsChange = useCallback4((items) => {
|
|
2948
1901
|
setMentions(items.filter((item) => item.kind === void 0 || item.kind === FILE_MENTION_KIND).map(toFileMention));
|
|
2949
1902
|
}, []);
|
|
2950
|
-
const clearMentions =
|
|
2951
|
-
const mention =
|
|
1903
|
+
const clearMentions = useCallback4(() => setMentions([]), []);
|
|
1904
|
+
const mention = useMemo4(
|
|
2952
1905
|
() => ({
|
|
2953
1906
|
fetchItems,
|
|
2954
1907
|
onMentionsChange,
|
|
@@ -3000,8 +1953,8 @@ function segmentMentionContent(content, parts) {
|
|
|
3000
1953
|
}
|
|
3001
1954
|
|
|
3002
1955
|
// src/web-react/mission-activity.tsx
|
|
3003
|
-
import { useCallback as
|
|
3004
|
-
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";
|
|
3005
1958
|
var LIVE_STATUSES = /* @__PURE__ */ new Set(["pending", "running"]);
|
|
3006
1959
|
var OK_STATUSES = /* @__PURE__ */ new Set(["completed", "done", "succeeded"]);
|
|
3007
1960
|
var ERROR_STATUSES = /* @__PURE__ */ new Set(["failed", "error", "cancelled", "aborted"]);
|
|
@@ -3048,20 +2001,20 @@ function waterfallLayout(trace) {
|
|
|
3048
2001
|
});
|
|
3049
2002
|
}
|
|
3050
2003
|
function ChevronGlyph({ className }) {
|
|
3051
|
-
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" }) });
|
|
3052
2005
|
}
|
|
3053
2006
|
function RefreshGlyph({ className }) {
|
|
3054
|
-
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" }) });
|
|
3055
2008
|
}
|
|
3056
2009
|
function CopyGlyph({ className }) {
|
|
3057
|
-
return /* @__PURE__ */
|
|
3058
|
-
/* @__PURE__ */
|
|
3059
|
-
/* @__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" })
|
|
3060
2013
|
] });
|
|
3061
2014
|
}
|
|
3062
2015
|
function TraceIdCopy({ traceId }) {
|
|
3063
|
-
const [copied, setCopied] =
|
|
3064
|
-
const copy =
|
|
2016
|
+
const [copied, setCopied] = useState10(false);
|
|
2017
|
+
const copy = useCallback5(() => {
|
|
3065
2018
|
void navigator.clipboard?.writeText(traceId).then(
|
|
3066
2019
|
() => {
|
|
3067
2020
|
setCopied(true);
|
|
@@ -3071,7 +2024,7 @@ function TraceIdCopy({ traceId }) {
|
|
|
3071
2024
|
}
|
|
3072
2025
|
);
|
|
3073
2026
|
}, [traceId]);
|
|
3074
|
-
return /* @__PURE__ */
|
|
2027
|
+
return /* @__PURE__ */ jsxs5(
|
|
3075
2028
|
"button",
|
|
3076
2029
|
{
|
|
3077
2030
|
type: "button",
|
|
@@ -3080,29 +2033,29 @@ function TraceIdCopy({ traceId }) {
|
|
|
3080
2033
|
"aria-label": "Copy trace id",
|
|
3081
2034
|
className: "inline-flex min-w-0 items-center gap-1.5 rounded text-left font-mono text-muted-foreground transition hover:text-foreground",
|
|
3082
2035
|
children: [
|
|
3083
|
-
/* @__PURE__ */
|
|
3084
|
-
/* @__PURE__ */
|
|
3085
|
-
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" })
|
|
3086
2039
|
]
|
|
3087
2040
|
}
|
|
3088
2041
|
);
|
|
3089
2042
|
}
|
|
3090
2043
|
function StatusDot({ tone }) {
|
|
3091
|
-
return /* @__PURE__ */
|
|
3092
|
-
/* @__PURE__ */
|
|
2044
|
+
return /* @__PURE__ */ jsxs5("span", { className: "inline-flex items-center", children: [
|
|
2045
|
+
/* @__PURE__ */ jsx7(
|
|
3093
2046
|
"span",
|
|
3094
2047
|
{
|
|
3095
2048
|
"aria-hidden": true,
|
|
3096
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"}`
|
|
3097
2050
|
}
|
|
3098
2051
|
),
|
|
3099
|
-
/* @__PURE__ */
|
|
2052
|
+
/* @__PURE__ */ jsx7("span", { className: "sr-only", children: tone })
|
|
3100
2053
|
] });
|
|
3101
2054
|
}
|
|
3102
2055
|
function RunLabel({ tool, detail, live }) {
|
|
3103
|
-
return /* @__PURE__ */
|
|
3104
|
-
/* @__PURE__ */
|
|
3105
|
-
/* @__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: [
|
|
3106
2059
|
" \u2014 ",
|
|
3107
2060
|
detail
|
|
3108
2061
|
] })
|
|
@@ -3117,19 +2070,19 @@ function FlowWaterfall({ trace }) {
|
|
|
3117
2070
|
const rows = waterfallLayout(trace);
|
|
3118
2071
|
if (rows.length === 0) return null;
|
|
3119
2072
|
const cost = formatActivityCost(trace.costUsd);
|
|
3120
|
-
return /* @__PURE__ */
|
|
3121
|
-
rows.map((row, i) => /* @__PURE__ */
|
|
3122
|
-
/* @__PURE__ */
|
|
3123
|
-
/* @__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(
|
|
3124
2077
|
"div",
|
|
3125
2078
|
{
|
|
3126
2079
|
className: `absolute inset-y-0 rounded-sm ${row.ok ? BAR_CLASS[row.kind] : "bg-destructive/80"} ${row.approx ? "opacity-70" : ""}`,
|
|
3127
2080
|
style: { left: `${row.offsetPct}%`, width: `${row.widthPct}%` }
|
|
3128
2081
|
}
|
|
3129
2082
|
) }),
|
|
3130
|
-
/* @__PURE__ */
|
|
2083
|
+
/* @__PURE__ */ jsx7("span", { className: "shrink-0 font-mono text-xs tabular-nums text-muted-foreground/70", children: row.durationLabel })
|
|
3131
2084
|
] }, i)),
|
|
3132
|
-
/* @__PURE__ */
|
|
2085
|
+
/* @__PURE__ */ jsxs5("p", { className: "pt-0.5 text-right font-mono text-xs tabular-nums text-muted-foreground/60", children: [
|
|
3133
2086
|
(trace.totalMs / 1e3).toFixed(1),
|
|
3134
2087
|
"s",
|
|
3135
2088
|
cost ? ` \xB7 ${cost}` : ""
|
|
@@ -3141,35 +2094,35 @@ function LaneRow({ run, staggerIndex }) {
|
|
|
3141
2094
|
const tone = activityTone(run.status);
|
|
3142
2095
|
const cost = formatActivityCost(run.costUsd);
|
|
3143
2096
|
const duration = formatActivityDuration(run.durationMs);
|
|
3144
|
-
return /* @__PURE__ */
|
|
3145
|
-
/* @__PURE__ */
|
|
3146
|
-
/* @__PURE__ */
|
|
3147
|
-
tone === "live" && (run.iteration !== void 0 || run.phase !== void 0) && /* @__PURE__ */
|
|
3148
|
-
/* @__PURE__ */
|
|
3149
|
-
tone !== "live" && tone !== "ok" && /* @__PURE__ */
|
|
3150
|
-
cost && /* @__PURE__ */
|
|
3151
|
-
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 })
|
|
3152
2105
|
] })
|
|
3153
2106
|
] });
|
|
3154
2107
|
}
|
|
3155
2108
|
function MissionActivityLane({ activity, startedAt, nowMs }) {
|
|
3156
|
-
const [expanded, setExpanded] =
|
|
2109
|
+
const [expanded, setExpanded] = useState10(false);
|
|
3157
2110
|
if (activity.length === 0) return null;
|
|
3158
|
-
return /* @__PURE__ */
|
|
3159
|
-
activity.map((run, index) => /* @__PURE__ */
|
|
3160
|
-
/* @__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(
|
|
3161
2114
|
"button",
|
|
3162
2115
|
{
|
|
3163
2116
|
type: "button",
|
|
3164
2117
|
onClick: () => setExpanded((v) => !v),
|
|
3165
2118
|
className: "flex items-center gap-1 py-0.5 text-xs font-medium text-muted-foreground/70 transition hover:text-foreground",
|
|
3166
2119
|
children: [
|
|
3167
|
-
/* @__PURE__ */
|
|
2120
|
+
/* @__PURE__ */ jsx7(ChevronGlyph, { className: `h-3 w-3 transition-transform ${expanded ? "rotate-180" : ""}` }),
|
|
3168
2121
|
"timeline"
|
|
3169
2122
|
]
|
|
3170
2123
|
}
|
|
3171
2124
|
),
|
|
3172
|
-
expanded && /* @__PURE__ */
|
|
2125
|
+
expanded && /* @__PURE__ */ jsx7("div", { className: "rounded-md border border-border bg-secondary p-2", children: /* @__PURE__ */ jsx7(
|
|
3173
2126
|
FlowWaterfall,
|
|
3174
2127
|
{
|
|
3175
2128
|
trace: stepActivityFlowTrace(activity, {
|
|
@@ -3186,39 +2139,39 @@ function ActivityRow({
|
|
|
3186
2139
|
staggerIndex
|
|
3187
2140
|
}) {
|
|
3188
2141
|
const arrival = useArrivalStyle(staggerIndex);
|
|
3189
|
-
const [open, setOpen] =
|
|
2142
|
+
const [open, setOpen] = useState10(false);
|
|
3190
2143
|
const tone = activityTone(record.status);
|
|
3191
2144
|
const cost = formatActivityCost(record.costUsd);
|
|
3192
2145
|
const duration = formatActivityDuration(record.durationMs);
|
|
3193
|
-
return /* @__PURE__ */
|
|
3194
|
-
/* @__PURE__ */
|
|
3195
|
-
/* @__PURE__ */
|
|
3196
|
-
/* @__PURE__ */
|
|
3197
|
-
tone === "live" && (record.iteration !== void 0 || record.phase !== void 0) && /* @__PURE__ */
|
|
3198
|
-
/* @__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(
|
|
3199
2152
|
"span",
|
|
3200
2153
|
{
|
|
3201
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"}`,
|
|
3202
2155
|
children: record.status
|
|
3203
2156
|
}
|
|
3204
2157
|
),
|
|
3205
|
-
cost && /* @__PURE__ */
|
|
3206
|
-
/* @__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" : ""}` })
|
|
3207
2160
|
] }),
|
|
3208
|
-
open && /* @__PURE__ */
|
|
3209
|
-
record.durationMs !== void 0 && /* @__PURE__ */
|
|
3210
|
-
/* @__PURE__ */
|
|
3211
|
-
/* @__PURE__ */
|
|
3212
|
-
/* @__PURE__ */
|
|
3213
|
-
/* @__PURE__ */
|
|
3214
|
-
/* @__PURE__ */
|
|
3215
|
-
duration && /* @__PURE__ */
|
|
3216
|
-
/* @__PURE__ */
|
|
3217
|
-
/* @__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 })
|
|
3218
2171
|
] }),
|
|
3219
|
-
record.traceId && /* @__PURE__ */
|
|
3220
|
-
/* @__PURE__ */
|
|
3221
|
-
/* @__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 }) })
|
|
3222
2175
|
] })
|
|
3223
2176
|
] }),
|
|
3224
2177
|
record.missionRef && renderMissionRef?.(record.missionRef, record)
|
|
@@ -3226,11 +2179,11 @@ function ActivityRow({
|
|
|
3226
2179
|
] });
|
|
3227
2180
|
}
|
|
3228
2181
|
function AgentActivityPanel({ fetchActivity, renderMissionRef, title = "Agent activity", emptyLabel = "No agent runs yet." }) {
|
|
3229
|
-
const [rows, setRows] =
|
|
3230
|
-
const [cursor, setCursor] =
|
|
3231
|
-
const [status, setStatus] =
|
|
3232
|
-
const [error, setError] =
|
|
3233
|
-
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(
|
|
3234
2187
|
async (from) => {
|
|
3235
2188
|
setStatus("loading");
|
|
3236
2189
|
setError(null);
|
|
@@ -3246,14 +2199,14 @@ function AgentActivityPanel({ fetchActivity, renderMissionRef, title = "Agent ac
|
|
|
3246
2199
|
},
|
|
3247
2200
|
[fetchActivity]
|
|
3248
2201
|
);
|
|
3249
|
-
|
|
2202
|
+
useEffect6(() => {
|
|
3250
2203
|
void load();
|
|
3251
2204
|
}, [load]);
|
|
3252
2205
|
const loading = status === "loading";
|
|
3253
|
-
return /* @__PURE__ */
|
|
3254
|
-
/* @__PURE__ */
|
|
3255
|
-
/* @__PURE__ */
|
|
3256
|
-
/* @__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(
|
|
3257
2210
|
"button",
|
|
3258
2211
|
{
|
|
3259
2212
|
type: "button",
|
|
@@ -3261,15 +2214,15 @@ function AgentActivityPanel({ fetchActivity, renderMissionRef, title = "Agent ac
|
|
|
3261
2214
|
disabled: loading,
|
|
3262
2215
|
"aria-label": "Refresh",
|
|
3263
2216
|
className: "rounded-md p-1.5 text-muted-foreground transition hover:bg-accent hover:text-foreground disabled:opacity-50",
|
|
3264
|
-
children: /* @__PURE__ */
|
|
2217
|
+
children: /* @__PURE__ */ jsx7(RefreshGlyph, { className: `h-3.5 w-3.5 ${loading ? "animate-spin" : ""}` })
|
|
3265
2218
|
}
|
|
3266
2219
|
)
|
|
3267
2220
|
] }),
|
|
3268
|
-
status === "error" && /* @__PURE__ */
|
|
3269
|
-
status === "ready" && rows.length === 0 && /* @__PURE__ */
|
|
3270
|
-
/* @__PURE__ */
|
|
3271
|
-
/* @__PURE__ */
|
|
3272
|
-
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(
|
|
3273
2226
|
"button",
|
|
3274
2227
|
{
|
|
3275
2228
|
type: "button",
|
|
@@ -3283,7 +2236,7 @@ function AgentActivityPanel({ fetchActivity, renderMissionRef, title = "Agent ac
|
|
|
3283
2236
|
}
|
|
3284
2237
|
|
|
3285
2238
|
// src/web-react/provenance.tsx
|
|
3286
|
-
import { useCallback as
|
|
2239
|
+
import { useCallback as useCallback6, useEffect as useEffect7, useId, useRef as useRef7, useState as useState11 } from "react";
|
|
3287
2240
|
|
|
3288
2241
|
// src/web-react/provenance-model.ts
|
|
3289
2242
|
var PROVENANCE_BASES = ["extracted", "entered", "computed", "asserted"];
|
|
@@ -3443,7 +2396,7 @@ function provenanceTriggerLabel(record, standing) {
|
|
|
3443
2396
|
}
|
|
3444
2397
|
|
|
3445
2398
|
// src/web-react/provenance.tsx
|
|
3446
|
-
import { jsx as
|
|
2399
|
+
import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
3447
2400
|
var BASIS_TONES = {
|
|
3448
2401
|
extracted: "border-primary/30 bg-primary/10 text-primary",
|
|
3449
2402
|
entered: "border-success/30 bg-success/10 text-success",
|
|
@@ -3468,27 +2421,27 @@ function BasisGlyph({ basis, className }) {
|
|
|
3468
2421
|
};
|
|
3469
2422
|
switch (basis) {
|
|
3470
2423
|
case "extracted":
|
|
3471
|
-
return /* @__PURE__ */
|
|
3472
|
-
/* @__PURE__ */
|
|
3473
|
-
/* @__PURE__ */
|
|
3474
|
-
/* @__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" })
|
|
3475
2428
|
] });
|
|
3476
2429
|
case "entered":
|
|
3477
|
-
return /* @__PURE__ */
|
|
3478
|
-
/* @__PURE__ */
|
|
3479
|
-
/* @__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" })
|
|
3480
2433
|
] });
|
|
3481
2434
|
case "computed":
|
|
3482
|
-
return /* @__PURE__ */
|
|
3483
|
-
/* @__PURE__ */
|
|
3484
|
-
/* @__PURE__ */
|
|
3485
|
-
/* @__PURE__ */
|
|
3486
|
-
/* @__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" })
|
|
3487
2440
|
] });
|
|
3488
2441
|
case "asserted":
|
|
3489
|
-
return /* @__PURE__ */
|
|
3490
|
-
/* @__PURE__ */
|
|
3491
|
-
/* @__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" })
|
|
3492
2445
|
] });
|
|
3493
2446
|
}
|
|
3494
2447
|
}
|
|
@@ -3508,11 +2461,11 @@ function SourceRow({
|
|
|
3508
2461
|
const status = source.status ?? "ready";
|
|
3509
2462
|
const statusLine = describeProvenanceSourceStatus(source);
|
|
3510
2463
|
const openable = status === "ready" && (onOpenSource !== void 0 || source.href !== void 0);
|
|
3511
|
-
return /* @__PURE__ */
|
|
3512
|
-
/* @__PURE__ */
|
|
3513
|
-
/* @__PURE__ */
|
|
3514
|
-
source.locator && /* @__PURE__ */
|
|
3515
|
-
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(
|
|
3516
2469
|
"button",
|
|
3517
2470
|
{
|
|
3518
2471
|
type: "button",
|
|
@@ -3523,7 +2476,7 @@ function SourceRow({
|
|
|
3523
2476
|
source.label
|
|
3524
2477
|
]
|
|
3525
2478
|
}
|
|
3526
|
-
) : /* @__PURE__ */
|
|
2479
|
+
) : /* @__PURE__ */ jsxs6(
|
|
3527
2480
|
"a",
|
|
3528
2481
|
{
|
|
3529
2482
|
href: source.href,
|
|
@@ -3537,7 +2490,7 @@ function SourceRow({
|
|
|
3537
2490
|
}
|
|
3538
2491
|
))
|
|
3539
2492
|
] }),
|
|
3540
|
-
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: [
|
|
3541
2494
|
"\u201C",
|
|
3542
2495
|
source.quote,
|
|
3543
2496
|
"\u201D"
|
|
@@ -3546,14 +2499,14 @@ function SourceRow({
|
|
|
3546
2499
|
// update is theirs to read, not an interruption. Either way it is TEXT
|
|
3547
2500
|
// — a spinner alone and a greyed row alone both render as "nothing
|
|
3548
2501
|
// here".
|
|
3549
|
-
/* @__PURE__ */
|
|
2502
|
+
/* @__PURE__ */ jsxs6(
|
|
3550
2503
|
"p",
|
|
3551
2504
|
{
|
|
3552
2505
|
role: "status",
|
|
3553
2506
|
className: `mt-1 text-xs ${status === "unavailable" ? "text-destructive" : "text-muted-foreground"}`,
|
|
3554
2507
|
children: [
|
|
3555
2508
|
statusLine,
|
|
3556
|
-
status === "unavailable" && onRetrySource && /* @__PURE__ */
|
|
2509
|
+
status === "unavailable" && onRetrySource && /* @__PURE__ */ jsx8(
|
|
3557
2510
|
"button",
|
|
3558
2511
|
{
|
|
3559
2512
|
type: "button",
|
|
@@ -3577,10 +2530,10 @@ function ProvenanceValue({
|
|
|
3577
2530
|
missingValueLabel = DEFAULT_MISSING_VALUE_LABEL,
|
|
3578
2531
|
className
|
|
3579
2532
|
}) {
|
|
3580
|
-
const [open, setOpen] =
|
|
3581
|
-
const triggerRef =
|
|
3582
|
-
const rootRef =
|
|
3583
|
-
const panelId =
|
|
2533
|
+
const [open, setOpen] = useState11(defaultOpen);
|
|
2534
|
+
const triggerRef = useRef7(null);
|
|
2535
|
+
const rootRef = useRef7(null);
|
|
2536
|
+
const panelId = useId();
|
|
3584
2537
|
const standing = rollUpProvenanceStanding(record, confidencePolicy);
|
|
3585
2538
|
const basisMeta = provenanceBasisMeta(record.basis);
|
|
3586
2539
|
const standingMeta = provenanceStandingMeta(standing);
|
|
@@ -3589,7 +2542,7 @@ function ProvenanceValue({
|
|
|
3589
2542
|
const sources = record.sources ?? [];
|
|
3590
2543
|
const inputs = record.inputs ?? [];
|
|
3591
2544
|
const hasValue = record.display.trim() !== "";
|
|
3592
|
-
const onKeyDown =
|
|
2545
|
+
const onKeyDown = useCallback6(
|
|
3593
2546
|
(event) => {
|
|
3594
2547
|
if (event.key !== "Escape" || !open) return;
|
|
3595
2548
|
event.stopPropagation();
|
|
@@ -3598,11 +2551,11 @@ function ProvenanceValue({
|
|
|
3598
2551
|
},
|
|
3599
2552
|
[open]
|
|
3600
2553
|
);
|
|
3601
|
-
const onToggle =
|
|
2554
|
+
const onToggle = useCallback6(() => {
|
|
3602
2555
|
if (!open) closeTrailsOutside(rootRef.current);
|
|
3603
2556
|
setOpen(!open);
|
|
3604
2557
|
}, [open]);
|
|
3605
|
-
|
|
2558
|
+
useEffect7(() => {
|
|
3606
2559
|
const root = rootRef.current;
|
|
3607
2560
|
if (!open || root === null) return;
|
|
3608
2561
|
const entry = { root, close: () => setOpen(false) };
|
|
@@ -3620,12 +2573,12 @@ function ProvenanceValue({
|
|
|
3620
2573
|
document.removeEventListener("touchstart", onPointerDown, true);
|
|
3621
2574
|
};
|
|
3622
2575
|
}, [open]);
|
|
3623
|
-
const summary = /* @__PURE__ */
|
|
3624
|
-
record.label && /* @__PURE__ */
|
|
3625
|
-
/* @__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 })
|
|
3626
2579
|
] });
|
|
3627
2580
|
if (maxDepth <= 0) {
|
|
3628
|
-
return /* @__PURE__ */
|
|
2581
|
+
return /* @__PURE__ */ jsxs6(
|
|
3629
2582
|
"div",
|
|
3630
2583
|
{
|
|
3631
2584
|
className: `inline-block max-w-full ${className ?? ""}`,
|
|
@@ -3633,22 +2586,22 @@ function ProvenanceValue({
|
|
|
3633
2586
|
"data-provenance-standing": standing,
|
|
3634
2587
|
children: [
|
|
3635
2588
|
summary,
|
|
3636
|
-
/* @__PURE__ */
|
|
2589
|
+
/* @__PURE__ */ jsxs6(
|
|
3637
2590
|
"span",
|
|
3638
2591
|
{
|
|
3639
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]}`,
|
|
3640
2593
|
children: [
|
|
3641
|
-
/* @__PURE__ */
|
|
2594
|
+
/* @__PURE__ */ jsx8(BasisGlyph, { basis: record.basis, className: "h-3 w-3" }),
|
|
3642
2595
|
basisMeta.label
|
|
3643
2596
|
]
|
|
3644
2597
|
}
|
|
3645
2598
|
),
|
|
3646
|
-
/* @__PURE__ */
|
|
2599
|
+
/* @__PURE__ */ jsx8("span", { className: "mt-0.5 block text-xs text-muted-foreground", children: describeProvenance(record) })
|
|
3647
2600
|
]
|
|
3648
2601
|
}
|
|
3649
2602
|
);
|
|
3650
2603
|
}
|
|
3651
|
-
return /* @__PURE__ */
|
|
2604
|
+
return /* @__PURE__ */ jsxs6(
|
|
3652
2605
|
"div",
|
|
3653
2606
|
{
|
|
3654
2607
|
ref: rootRef,
|
|
@@ -3657,9 +2610,9 @@ function ProvenanceValue({
|
|
|
3657
2610
|
"data-provenance-basis": record.basis,
|
|
3658
2611
|
"data-provenance-standing": standing,
|
|
3659
2612
|
children: [
|
|
3660
|
-
/* @__PURE__ */
|
|
2613
|
+
/* @__PURE__ */ jsxs6("span", { className: "inline-flex flex-wrap items-baseline gap-1.5", children: [
|
|
3661
2614
|
summary,
|
|
3662
|
-
/* @__PURE__ */
|
|
2615
|
+
/* @__PURE__ */ jsxs6(
|
|
3663
2616
|
"button",
|
|
3664
2617
|
{
|
|
3665
2618
|
ref: triggerRef,
|
|
@@ -3670,17 +2623,17 @@ function ProvenanceValue({
|
|
|
3670
2623
|
"aria-label": provenanceTriggerLabel(record, standing),
|
|
3671
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]}`,
|
|
3672
2625
|
children: [
|
|
3673
|
-
/* @__PURE__ */
|
|
3674
|
-
/* @__PURE__ */
|
|
2626
|
+
/* @__PURE__ */ jsx8(BasisGlyph, { basis: record.basis, className: "h-3 w-3" }),
|
|
2627
|
+
/* @__PURE__ */ jsx8("span", { "aria-hidden": true, children: basisMeta.label })
|
|
3675
2628
|
]
|
|
3676
2629
|
}
|
|
3677
2630
|
),
|
|
3678
2631
|
standing !== "settled" && // Legible at rest: what to do about the value does not wait for
|
|
3679
2632
|
// someone to open the panel. `aria-hidden` because the trigger's
|
|
3680
2633
|
// accessible name already carries it — this is the visual half.
|
|
3681
|
-
/* @__PURE__ */
|
|
2634
|
+
/* @__PURE__ */ jsx8("span", { "aria-hidden": true, className: `text-xs font-medium ${STANDING_TONES[standing]}`, children: standingMeta.label })
|
|
3682
2635
|
] }),
|
|
3683
|
-
open && /* @__PURE__ */
|
|
2636
|
+
open && /* @__PURE__ */ jsxs6(
|
|
3684
2637
|
"div",
|
|
3685
2638
|
{
|
|
3686
2639
|
id: panelId,
|
|
@@ -3688,19 +2641,19 @@ function ProvenanceValue({
|
|
|
3688
2641
|
"aria-label": provenanceTriggerLabel(record, standing),
|
|
3689
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",
|
|
3690
2643
|
children: [
|
|
3691
|
-
/* @__PURE__ */
|
|
3692
|
-
/* @__PURE__ */
|
|
3693
|
-
/* @__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: [
|
|
3694
2647
|
standingMeta.label,
|
|
3695
2648
|
" \u2014 ",
|
|
3696
2649
|
provenanceNextMove(record, standing, confidencePolicy)
|
|
3697
2650
|
] }),
|
|
3698
|
-
basisMeta.checkableAgainst === null && /* @__PURE__ */
|
|
2651
|
+
basisMeta.checkableAgainst === null && /* @__PURE__ */ jsxs6("p", { className: "mt-0.5 text-xs leading-snug text-muted-foreground", children: [
|
|
3699
2652
|
basisMeta.meaning,
|
|
3700
2653
|
" There is nothing outside the model to check it against."
|
|
3701
2654
|
] })
|
|
3702
2655
|
] }),
|
|
3703
|
-
sources.length > 0 && /* @__PURE__ */
|
|
2656
|
+
sources.length > 0 && /* @__PURE__ */ jsx8("ul", { className: "space-y-1.5", children: sources.map((source, index) => /* @__PURE__ */ jsx8(
|
|
3704
2657
|
SourceRow,
|
|
3705
2658
|
{
|
|
3706
2659
|
source,
|
|
@@ -3713,12 +2666,12 @@ function ProvenanceValue({
|
|
|
3713
2666
|
gaps.filter((gap) => gap.kind !== "unavailable-source").map((gap) => (
|
|
3714
2667
|
// An unavailable source already states itself on its own row; a
|
|
3715
2668
|
// structural gap has no row to state it, so it gets one here.
|
|
3716
|
-
/* @__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)
|
|
3717
2670
|
)),
|
|
3718
|
-
loading.length > 0 && sources.length === 0 && /* @__PURE__ */
|
|
3719
|
-
inputs.length > 0 && /* @__PURE__ */
|
|
3720
|
-
/* @__PURE__ */
|
|
3721
|
-
/* @__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(
|
|
3722
2675
|
ProvenanceValue,
|
|
3723
2676
|
{
|
|
3724
2677
|
record: input,
|
|
@@ -3739,26 +2692,26 @@ function ProvenanceValue({
|
|
|
3739
2692
|
}
|
|
3740
2693
|
function ProvenanceLegend({ bases, className }) {
|
|
3741
2694
|
if (bases.length === 0) return null;
|
|
3742
|
-
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) => {
|
|
3743
2696
|
const meta = provenanceBasisMeta(basis);
|
|
3744
|
-
return /* @__PURE__ */
|
|
3745
|
-
/* @__PURE__ */
|
|
2697
|
+
return /* @__PURE__ */ jsxs6("li", { className: "flex items-center gap-1.5 text-xs text-muted-foreground", children: [
|
|
2698
|
+
/* @__PURE__ */ jsxs6(
|
|
3746
2699
|
"span",
|
|
3747
2700
|
{
|
|
3748
2701
|
className: `inline-flex items-center gap-1 rounded-full border px-1.5 py-0.5 text-xs font-medium ${BASIS_TONES[basis]}`,
|
|
3749
2702
|
children: [
|
|
3750
|
-
/* @__PURE__ */
|
|
2703
|
+
/* @__PURE__ */ jsx8(BasisGlyph, { basis, className: "h-3 w-3" }),
|
|
3751
2704
|
meta.label
|
|
3752
2705
|
]
|
|
3753
2706
|
}
|
|
3754
2707
|
),
|
|
3755
|
-
/* @__PURE__ */
|
|
2708
|
+
/* @__PURE__ */ jsx8("span", { children: meta.meaning })
|
|
3756
2709
|
] }, basis);
|
|
3757
2710
|
}) });
|
|
3758
2711
|
}
|
|
3759
2712
|
|
|
3760
2713
|
// src/web-react/seat-paywall.tsx
|
|
3761
|
-
import { Fragment as
|
|
2714
|
+
import { Fragment as Fragment3, jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
3762
2715
|
function usd(cents) {
|
|
3763
2716
|
return new Intl.NumberFormat("en-US", {
|
|
3764
2717
|
style: "currency",
|
|
@@ -3768,7 +2721,7 @@ function usd(cents) {
|
|
|
3768
2721
|
}).format(cents / 100);
|
|
3769
2722
|
}
|
|
3770
2723
|
function CheckGlyph3() {
|
|
3771
|
-
return /* @__PURE__ */
|
|
2724
|
+
return /* @__PURE__ */ jsx9(
|
|
3772
2725
|
"svg",
|
|
3773
2726
|
{
|
|
3774
2727
|
className: "h-4 w-4 shrink-0 text-primary",
|
|
@@ -3779,14 +2732,14 @@ function CheckGlyph3() {
|
|
|
3779
2732
|
strokeLinecap: "round",
|
|
3780
2733
|
strokeLinejoin: "round",
|
|
3781
2734
|
"aria-hidden": true,
|
|
3782
|
-
children: /* @__PURE__ */
|
|
2735
|
+
children: /* @__PURE__ */ jsx9("path", { d: "M20 6 9 17l-5-5" })
|
|
3783
2736
|
}
|
|
3784
2737
|
);
|
|
3785
2738
|
}
|
|
3786
2739
|
function Benefit({ children }) {
|
|
3787
|
-
return /* @__PURE__ */
|
|
3788
|
-
/* @__PURE__ */
|
|
3789
|
-
/* @__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 })
|
|
3790
2743
|
] });
|
|
3791
2744
|
}
|
|
3792
2745
|
function SeatPaywall({
|
|
@@ -3804,45 +2757,45 @@ function SeatPaywall({
|
|
|
3804
2757
|
const recurringPrice = offer ? usd(offer.recurring.priceCents) : `$${priceUsd}`;
|
|
3805
2758
|
const recurringUsage = offer ? usd(offer.recurring.includedCreditsCents) : `$${includedUsageUsd}`;
|
|
3806
2759
|
const introductory = offer?.introductory ?? null;
|
|
3807
|
-
return /* @__PURE__ */
|
|
3808
|
-
/* @__PURE__ */
|
|
3809
|
-
/* @__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: [
|
|
3810
2763
|
"Unlock ",
|
|
3811
2764
|
product
|
|
3812
2765
|
] }),
|
|
3813
|
-
tagline && /* @__PURE__ */
|
|
3814
|
-
introductory ? /* @__PURE__ */
|
|
3815
|
-
/* @__PURE__ */
|
|
3816
|
-
/* @__PURE__ */
|
|
3817
|
-
/* @__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" })
|
|
3818
2771
|
] }),
|
|
3819
|
-
/* @__PURE__ */
|
|
2772
|
+
/* @__PURE__ */ jsxs7("p", { className: "mt-1 text-sm text-muted-foreground", children: [
|
|
3820
2773
|
"Includes ",
|
|
3821
2774
|
usd(introductory.includedCreditsCents),
|
|
3822
2775
|
" of AI usage in your first month"
|
|
3823
2776
|
] }),
|
|
3824
|
-
/* @__PURE__ */
|
|
2777
|
+
/* @__PURE__ */ jsxs7("p", { className: "mt-1 text-sm text-muted-foreground", children: [
|
|
3825
2778
|
"Then ",
|
|
3826
2779
|
recurringPrice,
|
|
3827
2780
|
"/mo \xB7 includes ",
|
|
3828
2781
|
recurringUsage,
|
|
3829
2782
|
"/mo of AI usage"
|
|
3830
2783
|
] })
|
|
3831
|
-
] }) : /* @__PURE__ */
|
|
3832
|
-
/* @__PURE__ */
|
|
3833
|
-
/* @__PURE__ */
|
|
3834
|
-
/* @__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" })
|
|
3835
2788
|
] }),
|
|
3836
|
-
/* @__PURE__ */
|
|
2789
|
+
/* @__PURE__ */ jsxs7("p", { className: "mt-1 text-sm text-muted-foreground", children: [
|
|
3837
2790
|
"Includes ",
|
|
3838
2791
|
recurringUsage,
|
|
3839
2792
|
"/mo of AI usage"
|
|
3840
2793
|
] })
|
|
3841
2794
|
] }),
|
|
3842
|
-
/* @__PURE__ */
|
|
2795
|
+
/* @__PURE__ */ jsx9("ul", { className: "mt-6 space-y-2.5", children: (benefits ?? [
|
|
3843
2796
|
`Full access to ${product}`
|
|
3844
|
-
]).map((benefit, i) => /* @__PURE__ */
|
|
3845
|
-
/* @__PURE__ */
|
|
2797
|
+
]).map((benefit, i) => /* @__PURE__ */ jsx9(Benefit, { children: benefit }, i)) }),
|
|
2798
|
+
/* @__PURE__ */ jsx9(
|
|
3846
2799
|
"button",
|
|
3847
2800
|
{
|
|
3848
2801
|
type: "button",
|
|
@@ -3852,20 +2805,20 @@ function SeatPaywall({
|
|
|
3852
2805
|
children: pending ? "Opening checkout\u2026" : ctaLabel ?? "Continue to checkout"
|
|
3853
2806
|
}
|
|
3854
2807
|
),
|
|
3855
|
-
footnote && /* @__PURE__ */
|
|
2808
|
+
footnote && /* @__PURE__ */ jsx9("p", { className: "mt-3 text-center text-xs text-muted-foreground/70", children: footnote })
|
|
3856
2809
|
] }) });
|
|
3857
2810
|
}
|
|
3858
2811
|
|
|
3859
2812
|
// src/web-react/record-grid.tsx
|
|
3860
2813
|
import {
|
|
3861
|
-
Fragment as
|
|
2814
|
+
Fragment as Fragment4,
|
|
3862
2815
|
isValidElement,
|
|
3863
|
-
useCallback as
|
|
3864
|
-
useEffect as
|
|
3865
|
-
useId as
|
|
3866
|
-
useMemo as
|
|
3867
|
-
useRef as
|
|
3868
|
-
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
|
|
3869
2822
|
} from "react";
|
|
3870
2823
|
|
|
3871
2824
|
// src/web-react/record-grid-model.ts
|
|
@@ -4221,7 +3174,7 @@ function pruneRecordGridOverlay(rows, overlay) {
|
|
|
4221
3174
|
}
|
|
4222
3175
|
|
|
4223
3176
|
// src/web-react/record-grid.tsx
|
|
4224
|
-
import { jsx as
|
|
3177
|
+
import { jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
4225
3178
|
var EMPTY_RECORD_GRID_ROWS = [];
|
|
4226
3179
|
var CELL_KEY_SEPARATOR = "\0";
|
|
4227
3180
|
function cellKey(rowId, columnId) {
|
|
@@ -4280,57 +3233,57 @@ function RecordGrid({
|
|
|
4280
3233
|
loadingRowCount = 3,
|
|
4281
3234
|
className
|
|
4282
3235
|
}) {
|
|
4283
|
-
const fieldPrefix =
|
|
4284
|
-
const [overlay, setOverlay] =
|
|
4285
|
-
const [editing, setEditingState] =
|
|
4286
|
-
const [cellErrors, setCellErrors] =
|
|
4287
|
-
const [rowErrors, setRowErrors] =
|
|
4288
|
-
const [pendingRows, setPendingRows] =
|
|
4289
|
-
const [focus, setFocus] =
|
|
4290
|
-
const [openSource, setOpenSource] =
|
|
4291
|
-
const [confirmDelete, setConfirmDelete] =
|
|
4292
|
-
const [adding, setAdding] =
|
|
4293
|
-
const [draft, setDraft] =
|
|
4294
|
-
const [draftErrors, setDraftErrors] =
|
|
4295
|
-
const [draftError, setDraftError] =
|
|
4296
|
-
const [creating, setCreating] =
|
|
4297
|
-
const cellRefs =
|
|
4298
|
-
const settling =
|
|
4299
|
-
const draftCounter =
|
|
4300
|
-
const editingRef =
|
|
4301
|
-
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) => {
|
|
4302
3255
|
editingRef.current = next;
|
|
4303
3256
|
setEditingState(next);
|
|
4304
3257
|
}, []);
|
|
4305
3258
|
const callerRows = state.status === "ready" || state.status === "empty" ? state.value : EMPTY_RECORD_GRID_ROWS;
|
|
4306
|
-
|
|
3259
|
+
useEffect8(() => {
|
|
4307
3260
|
setOverlay((current) => pruneRecordGridOverlay(callerRows, current));
|
|
4308
3261
|
}, [callerRows]);
|
|
4309
|
-
const visibleRows =
|
|
4310
|
-
const diffs =
|
|
3262
|
+
const visibleRows = useMemo5(() => projectRecordGridRows(callerRows, overlay), [callerRows, overlay]);
|
|
3263
|
+
const diffs = useMemo5(
|
|
4311
3264
|
() => proposed === void 0 ? null : diffRecordGridProposal(visibleRows, proposed),
|
|
4312
3265
|
[proposed, visibleRows]
|
|
4313
3266
|
);
|
|
4314
3267
|
const reviewing = diffs !== null && diffs.length > 0;
|
|
4315
|
-
const diffByRow =
|
|
4316
|
-
const diffCellByKey =
|
|
3268
|
+
const diffByRow = useMemo5(() => new Map((diffs ?? []).map((diff) => [diff.rowId, diff])), [diffs]);
|
|
3269
|
+
const diffCellByKey = useMemo5(() => {
|
|
4317
3270
|
const map = /* @__PURE__ */ new Map();
|
|
4318
3271
|
for (const diff of diffs ?? []) {
|
|
4319
3272
|
for (const cell of diff.cells) map.set(cellKey(diff.rowId, cell.columnId), cell);
|
|
4320
3273
|
}
|
|
4321
3274
|
return map;
|
|
4322
3275
|
}, [diffs]);
|
|
4323
|
-
const addedRows =
|
|
3276
|
+
const addedRows = useMemo5(
|
|
4324
3277
|
() => (diffs ?? []).filter((diff) => diff.kind === "added").map((diff) => diff.row),
|
|
4325
3278
|
[diffs]
|
|
4326
3279
|
);
|
|
4327
|
-
const activeFocus =
|
|
3280
|
+
const activeFocus = useMemo5(() => {
|
|
4328
3281
|
if (focus === null) return null;
|
|
4329
3282
|
if (!visibleRows.some((row) => row.id === focus.rowId)) return null;
|
|
4330
3283
|
if (!columns.some((column) => column.id === focus.columnId)) return null;
|
|
4331
3284
|
return focus;
|
|
4332
3285
|
}, [columns, focus, visibleRows]);
|
|
4333
|
-
const setCellError =
|
|
3286
|
+
const setCellError = useCallback7((key, message) => {
|
|
4334
3287
|
setCellErrors((current) => {
|
|
4335
3288
|
if (message === null) {
|
|
4336
3289
|
if (!(key in current)) return current;
|
|
@@ -4342,7 +3295,7 @@ function RecordGrid({
|
|
|
4342
3295
|
return { ...current, [key]: message };
|
|
4343
3296
|
});
|
|
4344
3297
|
}, []);
|
|
4345
|
-
const setRowError =
|
|
3298
|
+
const setRowError = useCallback7((rowId, message) => {
|
|
4346
3299
|
setRowErrors((current) => {
|
|
4347
3300
|
if (message === null) {
|
|
4348
3301
|
if (!(rowId in current)) return current;
|
|
@@ -4353,7 +3306,7 @@ function RecordGrid({
|
|
|
4353
3306
|
return { ...current, [rowId]: message };
|
|
4354
3307
|
});
|
|
4355
3308
|
}, []);
|
|
4356
|
-
const setRowPending =
|
|
3309
|
+
const setRowPending = useCallback7((rowId, pending) => {
|
|
4357
3310
|
setPendingRows((current) => {
|
|
4358
3311
|
if (pending) return rowId in current ? current : { ...current, [rowId]: true };
|
|
4359
3312
|
if (!(rowId in current)) return current;
|
|
@@ -4362,11 +3315,11 @@ function RecordGrid({
|
|
|
4362
3315
|
return next;
|
|
4363
3316
|
});
|
|
4364
3317
|
}, []);
|
|
4365
|
-
const focusCell =
|
|
3318
|
+
const focusCell = useCallback7((rowId, columnId) => {
|
|
4366
3319
|
setFocus({ rowId, columnId });
|
|
4367
3320
|
cellRefs.current.get(cellKey(rowId, columnId))?.focus();
|
|
4368
3321
|
}, []);
|
|
4369
|
-
const beginEdit =
|
|
3322
|
+
const beginEdit = useCallback7(
|
|
4370
3323
|
(row, column) => {
|
|
4371
3324
|
setCellError(cellKey(row.id, column.id), null);
|
|
4372
3325
|
setEditing({
|
|
@@ -4377,7 +3330,7 @@ function RecordGrid({
|
|
|
4377
3330
|
},
|
|
4378
3331
|
[setCellError, setEditing]
|
|
4379
3332
|
);
|
|
4380
|
-
const applyCellWrite =
|
|
3333
|
+
const applyCellWrite = useCallback7(
|
|
4381
3334
|
async (row, column, value) => {
|
|
4382
3335
|
if (!onUpdate) return;
|
|
4383
3336
|
const values = { ...row.values, [column.id]: value };
|
|
@@ -4405,7 +3358,7 @@ function RecordGrid({
|
|
|
4405
3358
|
},
|
|
4406
3359
|
[locale, onUpdate, setRowError, setRowPending]
|
|
4407
3360
|
);
|
|
4408
|
-
const commitEdit =
|
|
3361
|
+
const commitEdit = useCallback7(
|
|
4409
3362
|
async (row, column, text) => {
|
|
4410
3363
|
const open = editingRef.current;
|
|
4411
3364
|
if (open === null || open.rowId !== row.id || open.columnId !== column.id) return;
|
|
@@ -4429,7 +3382,7 @@ function RecordGrid({
|
|
|
4429
3382
|
},
|
|
4430
3383
|
[applyCellWrite, setCellError, setEditing]
|
|
4431
3384
|
);
|
|
4432
|
-
const cancelEdit =
|
|
3385
|
+
const cancelEdit = useCallback7(
|
|
4433
3386
|
(row, column) => {
|
|
4434
3387
|
setCellError(cellKey(row.id, column.id), null);
|
|
4435
3388
|
setEditing(null);
|
|
@@ -4437,7 +3390,7 @@ function RecordGrid({
|
|
|
4437
3390
|
},
|
|
4438
3391
|
[focusCell, setCellError, setEditing]
|
|
4439
3392
|
);
|
|
4440
|
-
const performDelete =
|
|
3393
|
+
const performDelete = useCallback7(
|
|
4441
3394
|
async (row) => {
|
|
4442
3395
|
if (!onDelete) return;
|
|
4443
3396
|
setConfirmDelete(null);
|
|
@@ -4455,16 +3408,16 @@ function RecordGrid({
|
|
|
4455
3408
|
},
|
|
4456
3409
|
[columns, onDelete, setRowError]
|
|
4457
3410
|
);
|
|
4458
|
-
const resetDraft =
|
|
3411
|
+
const resetDraft = useCallback7(() => {
|
|
4459
3412
|
setDraft({ ...newRowDefaults ?? {} });
|
|
4460
3413
|
setDraftErrors({});
|
|
4461
3414
|
setDraftError(null);
|
|
4462
3415
|
}, [newRowDefaults]);
|
|
4463
|
-
const openAdd =
|
|
3416
|
+
const openAdd = useCallback7(() => {
|
|
4464
3417
|
resetDraft();
|
|
4465
3418
|
setAdding(true);
|
|
4466
3419
|
}, [resetDraft]);
|
|
4467
|
-
const submitDraft =
|
|
3420
|
+
const submitDraft = useCallback7(async () => {
|
|
4468
3421
|
if (!onCreate) return;
|
|
4469
3422
|
const validated = validateRecordGridRow(columns, draft);
|
|
4470
3423
|
if (!validated.succeeded) {
|
|
@@ -4494,7 +3447,7 @@ function RecordGrid({
|
|
|
4494
3447
|
setOverlay((current) => withoutRecordGridCreated(current, draftId));
|
|
4495
3448
|
setDraftError(outcome.error);
|
|
4496
3449
|
}, [columns, draft, fieldPrefix, onCreate, resetDraft]);
|
|
4497
|
-
const handleGridKeyDown =
|
|
3450
|
+
const handleGridKeyDown = useCallback7(
|
|
4498
3451
|
(event) => {
|
|
4499
3452
|
if (editing !== null) return;
|
|
4500
3453
|
const target = event.target;
|
|
@@ -4533,9 +3486,9 @@ function RecordGrid({
|
|
|
4533
3486
|
[beginEdit, columns, editing, focusCell, onUpdate, reviewing, visibleRows]
|
|
4534
3487
|
);
|
|
4535
3488
|
if (state.status === "idle" || state.status === "loading") {
|
|
4536
|
-
return /* @__PURE__ */
|
|
3489
|
+
return /* @__PURE__ */ jsxs8("div", { className: `space-y-3 ${className ?? ""}`, children: [
|
|
4537
3490
|
toolbar,
|
|
4538
|
-
/* @__PURE__ */
|
|
3491
|
+
/* @__PURE__ */ jsxs8(
|
|
4539
3492
|
"div",
|
|
4540
3493
|
{
|
|
4541
3494
|
role: "status",
|
|
@@ -4543,22 +3496,22 @@ function RecordGrid({
|
|
|
4543
3496
|
"aria-live": "polite",
|
|
4544
3497
|
className: "space-y-2 rounded-xl border border-card-edge bg-card p-4",
|
|
4545
3498
|
children: [
|
|
4546
|
-
/* @__PURE__ */
|
|
3499
|
+
/* @__PURE__ */ jsxs8("span", { className: "sr-only", children: [
|
|
4547
3500
|
"Loading ",
|
|
4548
3501
|
caption
|
|
4549
3502
|
] }),
|
|
4550
|
-
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))
|
|
4551
3504
|
]
|
|
4552
3505
|
}
|
|
4553
3506
|
)
|
|
4554
3507
|
] });
|
|
4555
3508
|
}
|
|
4556
3509
|
if (state.status === "error") {
|
|
4557
|
-
return /* @__PURE__ */
|
|
3510
|
+
return /* @__PURE__ */ jsxs8("div", { className: `space-y-3 ${className ?? ""}`, children: [
|
|
4558
3511
|
toolbar,
|
|
4559
|
-
/* @__PURE__ */
|
|
4560
|
-
/* @__PURE__ */
|
|
4561
|
-
/* @__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(
|
|
4562
3515
|
"button",
|
|
4563
3516
|
{
|
|
4564
3517
|
type: "button",
|
|
@@ -4570,7 +3523,7 @@ function RecordGrid({
|
|
|
4570
3523
|
] })
|
|
4571
3524
|
] });
|
|
4572
3525
|
}
|
|
4573
|
-
const addForm = adding && onCreate && !reviewing ? /* @__PURE__ */
|
|
3526
|
+
const addForm = adding && onCreate && !reviewing ? /* @__PURE__ */ jsx10(
|
|
4574
3527
|
AddRecordForm,
|
|
4575
3528
|
{
|
|
4576
3529
|
columns,
|
|
@@ -4589,13 +3542,13 @@ function RecordGrid({
|
|
|
4589
3542
|
}
|
|
4590
3543
|
) : null;
|
|
4591
3544
|
if (visibleRows.length === 0 && !reviewing) {
|
|
4592
|
-
return /* @__PURE__ */
|
|
3545
|
+
return /* @__PURE__ */ jsxs8("div", { className: `space-y-3 ${className ?? ""}`, children: [
|
|
4593
3546
|
toolbar,
|
|
4594
|
-
addForm ?? /* @__PURE__ */
|
|
4595
|
-
/* @__PURE__ */
|
|
4596
|
-
empty.description && /* @__PURE__ */
|
|
4597
|
-
/* @__PURE__ */
|
|
4598
|
-
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(
|
|
4599
3552
|
"button",
|
|
4600
3553
|
{
|
|
4601
3554
|
type: "button",
|
|
@@ -4604,7 +3557,7 @@ function RecordGrid({
|
|
|
4604
3557
|
children: empty.action.label
|
|
4605
3558
|
}
|
|
4606
3559
|
)),
|
|
4607
|
-
onCreate && /* @__PURE__ */
|
|
3560
|
+
onCreate && /* @__PURE__ */ jsx10(
|
|
4608
3561
|
"button",
|
|
4609
3562
|
{
|
|
4610
3563
|
type: "button",
|
|
@@ -4629,18 +3582,18 @@ function RecordGrid({
|
|
|
4629
3582
|
addedCount > 0 ? `${addedCount} added` : null,
|
|
4630
3583
|
removedCount > 0 ? `${removedCount} removed` : null
|
|
4631
3584
|
].filter((part) => part !== null).join(" \xB7 ");
|
|
4632
|
-
const reviewBar = reviewing ? /* @__PURE__ */
|
|
3585
|
+
const reviewBar = reviewing ? /* @__PURE__ */ jsxs8(
|
|
4633
3586
|
"div",
|
|
4634
3587
|
{
|
|
4635
3588
|
"data-record-grid-review": "",
|
|
4636
3589
|
className: "flex flex-wrap items-center justify-between gap-3 rounded-xl border border-card-edge bg-card px-4 py-2.5",
|
|
4637
3590
|
children: [
|
|
4638
|
-
/* @__PURE__ */
|
|
4639
|
-
/* @__PURE__ */
|
|
4640
|
-
/* @__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 })
|
|
4641
3594
|
] }),
|
|
4642
|
-
(onAcceptAll || onRejectAll) && /* @__PURE__ */
|
|
4643
|
-
onRejectAll && /* @__PURE__ */
|
|
3595
|
+
(onAcceptAll || onRejectAll) && /* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-2", children: [
|
|
3596
|
+
onRejectAll && /* @__PURE__ */ jsx10(
|
|
4644
3597
|
"button",
|
|
4645
3598
|
{
|
|
4646
3599
|
type: "button",
|
|
@@ -4650,7 +3603,7 @@ function RecordGrid({
|
|
|
4650
3603
|
children: "Reject all"
|
|
4651
3604
|
}
|
|
4652
3605
|
),
|
|
4653
|
-
onAcceptAll && /* @__PURE__ */
|
|
3606
|
+
onAcceptAll && /* @__PURE__ */ jsx10(
|
|
4654
3607
|
"button",
|
|
4655
3608
|
{
|
|
4656
3609
|
type: "button",
|
|
@@ -4664,10 +3617,10 @@ function RecordGrid({
|
|
|
4664
3617
|
]
|
|
4665
3618
|
}
|
|
4666
3619
|
) : null;
|
|
4667
|
-
return /* @__PURE__ */
|
|
3620
|
+
return /* @__PURE__ */ jsxs8("div", { className: `space-y-3 ${className ?? ""}`, children: [
|
|
4668
3621
|
toolbar,
|
|
4669
3622
|
reviewBar,
|
|
4670
|
-
/* @__PURE__ */
|
|
3623
|
+
/* @__PURE__ */ jsx10("div", { className: "overflow-x-auto rounded-xl border border-card-edge bg-card", children: /* @__PURE__ */ jsxs8(
|
|
4671
3624
|
"table",
|
|
4672
3625
|
{
|
|
4673
3626
|
role: "grid",
|
|
@@ -4675,8 +3628,8 @@ function RecordGrid({
|
|
|
4675
3628
|
className: "w-full border-collapse text-left text-sm",
|
|
4676
3629
|
onKeyDown: handleGridKeyDown,
|
|
4677
3630
|
children: [
|
|
4678
|
-
/* @__PURE__ */
|
|
4679
|
-
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(
|
|
4680
3633
|
"th",
|
|
4681
3634
|
{
|
|
4682
3635
|
role: "columnheader",
|
|
@@ -4686,17 +3639,17 @@ function RecordGrid({
|
|
|
4686
3639
|
},
|
|
4687
3640
|
column.id
|
|
4688
3641
|
)),
|
|
4689
|
-
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" }) })
|
|
4690
3643
|
] }) }),
|
|
4691
|
-
/* @__PURE__ */
|
|
3644
|
+
/* @__PURE__ */ jsxs8("tbody", { children: [
|
|
4692
3645
|
visibleRows.map((row) => {
|
|
4693
3646
|
const rowLabel = recordGridRowLabel(columns, row);
|
|
4694
3647
|
const pending = row.id in pendingRows;
|
|
4695
3648
|
const rowError = rowErrors[row.id];
|
|
4696
3649
|
const rowDiff = reviewing ? diffByRow.get(row.id) : void 0;
|
|
4697
3650
|
const removedRow = rowDiff?.kind === "removed";
|
|
4698
|
-
return /* @__PURE__ */
|
|
4699
|
-
/* @__PURE__ */
|
|
3651
|
+
return /* @__PURE__ */ jsxs8(Fragment4, { children: [
|
|
3652
|
+
/* @__PURE__ */ jsxs8(
|
|
4700
3653
|
"tr",
|
|
4701
3654
|
{
|
|
4702
3655
|
role: "row",
|
|
@@ -4716,8 +3669,8 @@ function RecordGrid({
|
|
|
4716
3669
|
const errorId = `${fieldPrefix}-cell-error-${row.id}-${column.id}`;
|
|
4717
3670
|
const cellDiff = rowDiff?.kind === "changed" ? diffCellByKey.get(key) : void 0;
|
|
4718
3671
|
if (isEditing && editable) {
|
|
4719
|
-
return /* @__PURE__ */
|
|
4720
|
-
/* @__PURE__ */
|
|
3672
|
+
return /* @__PURE__ */ jsxs8("td", { role: "gridcell", className: `px-3 py-1.5 ${alignmentClass(column)}`, children: [
|
|
3673
|
+
/* @__PURE__ */ jsx10(
|
|
4721
3674
|
CellEditor,
|
|
4722
3675
|
{
|
|
4723
3676
|
column,
|
|
@@ -4730,11 +3683,11 @@ function RecordGrid({
|
|
|
4730
3683
|
onCancel: () => cancelEdit(row, column)
|
|
4731
3684
|
}
|
|
4732
3685
|
),
|
|
4733
|
-
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 })
|
|
4734
3687
|
] }, column.id);
|
|
4735
3688
|
}
|
|
4736
3689
|
if (column.kind === "boolean" && editable) {
|
|
4737
|
-
return /* @__PURE__ */
|
|
3690
|
+
return /* @__PURE__ */ jsx10("td", { role: "gridcell", className: `px-3 py-2 ${alignmentClass(column)}`, children: /* @__PURE__ */ jsx10(
|
|
4738
3691
|
"input",
|
|
4739
3692
|
{
|
|
4740
3693
|
type: "checkbox",
|
|
@@ -4753,7 +3706,7 @@ function RecordGrid({
|
|
|
4753
3706
|
) }, column.id);
|
|
4754
3707
|
}
|
|
4755
3708
|
const display = applicable ? formatRecordGridValue(column, value, locale) : "";
|
|
4756
|
-
return /* @__PURE__ */
|
|
3709
|
+
return /* @__PURE__ */ jsx10(
|
|
4757
3710
|
"td",
|
|
4758
3711
|
{
|
|
4759
3712
|
role: "gridcell",
|
|
@@ -4771,20 +3724,20 @@ function RecordGrid({
|
|
|
4771
3724
|
className: `px-3 py-2 outline-none focus:ring-2 focus:ring-inset focus:ring-primary/50 ${alignmentClass(
|
|
4772
3725
|
column
|
|
4773
3726
|
)} ${editable ? "cursor-text" : ""}`,
|
|
4774
|
-
children: /* @__PURE__ */
|
|
4775
|
-
column.id === columns[0]?.id && removedRow && /* @__PURE__ */
|
|
4776
|
-
cellDiff ? /* @__PURE__ */
|
|
4777
|
-
/* @__PURE__ */
|
|
4778
|
-
/* @__PURE__ */
|
|
4779
|
-
/* @__PURE__ */
|
|
4780
|
-
] }) : /* @__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(
|
|
4781
3734
|
"span",
|
|
4782
3735
|
{
|
|
4783
3736
|
className: removedRow ? "truncate text-destructive line-through decoration-destructive/60" : display === "" ? "text-muted-foreground" : "truncate text-foreground",
|
|
4784
3737
|
children: display === "" ? applicable ? "\u2014" : "n/a" : display
|
|
4785
3738
|
}
|
|
4786
3739
|
),
|
|
4787
|
-
source && /* @__PURE__ */
|
|
3740
|
+
source && /* @__PURE__ */ jsx10(
|
|
4788
3741
|
SourceMarker,
|
|
4789
3742
|
{
|
|
4790
3743
|
panelId: `${fieldPrefix}-source-${row.id}-${column.id}`,
|
|
@@ -4800,7 +3753,7 @@ function RecordGrid({
|
|
|
4800
3753
|
column.id
|
|
4801
3754
|
);
|
|
4802
3755
|
}),
|
|
4803
|
-
showActionsColumn && /* @__PURE__ */
|
|
3756
|
+
showActionsColumn && /* @__PURE__ */ jsx10("td", { role: "gridcell", className: "px-3 py-2 text-right", children: reviewing ? rowDiff && /* @__PURE__ */ jsx10(
|
|
4804
3757
|
ReviewActions,
|
|
4805
3758
|
{
|
|
4806
3759
|
rowId: row.id,
|
|
@@ -4809,8 +3762,8 @@ function RecordGrid({
|
|
|
4809
3762
|
onAccept: onAcceptRow,
|
|
4810
3763
|
onReject: onRejectRow
|
|
4811
3764
|
}
|
|
4812
|
-
) : row.readOnly === true ? null : confirmDelete === row.id ? /* @__PURE__ */
|
|
4813
|
-
/* @__PURE__ */
|
|
3765
|
+
) : row.readOnly === true ? null : confirmDelete === row.id ? /* @__PURE__ */ jsxs8("span", { className: "inline-flex items-center gap-1.5", children: [
|
|
3766
|
+
/* @__PURE__ */ jsx10(
|
|
4814
3767
|
"button",
|
|
4815
3768
|
{
|
|
4816
3769
|
type: "button",
|
|
@@ -4820,7 +3773,7 @@ function RecordGrid({
|
|
|
4820
3773
|
children: "Delete"
|
|
4821
3774
|
}
|
|
4822
3775
|
),
|
|
4823
|
-
/* @__PURE__ */
|
|
3776
|
+
/* @__PURE__ */ jsx10(
|
|
4824
3777
|
"button",
|
|
4825
3778
|
{
|
|
4826
3779
|
type: "button",
|
|
@@ -4830,14 +3783,14 @@ function RecordGrid({
|
|
|
4830
3783
|
children: "Cancel"
|
|
4831
3784
|
}
|
|
4832
3785
|
)
|
|
4833
|
-
] }) : /* @__PURE__ */
|
|
3786
|
+
] }) : /* @__PURE__ */ jsx10(
|
|
4834
3787
|
"button",
|
|
4835
3788
|
{
|
|
4836
3789
|
type: "button",
|
|
4837
3790
|
"aria-label": `Delete ${rowLabel}`,
|
|
4838
3791
|
onClick: () => setConfirmDelete(row.id),
|
|
4839
3792
|
className: "rounded-md p-1.5 text-muted-foreground transition hover:bg-destructive/10 hover:text-destructive",
|
|
4840
|
-
children: /* @__PURE__ */
|
|
3793
|
+
children: /* @__PURE__ */ jsxs8(
|
|
4841
3794
|
"svg",
|
|
4842
3795
|
{
|
|
4843
3796
|
viewBox: "0 0 24 24",
|
|
@@ -4849,8 +3802,8 @@ function RecordGrid({
|
|
|
4849
3802
|
strokeLinejoin: "round",
|
|
4850
3803
|
"aria-hidden": true,
|
|
4851
3804
|
children: [
|
|
4852
|
-
/* @__PURE__ */
|
|
4853
|
-
/* @__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" })
|
|
4854
3807
|
]
|
|
4855
3808
|
}
|
|
4856
3809
|
)
|
|
@@ -4859,12 +3812,12 @@ function RecordGrid({
|
|
|
4859
3812
|
]
|
|
4860
3813
|
}
|
|
4861
3814
|
),
|
|
4862
|
-
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 }) }) })
|
|
4863
3816
|
] }, row.id);
|
|
4864
3817
|
}),
|
|
4865
3818
|
reviewing && addedRows.map((row) => {
|
|
4866
3819
|
const rowLabel = recordGridRowLabel(columns, row);
|
|
4867
|
-
return /* @__PURE__ */
|
|
3820
|
+
return /* @__PURE__ */ jsxs8(
|
|
4868
3821
|
"tr",
|
|
4869
3822
|
{
|
|
4870
3823
|
role: "row",
|
|
@@ -4875,9 +3828,9 @@ function RecordGrid({
|
|
|
4875
3828
|
const applicable = isRecordGridCellApplicable(column, row.values);
|
|
4876
3829
|
const value = row.values[column.id] ?? null;
|
|
4877
3830
|
const display = applicable ? formatRecordGridValue(column, value, locale) : "";
|
|
4878
|
-
return /* @__PURE__ */
|
|
4879
|
-
columnIndex === 0 && /* @__PURE__ */
|
|
4880
|
-
/* @__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(
|
|
4881
3834
|
"span",
|
|
4882
3835
|
{
|
|
4883
3836
|
className: `tabular-nums ${display === "" ? "text-muted-foreground" : "truncate text-foreground"}`,
|
|
@@ -4886,7 +3839,7 @@ function RecordGrid({
|
|
|
4886
3839
|
)
|
|
4887
3840
|
] }) }, column.id);
|
|
4888
3841
|
}),
|
|
4889
|
-
/* @__PURE__ */
|
|
3842
|
+
/* @__PURE__ */ jsx10("td", { role: "gridcell", className: "px-3 py-2 text-right", children: /* @__PURE__ */ jsx10(
|
|
4890
3843
|
ReviewActions,
|
|
4891
3844
|
{
|
|
4892
3845
|
rowId: row.id,
|
|
@@ -4902,8 +3855,8 @@ function RecordGrid({
|
|
|
4902
3855
|
);
|
|
4903
3856
|
})
|
|
4904
3857
|
] }),
|
|
4905
|
-
hasFooter && /* @__PURE__ */
|
|
4906
|
-
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(
|
|
4907
3860
|
"td",
|
|
4908
3861
|
{
|
|
4909
3862
|
role: "gridcell",
|
|
@@ -4912,19 +3865,19 @@ function RecordGrid({
|
|
|
4912
3865
|
},
|
|
4913
3866
|
column.id
|
|
4914
3867
|
)),
|
|
4915
|
-
showActionsColumn && /* @__PURE__ */
|
|
3868
|
+
showActionsColumn && /* @__PURE__ */ jsx10("td", { role: "gridcell" })
|
|
4916
3869
|
] }) })
|
|
4917
3870
|
]
|
|
4918
3871
|
}
|
|
4919
3872
|
) }),
|
|
4920
|
-
onCreate && !reviewing && (addForm ?? /* @__PURE__ */
|
|
3873
|
+
onCreate && !reviewing && (addForm ?? /* @__PURE__ */ jsxs8(
|
|
4921
3874
|
"button",
|
|
4922
3875
|
{
|
|
4923
3876
|
type: "button",
|
|
4924
3877
|
onClick: openAdd,
|
|
4925
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",
|
|
4926
3879
|
children: [
|
|
4927
|
-
/* @__PURE__ */
|
|
3880
|
+
/* @__PURE__ */ jsxs8(
|
|
4928
3881
|
"svg",
|
|
4929
3882
|
{
|
|
4930
3883
|
viewBox: "0 0 24 24",
|
|
@@ -4936,8 +3889,8 @@ function RecordGrid({
|
|
|
4936
3889
|
strokeLinejoin: "round",
|
|
4937
3890
|
"aria-hidden": true,
|
|
4938
3891
|
children: [
|
|
4939
|
-
/* @__PURE__ */
|
|
4940
|
-
/* @__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" })
|
|
4941
3894
|
]
|
|
4942
3895
|
}
|
|
4943
3896
|
),
|
|
@@ -4949,8 +3902,8 @@ function RecordGrid({
|
|
|
4949
3902
|
}
|
|
4950
3903
|
function ReviewActions({ rowId, kind, rowLabel, onAccept, onReject }) {
|
|
4951
3904
|
const noun = kind === "changed" ? `proposed change to ${rowLabel}` : kind === "added" ? `new row ${rowLabel}` : `removal of ${rowLabel}`;
|
|
4952
|
-
return /* @__PURE__ */
|
|
4953
|
-
onReject && /* @__PURE__ */
|
|
3905
|
+
return /* @__PURE__ */ jsxs8("span", { className: "inline-flex items-center gap-1.5", children: [
|
|
3906
|
+
onReject && /* @__PURE__ */ jsx10(
|
|
4954
3907
|
"button",
|
|
4955
3908
|
{
|
|
4956
3909
|
type: "button",
|
|
@@ -4960,7 +3913,7 @@ function ReviewActions({ rowId, kind, rowLabel, onAccept, onReject }) {
|
|
|
4960
3913
|
children: "Reject"
|
|
4961
3914
|
}
|
|
4962
3915
|
),
|
|
4963
|
-
onAccept && /* @__PURE__ */
|
|
3916
|
+
onAccept && /* @__PURE__ */ jsx10(
|
|
4964
3917
|
"button",
|
|
4965
3918
|
{
|
|
4966
3919
|
type: "button",
|
|
@@ -4981,7 +3934,7 @@ function CellEditor({ column, rowLabel, text, invalid, describedBy, onText, onCo
|
|
|
4981
3934
|
className: INPUT_CLASS
|
|
4982
3935
|
};
|
|
4983
3936
|
if (column.kind === "select") {
|
|
4984
|
-
return /* @__PURE__ */
|
|
3937
|
+
return /* @__PURE__ */ jsxs8(
|
|
4985
3938
|
"select",
|
|
4986
3939
|
{
|
|
4987
3940
|
...shared,
|
|
@@ -4998,8 +3951,8 @@ function CellEditor({ column, rowLabel, text, invalid, describedBy, onText, onCo
|
|
|
4998
3951
|
},
|
|
4999
3952
|
onBlur: () => onCommit(text),
|
|
5000
3953
|
children: [
|
|
5001
|
-
/* @__PURE__ */
|
|
5002
|
-
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))
|
|
5003
3956
|
]
|
|
5004
3957
|
}
|
|
5005
3958
|
);
|
|
@@ -5017,7 +3970,7 @@ function CellEditor({ column, rowLabel, text, invalid, describedBy, onText, onCo
|
|
|
5017
3970
|
}
|
|
5018
3971
|
};
|
|
5019
3972
|
if (column.kind === "text" && column.multiline === true) {
|
|
5020
|
-
return /* @__PURE__ */
|
|
3973
|
+
return /* @__PURE__ */ jsx10(
|
|
5021
3974
|
"textarea",
|
|
5022
3975
|
{
|
|
5023
3976
|
...shared,
|
|
@@ -5029,7 +3982,7 @@ function CellEditor({ column, rowLabel, text, invalid, describedBy, onText, onCo
|
|
|
5029
3982
|
}
|
|
5030
3983
|
);
|
|
5031
3984
|
}
|
|
5032
|
-
return /* @__PURE__ */
|
|
3985
|
+
return /* @__PURE__ */ jsx10(
|
|
5033
3986
|
"input",
|
|
5034
3987
|
{
|
|
5035
3988
|
...shared,
|
|
@@ -5044,15 +3997,15 @@ function CellEditor({ column, rowLabel, text, invalid, describedBy, onText, onCo
|
|
|
5044
3997
|
}
|
|
5045
3998
|
function SourceMarker({ panelId, columnHeader, rowLabel, source, open, onToggle }) {
|
|
5046
3999
|
const basis = source.basis ?? "asserted";
|
|
5047
|
-
const setOpen =
|
|
4000
|
+
const setOpen = useCallback7(
|
|
5048
4001
|
(next) => {
|
|
5049
4002
|
if (!next) onToggle();
|
|
5050
4003
|
},
|
|
5051
4004
|
[onToggle]
|
|
5052
4005
|
);
|
|
5053
4006
|
const { containerRef, triggerRef, panelRef, triggerProps } = usePopover(open, setOpen);
|
|
5054
|
-
return /* @__PURE__ */
|
|
5055
|
-
/* @__PURE__ */
|
|
4007
|
+
return /* @__PURE__ */ jsxs8("span", { ref: containerRef, className: "relative inline-flex", children: [
|
|
4008
|
+
/* @__PURE__ */ jsx10(
|
|
5056
4009
|
"button",
|
|
5057
4010
|
{
|
|
5058
4011
|
type: "button",
|
|
@@ -5065,7 +4018,7 @@ function SourceMarker({ panelId, columnHeader, rowLabel, source, open, onToggle
|
|
|
5065
4018
|
onToggle();
|
|
5066
4019
|
},
|
|
5067
4020
|
className: `inline-flex h-4 w-4 shrink-0 items-center justify-center rounded-full border ${BASIS_TONES2[basis]}`,
|
|
5068
|
-
children: /* @__PURE__ */
|
|
4021
|
+
children: /* @__PURE__ */ jsx10(
|
|
5069
4022
|
"svg",
|
|
5070
4023
|
{
|
|
5071
4024
|
viewBox: "0 0 24 24",
|
|
@@ -5075,12 +4028,12 @@ function SourceMarker({ panelId, columnHeader, rowLabel, source, open, onToggle
|
|
|
5075
4028
|
strokeWidth: "2.5",
|
|
5076
4029
|
strokeLinecap: "round",
|
|
5077
4030
|
"aria-hidden": true,
|
|
5078
|
-
children: /* @__PURE__ */
|
|
4031
|
+
children: /* @__PURE__ */ jsx10("path", { d: "M9 8h6M9 12h6M9 16h3" })
|
|
5079
4032
|
}
|
|
5080
4033
|
)
|
|
5081
4034
|
}
|
|
5082
4035
|
),
|
|
5083
|
-
/* @__PURE__ */
|
|
4036
|
+
/* @__PURE__ */ jsxs8(
|
|
5084
4037
|
PopoverSurface,
|
|
5085
4038
|
{
|
|
5086
4039
|
open,
|
|
@@ -5090,17 +4043,17 @@ function SourceMarker({ panelId, columnHeader, rowLabel, source, open, onToggle
|
|
|
5090
4043
|
panelRef,
|
|
5091
4044
|
className: `w-64 rounded-lg border border-card-edge bg-popover p-3 text-left ${OVERLAY_SHADOW}`,
|
|
5092
4045
|
children: [
|
|
5093
|
-
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: [
|
|
5094
4047
|
"\u201C",
|
|
5095
4048
|
source.quote,
|
|
5096
4049
|
"\u201D"
|
|
5097
4050
|
] }),
|
|
5098
|
-
/* @__PURE__ */
|
|
4051
|
+
/* @__PURE__ */ jsxs8("span", { className: "mt-2 block text-xs text-muted-foreground", children: [
|
|
5099
4052
|
source.label ?? "Source",
|
|
5100
4053
|
source.locator ? ` \xB7 ${source.locator}` : "",
|
|
5101
4054
|
` \xB7 ${BASIS_TITLES[basis]}`
|
|
5102
4055
|
] }),
|
|
5103
|
-
source.href && /* @__PURE__ */
|
|
4056
|
+
source.href && /* @__PURE__ */ jsx10(
|
|
5104
4057
|
"a",
|
|
5105
4058
|
{
|
|
5106
4059
|
href: source.href,
|
|
@@ -5128,8 +4081,8 @@ function AddRecordForm({
|
|
|
5128
4081
|
onSubmit,
|
|
5129
4082
|
onCancel
|
|
5130
4083
|
}) {
|
|
5131
|
-
const groups =
|
|
5132
|
-
return /* @__PURE__ */
|
|
4084
|
+
const groups = useMemo5(() => groupColumns(columns), [columns]);
|
|
4085
|
+
return /* @__PURE__ */ jsxs8(
|
|
5133
4086
|
"form",
|
|
5134
4087
|
{
|
|
5135
4088
|
noValidate: true,
|
|
@@ -5140,31 +4093,31 @@ function AddRecordForm({
|
|
|
5140
4093
|
},
|
|
5141
4094
|
className: "space-y-4 rounded-xl border border-card-edge bg-card p-4",
|
|
5142
4095
|
children: [
|
|
5143
|
-
/* @__PURE__ */
|
|
5144
|
-
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 }),
|
|
5145
4098
|
groups.map((group) => {
|
|
5146
4099
|
const fields = group.columns.filter((column) => isRecordGridCellApplicable(column, draft));
|
|
5147
4100
|
if (fields.length === 0) return null;
|
|
5148
|
-
return /* @__PURE__ */
|
|
4101
|
+
return /* @__PURE__ */ jsxs8(
|
|
5149
4102
|
"fieldset",
|
|
5150
4103
|
{
|
|
5151
4104
|
className: group.label === null ? "min-w-0" : "min-w-0 rounded-lg border border-card-edge p-3",
|
|
5152
4105
|
children: [
|
|
5153
|
-
group.label !== null && /* @__PURE__ */
|
|
5154
|
-
/* @__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) => {
|
|
5155
4108
|
const fieldId = `${fieldPrefix}-${column.id}`;
|
|
5156
4109
|
const errorId = `${fieldId}-error`;
|
|
5157
4110
|
const message = errors[column.id];
|
|
5158
|
-
return /* @__PURE__ */
|
|
4111
|
+
return /* @__PURE__ */ jsxs8(
|
|
5159
4112
|
"div",
|
|
5160
4113
|
{
|
|
5161
4114
|
className: column.kind === "text" && column.multiline === true ? "sm:col-span-2" : "",
|
|
5162
4115
|
children: [
|
|
5163
|
-
/* @__PURE__ */
|
|
4116
|
+
/* @__PURE__ */ jsxs8("label", { htmlFor: fieldId, className: "mb-1 block text-xs font-medium text-muted-foreground", children: [
|
|
5164
4117
|
column.header,
|
|
5165
|
-
column.required === true && /* @__PURE__ */
|
|
4118
|
+
column.required === true && /* @__PURE__ */ jsx10("span", { className: "ml-0.5 text-destructive", children: "*" })
|
|
5166
4119
|
] }),
|
|
5167
|
-
/* @__PURE__ */
|
|
4120
|
+
/* @__PURE__ */ jsx10(
|
|
5168
4121
|
DraftField,
|
|
5169
4122
|
{
|
|
5170
4123
|
column,
|
|
@@ -5175,8 +4128,8 @@ function AddRecordForm({
|
|
|
5175
4128
|
onValue: (next) => setDraft({ ...draft, [column.id]: next })
|
|
5176
4129
|
}
|
|
5177
4130
|
),
|
|
5178
|
-
column.hint && /* @__PURE__ */
|
|
5179
|
-
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 })
|
|
5180
4133
|
]
|
|
5181
4134
|
},
|
|
5182
4135
|
column.id
|
|
@@ -5187,8 +4140,8 @@ function AddRecordForm({
|
|
|
5187
4140
|
group.label ?? "_"
|
|
5188
4141
|
);
|
|
5189
4142
|
}),
|
|
5190
|
-
/* @__PURE__ */
|
|
5191
|
-
/* @__PURE__ */
|
|
4143
|
+
/* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-2", children: [
|
|
4144
|
+
/* @__PURE__ */ jsx10(
|
|
5192
4145
|
"button",
|
|
5193
4146
|
{
|
|
5194
4147
|
type: "submit",
|
|
@@ -5197,7 +4150,7 @@ function AddRecordForm({
|
|
|
5197
4150
|
children: busy ? "Saving\u2026" : "Save"
|
|
5198
4151
|
}
|
|
5199
4152
|
),
|
|
5200
|
-
/* @__PURE__ */
|
|
4153
|
+
/* @__PURE__ */ jsx10(
|
|
5201
4154
|
"button",
|
|
5202
4155
|
{
|
|
5203
4156
|
type: "button",
|
|
@@ -5218,7 +4171,7 @@ function DraftField({ column, id, value, invalid, describedBy, onValue }) {
|
|
|
5218
4171
|
"aria-describedby": describedBy
|
|
5219
4172
|
};
|
|
5220
4173
|
if (column.kind === "boolean") {
|
|
5221
|
-
return /* @__PURE__ */
|
|
4174
|
+
return /* @__PURE__ */ jsx10(
|
|
5222
4175
|
"input",
|
|
5223
4176
|
{
|
|
5224
4177
|
...shared,
|
|
@@ -5230,7 +4183,7 @@ function DraftField({ column, id, value, invalid, describedBy, onValue }) {
|
|
|
5230
4183
|
);
|
|
5231
4184
|
}
|
|
5232
4185
|
if (column.kind === "select") {
|
|
5233
|
-
return /* @__PURE__ */
|
|
4186
|
+
return /* @__PURE__ */ jsxs8(
|
|
5234
4187
|
"select",
|
|
5235
4188
|
{
|
|
5236
4189
|
...shared,
|
|
@@ -5238,14 +4191,14 @@ function DraftField({ column, id, value, invalid, describedBy, onValue }) {
|
|
|
5238
4191
|
value: typeof value === "string" ? value : "",
|
|
5239
4192
|
onChange: (event) => onValue(event.target.value === "" ? null : event.target.value),
|
|
5240
4193
|
children: [
|
|
5241
|
-
/* @__PURE__ */
|
|
5242
|
-
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))
|
|
5243
4196
|
]
|
|
5244
4197
|
}
|
|
5245
4198
|
);
|
|
5246
4199
|
}
|
|
5247
4200
|
if (column.kind === "text" && column.multiline === true) {
|
|
5248
|
-
return /* @__PURE__ */
|
|
4201
|
+
return /* @__PURE__ */ jsx10(
|
|
5249
4202
|
"textarea",
|
|
5250
4203
|
{
|
|
5251
4204
|
...shared,
|
|
@@ -5257,7 +4210,7 @@ function DraftField({ column, id, value, invalid, describedBy, onValue }) {
|
|
|
5257
4210
|
);
|
|
5258
4211
|
}
|
|
5259
4212
|
if (column.kind === "number" || column.kind === "currency") {
|
|
5260
|
-
return /* @__PURE__ */
|
|
4213
|
+
return /* @__PURE__ */ jsx10(
|
|
5261
4214
|
"input",
|
|
5262
4215
|
{
|
|
5263
4216
|
...shared,
|
|
@@ -5277,7 +4230,7 @@ function DraftField({ column, id, value, invalid, describedBy, onValue }) {
|
|
|
5277
4230
|
}
|
|
5278
4231
|
);
|
|
5279
4232
|
}
|
|
5280
|
-
return /* @__PURE__ */
|
|
4233
|
+
return /* @__PURE__ */ jsx10(
|
|
5281
4234
|
"input",
|
|
5282
4235
|
{
|
|
5283
4236
|
...shared,
|
|
@@ -5291,19 +4244,19 @@ function DraftField({ column, id, value, invalid, describedBy, onValue }) {
|
|
|
5291
4244
|
|
|
5292
4245
|
// src/web-react/command-palette.tsx
|
|
5293
4246
|
import {
|
|
5294
|
-
useCallback as
|
|
5295
|
-
useEffect as
|
|
5296
|
-
useId as
|
|
5297
|
-
useMemo as
|
|
5298
|
-
useRef as
|
|
5299
|
-
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
|
|
5300
4253
|
} from "react";
|
|
5301
4254
|
import { createPortal } from "react-dom";
|
|
5302
|
-
import { Fragment as
|
|
4255
|
+
import { Fragment as Fragment5, jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
5303
4256
|
function SearchGlyph({ className }) {
|
|
5304
|
-
return /* @__PURE__ */
|
|
5305
|
-
/* @__PURE__ */
|
|
5306
|
-
/* @__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" })
|
|
5307
4260
|
] });
|
|
5308
4261
|
}
|
|
5309
4262
|
function CommandPalette({
|
|
@@ -5318,25 +4271,25 @@ function CommandPalette({
|
|
|
5318
4271
|
emptyMessage,
|
|
5319
4272
|
label = "Command palette"
|
|
5320
4273
|
}) {
|
|
5321
|
-
const [internalOpen, setInternalOpen] =
|
|
4274
|
+
const [internalOpen, setInternalOpen] = useState13(false);
|
|
5322
4275
|
const open = controlledOpen ?? internalOpen;
|
|
5323
|
-
const setOpen =
|
|
4276
|
+
const setOpen = useCallback8(
|
|
5324
4277
|
(next) => {
|
|
5325
4278
|
if (controlledOpen === void 0) setInternalOpen(next);
|
|
5326
4279
|
onOpenChange?.(next);
|
|
5327
4280
|
},
|
|
5328
4281
|
[controlledOpen, onOpenChange]
|
|
5329
4282
|
);
|
|
5330
|
-
const [query, setQuery] =
|
|
5331
|
-
const [active, setActive] =
|
|
5332
|
-
const inputRef =
|
|
5333
|
-
const surfaceId =
|
|
4283
|
+
const [query, setQuery] = useState13(initialQuery ?? "");
|
|
4284
|
+
const [active, setActive] = useState13(0);
|
|
4285
|
+
const inputRef = useRef9(null);
|
|
4286
|
+
const surfaceId = useId3();
|
|
5334
4287
|
const listId = `${surfaceId}-list`;
|
|
5335
|
-
const flat =
|
|
5336
|
-
const sections =
|
|
4288
|
+
const flat = useMemo6(() => filterCommandPaletteItems(items, query), [items, query]);
|
|
4289
|
+
const sections = useMemo6(() => groupCommandPaletteItems(flat), [flat]);
|
|
5337
4290
|
const activeIndex = flat.length === 0 ? 0 : Math.min(active, flat.length - 1);
|
|
5338
4291
|
const activeId = flat.length > 0 ? `${listId}-${activeIndex}` : void 0;
|
|
5339
|
-
|
|
4292
|
+
useEffect9(() => {
|
|
5340
4293
|
if (!hotkey) return;
|
|
5341
4294
|
function onKeyDown(e) {
|
|
5342
4295
|
if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === "k") {
|
|
@@ -5347,8 +4300,8 @@ function CommandPalette({
|
|
|
5347
4300
|
document.addEventListener("keydown", onKeyDown);
|
|
5348
4301
|
return () => document.removeEventListener("keydown", onKeyDown);
|
|
5349
4302
|
}, [hotkey, open, setOpen]);
|
|
5350
|
-
const restoreFocusRef =
|
|
5351
|
-
|
|
4303
|
+
const restoreFocusRef = useRef9(null);
|
|
4304
|
+
useEffect9(() => {
|
|
5352
4305
|
if (open) {
|
|
5353
4306
|
restoreFocusRef.current = document.activeElement;
|
|
5354
4307
|
inputRef.current?.focus();
|
|
@@ -5360,11 +4313,11 @@ function CommandPalette({
|
|
|
5360
4313
|
restoreFocusRef.current = null;
|
|
5361
4314
|
if (restore instanceof HTMLElement) restore.focus();
|
|
5362
4315
|
}, [open]);
|
|
5363
|
-
|
|
4316
|
+
useEffect9(() => {
|
|
5364
4317
|
if (!open || !activeId) return;
|
|
5365
4318
|
document.getElementById(activeId)?.scrollIntoView?.({ block: "nearest" });
|
|
5366
4319
|
}, [open, activeId]);
|
|
5367
|
-
const choose =
|
|
4320
|
+
const choose = useCallback8(
|
|
5368
4321
|
(item) => {
|
|
5369
4322
|
onSelect(item);
|
|
5370
4323
|
setOpen(false);
|
|
@@ -5390,8 +4343,8 @@ function CommandPalette({
|
|
|
5390
4343
|
if (!open || typeof document === "undefined") return null;
|
|
5391
4344
|
let rowIndex = -1;
|
|
5392
4345
|
return createPortal(
|
|
5393
|
-
/* @__PURE__ */
|
|
5394
|
-
/* @__PURE__ */
|
|
4346
|
+
/* @__PURE__ */ jsxs9(Fragment5, { children: [
|
|
4347
|
+
/* @__PURE__ */ jsx11(
|
|
5395
4348
|
"div",
|
|
5396
4349
|
{
|
|
5397
4350
|
"aria-hidden": true,
|
|
@@ -5400,7 +4353,7 @@ function CommandPalette({
|
|
|
5400
4353
|
className: "fixed inset-0 z-[999] bg-background/80"
|
|
5401
4354
|
}
|
|
5402
4355
|
),
|
|
5403
|
-
/* @__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(
|
|
5404
4357
|
"div",
|
|
5405
4358
|
{
|
|
5406
4359
|
role: "dialog",
|
|
@@ -5409,9 +4362,9 @@ function CommandPalette({
|
|
|
5409
4362
|
...{ [POPOVER_SURFACE_ATTR]: surfaceId },
|
|
5410
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}`,
|
|
5411
4364
|
children: [
|
|
5412
|
-
/* @__PURE__ */
|
|
5413
|
-
/* @__PURE__ */
|
|
5414
|
-
/* @__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(
|
|
5415
4368
|
"input",
|
|
5416
4369
|
{
|
|
5417
4370
|
ref: inputRef,
|
|
@@ -5432,15 +4385,15 @@ function CommandPalette({
|
|
|
5432
4385
|
}
|
|
5433
4386
|
)
|
|
5434
4387
|
] }),
|
|
5435
|
-
/* @__PURE__ */
|
|
5436
|
-
loading && /* @__PURE__ */
|
|
5437
|
-
!loading && flat.length === 0 && /* @__PURE__ */
|
|
5438
|
-
!loading && sections.map((section) => /* @__PURE__ */
|
|
5439
|
-
/* @__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 }),
|
|
5440
4393
|
section.items.map((item) => {
|
|
5441
4394
|
rowIndex += 1;
|
|
5442
4395
|
const index = rowIndex;
|
|
5443
|
-
return /* @__PURE__ */
|
|
4396
|
+
return /* @__PURE__ */ jsxs9(
|
|
5444
4397
|
"div",
|
|
5445
4398
|
{
|
|
5446
4399
|
id: `${listId}-${index}`,
|
|
@@ -5450,9 +4403,9 @@ function CommandPalette({
|
|
|
5450
4403
|
onClick: () => choose(item),
|
|
5451
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" : ""}`,
|
|
5452
4405
|
children: [
|
|
5453
|
-
/* @__PURE__ */
|
|
5454
|
-
item.description && /* @__PURE__ */
|
|
5455
|
-
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 })
|
|
5456
4409
|
]
|
|
5457
4410
|
},
|
|
5458
4411
|
item.id
|
|
@@ -5460,15 +4413,15 @@ function CommandPalette({
|
|
|
5460
4413
|
})
|
|
5461
4414
|
] }, section.group))
|
|
5462
4415
|
] }),
|
|
5463
|
-
/* @__PURE__ */
|
|
5464
|
-
/* @__PURE__ */
|
|
5465
|
-
/* @__PURE__ */
|
|
5466
|
-
/* @__PURE__ */
|
|
5467
|
-
/* @__PURE__ */
|
|
5468
|
-
/* @__PURE__ */
|
|
5469
|
-
/* @__PURE__ */
|
|
5470
|
-
/* @__PURE__ */
|
|
5471
|
-
/* @__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" })
|
|
5472
4425
|
] })
|
|
5473
4426
|
] })
|
|
5474
4427
|
]
|
|
@@ -5480,7 +4433,7 @@ function CommandPalette({
|
|
|
5480
4433
|
}
|
|
5481
4434
|
|
|
5482
4435
|
// src/web-react/sparkline.tsx
|
|
5483
|
-
import { jsx as
|
|
4436
|
+
import { jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
5484
4437
|
var DEFAULT_SPARKLINE_WIDTH = 96;
|
|
5485
4438
|
var DEFAULT_SPARKLINE_HEIGHT = 24;
|
|
5486
4439
|
var DEFAULT_INSET = 2.5;
|
|
@@ -5586,21 +4539,21 @@ function Sparkline({
|
|
|
5586
4539
|
const geometry = sparklineGeometry(values, { width, height });
|
|
5587
4540
|
const accessibleName = sparklineLabel(values, { label, format });
|
|
5588
4541
|
if (geometry.points.length === 0) {
|
|
5589
|
-
return /* @__PURE__ */
|
|
4542
|
+
return /* @__PURE__ */ jsxs10(
|
|
5590
4543
|
"span",
|
|
5591
4544
|
{
|
|
5592
4545
|
"data-sparkline": geometry.gaps > 0 ? "unavailable" : "empty",
|
|
5593
4546
|
className: joinClasses("text-[11px] text-muted-foreground", className),
|
|
5594
4547
|
children: [
|
|
5595
|
-
/* @__PURE__ */
|
|
5596
|
-
/* @__PURE__ */
|
|
4548
|
+
/* @__PURE__ */ jsx12("span", { className: "sr-only", children: accessibleName }),
|
|
4549
|
+
/* @__PURE__ */ jsx12("span", { "aria-hidden": "true", children: geometry.gaps > 0 ? unavailableLabel : emptyLabel })
|
|
5597
4550
|
]
|
|
5598
4551
|
}
|
|
5599
4552
|
);
|
|
5600
4553
|
}
|
|
5601
4554
|
const drawsLine = geometry.segments.some((segment) => segment.length > 1);
|
|
5602
4555
|
const end = geometry.points[geometry.points.length - 1];
|
|
5603
|
-
return /* @__PURE__ */
|
|
4556
|
+
return /* @__PURE__ */ jsxs10(
|
|
5604
4557
|
"svg",
|
|
5605
4558
|
{
|
|
5606
4559
|
role: "img",
|
|
@@ -5617,7 +4570,7 @@ function Sparkline({
|
|
|
5617
4570
|
geometry.segments.map((segment, index) => {
|
|
5618
4571
|
const key = `segment-${index}`;
|
|
5619
4572
|
if (segment.length > 1) {
|
|
5620
|
-
return /* @__PURE__ */
|
|
4573
|
+
return /* @__PURE__ */ jsx12(
|
|
5621
4574
|
"polyline",
|
|
5622
4575
|
{
|
|
5623
4576
|
points: sparklinePointsAttribute(segment),
|
|
@@ -5633,9 +4586,9 @@ function Sparkline({
|
|
|
5633
4586
|
}
|
|
5634
4587
|
const only = segment[0];
|
|
5635
4588
|
if (only.x === end.x && only.y === end.y) return null;
|
|
5636
|
-
return /* @__PURE__ */
|
|
4589
|
+
return /* @__PURE__ */ jsx12("circle", { cx: only.x, cy: only.y, r: DOT_RADIUS, fill: "currentColor" }, key);
|
|
5637
4590
|
}),
|
|
5638
|
-
/* @__PURE__ */
|
|
4591
|
+
/* @__PURE__ */ jsx12("circle", { cx: end.x, cy: end.y, r: DOT_RADIUS, fill: "currentColor" })
|
|
5639
4592
|
]
|
|
5640
4593
|
}
|
|
5641
4594
|
);
|
|
@@ -5644,12 +4597,12 @@ function Sparkline({
|
|
|
5644
4597
|
// src/web-react/insight-card.tsx
|
|
5645
4598
|
import {
|
|
5646
4599
|
isValidElement as isValidElement2,
|
|
5647
|
-
useCallback as
|
|
5648
|
-
useEffect as
|
|
5649
|
-
useRef as
|
|
5650
|
-
useState as
|
|
4600
|
+
useCallback as useCallback9,
|
|
4601
|
+
useEffect as useEffect10,
|
|
4602
|
+
useRef as useRef10,
|
|
4603
|
+
useState as useState14
|
|
5651
4604
|
} from "react";
|
|
5652
|
-
import { Fragment as
|
|
4605
|
+
import { Fragment as Fragment6, jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
5653
4606
|
function insightDelta(value, previous) {
|
|
5654
4607
|
if (typeof value !== "number" || !Number.isFinite(value)) return null;
|
|
5655
4608
|
if (typeof previous !== "number" || !Number.isFinite(previous)) return null;
|
|
@@ -5702,7 +4655,7 @@ function InsightCard({
|
|
|
5702
4655
|
const tone = delta ? insightDeltaTone(delta.direction, polarity) : "neutral";
|
|
5703
4656
|
const unavailable = typeof value === "number" && !Number.isFinite(value);
|
|
5704
4657
|
const shown = typeof value === "number" ? format(value) : value;
|
|
5705
|
-
return /* @__PURE__ */
|
|
4658
|
+
return /* @__PURE__ */ jsxs11(
|
|
5706
4659
|
"article",
|
|
5707
4660
|
{
|
|
5708
4661
|
"data-insight-card": "",
|
|
@@ -5710,40 +4663,40 @@ function InsightCard({
|
|
|
5710
4663
|
className: joinClasses("agent-arrive flex h-full flex-col rounded-xl border border-card-edge bg-card p-4", className),
|
|
5711
4664
|
style,
|
|
5712
4665
|
children: [
|
|
5713
|
-
eyebrow ? /* @__PURE__ */
|
|
5714
|
-
/* @__PURE__ */
|
|
5715
|
-
/* @__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 }),
|
|
5716
4669
|
live ? (
|
|
5717
4670
|
// No `data-motion` opt-out: the word is the signal and the sweep is
|
|
5718
4671
|
// emphasis, so the reduced-motion floor reaches this like everything
|
|
5719
4672
|
// else and leaves a static, legible label.
|
|
5720
|
-
/* @__PURE__ */
|
|
4673
|
+
/* @__PURE__ */ jsx13("span", { className: "agent-shimmer shrink-0 text-[11px] font-medium", "data-insight-live": "", children: liveLabel })
|
|
5721
4674
|
) : null
|
|
5722
4675
|
] }),
|
|
5723
|
-
/* @__PURE__ */
|
|
5724
|
-
/* @__PURE__ */
|
|
5725
|
-
/* @__PURE__ */
|
|
5726
|
-
] }) : /* @__PURE__ */
|
|
5727
|
-
/* @__PURE__ */
|
|
5728
|
-
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
|
|
5729
4682
|
] }) }),
|
|
5730
|
-
delta ? /* @__PURE__ */
|
|
5731
|
-
/* @__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: [
|
|
5732
4685
|
DIRECTION_GLYPH[delta.direction],
|
|
5733
4686
|
" "
|
|
5734
4687
|
] }),
|
|
5735
4688
|
formatInsightDelta(delta, format)
|
|
5736
4689
|
] }) : null,
|
|
5737
|
-
description ? /* @__PURE__ */
|
|
5738
|
-
series ? /* @__PURE__ */
|
|
5739
|
-
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
|
|
5740
4693
|
]
|
|
5741
4694
|
}
|
|
5742
4695
|
);
|
|
5743
4696
|
}
|
|
5744
4697
|
function renderInsightAction(action) {
|
|
5745
4698
|
if (isValidElement2(action)) return action;
|
|
5746
|
-
return /* @__PURE__ */
|
|
4699
|
+
return /* @__PURE__ */ jsx13(
|
|
5747
4700
|
"button",
|
|
5748
4701
|
{
|
|
5749
4702
|
type: "button",
|
|
@@ -5812,15 +4765,15 @@ function InsightDeck({
|
|
|
5812
4765
|
className,
|
|
5813
4766
|
onPageChange
|
|
5814
4767
|
}) {
|
|
5815
|
-
const [page, setPage] =
|
|
5816
|
-
const [held, setHeld] =
|
|
4768
|
+
const [page, setPage] = useState14(0);
|
|
4769
|
+
const [held, setHeld] = useState14(null);
|
|
5817
4770
|
const answered = state.status === "error" || state.status === "empty";
|
|
5818
4771
|
const carried = state.status === "ready" ? state.value : answered ? null : held;
|
|
5819
4772
|
if (carried !== held) setHeld(carried);
|
|
5820
4773
|
const shown = carried !== null && state.status !== "ready" ? { status: "ready", value: carried, retry: state.retry } : state;
|
|
5821
4774
|
const refreshing = shown !== state;
|
|
5822
|
-
const reported =
|
|
5823
|
-
const settlePage =
|
|
4775
|
+
const reported = useRef10(0);
|
|
4776
|
+
const settlePage = useCallback9(
|
|
5824
4777
|
(next) => {
|
|
5825
4778
|
if (reported.current === next) return;
|
|
5826
4779
|
reported.current = next;
|
|
@@ -5828,7 +4781,7 @@ function InsightDeck({
|
|
|
5828
4781
|
},
|
|
5829
4782
|
[onPageChange]
|
|
5830
4783
|
);
|
|
5831
|
-
return /* @__PURE__ */
|
|
4784
|
+
return /* @__PURE__ */ jsx13(
|
|
5832
4785
|
AsyncView,
|
|
5833
4786
|
{
|
|
5834
4787
|
state: shown,
|
|
@@ -5836,7 +4789,7 @@ function InsightDeck({
|
|
|
5836
4789
|
loadingLabel,
|
|
5837
4790
|
retryLabel,
|
|
5838
4791
|
className,
|
|
5839
|
-
children: (insights) => /* @__PURE__ */
|
|
4792
|
+
children: (insights) => /* @__PURE__ */ jsx13(
|
|
5840
4793
|
InsightPages,
|
|
5841
4794
|
{
|
|
5842
4795
|
insights,
|
|
@@ -5903,18 +4856,18 @@ function InsightPages({
|
|
|
5903
4856
|
const pageCount = insightPageCount(insights.length, size);
|
|
5904
4857
|
const current = Math.min(Math.max(page, 0), pageCount - 1);
|
|
5905
4858
|
const visible = insightPageSlice(insights, current, size);
|
|
5906
|
-
const sectionRef =
|
|
5907
|
-
const listRef =
|
|
5908
|
-
const recoverFocus =
|
|
5909
|
-
|
|
4859
|
+
const sectionRef = useRef10(null);
|
|
4860
|
+
const listRef = useRef10(null);
|
|
4861
|
+
const recoverFocus = useRef10(false);
|
|
4862
|
+
useEffect10(() => {
|
|
5910
4863
|
onPageSettled(current);
|
|
5911
4864
|
}, [current, onPageSettled]);
|
|
5912
|
-
|
|
4865
|
+
useEffect10(() => {
|
|
5913
4866
|
if (!recoverFocus.current) return;
|
|
5914
4867
|
recoverFocus.current = false;
|
|
5915
4868
|
sectionRef.current?.focus();
|
|
5916
4869
|
}, [current]);
|
|
5917
|
-
const goTo =
|
|
4870
|
+
const goTo = useCallback9(
|
|
5918
4871
|
(next) => {
|
|
5919
4872
|
const clamped = Math.min(Math.max(next, 0), pageCount - 1);
|
|
5920
4873
|
if (clamped === current) return false;
|
|
@@ -5949,7 +4902,7 @@ function InsightPages({
|
|
|
5949
4902
|
}
|
|
5950
4903
|
if (moved) event.preventDefault();
|
|
5951
4904
|
};
|
|
5952
|
-
return /* @__PURE__ */
|
|
4905
|
+
return /* @__PURE__ */ jsxs11(
|
|
5953
4906
|
"section",
|
|
5954
4907
|
{
|
|
5955
4908
|
ref: sectionRef,
|
|
@@ -5961,7 +4914,7 @@ function InsightPages({
|
|
|
5961
4914
|
tabIndex: pageCount > 1 ? 0 : void 0,
|
|
5962
4915
|
"aria-keyshortcuts": pageCount > 1 ? "ArrowLeft ArrowRight PageUp PageDown Home End" : void 0,
|
|
5963
4916
|
children: [
|
|
5964
|
-
/* @__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) => (
|
|
5965
4918
|
// The page index is in the key on purpose: a page turn is an arrival,
|
|
5966
4919
|
// and reusing the node would swap the text under a card that never
|
|
5967
4920
|
// moved. Remounting replays `.agent-arrive` with the new stagger.
|
|
@@ -5972,10 +4925,10 @@ function InsightPages({
|
|
|
5972
4925
|
// does not arrive a second time. The key does BOTH jobs — but only
|
|
5973
4926
|
// because the deck now keeps this subtree mounted across a reload
|
|
5974
4927
|
// (see `InsightDeck`); a key is never compared across a teardown.
|
|
5975
|
-
/* @__PURE__ */
|
|
4928
|
+
/* @__PURE__ */ jsx13("li", { children: /* @__PURE__ */ jsx13(InsightCard, { ...card, style: staggerStyle(index, style) }) }, `${current}:${id}`)
|
|
5976
4929
|
)) }),
|
|
5977
|
-
/* @__PURE__ */
|
|
5978
|
-
/* @__PURE__ */
|
|
4930
|
+
/* @__PURE__ */ jsxs11("div", { className: pageCount > 1 ? "flex items-center justify-between gap-2" : void 0, children: [
|
|
4931
|
+
/* @__PURE__ */ jsxs11(
|
|
5979
4932
|
"p",
|
|
5980
4933
|
{
|
|
5981
4934
|
role: "status",
|
|
@@ -5989,8 +4942,8 @@ function InsightPages({
|
|
|
5989
4942
|
]
|
|
5990
4943
|
}
|
|
5991
4944
|
),
|
|
5992
|
-
pageCount > 1 ? /* @__PURE__ */
|
|
5993
|
-
/* @__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) }),
|
|
5994
4947
|
pageCount <= MAX_PAGE_DOTS ? Array.from({ length: pageCount }, (_, index) => (
|
|
5995
4948
|
// WCAG 2.2 SC 2.5.8 wants a 24x24 CSS px target. The dot stays
|
|
5996
4949
|
// 8px because a 24px dot is a different control; the BUTTON
|
|
@@ -5998,7 +4951,7 @@ function InsightPages({
|
|
|
5998
4951
|
// and the span is the graphic. The Spacing exception cannot
|
|
5999
4952
|
// rescue the bare dot — at a 12px pitch the 24px circle around
|
|
6000
4953
|
// each centre overlaps its neighbour's.
|
|
6001
|
-
/* @__PURE__ */
|
|
4954
|
+
/* @__PURE__ */ jsx13(
|
|
6002
4955
|
"button",
|
|
6003
4956
|
{
|
|
6004
4957
|
type: "button",
|
|
@@ -6006,7 +4959,7 @@ function InsightPages({
|
|
|
6006
4959
|
"aria-current": index === current ? "page" : void 0,
|
|
6007
4960
|
onClick: () => goTo(index),
|
|
6008
4961
|
className: "group flex h-6 w-6 shrink-0 items-center justify-center rounded-full",
|
|
6009
|
-
children: /* @__PURE__ */
|
|
4962
|
+
children: /* @__PURE__ */ jsx13(
|
|
6010
4963
|
"span",
|
|
6011
4964
|
{
|
|
6012
4965
|
"aria-hidden": "true",
|
|
@@ -6020,7 +4973,7 @@ function InsightPages({
|
|
|
6020
4973
|
index
|
|
6021
4974
|
)
|
|
6022
4975
|
)) : null,
|
|
6023
|
-
/* @__PURE__ */
|
|
4976
|
+
/* @__PURE__ */ jsx13(
|
|
6024
4977
|
PagerButton,
|
|
6025
4978
|
{
|
|
6026
4979
|
label: "Next insights",
|
|
@@ -6041,7 +4994,7 @@ function PagerButton({
|
|
|
6041
4994
|
atEnd,
|
|
6042
4995
|
onClick
|
|
6043
4996
|
}) {
|
|
6044
|
-
return /* @__PURE__ */
|
|
4997
|
+
return /* @__PURE__ */ jsx13(
|
|
6045
4998
|
"button",
|
|
6046
4999
|
{
|
|
6047
5000
|
type: "button",
|
|
@@ -6051,13 +5004,13 @@ function PagerButton({
|
|
|
6051
5004
|
if (!atEnd) onClick();
|
|
6052
5005
|
},
|
|
6053
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"}`,
|
|
6054
|
-
children: /* @__PURE__ */
|
|
5007
|
+
children: /* @__PURE__ */ jsx13("span", { "aria-hidden": "true", children: glyph })
|
|
6055
5008
|
}
|
|
6056
5009
|
);
|
|
6057
5010
|
}
|
|
6058
5011
|
|
|
6059
5012
|
// src/web-react/index.tsx
|
|
6060
|
-
import { Fragment as
|
|
5013
|
+
import { Fragment as Fragment7, jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
6061
5014
|
function formatModelCost(msg, models) {
|
|
6062
5015
|
if (msg.promptTokens == null && msg.completionTokens == null) return null;
|
|
6063
5016
|
const pricing = models.find((m) => m.id === msg.modelUsed)?.pricing;
|
|
@@ -6076,41 +5029,41 @@ function formatTokensPerSecond(msg) {
|
|
|
6076
5029
|
return `${Math.round(msg.completionTokens / (msg.durationMs / 1e3))} tok/s`;
|
|
6077
5030
|
}
|
|
6078
5031
|
function RunDrillIn({ run, onClose }) {
|
|
6079
|
-
return /* @__PURE__ */
|
|
6080
|
-
/* @__PURE__ */
|
|
6081
|
-
/* @__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(
|
|
6082
5035
|
"span",
|
|
6083
5036
|
{
|
|
6084
5037
|
className: `h-2 w-2 shrink-0 rounded-full ${run.status === "running" ? "bg-warning" : run.status === "error" ? "bg-destructive" : "bg-success"}`
|
|
6085
5038
|
}
|
|
6086
5039
|
),
|
|
6087
|
-
/* @__PURE__ */
|
|
6088
|
-
/* @__PURE__ */
|
|
6089
|
-
/* @__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 })
|
|
6090
5043
|
] }),
|
|
6091
|
-
/* @__PURE__ */
|
|
5044
|
+
/* @__PURE__ */ jsx14(
|
|
6092
5045
|
"button",
|
|
6093
5046
|
{
|
|
6094
5047
|
type: "button",
|
|
6095
5048
|
onClick: onClose,
|
|
6096
5049
|
"aria-label": "Close",
|
|
6097
5050
|
className: "rounded-md p-1.5 text-muted-foreground transition hover:bg-accent hover:text-foreground",
|
|
6098
|
-
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" }) })
|
|
6099
5052
|
}
|
|
6100
5053
|
)
|
|
6101
5054
|
] }),
|
|
6102
|
-
/* @__PURE__ */
|
|
6103
|
-
run.steps.length === 0 && /* @__PURE__ */
|
|
6104
|
-
run.steps.map((step, i) => /* @__PURE__ */
|
|
6105
|
-
/* @__PURE__ */
|
|
6106
|
-
/* @__PURE__ */
|
|
6107
|
-
/* @__PURE__ */
|
|
6108
|
-
/* @__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" }) })
|
|
6109
5062
|
] }),
|
|
6110
|
-
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 })
|
|
6111
5064
|
] }, i))
|
|
6112
5065
|
] }),
|
|
6113
|
-
/* @__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." })
|
|
6114
5067
|
] });
|
|
6115
5068
|
}
|
|
6116
5069
|
function pendingApprovalOf(call) {
|
|
@@ -6126,23 +5079,23 @@ function ChatEmptyState({
|
|
|
6126
5079
|
}) {
|
|
6127
5080
|
const doorCount = Math.min(doors?.length ?? 0, 3);
|
|
6128
5081
|
const doorsGridClass = doorCount === 1 ? "mx-auto max-w-sm sm:grid-cols-1" : doorCount === 2 ? "sm:grid-cols-2" : "sm:grid-cols-3";
|
|
6129
|
-
return /* @__PURE__ */
|
|
6130
|
-
/* @__PURE__ */
|
|
6131
|
-
/* @__PURE__ */
|
|
6132
|
-
/* @__PURE__ */
|
|
6133
|
-
subline && /* @__PURE__ */
|
|
6134
|
-
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(
|
|
6135
5088
|
"button",
|
|
6136
5089
|
{
|
|
6137
5090
|
type: "button",
|
|
6138
5091
|
onClick: door.onSelect,
|
|
6139
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",
|
|
6140
5093
|
children: [
|
|
6141
|
-
/* @__PURE__ */
|
|
5094
|
+
/* @__PURE__ */ jsxs12("span", { className: "flex items-center gap-2 text-sm font-semibold text-foreground", children: [
|
|
6142
5095
|
door.icon,
|
|
6143
5096
|
door.label
|
|
6144
5097
|
] }),
|
|
6145
|
-
door.description && /* @__PURE__ */
|
|
5098
|
+
door.description && /* @__PURE__ */ jsx14("span", { className: "mt-0.5 text-[12px] leading-snug text-muted-foreground", children: door.description })
|
|
6146
5099
|
]
|
|
6147
5100
|
},
|
|
6148
5101
|
i
|
|
@@ -6151,26 +5104,26 @@ function ChatEmptyState({
|
|
|
6151
5104
|
}
|
|
6152
5105
|
function ToolGlyph({ name, className }) {
|
|
6153
5106
|
if (name.startsWith("sandbox_")) {
|
|
6154
|
-
return /* @__PURE__ */
|
|
6155
|
-
/* @__PURE__ */
|
|
6156
|
-
/* @__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" })
|
|
6157
5110
|
] });
|
|
6158
5111
|
}
|
|
6159
5112
|
if (name === "submit_proposal") {
|
|
6160
|
-
return /* @__PURE__ */
|
|
6161
|
-
/* @__PURE__ */
|
|
6162
|
-
/* @__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" })
|
|
6163
5116
|
] });
|
|
6164
5117
|
}
|
|
6165
5118
|
if (name === "schedule_followup") {
|
|
6166
|
-
return /* @__PURE__ */
|
|
6167
|
-
/* @__PURE__ */
|
|
6168
|
-
/* @__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" })
|
|
6169
5122
|
] });
|
|
6170
5123
|
}
|
|
6171
|
-
return /* @__PURE__ */
|
|
6172
|
-
/* @__PURE__ */
|
|
6173
|
-
/* @__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" })
|
|
6174
5127
|
] });
|
|
6175
5128
|
}
|
|
6176
5129
|
function toolOutcomeOf(call) {
|
|
@@ -6256,40 +5209,40 @@ function truncate(v, max = 240) {
|
|
|
6256
5209
|
function KvRows({ data }) {
|
|
6257
5210
|
const entries = Object.entries(data).filter(([, v]) => v !== void 0 && v !== null && v !== "");
|
|
6258
5211
|
if (!entries.length) return null;
|
|
6259
|
-
return /* @__PURE__ */
|
|
6260
|
-
/* @__PURE__ */
|
|
6261
|
-
/* @__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) })
|
|
6262
5215
|
] }, k)) });
|
|
6263
5216
|
}
|
|
6264
5217
|
function ShellDetail({ call }) {
|
|
6265
5218
|
const outcome = toolOutcomeOf(call);
|
|
6266
5219
|
const r = outcome?.result ?? {};
|
|
6267
|
-
return /* @__PURE__ */
|
|
6268
|
-
/* @__PURE__ */
|
|
6269
|
-
/* @__PURE__ */
|
|
6270
|
-
/* @__PURE__ */
|
|
6271
|
-
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: [
|
|
6272
5225
|
"exit ",
|
|
6273
5226
|
r.exitCode
|
|
6274
5227
|
] })
|
|
6275
5228
|
] }),
|
|
6276
|
-
/* @__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)" })
|
|
6277
5230
|
] });
|
|
6278
5231
|
}
|
|
6279
5232
|
function DefaultToolDetail({ call }) {
|
|
6280
5233
|
const result = call.result;
|
|
6281
5234
|
const envelope = typeof result === "object" && result !== null ? result : null;
|
|
6282
|
-
return /* @__PURE__ */
|
|
6283
|
-
call.args && Object.keys(call.args).length > 0 && /* @__PURE__ */
|
|
6284
|
-
/* @__PURE__ */
|
|
6285
|
-
/* @__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 })
|
|
6286
5239
|
] }),
|
|
6287
|
-
envelope ? /* @__PURE__ */
|
|
6288
|
-
/* @__PURE__ */
|
|
6289
|
-
envelope.ok === false ? /* @__PURE__ */
|
|
6290
|
-
] }) : result != null ? /* @__PURE__ */
|
|
6291
|
-
/* @__PURE__ */
|
|
6292
|
-
/* @__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) })
|
|
6293
5246
|
] }) : null
|
|
6294
5247
|
] });
|
|
6295
5248
|
}
|
|
@@ -6300,24 +5253,24 @@ function ProposalCard({
|
|
|
6300
5253
|
approval,
|
|
6301
5254
|
renderers
|
|
6302
5255
|
}) {
|
|
6303
|
-
const [expanded, setExpanded] =
|
|
5256
|
+
const [expanded, setExpanded] = useState15(false);
|
|
6304
5257
|
const { summary, meta, typeSlug } = proposalPreview(call);
|
|
6305
5258
|
const custom = renderers?.[call.name]?.(call, message);
|
|
6306
5259
|
const { pending: deciding, run: decide } = usePending();
|
|
6307
|
-
return /* @__PURE__ */
|
|
6308
|
-
/* @__PURE__ */
|
|
6309
|
-
/* @__PURE__ */
|
|
6310
|
-
/* @__PURE__ */
|
|
6311
|
-
/* @__PURE__ */
|
|
6312
|
-
/* @__PURE__ */
|
|
6313
|
-
summary && /* @__PURE__ */
|
|
6314
|
-
typeSlug && /* @__PURE__ */
|
|
6315
|
-
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)) })
|
|
6316
5269
|
] })
|
|
6317
5270
|
] }),
|
|
6318
|
-
/* @__PURE__ */
|
|
6319
|
-
approval && /* @__PURE__ */
|
|
6320
|
-
/* @__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(
|
|
6321
5274
|
"button",
|
|
6322
5275
|
{
|
|
6323
5276
|
type: "button",
|
|
@@ -6327,7 +5280,7 @@ function ProposalCard({
|
|
|
6327
5280
|
children: "Approve & run"
|
|
6328
5281
|
}
|
|
6329
5282
|
),
|
|
6330
|
-
/* @__PURE__ */
|
|
5283
|
+
/* @__PURE__ */ jsx14(
|
|
6331
5284
|
"button",
|
|
6332
5285
|
{
|
|
6333
5286
|
type: "button",
|
|
@@ -6338,7 +5291,7 @@ function ProposalCard({
|
|
|
6338
5291
|
}
|
|
6339
5292
|
)
|
|
6340
5293
|
] }),
|
|
6341
|
-
/* @__PURE__ */
|
|
5294
|
+
/* @__PURE__ */ jsxs12(
|
|
6342
5295
|
"button",
|
|
6343
5296
|
{
|
|
6344
5297
|
type: "button",
|
|
@@ -6347,12 +5300,12 @@ function ProposalCard({
|
|
|
6347
5300
|
className: "ml-auto inline-flex items-center gap-1 rounded text-[12px] font-medium text-muted-foreground transition hover:text-foreground",
|
|
6348
5301
|
children: [
|
|
6349
5302
|
expanded ? "Hide details" : "View details",
|
|
6350
|
-
/* @__PURE__ */
|
|
5303
|
+
/* @__PURE__ */ jsx14(ChevronDown, { className: `h-3 w-3 transition-transform ${expanded ? "rotate-180" : ""}` })
|
|
6351
5304
|
]
|
|
6352
5305
|
}
|
|
6353
5306
|
)
|
|
6354
5307
|
] }),
|
|
6355
|
-
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 }) })
|
|
6356
5309
|
] });
|
|
6357
5310
|
}
|
|
6358
5311
|
function formatFollowupWhen(when) {
|
|
@@ -6367,14 +5320,14 @@ function FollowupCard({ call }) {
|
|
|
6367
5320
|
const when = typeof a.when === "string" ? a.when : typeof a.at === "string" ? a.at : typeof a.schedule === "string" ? a.schedule : null;
|
|
6368
5321
|
const failed = toolCallFailed(call);
|
|
6369
5322
|
const errorText = failed ? toolOutcomeOf(call)?.message ?? "Scheduling failed" : null;
|
|
6370
|
-
return /* @__PURE__ */
|
|
6371
|
-
/* @__PURE__ */
|
|
6372
|
-
/* @__PURE__ */
|
|
6373
|
-
/* @__PURE__ */
|
|
6374
|
-
when && /* @__PURE__ */
|
|
6375
|
-
/* @__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)]"}` }) })
|
|
6376
5329
|
] }),
|
|
6377
|
-
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 })
|
|
6378
5331
|
] }) });
|
|
6379
5332
|
}
|
|
6380
5333
|
function toolRowTitle(call) {
|
|
@@ -6397,10 +5350,10 @@ function ToolCallCard({
|
|
|
6397
5350
|
const arrival = useArrivalStyle(staggerIndex ?? 0);
|
|
6398
5351
|
const pending = call.status === "done" ? pendingApprovalOf(call) : null;
|
|
6399
5352
|
const kind = blockKindOf(call);
|
|
6400
|
-
const arrive = (row) => /* @__PURE__ */
|
|
5353
|
+
const arrive = (row) => /* @__PURE__ */ jsx14("div", { className: "agent-arrive", style: arrival, children: row });
|
|
6401
5354
|
if (pending) {
|
|
6402
5355
|
return arrive(
|
|
6403
|
-
/* @__PURE__ */
|
|
5356
|
+
/* @__PURE__ */ jsx14(
|
|
6404
5357
|
ProposalCard,
|
|
6405
5358
|
{
|
|
6406
5359
|
call,
|
|
@@ -6413,18 +5366,18 @@ function ToolCallCard({
|
|
|
6413
5366
|
);
|
|
6414
5367
|
}
|
|
6415
5368
|
if (kind === "followup") {
|
|
6416
|
-
return arrive(/* @__PURE__ */
|
|
5369
|
+
return arrive(/* @__PURE__ */ jsx14(FollowupCard, { call }));
|
|
6417
5370
|
}
|
|
6418
5371
|
const custom = renderers?.[call.name]?.(call, message);
|
|
6419
5372
|
return arrive(
|
|
6420
|
-
/* @__PURE__ */
|
|
5373
|
+
/* @__PURE__ */ jsx14(
|
|
6421
5374
|
InlineToolItem,
|
|
6422
5375
|
{
|
|
6423
5376
|
part: chatToolCallPart(call),
|
|
6424
5377
|
title: toolRowTitle(call),
|
|
6425
5378
|
description: toolRowDescription(call),
|
|
6426
|
-
renderToolDetail: () => custom ?? (call.name === "sandbox_run_command" ? /* @__PURE__ */
|
|
6427
|
-
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(
|
|
6428
5381
|
"button",
|
|
6429
5382
|
{
|
|
6430
5383
|
type: "button",
|
|
@@ -6432,9 +5385,9 @@ function ToolCallCard({
|
|
|
6432
5385
|
"aria-label": "Open full transcript",
|
|
6433
5386
|
title: "Open full transcript",
|
|
6434
5387
|
className: "rounded-md p-1.5 text-muted-foreground transition hover:bg-accent hover:text-foreground",
|
|
6435
|
-
children: /* @__PURE__ */
|
|
6436
|
-
/* @__PURE__ */
|
|
6437
|
-
/* @__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" })
|
|
6438
5391
|
] })
|
|
6439
5392
|
}
|
|
6440
5393
|
) : void 0
|
|
@@ -6443,7 +5396,7 @@ function ToolCallCard({
|
|
|
6443
5396
|
);
|
|
6444
5397
|
}
|
|
6445
5398
|
function StreamingCaret() {
|
|
6446
|
-
return /* @__PURE__ */
|
|
5399
|
+
return /* @__PURE__ */ jsx14(
|
|
6447
5400
|
"span",
|
|
6448
5401
|
{
|
|
6449
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",
|
|
@@ -6460,7 +5413,7 @@ function SegmentText({
|
|
|
6460
5413
|
messageClassName
|
|
6461
5414
|
}) {
|
|
6462
5415
|
const text = useSmoothText(content, streaming);
|
|
6463
|
-
const body =
|
|
5416
|
+
const body = useMemo7(() => renderBody(text), [renderBody, text]);
|
|
6464
5417
|
if (!content.trim() && !showCaret) return null;
|
|
6465
5418
|
return (
|
|
6466
5419
|
// A settled run arrives from a short blur; the LIVE run does not, because
|
|
@@ -6468,9 +5421,9 @@ function SegmentText({
|
|
|
6468
5421
|
// the container on top of that makes the paragraph shimmer while it types.
|
|
6469
5422
|
// The distinction is what separates "the answer materialised" from "the
|
|
6470
5423
|
// log was appended to".
|
|
6471
|
-
/* @__PURE__ */
|
|
5424
|
+
/* @__PURE__ */ jsxs12("div", { className: `${messageClassName}${streaming ? "" : " agent-stream-in"}`, children: [
|
|
6472
5425
|
body,
|
|
6473
|
-
showCaret && /* @__PURE__ */
|
|
5426
|
+
showCaret && /* @__PURE__ */ jsx14(StreamingCaret, {})
|
|
6474
5427
|
] })
|
|
6475
5428
|
);
|
|
6476
5429
|
}
|
|
@@ -6495,7 +5448,7 @@ function SegmentedBody({
|
|
|
6495
5448
|
const leftoverToolCalls = (msg.toolCalls ?? []).filter(
|
|
6496
5449
|
(tc) => !segmentToolIds.has(tc.id)
|
|
6497
5450
|
);
|
|
6498
|
-
const renderToolCard = (call, index) => /* @__PURE__ */
|
|
5451
|
+
const renderToolCard = (call, index) => /* @__PURE__ */ jsx14(
|
|
6499
5452
|
ToolCallCard,
|
|
6500
5453
|
{
|
|
6501
5454
|
call,
|
|
@@ -6523,7 +5476,7 @@ function SegmentedBody({
|
|
|
6523
5476
|
for (const g of groups) {
|
|
6524
5477
|
if (g.kind === "text") {
|
|
6525
5478
|
children.push(
|
|
6526
|
-
/* @__PURE__ */
|
|
5479
|
+
/* @__PURE__ */ jsx14(
|
|
6527
5480
|
SegmentText,
|
|
6528
5481
|
{
|
|
6529
5482
|
content: g.content,
|
|
@@ -6539,13 +5492,13 @@ function SegmentedBody({
|
|
|
6539
5492
|
}
|
|
6540
5493
|
if (!streaming && g.calls.length >= COLLAPSE_TOOL_RUN_AT && !g.calls.some(isImportantTool)) {
|
|
6541
5494
|
children.push(
|
|
6542
|
-
/* @__PURE__ */
|
|
6543
|
-
/* @__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: [
|
|
6544
5497
|
"Worked through ",
|
|
6545
5498
|
g.calls.length,
|
|
6546
5499
|
" steps"
|
|
6547
5500
|
] }),
|
|
6548
|
-
/* @__PURE__ */
|
|
5501
|
+
/* @__PURE__ */ jsx14("div", { className: "mt-1.5 flex flex-col gap-1.5", children: g.calls.map(renderToolCard) })
|
|
6549
5502
|
] }, `tools-fold-${g.index}`)
|
|
6550
5503
|
);
|
|
6551
5504
|
continue;
|
|
@@ -6554,9 +5507,9 @@ function SegmentedBody({
|
|
|
6554
5507
|
}
|
|
6555
5508
|
leftoverToolCalls.forEach((call, index) => children.push(renderToolCard(call, index)));
|
|
6556
5509
|
if (streaming && segments[lastIndex]?.kind === "tool") {
|
|
6557
|
-
children.push(/* @__PURE__ */
|
|
5510
|
+
children.push(/* @__PURE__ */ jsx14(StreamingCaret, {}, "streaming-caret"));
|
|
6558
5511
|
}
|
|
6559
|
-
return /* @__PURE__ */
|
|
5512
|
+
return /* @__PURE__ */ jsx14("div", { className: "flex flex-col gap-2", children });
|
|
6560
5513
|
}
|
|
6561
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";
|
|
6562
5515
|
function copyTextOf(msg) {
|
|
@@ -6565,9 +5518,9 @@ function copyTextOf(msg) {
|
|
|
6565
5518
|
return msg.content;
|
|
6566
5519
|
}
|
|
6567
5520
|
function CopyMessageButton({ text }) {
|
|
6568
|
-
const [copied, setCopied] =
|
|
6569
|
-
const timerRef =
|
|
6570
|
-
|
|
5521
|
+
const [copied, setCopied] = useState15(false);
|
|
5522
|
+
const timerRef = useRef11(null);
|
|
5523
|
+
useEffect11(
|
|
6571
5524
|
() => () => {
|
|
6572
5525
|
if (timerRef.current !== null) clearTimeout(timerRef.current);
|
|
6573
5526
|
},
|
|
@@ -6586,7 +5539,7 @@ function CopyMessageButton({ text }) {
|
|
|
6586
5539
|
}
|
|
6587
5540
|
);
|
|
6588
5541
|
};
|
|
6589
|
-
return /* @__PURE__ */
|
|
5542
|
+
return /* @__PURE__ */ jsx14(
|
|
6590
5543
|
"button",
|
|
6591
5544
|
{
|
|
6592
5545
|
type: "button",
|
|
@@ -6594,9 +5547,9 @@ function CopyMessageButton({ text }) {
|
|
|
6594
5547
|
"aria-label": "Copy message",
|
|
6595
5548
|
title: "Copy message",
|
|
6596
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",
|
|
6597
|
-
children: copied ? /* @__PURE__ */
|
|
6598
|
-
/* @__PURE__ */
|
|
6599
|
-
/* @__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" })
|
|
6600
5553
|
] })
|
|
6601
5554
|
}
|
|
6602
5555
|
);
|
|
@@ -6619,34 +5572,34 @@ function AssistantMessageImpl({
|
|
|
6619
5572
|
}) {
|
|
6620
5573
|
const content = useSmoothText(msg.content, streaming);
|
|
6621
5574
|
const reasoning = useSmoothText(msg.reasoning ?? "", streaming);
|
|
6622
|
-
const body =
|
|
5575
|
+
const body = useMemo7(() => renderBody(content), [renderBody, content]);
|
|
6623
5576
|
const segments = msg.segments;
|
|
6624
5577
|
const hasAnswerText = content !== "" || (segments?.some((s) => s.kind === "text" && s.content.trim() !== "") ?? false);
|
|
6625
|
-
const reasoningScrollRef =
|
|
6626
|
-
const thinkStartRef =
|
|
6627
|
-
const thinkMsRef =
|
|
5578
|
+
const reasoningScrollRef = useRef11(null);
|
|
5579
|
+
const thinkStartRef = useRef11(null);
|
|
5580
|
+
const thinkMsRef = useRef11(null);
|
|
6628
5581
|
if (streaming && reasoning && !hasAnswerText && thinkStartRef.current === null) {
|
|
6629
5582
|
thinkStartRef.current = performance.now();
|
|
6630
5583
|
}
|
|
6631
5584
|
if (hasAnswerText && thinkStartRef.current !== null && thinkMsRef.current === null) {
|
|
6632
5585
|
thinkMsRef.current = performance.now() - thinkStartRef.current;
|
|
6633
5586
|
}
|
|
6634
|
-
|
|
5587
|
+
useEffect11(() => {
|
|
6635
5588
|
const el = reasoningScrollRef.current;
|
|
6636
5589
|
if (el && streaming && !hasAnswerText) el.scrollTop = el.scrollHeight;
|
|
6637
5590
|
}, [reasoning, streaming, hasAnswerText]);
|
|
6638
5591
|
const thinkingSeconds = useThinkingSeconds(
|
|
6639
5592
|
streaming && !!reasoning && !hasAnswerText
|
|
6640
5593
|
);
|
|
6641
|
-
const [reasoningToggled, setReasoningToggled] =
|
|
5594
|
+
const [reasoningToggled, setReasoningToggled] = useState15(null);
|
|
6642
5595
|
const reasoningOpen = reasoningToggled ?? !hasAnswerText;
|
|
6643
5596
|
const quiet = chrome === "quiet";
|
|
6644
|
-
return /* @__PURE__ */
|
|
6645
|
-
!quiet && /* @__PURE__ */
|
|
6646
|
-
/* @__PURE__ */
|
|
6647
|
-
msg.modelUsed && /* @__PURE__ */
|
|
6648
|
-
formatTokensPerSecond(msg) && /* @__PURE__ */
|
|
6649
|
-
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) })
|
|
6650
5603
|
] }),
|
|
6651
5604
|
reasoning && // The canonical run-row grammar (RunRowShell — the same shell the tool
|
|
6652
5605
|
// rows compose): one family of rows instead of a bespoke disclosure per
|
|
@@ -6656,12 +5609,12 @@ function AssistantMessageImpl({
|
|
|
6656
5609
|
// and a click outranks the default from then on — the contract the old
|
|
6657
5610
|
// hand-rolled disclosure had, now enforced through the shell's
|
|
6658
5611
|
// controlled `open`.
|
|
6659
|
-
/* @__PURE__ */
|
|
5612
|
+
/* @__PURE__ */ jsx14(
|
|
6660
5613
|
RunRowShell,
|
|
6661
5614
|
{
|
|
6662
5615
|
className: "mb-2",
|
|
6663
|
-
icon: /* @__PURE__ */
|
|
6664
|
-
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: [
|
|
6665
5618
|
"Thinking",
|
|
6666
5619
|
thinkingSeconds >= 1 ? ` \xB7 ${thinkingSeconds}s` : "\u2026"
|
|
6667
5620
|
] }) : thinkMsRef.current != null ? (
|
|
@@ -6676,7 +5629,7 @@ function AssistantMessageImpl({
|
|
|
6676
5629
|
status: hasAnswerText ? "idle" : "running",
|
|
6677
5630
|
open: reasoningOpen,
|
|
6678
5631
|
onOpenChange: (next) => setReasoningToggled(next),
|
|
6679
|
-
children: /* @__PURE__ */
|
|
5632
|
+
children: /* @__PURE__ */ jsx14(
|
|
6680
5633
|
"div",
|
|
6681
5634
|
{
|
|
6682
5635
|
ref: reasoningScrollRef,
|
|
@@ -6686,7 +5639,7 @@ function AssistantMessageImpl({
|
|
|
6686
5639
|
)
|
|
6687
5640
|
}
|
|
6688
5641
|
),
|
|
6689
|
-
segments && segments.length > 0 ? /* @__PURE__ */
|
|
5642
|
+
segments && segments.length > 0 ? /* @__PURE__ */ jsx14(
|
|
6690
5643
|
SegmentedBody,
|
|
6691
5644
|
{
|
|
6692
5645
|
segments,
|
|
@@ -6698,12 +5651,12 @@ function AssistantMessageImpl({
|
|
|
6698
5651
|
toolRenderers,
|
|
6699
5652
|
messageClassName
|
|
6700
5653
|
}
|
|
6701
|
-
) : /* @__PURE__ */
|
|
6702
|
-
/* @__PURE__ */
|
|
5654
|
+
) : /* @__PURE__ */ jsxs12(Fragment7, { children: [
|
|
5655
|
+
/* @__PURE__ */ jsxs12("div", { className: messageClassName, children: [
|
|
6703
5656
|
body,
|
|
6704
|
-
streaming && content && !msg.toolCalls?.length && /* @__PURE__ */
|
|
5657
|
+
streaming && content && !msg.toolCalls?.length && /* @__PURE__ */ jsx14(StreamingCaret, {})
|
|
6705
5658
|
] }),
|
|
6706
|
-
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(
|
|
6707
5660
|
ToolCallCard,
|
|
6708
5661
|
{
|
|
6709
5662
|
call: tc,
|
|
@@ -6716,7 +5669,7 @@ function AssistantMessageImpl({
|
|
|
6716
5669
|
tc.id
|
|
6717
5670
|
)) })
|
|
6718
5671
|
] }),
|
|
6719
|
-
durableCards && msg.parts && /* @__PURE__ */
|
|
5672
|
+
durableCards && msg.parts && /* @__PURE__ */ jsx14(
|
|
6720
5673
|
DurableChatCards,
|
|
6721
5674
|
{
|
|
6722
5675
|
...durableCards,
|
|
@@ -6725,7 +5678,7 @@ function AssistantMessageImpl({
|
|
|
6725
5678
|
className: "mt-3"
|
|
6726
5679
|
}
|
|
6727
5680
|
),
|
|
6728
|
-
workProductCards && workProductPartsFromMessageParts(msg.parts).map((part) => /* @__PURE__ */
|
|
5681
|
+
workProductCards && workProductPartsFromMessageParts(msg.parts).map((part) => /* @__PURE__ */ jsx14(
|
|
6729
5682
|
WorkProductCard,
|
|
6730
5683
|
{
|
|
6731
5684
|
part,
|
|
@@ -6735,7 +5688,7 @@ function AssistantMessageImpl({
|
|
|
6735
5688
|
`${part.ref.id}:${part.ref.version}`
|
|
6736
5689
|
)),
|
|
6737
5690
|
renderExtras?.(msg),
|
|
6738
|
-
resolveAttachmentUrl && attachmentPartsFromMessageParts(msg.parts).length > 0 && /* @__PURE__ */
|
|
5691
|
+
resolveAttachmentUrl && attachmentPartsFromMessageParts(msg.parts).length > 0 && /* @__PURE__ */ jsx14("div", { className: "mt-2", children: /* @__PURE__ */ jsx14(
|
|
6739
5692
|
MessageAttachments,
|
|
6740
5693
|
{
|
|
6741
5694
|
parts: attachmentPartsFromMessageParts(msg.parts),
|
|
@@ -6743,18 +5696,18 @@ function AssistantMessageImpl({
|
|
|
6743
5696
|
justify: "start"
|
|
6744
5697
|
}
|
|
6745
5698
|
) }),
|
|
6746
|
-
quiet && /* @__PURE__ */
|
|
6747
|
-
/* @__PURE__ */
|
|
6748
|
-
msg.modelUsed && /* @__PURE__ */
|
|
6749
|
-
formatTokensPerSecond(msg) && /* @__PURE__ */
|
|
6750
|
-
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) })
|
|
6751
5704
|
] })
|
|
6752
5705
|
] });
|
|
6753
5706
|
}
|
|
6754
5707
|
var AssistantMessage = memo(AssistantMessageImpl);
|
|
6755
5708
|
function useThinkingSeconds(active) {
|
|
6756
|
-
const [seconds, setSeconds] =
|
|
6757
|
-
|
|
5709
|
+
const [seconds, setSeconds] = useState15(0);
|
|
5710
|
+
useEffect11(() => {
|
|
6758
5711
|
if (!active) return;
|
|
6759
5712
|
setSeconds(0);
|
|
6760
5713
|
const id = setInterval(() => setSeconds((s) => s + 1), 1e3);
|
|
@@ -6764,23 +5717,23 @@ function useThinkingSeconds(active) {
|
|
|
6764
5717
|
}
|
|
6765
5718
|
function ThinkingRow({ agentLabel, chrome = "labeled" }) {
|
|
6766
5719
|
const seconds = useThinkingSeconds(true);
|
|
6767
|
-
return /* @__PURE__ */
|
|
6768
|
-
chrome !== "quiet" && /* @__PURE__ */
|
|
6769
|
-
/* @__PURE__ */
|
|
6770
|
-
/* @__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" }) }),
|
|
6771
5724
|
"Thinking",
|
|
6772
5725
|
seconds >= 3 ? ` \xB7 ${seconds}s` : "..."
|
|
6773
5726
|
] })
|
|
6774
5727
|
] });
|
|
6775
5728
|
}
|
|
6776
5729
|
function StreamErrorRow({ message, onRetry }) {
|
|
6777
|
-
return /* @__PURE__ */
|
|
6778
|
-
/* @__PURE__ */
|
|
6779
|
-
/* @__PURE__ */
|
|
6780
|
-
/* @__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" })
|
|
6781
5734
|
] }),
|
|
6782
|
-
/* @__PURE__ */
|
|
6783
|
-
onRetry && /* @__PURE__ */
|
|
5735
|
+
/* @__PURE__ */ jsx14("span", { className: "min-w-0 flex-1 break-words", children: message }),
|
|
5736
|
+
onRetry && /* @__PURE__ */ jsx14(
|
|
6784
5737
|
"button",
|
|
6785
5738
|
{
|
|
6786
5739
|
type: "button",
|
|
@@ -6814,33 +5767,33 @@ function ChatMessages({
|
|
|
6814
5767
|
workProductCards
|
|
6815
5768
|
}) {
|
|
6816
5769
|
const messageClassName = messageSize === "large" ? "agent-app-message-copy text-[17px] leading-[1.6]" : "agent-app-message-copy text-base leading-[1.6]";
|
|
6817
|
-
const renderBody =
|
|
6818
|
-
() => renderMarkdown ?? ((content) => /* @__PURE__ */
|
|
5770
|
+
const renderBody = useMemo7(
|
|
5771
|
+
() => renderMarkdown ?? ((content) => /* @__PURE__ */ jsx14("p", { className: "whitespace-pre-wrap", children: content })),
|
|
6819
5772
|
[renderMarkdown]
|
|
6820
5773
|
);
|
|
6821
5774
|
const lastIsUser = messages[messages.length - 1]?.role === "user";
|
|
6822
5775
|
const quiet = chrome === "quiet";
|
|
6823
5776
|
if (messages.length === 0 && !loading && !error) {
|
|
6824
|
-
const empty = renderEmpty ? renderEmpty() : /* @__PURE__ */
|
|
6825
|
-
return /* @__PURE__ */
|
|
5777
|
+
const empty = renderEmpty ? renderEmpty() : /* @__PURE__ */ jsx14(ChatEmptyState, { ...emptyState });
|
|
5778
|
+
return /* @__PURE__ */ jsxs12(Fragment7, { children: [
|
|
6826
5779
|
header,
|
|
6827
5780
|
empty
|
|
6828
5781
|
] });
|
|
6829
5782
|
}
|
|
6830
|
-
return /* @__PURE__ */
|
|
5783
|
+
return /* @__PURE__ */ jsxs12(Fragment7, { children: [
|
|
6831
5784
|
header,
|
|
6832
5785
|
messages.map(
|
|
6833
|
-
(msg) => msg.role === "user" ? /* @__PURE__ */
|
|
6834
|
-
/* @__PURE__ */
|
|
6835
|
-
!quiet && /* @__PURE__ */
|
|
6836
|
-
/* @__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(
|
|
6837
5790
|
"div",
|
|
6838
5791
|
{
|
|
6839
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}`,
|
|
6840
|
-
children: /* @__PURE__ */
|
|
5793
|
+
children: /* @__PURE__ */ jsx14("p", { className: "whitespace-pre-wrap", children: msg.content })
|
|
6841
5794
|
}
|
|
6842
5795
|
),
|
|
6843
|
-
resolveAttachmentUrl && attachmentPartsFromMessageParts(msg.parts).length > 0 && /* @__PURE__ */
|
|
5796
|
+
resolveAttachmentUrl && attachmentPartsFromMessageParts(msg.parts).length > 0 && /* @__PURE__ */ jsx14("div", { className: "mt-1.5", children: /* @__PURE__ */ jsx14(
|
|
6844
5797
|
MessageAttachments,
|
|
6845
5798
|
{
|
|
6846
5799
|
parts: attachmentPartsFromMessageParts(msg.parts),
|
|
@@ -6849,8 +5802,8 @@ function ChatMessages({
|
|
|
6849
5802
|
}
|
|
6850
5803
|
) })
|
|
6851
5804
|
] }),
|
|
6852
|
-
quiet && /* @__PURE__ */
|
|
6853
|
-
] }, 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(
|
|
6854
5807
|
AssistantMessage,
|
|
6855
5808
|
{
|
|
6856
5809
|
msg,
|
|
@@ -6871,8 +5824,8 @@ function ChatMessages({
|
|
|
6871
5824
|
msg.id
|
|
6872
5825
|
)
|
|
6873
5826
|
),
|
|
6874
|
-
loading && lastIsUser && /* @__PURE__ */
|
|
6875
|
-
error && !loading && /* @__PURE__ */
|
|
5827
|
+
loading && lastIsUser && /* @__PURE__ */ jsx14(ThinkingRow, { agentLabel, chrome }),
|
|
5828
|
+
error && !loading && /* @__PURE__ */ jsx14(StreamErrorRow, { message: error, onRetry })
|
|
6876
5829
|
] });
|
|
6877
5830
|
}
|
|
6878
5831
|
|
|
@@ -6907,11 +5860,6 @@ export {
|
|
|
6907
5860
|
dispatchChatStreamLine,
|
|
6908
5861
|
consumeChatStream,
|
|
6909
5862
|
streamChatTurn,
|
|
6910
|
-
pickDictationMimeType,
|
|
6911
|
-
dictationErrorMessage,
|
|
6912
|
-
formatDictationElapsed,
|
|
6913
|
-
useDictation,
|
|
6914
|
-
ChatComposer,
|
|
6915
5863
|
DurablePlanClientError,
|
|
6916
5864
|
createDurablePlanDecisionClient,
|
|
6917
5865
|
useDurablePlanFlow,
|
|
@@ -7011,4 +5959,4 @@ export {
|
|
|
7011
5959
|
useThinkingSeconds,
|
|
7012
5960
|
ChatMessages
|
|
7013
5961
|
};
|
|
7014
|
-
//# sourceMappingURL=chunk-
|
|
5962
|
+
//# sourceMappingURL=chunk-JAYKCWW4.js.map
|