@dudousxd/nestjs-agent-react 0.16.0 → 0.17.0

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/index.cjs CHANGED
@@ -40,6 +40,7 @@ __export(src_exports, {
40
40
  MessageItem: () => MessageItem,
41
41
  MessageItemView: () => MessageItemView,
42
42
  MessageList: () => MessageList,
43
+ QuotaBlockedError: () => QuotaBlockedError,
43
44
  SPEECH_LANGUAGES: () => SPEECH_LANGUAGES,
44
45
  applyCompletion: () => applyCompletion,
45
46
  approvalCountdown: () => approvalCountdown,
@@ -81,6 +82,7 @@ __export(src_exports, {
81
82
  useElapsed: () => useElapsed,
82
83
  useMessageFeedback: () => useMessageFeedback,
83
84
  useModels: () => useModels,
85
+ useQuota: () => useQuota,
84
86
  useSpeechRecognition: () => useSpeechRecognition,
85
87
  useStickToBottom: () => useStickToBottom,
86
88
  useThreads: () => useThreads,
@@ -246,6 +248,10 @@ var AgentClient = class {
246
248
  listAgents() {
247
249
  return this.request("GET", "/agent/agents");
248
250
  }
251
+ /** `GET /agent/quota` — the caller's budget windows and the one blocking sends, if any. */
252
+ getQuota() {
253
+ return this.request("GET", "/agent/quota");
254
+ }
249
255
  getQuotaToday() {
250
256
  return this.request("GET", "/agent/quota/today");
251
257
  }
@@ -1193,28 +1199,96 @@ function useModels(options) {
1193
1199
  }
1194
1200
  __name(useModels, "useModels");
1195
1201
 
1196
- // src/feedback/use-message-feedback.ts
1202
+ // src/quota/use-quota.ts
1197
1203
  var import_react5 = require("react");
1204
+
1205
+ // src/threads/threads-events.ts
1206
+ var listeners = /* @__PURE__ */ new WeakMap();
1207
+ function notifyThreads(backend, event) {
1208
+ for (const listener of listeners.get(backend) ?? []) {
1209
+ listener(event);
1210
+ }
1211
+ }
1212
+ __name(notifyThreads, "notifyThreads");
1213
+ function onThreadsEvent(backend, listener) {
1214
+ let set = listeners.get(backend);
1215
+ if (set === void 0) {
1216
+ set = /* @__PURE__ */ new Set();
1217
+ listeners.set(backend, set);
1218
+ }
1219
+ set.add(listener);
1220
+ return () => {
1221
+ set.delete(listener);
1222
+ };
1223
+ }
1224
+ __name(onThreadsEvent, "onThreadsEvent");
1225
+
1226
+ // src/quota/use-quota.ts
1227
+ function useQuota(options) {
1228
+ const { backend, enabled = true, pollMs } = options;
1229
+ const { data, isLoading, error, refresh } = useResource(() => requireBackendMethod(backend, "getQuota")(), "", enabled);
1230
+ (0, import_react5.useEffect)(() => {
1231
+ if (!enabled) return;
1232
+ return onThreadsEvent(backend, (event) => {
1233
+ if (event.type === "changed") void refresh();
1234
+ });
1235
+ }, [
1236
+ backend,
1237
+ enabled,
1238
+ refresh
1239
+ ]);
1240
+ (0, import_react5.useEffect)(() => {
1241
+ if (!enabled || pollMs === void 0 || pollMs <= 0) return;
1242
+ const timer = setInterval(() => void refresh(), pollMs);
1243
+ return () => clearInterval(timer);
1244
+ }, [
1245
+ enabled,
1246
+ pollMs,
1247
+ refresh
1248
+ ]);
1249
+ return (0, import_react5.useMemo)(() => {
1250
+ const windows = data?.windows ?? [];
1251
+ return {
1252
+ report: data,
1253
+ windows,
1254
+ day: windows.find((window2) => window2.period === "day"),
1255
+ month: windows.find((window2) => window2.period === "month"),
1256
+ blocked: data?.blocked ?? null,
1257
+ isLoading,
1258
+ error,
1259
+ refresh
1260
+ };
1261
+ }, [
1262
+ data,
1263
+ isLoading,
1264
+ error,
1265
+ refresh
1266
+ ]);
1267
+ }
1268
+ __name(useQuota, "useQuota");
1269
+
1270
+ // src/feedback/use-message-feedback.ts
1271
+ var import_react6 = require("react");
1198
1272
  function useMessageFeedback(options) {
1199
- const latest = (0, import_react5.useRef)(options);
1273
+ const latest = (0, import_react6.useRef)(options);
1200
1274
  latest.current = options;
1201
- const [local, setLocal] = (0, import_react5.useState)(/* @__PURE__ */ new Map());
1202
- const [pending, setPending] = (0, import_react5.useState)(/* @__PURE__ */ new Set());
1203
- const [error, setError] = (0, import_react5.useState)(null);
1204
- const localRef = (0, import_react5.useRef)(local);
1275
+ const [local, setLocal] = (0, import_react6.useState)(/* @__PURE__ */ new Map());
1276
+ const [pending, setPending] = (0, import_react6.useState)(/* @__PURE__ */ new Set());
1277
+ const [error, setError] = (0, import_react6.useState)(null);
1278
+ const localRef = (0, import_react6.useRef)(local);
1205
1279
  localRef.current = local;
1206
- const resolved = (0, import_react5.useRef)(/* @__PURE__ */ new Map());
1207
- const feedbackOf = (0, import_react5.useCallback)((message) => {
1280
+ const resolved = (0, import_react6.useRef)(/* @__PURE__ */ new Map());
1281
+ const feedbackOf = (0, import_react6.useCallback)((message) => {
1208
1282
  const mine = local.get(message.id);
1209
1283
  if (mine !== void 0) return mine.feedback;
1210
1284
  return metadataOf(message).feedback ?? null;
1211
1285
  }, [
1212
1286
  local
1213
1287
  ]);
1214
- const isPending = (0, import_react5.useCallback)((message) => pending.has(message.id), [
1288
+ const isPending = (0, import_react6.useCallback)((message) => pending.has(message.id), [
1215
1289
  pending
1216
1290
  ]);
1217
- const storedIdFor = (0, import_react5.useCallback)(async (message) => {
1291
+ const storedIdFor = (0, import_react6.useCallback)(async (message) => {
1218
1292
  const runId = metadataOf(message).runId;
1219
1293
  if (runId === void 0) return message.id;
1220
1294
  const known = resolved.current.get(message.id);
@@ -1234,7 +1308,7 @@ function useMessageFeedback(options) {
1234
1308
  resolved.current.set(message.id, row.id);
1235
1309
  return row.id;
1236
1310
  }, []);
1237
- const rate = (0, import_react5.useCallback)(async (message, value, comment) => {
1311
+ const rate = (0, import_react6.useCallback)(async (message, value, comment) => {
1238
1312
  const setFeedback = requireBackendMethod(latest.current.backend, "setMessageFeedback");
1239
1313
  const had = localRef.current.get(message.id);
1240
1314
  const optimistic = value === null ? null : {
@@ -1280,7 +1354,7 @@ function useMessageFeedback(options) {
1280
1354
  }, [
1281
1355
  storedIdFor
1282
1356
  ]);
1283
- const toggle = (0, import_react5.useCallback)((message, value) => {
1357
+ const toggle = (0, import_react6.useCallback)((message, value) => {
1284
1358
  const mine = localRef.current.get(message.id);
1285
1359
  const current = mine !== void 0 ? mine.feedback : metadataOf(message).feedback ?? null;
1286
1360
  return rate(message, current?.value === value ? null : value);
@@ -1302,38 +1376,17 @@ function metadataOf(message) {
1302
1376
  }
1303
1377
  __name(metadataOf, "metadataOf");
1304
1378
 
1305
- // src/threads/threads-events.ts
1306
- var listeners = /* @__PURE__ */ new WeakMap();
1307
- function notifyThreads(backend, event) {
1308
- for (const listener of listeners.get(backend) ?? []) {
1309
- listener(event);
1310
- }
1311
- }
1312
- __name(notifyThreads, "notifyThreads");
1313
- function onThreadsEvent(backend, listener) {
1314
- let set = listeners.get(backend);
1315
- if (set === void 0) {
1316
- set = /* @__PURE__ */ new Set();
1317
- listeners.set(backend, set);
1318
- }
1319
- set.add(listener);
1320
- return () => {
1321
- set.delete(listener);
1322
- };
1323
- }
1324
- __name(onThreadsEvent, "onThreadsEvent");
1325
-
1326
1379
  // src/threads/use-threads.ts
1327
- var import_react6 = require("react");
1380
+ var import_react7 = require("react");
1328
1381
  function useThreads(options) {
1329
1382
  const { backend, enabled = true } = options;
1330
- const [threads, setThreads] = (0, import_react6.useState)([]);
1331
- const [isLoading, setIsLoading] = (0, import_react6.useState)(enabled);
1332
- const [error, setError] = (0, import_react6.useState)(null);
1333
- const threadsRef = (0, import_react6.useRef)(threads);
1383
+ const [threads, setThreads] = (0, import_react7.useState)([]);
1384
+ const [isLoading, setIsLoading] = (0, import_react7.useState)(enabled);
1385
+ const [error, setError] = (0, import_react7.useState)(null);
1386
+ const threadsRef = (0, import_react7.useRef)(threads);
1334
1387
  threadsRef.current = threads;
1335
- const generation = (0, import_react6.useRef)(0);
1336
- const refresh = (0, import_react6.useCallback)(async () => {
1388
+ const generation = (0, import_react7.useRef)(0);
1389
+ const refresh = (0, import_react7.useCallback)(async () => {
1337
1390
  const mine = ++generation.current;
1338
1391
  setIsLoading(true);
1339
1392
  try {
@@ -1350,7 +1403,7 @@ function useThreads(options) {
1350
1403
  }, [
1351
1404
  backend
1352
1405
  ]);
1353
- (0, import_react6.useEffect)(() => {
1406
+ (0, import_react7.useEffect)(() => {
1354
1407
  if (!enabled) return;
1355
1408
  void refresh();
1356
1409
  return onThreadsEvent(backend, (event) => {
@@ -1370,7 +1423,7 @@ function useThreads(options) {
1370
1423
  enabled,
1371
1424
  refresh
1372
1425
  ]);
1373
- const rename = (0, import_react6.useCallback)(async (id, title) => {
1426
+ const rename = (0, import_react7.useCallback)(async (id, title) => {
1374
1427
  const before = threadsRef.current;
1375
1428
  setThreads((current) => current.map((thread) => thread.id === id ? {
1376
1429
  ...thread,
@@ -1392,7 +1445,7 @@ function useThreads(options) {
1392
1445
  }, [
1393
1446
  backend
1394
1447
  ]);
1395
- const remove = (0, import_react6.useCallback)(async (id) => {
1448
+ const remove = (0, import_react7.useCallback)(async (id) => {
1396
1449
  const before = threadsRef.current;
1397
1450
  setThreads((current) => current.filter((thread) => thread.id !== id));
1398
1451
  try {
@@ -1467,10 +1520,10 @@ function backgroundRunsFromThread(messages) {
1467
1520
  __name(backgroundRunsFromThread, "backgroundRunsFromThread");
1468
1521
 
1469
1522
  // src/components/chat-input.tsx
1470
- var import_react8 = __toESM(require("react"), 1);
1523
+ var import_react9 = __toESM(require("react"), 1);
1471
1524
 
1472
1525
  // src/components/use-speech-recognition.ts
1473
- var import_react7 = require("react");
1526
+ var import_react8 = require("react");
1474
1527
  function getRecognitionCtor() {
1475
1528
  if (typeof window === "undefined") return null;
1476
1529
  const scope = window;
@@ -1478,15 +1531,15 @@ function getRecognitionCtor() {
1478
1531
  }
1479
1532
  __name(getRecognitionCtor, "getRecognitionCtor");
1480
1533
  function useSpeechRecognition({ lang = "en-US", onFinalTranscript, onInterimTranscript }) {
1481
- const recognitionRef = (0, import_react7.useRef)(null);
1482
- const [isListening, setIsListening] = (0, import_react7.useState)(false);
1483
- const ctor = (0, import_react7.useMemo)(() => getRecognitionCtor(), []);
1534
+ const recognitionRef = (0, import_react8.useRef)(null);
1535
+ const [isListening, setIsListening] = (0, import_react8.useState)(false);
1536
+ const ctor = (0, import_react8.useMemo)(() => getRecognitionCtor(), []);
1484
1537
  const isSupported = ctor !== null;
1485
- const finalRef = (0, import_react7.useRef)(onFinalTranscript);
1486
- const interimRef = (0, import_react7.useRef)(onInterimTranscript);
1538
+ const finalRef = (0, import_react8.useRef)(onFinalTranscript);
1539
+ const interimRef = (0, import_react8.useRef)(onInterimTranscript);
1487
1540
  finalRef.current = onFinalTranscript;
1488
1541
  interimRef.current = onInterimTranscript;
1489
- (0, import_react7.useEffect)(() => {
1542
+ (0, import_react8.useEffect)(() => {
1490
1543
  if (!ctor) return;
1491
1544
  const recognition = new ctor();
1492
1545
  recognition.lang = lang;
@@ -1525,7 +1578,7 @@ function useSpeechRecognition({ lang = "en-US", onFinalTranscript, onInterimTran
1525
1578
  ctor,
1526
1579
  lang
1527
1580
  ]);
1528
- const start = (0, import_react7.useCallback)(() => {
1581
+ const start = (0, import_react8.useCallback)(() => {
1529
1582
  const recognition = recognitionRef.current;
1530
1583
  if (!recognition) return;
1531
1584
  try {
@@ -1535,7 +1588,7 @@ function useSpeechRecognition({ lang = "en-US", onFinalTranscript, onInterimTran
1535
1588
  console.warn("SpeechRecognition start failed", error);
1536
1589
  }
1537
1590
  }, []);
1538
- const stop = (0, import_react7.useCallback)(() => {
1591
+ const stop = (0, import_react8.useCallback)(() => {
1539
1592
  const recognition = recognitionRef.current;
1540
1593
  if (!recognition) return;
1541
1594
  try {
@@ -1554,8 +1607,8 @@ __name(useSpeechRecognition, "useSpeechRecognition");
1554
1607
 
1555
1608
  // src/components/chat-input.tsx
1556
1609
  function ChatInput({ onSubmit, disabled, placeholder, rows = 2, enableSpeech = true, speechLang = "en-US", sendLabel = "Send", onStop, isStreaming = false, stopLabel = "Stop generating", className, textareaClassName, sendButtonClassName, micButtonClassName, stopButtonClassName, renderMic }) {
1557
- const [value, setValue] = (0, import_react8.useState)("");
1558
- const [interim, setInterim] = (0, import_react8.useState)("");
1610
+ const [value, setValue] = (0, import_react9.useState)("");
1611
+ const [interim, setInterim] = (0, import_react9.useState)("");
1559
1612
  const speech = useSpeechRecognition({
1560
1613
  lang: speechLang,
1561
1614
  onFinalTranscript: /* @__PURE__ */ __name((text) => {
@@ -1566,7 +1619,7 @@ function ChatInput({ onSubmit, disabled, placeholder, rows = 2, enableSpeech = t
1566
1619
  }, "onFinalTranscript"),
1567
1620
  onInterimTranscript: /* @__PURE__ */ __name((text) => setInterim(text), "onInterimTranscript")
1568
1621
  });
1569
- (0, import_react8.useEffect)(() => {
1622
+ (0, import_react9.useEffect)(() => {
1570
1623
  if (!speech.isListening) setInterim("");
1571
1624
  }, [
1572
1625
  speech.isListening
@@ -1594,9 +1647,9 @@ function ChatInput({ onSubmit, disabled, placeholder, rows = 2, enableSpeech = t
1594
1647
  const displayValue = speech.isListening && interim ? `${value}${value && !value.endsWith(" ") ? " " : ""}${interim}` : value;
1595
1648
  const showMic = enableSpeech && speech.isSupported;
1596
1649
  const showStop = isStreaming && onStop !== void 0;
1597
- return /* @__PURE__ */ import_react8.default.createElement("div", {
1650
+ return /* @__PURE__ */ import_react9.default.createElement("div", {
1598
1651
  className
1599
- }, /* @__PURE__ */ import_react8.default.createElement("textarea", {
1652
+ }, /* @__PURE__ */ import_react9.default.createElement("textarea", {
1600
1653
  className: textareaClassName,
1601
1654
  rows,
1602
1655
  value: displayValue,
@@ -1607,17 +1660,17 @@ function ChatInput({ onSubmit, disabled, placeholder, rows = 2, enableSpeech = t
1607
1660
  }, "onChange"),
1608
1661
  onKeyDown: handleKeyDown,
1609
1662
  placeholder: placeholder ?? "Ask something (Enter to send, Shift+Enter for newline)"
1610
- }), /* @__PURE__ */ import_react8.default.createElement("button", {
1663
+ }), /* @__PURE__ */ import_react9.default.createElement("button", {
1611
1664
  type: "button",
1612
1665
  className: sendButtonClassName,
1613
1666
  onClick: submit,
1614
1667
  disabled: disabled || !value.trim()
1615
- }, sendLabel), showStop ? /* @__PURE__ */ import_react8.default.createElement("button", {
1668
+ }, sendLabel), showStop ? /* @__PURE__ */ import_react9.default.createElement("button", {
1616
1669
  type: "button",
1617
1670
  className: stopButtonClassName,
1618
1671
  onClick: /* @__PURE__ */ __name(() => void onStop(), "onClick"),
1619
1672
  "aria-label": "Stop generating"
1620
- }, stopLabel) : null, showMic ? /* @__PURE__ */ import_react8.default.createElement("button", {
1673
+ }, stopLabel) : null, showMic ? /* @__PURE__ */ import_react9.default.createElement("button", {
1621
1674
  type: "button",
1622
1675
  className: micButtonClassName,
1623
1676
  onClick: toggleMic,
@@ -1630,10 +1683,10 @@ function ChatInput({ onSubmit, disabled, placeholder, rows = 2, enableSpeech = t
1630
1683
  __name(ChatInput, "ChatInput");
1631
1684
 
1632
1685
  // src/components/message-item.tsx
1633
- var import_react11 = __toESM(require("react"), 1);
1686
+ var import_react12 = __toESM(require("react"), 1);
1634
1687
 
1635
1688
  // src/transcript/use-chat-transcript.ts
1636
- var import_react10 = require("react");
1689
+ var import_react11 = require("react");
1637
1690
 
1638
1691
  // src/transcript/model.ts
1639
1692
  var import_nestjs_agent_core2 = require("@dudousxd/nestjs-agent-core");
@@ -2610,11 +2663,11 @@ function formatCostUsd(cost) {
2610
2663
  __name(formatCostUsd, "formatCostUsd");
2611
2664
 
2612
2665
  // src/transcript/use-stick-to-bottom.ts
2613
- var import_react9 = require("react");
2666
+ var import_react10 = require("react");
2614
2667
  function useStickToBottom({ contentKey, threshold = 32 }) {
2615
- const containerRef = (0, import_react9.useRef)(null);
2616
- const [isAtBottom, setIsAtBottom] = (0, import_react9.useState)(true);
2617
- const measure = (0, import_react9.useCallback)(() => {
2668
+ const containerRef = (0, import_react10.useRef)(null);
2669
+ const [isAtBottom, setIsAtBottom] = (0, import_react10.useState)(true);
2670
+ const measure = (0, import_react10.useCallback)(() => {
2618
2671
  const element = containerRef.current;
2619
2672
  if (!element) {
2620
2673
  return;
@@ -2624,7 +2677,7 @@ function useStickToBottom({ contentKey, threshold = 32 }) {
2624
2677
  }, [
2625
2678
  threshold
2626
2679
  ]);
2627
- const scrollToBottom = (0, import_react9.useCallback)(() => {
2680
+ const scrollToBottom = (0, import_react10.useCallback)(() => {
2628
2681
  const element = containerRef.current;
2629
2682
  if (!element) {
2630
2683
  return;
@@ -2632,7 +2685,7 @@ function useStickToBottom({ contentKey, threshold = 32 }) {
2632
2685
  element.scrollTop = element.scrollHeight;
2633
2686
  setIsAtBottom(true);
2634
2687
  }, []);
2635
- const setContainer = (0, import_react9.useCallback)((element) => {
2688
+ const setContainer = (0, import_react10.useCallback)((element) => {
2636
2689
  containerRef.current = element;
2637
2690
  if (element) {
2638
2691
  measure();
@@ -2640,7 +2693,7 @@ function useStickToBottom({ contentKey, threshold = 32 }) {
2640
2693
  }, [
2641
2694
  measure
2642
2695
  ]);
2643
- (0, import_react9.useEffect)(() => {
2696
+ (0, import_react10.useEffect)(() => {
2644
2697
  if (isAtBottom) {
2645
2698
  scrollToBottom();
2646
2699
  }
@@ -2649,7 +2702,7 @@ function useStickToBottom({ contentKey, threshold = 32 }) {
2649
2702
  isAtBottom,
2650
2703
  scrollToBottom
2651
2704
  ]);
2652
- const getContainerProps = (0, import_react9.useCallback)(() => ({
2705
+ const getContainerProps = (0, import_react10.useCallback)(() => ({
2653
2706
  ref: setContainer,
2654
2707
  onScroll: measure
2655
2708
  }), [
@@ -2671,14 +2724,14 @@ var DEFAULT_LOAD_EARLIER_STEP = 50;
2671
2724
  var DEFAULT_COPY_RESET_MS = 1500;
2672
2725
  function useChatTranscript(options) {
2673
2726
  const { messages, status, initialVisibleCount = DEFAULT_VISIBLE_COUNT, loadEarlierStep = DEFAULT_LOAD_EARLIER_STEP, followUps, stickToBottomThreshold } = options;
2674
- const latest = (0, import_react10.useRef)(options);
2727
+ const latest = (0, import_react11.useRef)(options);
2675
2728
  latest.current = options;
2676
- const [visibleCount, setVisibleCount] = (0, import_react10.useState)(initialVisibleCount);
2677
- const [stopRequested, setStopRequested] = (0, import_react10.useState)(false);
2729
+ const [visibleCount, setVisibleCount] = (0, import_react11.useState)(initialVisibleCount);
2730
+ const [stopRequested, setStopRequested] = (0, import_react11.useState)(false);
2678
2731
  const isStreaming = status === "streaming" || status === "reconnecting";
2679
2732
  const isBusy = status === "submitted" || isStreaming;
2680
2733
  const isEmpty = messages.length === 0;
2681
- (0, import_react10.useEffect)(() => {
2734
+ (0, import_react11.useEffect)(() => {
2682
2735
  if (!isBusy) {
2683
2736
  setStopRequested(false);
2684
2737
  }
@@ -2695,7 +2748,7 @@ function useChatTranscript(options) {
2695
2748
  streamingMessageId,
2696
2749
  options
2697
2750
  });
2698
- const stop = (0, import_react10.useCallback)(() => {
2751
+ const stop = (0, import_react11.useCallback)(() => {
2699
2752
  const current = latest.current;
2700
2753
  if (current.status !== "submitted" && current.status !== "streaming" && current.status !== "reconnecting") {
2701
2754
  return;
@@ -2703,8 +2756,8 @@ function useChatTranscript(options) {
2703
2756
  setStopRequested(true);
2704
2757
  void current.onStop?.();
2705
2758
  }, []);
2706
- const loadEarlier = (0, import_react10.useCallback)(() => setVisibleCount((count) => count + (latest.current.loadEarlierStep ?? DEFAULT_LOAD_EARLIER_STEP)), []);
2707
- const showAll = (0, import_react10.useCallback)(() => setVisibleCount(latest.current.messages.length), []);
2759
+ const loadEarlier = (0, import_react11.useCallback)(() => setVisibleCount((count) => count + (latest.current.loadEarlierStep ?? DEFAULT_LOAD_EARLIER_STEP)), []);
2760
+ const showAll = (0, import_react11.useCallback)(() => setVisibleCount(latest.current.messages.length), []);
2708
2761
  const scroll = useStickToBottom({
2709
2762
  contentKey: contentSignature(messages),
2710
2763
  ...stickToBottomThreshold !== void 0 ? {
@@ -2740,7 +2793,7 @@ function useChatTranscript(options) {
2740
2793
  __name(useChatTranscript, "useChatTranscript");
2741
2794
  function useTranscriptItem(options) {
2742
2795
  const { message, isStreaming = false } = options;
2743
- const messagesRef = (0, import_react10.useRef)([
2796
+ const messagesRef = (0, import_react11.useRef)([
2744
2797
  message
2745
2798
  ]);
2746
2799
  if (messagesRef.current[0] !== message) {
@@ -2758,13 +2811,13 @@ function useTranscriptItem(options) {
2758
2811
  }
2759
2812
  __name(useTranscriptItem, "useTranscriptItem");
2760
2813
  function useTranscriptItems({ messages, visibleStart, streamingMessageId, options }) {
2761
- const [drafts, setDrafts] = (0, import_react10.useState)(() => /* @__PURE__ */ new Map());
2762
- const [copied, setCopied] = (0, import_react10.useState)(() => /* @__PURE__ */ new Set());
2763
- const [openReasoning, setOpenReasoning] = (0, import_react10.useState)(() => /* @__PURE__ */ new Map());
2764
- const [picks, setPicks] = (0, import_react10.useState)(() => /* @__PURE__ */ new Map());
2765
- const [settling, setSettling] = (0, import_react10.useState)(() => /* @__PURE__ */ new Map());
2766
- const [settleErrors, setSettleErrors] = (0, import_react10.useState)(() => /* @__PURE__ */ new Map());
2767
- const latest = (0, import_react10.useRef)({
2814
+ const [drafts, setDrafts] = (0, import_react11.useState)(() => /* @__PURE__ */ new Map());
2815
+ const [copied, setCopied] = (0, import_react11.useState)(() => /* @__PURE__ */ new Set());
2816
+ const [openReasoning, setOpenReasoning] = (0, import_react11.useState)(() => /* @__PURE__ */ new Map());
2817
+ const [picks, setPicks] = (0, import_react11.useState)(() => /* @__PURE__ */ new Map());
2818
+ const [settling, setSettling] = (0, import_react11.useState)(() => /* @__PURE__ */ new Map());
2819
+ const [settleErrors, setSettleErrors] = (0, import_react11.useState)(() => /* @__PURE__ */ new Map());
2820
+ const latest = (0, import_react11.useRef)({
2768
2821
  options,
2769
2822
  drafts,
2770
2823
  picks,
@@ -2776,23 +2829,23 @@ function useTranscriptItems({ messages, visibleStart, streamingMessageId, option
2776
2829
  picks,
2777
2830
  messages
2778
2831
  };
2779
- const copyTimers = (0, import_react10.useRef)(/* @__PURE__ */ new Map());
2780
- (0, import_react10.useEffect)(() => () => {
2832
+ const copyTimers = (0, import_react11.useRef)(/* @__PURE__ */ new Map());
2833
+ (0, import_react11.useEffect)(() => () => {
2781
2834
  for (const timer of copyTimers.current.values()) {
2782
2835
  clearTimeout(timer);
2783
2836
  }
2784
2837
  copyTimers.current.clear();
2785
2838
  }, []);
2786
- const callbackCache = (0, import_react10.useRef)(/* @__PURE__ */ new Map());
2787
- const reasoningToggleCache = (0, import_react10.useRef)(/* @__PURE__ */ new Map());
2788
- const toggleReasoning = (0, import_react10.useCallback)((key, open) => {
2839
+ const callbackCache = (0, import_react11.useRef)(/* @__PURE__ */ new Map());
2840
+ const reasoningToggleCache = (0, import_react11.useRef)(/* @__PURE__ */ new Map());
2841
+ const toggleReasoning = (0, import_react11.useCallback)((key, open) => {
2789
2842
  setOpenReasoning((current) => {
2790
2843
  const next = new Map(current);
2791
2844
  next.set(key, open ?? !(current.get(key) ?? false));
2792
2845
  return next;
2793
2846
  });
2794
2847
  }, []);
2795
- const stableToggle = (0, import_react10.useCallback)((key) => {
2848
+ const stableToggle = (0, import_react11.useCallback)((key) => {
2796
2849
  let cached = reasoningToggleCache.current.get(key);
2797
2850
  if (!cached) {
2798
2851
  cached = /* @__PURE__ */ __name((open) => toggleReasoning(key, open), "cached");
@@ -2802,10 +2855,10 @@ function useTranscriptItems({ messages, visibleStart, streamingMessageId, option
2802
2855
  }, [
2803
2856
  toggleReasoning
2804
2857
  ]);
2805
- const pick = (0, import_react10.useCallback)((toolCallId, questionId, values) => {
2858
+ const pick = (0, import_react11.useCallback)((toolCallId, questionId, values) => {
2806
2859
  setPicks((current) => new Map(current).set(pickKey(toolCallId, questionId), values));
2807
2860
  }, []);
2808
- const settle = (0, import_react10.useCallback)((toolCallId, action, send) => {
2861
+ const settle = (0, import_react11.useCallback)((toolCallId, action, send) => {
2809
2862
  setSettleErrors((current) => {
2810
2863
  if (!current.has(toolCallId)) {
2811
2864
  return current;
@@ -2829,7 +2882,7 @@ function useTranscriptItems({ messages, visibleStart, streamingMessageId, option
2829
2882
  failed(error);
2830
2883
  }
2831
2884
  }, []);
2832
- const answer = (0, import_react10.useCallback)((toolCallId) => {
2885
+ const answer = (0, import_react11.useCallback)((toolCallId) => {
2833
2886
  const current = latest.current;
2834
2887
  const onAnswer = current.options.onAnswer;
2835
2888
  if (!onAnswer) {
@@ -2839,7 +2892,7 @@ function useTranscriptItems({ messages, visibleStart, streamingMessageId, option
2839
2892
  }, [
2840
2893
  settle
2841
2894
  ]);
2842
- const skip = (0, import_react10.useCallback)((toolCallId) => {
2895
+ const skip = (0, import_react11.useCallback)((toolCallId) => {
2843
2896
  const onSkip = latest.current.options.onSkip;
2844
2897
  if (onSkip) {
2845
2898
  settle(toolCallId, "skip", () => onSkip(toolCallId));
@@ -2847,7 +2900,7 @@ function useTranscriptItems({ messages, visibleStart, streamingMessageId, option
2847
2900
  }, [
2848
2901
  settle
2849
2902
  ]);
2850
- const approve = (0, import_react10.useCallback)((toolCallId, options2) => {
2903
+ const approve = (0, import_react11.useCallback)((toolCallId, options2) => {
2851
2904
  const onApprove = latest.current.options.onApprove;
2852
2905
  if (onApprove) {
2853
2906
  settle(toolCallId, "approve", () => options2 === void 0 ? onApprove(toolCallId) : onApprove(toolCallId, options2));
@@ -2855,7 +2908,7 @@ function useTranscriptItems({ messages, visibleStart, streamingMessageId, option
2855
2908
  }, [
2856
2909
  settle
2857
2910
  ]);
2858
- const reject = (0, import_react10.useCallback)((toolCallId) => {
2911
+ const reject = (0, import_react11.useCallback)((toolCallId) => {
2859
2912
  const onReject = latest.current.options.onReject;
2860
2913
  if (onReject) {
2861
2914
  settle(toolCallId, "reject", () => onReject(toolCallId));
@@ -2863,7 +2916,7 @@ function useTranscriptItems({ messages, visibleStart, streamingMessageId, option
2863
2916
  }, [
2864
2917
  settle
2865
2918
  ]);
2866
- const callbacksFor = (0, import_react10.useCallback)((id) => {
2919
+ const callbacksFor = (0, import_react11.useCallback)((id) => {
2867
2920
  const cached = callbackCache.current.get(id);
2868
2921
  if (cached) {
2869
2922
  return cached;
@@ -3105,7 +3158,7 @@ function MessageItem({ message, isStreaming = false, editable, onEditSubmit, reg
3105
3158
  getCreatedAt: /* @__PURE__ */ __name(() => createdAt, "getCreatedAt")
3106
3159
  } : {}
3107
3160
  });
3108
- return /* @__PURE__ */ import_react11.default.createElement(MessageItemView, {
3161
+ return /* @__PURE__ */ import_react12.default.createElement(MessageItemView, {
3109
3162
  item,
3110
3163
  ...slots
3111
3164
  });
@@ -3113,51 +3166,51 @@ function MessageItem({ message, isStreaming = false, editable, onEditSubmit, reg
3113
3166
  __name(MessageItem, "MessageItem");
3114
3167
  function MessageItemView({ item, ...slots }) {
3115
3168
  const { classNames } = slots;
3116
- const actionRow = /* @__PURE__ */ import_react11.default.createElement("div", {
3169
+ const actionRow = /* @__PURE__ */ import_react12.default.createElement("div", {
3117
3170
  className: classNames?.actions,
3118
3171
  "data-actions-for": item.role
3119
- }, item.copy.available ? /* @__PURE__ */ import_react11.default.createElement("button", {
3172
+ }, item.copy.available ? /* @__PURE__ */ import_react12.default.createElement("button", {
3120
3173
  type: "button",
3121
3174
  onClick: item.copy.copy,
3122
3175
  className: classNames?.actionButton,
3123
3176
  title: item.copy.copied ? "Copied!" : "Copy message text"
3124
- }, item.copy.copied ? "Copied" : "Copy") : null, item.fork.available ? /* @__PURE__ */ import_react11.default.createElement("button", {
3177
+ }, item.copy.copied ? "Copied" : "Copy") : null, item.fork.available ? /* @__PURE__ */ import_react12.default.createElement("button", {
3125
3178
  type: "button",
3126
3179
  onClick: item.fork.run,
3127
3180
  className: classNames?.actionButton,
3128
3181
  title: "Fork thread from this message"
3129
- }, "Fork") : null, item.regenerate.available ? /* @__PURE__ */ import_react11.default.createElement("button", {
3182
+ }, "Fork") : null, item.regenerate.available ? /* @__PURE__ */ import_react12.default.createElement("button", {
3130
3183
  type: "button",
3131
3184
  onClick: item.regenerate.run,
3132
3185
  className: classNames?.actionButton,
3133
3186
  title: "Regenerate response"
3134
- }, "Regenerate") : null, slots.meta, !item.isUser && item.usage ? /* @__PURE__ */ import_react11.default.createElement("span", {
3187
+ }, "Regenerate") : null, slots.meta, !item.isUser && item.usage ? /* @__PURE__ */ import_react12.default.createElement("span", {
3135
3188
  className: classNames?.usage,
3136
3189
  title: `Input ${item.usage.inputTokens.toLocaleString()} \xB7 Output ${item.usage.outputTokens.toLocaleString()} tokens`
3137
- }, item.usage.costLabel, " \xB7 ", item.usage.tokensLabel) : null, item.timestamp ? /* @__PURE__ */ import_react11.default.createElement("span", {
3190
+ }, item.usage.costLabel, " \xB7 ", item.usage.tokensLabel) : null, item.timestamp ? /* @__PURE__ */ import_react12.default.createElement("span", {
3138
3191
  className: classNames?.timestamp,
3139
3192
  title: item.timestamp.absolute
3140
3193
  }, item.timestamp.relative) : null);
3141
3194
  if (item.edit.available) {
3142
- return /* @__PURE__ */ import_react11.default.createElement(EditableUserBubble, {
3195
+ return /* @__PURE__ */ import_react12.default.createElement(EditableUserBubble, {
3143
3196
  item,
3144
3197
  slots,
3145
3198
  actions: actionRow
3146
3199
  });
3147
3200
  }
3148
3201
  const className = joinClasses(classNames?.root, classNames?.byRole?.[item.role]);
3149
- return /* @__PURE__ */ import_react11.default.createElement("div", {
3202
+ return /* @__PURE__ */ import_react12.default.createElement("div", {
3150
3203
  className,
3151
3204
  "data-role": item.role,
3152
3205
  "data-streaming": item.isStreaming ? "true" : void 0
3153
- }, /* @__PURE__ */ import_react11.default.createElement("div", null, renderBlocks(item, slots)), actionRow);
3206
+ }, /* @__PURE__ */ import_react12.default.createElement("div", null, renderBlocks(item, slots)), actionRow);
3154
3207
  }
3155
3208
  __name(MessageItemView, "MessageItemView");
3156
3209
  function renderBlocks(item, slots) {
3157
3210
  const nodes = [];
3158
3211
  for (const block of item.blocks) {
3159
3212
  if (block.kind === "text") {
3160
- nodes.push(/* @__PURE__ */ import_react11.default.createElement("div", {
3213
+ nodes.push(/* @__PURE__ */ import_react12.default.createElement("div", {
3161
3214
  key: block.key,
3162
3215
  className: slots.classNames?.text
3163
3216
  }, slots.renderText ? slots.renderText(block.text, {
@@ -3178,7 +3231,7 @@ function renderBlocks(item, slots) {
3178
3231
  continue;
3179
3232
  }
3180
3233
  if (block.kind === "ui" && slots.renderUi) {
3181
- nodes.push(/* @__PURE__ */ import_react11.default.createElement("div", {
3234
+ nodes.push(/* @__PURE__ */ import_react12.default.createElement("div", {
3182
3235
  key: block.key,
3183
3236
  "data-slot": "ui",
3184
3237
  "data-component": block.component
@@ -3189,18 +3242,18 @@ function renderBlocks(item, slots) {
3189
3242
  }
3190
3243
  __name(renderBlocks, "renderBlocks");
3191
3244
  function renderFilesBlock(block, slots) {
3192
- return /* @__PURE__ */ import_react11.default.createElement("div", {
3245
+ return /* @__PURE__ */ import_react12.default.createElement("div", {
3193
3246
  key: block.key,
3194
3247
  className: slots.classNames?.files,
3195
3248
  "data-files": "true"
3196
- }, slots.renderFiles ? slots.renderFiles(block.files) : block.files.map((file) => /* @__PURE__ */ import_react11.default.createElement("a", {
3249
+ }, slots.renderFiles ? slots.renderFiles(block.files) : block.files.map((file) => /* @__PURE__ */ import_react12.default.createElement("a", {
3197
3250
  key: file.url,
3198
3251
  href: file.url,
3199
3252
  target: "_blank",
3200
3253
  rel: "noreferrer",
3201
3254
  className: slots.classNames?.file,
3202
3255
  title: file.filename ?? file.mediaType
3203
- }, file.isImage ? /* @__PURE__ */ import_react11.default.createElement("img", {
3256
+ }, file.isImage ? /* @__PURE__ */ import_react12.default.createElement("img", {
3204
3257
  src: file.url,
3205
3258
  alt: file.filename ?? "image",
3206
3259
  className: slots.classNames?.fileImage
@@ -3208,17 +3261,17 @@ function renderFilesBlock(block, slots) {
3208
3261
  }
3209
3262
  __name(renderFilesBlock, "renderFilesBlock");
3210
3263
  function renderReasoningBlock(block, slots) {
3211
- return /* @__PURE__ */ import_react11.default.createElement("div", {
3264
+ return /* @__PURE__ */ import_react12.default.createElement("div", {
3212
3265
  key: block.key,
3213
3266
  className: slots.classNames?.reasoning,
3214
3267
  "data-reasoning": "true",
3215
3268
  "data-streaming": block.isStreaming ? "true" : void 0
3216
- }, /* @__PURE__ */ import_react11.default.createElement("button", {
3269
+ }, /* @__PURE__ */ import_react12.default.createElement("button", {
3217
3270
  type: "button",
3218
3271
  className: slots.classNames?.reasoningToggle,
3219
3272
  onClick: /* @__PURE__ */ __name(() => block.toggle(), "onClick"),
3220
3273
  "aria-expanded": block.isOpen
3221
- }, slots.reasoningLabel ?? "Reasoning"), block.isOpen ? /* @__PURE__ */ import_react11.default.createElement("div", {
3274
+ }, slots.reasoningLabel ?? "Reasoning"), block.isOpen ? /* @__PURE__ */ import_react12.default.createElement("div", {
3222
3275
  className: slots.classNames?.reasoningText
3223
3276
  }, slots.renderReasoning ? slots.renderReasoning(block.text, {
3224
3277
  isStreaming: block.isStreaming,
@@ -3229,7 +3282,7 @@ __name(renderReasoningBlock, "renderReasoningBlock");
3229
3282
  function renderToolBlock(item, block, slots) {
3230
3283
  if (slots.renderToolGroup) {
3231
3284
  return [
3232
- /* @__PURE__ */ import_react11.default.createElement(import_react11.default.Fragment, {
3285
+ /* @__PURE__ */ import_react12.default.createElement(import_react12.default.Fragment, {
3233
3286
  key: block.key
3234
3287
  }, slots.renderToolGroup(block.parts, block.key))
3235
3288
  ];
@@ -3240,7 +3293,7 @@ function renderToolBlock(item, block, slots) {
3240
3293
  const renderToolPart = slots.renderToolPart;
3241
3294
  return block.parts.map((part) => {
3242
3295
  const partKey = `${item.id}-${part.toolCallId}`;
3243
- return /* @__PURE__ */ import_react11.default.createElement(import_react11.default.Fragment, {
3296
+ return /* @__PURE__ */ import_react12.default.createElement(import_react12.default.Fragment, {
3244
3297
  key: partKey
3245
3298
  }, renderToolPart(part, partKey));
3246
3299
  });
@@ -3250,14 +3303,14 @@ function EditableUserBubble({ item, slots, actions }) {
3250
3303
  const { classNames } = slots;
3251
3304
  const { edit } = item;
3252
3305
  if (!edit.isEditing) {
3253
- return /* @__PURE__ */ import_react11.default.createElement("div", {
3306
+ return /* @__PURE__ */ import_react12.default.createElement("div", {
3254
3307
  className: joinClasses(classNames?.root, classNames?.byRole?.user),
3255
3308
  "data-role": "user"
3256
- }, /* @__PURE__ */ import_react11.default.createElement("div", {
3309
+ }, /* @__PURE__ */ import_react12.default.createElement("div", {
3257
3310
  className: classNames?.text
3258
3311
  }, slots.renderText ? slots.renderText(item.text, {
3259
3312
  isStreaming: false
3260
- }) : item.text), /* @__PURE__ */ import_react11.default.createElement("button", {
3313
+ }) : item.text), /* @__PURE__ */ import_react12.default.createElement("button", {
3261
3314
  type: "button",
3262
3315
  onClick: edit.start,
3263
3316
  className: classNames?.actionButton,
@@ -3265,18 +3318,18 @@ function EditableUserBubble({ item, slots, actions }) {
3265
3318
  }, "Edit"), actions);
3266
3319
  }
3267
3320
  const textareaProps = edit.getTextareaProps();
3268
- return /* @__PURE__ */ import_react11.default.createElement("div", {
3321
+ return /* @__PURE__ */ import_react12.default.createElement("div", {
3269
3322
  "data-editing": "true"
3270
- }, /* @__PURE__ */ import_react11.default.createElement("textarea", {
3323
+ }, /* @__PURE__ */ import_react12.default.createElement("textarea", {
3271
3324
  ...textareaProps,
3272
3325
  rows: Math.min(8, edit.draft.split("\n").length + 1),
3273
3326
  className: classNames?.editTextarea
3274
- }), /* @__PURE__ */ import_react11.default.createElement("div", {
3327
+ }), /* @__PURE__ */ import_react12.default.createElement("div", {
3275
3328
  className: classNames?.editActions
3276
- }, /* @__PURE__ */ import_react11.default.createElement("button", {
3329
+ }, /* @__PURE__ */ import_react12.default.createElement("button", {
3277
3330
  type: "button",
3278
3331
  onClick: edit.cancel
3279
- }, "Cancel"), /* @__PURE__ */ import_react11.default.createElement("button", {
3332
+ }, "Cancel"), /* @__PURE__ */ import_react12.default.createElement("button", {
3280
3333
  type: "button",
3281
3334
  onClick: edit.save,
3282
3335
  disabled: !edit.canSave
@@ -3520,35 +3573,35 @@ function toItem(entry) {
3520
3573
  __name(toItem, "toItem");
3521
3574
 
3522
3575
  // src/composer/use-composer-autocomplete.ts
3523
- var import_react12 = require("react");
3576
+ var import_react13 = require("react");
3524
3577
  function useComposerAutocomplete(options) {
3525
3578
  const { value, sources, acceptOnTab = true } = options;
3526
- const latest = (0, import_react12.useRef)(options);
3579
+ const latest = (0, import_react13.useRef)(options);
3527
3580
  latest.current = options;
3528
- const inputRef = (0, import_react12.useRef)(null);
3529
- const [caret, setCaret] = (0, import_react12.useState)(value.length);
3530
- const [items, setItems] = (0, import_react12.useState)([]);
3531
- const [isLoading, setLoading] = (0, import_react12.useState)(false);
3532
- const [error, setError] = (0, import_react12.useState)(null);
3533
- const [activeIndex, setActiveIndex] = (0, import_react12.useState)(0);
3534
- const [dismissedIndex, setDismissedIndex] = (0, import_react12.useState)(null);
3581
+ const inputRef = (0, import_react13.useRef)(null);
3582
+ const [caret, setCaret] = (0, import_react13.useState)(value.length);
3583
+ const [items, setItems] = (0, import_react13.useState)([]);
3584
+ const [isLoading, setLoading] = (0, import_react13.useState)(false);
3585
+ const [error, setError] = (0, import_react13.useState)(null);
3586
+ const [activeIndex, setActiveIndex] = (0, import_react13.useState)(0);
3587
+ const [dismissedIndex, setDismissedIndex] = (0, import_react13.useState)(null);
3535
3588
  const safeCaret = Math.min(caret, value.length);
3536
- const match = (0, import_react12.useMemo)(() => findActiveTrigger(value, safeCaret, sources), [
3589
+ const match = (0, import_react13.useMemo)(() => findActiveTrigger(value, safeCaret, sources), [
3537
3590
  value,
3538
3591
  safeCaret,
3539
3592
  sources
3540
3593
  ]);
3541
3594
  const isActive = match !== null && dismissedIndex !== match.index;
3542
- const matchRef = (0, import_react12.useRef)(match);
3595
+ const matchRef = (0, import_react13.useRef)(match);
3543
3596
  matchRef.current = match;
3544
- const caretRef = (0, import_react12.useRef)(safeCaret);
3597
+ const caretRef = (0, import_react13.useRef)(safeCaret);
3545
3598
  caretRef.current = safeCaret;
3546
- const itemsRef = (0, import_react12.useRef)(items);
3599
+ const itemsRef = (0, import_react13.useRef)(items);
3547
3600
  itemsRef.current = items;
3548
- const activeIndexRef = (0, import_react12.useRef)(activeIndex);
3601
+ const activeIndexRef = (0, import_react13.useRef)(activeIndex);
3549
3602
  activeIndexRef.current = activeIndex;
3550
3603
  const requestKey = isActive && match ? `${match.source.id}\0${match.query}` : null;
3551
- (0, import_react12.useEffect)(() => {
3604
+ (0, import_react13.useEffect)(() => {
3552
3605
  const current = matchRef.current;
3553
3606
  if (requestKey === null || current === null) {
3554
3607
  setItems([]);
@@ -3596,25 +3649,25 @@ function useComposerAutocomplete(options) {
3596
3649
  ]);
3597
3650
  const isOpen = isActive;
3598
3651
  const activeItem = isOpen ? items[activeIndex] ?? null : null;
3599
- const reactId = (0, import_react12.useId)();
3652
+ const reactId = (0, import_react13.useId)();
3600
3653
  const listboxId = options.id ?? `agent-autocomplete-${reactId}`;
3601
- const optionId = (0, import_react12.useCallback)((index) => `${listboxId}-option-${index}`, [
3654
+ const optionId = (0, import_react13.useCallback)((index) => `${listboxId}-option-${index}`, [
3602
3655
  listboxId
3603
3656
  ]);
3604
- const highlight = (0, import_react12.useCallback)((index) => {
3657
+ const highlight = (0, import_react13.useCallback)((index) => {
3605
3658
  const total = itemsRef.current.length;
3606
3659
  if (total === 0) return;
3607
3660
  setActiveIndex((index % total + total) % total);
3608
3661
  }, []);
3609
- const moveHighlight = (0, import_react12.useCallback)((delta) => highlight(activeIndexRef.current + delta), [
3662
+ const moveHighlight = (0, import_react13.useCallback)((delta) => highlight(activeIndexRef.current + delta), [
3610
3663
  highlight
3611
3664
  ]);
3612
- const dismiss = (0, import_react12.useCallback)(() => {
3665
+ const dismiss = (0, import_react13.useCallback)(() => {
3613
3666
  const current = matchRef.current;
3614
3667
  if (current) setDismissedIndex(current.index);
3615
3668
  }, []);
3616
- const pendingCaret = (0, import_react12.useRef)(null);
3617
- const accept = (0, import_react12.useCallback)((item) => {
3669
+ const pendingCaret = (0, import_react13.useRef)(null);
3670
+ const accept = (0, import_react13.useCallback)((item) => {
3618
3671
  const current = matchRef.current;
3619
3672
  if (!current) return;
3620
3673
  const chosen = item ?? itemsRef.current[activeIndexRef.current];
@@ -3625,16 +3678,16 @@ function useComposerAutocomplete(options) {
3625
3678
  setDismissedIndex(null);
3626
3679
  pendingCaret.current = edit.caret;
3627
3680
  }, []);
3628
- (0, import_react12.useLayoutEffect)(() => {
3681
+ (0, import_react13.useLayoutEffect)(() => {
3629
3682
  const position = pendingCaret.current;
3630
3683
  if (position === null) return;
3631
3684
  pendingCaret.current = null;
3632
3685
  inputRef.current?.setSelectionRange(position, position);
3633
3686
  });
3634
- const readCaret = (0, import_react12.useCallback)((element) => {
3687
+ const readCaret = (0, import_react13.useCallback)((element) => {
3635
3688
  setCaret(element.selectionStart ?? element.value.length);
3636
3689
  }, []);
3637
- const onKeyDown = (0, import_react12.useCallback)((event) => {
3690
+ const onKeyDown = (0, import_react13.useCallback)((event) => {
3638
3691
  if (!isOpen) return;
3639
3692
  const hasItems = itemsRef.current.length > 0;
3640
3693
  switch (event.key) {
@@ -3672,23 +3725,23 @@ function useComposerAutocomplete(options) {
3672
3725
  dismiss,
3673
3726
  moveHighlight
3674
3727
  ]);
3675
- const onChange = (0, import_react12.useCallback)((event) => {
3728
+ const onChange = (0, import_react13.useCallback)((event) => {
3676
3729
  readCaret(event.target);
3677
3730
  const next = findActiveTrigger(event.target.value, event.target.selectionStart ?? event.target.value.length, latest.current.sources);
3678
3731
  setDismissedIndex((current) => current !== null && next?.index === current ? current : null);
3679
3732
  }, [
3680
3733
  readCaret
3681
3734
  ]);
3682
- const onSelect = (0, import_react12.useCallback)((event) => readCaret(event.currentTarget), [
3735
+ const onSelect = (0, import_react13.useCallback)((event) => readCaret(event.currentTarget), [
3683
3736
  readCaret
3684
3737
  ]);
3685
- const onClick = (0, import_react12.useCallback)((event) => readCaret(event.currentTarget), [
3738
+ const onClick = (0, import_react13.useCallback)((event) => readCaret(event.currentTarget), [
3686
3739
  readCaret
3687
3740
  ]);
3688
- const setInput = (0, import_react12.useCallback)((element) => {
3741
+ const setInput = (0, import_react13.useCallback)((element) => {
3689
3742
  inputRef.current = element;
3690
3743
  }, []);
3691
- const getInputProps = (0, import_react12.useCallback)(() => ({
3744
+ const getInputProps = (0, import_react13.useCallback)(() => ({
3692
3745
  ref: setInput,
3693
3746
  onChange,
3694
3747
  onKeyDown,
@@ -3716,7 +3769,7 @@ function useComposerAutocomplete(options) {
3716
3769
  activeIndex,
3717
3770
  optionId
3718
3771
  ]);
3719
- const getListboxProps = (0, import_react12.useCallback)(() => ({
3772
+ const getListboxProps = (0, import_react13.useCallback)(() => ({
3720
3773
  id: listboxId,
3721
3774
  role: "listbox",
3722
3775
  "aria-label": match?.source.label ?? match?.source.id ?? "Suggestions"
@@ -3724,7 +3777,7 @@ function useComposerAutocomplete(options) {
3724
3777
  listboxId,
3725
3778
  match
3726
3779
  ]);
3727
- const getOptionProps = (0, import_react12.useCallback)((index) => ({
3780
+ const getOptionProps = (0, import_react13.useCallback)((index) => ({
3728
3781
  id: optionId(index),
3729
3782
  role: "option",
3730
3783
  "aria-selected": index === activeIndex
@@ -3758,7 +3811,7 @@ function isPromise(value) {
3758
3811
  __name(isPromise, "isPromise");
3759
3812
 
3760
3813
  // src/presentation/use-tool-catalog.ts
3761
- var import_react13 = require("react");
3814
+ var import_react14 = require("react");
3762
3815
  var shared = /* @__PURE__ */ new WeakMap();
3763
3816
  function load(client, agent) {
3764
3817
  let byAgent = shared.get(client);
@@ -3782,11 +3835,11 @@ function load(client, agent) {
3782
3835
  __name(load, "load");
3783
3836
  function useToolCatalog(options) {
3784
3837
  const { client, agent, enabled = true } = options;
3785
- const [entries, setEntries] = (0, import_react13.useState)([]);
3786
- const [isLoading, setLoading] = (0, import_react13.useState)(enabled);
3787
- const [error, setError] = (0, import_react13.useState)(null);
3788
- const [generation, setGeneration] = (0, import_react13.useState)(0);
3789
- (0, import_react13.useEffect)(() => {
3838
+ const [entries, setEntries] = (0, import_react14.useState)([]);
3839
+ const [isLoading, setLoading] = (0, import_react14.useState)(enabled);
3840
+ const [error, setError] = (0, import_react14.useState)(null);
3841
+ const [generation, setGeneration] = (0, import_react14.useState)(0);
3842
+ (0, import_react14.useEffect)(() => {
3790
3843
  if (!enabled) {
3791
3844
  setLoading(false);
3792
3845
  return;
@@ -3812,14 +3865,14 @@ function useToolCatalog(options) {
3812
3865
  enabled,
3813
3866
  generation
3814
3867
  ]);
3815
- const refresh = (0, import_react13.useCallback)(() => {
3868
+ const refresh = (0, import_react14.useCallback)(() => {
3816
3869
  shared.get(client)?.delete(agent ?? "");
3817
3870
  setGeneration((current) => current + 1);
3818
3871
  }, [
3819
3872
  client,
3820
3873
  agent
3821
3874
  ]);
3822
- const catalog = (0, import_react13.useMemo)(() => toolCatalogFrom(entries), [
3875
+ const catalog = (0, import_react14.useMemo)(() => toolCatalogFrom(entries), [
3823
3876
  entries
3824
3877
  ]);
3825
3878
  return {
@@ -3833,7 +3886,7 @@ function useToolCatalog(options) {
3833
3886
  __name(useToolCatalog, "useToolCatalog");
3834
3887
 
3835
3888
  // src/approvals/countdown.ts
3836
- var import_react14 = require("react");
3889
+ var import_react15 = require("react");
3837
3890
  function approvalCountdown(expiresAt, now = Date.now()) {
3838
3891
  const deadline = expiresAt == null ? Number.NaN : Date.parse(expiresAt);
3839
3892
  if (!Number.isFinite(deadline)) {
@@ -3851,10 +3904,10 @@ function approvalCountdown(expiresAt, now = Date.now()) {
3851
3904
  __name(approvalCountdown, "approvalCountdown");
3852
3905
  function useApprovalCountdown(expiresAt, options = {}) {
3853
3906
  const { intervalMs = 1e3 } = options;
3854
- const nowRef = (0, import_react14.useRef)(options.now ?? Date.now);
3907
+ const nowRef = (0, import_react15.useRef)(options.now ?? Date.now);
3855
3908
  nowRef.current = options.now ?? Date.now;
3856
- const [state, setState] = (0, import_react14.useState)(() => approvalCountdown(expiresAt, nowRef.current()));
3857
- (0, import_react14.useEffect)(() => {
3909
+ const [state, setState] = (0, import_react15.useState)(() => approvalCountdown(expiresAt, nowRef.current()));
3910
+ (0, import_react15.useEffect)(() => {
3858
3911
  const read = /* @__PURE__ */ __name(() => approvalCountdown(expiresAt, nowRef.current()), "read");
3859
3912
  const first = read();
3860
3913
  setState(first);
@@ -4095,21 +4148,21 @@ function sumUsage(rows) {
4095
4148
  __name(sumUsage, "sumUsage");
4096
4149
 
4097
4150
  // src/use-agent-chat.ts
4098
- var import_react15 = require("@ai-sdk/react");
4099
- var import_react16 = require("react");
4151
+ var import_react16 = require("@ai-sdk/react");
4152
+ var import_react17 = require("react");
4100
4153
  function useAgentChat(options) {
4101
- const latest = (0, import_react16.useRef)(options);
4154
+ const latest = (0, import_react17.useRef)(options);
4102
4155
  latest.current = options;
4103
- const [runId, setRunId] = (0, import_react16.useState)(options.resumeRunId);
4104
- const runIdRef = (0, import_react16.useRef)(runId);
4156
+ const [runId, setRunId] = (0, import_react17.useState)(options.resumeRunId);
4157
+ const runIdRef = (0, import_react17.useRef)(runId);
4105
4158
  runIdRef.current = runId;
4106
- const settlingRunIdRef = (0, import_react16.useRef)(void 0);
4107
- const autoResumeRunIdRef = (0, import_react16.useRef)(void 0);
4108
- const [autoResume, setAutoResume] = (0, import_react16.useState)(false);
4109
- const [activeRunId, setActiveRunId] = (0, import_react16.useState)(null);
4110
- const regenerateNext = (0, import_react16.useRef)(false);
4111
- const createdThreadId = (0, import_react16.useRef)(void 0);
4112
- const client = (0, import_react16.useMemo)(() => {
4159
+ const settlingRunIdRef = (0, import_react17.useRef)(void 0);
4160
+ const autoResumeRunIdRef = (0, import_react17.useRef)(void 0);
4161
+ const [autoResume, setAutoResume] = (0, import_react17.useState)(false);
4162
+ const [activeRunId, setActiveRunId] = (0, import_react17.useState)(null);
4163
+ const regenerateNext = (0, import_react17.useRef)(false);
4164
+ const createdThreadId = (0, import_react17.useRef)(void 0);
4165
+ const client = (0, import_react17.useMemo)(() => {
4113
4166
  if (options.backend) return options.backend;
4114
4167
  if (options.client) return options.client;
4115
4168
  return new AgentClient({
@@ -4125,11 +4178,11 @@ function useAgentChat(options) {
4125
4178
  getHeaders: /* @__PURE__ */ __name(async () => mergeHeaders(latest.current), "getHeaders")
4126
4179
  });
4127
4180
  }, []);
4128
- const [connection, setConnection] = (0, import_react16.useState)({
4181
+ const [connection, setConnection] = (0, import_react17.useState)({
4129
4182
  status: "live"
4130
4183
  });
4131
- const resyncAfterSettle = (0, import_react16.useRef)(false);
4132
- (0, import_react16.useEffect)(() => {
4184
+ const resyncAfterSettle = (0, import_react17.useRef)(false);
4185
+ (0, import_react17.useEffect)(() => {
4133
4186
  if (!options.resume || options.threadId === void 0) return;
4134
4187
  let cancelled = false;
4135
4188
  const threadId = options.threadId;
@@ -4149,7 +4202,7 @@ function useAgentChat(options) {
4149
4202
  options.resume,
4150
4203
  options.threadId
4151
4204
  ]);
4152
- const transport = (0, import_react16.useMemo)(() => {
4205
+ const transport = (0, import_react17.useMemo)(() => {
4153
4206
  function onMeta(meta) {
4154
4207
  settlingRunIdRef.current = meta.runId;
4155
4208
  setRunId(meta.runId);
@@ -4204,8 +4257,8 @@ function useAgentChat(options) {
4204
4257
  }, "onAttemptStart")
4205
4258
  });
4206
4259
  }, []);
4207
- const backgroundRef = (0, import_react16.useRef)(() => Promise.resolve());
4208
- const chat = (0, import_react15.useChat)({
4260
+ const backgroundRef = (0, import_react17.useRef)(() => Promise.resolve());
4261
+ const chat = (0, import_react16.useChat)({
4209
4262
  transport,
4210
4263
  resume: options.resumeRunId !== void 0 || autoResume,
4211
4264
  ...options.threadId !== void 0 ? {
@@ -4253,7 +4306,7 @@ function useAgentChat(options) {
4253
4306
  }
4254
4307
  }, "onFinish")
4255
4308
  });
4256
- const chatRef = (0, import_react16.useRef)(chat);
4309
+ const chatRef = (0, import_react17.useRef)(chat);
4257
4310
  chatRef.current = chat;
4258
4311
  async function resyncFromThread() {
4259
4312
  const threadId = latest.current.threadId ?? createdThreadId.current;
@@ -4265,11 +4318,13 @@ function useAgentChat(options) {
4265
4318
  }
4266
4319
  }
4267
4320
  __name(resyncFromThread, "resyncFromThread");
4268
- const turnInFlight = (0, import_react16.useRef)(false);
4269
- const isTurnInFlight = (0, import_react16.useCallback)(() => turnInFlight.current || transport.isAttemptLive, [
4321
+ const turnInFlight = (0, import_react17.useRef)(false);
4322
+ const isTurnInFlight = (0, import_react17.useCallback)(() => turnInFlight.current || transport.isAttemptLive, [
4270
4323
  transport
4271
4324
  ]);
4272
- const sendMessage = (0, import_react16.useCallback)(async (...args) => {
4325
+ const sendMessage = (0, import_react17.useCallback)(async (...args) => {
4326
+ const blocked = latest.current.blocked;
4327
+ if (blocked != null) throw new QuotaBlockedError(blocked);
4273
4328
  if (isTurnInFlight()) return;
4274
4329
  turnInFlight.current = true;
4275
4330
  try {
@@ -4280,15 +4335,15 @@ function useAgentChat(options) {
4280
4335
  }, [
4281
4336
  isTurnInFlight
4282
4337
  ]);
4283
- const addToolResult = (0, import_react16.useCallback)(({ tool, toolCallId, output }) => chatRef.current.addToolResult({
4338
+ const addToolResult = (0, import_react17.useCallback)(({ tool, toolCallId, output }) => chatRef.current.addToolResult({
4284
4339
  tool,
4285
4340
  toolCallId,
4286
4341
  output
4287
4342
  }), []);
4288
- const [threads, setThreads] = (0, import_react16.useState)([]);
4289
- const [quota, setQuota] = (0, import_react16.useState)(null);
4290
- const [backgroundRuns, setBackgroundRuns] = (0, import_react16.useState)([]);
4291
- const refreshBackground = (0, import_react16.useCallback)(async () => {
4343
+ const [threads, setThreads] = (0, import_react17.useState)([]);
4344
+ const [quota, setQuota] = (0, import_react17.useState)(null);
4345
+ const [backgroundRuns, setBackgroundRuns] = (0, import_react17.useState)([]);
4346
+ const refreshBackground = (0, import_react17.useCallback)(async () => {
4292
4347
  const threadId = latest.current.threadId ?? createdThreadId.current;
4293
4348
  if (threadId === void 0) {
4294
4349
  return;
@@ -4313,7 +4368,7 @@ function useAgentChat(options) {
4313
4368
  ]);
4314
4369
  backgroundRef.current = refreshBackground;
4315
4370
  const isWorking = backgroundRuns.some((run) => run.status === "running");
4316
- (0, import_react16.useEffect)(() => {
4371
+ (0, import_react17.useEffect)(() => {
4317
4372
  if (options.background !== true || options.threadId === void 0) {
4318
4373
  return;
4319
4374
  }
@@ -4323,7 +4378,7 @@ function useAgentChat(options) {
4323
4378
  options.threadId,
4324
4379
  refreshBackground
4325
4380
  ]);
4326
- (0, import_react16.useEffect)(() => {
4381
+ (0, import_react17.useEffect)(() => {
4327
4382
  const every = latest.current.backgroundPollMs ?? 5e3;
4328
4383
  if (latest.current.background !== true || !isWorking || every <= 0) {
4329
4384
  return;
@@ -4334,26 +4389,26 @@ function useAgentChat(options) {
4334
4389
  isWorking,
4335
4390
  refreshBackground
4336
4391
  ]);
4337
- const loadThreads = (0, import_react16.useCallback)(async () => {
4392
+ const loadThreads = (0, import_react17.useCallback)(async () => {
4338
4393
  const list = await client.listThreads();
4339
4394
  setThreads(list);
4340
4395
  return list;
4341
4396
  }, [
4342
4397
  client
4343
4398
  ]);
4344
- const loadThread = (0, import_react16.useCallback)((id) => client.getThread(id), [
4399
+ const loadThread = (0, import_react17.useCallback)((id) => client.getThread(id), [
4345
4400
  client
4346
4401
  ]);
4347
- const deleteThread = (0, import_react16.useCallback)(async (id) => {
4402
+ const deleteThread = (0, import_react17.useCallback)(async (id) => {
4348
4403
  await client.deleteThread(id);
4349
4404
  setThreads((current) => current.filter((thread) => thread.id !== id));
4350
4405
  }, [
4351
4406
  client
4352
4407
  ]);
4353
- const forkThread = (0, import_react16.useCallback)((threadId, messageId) => requireBackendMethod(client, "forkFromMessage")(threadId, messageId), [
4408
+ const forkThread = (0, import_react17.useCallback)((threadId, messageId) => requireBackendMethod(client, "forkFromMessage")(threadId, messageId), [
4354
4409
  client
4355
4410
  ]);
4356
- const renameThread = (0, import_react16.useCallback)(async (id, title) => {
4411
+ const renameThread = (0, import_react17.useCallback)(async (id, title) => {
4357
4412
  await client.updateThread(id, {
4358
4413
  title
4359
4414
  });
@@ -4364,24 +4419,24 @@ function useAgentChat(options) {
4364
4419
  }, [
4365
4420
  client
4366
4421
  ]);
4367
- const promoteThread = (0, import_react16.useCallback)(async (id) => {
4422
+ const promoteThread = (0, import_react17.useCallback)(async (id) => {
4368
4423
  await requireBackendMethod(client, "promoteThread")(id);
4369
4424
  await loadThreads();
4370
4425
  }, [
4371
4426
  client,
4372
4427
  loadThreads
4373
4428
  ]);
4374
- const truncateFromMessage = (0, import_react16.useCallback)((threadId, messageId) => requireBackendMethod(client, "truncateFromMessage")(threadId, messageId).then(() => void 0), [
4429
+ const truncateFromMessage = (0, import_react17.useCallback)((threadId, messageId) => requireBackendMethod(client, "truncateFromMessage")(threadId, messageId).then(() => void 0), [
4375
4430
  client
4376
4431
  ]);
4377
- const loadQuota = (0, import_react16.useCallback)(async () => {
4432
+ const loadQuota = (0, import_react17.useCallback)(async () => {
4378
4433
  const today = await requireBackendMethod(client, "getQuotaToday")();
4379
4434
  setQuota(today);
4380
4435
  return today;
4381
4436
  }, [
4382
4437
  client
4383
4438
  ]);
4384
- const cancel = (0, import_react16.useCallback)(async () => {
4439
+ const cancel = (0, import_react17.useCallback)(async () => {
4385
4440
  chatRef.current.stop();
4386
4441
  const activeRunId2 = runIdRef.current;
4387
4442
  if (activeRunId2) {
@@ -4393,7 +4448,7 @@ function useAgentChat(options) {
4393
4448
  }, [
4394
4449
  client
4395
4450
  ]);
4396
- const approve = (0, import_react16.useCallback)(async ({ toolCallId, remember, via }) => {
4451
+ const approve = (0, import_react17.useCallback)(async ({ toolCallId, remember, via }) => {
4397
4452
  await requireBackendMethod(client, "approveToolCall")({
4398
4453
  toolCallId,
4399
4454
  ...remember === true ? {
@@ -4406,7 +4461,7 @@ function useAgentChat(options) {
4406
4461
  }, [
4407
4462
  client
4408
4463
  ]);
4409
- const reject = (0, import_react16.useCallback)(async ({ toolCallId, reason, via }) => {
4464
+ const reject = (0, import_react17.useCallback)(async ({ toolCallId, reason, via }) => {
4410
4465
  await requireBackendMethod(client, "rejectToolCall")({
4411
4466
  toolCallId,
4412
4467
  ...reason !== void 0 ? {
@@ -4419,7 +4474,7 @@ function useAgentChat(options) {
4419
4474
  }, [
4420
4475
  client
4421
4476
  ]);
4422
- const answer = (0, import_react16.useCallback)(async ({ toolCallId, answers }) => {
4477
+ const answer = (0, import_react17.useCallback)(async ({ toolCallId, answers }) => {
4423
4478
  await requireBackendMethod(client, "answerToolCall")({
4424
4479
  toolCallId,
4425
4480
  ...answers !== void 0 ? {
@@ -4429,14 +4484,16 @@ function useAgentChat(options) {
4429
4484
  }, [
4430
4485
  client
4431
4486
  ]);
4432
- const skip = (0, import_react16.useCallback)(async ({ toolCallId }) => {
4487
+ const skip = (0, import_react17.useCallback)(async ({ toolCallId }) => {
4433
4488
  await requireBackendMethod(client, "skipToolCall")({
4434
4489
  toolCallId
4435
4490
  });
4436
4491
  }, [
4437
4492
  client
4438
4493
  ]);
4439
- const regenerate = (0, import_react16.useCallback)(() => {
4494
+ const regenerate = (0, import_react17.useCallback)(() => {
4495
+ const blocked = latest.current.blocked;
4496
+ if (blocked != null) throw new QuotaBlockedError(blocked);
4440
4497
  if (isTurnInFlight()) return;
4441
4498
  regenerateNext.current = true;
4442
4499
  turnInFlight.current = true;
@@ -4451,7 +4508,7 @@ function useAgentChat(options) {
4451
4508
  isWorking,
4452
4509
  refresh: refreshBackground
4453
4510
  };
4454
- const setThreadModel = (0, import_react16.useCallback)(async (model) => {
4511
+ const setThreadModel = (0, import_react17.useCallback)(async (model) => {
4455
4512
  const threadId = latest.current.threadId ?? createdThreadId.current;
4456
4513
  if (threadId === void 0) {
4457
4514
  throw new Error("setThreadModel: this chat has no thread yet");
@@ -4465,7 +4522,7 @@ function useAgentChat(options) {
4465
4522
  }, [
4466
4523
  client
4467
4524
  ]);
4468
- const getThreadId = (0, import_react16.useCallback)(() => latest.current.threadId ?? createdThreadId.current, []);
4525
+ const getThreadId = (0, import_react17.useCallback)(() => latest.current.threadId ?? createdThreadId.current, []);
4469
4526
  const status = connection.status === "reconnecting" ? "reconnecting" : chat.status;
4470
4527
  return {
4471
4528
  ...chat,
@@ -4508,6 +4565,16 @@ function useAgentChat(options) {
4508
4565
  };
4509
4566
  }
4510
4567
  __name(useAgentChat, "useAgentChat");
4568
+ var QuotaBlockedError = class extends Error {
4569
+ static {
4570
+ __name(this, "QuotaBlockedError");
4571
+ }
4572
+ block;
4573
+ constructor(block) {
4574
+ super(block.reason ?? `The ${block.period === "day" ? "daily" : "monthly"} quota is used up`), this.block = block;
4575
+ this.name = "QuotaBlockedError";
4576
+ }
4577
+ };
4511
4578
  async function mergeHeaders(options) {
4512
4579
  const dynamic = await options.getHeaders?.() ?? {};
4513
4580
  return {
@@ -4527,6 +4594,7 @@ __name(mergeHeaders, "mergeHeaders");
4527
4594
  MessageItem,
4528
4595
  MessageItemView,
4529
4596
  MessageList,
4597
+ QuotaBlockedError,
4530
4598
  SPEECH_LANGUAGES,
4531
4599
  applyCompletion,
4532
4600
  approvalCountdown,
@@ -4568,6 +4636,7 @@ __name(mergeHeaders, "mergeHeaders");
4568
4636
  useElapsed,
4569
4637
  useMessageFeedback,
4570
4638
  useModels,
4639
+ useQuota,
4571
4640
  useSpeechRecognition,
4572
4641
  useStickToBottom,
4573
4642
  useThreads,