@dudousxd/nestjs-agent-react 0.15.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,
@@ -74,11 +75,14 @@ __export(src_exports, {
74
75
  toolCallState: () => toolCallState,
75
76
  toolCatalogFrom: () => toolCatalogFrom,
76
77
  useAgentChat: () => useAgentChat,
78
+ useAgents: () => useAgents,
77
79
  useApprovalCountdown: () => useApprovalCountdown,
78
80
  useChatTranscript: () => useChatTranscript,
79
81
  useComposerAutocomplete: () => useComposerAutocomplete,
80
82
  useElapsed: () => useElapsed,
81
83
  useMessageFeedback: () => useMessageFeedback,
84
+ useModels: () => useModels,
85
+ useQuota: () => useQuota,
82
86
  useSpeechRecognition: () => useSpeechRecognition,
83
87
  useStickToBottom: () => useStickToBottom,
84
88
  useThreads: () => useThreads,
@@ -235,6 +239,19 @@ var AgentClient = class {
235
239
  truncateFromMessage(threadId, messageId) {
236
240
  return this.request("DELETE", `/agent/threads/${encodeURIComponent(threadId)}/from/${encodeURIComponent(messageId)}`);
237
241
  }
242
+ /** `GET /agent/models?agent=` — the models this caller may pick, grouped by provider. */
243
+ listModels(agent) {
244
+ const query = agent === void 0 ? "" : `?agent=${encodeURIComponent(agent)}`;
245
+ return this.request("GET", `/agent/models${query}`);
246
+ }
247
+ /** `GET /agent/agents` — the registered agents, the default one flagged. */
248
+ listAgents() {
249
+ return this.request("GET", "/agent/agents");
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
+ }
238
255
  getQuotaToday() {
239
256
  return this.request("GET", "/agent/quota/today");
240
257
  }
@@ -1082,28 +1099,196 @@ function requireBackendMethod(backend, name) {
1082
1099
  }
1083
1100
  __name(requireBackendMethod, "requireBackendMethod");
1084
1101
 
1085
- // src/feedback/use-message-feedback.ts
1102
+ // src/catalog/use-agents.ts
1103
+ var import_react3 = require("react");
1104
+
1105
+ // src/catalog/use-resource.ts
1086
1106
  var import_react2 = require("react");
1107
+ function useResource(load2, key, enabled) {
1108
+ const [data, setData] = (0, import_react2.useState)(void 0);
1109
+ const [isLoading, setIsLoading] = (0, import_react2.useState)(enabled);
1110
+ const [error, setError] = (0, import_react2.useState)(null);
1111
+ const loadRef = (0, import_react2.useRef)(load2);
1112
+ loadRef.current = load2;
1113
+ const generation = (0, import_react2.useRef)(0);
1114
+ const refresh = (0, import_react2.useCallback)(async () => {
1115
+ const mine = ++generation.current;
1116
+ setIsLoading(true);
1117
+ try {
1118
+ const value = await loadRef.current();
1119
+ if (mine !== generation.current) return;
1120
+ setData(value);
1121
+ setError(null);
1122
+ } catch (caught) {
1123
+ if (mine !== generation.current) return;
1124
+ setError(caught instanceof Error ? caught : new Error(String(caught)));
1125
+ } finally {
1126
+ if (mine === generation.current) setIsLoading(false);
1127
+ }
1128
+ }, []);
1129
+ (0, import_react2.useEffect)(() => {
1130
+ if (!enabled) return;
1131
+ void refresh();
1132
+ }, [
1133
+ enabled,
1134
+ key,
1135
+ refresh
1136
+ ]);
1137
+ return {
1138
+ data,
1139
+ isLoading,
1140
+ error,
1141
+ refresh
1142
+ };
1143
+ }
1144
+ __name(useResource, "useResource");
1145
+
1146
+ // src/catalog/use-agents.ts
1147
+ function useAgents(options) {
1148
+ const { backend, enabled = true } = options;
1149
+ const { data, isLoading, error, refresh } = useResource(() => requireBackendMethod(backend, "listAgents")(), "", enabled);
1150
+ return (0, import_react3.useMemo)(() => {
1151
+ const agents = data ?? [];
1152
+ return {
1153
+ agents,
1154
+ defaultAgent: agents.find((agent) => agent.isDefault === true)?.name ?? null,
1155
+ isLoading,
1156
+ error,
1157
+ refresh
1158
+ };
1159
+ }, [
1160
+ data,
1161
+ isLoading,
1162
+ error,
1163
+ refresh
1164
+ ]);
1165
+ }
1166
+ __name(useAgents, "useAgents");
1167
+
1168
+ // src/catalog/use-models.ts
1169
+ var import_react4 = require("react");
1170
+ function useModels(options) {
1171
+ const { backend, agent, enabled = true } = options;
1172
+ const { data, isLoading, error, refresh } = useResource(() => requireBackendMethod(backend, "listModels")(agent), `${agent ?? ""}`, enabled);
1173
+ return (0, import_react4.useMemo)(() => {
1174
+ const providers = data?.providers ?? [];
1175
+ const models = providers.flatMap((provider) => provider.models.map((model) => ({
1176
+ ...model,
1177
+ providerId: provider.id,
1178
+ providerLabel: provider.label
1179
+ })));
1180
+ const byId = new Map(models.map((model) => [
1181
+ model.id,
1182
+ model
1183
+ ]));
1184
+ return {
1185
+ providers,
1186
+ models,
1187
+ defaultModel: data?.default ?? null,
1188
+ find: /* @__PURE__ */ __name((id) => id == null ? void 0 : byId.get(id), "find"),
1189
+ isLoading,
1190
+ error,
1191
+ refresh
1192
+ };
1193
+ }, [
1194
+ data,
1195
+ isLoading,
1196
+ error,
1197
+ refresh
1198
+ ]);
1199
+ }
1200
+ __name(useModels, "useModels");
1201
+
1202
+ // src/quota/use-quota.ts
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");
1087
1272
  function useMessageFeedback(options) {
1088
- const latest = (0, import_react2.useRef)(options);
1273
+ const latest = (0, import_react6.useRef)(options);
1089
1274
  latest.current = options;
1090
- const [local, setLocal] = (0, import_react2.useState)(/* @__PURE__ */ new Map());
1091
- const [pending, setPending] = (0, import_react2.useState)(/* @__PURE__ */ new Set());
1092
- const [error, setError] = (0, import_react2.useState)(null);
1093
- const localRef = (0, import_react2.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);
1094
1279
  localRef.current = local;
1095
- const resolved = (0, import_react2.useRef)(/* @__PURE__ */ new Map());
1096
- const feedbackOf = (0, import_react2.useCallback)((message) => {
1280
+ const resolved = (0, import_react6.useRef)(/* @__PURE__ */ new Map());
1281
+ const feedbackOf = (0, import_react6.useCallback)((message) => {
1097
1282
  const mine = local.get(message.id);
1098
1283
  if (mine !== void 0) return mine.feedback;
1099
1284
  return metadataOf(message).feedback ?? null;
1100
1285
  }, [
1101
1286
  local
1102
1287
  ]);
1103
- const isPending = (0, import_react2.useCallback)((message) => pending.has(message.id), [
1288
+ const isPending = (0, import_react6.useCallback)((message) => pending.has(message.id), [
1104
1289
  pending
1105
1290
  ]);
1106
- const storedIdFor = (0, import_react2.useCallback)(async (message) => {
1291
+ const storedIdFor = (0, import_react6.useCallback)(async (message) => {
1107
1292
  const runId = metadataOf(message).runId;
1108
1293
  if (runId === void 0) return message.id;
1109
1294
  const known = resolved.current.get(message.id);
@@ -1123,7 +1308,7 @@ function useMessageFeedback(options) {
1123
1308
  resolved.current.set(message.id, row.id);
1124
1309
  return row.id;
1125
1310
  }, []);
1126
- const rate = (0, import_react2.useCallback)(async (message, value, comment) => {
1311
+ const rate = (0, import_react6.useCallback)(async (message, value, comment) => {
1127
1312
  const setFeedback = requireBackendMethod(latest.current.backend, "setMessageFeedback");
1128
1313
  const had = localRef.current.get(message.id);
1129
1314
  const optimistic = value === null ? null : {
@@ -1169,7 +1354,7 @@ function useMessageFeedback(options) {
1169
1354
  }, [
1170
1355
  storedIdFor
1171
1356
  ]);
1172
- const toggle = (0, import_react2.useCallback)((message, value) => {
1357
+ const toggle = (0, import_react6.useCallback)((message, value) => {
1173
1358
  const mine = localRef.current.get(message.id);
1174
1359
  const current = mine !== void 0 ? mine.feedback : metadataOf(message).feedback ?? null;
1175
1360
  return rate(message, current?.value === value ? null : value);
@@ -1191,38 +1376,17 @@ function metadataOf(message) {
1191
1376
  }
1192
1377
  __name(metadataOf, "metadataOf");
1193
1378
 
1194
- // src/threads/threads-events.ts
1195
- var listeners = /* @__PURE__ */ new WeakMap();
1196
- function notifyThreads(backend, event) {
1197
- for (const listener of listeners.get(backend) ?? []) {
1198
- listener(event);
1199
- }
1200
- }
1201
- __name(notifyThreads, "notifyThreads");
1202
- function onThreadsEvent(backend, listener) {
1203
- let set = listeners.get(backend);
1204
- if (set === void 0) {
1205
- set = /* @__PURE__ */ new Set();
1206
- listeners.set(backend, set);
1207
- }
1208
- set.add(listener);
1209
- return () => {
1210
- set.delete(listener);
1211
- };
1212
- }
1213
- __name(onThreadsEvent, "onThreadsEvent");
1214
-
1215
1379
  // src/threads/use-threads.ts
1216
- var import_react3 = require("react");
1380
+ var import_react7 = require("react");
1217
1381
  function useThreads(options) {
1218
1382
  const { backend, enabled = true } = options;
1219
- const [threads, setThreads] = (0, import_react3.useState)([]);
1220
- const [isLoading, setIsLoading] = (0, import_react3.useState)(enabled);
1221
- const [error, setError] = (0, import_react3.useState)(null);
1222
- const threadsRef = (0, import_react3.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);
1223
1387
  threadsRef.current = threads;
1224
- const generation = (0, import_react3.useRef)(0);
1225
- const refresh = (0, import_react3.useCallback)(async () => {
1388
+ const generation = (0, import_react7.useRef)(0);
1389
+ const refresh = (0, import_react7.useCallback)(async () => {
1226
1390
  const mine = ++generation.current;
1227
1391
  setIsLoading(true);
1228
1392
  try {
@@ -1239,7 +1403,7 @@ function useThreads(options) {
1239
1403
  }, [
1240
1404
  backend
1241
1405
  ]);
1242
- (0, import_react3.useEffect)(() => {
1406
+ (0, import_react7.useEffect)(() => {
1243
1407
  if (!enabled) return;
1244
1408
  void refresh();
1245
1409
  return onThreadsEvent(backend, (event) => {
@@ -1259,7 +1423,7 @@ function useThreads(options) {
1259
1423
  enabled,
1260
1424
  refresh
1261
1425
  ]);
1262
- const rename = (0, import_react3.useCallback)(async (id, title) => {
1426
+ const rename = (0, import_react7.useCallback)(async (id, title) => {
1263
1427
  const before = threadsRef.current;
1264
1428
  setThreads((current) => current.map((thread) => thread.id === id ? {
1265
1429
  ...thread,
@@ -1281,7 +1445,7 @@ function useThreads(options) {
1281
1445
  }, [
1282
1446
  backend
1283
1447
  ]);
1284
- const remove = (0, import_react3.useCallback)(async (id) => {
1448
+ const remove = (0, import_react7.useCallback)(async (id) => {
1285
1449
  const before = threadsRef.current;
1286
1450
  setThreads((current) => current.filter((thread) => thread.id !== id));
1287
1451
  try {
@@ -1356,10 +1520,10 @@ function backgroundRunsFromThread(messages) {
1356
1520
  __name(backgroundRunsFromThread, "backgroundRunsFromThread");
1357
1521
 
1358
1522
  // src/components/chat-input.tsx
1359
- var import_react5 = __toESM(require("react"), 1);
1523
+ var import_react9 = __toESM(require("react"), 1);
1360
1524
 
1361
1525
  // src/components/use-speech-recognition.ts
1362
- var import_react4 = require("react");
1526
+ var import_react8 = require("react");
1363
1527
  function getRecognitionCtor() {
1364
1528
  if (typeof window === "undefined") return null;
1365
1529
  const scope = window;
@@ -1367,15 +1531,15 @@ function getRecognitionCtor() {
1367
1531
  }
1368
1532
  __name(getRecognitionCtor, "getRecognitionCtor");
1369
1533
  function useSpeechRecognition({ lang = "en-US", onFinalTranscript, onInterimTranscript }) {
1370
- const recognitionRef = (0, import_react4.useRef)(null);
1371
- const [isListening, setIsListening] = (0, import_react4.useState)(false);
1372
- const ctor = (0, import_react4.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(), []);
1373
1537
  const isSupported = ctor !== null;
1374
- const finalRef = (0, import_react4.useRef)(onFinalTranscript);
1375
- const interimRef = (0, import_react4.useRef)(onInterimTranscript);
1538
+ const finalRef = (0, import_react8.useRef)(onFinalTranscript);
1539
+ const interimRef = (0, import_react8.useRef)(onInterimTranscript);
1376
1540
  finalRef.current = onFinalTranscript;
1377
1541
  interimRef.current = onInterimTranscript;
1378
- (0, import_react4.useEffect)(() => {
1542
+ (0, import_react8.useEffect)(() => {
1379
1543
  if (!ctor) return;
1380
1544
  const recognition = new ctor();
1381
1545
  recognition.lang = lang;
@@ -1414,7 +1578,7 @@ function useSpeechRecognition({ lang = "en-US", onFinalTranscript, onInterimTran
1414
1578
  ctor,
1415
1579
  lang
1416
1580
  ]);
1417
- const start = (0, import_react4.useCallback)(() => {
1581
+ const start = (0, import_react8.useCallback)(() => {
1418
1582
  const recognition = recognitionRef.current;
1419
1583
  if (!recognition) return;
1420
1584
  try {
@@ -1424,7 +1588,7 @@ function useSpeechRecognition({ lang = "en-US", onFinalTranscript, onInterimTran
1424
1588
  console.warn("SpeechRecognition start failed", error);
1425
1589
  }
1426
1590
  }, []);
1427
- const stop = (0, import_react4.useCallback)(() => {
1591
+ const stop = (0, import_react8.useCallback)(() => {
1428
1592
  const recognition = recognitionRef.current;
1429
1593
  if (!recognition) return;
1430
1594
  try {
@@ -1443,8 +1607,8 @@ __name(useSpeechRecognition, "useSpeechRecognition");
1443
1607
 
1444
1608
  // src/components/chat-input.tsx
1445
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 }) {
1446
- const [value, setValue] = (0, import_react5.useState)("");
1447
- const [interim, setInterim] = (0, import_react5.useState)("");
1610
+ const [value, setValue] = (0, import_react9.useState)("");
1611
+ const [interim, setInterim] = (0, import_react9.useState)("");
1448
1612
  const speech = useSpeechRecognition({
1449
1613
  lang: speechLang,
1450
1614
  onFinalTranscript: /* @__PURE__ */ __name((text) => {
@@ -1455,7 +1619,7 @@ function ChatInput({ onSubmit, disabled, placeholder, rows = 2, enableSpeech = t
1455
1619
  }, "onFinalTranscript"),
1456
1620
  onInterimTranscript: /* @__PURE__ */ __name((text) => setInterim(text), "onInterimTranscript")
1457
1621
  });
1458
- (0, import_react5.useEffect)(() => {
1622
+ (0, import_react9.useEffect)(() => {
1459
1623
  if (!speech.isListening) setInterim("");
1460
1624
  }, [
1461
1625
  speech.isListening
@@ -1483,9 +1647,9 @@ function ChatInput({ onSubmit, disabled, placeholder, rows = 2, enableSpeech = t
1483
1647
  const displayValue = speech.isListening && interim ? `${value}${value && !value.endsWith(" ") ? " " : ""}${interim}` : value;
1484
1648
  const showMic = enableSpeech && speech.isSupported;
1485
1649
  const showStop = isStreaming && onStop !== void 0;
1486
- return /* @__PURE__ */ import_react5.default.createElement("div", {
1650
+ return /* @__PURE__ */ import_react9.default.createElement("div", {
1487
1651
  className
1488
- }, /* @__PURE__ */ import_react5.default.createElement("textarea", {
1652
+ }, /* @__PURE__ */ import_react9.default.createElement("textarea", {
1489
1653
  className: textareaClassName,
1490
1654
  rows,
1491
1655
  value: displayValue,
@@ -1496,17 +1660,17 @@ function ChatInput({ onSubmit, disabled, placeholder, rows = 2, enableSpeech = t
1496
1660
  }, "onChange"),
1497
1661
  onKeyDown: handleKeyDown,
1498
1662
  placeholder: placeholder ?? "Ask something (Enter to send, Shift+Enter for newline)"
1499
- }), /* @__PURE__ */ import_react5.default.createElement("button", {
1663
+ }), /* @__PURE__ */ import_react9.default.createElement("button", {
1500
1664
  type: "button",
1501
1665
  className: sendButtonClassName,
1502
1666
  onClick: submit,
1503
1667
  disabled: disabled || !value.trim()
1504
- }, sendLabel), showStop ? /* @__PURE__ */ import_react5.default.createElement("button", {
1668
+ }, sendLabel), showStop ? /* @__PURE__ */ import_react9.default.createElement("button", {
1505
1669
  type: "button",
1506
1670
  className: stopButtonClassName,
1507
1671
  onClick: /* @__PURE__ */ __name(() => void onStop(), "onClick"),
1508
1672
  "aria-label": "Stop generating"
1509
- }, stopLabel) : null, showMic ? /* @__PURE__ */ import_react5.default.createElement("button", {
1673
+ }, stopLabel) : null, showMic ? /* @__PURE__ */ import_react9.default.createElement("button", {
1510
1674
  type: "button",
1511
1675
  className: micButtonClassName,
1512
1676
  onClick: toggleMic,
@@ -1519,10 +1683,10 @@ function ChatInput({ onSubmit, disabled, placeholder, rows = 2, enableSpeech = t
1519
1683
  __name(ChatInput, "ChatInput");
1520
1684
 
1521
1685
  // src/components/message-item.tsx
1522
- var import_react8 = __toESM(require("react"), 1);
1686
+ var import_react12 = __toESM(require("react"), 1);
1523
1687
 
1524
1688
  // src/transcript/use-chat-transcript.ts
1525
- var import_react7 = require("react");
1689
+ var import_react11 = require("react");
1526
1690
 
1527
1691
  // src/transcript/model.ts
1528
1692
  var import_nestjs_agent_core2 = require("@dudousxd/nestjs-agent-core");
@@ -2499,11 +2663,11 @@ function formatCostUsd(cost) {
2499
2663
  __name(formatCostUsd, "formatCostUsd");
2500
2664
 
2501
2665
  // src/transcript/use-stick-to-bottom.ts
2502
- var import_react6 = require("react");
2666
+ var import_react10 = require("react");
2503
2667
  function useStickToBottom({ contentKey, threshold = 32 }) {
2504
- const containerRef = (0, import_react6.useRef)(null);
2505
- const [isAtBottom, setIsAtBottom] = (0, import_react6.useState)(true);
2506
- const measure = (0, import_react6.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)(() => {
2507
2671
  const element = containerRef.current;
2508
2672
  if (!element) {
2509
2673
  return;
@@ -2513,7 +2677,7 @@ function useStickToBottom({ contentKey, threshold = 32 }) {
2513
2677
  }, [
2514
2678
  threshold
2515
2679
  ]);
2516
- const scrollToBottom = (0, import_react6.useCallback)(() => {
2680
+ const scrollToBottom = (0, import_react10.useCallback)(() => {
2517
2681
  const element = containerRef.current;
2518
2682
  if (!element) {
2519
2683
  return;
@@ -2521,7 +2685,7 @@ function useStickToBottom({ contentKey, threshold = 32 }) {
2521
2685
  element.scrollTop = element.scrollHeight;
2522
2686
  setIsAtBottom(true);
2523
2687
  }, []);
2524
- const setContainer = (0, import_react6.useCallback)((element) => {
2688
+ const setContainer = (0, import_react10.useCallback)((element) => {
2525
2689
  containerRef.current = element;
2526
2690
  if (element) {
2527
2691
  measure();
@@ -2529,7 +2693,7 @@ function useStickToBottom({ contentKey, threshold = 32 }) {
2529
2693
  }, [
2530
2694
  measure
2531
2695
  ]);
2532
- (0, import_react6.useEffect)(() => {
2696
+ (0, import_react10.useEffect)(() => {
2533
2697
  if (isAtBottom) {
2534
2698
  scrollToBottom();
2535
2699
  }
@@ -2538,7 +2702,7 @@ function useStickToBottom({ contentKey, threshold = 32 }) {
2538
2702
  isAtBottom,
2539
2703
  scrollToBottom
2540
2704
  ]);
2541
- const getContainerProps = (0, import_react6.useCallback)(() => ({
2705
+ const getContainerProps = (0, import_react10.useCallback)(() => ({
2542
2706
  ref: setContainer,
2543
2707
  onScroll: measure
2544
2708
  }), [
@@ -2560,14 +2724,14 @@ var DEFAULT_LOAD_EARLIER_STEP = 50;
2560
2724
  var DEFAULT_COPY_RESET_MS = 1500;
2561
2725
  function useChatTranscript(options) {
2562
2726
  const { messages, status, initialVisibleCount = DEFAULT_VISIBLE_COUNT, loadEarlierStep = DEFAULT_LOAD_EARLIER_STEP, followUps, stickToBottomThreshold } = options;
2563
- const latest = (0, import_react7.useRef)(options);
2727
+ const latest = (0, import_react11.useRef)(options);
2564
2728
  latest.current = options;
2565
- const [visibleCount, setVisibleCount] = (0, import_react7.useState)(initialVisibleCount);
2566
- const [stopRequested, setStopRequested] = (0, import_react7.useState)(false);
2729
+ const [visibleCount, setVisibleCount] = (0, import_react11.useState)(initialVisibleCount);
2730
+ const [stopRequested, setStopRequested] = (0, import_react11.useState)(false);
2567
2731
  const isStreaming = status === "streaming" || status === "reconnecting";
2568
2732
  const isBusy = status === "submitted" || isStreaming;
2569
2733
  const isEmpty = messages.length === 0;
2570
- (0, import_react7.useEffect)(() => {
2734
+ (0, import_react11.useEffect)(() => {
2571
2735
  if (!isBusy) {
2572
2736
  setStopRequested(false);
2573
2737
  }
@@ -2584,7 +2748,7 @@ function useChatTranscript(options) {
2584
2748
  streamingMessageId,
2585
2749
  options
2586
2750
  });
2587
- const stop = (0, import_react7.useCallback)(() => {
2751
+ const stop = (0, import_react11.useCallback)(() => {
2588
2752
  const current = latest.current;
2589
2753
  if (current.status !== "submitted" && current.status !== "streaming" && current.status !== "reconnecting") {
2590
2754
  return;
@@ -2592,8 +2756,8 @@ function useChatTranscript(options) {
2592
2756
  setStopRequested(true);
2593
2757
  void current.onStop?.();
2594
2758
  }, []);
2595
- const loadEarlier = (0, import_react7.useCallback)(() => setVisibleCount((count) => count + (latest.current.loadEarlierStep ?? DEFAULT_LOAD_EARLIER_STEP)), []);
2596
- const showAll = (0, import_react7.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), []);
2597
2761
  const scroll = useStickToBottom({
2598
2762
  contentKey: contentSignature(messages),
2599
2763
  ...stickToBottomThreshold !== void 0 ? {
@@ -2629,7 +2793,7 @@ function useChatTranscript(options) {
2629
2793
  __name(useChatTranscript, "useChatTranscript");
2630
2794
  function useTranscriptItem(options) {
2631
2795
  const { message, isStreaming = false } = options;
2632
- const messagesRef = (0, import_react7.useRef)([
2796
+ const messagesRef = (0, import_react11.useRef)([
2633
2797
  message
2634
2798
  ]);
2635
2799
  if (messagesRef.current[0] !== message) {
@@ -2647,13 +2811,13 @@ function useTranscriptItem(options) {
2647
2811
  }
2648
2812
  __name(useTranscriptItem, "useTranscriptItem");
2649
2813
  function useTranscriptItems({ messages, visibleStart, streamingMessageId, options }) {
2650
- const [drafts, setDrafts] = (0, import_react7.useState)(() => /* @__PURE__ */ new Map());
2651
- const [copied, setCopied] = (0, import_react7.useState)(() => /* @__PURE__ */ new Set());
2652
- const [openReasoning, setOpenReasoning] = (0, import_react7.useState)(() => /* @__PURE__ */ new Map());
2653
- const [picks, setPicks] = (0, import_react7.useState)(() => /* @__PURE__ */ new Map());
2654
- const [settling, setSettling] = (0, import_react7.useState)(() => /* @__PURE__ */ new Map());
2655
- const [settleErrors, setSettleErrors] = (0, import_react7.useState)(() => /* @__PURE__ */ new Map());
2656
- const latest = (0, import_react7.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)({
2657
2821
  options,
2658
2822
  drafts,
2659
2823
  picks,
@@ -2665,23 +2829,23 @@ function useTranscriptItems({ messages, visibleStart, streamingMessageId, option
2665
2829
  picks,
2666
2830
  messages
2667
2831
  };
2668
- const copyTimers = (0, import_react7.useRef)(/* @__PURE__ */ new Map());
2669
- (0, import_react7.useEffect)(() => () => {
2832
+ const copyTimers = (0, import_react11.useRef)(/* @__PURE__ */ new Map());
2833
+ (0, import_react11.useEffect)(() => () => {
2670
2834
  for (const timer of copyTimers.current.values()) {
2671
2835
  clearTimeout(timer);
2672
2836
  }
2673
2837
  copyTimers.current.clear();
2674
2838
  }, []);
2675
- const callbackCache = (0, import_react7.useRef)(/* @__PURE__ */ new Map());
2676
- const reasoningToggleCache = (0, import_react7.useRef)(/* @__PURE__ */ new Map());
2677
- const toggleReasoning = (0, import_react7.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) => {
2678
2842
  setOpenReasoning((current) => {
2679
2843
  const next = new Map(current);
2680
2844
  next.set(key, open ?? !(current.get(key) ?? false));
2681
2845
  return next;
2682
2846
  });
2683
2847
  }, []);
2684
- const stableToggle = (0, import_react7.useCallback)((key) => {
2848
+ const stableToggle = (0, import_react11.useCallback)((key) => {
2685
2849
  let cached = reasoningToggleCache.current.get(key);
2686
2850
  if (!cached) {
2687
2851
  cached = /* @__PURE__ */ __name((open) => toggleReasoning(key, open), "cached");
@@ -2691,10 +2855,10 @@ function useTranscriptItems({ messages, visibleStart, streamingMessageId, option
2691
2855
  }, [
2692
2856
  toggleReasoning
2693
2857
  ]);
2694
- const pick = (0, import_react7.useCallback)((toolCallId, questionId, values) => {
2858
+ const pick = (0, import_react11.useCallback)((toolCallId, questionId, values) => {
2695
2859
  setPicks((current) => new Map(current).set(pickKey(toolCallId, questionId), values));
2696
2860
  }, []);
2697
- const settle = (0, import_react7.useCallback)((toolCallId, action, send) => {
2861
+ const settle = (0, import_react11.useCallback)((toolCallId, action, send) => {
2698
2862
  setSettleErrors((current) => {
2699
2863
  if (!current.has(toolCallId)) {
2700
2864
  return current;
@@ -2718,7 +2882,7 @@ function useTranscriptItems({ messages, visibleStart, streamingMessageId, option
2718
2882
  failed(error);
2719
2883
  }
2720
2884
  }, []);
2721
- const answer = (0, import_react7.useCallback)((toolCallId) => {
2885
+ const answer = (0, import_react11.useCallback)((toolCallId) => {
2722
2886
  const current = latest.current;
2723
2887
  const onAnswer = current.options.onAnswer;
2724
2888
  if (!onAnswer) {
@@ -2728,7 +2892,7 @@ function useTranscriptItems({ messages, visibleStart, streamingMessageId, option
2728
2892
  }, [
2729
2893
  settle
2730
2894
  ]);
2731
- const skip = (0, import_react7.useCallback)((toolCallId) => {
2895
+ const skip = (0, import_react11.useCallback)((toolCallId) => {
2732
2896
  const onSkip = latest.current.options.onSkip;
2733
2897
  if (onSkip) {
2734
2898
  settle(toolCallId, "skip", () => onSkip(toolCallId));
@@ -2736,7 +2900,7 @@ function useTranscriptItems({ messages, visibleStart, streamingMessageId, option
2736
2900
  }, [
2737
2901
  settle
2738
2902
  ]);
2739
- const approve = (0, import_react7.useCallback)((toolCallId, options2) => {
2903
+ const approve = (0, import_react11.useCallback)((toolCallId, options2) => {
2740
2904
  const onApprove = latest.current.options.onApprove;
2741
2905
  if (onApprove) {
2742
2906
  settle(toolCallId, "approve", () => options2 === void 0 ? onApprove(toolCallId) : onApprove(toolCallId, options2));
@@ -2744,7 +2908,7 @@ function useTranscriptItems({ messages, visibleStart, streamingMessageId, option
2744
2908
  }, [
2745
2909
  settle
2746
2910
  ]);
2747
- const reject = (0, import_react7.useCallback)((toolCallId) => {
2911
+ const reject = (0, import_react11.useCallback)((toolCallId) => {
2748
2912
  const onReject = latest.current.options.onReject;
2749
2913
  if (onReject) {
2750
2914
  settle(toolCallId, "reject", () => onReject(toolCallId));
@@ -2752,7 +2916,7 @@ function useTranscriptItems({ messages, visibleStart, streamingMessageId, option
2752
2916
  }, [
2753
2917
  settle
2754
2918
  ]);
2755
- const callbacksFor = (0, import_react7.useCallback)((id) => {
2919
+ const callbacksFor = (0, import_react11.useCallback)((id) => {
2756
2920
  const cached = callbackCache.current.get(id);
2757
2921
  if (cached) {
2758
2922
  return cached;
@@ -2994,7 +3158,7 @@ function MessageItem({ message, isStreaming = false, editable, onEditSubmit, reg
2994
3158
  getCreatedAt: /* @__PURE__ */ __name(() => createdAt, "getCreatedAt")
2995
3159
  } : {}
2996
3160
  });
2997
- return /* @__PURE__ */ import_react8.default.createElement(MessageItemView, {
3161
+ return /* @__PURE__ */ import_react12.default.createElement(MessageItemView, {
2998
3162
  item,
2999
3163
  ...slots
3000
3164
  });
@@ -3002,51 +3166,51 @@ function MessageItem({ message, isStreaming = false, editable, onEditSubmit, reg
3002
3166
  __name(MessageItem, "MessageItem");
3003
3167
  function MessageItemView({ item, ...slots }) {
3004
3168
  const { classNames } = slots;
3005
- const actionRow = /* @__PURE__ */ import_react8.default.createElement("div", {
3169
+ const actionRow = /* @__PURE__ */ import_react12.default.createElement("div", {
3006
3170
  className: classNames?.actions,
3007
3171
  "data-actions-for": item.role
3008
- }, item.copy.available ? /* @__PURE__ */ import_react8.default.createElement("button", {
3172
+ }, item.copy.available ? /* @__PURE__ */ import_react12.default.createElement("button", {
3009
3173
  type: "button",
3010
3174
  onClick: item.copy.copy,
3011
3175
  className: classNames?.actionButton,
3012
3176
  title: item.copy.copied ? "Copied!" : "Copy message text"
3013
- }, item.copy.copied ? "Copied" : "Copy") : null, item.fork.available ? /* @__PURE__ */ import_react8.default.createElement("button", {
3177
+ }, item.copy.copied ? "Copied" : "Copy") : null, item.fork.available ? /* @__PURE__ */ import_react12.default.createElement("button", {
3014
3178
  type: "button",
3015
3179
  onClick: item.fork.run,
3016
3180
  className: classNames?.actionButton,
3017
3181
  title: "Fork thread from this message"
3018
- }, "Fork") : null, item.regenerate.available ? /* @__PURE__ */ import_react8.default.createElement("button", {
3182
+ }, "Fork") : null, item.regenerate.available ? /* @__PURE__ */ import_react12.default.createElement("button", {
3019
3183
  type: "button",
3020
3184
  onClick: item.regenerate.run,
3021
3185
  className: classNames?.actionButton,
3022
3186
  title: "Regenerate response"
3023
- }, "Regenerate") : null, slots.meta, !item.isUser && item.usage ? /* @__PURE__ */ import_react8.default.createElement("span", {
3187
+ }, "Regenerate") : null, slots.meta, !item.isUser && item.usage ? /* @__PURE__ */ import_react12.default.createElement("span", {
3024
3188
  className: classNames?.usage,
3025
3189
  title: `Input ${item.usage.inputTokens.toLocaleString()} \xB7 Output ${item.usage.outputTokens.toLocaleString()} tokens`
3026
- }, item.usage.costLabel, " \xB7 ", item.usage.tokensLabel) : null, item.timestamp ? /* @__PURE__ */ import_react8.default.createElement("span", {
3190
+ }, item.usage.costLabel, " \xB7 ", item.usage.tokensLabel) : null, item.timestamp ? /* @__PURE__ */ import_react12.default.createElement("span", {
3027
3191
  className: classNames?.timestamp,
3028
3192
  title: item.timestamp.absolute
3029
3193
  }, item.timestamp.relative) : null);
3030
3194
  if (item.edit.available) {
3031
- return /* @__PURE__ */ import_react8.default.createElement(EditableUserBubble, {
3195
+ return /* @__PURE__ */ import_react12.default.createElement(EditableUserBubble, {
3032
3196
  item,
3033
3197
  slots,
3034
3198
  actions: actionRow
3035
3199
  });
3036
3200
  }
3037
3201
  const className = joinClasses(classNames?.root, classNames?.byRole?.[item.role]);
3038
- return /* @__PURE__ */ import_react8.default.createElement("div", {
3202
+ return /* @__PURE__ */ import_react12.default.createElement("div", {
3039
3203
  className,
3040
3204
  "data-role": item.role,
3041
3205
  "data-streaming": item.isStreaming ? "true" : void 0
3042
- }, /* @__PURE__ */ import_react8.default.createElement("div", null, renderBlocks(item, slots)), actionRow);
3206
+ }, /* @__PURE__ */ import_react12.default.createElement("div", null, renderBlocks(item, slots)), actionRow);
3043
3207
  }
3044
3208
  __name(MessageItemView, "MessageItemView");
3045
3209
  function renderBlocks(item, slots) {
3046
3210
  const nodes = [];
3047
3211
  for (const block of item.blocks) {
3048
3212
  if (block.kind === "text") {
3049
- nodes.push(/* @__PURE__ */ import_react8.default.createElement("div", {
3213
+ nodes.push(/* @__PURE__ */ import_react12.default.createElement("div", {
3050
3214
  key: block.key,
3051
3215
  className: slots.classNames?.text
3052
3216
  }, slots.renderText ? slots.renderText(block.text, {
@@ -3067,7 +3231,7 @@ function renderBlocks(item, slots) {
3067
3231
  continue;
3068
3232
  }
3069
3233
  if (block.kind === "ui" && slots.renderUi) {
3070
- nodes.push(/* @__PURE__ */ import_react8.default.createElement("div", {
3234
+ nodes.push(/* @__PURE__ */ import_react12.default.createElement("div", {
3071
3235
  key: block.key,
3072
3236
  "data-slot": "ui",
3073
3237
  "data-component": block.component
@@ -3078,18 +3242,18 @@ function renderBlocks(item, slots) {
3078
3242
  }
3079
3243
  __name(renderBlocks, "renderBlocks");
3080
3244
  function renderFilesBlock(block, slots) {
3081
- return /* @__PURE__ */ import_react8.default.createElement("div", {
3245
+ return /* @__PURE__ */ import_react12.default.createElement("div", {
3082
3246
  key: block.key,
3083
3247
  className: slots.classNames?.files,
3084
3248
  "data-files": "true"
3085
- }, slots.renderFiles ? slots.renderFiles(block.files) : block.files.map((file) => /* @__PURE__ */ import_react8.default.createElement("a", {
3249
+ }, slots.renderFiles ? slots.renderFiles(block.files) : block.files.map((file) => /* @__PURE__ */ import_react12.default.createElement("a", {
3086
3250
  key: file.url,
3087
3251
  href: file.url,
3088
3252
  target: "_blank",
3089
3253
  rel: "noreferrer",
3090
3254
  className: slots.classNames?.file,
3091
3255
  title: file.filename ?? file.mediaType
3092
- }, file.isImage ? /* @__PURE__ */ import_react8.default.createElement("img", {
3256
+ }, file.isImage ? /* @__PURE__ */ import_react12.default.createElement("img", {
3093
3257
  src: file.url,
3094
3258
  alt: file.filename ?? "image",
3095
3259
  className: slots.classNames?.fileImage
@@ -3097,17 +3261,17 @@ function renderFilesBlock(block, slots) {
3097
3261
  }
3098
3262
  __name(renderFilesBlock, "renderFilesBlock");
3099
3263
  function renderReasoningBlock(block, slots) {
3100
- return /* @__PURE__ */ import_react8.default.createElement("div", {
3264
+ return /* @__PURE__ */ import_react12.default.createElement("div", {
3101
3265
  key: block.key,
3102
3266
  className: slots.classNames?.reasoning,
3103
3267
  "data-reasoning": "true",
3104
3268
  "data-streaming": block.isStreaming ? "true" : void 0
3105
- }, /* @__PURE__ */ import_react8.default.createElement("button", {
3269
+ }, /* @__PURE__ */ import_react12.default.createElement("button", {
3106
3270
  type: "button",
3107
3271
  className: slots.classNames?.reasoningToggle,
3108
3272
  onClick: /* @__PURE__ */ __name(() => block.toggle(), "onClick"),
3109
3273
  "aria-expanded": block.isOpen
3110
- }, slots.reasoningLabel ?? "Reasoning"), block.isOpen ? /* @__PURE__ */ import_react8.default.createElement("div", {
3274
+ }, slots.reasoningLabel ?? "Reasoning"), block.isOpen ? /* @__PURE__ */ import_react12.default.createElement("div", {
3111
3275
  className: slots.classNames?.reasoningText
3112
3276
  }, slots.renderReasoning ? slots.renderReasoning(block.text, {
3113
3277
  isStreaming: block.isStreaming,
@@ -3118,7 +3282,7 @@ __name(renderReasoningBlock, "renderReasoningBlock");
3118
3282
  function renderToolBlock(item, block, slots) {
3119
3283
  if (slots.renderToolGroup) {
3120
3284
  return [
3121
- /* @__PURE__ */ import_react8.default.createElement(import_react8.default.Fragment, {
3285
+ /* @__PURE__ */ import_react12.default.createElement(import_react12.default.Fragment, {
3122
3286
  key: block.key
3123
3287
  }, slots.renderToolGroup(block.parts, block.key))
3124
3288
  ];
@@ -3129,7 +3293,7 @@ function renderToolBlock(item, block, slots) {
3129
3293
  const renderToolPart = slots.renderToolPart;
3130
3294
  return block.parts.map((part) => {
3131
3295
  const partKey = `${item.id}-${part.toolCallId}`;
3132
- return /* @__PURE__ */ import_react8.default.createElement(import_react8.default.Fragment, {
3296
+ return /* @__PURE__ */ import_react12.default.createElement(import_react12.default.Fragment, {
3133
3297
  key: partKey
3134
3298
  }, renderToolPart(part, partKey));
3135
3299
  });
@@ -3139,14 +3303,14 @@ function EditableUserBubble({ item, slots, actions }) {
3139
3303
  const { classNames } = slots;
3140
3304
  const { edit } = item;
3141
3305
  if (!edit.isEditing) {
3142
- return /* @__PURE__ */ import_react8.default.createElement("div", {
3306
+ return /* @__PURE__ */ import_react12.default.createElement("div", {
3143
3307
  className: joinClasses(classNames?.root, classNames?.byRole?.user),
3144
3308
  "data-role": "user"
3145
- }, /* @__PURE__ */ import_react8.default.createElement("div", {
3309
+ }, /* @__PURE__ */ import_react12.default.createElement("div", {
3146
3310
  className: classNames?.text
3147
3311
  }, slots.renderText ? slots.renderText(item.text, {
3148
3312
  isStreaming: false
3149
- }) : item.text), /* @__PURE__ */ import_react8.default.createElement("button", {
3313
+ }) : item.text), /* @__PURE__ */ import_react12.default.createElement("button", {
3150
3314
  type: "button",
3151
3315
  onClick: edit.start,
3152
3316
  className: classNames?.actionButton,
@@ -3154,18 +3318,18 @@ function EditableUserBubble({ item, slots, actions }) {
3154
3318
  }, "Edit"), actions);
3155
3319
  }
3156
3320
  const textareaProps = edit.getTextareaProps();
3157
- return /* @__PURE__ */ import_react8.default.createElement("div", {
3321
+ return /* @__PURE__ */ import_react12.default.createElement("div", {
3158
3322
  "data-editing": "true"
3159
- }, /* @__PURE__ */ import_react8.default.createElement("textarea", {
3323
+ }, /* @__PURE__ */ import_react12.default.createElement("textarea", {
3160
3324
  ...textareaProps,
3161
3325
  rows: Math.min(8, edit.draft.split("\n").length + 1),
3162
3326
  className: classNames?.editTextarea
3163
- }), /* @__PURE__ */ import_react8.default.createElement("div", {
3327
+ }), /* @__PURE__ */ import_react12.default.createElement("div", {
3164
3328
  className: classNames?.editActions
3165
- }, /* @__PURE__ */ import_react8.default.createElement("button", {
3329
+ }, /* @__PURE__ */ import_react12.default.createElement("button", {
3166
3330
  type: "button",
3167
3331
  onClick: edit.cancel
3168
- }, "Cancel"), /* @__PURE__ */ import_react8.default.createElement("button", {
3332
+ }, "Cancel"), /* @__PURE__ */ import_react12.default.createElement("button", {
3169
3333
  type: "button",
3170
3334
  onClick: edit.save,
3171
3335
  disabled: !edit.canSave
@@ -3409,35 +3573,35 @@ function toItem(entry) {
3409
3573
  __name(toItem, "toItem");
3410
3574
 
3411
3575
  // src/composer/use-composer-autocomplete.ts
3412
- var import_react9 = require("react");
3576
+ var import_react13 = require("react");
3413
3577
  function useComposerAutocomplete(options) {
3414
3578
  const { value, sources, acceptOnTab = true } = options;
3415
- const latest = (0, import_react9.useRef)(options);
3579
+ const latest = (0, import_react13.useRef)(options);
3416
3580
  latest.current = options;
3417
- const inputRef = (0, import_react9.useRef)(null);
3418
- const [caret, setCaret] = (0, import_react9.useState)(value.length);
3419
- const [items, setItems] = (0, import_react9.useState)([]);
3420
- const [isLoading, setLoading] = (0, import_react9.useState)(false);
3421
- const [error, setError] = (0, import_react9.useState)(null);
3422
- const [activeIndex, setActiveIndex] = (0, import_react9.useState)(0);
3423
- const [dismissedIndex, setDismissedIndex] = (0, import_react9.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);
3424
3588
  const safeCaret = Math.min(caret, value.length);
3425
- const match = (0, import_react9.useMemo)(() => findActiveTrigger(value, safeCaret, sources), [
3589
+ const match = (0, import_react13.useMemo)(() => findActiveTrigger(value, safeCaret, sources), [
3426
3590
  value,
3427
3591
  safeCaret,
3428
3592
  sources
3429
3593
  ]);
3430
3594
  const isActive = match !== null && dismissedIndex !== match.index;
3431
- const matchRef = (0, import_react9.useRef)(match);
3595
+ const matchRef = (0, import_react13.useRef)(match);
3432
3596
  matchRef.current = match;
3433
- const caretRef = (0, import_react9.useRef)(safeCaret);
3597
+ const caretRef = (0, import_react13.useRef)(safeCaret);
3434
3598
  caretRef.current = safeCaret;
3435
- const itemsRef = (0, import_react9.useRef)(items);
3599
+ const itemsRef = (0, import_react13.useRef)(items);
3436
3600
  itemsRef.current = items;
3437
- const activeIndexRef = (0, import_react9.useRef)(activeIndex);
3601
+ const activeIndexRef = (0, import_react13.useRef)(activeIndex);
3438
3602
  activeIndexRef.current = activeIndex;
3439
3603
  const requestKey = isActive && match ? `${match.source.id}\0${match.query}` : null;
3440
- (0, import_react9.useEffect)(() => {
3604
+ (0, import_react13.useEffect)(() => {
3441
3605
  const current = matchRef.current;
3442
3606
  if (requestKey === null || current === null) {
3443
3607
  setItems([]);
@@ -3485,25 +3649,25 @@ function useComposerAutocomplete(options) {
3485
3649
  ]);
3486
3650
  const isOpen = isActive;
3487
3651
  const activeItem = isOpen ? items[activeIndex] ?? null : null;
3488
- const reactId = (0, import_react9.useId)();
3652
+ const reactId = (0, import_react13.useId)();
3489
3653
  const listboxId = options.id ?? `agent-autocomplete-${reactId}`;
3490
- const optionId = (0, import_react9.useCallback)((index) => `${listboxId}-option-${index}`, [
3654
+ const optionId = (0, import_react13.useCallback)((index) => `${listboxId}-option-${index}`, [
3491
3655
  listboxId
3492
3656
  ]);
3493
- const highlight = (0, import_react9.useCallback)((index) => {
3657
+ const highlight = (0, import_react13.useCallback)((index) => {
3494
3658
  const total = itemsRef.current.length;
3495
3659
  if (total === 0) return;
3496
3660
  setActiveIndex((index % total + total) % total);
3497
3661
  }, []);
3498
- const moveHighlight = (0, import_react9.useCallback)((delta) => highlight(activeIndexRef.current + delta), [
3662
+ const moveHighlight = (0, import_react13.useCallback)((delta) => highlight(activeIndexRef.current + delta), [
3499
3663
  highlight
3500
3664
  ]);
3501
- const dismiss = (0, import_react9.useCallback)(() => {
3665
+ const dismiss = (0, import_react13.useCallback)(() => {
3502
3666
  const current = matchRef.current;
3503
3667
  if (current) setDismissedIndex(current.index);
3504
3668
  }, []);
3505
- const pendingCaret = (0, import_react9.useRef)(null);
3506
- const accept = (0, import_react9.useCallback)((item) => {
3669
+ const pendingCaret = (0, import_react13.useRef)(null);
3670
+ const accept = (0, import_react13.useCallback)((item) => {
3507
3671
  const current = matchRef.current;
3508
3672
  if (!current) return;
3509
3673
  const chosen = item ?? itemsRef.current[activeIndexRef.current];
@@ -3514,16 +3678,16 @@ function useComposerAutocomplete(options) {
3514
3678
  setDismissedIndex(null);
3515
3679
  pendingCaret.current = edit.caret;
3516
3680
  }, []);
3517
- (0, import_react9.useLayoutEffect)(() => {
3681
+ (0, import_react13.useLayoutEffect)(() => {
3518
3682
  const position = pendingCaret.current;
3519
3683
  if (position === null) return;
3520
3684
  pendingCaret.current = null;
3521
3685
  inputRef.current?.setSelectionRange(position, position);
3522
3686
  });
3523
- const readCaret = (0, import_react9.useCallback)((element) => {
3687
+ const readCaret = (0, import_react13.useCallback)((element) => {
3524
3688
  setCaret(element.selectionStart ?? element.value.length);
3525
3689
  }, []);
3526
- const onKeyDown = (0, import_react9.useCallback)((event) => {
3690
+ const onKeyDown = (0, import_react13.useCallback)((event) => {
3527
3691
  if (!isOpen) return;
3528
3692
  const hasItems = itemsRef.current.length > 0;
3529
3693
  switch (event.key) {
@@ -3561,23 +3725,23 @@ function useComposerAutocomplete(options) {
3561
3725
  dismiss,
3562
3726
  moveHighlight
3563
3727
  ]);
3564
- const onChange = (0, import_react9.useCallback)((event) => {
3728
+ const onChange = (0, import_react13.useCallback)((event) => {
3565
3729
  readCaret(event.target);
3566
3730
  const next = findActiveTrigger(event.target.value, event.target.selectionStart ?? event.target.value.length, latest.current.sources);
3567
3731
  setDismissedIndex((current) => current !== null && next?.index === current ? current : null);
3568
3732
  }, [
3569
3733
  readCaret
3570
3734
  ]);
3571
- const onSelect = (0, import_react9.useCallback)((event) => readCaret(event.currentTarget), [
3735
+ const onSelect = (0, import_react13.useCallback)((event) => readCaret(event.currentTarget), [
3572
3736
  readCaret
3573
3737
  ]);
3574
- const onClick = (0, import_react9.useCallback)((event) => readCaret(event.currentTarget), [
3738
+ const onClick = (0, import_react13.useCallback)((event) => readCaret(event.currentTarget), [
3575
3739
  readCaret
3576
3740
  ]);
3577
- const setInput = (0, import_react9.useCallback)((element) => {
3741
+ const setInput = (0, import_react13.useCallback)((element) => {
3578
3742
  inputRef.current = element;
3579
3743
  }, []);
3580
- const getInputProps = (0, import_react9.useCallback)(() => ({
3744
+ const getInputProps = (0, import_react13.useCallback)(() => ({
3581
3745
  ref: setInput,
3582
3746
  onChange,
3583
3747
  onKeyDown,
@@ -3605,7 +3769,7 @@ function useComposerAutocomplete(options) {
3605
3769
  activeIndex,
3606
3770
  optionId
3607
3771
  ]);
3608
- const getListboxProps = (0, import_react9.useCallback)(() => ({
3772
+ const getListboxProps = (0, import_react13.useCallback)(() => ({
3609
3773
  id: listboxId,
3610
3774
  role: "listbox",
3611
3775
  "aria-label": match?.source.label ?? match?.source.id ?? "Suggestions"
@@ -3613,7 +3777,7 @@ function useComposerAutocomplete(options) {
3613
3777
  listboxId,
3614
3778
  match
3615
3779
  ]);
3616
- const getOptionProps = (0, import_react9.useCallback)((index) => ({
3780
+ const getOptionProps = (0, import_react13.useCallback)((index) => ({
3617
3781
  id: optionId(index),
3618
3782
  role: "option",
3619
3783
  "aria-selected": index === activeIndex
@@ -3647,7 +3811,7 @@ function isPromise(value) {
3647
3811
  __name(isPromise, "isPromise");
3648
3812
 
3649
3813
  // src/presentation/use-tool-catalog.ts
3650
- var import_react10 = require("react");
3814
+ var import_react14 = require("react");
3651
3815
  var shared = /* @__PURE__ */ new WeakMap();
3652
3816
  function load(client, agent) {
3653
3817
  let byAgent = shared.get(client);
@@ -3671,11 +3835,11 @@ function load(client, agent) {
3671
3835
  __name(load, "load");
3672
3836
  function useToolCatalog(options) {
3673
3837
  const { client, agent, enabled = true } = options;
3674
- const [entries, setEntries] = (0, import_react10.useState)([]);
3675
- const [isLoading, setLoading] = (0, import_react10.useState)(enabled);
3676
- const [error, setError] = (0, import_react10.useState)(null);
3677
- const [generation, setGeneration] = (0, import_react10.useState)(0);
3678
- (0, import_react10.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)(() => {
3679
3843
  if (!enabled) {
3680
3844
  setLoading(false);
3681
3845
  return;
@@ -3701,14 +3865,14 @@ function useToolCatalog(options) {
3701
3865
  enabled,
3702
3866
  generation
3703
3867
  ]);
3704
- const refresh = (0, import_react10.useCallback)(() => {
3868
+ const refresh = (0, import_react14.useCallback)(() => {
3705
3869
  shared.get(client)?.delete(agent ?? "");
3706
3870
  setGeneration((current) => current + 1);
3707
3871
  }, [
3708
3872
  client,
3709
3873
  agent
3710
3874
  ]);
3711
- const catalog = (0, import_react10.useMemo)(() => toolCatalogFrom(entries), [
3875
+ const catalog = (0, import_react14.useMemo)(() => toolCatalogFrom(entries), [
3712
3876
  entries
3713
3877
  ]);
3714
3878
  return {
@@ -3722,7 +3886,7 @@ function useToolCatalog(options) {
3722
3886
  __name(useToolCatalog, "useToolCatalog");
3723
3887
 
3724
3888
  // src/approvals/countdown.ts
3725
- var import_react11 = require("react");
3889
+ var import_react15 = require("react");
3726
3890
  function approvalCountdown(expiresAt, now = Date.now()) {
3727
3891
  const deadline = expiresAt == null ? Number.NaN : Date.parse(expiresAt);
3728
3892
  if (!Number.isFinite(deadline)) {
@@ -3740,10 +3904,10 @@ function approvalCountdown(expiresAt, now = Date.now()) {
3740
3904
  __name(approvalCountdown, "approvalCountdown");
3741
3905
  function useApprovalCountdown(expiresAt, options = {}) {
3742
3906
  const { intervalMs = 1e3 } = options;
3743
- const nowRef = (0, import_react11.useRef)(options.now ?? Date.now);
3907
+ const nowRef = (0, import_react15.useRef)(options.now ?? Date.now);
3744
3908
  nowRef.current = options.now ?? Date.now;
3745
- const [state, setState] = (0, import_react11.useState)(() => approvalCountdown(expiresAt, nowRef.current()));
3746
- (0, import_react11.useEffect)(() => {
3909
+ const [state, setState] = (0, import_react15.useState)(() => approvalCountdown(expiresAt, nowRef.current()));
3910
+ (0, import_react15.useEffect)(() => {
3747
3911
  const read = /* @__PURE__ */ __name(() => approvalCountdown(expiresAt, nowRef.current()), "read");
3748
3912
  const first = read();
3749
3913
  setState(first);
@@ -3984,21 +4148,21 @@ function sumUsage(rows) {
3984
4148
  __name(sumUsage, "sumUsage");
3985
4149
 
3986
4150
  // src/use-agent-chat.ts
3987
- var import_react12 = require("@ai-sdk/react");
3988
- var import_react13 = require("react");
4151
+ var import_react16 = require("@ai-sdk/react");
4152
+ var import_react17 = require("react");
3989
4153
  function useAgentChat(options) {
3990
- const latest = (0, import_react13.useRef)(options);
4154
+ const latest = (0, import_react17.useRef)(options);
3991
4155
  latest.current = options;
3992
- const [runId, setRunId] = (0, import_react13.useState)(options.resumeRunId);
3993
- const runIdRef = (0, import_react13.useRef)(runId);
4156
+ const [runId, setRunId] = (0, import_react17.useState)(options.resumeRunId);
4157
+ const runIdRef = (0, import_react17.useRef)(runId);
3994
4158
  runIdRef.current = runId;
3995
- const settlingRunIdRef = (0, import_react13.useRef)(void 0);
3996
- const autoResumeRunIdRef = (0, import_react13.useRef)(void 0);
3997
- const [autoResume, setAutoResume] = (0, import_react13.useState)(false);
3998
- const [activeRunId, setActiveRunId] = (0, import_react13.useState)(null);
3999
- const regenerateNext = (0, import_react13.useRef)(false);
4000
- const createdThreadId = (0, import_react13.useRef)(void 0);
4001
- const client = (0, import_react13.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)(() => {
4002
4166
  if (options.backend) return options.backend;
4003
4167
  if (options.client) return options.client;
4004
4168
  return new AgentClient({
@@ -4014,11 +4178,11 @@ function useAgentChat(options) {
4014
4178
  getHeaders: /* @__PURE__ */ __name(async () => mergeHeaders(latest.current), "getHeaders")
4015
4179
  });
4016
4180
  }, []);
4017
- const [connection, setConnection] = (0, import_react13.useState)({
4181
+ const [connection, setConnection] = (0, import_react17.useState)({
4018
4182
  status: "live"
4019
4183
  });
4020
- const resyncAfterSettle = (0, import_react13.useRef)(false);
4021
- (0, import_react13.useEffect)(() => {
4184
+ const resyncAfterSettle = (0, import_react17.useRef)(false);
4185
+ (0, import_react17.useEffect)(() => {
4022
4186
  if (!options.resume || options.threadId === void 0) return;
4023
4187
  let cancelled = false;
4024
4188
  const threadId = options.threadId;
@@ -4038,7 +4202,7 @@ function useAgentChat(options) {
4038
4202
  options.resume,
4039
4203
  options.threadId
4040
4204
  ]);
4041
- const transport = (0, import_react13.useMemo)(() => {
4205
+ const transport = (0, import_react17.useMemo)(() => {
4042
4206
  function onMeta(meta) {
4043
4207
  settlingRunIdRef.current = meta.runId;
4044
4208
  setRunId(meta.runId);
@@ -4075,6 +4239,9 @@ function useAgentChat(options) {
4075
4239
  ...threadId !== void 0 ? {
4076
4240
  threadId
4077
4241
  } : {},
4242
+ ...current.model !== void 0 ? {
4243
+ model: current.model
4244
+ } : {},
4078
4245
  ...pageContext ? {
4079
4246
  pageContext
4080
4247
  } : {},
@@ -4090,8 +4257,8 @@ function useAgentChat(options) {
4090
4257
  }, "onAttemptStart")
4091
4258
  });
4092
4259
  }, []);
4093
- const backgroundRef = (0, import_react13.useRef)(() => Promise.resolve());
4094
- const chat = (0, import_react12.useChat)({
4260
+ const backgroundRef = (0, import_react17.useRef)(() => Promise.resolve());
4261
+ const chat = (0, import_react16.useChat)({
4095
4262
  transport,
4096
4263
  resume: options.resumeRunId !== void 0 || autoResume,
4097
4264
  ...options.threadId !== void 0 ? {
@@ -4139,7 +4306,7 @@ function useAgentChat(options) {
4139
4306
  }
4140
4307
  }, "onFinish")
4141
4308
  });
4142
- const chatRef = (0, import_react13.useRef)(chat);
4309
+ const chatRef = (0, import_react17.useRef)(chat);
4143
4310
  chatRef.current = chat;
4144
4311
  async function resyncFromThread() {
4145
4312
  const threadId = latest.current.threadId ?? createdThreadId.current;
@@ -4151,11 +4318,13 @@ function useAgentChat(options) {
4151
4318
  }
4152
4319
  }
4153
4320
  __name(resyncFromThread, "resyncFromThread");
4154
- const turnInFlight = (0, import_react13.useRef)(false);
4155
- const isTurnInFlight = (0, import_react13.useCallback)(() => turnInFlight.current || transport.isAttemptLive, [
4321
+ const turnInFlight = (0, import_react17.useRef)(false);
4322
+ const isTurnInFlight = (0, import_react17.useCallback)(() => turnInFlight.current || transport.isAttemptLive, [
4156
4323
  transport
4157
4324
  ]);
4158
- const sendMessage = (0, import_react13.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);
4159
4328
  if (isTurnInFlight()) return;
4160
4329
  turnInFlight.current = true;
4161
4330
  try {
@@ -4166,15 +4335,15 @@ function useAgentChat(options) {
4166
4335
  }, [
4167
4336
  isTurnInFlight
4168
4337
  ]);
4169
- const addToolResult = (0, import_react13.useCallback)(({ tool, toolCallId, output }) => chatRef.current.addToolResult({
4338
+ const addToolResult = (0, import_react17.useCallback)(({ tool, toolCallId, output }) => chatRef.current.addToolResult({
4170
4339
  tool,
4171
4340
  toolCallId,
4172
4341
  output
4173
4342
  }), []);
4174
- const [threads, setThreads] = (0, import_react13.useState)([]);
4175
- const [quota, setQuota] = (0, import_react13.useState)(null);
4176
- const [backgroundRuns, setBackgroundRuns] = (0, import_react13.useState)([]);
4177
- const refreshBackground = (0, import_react13.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 () => {
4178
4347
  const threadId = latest.current.threadId ?? createdThreadId.current;
4179
4348
  if (threadId === void 0) {
4180
4349
  return;
@@ -4199,7 +4368,7 @@ function useAgentChat(options) {
4199
4368
  ]);
4200
4369
  backgroundRef.current = refreshBackground;
4201
4370
  const isWorking = backgroundRuns.some((run) => run.status === "running");
4202
- (0, import_react13.useEffect)(() => {
4371
+ (0, import_react17.useEffect)(() => {
4203
4372
  if (options.background !== true || options.threadId === void 0) {
4204
4373
  return;
4205
4374
  }
@@ -4209,7 +4378,7 @@ function useAgentChat(options) {
4209
4378
  options.threadId,
4210
4379
  refreshBackground
4211
4380
  ]);
4212
- (0, import_react13.useEffect)(() => {
4381
+ (0, import_react17.useEffect)(() => {
4213
4382
  const every = latest.current.backgroundPollMs ?? 5e3;
4214
4383
  if (latest.current.background !== true || !isWorking || every <= 0) {
4215
4384
  return;
@@ -4220,26 +4389,26 @@ function useAgentChat(options) {
4220
4389
  isWorking,
4221
4390
  refreshBackground
4222
4391
  ]);
4223
- const loadThreads = (0, import_react13.useCallback)(async () => {
4392
+ const loadThreads = (0, import_react17.useCallback)(async () => {
4224
4393
  const list = await client.listThreads();
4225
4394
  setThreads(list);
4226
4395
  return list;
4227
4396
  }, [
4228
4397
  client
4229
4398
  ]);
4230
- const loadThread = (0, import_react13.useCallback)((id) => client.getThread(id), [
4399
+ const loadThread = (0, import_react17.useCallback)((id) => client.getThread(id), [
4231
4400
  client
4232
4401
  ]);
4233
- const deleteThread = (0, import_react13.useCallback)(async (id) => {
4402
+ const deleteThread = (0, import_react17.useCallback)(async (id) => {
4234
4403
  await client.deleteThread(id);
4235
4404
  setThreads((current) => current.filter((thread) => thread.id !== id));
4236
4405
  }, [
4237
4406
  client
4238
4407
  ]);
4239
- const forkThread = (0, import_react13.useCallback)((threadId, messageId) => requireBackendMethod(client, "forkFromMessage")(threadId, messageId), [
4408
+ const forkThread = (0, import_react17.useCallback)((threadId, messageId) => requireBackendMethod(client, "forkFromMessage")(threadId, messageId), [
4240
4409
  client
4241
4410
  ]);
4242
- const renameThread = (0, import_react13.useCallback)(async (id, title) => {
4411
+ const renameThread = (0, import_react17.useCallback)(async (id, title) => {
4243
4412
  await client.updateThread(id, {
4244
4413
  title
4245
4414
  });
@@ -4250,24 +4419,24 @@ function useAgentChat(options) {
4250
4419
  }, [
4251
4420
  client
4252
4421
  ]);
4253
- const promoteThread = (0, import_react13.useCallback)(async (id) => {
4422
+ const promoteThread = (0, import_react17.useCallback)(async (id) => {
4254
4423
  await requireBackendMethod(client, "promoteThread")(id);
4255
4424
  await loadThreads();
4256
4425
  }, [
4257
4426
  client,
4258
4427
  loadThreads
4259
4428
  ]);
4260
- const truncateFromMessage = (0, import_react13.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), [
4261
4430
  client
4262
4431
  ]);
4263
- const loadQuota = (0, import_react13.useCallback)(async () => {
4432
+ const loadQuota = (0, import_react17.useCallback)(async () => {
4264
4433
  const today = await requireBackendMethod(client, "getQuotaToday")();
4265
4434
  setQuota(today);
4266
4435
  return today;
4267
4436
  }, [
4268
4437
  client
4269
4438
  ]);
4270
- const cancel = (0, import_react13.useCallback)(async () => {
4439
+ const cancel = (0, import_react17.useCallback)(async () => {
4271
4440
  chatRef.current.stop();
4272
4441
  const activeRunId2 = runIdRef.current;
4273
4442
  if (activeRunId2) {
@@ -4279,7 +4448,7 @@ function useAgentChat(options) {
4279
4448
  }, [
4280
4449
  client
4281
4450
  ]);
4282
- const approve = (0, import_react13.useCallback)(async ({ toolCallId, remember, via }) => {
4451
+ const approve = (0, import_react17.useCallback)(async ({ toolCallId, remember, via }) => {
4283
4452
  await requireBackendMethod(client, "approveToolCall")({
4284
4453
  toolCallId,
4285
4454
  ...remember === true ? {
@@ -4292,7 +4461,7 @@ function useAgentChat(options) {
4292
4461
  }, [
4293
4462
  client
4294
4463
  ]);
4295
- const reject = (0, import_react13.useCallback)(async ({ toolCallId, reason, via }) => {
4464
+ const reject = (0, import_react17.useCallback)(async ({ toolCallId, reason, via }) => {
4296
4465
  await requireBackendMethod(client, "rejectToolCall")({
4297
4466
  toolCallId,
4298
4467
  ...reason !== void 0 ? {
@@ -4305,7 +4474,7 @@ function useAgentChat(options) {
4305
4474
  }, [
4306
4475
  client
4307
4476
  ]);
4308
- const answer = (0, import_react13.useCallback)(async ({ toolCallId, answers }) => {
4477
+ const answer = (0, import_react17.useCallback)(async ({ toolCallId, answers }) => {
4309
4478
  await requireBackendMethod(client, "answerToolCall")({
4310
4479
  toolCallId,
4311
4480
  ...answers !== void 0 ? {
@@ -4315,14 +4484,16 @@ function useAgentChat(options) {
4315
4484
  }, [
4316
4485
  client
4317
4486
  ]);
4318
- const skip = (0, import_react13.useCallback)(async ({ toolCallId }) => {
4487
+ const skip = (0, import_react17.useCallback)(async ({ toolCallId }) => {
4319
4488
  await requireBackendMethod(client, "skipToolCall")({
4320
4489
  toolCallId
4321
4490
  });
4322
4491
  }, [
4323
4492
  client
4324
4493
  ]);
4325
- const regenerate = (0, import_react13.useCallback)(() => {
4494
+ const regenerate = (0, import_react17.useCallback)(() => {
4495
+ const blocked = latest.current.blocked;
4496
+ if (blocked != null) throw new QuotaBlockedError(blocked);
4326
4497
  if (isTurnInFlight()) return;
4327
4498
  regenerateNext.current = true;
4328
4499
  turnInFlight.current = true;
@@ -4337,7 +4508,21 @@ function useAgentChat(options) {
4337
4508
  isWorking,
4338
4509
  refresh: refreshBackground
4339
4510
  };
4340
- const getThreadId = (0, import_react13.useCallback)(() => latest.current.threadId ?? createdThreadId.current, []);
4511
+ const setThreadModel = (0, import_react17.useCallback)(async (model) => {
4512
+ const threadId = latest.current.threadId ?? createdThreadId.current;
4513
+ if (threadId === void 0) {
4514
+ throw new Error("setThreadModel: this chat has no thread yet");
4515
+ }
4516
+ await client.updateThread(threadId, {
4517
+ model
4518
+ });
4519
+ notifyThreads(client, {
4520
+ type: "changed"
4521
+ });
4522
+ }, [
4523
+ client
4524
+ ]);
4525
+ const getThreadId = (0, import_react17.useCallback)(() => latest.current.threadId ?? createdThreadId.current, []);
4341
4526
  const status = connection.status === "reconnecting" ? "reconnecting" : chat.status;
4342
4527
  return {
4343
4528
  ...chat,
@@ -4356,6 +4541,7 @@ function useAgentChat(options) {
4356
4541
  * on the first send. A getter, because the created id is learned mid-stream.
4357
4542
  */
4358
4543
  getThreadId,
4544
+ setThreadModel,
4359
4545
  /** The backend this chat talks to — pass it to `useThreads`, `useMessageFeedback`, … */
4360
4546
  backend: client,
4361
4547
  /** Same object as {@link backend}; kept for callers that read it under its old name. */
@@ -4379,6 +4565,16 @@ function useAgentChat(options) {
4379
4565
  };
4380
4566
  }
4381
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
+ };
4382
4578
  async function mergeHeaders(options) {
4383
4579
  const dynamic = await options.getHeaders?.() ?? {};
4384
4580
  return {
@@ -4398,6 +4594,7 @@ __name(mergeHeaders, "mergeHeaders");
4398
4594
  MessageItem,
4399
4595
  MessageItemView,
4400
4596
  MessageList,
4597
+ QuotaBlockedError,
4401
4598
  SPEECH_LANGUAGES,
4402
4599
  applyCompletion,
4403
4600
  approvalCountdown,
@@ -4432,11 +4629,14 @@ __name(mergeHeaders, "mergeHeaders");
4432
4629
  toolCallState,
4433
4630
  toolCatalogFrom,
4434
4631
  useAgentChat,
4632
+ useAgents,
4435
4633
  useApprovalCountdown,
4436
4634
  useChatTranscript,
4437
4635
  useComposerAutocomplete,
4438
4636
  useElapsed,
4439
4637
  useMessageFeedback,
4638
+ useModels,
4639
+ useQuota,
4440
4640
  useSpeechRecognition,
4441
4641
  useStickToBottom,
4442
4642
  useThreads,