@dudousxd/nestjs-agent-react 0.16.0 → 0.18.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/README.md +60 -6
- package/dist/index.cjs +642 -230
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +178 -2
- package/dist/index.d.ts +178 -2
- package/dist/index.js +596 -192
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -40,7 +40,9 @@ __export(src_exports, {
|
|
|
40
40
|
MessageItem: () => MessageItem,
|
|
41
41
|
MessageItemView: () => MessageItemView,
|
|
42
42
|
MessageList: () => MessageList,
|
|
43
|
+
QuotaBlockedError: () => QuotaBlockedError,
|
|
43
44
|
SPEECH_LANGUAGES: () => SPEECH_LANGUAGES,
|
|
45
|
+
acceptsFile: () => acceptsFile,
|
|
44
46
|
applyCompletion: () => applyCompletion,
|
|
45
47
|
approvalCountdown: () => approvalCountdown,
|
|
46
48
|
backgroundRunsFromThread: () => backgroundRunsFromThread,
|
|
@@ -51,7 +53,10 @@ __export(src_exports, {
|
|
|
51
53
|
describeTimestamp: () => describeTimestamp,
|
|
52
54
|
describeToolCall: () => describeToolCall,
|
|
53
55
|
describeUsage: () => describeUsage,
|
|
56
|
+
dragHasFiles: () => dragHasFiles,
|
|
54
57
|
extractMessageText: () => extractMessageText,
|
|
58
|
+
fileKind: () => fileKind,
|
|
59
|
+
filesFromClipboard: () => filesFromClipboard,
|
|
55
60
|
fillTemplate: () => fillTemplate,
|
|
56
61
|
filterAutocompleteItems: () => filterAutocompleteItems,
|
|
57
62
|
findActiveTrigger: () => findActiveTrigger,
|
|
@@ -61,6 +66,7 @@ __export(src_exports, {
|
|
|
61
66
|
inferResultView: () => inferResultView,
|
|
62
67
|
isActionCall: () => isActionCall,
|
|
63
68
|
loadStoredSpeechLang: () => loadStoredSpeechLang,
|
|
69
|
+
messageFiles: () => messageFiles,
|
|
64
70
|
notifyThreads: () => notifyThreads,
|
|
65
71
|
onThreadsEvent: () => onThreadsEvent,
|
|
66
72
|
persistSpeechLang: () => persistSpeechLang,
|
|
@@ -76,11 +82,13 @@ __export(src_exports, {
|
|
|
76
82
|
useAgentChat: () => useAgentChat,
|
|
77
83
|
useAgents: () => useAgents,
|
|
78
84
|
useApprovalCountdown: () => useApprovalCountdown,
|
|
85
|
+
useAttachments: () => useAttachments,
|
|
79
86
|
useChatTranscript: () => useChatTranscript,
|
|
80
87
|
useComposerAutocomplete: () => useComposerAutocomplete,
|
|
81
88
|
useElapsed: () => useElapsed,
|
|
82
89
|
useMessageFeedback: () => useMessageFeedback,
|
|
83
90
|
useModels: () => useModels,
|
|
91
|
+
useQuota: () => useQuota,
|
|
84
92
|
useSpeechRecognition: () => useSpeechRecognition,
|
|
85
93
|
useStickToBottom: () => useStickToBottom,
|
|
86
94
|
useThreads: () => useThreads,
|
|
@@ -215,6 +223,9 @@ var AgentClient = class {
|
|
|
215
223
|
* what a caller then rides on `sendMessage({ text }, { body: { attachments: [...] } })`.
|
|
216
224
|
*/
|
|
217
225
|
async uploadAttachment(file, options = {}) {
|
|
226
|
+
if (options.onProgress !== void 0 && this.options.fetch === void 0 && typeof XMLHttpRequest !== "undefined") {
|
|
227
|
+
return this.uploadWithProgress(file, options);
|
|
228
|
+
}
|
|
218
229
|
const formData = new FormData();
|
|
219
230
|
formData.append("file", file);
|
|
220
231
|
const response = await this.fetchImpl()(`${this.baseUrl()}/agent/attachments`, {
|
|
@@ -229,7 +240,47 @@ var AgentClient = class {
|
|
|
229
240
|
signal: options.signal
|
|
230
241
|
} : {}
|
|
231
242
|
});
|
|
232
|
-
|
|
243
|
+
const attachment = await this.handleResponse(response, "POST", "/agent/attachments");
|
|
244
|
+
options.onProgress?.(1);
|
|
245
|
+
return attachment;
|
|
246
|
+
}
|
|
247
|
+
async uploadWithProgress(file, { signal, onProgress }) {
|
|
248
|
+
const headers = {
|
|
249
|
+
accept: "application/json",
|
|
250
|
+
...await this.resolveHeaders()
|
|
251
|
+
};
|
|
252
|
+
const url = `${this.baseUrl()}/agent/attachments`;
|
|
253
|
+
return new Promise((resolve, reject) => {
|
|
254
|
+
const xhr = new XMLHttpRequest();
|
|
255
|
+
xhr.open("POST", url);
|
|
256
|
+
for (const [name, value] of Object.entries(headers)) xhr.setRequestHeader(name, value);
|
|
257
|
+
xhr.withCredentials = this.options.credentials === "include";
|
|
258
|
+
xhr.upload.onprogress = (event) => {
|
|
259
|
+
if (event.lengthComputable && event.total > 0) onProgress?.(event.loaded / event.total);
|
|
260
|
+
};
|
|
261
|
+
xhr.onload = () => {
|
|
262
|
+
if (xhr.status < 200 || xhr.status >= 300) {
|
|
263
|
+
reject(new AgentHttpError(xhr.status, "POST", "/agent/attachments", xhr.statusText));
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
266
|
+
onProgress?.(1);
|
|
267
|
+
resolve(JSON.parse(xhr.responseText));
|
|
268
|
+
};
|
|
269
|
+
xhr.onerror = () => reject(new TypeError("Network error while uploading the attachment"));
|
|
270
|
+
xhr.onabort = () => reject(new DOMException("The upload was aborted", "AbortError"));
|
|
271
|
+
if (signal !== void 0) {
|
|
272
|
+
if (signal.aborted) {
|
|
273
|
+
reject(new DOMException("The upload was aborted", "AbortError"));
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
276
|
+
signal.addEventListener("abort", () => xhr.abort(), {
|
|
277
|
+
once: true
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
const formData = new FormData();
|
|
281
|
+
formData.append("file", file);
|
|
282
|
+
xhr.send(formData);
|
|
283
|
+
});
|
|
233
284
|
}
|
|
234
285
|
promoteThread(id) {
|
|
235
286
|
return this.request("POST", `/agent/threads/${encodeURIComponent(id)}/promote`);
|
|
@@ -246,6 +297,10 @@ var AgentClient = class {
|
|
|
246
297
|
listAgents() {
|
|
247
298
|
return this.request("GET", "/agent/agents");
|
|
248
299
|
}
|
|
300
|
+
/** `GET /agent/quota` — the caller's budget windows and the one blocking sends, if any. */
|
|
301
|
+
getQuota() {
|
|
302
|
+
return this.request("GET", "/agent/quota");
|
|
303
|
+
}
|
|
249
304
|
getQuotaToday() {
|
|
250
305
|
return this.request("GET", "/agent/quota/today");
|
|
251
306
|
}
|
|
@@ -1073,6 +1128,68 @@ function delay(ms, signal) {
|
|
|
1073
1128
|
}
|
|
1074
1129
|
__name(delay, "delay");
|
|
1075
1130
|
|
|
1131
|
+
// src/attachments/files.ts
|
|
1132
|
+
function fileKind(mediaType) {
|
|
1133
|
+
const type = mediaType.toLowerCase();
|
|
1134
|
+
if (type.startsWith("image/")) return "image";
|
|
1135
|
+
if (type === "application/pdf") return "pdf";
|
|
1136
|
+
if (type.startsWith("text/") || type === "application/json") return "text";
|
|
1137
|
+
if (type.startsWith("audio/")) return "audio";
|
|
1138
|
+
if (type.startsWith("video/")) return "video";
|
|
1139
|
+
return "other";
|
|
1140
|
+
}
|
|
1141
|
+
__name(fileKind, "fileKind");
|
|
1142
|
+
function messageFiles(message) {
|
|
1143
|
+
const files = [];
|
|
1144
|
+
for (const part of message.parts) {
|
|
1145
|
+
if (part.type !== "file") continue;
|
|
1146
|
+
const file = part;
|
|
1147
|
+
const filename = file.filename ?? null;
|
|
1148
|
+
const dot = filename?.lastIndexOf(".") ?? -1;
|
|
1149
|
+
const mediaId = file.providerMetadata?.agent?.mediaId;
|
|
1150
|
+
files.push({
|
|
1151
|
+
url: file.url,
|
|
1152
|
+
mediaType: file.mediaType,
|
|
1153
|
+
filename,
|
|
1154
|
+
kind: fileKind(file.mediaType),
|
|
1155
|
+
extension: filename !== null && dot > 0 ? filename.slice(dot + 1).toLowerCase() : null,
|
|
1156
|
+
mediaId: typeof mediaId === "string" ? mediaId : null
|
|
1157
|
+
});
|
|
1158
|
+
}
|
|
1159
|
+
return files;
|
|
1160
|
+
}
|
|
1161
|
+
__name(messageFiles, "messageFiles");
|
|
1162
|
+
function acceptsFile(accept, file) {
|
|
1163
|
+
const rules = (typeof accept === "string" ? accept.split(",") : accept ?? []).map((rule) => rule.trim().toLowerCase()).filter((rule) => rule.length > 0);
|
|
1164
|
+
if (rules.length === 0) return true;
|
|
1165
|
+
const type = file.type.toLowerCase();
|
|
1166
|
+
const name = file.name.toLowerCase();
|
|
1167
|
+
return rules.some((rule) => {
|
|
1168
|
+
if (rule.startsWith(".")) return name.endsWith(rule);
|
|
1169
|
+
if (rule.endsWith("/*")) return type.startsWith(rule.slice(0, -1));
|
|
1170
|
+
return type === rule;
|
|
1171
|
+
});
|
|
1172
|
+
}
|
|
1173
|
+
__name(acceptsFile, "acceptsFile");
|
|
1174
|
+
function filesFromClipboard(data) {
|
|
1175
|
+
if (!data) return [];
|
|
1176
|
+
const files = [];
|
|
1177
|
+
for (const item of Array.from(data.items ?? [])) {
|
|
1178
|
+
if (item.kind !== "file") continue;
|
|
1179
|
+
const file = item.getAsFile();
|
|
1180
|
+
if (file !== null) files.push(file);
|
|
1181
|
+
}
|
|
1182
|
+
return files.length > 0 ? files : Array.from(data.files ?? []);
|
|
1183
|
+
}
|
|
1184
|
+
__name(filesFromClipboard, "filesFromClipboard");
|
|
1185
|
+
function dragHasFiles(data) {
|
|
1186
|
+
return Array.from(data?.types ?? []).includes("Files");
|
|
1187
|
+
}
|
|
1188
|
+
__name(dragHasFiles, "dragHasFiles");
|
|
1189
|
+
|
|
1190
|
+
// src/attachments/use-attachments.ts
|
|
1191
|
+
var import_react2 = require("react");
|
|
1192
|
+
|
|
1076
1193
|
// src/backend.ts
|
|
1077
1194
|
var AgentBackendUnsupportedError = class extends Error {
|
|
1078
1195
|
static {
|
|
@@ -1093,19 +1210,239 @@ function requireBackendMethod(backend, name) {
|
|
|
1093
1210
|
}
|
|
1094
1211
|
__name(requireBackendMethod, "requireBackendMethod");
|
|
1095
1212
|
|
|
1213
|
+
// src/attachments/use-attachments.ts
|
|
1214
|
+
var DEFAULT_REJECTION = {
|
|
1215
|
+
type: /* @__PURE__ */ __name((file) => `${file.name} is not a supported file type`, "type"),
|
|
1216
|
+
size: /* @__PURE__ */ __name((file) => `${file.name} is too large`, "size"),
|
|
1217
|
+
count: /* @__PURE__ */ __name(() => "Too many files", "count")
|
|
1218
|
+
};
|
|
1219
|
+
var sequence = 0;
|
|
1220
|
+
function useAttachments(options) {
|
|
1221
|
+
const latest = (0, import_react2.useRef)(options);
|
|
1222
|
+
latest.current = options;
|
|
1223
|
+
const [items, setItems] = (0, import_react2.useState)([]);
|
|
1224
|
+
const itemsRef = (0, import_react2.useRef)(items);
|
|
1225
|
+
itemsRef.current = items;
|
|
1226
|
+
const controllers = (0, import_react2.useRef)(/* @__PURE__ */ new Map());
|
|
1227
|
+
const [dragDepth, setDragDepth] = (0, import_react2.useState)(0);
|
|
1228
|
+
const patch = (0, import_react2.useCallback)((id, change) => {
|
|
1229
|
+
setItems((current) => current.map((item) => item.id === id ? {
|
|
1230
|
+
...item,
|
|
1231
|
+
...change
|
|
1232
|
+
} : item));
|
|
1233
|
+
}, []);
|
|
1234
|
+
const start = (0, import_react2.useCallback)((item) => {
|
|
1235
|
+
const { upload, backend } = latest.current;
|
|
1236
|
+
const run = upload ?? (backend?.uploadAttachment !== void 0 ? backend.uploadAttachment.bind(backend) : void 0);
|
|
1237
|
+
if (run === void 0) {
|
|
1238
|
+
patch(item.id, {
|
|
1239
|
+
status: "error",
|
|
1240
|
+
error: new AgentBackendUnsupportedError("uploadAttachment").message
|
|
1241
|
+
});
|
|
1242
|
+
return;
|
|
1243
|
+
}
|
|
1244
|
+
const controller = new AbortController();
|
|
1245
|
+
controllers.current.set(item.id, controller);
|
|
1246
|
+
run(item.file, {
|
|
1247
|
+
signal: controller.signal,
|
|
1248
|
+
onProgress: /* @__PURE__ */ __name((fraction) => patch(item.id, {
|
|
1249
|
+
progress: Math.max(0, Math.min(1, fraction))
|
|
1250
|
+
}), "onProgress")
|
|
1251
|
+
}).then((attachment) => {
|
|
1252
|
+
if (controller.signal.aborted) return;
|
|
1253
|
+
controllers.current.delete(item.id);
|
|
1254
|
+
patch(item.id, {
|
|
1255
|
+
status: "ready",
|
|
1256
|
+
progress: 1,
|
|
1257
|
+
attachment
|
|
1258
|
+
});
|
|
1259
|
+
}, (error) => {
|
|
1260
|
+
if (controller.signal.aborted) return;
|
|
1261
|
+
controllers.current.delete(item.id);
|
|
1262
|
+
patch(item.id, {
|
|
1263
|
+
status: "error",
|
|
1264
|
+
error: error instanceof Error ? error.message : String(error)
|
|
1265
|
+
});
|
|
1266
|
+
});
|
|
1267
|
+
}, [
|
|
1268
|
+
patch
|
|
1269
|
+
]);
|
|
1270
|
+
const add = (0, import_react2.useCallback)((files) => {
|
|
1271
|
+
if (files == null) return;
|
|
1272
|
+
const { accept: accept2, maxBytes, maxFiles, describeRejection } = latest.current;
|
|
1273
|
+
const describe = /* @__PURE__ */ __name((reason, file) => describeRejection?.(reason, file) ?? DEFAULT_REJECTION[reason](file), "describe");
|
|
1274
|
+
let room = maxFiles === void 0 ? Number.POSITIVE_INFINITY : maxFiles - itemsRef.current.filter((item) => item.status !== "rejected").length;
|
|
1275
|
+
const staged = [];
|
|
1276
|
+
for (const file of Array.from(files)) {
|
|
1277
|
+
sequence += 1;
|
|
1278
|
+
const base = {
|
|
1279
|
+
id: `att-${sequence}`,
|
|
1280
|
+
file,
|
|
1281
|
+
name: file.name,
|
|
1282
|
+
size: file.size,
|
|
1283
|
+
type: file.type,
|
|
1284
|
+
progress: 0
|
|
1285
|
+
};
|
|
1286
|
+
const reason = !acceptsFile(accept2, file) ? "type" : maxBytes !== void 0 && file.size > maxBytes ? "size" : room <= 0 ? "count" : void 0;
|
|
1287
|
+
if (reason !== void 0) {
|
|
1288
|
+
staged.push({
|
|
1289
|
+
...base,
|
|
1290
|
+
status: "rejected",
|
|
1291
|
+
error: describe(reason, file)
|
|
1292
|
+
});
|
|
1293
|
+
continue;
|
|
1294
|
+
}
|
|
1295
|
+
room -= 1;
|
|
1296
|
+
const previewUrl = file.type.startsWith("image/") && typeof URL.createObjectURL === "function" ? URL.createObjectURL(file) : void 0;
|
|
1297
|
+
staged.push({
|
|
1298
|
+
...base,
|
|
1299
|
+
status: "uploading",
|
|
1300
|
+
...previewUrl ? {
|
|
1301
|
+
previewUrl
|
|
1302
|
+
} : {}
|
|
1303
|
+
});
|
|
1304
|
+
}
|
|
1305
|
+
if (staged.length === 0) return;
|
|
1306
|
+
setItems((current) => [
|
|
1307
|
+
...current,
|
|
1308
|
+
...staged
|
|
1309
|
+
]);
|
|
1310
|
+
for (const item of staged) {
|
|
1311
|
+
if (item.status === "uploading") start(item);
|
|
1312
|
+
}
|
|
1313
|
+
}, [
|
|
1314
|
+
start
|
|
1315
|
+
]);
|
|
1316
|
+
const release = (0, import_react2.useCallback)((item) => {
|
|
1317
|
+
if (item === void 0) return;
|
|
1318
|
+
controllers.current.get(item.id)?.abort();
|
|
1319
|
+
controllers.current.delete(item.id);
|
|
1320
|
+
if (item.previewUrl !== void 0 && typeof URL.revokeObjectURL === "function") {
|
|
1321
|
+
URL.revokeObjectURL(item.previewUrl);
|
|
1322
|
+
}
|
|
1323
|
+
}, []);
|
|
1324
|
+
const remove = (0, import_react2.useCallback)((id) => {
|
|
1325
|
+
release(itemsRef.current.find((item) => item.id === id));
|
|
1326
|
+
setItems((current) => current.filter((item) => item.id !== id));
|
|
1327
|
+
}, [
|
|
1328
|
+
release
|
|
1329
|
+
]);
|
|
1330
|
+
const clear = (0, import_react2.useCallback)(() => {
|
|
1331
|
+
for (const item of itemsRef.current) release(item);
|
|
1332
|
+
setItems([]);
|
|
1333
|
+
}, [
|
|
1334
|
+
release
|
|
1335
|
+
]);
|
|
1336
|
+
const retry = (0, import_react2.useCallback)((id) => {
|
|
1337
|
+
const item = itemsRef.current.find((candidate) => candidate.id === id);
|
|
1338
|
+
if (item === void 0 || item.status !== "error") return;
|
|
1339
|
+
const { error: _previous, ...rest } = item;
|
|
1340
|
+
const again = {
|
|
1341
|
+
...rest,
|
|
1342
|
+
status: "uploading",
|
|
1343
|
+
progress: 0
|
|
1344
|
+
};
|
|
1345
|
+
setItems((current) => current.map((candidate) => candidate.id === id ? again : candidate));
|
|
1346
|
+
start(again);
|
|
1347
|
+
}, [
|
|
1348
|
+
start
|
|
1349
|
+
]);
|
|
1350
|
+
(0, import_react2.useEffect)(() => () => {
|
|
1351
|
+
for (const item of itemsRef.current) release(item);
|
|
1352
|
+
}, [
|
|
1353
|
+
release
|
|
1354
|
+
]);
|
|
1355
|
+
const onPaste = (0, import_react2.useCallback)((event) => {
|
|
1356
|
+
const files = filesFromClipboard(event.clipboardData);
|
|
1357
|
+
if (files.length === 0) return;
|
|
1358
|
+
event.preventDefault();
|
|
1359
|
+
add(files);
|
|
1360
|
+
}, [
|
|
1361
|
+
add
|
|
1362
|
+
]);
|
|
1363
|
+
const dropZoneProps = (0, import_react2.useMemo)(() => ({
|
|
1364
|
+
onDragEnter: /* @__PURE__ */ __name((event) => {
|
|
1365
|
+
if (!dragHasFiles(event.dataTransfer)) return;
|
|
1366
|
+
event.preventDefault();
|
|
1367
|
+
setDragDepth((depth) => depth + 1);
|
|
1368
|
+
}, "onDragEnter"),
|
|
1369
|
+
onDragOver: /* @__PURE__ */ __name((event) => {
|
|
1370
|
+
if (dragHasFiles(event.dataTransfer)) event.preventDefault();
|
|
1371
|
+
}, "onDragOver"),
|
|
1372
|
+
onDragLeave: /* @__PURE__ */ __name((event) => {
|
|
1373
|
+
if (!dragHasFiles(event.dataTransfer)) return;
|
|
1374
|
+
setDragDepth((depth) => Math.max(0, depth - 1));
|
|
1375
|
+
}, "onDragLeave"),
|
|
1376
|
+
onDrop: /* @__PURE__ */ __name((event) => {
|
|
1377
|
+
if (!dragHasFiles(event.dataTransfer)) return;
|
|
1378
|
+
event.preventDefault();
|
|
1379
|
+
setDragDepth(0);
|
|
1380
|
+
add(event.dataTransfer?.files);
|
|
1381
|
+
}, "onDrop")
|
|
1382
|
+
}), [
|
|
1383
|
+
add
|
|
1384
|
+
]);
|
|
1385
|
+
const accept = options.accept;
|
|
1386
|
+
const inputProps = (0, import_react2.useMemo)(() => ({
|
|
1387
|
+
type: "file",
|
|
1388
|
+
accept: typeof accept === "string" ? accept : accept?.join(","),
|
|
1389
|
+
multiple: options.maxFiles === void 0 || options.maxFiles > 1,
|
|
1390
|
+
onChange: /* @__PURE__ */ __name((event) => {
|
|
1391
|
+
const input = event.currentTarget;
|
|
1392
|
+
add(input.files);
|
|
1393
|
+
input.value = "";
|
|
1394
|
+
}, "onChange")
|
|
1395
|
+
}), [
|
|
1396
|
+
accept,
|
|
1397
|
+
options.maxFiles,
|
|
1398
|
+
add
|
|
1399
|
+
]);
|
|
1400
|
+
return (0, import_react2.useMemo)(() => {
|
|
1401
|
+
const ready = items.filter((item) => item.status === "ready" && item.attachment !== void 0);
|
|
1402
|
+
const attachments = ready.map((item) => item.attachment);
|
|
1403
|
+
return {
|
|
1404
|
+
items,
|
|
1405
|
+
add,
|
|
1406
|
+
remove,
|
|
1407
|
+
retry,
|
|
1408
|
+
clear,
|
|
1409
|
+
isUploading: items.some((item) => item.status === "uploading"),
|
|
1410
|
+
attachments,
|
|
1411
|
+
refs: attachments.map((attachment) => ({
|
|
1412
|
+
mediaId: attachment.mediaId
|
|
1413
|
+
})),
|
|
1414
|
+
inputProps,
|
|
1415
|
+
dropZoneProps,
|
|
1416
|
+
isDragging: dragDepth > 0,
|
|
1417
|
+
onPaste
|
|
1418
|
+
};
|
|
1419
|
+
}, [
|
|
1420
|
+
items,
|
|
1421
|
+
add,
|
|
1422
|
+
remove,
|
|
1423
|
+
retry,
|
|
1424
|
+
clear,
|
|
1425
|
+
inputProps,
|
|
1426
|
+
dropZoneProps,
|
|
1427
|
+
dragDepth,
|
|
1428
|
+
onPaste
|
|
1429
|
+
]);
|
|
1430
|
+
}
|
|
1431
|
+
__name(useAttachments, "useAttachments");
|
|
1432
|
+
|
|
1096
1433
|
// src/catalog/use-agents.ts
|
|
1097
|
-
var
|
|
1434
|
+
var import_react4 = require("react");
|
|
1098
1435
|
|
|
1099
1436
|
// src/catalog/use-resource.ts
|
|
1100
|
-
var
|
|
1437
|
+
var import_react3 = require("react");
|
|
1101
1438
|
function useResource(load2, key, enabled) {
|
|
1102
|
-
const [data, setData] = (0,
|
|
1103
|
-
const [isLoading, setIsLoading] = (0,
|
|
1104
|
-
const [error, setError] = (0,
|
|
1105
|
-
const loadRef = (0,
|
|
1439
|
+
const [data, setData] = (0, import_react3.useState)(void 0);
|
|
1440
|
+
const [isLoading, setIsLoading] = (0, import_react3.useState)(enabled);
|
|
1441
|
+
const [error, setError] = (0, import_react3.useState)(null);
|
|
1442
|
+
const loadRef = (0, import_react3.useRef)(load2);
|
|
1106
1443
|
loadRef.current = load2;
|
|
1107
|
-
const generation = (0,
|
|
1108
|
-
const refresh = (0,
|
|
1444
|
+
const generation = (0, import_react3.useRef)(0);
|
|
1445
|
+
const refresh = (0, import_react3.useCallback)(async () => {
|
|
1109
1446
|
const mine = ++generation.current;
|
|
1110
1447
|
setIsLoading(true);
|
|
1111
1448
|
try {
|
|
@@ -1120,7 +1457,7 @@ function useResource(load2, key, enabled) {
|
|
|
1120
1457
|
if (mine === generation.current) setIsLoading(false);
|
|
1121
1458
|
}
|
|
1122
1459
|
}, []);
|
|
1123
|
-
(0,
|
|
1460
|
+
(0, import_react3.useEffect)(() => {
|
|
1124
1461
|
if (!enabled) return;
|
|
1125
1462
|
void refresh();
|
|
1126
1463
|
}, [
|
|
@@ -1141,7 +1478,7 @@ __name(useResource, "useResource");
|
|
|
1141
1478
|
function useAgents(options) {
|
|
1142
1479
|
const { backend, enabled = true } = options;
|
|
1143
1480
|
const { data, isLoading, error, refresh } = useResource(() => requireBackendMethod(backend, "listAgents")(), "", enabled);
|
|
1144
|
-
return (0,
|
|
1481
|
+
return (0, import_react4.useMemo)(() => {
|
|
1145
1482
|
const agents = data ?? [];
|
|
1146
1483
|
return {
|
|
1147
1484
|
agents,
|
|
@@ -1160,11 +1497,11 @@ function useAgents(options) {
|
|
|
1160
1497
|
__name(useAgents, "useAgents");
|
|
1161
1498
|
|
|
1162
1499
|
// src/catalog/use-models.ts
|
|
1163
|
-
var
|
|
1500
|
+
var import_react5 = require("react");
|
|
1164
1501
|
function useModels(options) {
|
|
1165
1502
|
const { backend, agent, enabled = true } = options;
|
|
1166
1503
|
const { data, isLoading, error, refresh } = useResource(() => requireBackendMethod(backend, "listModels")(agent), `${agent ?? ""}`, enabled);
|
|
1167
|
-
return (0,
|
|
1504
|
+
return (0, import_react5.useMemo)(() => {
|
|
1168
1505
|
const providers = data?.providers ?? [];
|
|
1169
1506
|
const models = providers.flatMap((provider) => provider.models.map((model) => ({
|
|
1170
1507
|
...model,
|
|
@@ -1193,28 +1530,96 @@ function useModels(options) {
|
|
|
1193
1530
|
}
|
|
1194
1531
|
__name(useModels, "useModels");
|
|
1195
1532
|
|
|
1533
|
+
// src/quota/use-quota.ts
|
|
1534
|
+
var import_react6 = require("react");
|
|
1535
|
+
|
|
1536
|
+
// src/threads/threads-events.ts
|
|
1537
|
+
var listeners = /* @__PURE__ */ new WeakMap();
|
|
1538
|
+
function notifyThreads(backend, event) {
|
|
1539
|
+
for (const listener of listeners.get(backend) ?? []) {
|
|
1540
|
+
listener(event);
|
|
1541
|
+
}
|
|
1542
|
+
}
|
|
1543
|
+
__name(notifyThreads, "notifyThreads");
|
|
1544
|
+
function onThreadsEvent(backend, listener) {
|
|
1545
|
+
let set = listeners.get(backend);
|
|
1546
|
+
if (set === void 0) {
|
|
1547
|
+
set = /* @__PURE__ */ new Set();
|
|
1548
|
+
listeners.set(backend, set);
|
|
1549
|
+
}
|
|
1550
|
+
set.add(listener);
|
|
1551
|
+
return () => {
|
|
1552
|
+
set.delete(listener);
|
|
1553
|
+
};
|
|
1554
|
+
}
|
|
1555
|
+
__name(onThreadsEvent, "onThreadsEvent");
|
|
1556
|
+
|
|
1557
|
+
// src/quota/use-quota.ts
|
|
1558
|
+
function useQuota(options) {
|
|
1559
|
+
const { backend, enabled = true, pollMs } = options;
|
|
1560
|
+
const { data, isLoading, error, refresh } = useResource(() => requireBackendMethod(backend, "getQuota")(), "", enabled);
|
|
1561
|
+
(0, import_react6.useEffect)(() => {
|
|
1562
|
+
if (!enabled) return;
|
|
1563
|
+
return onThreadsEvent(backend, (event) => {
|
|
1564
|
+
if (event.type === "changed") void refresh();
|
|
1565
|
+
});
|
|
1566
|
+
}, [
|
|
1567
|
+
backend,
|
|
1568
|
+
enabled,
|
|
1569
|
+
refresh
|
|
1570
|
+
]);
|
|
1571
|
+
(0, import_react6.useEffect)(() => {
|
|
1572
|
+
if (!enabled || pollMs === void 0 || pollMs <= 0) return;
|
|
1573
|
+
const timer = setInterval(() => void refresh(), pollMs);
|
|
1574
|
+
return () => clearInterval(timer);
|
|
1575
|
+
}, [
|
|
1576
|
+
enabled,
|
|
1577
|
+
pollMs,
|
|
1578
|
+
refresh
|
|
1579
|
+
]);
|
|
1580
|
+
return (0, import_react6.useMemo)(() => {
|
|
1581
|
+
const windows = data?.windows ?? [];
|
|
1582
|
+
return {
|
|
1583
|
+
report: data,
|
|
1584
|
+
windows,
|
|
1585
|
+
day: windows.find((window2) => window2.period === "day"),
|
|
1586
|
+
month: windows.find((window2) => window2.period === "month"),
|
|
1587
|
+
blocked: data?.blocked ?? null,
|
|
1588
|
+
isLoading,
|
|
1589
|
+
error,
|
|
1590
|
+
refresh
|
|
1591
|
+
};
|
|
1592
|
+
}, [
|
|
1593
|
+
data,
|
|
1594
|
+
isLoading,
|
|
1595
|
+
error,
|
|
1596
|
+
refresh
|
|
1597
|
+
]);
|
|
1598
|
+
}
|
|
1599
|
+
__name(useQuota, "useQuota");
|
|
1600
|
+
|
|
1196
1601
|
// src/feedback/use-message-feedback.ts
|
|
1197
|
-
var
|
|
1602
|
+
var import_react7 = require("react");
|
|
1198
1603
|
function useMessageFeedback(options) {
|
|
1199
|
-
const latest = (0,
|
|
1604
|
+
const latest = (0, import_react7.useRef)(options);
|
|
1200
1605
|
latest.current = options;
|
|
1201
|
-
const [local, setLocal] = (0,
|
|
1202
|
-
const [pending, setPending] = (0,
|
|
1203
|
-
const [error, setError] = (0,
|
|
1204
|
-
const localRef = (0,
|
|
1606
|
+
const [local, setLocal] = (0, import_react7.useState)(/* @__PURE__ */ new Map());
|
|
1607
|
+
const [pending, setPending] = (0, import_react7.useState)(/* @__PURE__ */ new Set());
|
|
1608
|
+
const [error, setError] = (0, import_react7.useState)(null);
|
|
1609
|
+
const localRef = (0, import_react7.useRef)(local);
|
|
1205
1610
|
localRef.current = local;
|
|
1206
|
-
const resolved = (0,
|
|
1207
|
-
const feedbackOf = (0,
|
|
1611
|
+
const resolved = (0, import_react7.useRef)(/* @__PURE__ */ new Map());
|
|
1612
|
+
const feedbackOf = (0, import_react7.useCallback)((message) => {
|
|
1208
1613
|
const mine = local.get(message.id);
|
|
1209
1614
|
if (mine !== void 0) return mine.feedback;
|
|
1210
1615
|
return metadataOf(message).feedback ?? null;
|
|
1211
1616
|
}, [
|
|
1212
1617
|
local
|
|
1213
1618
|
]);
|
|
1214
|
-
const isPending = (0,
|
|
1619
|
+
const isPending = (0, import_react7.useCallback)((message) => pending.has(message.id), [
|
|
1215
1620
|
pending
|
|
1216
1621
|
]);
|
|
1217
|
-
const storedIdFor = (0,
|
|
1622
|
+
const storedIdFor = (0, import_react7.useCallback)(async (message) => {
|
|
1218
1623
|
const runId = metadataOf(message).runId;
|
|
1219
1624
|
if (runId === void 0) return message.id;
|
|
1220
1625
|
const known = resolved.current.get(message.id);
|
|
@@ -1234,7 +1639,7 @@ function useMessageFeedback(options) {
|
|
|
1234
1639
|
resolved.current.set(message.id, row.id);
|
|
1235
1640
|
return row.id;
|
|
1236
1641
|
}, []);
|
|
1237
|
-
const rate = (0,
|
|
1642
|
+
const rate = (0, import_react7.useCallback)(async (message, value, comment) => {
|
|
1238
1643
|
const setFeedback = requireBackendMethod(latest.current.backend, "setMessageFeedback");
|
|
1239
1644
|
const had = localRef.current.get(message.id);
|
|
1240
1645
|
const optimistic = value === null ? null : {
|
|
@@ -1280,7 +1685,7 @@ function useMessageFeedback(options) {
|
|
|
1280
1685
|
}, [
|
|
1281
1686
|
storedIdFor
|
|
1282
1687
|
]);
|
|
1283
|
-
const toggle = (0,
|
|
1688
|
+
const toggle = (0, import_react7.useCallback)((message, value) => {
|
|
1284
1689
|
const mine = localRef.current.get(message.id);
|
|
1285
1690
|
const current = mine !== void 0 ? mine.feedback : metadataOf(message).feedback ?? null;
|
|
1286
1691
|
return rate(message, current?.value === value ? null : value);
|
|
@@ -1302,38 +1707,17 @@ function metadataOf(message) {
|
|
|
1302
1707
|
}
|
|
1303
1708
|
__name(metadataOf, "metadataOf");
|
|
1304
1709
|
|
|
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
1710
|
// src/threads/use-threads.ts
|
|
1327
|
-
var
|
|
1711
|
+
var import_react8 = require("react");
|
|
1328
1712
|
function useThreads(options) {
|
|
1329
1713
|
const { backend, enabled = true } = options;
|
|
1330
|
-
const [threads, setThreads] = (0,
|
|
1331
|
-
const [isLoading, setIsLoading] = (0,
|
|
1332
|
-
const [error, setError] = (0,
|
|
1333
|
-
const threadsRef = (0,
|
|
1714
|
+
const [threads, setThreads] = (0, import_react8.useState)([]);
|
|
1715
|
+
const [isLoading, setIsLoading] = (0, import_react8.useState)(enabled);
|
|
1716
|
+
const [error, setError] = (0, import_react8.useState)(null);
|
|
1717
|
+
const threadsRef = (0, import_react8.useRef)(threads);
|
|
1334
1718
|
threadsRef.current = threads;
|
|
1335
|
-
const generation = (0,
|
|
1336
|
-
const refresh = (0,
|
|
1719
|
+
const generation = (0, import_react8.useRef)(0);
|
|
1720
|
+
const refresh = (0, import_react8.useCallback)(async () => {
|
|
1337
1721
|
const mine = ++generation.current;
|
|
1338
1722
|
setIsLoading(true);
|
|
1339
1723
|
try {
|
|
@@ -1350,7 +1734,7 @@ function useThreads(options) {
|
|
|
1350
1734
|
}, [
|
|
1351
1735
|
backend
|
|
1352
1736
|
]);
|
|
1353
|
-
(0,
|
|
1737
|
+
(0, import_react8.useEffect)(() => {
|
|
1354
1738
|
if (!enabled) return;
|
|
1355
1739
|
void refresh();
|
|
1356
1740
|
return onThreadsEvent(backend, (event) => {
|
|
@@ -1370,7 +1754,7 @@ function useThreads(options) {
|
|
|
1370
1754
|
enabled,
|
|
1371
1755
|
refresh
|
|
1372
1756
|
]);
|
|
1373
|
-
const rename = (0,
|
|
1757
|
+
const rename = (0, import_react8.useCallback)(async (id, title) => {
|
|
1374
1758
|
const before = threadsRef.current;
|
|
1375
1759
|
setThreads((current) => current.map((thread) => thread.id === id ? {
|
|
1376
1760
|
...thread,
|
|
@@ -1392,7 +1776,7 @@ function useThreads(options) {
|
|
|
1392
1776
|
}, [
|
|
1393
1777
|
backend
|
|
1394
1778
|
]);
|
|
1395
|
-
const remove = (0,
|
|
1779
|
+
const remove = (0, import_react8.useCallback)(async (id) => {
|
|
1396
1780
|
const before = threadsRef.current;
|
|
1397
1781
|
setThreads((current) => current.filter((thread) => thread.id !== id));
|
|
1398
1782
|
try {
|
|
@@ -1467,10 +1851,10 @@ function backgroundRunsFromThread(messages) {
|
|
|
1467
1851
|
__name(backgroundRunsFromThread, "backgroundRunsFromThread");
|
|
1468
1852
|
|
|
1469
1853
|
// src/components/chat-input.tsx
|
|
1470
|
-
var
|
|
1854
|
+
var import_react10 = __toESM(require("react"), 1);
|
|
1471
1855
|
|
|
1472
1856
|
// src/components/use-speech-recognition.ts
|
|
1473
|
-
var
|
|
1857
|
+
var import_react9 = require("react");
|
|
1474
1858
|
function getRecognitionCtor() {
|
|
1475
1859
|
if (typeof window === "undefined") return null;
|
|
1476
1860
|
const scope = window;
|
|
@@ -1478,15 +1862,15 @@ function getRecognitionCtor() {
|
|
|
1478
1862
|
}
|
|
1479
1863
|
__name(getRecognitionCtor, "getRecognitionCtor");
|
|
1480
1864
|
function useSpeechRecognition({ lang = "en-US", onFinalTranscript, onInterimTranscript }) {
|
|
1481
|
-
const recognitionRef = (0,
|
|
1482
|
-
const [isListening, setIsListening] = (0,
|
|
1483
|
-
const ctor = (0,
|
|
1865
|
+
const recognitionRef = (0, import_react9.useRef)(null);
|
|
1866
|
+
const [isListening, setIsListening] = (0, import_react9.useState)(false);
|
|
1867
|
+
const ctor = (0, import_react9.useMemo)(() => getRecognitionCtor(), []);
|
|
1484
1868
|
const isSupported = ctor !== null;
|
|
1485
|
-
const finalRef = (0,
|
|
1486
|
-
const interimRef = (0,
|
|
1869
|
+
const finalRef = (0, import_react9.useRef)(onFinalTranscript);
|
|
1870
|
+
const interimRef = (0, import_react9.useRef)(onInterimTranscript);
|
|
1487
1871
|
finalRef.current = onFinalTranscript;
|
|
1488
1872
|
interimRef.current = onInterimTranscript;
|
|
1489
|
-
(0,
|
|
1873
|
+
(0, import_react9.useEffect)(() => {
|
|
1490
1874
|
if (!ctor) return;
|
|
1491
1875
|
const recognition = new ctor();
|
|
1492
1876
|
recognition.lang = lang;
|
|
@@ -1525,7 +1909,7 @@ function useSpeechRecognition({ lang = "en-US", onFinalTranscript, onInterimTran
|
|
|
1525
1909
|
ctor,
|
|
1526
1910
|
lang
|
|
1527
1911
|
]);
|
|
1528
|
-
const start = (0,
|
|
1912
|
+
const start = (0, import_react9.useCallback)(() => {
|
|
1529
1913
|
const recognition = recognitionRef.current;
|
|
1530
1914
|
if (!recognition) return;
|
|
1531
1915
|
try {
|
|
@@ -1535,7 +1919,7 @@ function useSpeechRecognition({ lang = "en-US", onFinalTranscript, onInterimTran
|
|
|
1535
1919
|
console.warn("SpeechRecognition start failed", error);
|
|
1536
1920
|
}
|
|
1537
1921
|
}, []);
|
|
1538
|
-
const stop = (0,
|
|
1922
|
+
const stop = (0, import_react9.useCallback)(() => {
|
|
1539
1923
|
const recognition = recognitionRef.current;
|
|
1540
1924
|
if (!recognition) return;
|
|
1541
1925
|
try {
|
|
@@ -1554,8 +1938,8 @@ __name(useSpeechRecognition, "useSpeechRecognition");
|
|
|
1554
1938
|
|
|
1555
1939
|
// src/components/chat-input.tsx
|
|
1556
1940
|
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,
|
|
1558
|
-
const [interim, setInterim] = (0,
|
|
1941
|
+
const [value, setValue] = (0, import_react10.useState)("");
|
|
1942
|
+
const [interim, setInterim] = (0, import_react10.useState)("");
|
|
1559
1943
|
const speech = useSpeechRecognition({
|
|
1560
1944
|
lang: speechLang,
|
|
1561
1945
|
onFinalTranscript: /* @__PURE__ */ __name((text) => {
|
|
@@ -1566,7 +1950,7 @@ function ChatInput({ onSubmit, disabled, placeholder, rows = 2, enableSpeech = t
|
|
|
1566
1950
|
}, "onFinalTranscript"),
|
|
1567
1951
|
onInterimTranscript: /* @__PURE__ */ __name((text) => setInterim(text), "onInterimTranscript")
|
|
1568
1952
|
});
|
|
1569
|
-
(0,
|
|
1953
|
+
(0, import_react10.useEffect)(() => {
|
|
1570
1954
|
if (!speech.isListening) setInterim("");
|
|
1571
1955
|
}, [
|
|
1572
1956
|
speech.isListening
|
|
@@ -1594,9 +1978,9 @@ function ChatInput({ onSubmit, disabled, placeholder, rows = 2, enableSpeech = t
|
|
|
1594
1978
|
const displayValue = speech.isListening && interim ? `${value}${value && !value.endsWith(" ") ? " " : ""}${interim}` : value;
|
|
1595
1979
|
const showMic = enableSpeech && speech.isSupported;
|
|
1596
1980
|
const showStop = isStreaming && onStop !== void 0;
|
|
1597
|
-
return /* @__PURE__ */
|
|
1981
|
+
return /* @__PURE__ */ import_react10.default.createElement("div", {
|
|
1598
1982
|
className
|
|
1599
|
-
}, /* @__PURE__ */
|
|
1983
|
+
}, /* @__PURE__ */ import_react10.default.createElement("textarea", {
|
|
1600
1984
|
className: textareaClassName,
|
|
1601
1985
|
rows,
|
|
1602
1986
|
value: displayValue,
|
|
@@ -1607,17 +1991,17 @@ function ChatInput({ onSubmit, disabled, placeholder, rows = 2, enableSpeech = t
|
|
|
1607
1991
|
}, "onChange"),
|
|
1608
1992
|
onKeyDown: handleKeyDown,
|
|
1609
1993
|
placeholder: placeholder ?? "Ask something (Enter to send, Shift+Enter for newline)"
|
|
1610
|
-
}), /* @__PURE__ */
|
|
1994
|
+
}), /* @__PURE__ */ import_react10.default.createElement("button", {
|
|
1611
1995
|
type: "button",
|
|
1612
1996
|
className: sendButtonClassName,
|
|
1613
1997
|
onClick: submit,
|
|
1614
1998
|
disabled: disabled || !value.trim()
|
|
1615
|
-
}, sendLabel), showStop ? /* @__PURE__ */
|
|
1999
|
+
}, sendLabel), showStop ? /* @__PURE__ */ import_react10.default.createElement("button", {
|
|
1616
2000
|
type: "button",
|
|
1617
2001
|
className: stopButtonClassName,
|
|
1618
2002
|
onClick: /* @__PURE__ */ __name(() => void onStop(), "onClick"),
|
|
1619
2003
|
"aria-label": "Stop generating"
|
|
1620
|
-
}, stopLabel) : null, showMic ? /* @__PURE__ */
|
|
2004
|
+
}, stopLabel) : null, showMic ? /* @__PURE__ */ import_react10.default.createElement("button", {
|
|
1621
2005
|
type: "button",
|
|
1622
2006
|
className: micButtonClassName,
|
|
1623
2007
|
onClick: toggleMic,
|
|
@@ -1630,10 +2014,10 @@ function ChatInput({ onSubmit, disabled, placeholder, rows = 2, enableSpeech = t
|
|
|
1630
2014
|
__name(ChatInput, "ChatInput");
|
|
1631
2015
|
|
|
1632
2016
|
// src/components/message-item.tsx
|
|
1633
|
-
var
|
|
2017
|
+
var import_react13 = __toESM(require("react"), 1);
|
|
1634
2018
|
|
|
1635
2019
|
// src/transcript/use-chat-transcript.ts
|
|
1636
|
-
var
|
|
2020
|
+
var import_react12 = require("react");
|
|
1637
2021
|
|
|
1638
2022
|
// src/transcript/model.ts
|
|
1639
2023
|
var import_nestjs_agent_core2 = require("@dudousxd/nestjs-agent-core");
|
|
@@ -2610,11 +2994,11 @@ function formatCostUsd(cost) {
|
|
|
2610
2994
|
__name(formatCostUsd, "formatCostUsd");
|
|
2611
2995
|
|
|
2612
2996
|
// src/transcript/use-stick-to-bottom.ts
|
|
2613
|
-
var
|
|
2997
|
+
var import_react11 = require("react");
|
|
2614
2998
|
function useStickToBottom({ contentKey, threshold = 32 }) {
|
|
2615
|
-
const containerRef = (0,
|
|
2616
|
-
const [isAtBottom, setIsAtBottom] = (0,
|
|
2617
|
-
const measure = (0,
|
|
2999
|
+
const containerRef = (0, import_react11.useRef)(null);
|
|
3000
|
+
const [isAtBottom, setIsAtBottom] = (0, import_react11.useState)(true);
|
|
3001
|
+
const measure = (0, import_react11.useCallback)(() => {
|
|
2618
3002
|
const element = containerRef.current;
|
|
2619
3003
|
if (!element) {
|
|
2620
3004
|
return;
|
|
@@ -2624,7 +3008,7 @@ function useStickToBottom({ contentKey, threshold = 32 }) {
|
|
|
2624
3008
|
}, [
|
|
2625
3009
|
threshold
|
|
2626
3010
|
]);
|
|
2627
|
-
const scrollToBottom = (0,
|
|
3011
|
+
const scrollToBottom = (0, import_react11.useCallback)(() => {
|
|
2628
3012
|
const element = containerRef.current;
|
|
2629
3013
|
if (!element) {
|
|
2630
3014
|
return;
|
|
@@ -2632,7 +3016,7 @@ function useStickToBottom({ contentKey, threshold = 32 }) {
|
|
|
2632
3016
|
element.scrollTop = element.scrollHeight;
|
|
2633
3017
|
setIsAtBottom(true);
|
|
2634
3018
|
}, []);
|
|
2635
|
-
const setContainer = (0,
|
|
3019
|
+
const setContainer = (0, import_react11.useCallback)((element) => {
|
|
2636
3020
|
containerRef.current = element;
|
|
2637
3021
|
if (element) {
|
|
2638
3022
|
measure();
|
|
@@ -2640,7 +3024,7 @@ function useStickToBottom({ contentKey, threshold = 32 }) {
|
|
|
2640
3024
|
}, [
|
|
2641
3025
|
measure
|
|
2642
3026
|
]);
|
|
2643
|
-
(0,
|
|
3027
|
+
(0, import_react11.useEffect)(() => {
|
|
2644
3028
|
if (isAtBottom) {
|
|
2645
3029
|
scrollToBottom();
|
|
2646
3030
|
}
|
|
@@ -2649,7 +3033,7 @@ function useStickToBottom({ contentKey, threshold = 32 }) {
|
|
|
2649
3033
|
isAtBottom,
|
|
2650
3034
|
scrollToBottom
|
|
2651
3035
|
]);
|
|
2652
|
-
const getContainerProps = (0,
|
|
3036
|
+
const getContainerProps = (0, import_react11.useCallback)(() => ({
|
|
2653
3037
|
ref: setContainer,
|
|
2654
3038
|
onScroll: measure
|
|
2655
3039
|
}), [
|
|
@@ -2671,14 +3055,14 @@ var DEFAULT_LOAD_EARLIER_STEP = 50;
|
|
|
2671
3055
|
var DEFAULT_COPY_RESET_MS = 1500;
|
|
2672
3056
|
function useChatTranscript(options) {
|
|
2673
3057
|
const { messages, status, initialVisibleCount = DEFAULT_VISIBLE_COUNT, loadEarlierStep = DEFAULT_LOAD_EARLIER_STEP, followUps, stickToBottomThreshold } = options;
|
|
2674
|
-
const latest = (0,
|
|
3058
|
+
const latest = (0, import_react12.useRef)(options);
|
|
2675
3059
|
latest.current = options;
|
|
2676
|
-
const [visibleCount, setVisibleCount] = (0,
|
|
2677
|
-
const [stopRequested, setStopRequested] = (0,
|
|
3060
|
+
const [visibleCount, setVisibleCount] = (0, import_react12.useState)(initialVisibleCount);
|
|
3061
|
+
const [stopRequested, setStopRequested] = (0, import_react12.useState)(false);
|
|
2678
3062
|
const isStreaming = status === "streaming" || status === "reconnecting";
|
|
2679
3063
|
const isBusy = status === "submitted" || isStreaming;
|
|
2680
3064
|
const isEmpty = messages.length === 0;
|
|
2681
|
-
(0,
|
|
3065
|
+
(0, import_react12.useEffect)(() => {
|
|
2682
3066
|
if (!isBusy) {
|
|
2683
3067
|
setStopRequested(false);
|
|
2684
3068
|
}
|
|
@@ -2695,7 +3079,7 @@ function useChatTranscript(options) {
|
|
|
2695
3079
|
streamingMessageId,
|
|
2696
3080
|
options
|
|
2697
3081
|
});
|
|
2698
|
-
const stop = (0,
|
|
3082
|
+
const stop = (0, import_react12.useCallback)(() => {
|
|
2699
3083
|
const current = latest.current;
|
|
2700
3084
|
if (current.status !== "submitted" && current.status !== "streaming" && current.status !== "reconnecting") {
|
|
2701
3085
|
return;
|
|
@@ -2703,8 +3087,8 @@ function useChatTranscript(options) {
|
|
|
2703
3087
|
setStopRequested(true);
|
|
2704
3088
|
void current.onStop?.();
|
|
2705
3089
|
}, []);
|
|
2706
|
-
const loadEarlier = (0,
|
|
2707
|
-
const showAll = (0,
|
|
3090
|
+
const loadEarlier = (0, import_react12.useCallback)(() => setVisibleCount((count) => count + (latest.current.loadEarlierStep ?? DEFAULT_LOAD_EARLIER_STEP)), []);
|
|
3091
|
+
const showAll = (0, import_react12.useCallback)(() => setVisibleCount(latest.current.messages.length), []);
|
|
2708
3092
|
const scroll = useStickToBottom({
|
|
2709
3093
|
contentKey: contentSignature(messages),
|
|
2710
3094
|
...stickToBottomThreshold !== void 0 ? {
|
|
@@ -2740,7 +3124,7 @@ function useChatTranscript(options) {
|
|
|
2740
3124
|
__name(useChatTranscript, "useChatTranscript");
|
|
2741
3125
|
function useTranscriptItem(options) {
|
|
2742
3126
|
const { message, isStreaming = false } = options;
|
|
2743
|
-
const messagesRef = (0,
|
|
3127
|
+
const messagesRef = (0, import_react12.useRef)([
|
|
2744
3128
|
message
|
|
2745
3129
|
]);
|
|
2746
3130
|
if (messagesRef.current[0] !== message) {
|
|
@@ -2758,13 +3142,13 @@ function useTranscriptItem(options) {
|
|
|
2758
3142
|
}
|
|
2759
3143
|
__name(useTranscriptItem, "useTranscriptItem");
|
|
2760
3144
|
function useTranscriptItems({ messages, visibleStart, streamingMessageId, options }) {
|
|
2761
|
-
const [drafts, setDrafts] = (0,
|
|
2762
|
-
const [copied, setCopied] = (0,
|
|
2763
|
-
const [openReasoning, setOpenReasoning] = (0,
|
|
2764
|
-
const [picks, setPicks] = (0,
|
|
2765
|
-
const [settling, setSettling] = (0,
|
|
2766
|
-
const [settleErrors, setSettleErrors] = (0,
|
|
2767
|
-
const latest = (0,
|
|
3145
|
+
const [drafts, setDrafts] = (0, import_react12.useState)(() => /* @__PURE__ */ new Map());
|
|
3146
|
+
const [copied, setCopied] = (0, import_react12.useState)(() => /* @__PURE__ */ new Set());
|
|
3147
|
+
const [openReasoning, setOpenReasoning] = (0, import_react12.useState)(() => /* @__PURE__ */ new Map());
|
|
3148
|
+
const [picks, setPicks] = (0, import_react12.useState)(() => /* @__PURE__ */ new Map());
|
|
3149
|
+
const [settling, setSettling] = (0, import_react12.useState)(() => /* @__PURE__ */ new Map());
|
|
3150
|
+
const [settleErrors, setSettleErrors] = (0, import_react12.useState)(() => /* @__PURE__ */ new Map());
|
|
3151
|
+
const latest = (0, import_react12.useRef)({
|
|
2768
3152
|
options,
|
|
2769
3153
|
drafts,
|
|
2770
3154
|
picks,
|
|
@@ -2776,23 +3160,23 @@ function useTranscriptItems({ messages, visibleStart, streamingMessageId, option
|
|
|
2776
3160
|
picks,
|
|
2777
3161
|
messages
|
|
2778
3162
|
};
|
|
2779
|
-
const copyTimers = (0,
|
|
2780
|
-
(0,
|
|
3163
|
+
const copyTimers = (0, import_react12.useRef)(/* @__PURE__ */ new Map());
|
|
3164
|
+
(0, import_react12.useEffect)(() => () => {
|
|
2781
3165
|
for (const timer of copyTimers.current.values()) {
|
|
2782
3166
|
clearTimeout(timer);
|
|
2783
3167
|
}
|
|
2784
3168
|
copyTimers.current.clear();
|
|
2785
3169
|
}, []);
|
|
2786
|
-
const callbackCache = (0,
|
|
2787
|
-
const reasoningToggleCache = (0,
|
|
2788
|
-
const toggleReasoning = (0,
|
|
3170
|
+
const callbackCache = (0, import_react12.useRef)(/* @__PURE__ */ new Map());
|
|
3171
|
+
const reasoningToggleCache = (0, import_react12.useRef)(/* @__PURE__ */ new Map());
|
|
3172
|
+
const toggleReasoning = (0, import_react12.useCallback)((key, open) => {
|
|
2789
3173
|
setOpenReasoning((current) => {
|
|
2790
3174
|
const next = new Map(current);
|
|
2791
3175
|
next.set(key, open ?? !(current.get(key) ?? false));
|
|
2792
3176
|
return next;
|
|
2793
3177
|
});
|
|
2794
3178
|
}, []);
|
|
2795
|
-
const stableToggle = (0,
|
|
3179
|
+
const stableToggle = (0, import_react12.useCallback)((key) => {
|
|
2796
3180
|
let cached = reasoningToggleCache.current.get(key);
|
|
2797
3181
|
if (!cached) {
|
|
2798
3182
|
cached = /* @__PURE__ */ __name((open) => toggleReasoning(key, open), "cached");
|
|
@@ -2802,10 +3186,10 @@ function useTranscriptItems({ messages, visibleStart, streamingMessageId, option
|
|
|
2802
3186
|
}, [
|
|
2803
3187
|
toggleReasoning
|
|
2804
3188
|
]);
|
|
2805
|
-
const pick = (0,
|
|
3189
|
+
const pick = (0, import_react12.useCallback)((toolCallId, questionId, values) => {
|
|
2806
3190
|
setPicks((current) => new Map(current).set(pickKey(toolCallId, questionId), values));
|
|
2807
3191
|
}, []);
|
|
2808
|
-
const settle = (0,
|
|
3192
|
+
const settle = (0, import_react12.useCallback)((toolCallId, action, send) => {
|
|
2809
3193
|
setSettleErrors((current) => {
|
|
2810
3194
|
if (!current.has(toolCallId)) {
|
|
2811
3195
|
return current;
|
|
@@ -2829,7 +3213,7 @@ function useTranscriptItems({ messages, visibleStart, streamingMessageId, option
|
|
|
2829
3213
|
failed(error);
|
|
2830
3214
|
}
|
|
2831
3215
|
}, []);
|
|
2832
|
-
const answer = (0,
|
|
3216
|
+
const answer = (0, import_react12.useCallback)((toolCallId) => {
|
|
2833
3217
|
const current = latest.current;
|
|
2834
3218
|
const onAnswer = current.options.onAnswer;
|
|
2835
3219
|
if (!onAnswer) {
|
|
@@ -2839,7 +3223,7 @@ function useTranscriptItems({ messages, visibleStart, streamingMessageId, option
|
|
|
2839
3223
|
}, [
|
|
2840
3224
|
settle
|
|
2841
3225
|
]);
|
|
2842
|
-
const skip = (0,
|
|
3226
|
+
const skip = (0, import_react12.useCallback)((toolCallId) => {
|
|
2843
3227
|
const onSkip = latest.current.options.onSkip;
|
|
2844
3228
|
if (onSkip) {
|
|
2845
3229
|
settle(toolCallId, "skip", () => onSkip(toolCallId));
|
|
@@ -2847,7 +3231,7 @@ function useTranscriptItems({ messages, visibleStart, streamingMessageId, option
|
|
|
2847
3231
|
}, [
|
|
2848
3232
|
settle
|
|
2849
3233
|
]);
|
|
2850
|
-
const approve = (0,
|
|
3234
|
+
const approve = (0, import_react12.useCallback)((toolCallId, options2) => {
|
|
2851
3235
|
const onApprove = latest.current.options.onApprove;
|
|
2852
3236
|
if (onApprove) {
|
|
2853
3237
|
settle(toolCallId, "approve", () => options2 === void 0 ? onApprove(toolCallId) : onApprove(toolCallId, options2));
|
|
@@ -2855,7 +3239,7 @@ function useTranscriptItems({ messages, visibleStart, streamingMessageId, option
|
|
|
2855
3239
|
}, [
|
|
2856
3240
|
settle
|
|
2857
3241
|
]);
|
|
2858
|
-
const reject = (0,
|
|
3242
|
+
const reject = (0, import_react12.useCallback)((toolCallId) => {
|
|
2859
3243
|
const onReject = latest.current.options.onReject;
|
|
2860
3244
|
if (onReject) {
|
|
2861
3245
|
settle(toolCallId, "reject", () => onReject(toolCallId));
|
|
@@ -2863,7 +3247,7 @@ function useTranscriptItems({ messages, visibleStart, streamingMessageId, option
|
|
|
2863
3247
|
}, [
|
|
2864
3248
|
settle
|
|
2865
3249
|
]);
|
|
2866
|
-
const callbacksFor = (0,
|
|
3250
|
+
const callbacksFor = (0, import_react12.useCallback)((id) => {
|
|
2867
3251
|
const cached = callbackCache.current.get(id);
|
|
2868
3252
|
if (cached) {
|
|
2869
3253
|
return cached;
|
|
@@ -3105,7 +3489,7 @@ function MessageItem({ message, isStreaming = false, editable, onEditSubmit, reg
|
|
|
3105
3489
|
getCreatedAt: /* @__PURE__ */ __name(() => createdAt, "getCreatedAt")
|
|
3106
3490
|
} : {}
|
|
3107
3491
|
});
|
|
3108
|
-
return /* @__PURE__ */
|
|
3492
|
+
return /* @__PURE__ */ import_react13.default.createElement(MessageItemView, {
|
|
3109
3493
|
item,
|
|
3110
3494
|
...slots
|
|
3111
3495
|
});
|
|
@@ -3113,51 +3497,51 @@ function MessageItem({ message, isStreaming = false, editable, onEditSubmit, reg
|
|
|
3113
3497
|
__name(MessageItem, "MessageItem");
|
|
3114
3498
|
function MessageItemView({ item, ...slots }) {
|
|
3115
3499
|
const { classNames } = slots;
|
|
3116
|
-
const actionRow = /* @__PURE__ */
|
|
3500
|
+
const actionRow = /* @__PURE__ */ import_react13.default.createElement("div", {
|
|
3117
3501
|
className: classNames?.actions,
|
|
3118
3502
|
"data-actions-for": item.role
|
|
3119
|
-
}, item.copy.available ? /* @__PURE__ */
|
|
3503
|
+
}, item.copy.available ? /* @__PURE__ */ import_react13.default.createElement("button", {
|
|
3120
3504
|
type: "button",
|
|
3121
3505
|
onClick: item.copy.copy,
|
|
3122
3506
|
className: classNames?.actionButton,
|
|
3123
3507
|
title: item.copy.copied ? "Copied!" : "Copy message text"
|
|
3124
|
-
}, item.copy.copied ? "Copied" : "Copy") : null, item.fork.available ? /* @__PURE__ */
|
|
3508
|
+
}, item.copy.copied ? "Copied" : "Copy") : null, item.fork.available ? /* @__PURE__ */ import_react13.default.createElement("button", {
|
|
3125
3509
|
type: "button",
|
|
3126
3510
|
onClick: item.fork.run,
|
|
3127
3511
|
className: classNames?.actionButton,
|
|
3128
3512
|
title: "Fork thread from this message"
|
|
3129
|
-
}, "Fork") : null, item.regenerate.available ? /* @__PURE__ */
|
|
3513
|
+
}, "Fork") : null, item.regenerate.available ? /* @__PURE__ */ import_react13.default.createElement("button", {
|
|
3130
3514
|
type: "button",
|
|
3131
3515
|
onClick: item.regenerate.run,
|
|
3132
3516
|
className: classNames?.actionButton,
|
|
3133
3517
|
title: "Regenerate response"
|
|
3134
|
-
}, "Regenerate") : null, slots.meta, !item.isUser && item.usage ? /* @__PURE__ */
|
|
3518
|
+
}, "Regenerate") : null, slots.meta, !item.isUser && item.usage ? /* @__PURE__ */ import_react13.default.createElement("span", {
|
|
3135
3519
|
className: classNames?.usage,
|
|
3136
3520
|
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__ */
|
|
3521
|
+
}, item.usage.costLabel, " \xB7 ", item.usage.tokensLabel) : null, item.timestamp ? /* @__PURE__ */ import_react13.default.createElement("span", {
|
|
3138
3522
|
className: classNames?.timestamp,
|
|
3139
3523
|
title: item.timestamp.absolute
|
|
3140
3524
|
}, item.timestamp.relative) : null);
|
|
3141
3525
|
if (item.edit.available) {
|
|
3142
|
-
return /* @__PURE__ */
|
|
3526
|
+
return /* @__PURE__ */ import_react13.default.createElement(EditableUserBubble, {
|
|
3143
3527
|
item,
|
|
3144
3528
|
slots,
|
|
3145
3529
|
actions: actionRow
|
|
3146
3530
|
});
|
|
3147
3531
|
}
|
|
3148
3532
|
const className = joinClasses(classNames?.root, classNames?.byRole?.[item.role]);
|
|
3149
|
-
return /* @__PURE__ */
|
|
3533
|
+
return /* @__PURE__ */ import_react13.default.createElement("div", {
|
|
3150
3534
|
className,
|
|
3151
3535
|
"data-role": item.role,
|
|
3152
3536
|
"data-streaming": item.isStreaming ? "true" : void 0
|
|
3153
|
-
}, /* @__PURE__ */
|
|
3537
|
+
}, /* @__PURE__ */ import_react13.default.createElement("div", null, renderBlocks(item, slots)), actionRow);
|
|
3154
3538
|
}
|
|
3155
3539
|
__name(MessageItemView, "MessageItemView");
|
|
3156
3540
|
function renderBlocks(item, slots) {
|
|
3157
3541
|
const nodes = [];
|
|
3158
3542
|
for (const block of item.blocks) {
|
|
3159
3543
|
if (block.kind === "text") {
|
|
3160
|
-
nodes.push(/* @__PURE__ */
|
|
3544
|
+
nodes.push(/* @__PURE__ */ import_react13.default.createElement("div", {
|
|
3161
3545
|
key: block.key,
|
|
3162
3546
|
className: slots.classNames?.text
|
|
3163
3547
|
}, slots.renderText ? slots.renderText(block.text, {
|
|
@@ -3178,7 +3562,7 @@ function renderBlocks(item, slots) {
|
|
|
3178
3562
|
continue;
|
|
3179
3563
|
}
|
|
3180
3564
|
if (block.kind === "ui" && slots.renderUi) {
|
|
3181
|
-
nodes.push(/* @__PURE__ */
|
|
3565
|
+
nodes.push(/* @__PURE__ */ import_react13.default.createElement("div", {
|
|
3182
3566
|
key: block.key,
|
|
3183
3567
|
"data-slot": "ui",
|
|
3184
3568
|
"data-component": block.component
|
|
@@ -3189,18 +3573,18 @@ function renderBlocks(item, slots) {
|
|
|
3189
3573
|
}
|
|
3190
3574
|
__name(renderBlocks, "renderBlocks");
|
|
3191
3575
|
function renderFilesBlock(block, slots) {
|
|
3192
|
-
return /* @__PURE__ */
|
|
3576
|
+
return /* @__PURE__ */ import_react13.default.createElement("div", {
|
|
3193
3577
|
key: block.key,
|
|
3194
3578
|
className: slots.classNames?.files,
|
|
3195
3579
|
"data-files": "true"
|
|
3196
|
-
}, slots.renderFiles ? slots.renderFiles(block.files) : block.files.map((file) => /* @__PURE__ */
|
|
3580
|
+
}, slots.renderFiles ? slots.renderFiles(block.files) : block.files.map((file) => /* @__PURE__ */ import_react13.default.createElement("a", {
|
|
3197
3581
|
key: file.url,
|
|
3198
3582
|
href: file.url,
|
|
3199
3583
|
target: "_blank",
|
|
3200
3584
|
rel: "noreferrer",
|
|
3201
3585
|
className: slots.classNames?.file,
|
|
3202
3586
|
title: file.filename ?? file.mediaType
|
|
3203
|
-
}, file.isImage ? /* @__PURE__ */
|
|
3587
|
+
}, file.isImage ? /* @__PURE__ */ import_react13.default.createElement("img", {
|
|
3204
3588
|
src: file.url,
|
|
3205
3589
|
alt: file.filename ?? "image",
|
|
3206
3590
|
className: slots.classNames?.fileImage
|
|
@@ -3208,17 +3592,17 @@ function renderFilesBlock(block, slots) {
|
|
|
3208
3592
|
}
|
|
3209
3593
|
__name(renderFilesBlock, "renderFilesBlock");
|
|
3210
3594
|
function renderReasoningBlock(block, slots) {
|
|
3211
|
-
return /* @__PURE__ */
|
|
3595
|
+
return /* @__PURE__ */ import_react13.default.createElement("div", {
|
|
3212
3596
|
key: block.key,
|
|
3213
3597
|
className: slots.classNames?.reasoning,
|
|
3214
3598
|
"data-reasoning": "true",
|
|
3215
3599
|
"data-streaming": block.isStreaming ? "true" : void 0
|
|
3216
|
-
}, /* @__PURE__ */
|
|
3600
|
+
}, /* @__PURE__ */ import_react13.default.createElement("button", {
|
|
3217
3601
|
type: "button",
|
|
3218
3602
|
className: slots.classNames?.reasoningToggle,
|
|
3219
3603
|
onClick: /* @__PURE__ */ __name(() => block.toggle(), "onClick"),
|
|
3220
3604
|
"aria-expanded": block.isOpen
|
|
3221
|
-
}, slots.reasoningLabel ?? "Reasoning"), block.isOpen ? /* @__PURE__ */
|
|
3605
|
+
}, slots.reasoningLabel ?? "Reasoning"), block.isOpen ? /* @__PURE__ */ import_react13.default.createElement("div", {
|
|
3222
3606
|
className: slots.classNames?.reasoningText
|
|
3223
3607
|
}, slots.renderReasoning ? slots.renderReasoning(block.text, {
|
|
3224
3608
|
isStreaming: block.isStreaming,
|
|
@@ -3229,7 +3613,7 @@ __name(renderReasoningBlock, "renderReasoningBlock");
|
|
|
3229
3613
|
function renderToolBlock(item, block, slots) {
|
|
3230
3614
|
if (slots.renderToolGroup) {
|
|
3231
3615
|
return [
|
|
3232
|
-
/* @__PURE__ */
|
|
3616
|
+
/* @__PURE__ */ import_react13.default.createElement(import_react13.default.Fragment, {
|
|
3233
3617
|
key: block.key
|
|
3234
3618
|
}, slots.renderToolGroup(block.parts, block.key))
|
|
3235
3619
|
];
|
|
@@ -3240,7 +3624,7 @@ function renderToolBlock(item, block, slots) {
|
|
|
3240
3624
|
const renderToolPart = slots.renderToolPart;
|
|
3241
3625
|
return block.parts.map((part) => {
|
|
3242
3626
|
const partKey = `${item.id}-${part.toolCallId}`;
|
|
3243
|
-
return /* @__PURE__ */
|
|
3627
|
+
return /* @__PURE__ */ import_react13.default.createElement(import_react13.default.Fragment, {
|
|
3244
3628
|
key: partKey
|
|
3245
3629
|
}, renderToolPart(part, partKey));
|
|
3246
3630
|
});
|
|
@@ -3250,14 +3634,14 @@ function EditableUserBubble({ item, slots, actions }) {
|
|
|
3250
3634
|
const { classNames } = slots;
|
|
3251
3635
|
const { edit } = item;
|
|
3252
3636
|
if (!edit.isEditing) {
|
|
3253
|
-
return /* @__PURE__ */
|
|
3637
|
+
return /* @__PURE__ */ import_react13.default.createElement("div", {
|
|
3254
3638
|
className: joinClasses(classNames?.root, classNames?.byRole?.user),
|
|
3255
3639
|
"data-role": "user"
|
|
3256
|
-
}, /* @__PURE__ */
|
|
3640
|
+
}, /* @__PURE__ */ import_react13.default.createElement("div", {
|
|
3257
3641
|
className: classNames?.text
|
|
3258
3642
|
}, slots.renderText ? slots.renderText(item.text, {
|
|
3259
3643
|
isStreaming: false
|
|
3260
|
-
}) : item.text), /* @__PURE__ */
|
|
3644
|
+
}) : item.text), /* @__PURE__ */ import_react13.default.createElement("button", {
|
|
3261
3645
|
type: "button",
|
|
3262
3646
|
onClick: edit.start,
|
|
3263
3647
|
className: classNames?.actionButton,
|
|
@@ -3265,18 +3649,18 @@ function EditableUserBubble({ item, slots, actions }) {
|
|
|
3265
3649
|
}, "Edit"), actions);
|
|
3266
3650
|
}
|
|
3267
3651
|
const textareaProps = edit.getTextareaProps();
|
|
3268
|
-
return /* @__PURE__ */
|
|
3652
|
+
return /* @__PURE__ */ import_react13.default.createElement("div", {
|
|
3269
3653
|
"data-editing": "true"
|
|
3270
|
-
}, /* @__PURE__ */
|
|
3654
|
+
}, /* @__PURE__ */ import_react13.default.createElement("textarea", {
|
|
3271
3655
|
...textareaProps,
|
|
3272
3656
|
rows: Math.min(8, edit.draft.split("\n").length + 1),
|
|
3273
3657
|
className: classNames?.editTextarea
|
|
3274
|
-
}), /* @__PURE__ */
|
|
3658
|
+
}), /* @__PURE__ */ import_react13.default.createElement("div", {
|
|
3275
3659
|
className: classNames?.editActions
|
|
3276
|
-
}, /* @__PURE__ */
|
|
3660
|
+
}, /* @__PURE__ */ import_react13.default.createElement("button", {
|
|
3277
3661
|
type: "button",
|
|
3278
3662
|
onClick: edit.cancel
|
|
3279
|
-
}, "Cancel"), /* @__PURE__ */
|
|
3663
|
+
}, "Cancel"), /* @__PURE__ */ import_react13.default.createElement("button", {
|
|
3280
3664
|
type: "button",
|
|
3281
3665
|
onClick: edit.save,
|
|
3282
3666
|
disabled: !edit.canSave
|
|
@@ -3520,35 +3904,35 @@ function toItem(entry) {
|
|
|
3520
3904
|
__name(toItem, "toItem");
|
|
3521
3905
|
|
|
3522
3906
|
// src/composer/use-composer-autocomplete.ts
|
|
3523
|
-
var
|
|
3907
|
+
var import_react14 = require("react");
|
|
3524
3908
|
function useComposerAutocomplete(options) {
|
|
3525
3909
|
const { value, sources, acceptOnTab = true } = options;
|
|
3526
|
-
const latest = (0,
|
|
3910
|
+
const latest = (0, import_react14.useRef)(options);
|
|
3527
3911
|
latest.current = options;
|
|
3528
|
-
const inputRef = (0,
|
|
3529
|
-
const [caret, setCaret] = (0,
|
|
3530
|
-
const [items, setItems] = (0,
|
|
3531
|
-
const [isLoading, setLoading] = (0,
|
|
3532
|
-
const [error, setError] = (0,
|
|
3533
|
-
const [activeIndex, setActiveIndex] = (0,
|
|
3534
|
-
const [dismissedIndex, setDismissedIndex] = (0,
|
|
3912
|
+
const inputRef = (0, import_react14.useRef)(null);
|
|
3913
|
+
const [caret, setCaret] = (0, import_react14.useState)(value.length);
|
|
3914
|
+
const [items, setItems] = (0, import_react14.useState)([]);
|
|
3915
|
+
const [isLoading, setLoading] = (0, import_react14.useState)(false);
|
|
3916
|
+
const [error, setError] = (0, import_react14.useState)(null);
|
|
3917
|
+
const [activeIndex, setActiveIndex] = (0, import_react14.useState)(0);
|
|
3918
|
+
const [dismissedIndex, setDismissedIndex] = (0, import_react14.useState)(null);
|
|
3535
3919
|
const safeCaret = Math.min(caret, value.length);
|
|
3536
|
-
const match = (0,
|
|
3920
|
+
const match = (0, import_react14.useMemo)(() => findActiveTrigger(value, safeCaret, sources), [
|
|
3537
3921
|
value,
|
|
3538
3922
|
safeCaret,
|
|
3539
3923
|
sources
|
|
3540
3924
|
]);
|
|
3541
3925
|
const isActive = match !== null && dismissedIndex !== match.index;
|
|
3542
|
-
const matchRef = (0,
|
|
3926
|
+
const matchRef = (0, import_react14.useRef)(match);
|
|
3543
3927
|
matchRef.current = match;
|
|
3544
|
-
const caretRef = (0,
|
|
3928
|
+
const caretRef = (0, import_react14.useRef)(safeCaret);
|
|
3545
3929
|
caretRef.current = safeCaret;
|
|
3546
|
-
const itemsRef = (0,
|
|
3930
|
+
const itemsRef = (0, import_react14.useRef)(items);
|
|
3547
3931
|
itemsRef.current = items;
|
|
3548
|
-
const activeIndexRef = (0,
|
|
3932
|
+
const activeIndexRef = (0, import_react14.useRef)(activeIndex);
|
|
3549
3933
|
activeIndexRef.current = activeIndex;
|
|
3550
3934
|
const requestKey = isActive && match ? `${match.source.id}\0${match.query}` : null;
|
|
3551
|
-
(0,
|
|
3935
|
+
(0, import_react14.useEffect)(() => {
|
|
3552
3936
|
const current = matchRef.current;
|
|
3553
3937
|
if (requestKey === null || current === null) {
|
|
3554
3938
|
setItems([]);
|
|
@@ -3596,25 +3980,25 @@ function useComposerAutocomplete(options) {
|
|
|
3596
3980
|
]);
|
|
3597
3981
|
const isOpen = isActive;
|
|
3598
3982
|
const activeItem = isOpen ? items[activeIndex] ?? null : null;
|
|
3599
|
-
const reactId = (0,
|
|
3983
|
+
const reactId = (0, import_react14.useId)();
|
|
3600
3984
|
const listboxId = options.id ?? `agent-autocomplete-${reactId}`;
|
|
3601
|
-
const optionId = (0,
|
|
3985
|
+
const optionId = (0, import_react14.useCallback)((index) => `${listboxId}-option-${index}`, [
|
|
3602
3986
|
listboxId
|
|
3603
3987
|
]);
|
|
3604
|
-
const highlight = (0,
|
|
3988
|
+
const highlight = (0, import_react14.useCallback)((index) => {
|
|
3605
3989
|
const total = itemsRef.current.length;
|
|
3606
3990
|
if (total === 0) return;
|
|
3607
3991
|
setActiveIndex((index % total + total) % total);
|
|
3608
3992
|
}, []);
|
|
3609
|
-
const moveHighlight = (0,
|
|
3993
|
+
const moveHighlight = (0, import_react14.useCallback)((delta) => highlight(activeIndexRef.current + delta), [
|
|
3610
3994
|
highlight
|
|
3611
3995
|
]);
|
|
3612
|
-
const dismiss = (0,
|
|
3996
|
+
const dismiss = (0, import_react14.useCallback)(() => {
|
|
3613
3997
|
const current = matchRef.current;
|
|
3614
3998
|
if (current) setDismissedIndex(current.index);
|
|
3615
3999
|
}, []);
|
|
3616
|
-
const pendingCaret = (0,
|
|
3617
|
-
const accept = (0,
|
|
4000
|
+
const pendingCaret = (0, import_react14.useRef)(null);
|
|
4001
|
+
const accept = (0, import_react14.useCallback)((item) => {
|
|
3618
4002
|
const current = matchRef.current;
|
|
3619
4003
|
if (!current) return;
|
|
3620
4004
|
const chosen = item ?? itemsRef.current[activeIndexRef.current];
|
|
@@ -3625,16 +4009,16 @@ function useComposerAutocomplete(options) {
|
|
|
3625
4009
|
setDismissedIndex(null);
|
|
3626
4010
|
pendingCaret.current = edit.caret;
|
|
3627
4011
|
}, []);
|
|
3628
|
-
(0,
|
|
4012
|
+
(0, import_react14.useLayoutEffect)(() => {
|
|
3629
4013
|
const position = pendingCaret.current;
|
|
3630
4014
|
if (position === null) return;
|
|
3631
4015
|
pendingCaret.current = null;
|
|
3632
4016
|
inputRef.current?.setSelectionRange(position, position);
|
|
3633
4017
|
});
|
|
3634
|
-
const readCaret = (0,
|
|
4018
|
+
const readCaret = (0, import_react14.useCallback)((element) => {
|
|
3635
4019
|
setCaret(element.selectionStart ?? element.value.length);
|
|
3636
4020
|
}, []);
|
|
3637
|
-
const onKeyDown = (0,
|
|
4021
|
+
const onKeyDown = (0, import_react14.useCallback)((event) => {
|
|
3638
4022
|
if (!isOpen) return;
|
|
3639
4023
|
const hasItems = itemsRef.current.length > 0;
|
|
3640
4024
|
switch (event.key) {
|
|
@@ -3672,23 +4056,23 @@ function useComposerAutocomplete(options) {
|
|
|
3672
4056
|
dismiss,
|
|
3673
4057
|
moveHighlight
|
|
3674
4058
|
]);
|
|
3675
|
-
const onChange = (0,
|
|
4059
|
+
const onChange = (0, import_react14.useCallback)((event) => {
|
|
3676
4060
|
readCaret(event.target);
|
|
3677
4061
|
const next = findActiveTrigger(event.target.value, event.target.selectionStart ?? event.target.value.length, latest.current.sources);
|
|
3678
4062
|
setDismissedIndex((current) => current !== null && next?.index === current ? current : null);
|
|
3679
4063
|
}, [
|
|
3680
4064
|
readCaret
|
|
3681
4065
|
]);
|
|
3682
|
-
const onSelect = (0,
|
|
4066
|
+
const onSelect = (0, import_react14.useCallback)((event) => readCaret(event.currentTarget), [
|
|
3683
4067
|
readCaret
|
|
3684
4068
|
]);
|
|
3685
|
-
const onClick = (0,
|
|
4069
|
+
const onClick = (0, import_react14.useCallback)((event) => readCaret(event.currentTarget), [
|
|
3686
4070
|
readCaret
|
|
3687
4071
|
]);
|
|
3688
|
-
const setInput = (0,
|
|
4072
|
+
const setInput = (0, import_react14.useCallback)((element) => {
|
|
3689
4073
|
inputRef.current = element;
|
|
3690
4074
|
}, []);
|
|
3691
|
-
const getInputProps = (0,
|
|
4075
|
+
const getInputProps = (0, import_react14.useCallback)(() => ({
|
|
3692
4076
|
ref: setInput,
|
|
3693
4077
|
onChange,
|
|
3694
4078
|
onKeyDown,
|
|
@@ -3716,7 +4100,7 @@ function useComposerAutocomplete(options) {
|
|
|
3716
4100
|
activeIndex,
|
|
3717
4101
|
optionId
|
|
3718
4102
|
]);
|
|
3719
|
-
const getListboxProps = (0,
|
|
4103
|
+
const getListboxProps = (0, import_react14.useCallback)(() => ({
|
|
3720
4104
|
id: listboxId,
|
|
3721
4105
|
role: "listbox",
|
|
3722
4106
|
"aria-label": match?.source.label ?? match?.source.id ?? "Suggestions"
|
|
@@ -3724,7 +4108,7 @@ function useComposerAutocomplete(options) {
|
|
|
3724
4108
|
listboxId,
|
|
3725
4109
|
match
|
|
3726
4110
|
]);
|
|
3727
|
-
const getOptionProps = (0,
|
|
4111
|
+
const getOptionProps = (0, import_react14.useCallback)((index) => ({
|
|
3728
4112
|
id: optionId(index),
|
|
3729
4113
|
role: "option",
|
|
3730
4114
|
"aria-selected": index === activeIndex
|
|
@@ -3758,7 +4142,7 @@ function isPromise(value) {
|
|
|
3758
4142
|
__name(isPromise, "isPromise");
|
|
3759
4143
|
|
|
3760
4144
|
// src/presentation/use-tool-catalog.ts
|
|
3761
|
-
var
|
|
4145
|
+
var import_react15 = require("react");
|
|
3762
4146
|
var shared = /* @__PURE__ */ new WeakMap();
|
|
3763
4147
|
function load(client, agent) {
|
|
3764
4148
|
let byAgent = shared.get(client);
|
|
@@ -3782,11 +4166,11 @@ function load(client, agent) {
|
|
|
3782
4166
|
__name(load, "load");
|
|
3783
4167
|
function useToolCatalog(options) {
|
|
3784
4168
|
const { client, agent, enabled = true } = options;
|
|
3785
|
-
const [entries, setEntries] = (0,
|
|
3786
|
-
const [isLoading, setLoading] = (0,
|
|
3787
|
-
const [error, setError] = (0,
|
|
3788
|
-
const [generation, setGeneration] = (0,
|
|
3789
|
-
(0,
|
|
4169
|
+
const [entries, setEntries] = (0, import_react15.useState)([]);
|
|
4170
|
+
const [isLoading, setLoading] = (0, import_react15.useState)(enabled);
|
|
4171
|
+
const [error, setError] = (0, import_react15.useState)(null);
|
|
4172
|
+
const [generation, setGeneration] = (0, import_react15.useState)(0);
|
|
4173
|
+
(0, import_react15.useEffect)(() => {
|
|
3790
4174
|
if (!enabled) {
|
|
3791
4175
|
setLoading(false);
|
|
3792
4176
|
return;
|
|
@@ -3812,14 +4196,14 @@ function useToolCatalog(options) {
|
|
|
3812
4196
|
enabled,
|
|
3813
4197
|
generation
|
|
3814
4198
|
]);
|
|
3815
|
-
const refresh = (0,
|
|
4199
|
+
const refresh = (0, import_react15.useCallback)(() => {
|
|
3816
4200
|
shared.get(client)?.delete(agent ?? "");
|
|
3817
4201
|
setGeneration((current) => current + 1);
|
|
3818
4202
|
}, [
|
|
3819
4203
|
client,
|
|
3820
4204
|
agent
|
|
3821
4205
|
]);
|
|
3822
|
-
const catalog = (0,
|
|
4206
|
+
const catalog = (0, import_react15.useMemo)(() => toolCatalogFrom(entries), [
|
|
3823
4207
|
entries
|
|
3824
4208
|
]);
|
|
3825
4209
|
return {
|
|
@@ -3833,7 +4217,7 @@ function useToolCatalog(options) {
|
|
|
3833
4217
|
__name(useToolCatalog, "useToolCatalog");
|
|
3834
4218
|
|
|
3835
4219
|
// src/approvals/countdown.ts
|
|
3836
|
-
var
|
|
4220
|
+
var import_react16 = require("react");
|
|
3837
4221
|
function approvalCountdown(expiresAt, now = Date.now()) {
|
|
3838
4222
|
const deadline = expiresAt == null ? Number.NaN : Date.parse(expiresAt);
|
|
3839
4223
|
if (!Number.isFinite(deadline)) {
|
|
@@ -3851,10 +4235,10 @@ function approvalCountdown(expiresAt, now = Date.now()) {
|
|
|
3851
4235
|
__name(approvalCountdown, "approvalCountdown");
|
|
3852
4236
|
function useApprovalCountdown(expiresAt, options = {}) {
|
|
3853
4237
|
const { intervalMs = 1e3 } = options;
|
|
3854
|
-
const nowRef = (0,
|
|
4238
|
+
const nowRef = (0, import_react16.useRef)(options.now ?? Date.now);
|
|
3855
4239
|
nowRef.current = options.now ?? Date.now;
|
|
3856
|
-
const [state, setState] = (0,
|
|
3857
|
-
(0,
|
|
4240
|
+
const [state, setState] = (0, import_react16.useState)(() => approvalCountdown(expiresAt, nowRef.current()));
|
|
4241
|
+
(0, import_react16.useEffect)(() => {
|
|
3858
4242
|
const read = /* @__PURE__ */ __name(() => approvalCountdown(expiresAt, nowRef.current()), "read");
|
|
3859
4243
|
const first = read();
|
|
3860
4244
|
setState(first);
|
|
@@ -3917,7 +4301,13 @@ function storedMessageToUiMessage(message) {
|
|
|
3917
4301
|
type: "file",
|
|
3918
4302
|
mediaType: attachment.contentType,
|
|
3919
4303
|
filename: attachment.name,
|
|
3920
|
-
url: attachment.url
|
|
4304
|
+
url: attachment.url,
|
|
4305
|
+
// The stored id rides along, so a replayed file can be referenced again (`messageFiles`).
|
|
4306
|
+
providerMetadata: {
|
|
4307
|
+
agent: {
|
|
4308
|
+
mediaId: attachment.mediaId
|
|
4309
|
+
}
|
|
4310
|
+
}
|
|
3921
4311
|
});
|
|
3922
4312
|
}
|
|
3923
4313
|
const toolCallIds = new Set((message.toolCalls ?? []).map((call) => call.id));
|
|
@@ -4095,21 +4485,21 @@ function sumUsage(rows) {
|
|
|
4095
4485
|
__name(sumUsage, "sumUsage");
|
|
4096
4486
|
|
|
4097
4487
|
// src/use-agent-chat.ts
|
|
4098
|
-
var
|
|
4099
|
-
var
|
|
4488
|
+
var import_react17 = require("@ai-sdk/react");
|
|
4489
|
+
var import_react18 = require("react");
|
|
4100
4490
|
function useAgentChat(options) {
|
|
4101
|
-
const latest = (0,
|
|
4491
|
+
const latest = (0, import_react18.useRef)(options);
|
|
4102
4492
|
latest.current = options;
|
|
4103
|
-
const [runId, setRunId] = (0,
|
|
4104
|
-
const runIdRef = (0,
|
|
4493
|
+
const [runId, setRunId] = (0, import_react18.useState)(options.resumeRunId);
|
|
4494
|
+
const runIdRef = (0, import_react18.useRef)(runId);
|
|
4105
4495
|
runIdRef.current = runId;
|
|
4106
|
-
const settlingRunIdRef = (0,
|
|
4107
|
-
const autoResumeRunIdRef = (0,
|
|
4108
|
-
const [autoResume, setAutoResume] = (0,
|
|
4109
|
-
const [activeRunId, setActiveRunId] = (0,
|
|
4110
|
-
const regenerateNext = (0,
|
|
4111
|
-
const createdThreadId = (0,
|
|
4112
|
-
const client = (0,
|
|
4496
|
+
const settlingRunIdRef = (0, import_react18.useRef)(void 0);
|
|
4497
|
+
const autoResumeRunIdRef = (0, import_react18.useRef)(void 0);
|
|
4498
|
+
const [autoResume, setAutoResume] = (0, import_react18.useState)(false);
|
|
4499
|
+
const [activeRunId, setActiveRunId] = (0, import_react18.useState)(null);
|
|
4500
|
+
const regenerateNext = (0, import_react18.useRef)(false);
|
|
4501
|
+
const createdThreadId = (0, import_react18.useRef)(void 0);
|
|
4502
|
+
const client = (0, import_react18.useMemo)(() => {
|
|
4113
4503
|
if (options.backend) return options.backend;
|
|
4114
4504
|
if (options.client) return options.client;
|
|
4115
4505
|
return new AgentClient({
|
|
@@ -4125,11 +4515,11 @@ function useAgentChat(options) {
|
|
|
4125
4515
|
getHeaders: /* @__PURE__ */ __name(async () => mergeHeaders(latest.current), "getHeaders")
|
|
4126
4516
|
});
|
|
4127
4517
|
}, []);
|
|
4128
|
-
const [connection, setConnection] = (0,
|
|
4518
|
+
const [connection, setConnection] = (0, import_react18.useState)({
|
|
4129
4519
|
status: "live"
|
|
4130
4520
|
});
|
|
4131
|
-
const resyncAfterSettle = (0,
|
|
4132
|
-
(0,
|
|
4521
|
+
const resyncAfterSettle = (0, import_react18.useRef)(false);
|
|
4522
|
+
(0, import_react18.useEffect)(() => {
|
|
4133
4523
|
if (!options.resume || options.threadId === void 0) return;
|
|
4134
4524
|
let cancelled = false;
|
|
4135
4525
|
const threadId = options.threadId;
|
|
@@ -4149,7 +4539,7 @@ function useAgentChat(options) {
|
|
|
4149
4539
|
options.resume,
|
|
4150
4540
|
options.threadId
|
|
4151
4541
|
]);
|
|
4152
|
-
const transport = (0,
|
|
4542
|
+
const transport = (0, import_react18.useMemo)(() => {
|
|
4153
4543
|
function onMeta(meta) {
|
|
4154
4544
|
settlingRunIdRef.current = meta.runId;
|
|
4155
4545
|
setRunId(meta.runId);
|
|
@@ -4204,8 +4594,8 @@ function useAgentChat(options) {
|
|
|
4204
4594
|
}, "onAttemptStart")
|
|
4205
4595
|
});
|
|
4206
4596
|
}, []);
|
|
4207
|
-
const backgroundRef = (0,
|
|
4208
|
-
const chat = (0,
|
|
4597
|
+
const backgroundRef = (0, import_react18.useRef)(() => Promise.resolve());
|
|
4598
|
+
const chat = (0, import_react17.useChat)({
|
|
4209
4599
|
transport,
|
|
4210
4600
|
resume: options.resumeRunId !== void 0 || autoResume,
|
|
4211
4601
|
...options.threadId !== void 0 ? {
|
|
@@ -4253,7 +4643,7 @@ function useAgentChat(options) {
|
|
|
4253
4643
|
}
|
|
4254
4644
|
}, "onFinish")
|
|
4255
4645
|
});
|
|
4256
|
-
const chatRef = (0,
|
|
4646
|
+
const chatRef = (0, import_react18.useRef)(chat);
|
|
4257
4647
|
chatRef.current = chat;
|
|
4258
4648
|
async function resyncFromThread() {
|
|
4259
4649
|
const threadId = latest.current.threadId ?? createdThreadId.current;
|
|
@@ -4265,11 +4655,13 @@ function useAgentChat(options) {
|
|
|
4265
4655
|
}
|
|
4266
4656
|
}
|
|
4267
4657
|
__name(resyncFromThread, "resyncFromThread");
|
|
4268
|
-
const turnInFlight = (0,
|
|
4269
|
-
const isTurnInFlight = (0,
|
|
4658
|
+
const turnInFlight = (0, import_react18.useRef)(false);
|
|
4659
|
+
const isTurnInFlight = (0, import_react18.useCallback)(() => turnInFlight.current || transport.isAttemptLive, [
|
|
4270
4660
|
transport
|
|
4271
4661
|
]);
|
|
4272
|
-
const sendMessage = (0,
|
|
4662
|
+
const sendMessage = (0, import_react18.useCallback)(async (...args) => {
|
|
4663
|
+
const blocked = latest.current.blocked;
|
|
4664
|
+
if (blocked != null) throw new QuotaBlockedError(blocked);
|
|
4273
4665
|
if (isTurnInFlight()) return;
|
|
4274
4666
|
turnInFlight.current = true;
|
|
4275
4667
|
try {
|
|
@@ -4280,15 +4672,15 @@ function useAgentChat(options) {
|
|
|
4280
4672
|
}, [
|
|
4281
4673
|
isTurnInFlight
|
|
4282
4674
|
]);
|
|
4283
|
-
const addToolResult = (0,
|
|
4675
|
+
const addToolResult = (0, import_react18.useCallback)(({ tool, toolCallId, output }) => chatRef.current.addToolResult({
|
|
4284
4676
|
tool,
|
|
4285
4677
|
toolCallId,
|
|
4286
4678
|
output
|
|
4287
4679
|
}), []);
|
|
4288
|
-
const [threads, setThreads] = (0,
|
|
4289
|
-
const [quota, setQuota] = (0,
|
|
4290
|
-
const [backgroundRuns, setBackgroundRuns] = (0,
|
|
4291
|
-
const refreshBackground = (0,
|
|
4680
|
+
const [threads, setThreads] = (0, import_react18.useState)([]);
|
|
4681
|
+
const [quota, setQuota] = (0, import_react18.useState)(null);
|
|
4682
|
+
const [backgroundRuns, setBackgroundRuns] = (0, import_react18.useState)([]);
|
|
4683
|
+
const refreshBackground = (0, import_react18.useCallback)(async () => {
|
|
4292
4684
|
const threadId = latest.current.threadId ?? createdThreadId.current;
|
|
4293
4685
|
if (threadId === void 0) {
|
|
4294
4686
|
return;
|
|
@@ -4313,7 +4705,7 @@ function useAgentChat(options) {
|
|
|
4313
4705
|
]);
|
|
4314
4706
|
backgroundRef.current = refreshBackground;
|
|
4315
4707
|
const isWorking = backgroundRuns.some((run) => run.status === "running");
|
|
4316
|
-
(0,
|
|
4708
|
+
(0, import_react18.useEffect)(() => {
|
|
4317
4709
|
if (options.background !== true || options.threadId === void 0) {
|
|
4318
4710
|
return;
|
|
4319
4711
|
}
|
|
@@ -4323,7 +4715,7 @@ function useAgentChat(options) {
|
|
|
4323
4715
|
options.threadId,
|
|
4324
4716
|
refreshBackground
|
|
4325
4717
|
]);
|
|
4326
|
-
(0,
|
|
4718
|
+
(0, import_react18.useEffect)(() => {
|
|
4327
4719
|
const every = latest.current.backgroundPollMs ?? 5e3;
|
|
4328
4720
|
if (latest.current.background !== true || !isWorking || every <= 0) {
|
|
4329
4721
|
return;
|
|
@@ -4334,26 +4726,26 @@ function useAgentChat(options) {
|
|
|
4334
4726
|
isWorking,
|
|
4335
4727
|
refreshBackground
|
|
4336
4728
|
]);
|
|
4337
|
-
const loadThreads = (0,
|
|
4729
|
+
const loadThreads = (0, import_react18.useCallback)(async () => {
|
|
4338
4730
|
const list = await client.listThreads();
|
|
4339
4731
|
setThreads(list);
|
|
4340
4732
|
return list;
|
|
4341
4733
|
}, [
|
|
4342
4734
|
client
|
|
4343
4735
|
]);
|
|
4344
|
-
const loadThread = (0,
|
|
4736
|
+
const loadThread = (0, import_react18.useCallback)((id) => client.getThread(id), [
|
|
4345
4737
|
client
|
|
4346
4738
|
]);
|
|
4347
|
-
const deleteThread = (0,
|
|
4739
|
+
const deleteThread = (0, import_react18.useCallback)(async (id) => {
|
|
4348
4740
|
await client.deleteThread(id);
|
|
4349
4741
|
setThreads((current) => current.filter((thread) => thread.id !== id));
|
|
4350
4742
|
}, [
|
|
4351
4743
|
client
|
|
4352
4744
|
]);
|
|
4353
|
-
const forkThread = (0,
|
|
4745
|
+
const forkThread = (0, import_react18.useCallback)((threadId, messageId) => requireBackendMethod(client, "forkFromMessage")(threadId, messageId), [
|
|
4354
4746
|
client
|
|
4355
4747
|
]);
|
|
4356
|
-
const renameThread = (0,
|
|
4748
|
+
const renameThread = (0, import_react18.useCallback)(async (id, title) => {
|
|
4357
4749
|
await client.updateThread(id, {
|
|
4358
4750
|
title
|
|
4359
4751
|
});
|
|
@@ -4364,24 +4756,24 @@ function useAgentChat(options) {
|
|
|
4364
4756
|
}, [
|
|
4365
4757
|
client
|
|
4366
4758
|
]);
|
|
4367
|
-
const promoteThread = (0,
|
|
4759
|
+
const promoteThread = (0, import_react18.useCallback)(async (id) => {
|
|
4368
4760
|
await requireBackendMethod(client, "promoteThread")(id);
|
|
4369
4761
|
await loadThreads();
|
|
4370
4762
|
}, [
|
|
4371
4763
|
client,
|
|
4372
4764
|
loadThreads
|
|
4373
4765
|
]);
|
|
4374
|
-
const truncateFromMessage = (0,
|
|
4766
|
+
const truncateFromMessage = (0, import_react18.useCallback)((threadId, messageId) => requireBackendMethod(client, "truncateFromMessage")(threadId, messageId).then(() => void 0), [
|
|
4375
4767
|
client
|
|
4376
4768
|
]);
|
|
4377
|
-
const loadQuota = (0,
|
|
4769
|
+
const loadQuota = (0, import_react18.useCallback)(async () => {
|
|
4378
4770
|
const today = await requireBackendMethod(client, "getQuotaToday")();
|
|
4379
4771
|
setQuota(today);
|
|
4380
4772
|
return today;
|
|
4381
4773
|
}, [
|
|
4382
4774
|
client
|
|
4383
4775
|
]);
|
|
4384
|
-
const cancel = (0,
|
|
4776
|
+
const cancel = (0, import_react18.useCallback)(async () => {
|
|
4385
4777
|
chatRef.current.stop();
|
|
4386
4778
|
const activeRunId2 = runIdRef.current;
|
|
4387
4779
|
if (activeRunId2) {
|
|
@@ -4393,7 +4785,7 @@ function useAgentChat(options) {
|
|
|
4393
4785
|
}, [
|
|
4394
4786
|
client
|
|
4395
4787
|
]);
|
|
4396
|
-
const approve = (0,
|
|
4788
|
+
const approve = (0, import_react18.useCallback)(async ({ toolCallId, remember, via }) => {
|
|
4397
4789
|
await requireBackendMethod(client, "approveToolCall")({
|
|
4398
4790
|
toolCallId,
|
|
4399
4791
|
...remember === true ? {
|
|
@@ -4406,7 +4798,7 @@ function useAgentChat(options) {
|
|
|
4406
4798
|
}, [
|
|
4407
4799
|
client
|
|
4408
4800
|
]);
|
|
4409
|
-
const reject = (0,
|
|
4801
|
+
const reject = (0, import_react18.useCallback)(async ({ toolCallId, reason, via }) => {
|
|
4410
4802
|
await requireBackendMethod(client, "rejectToolCall")({
|
|
4411
4803
|
toolCallId,
|
|
4412
4804
|
...reason !== void 0 ? {
|
|
@@ -4419,7 +4811,7 @@ function useAgentChat(options) {
|
|
|
4419
4811
|
}, [
|
|
4420
4812
|
client
|
|
4421
4813
|
]);
|
|
4422
|
-
const answer = (0,
|
|
4814
|
+
const answer = (0, import_react18.useCallback)(async ({ toolCallId, answers }) => {
|
|
4423
4815
|
await requireBackendMethod(client, "answerToolCall")({
|
|
4424
4816
|
toolCallId,
|
|
4425
4817
|
...answers !== void 0 ? {
|
|
@@ -4429,14 +4821,16 @@ function useAgentChat(options) {
|
|
|
4429
4821
|
}, [
|
|
4430
4822
|
client
|
|
4431
4823
|
]);
|
|
4432
|
-
const skip = (0,
|
|
4824
|
+
const skip = (0, import_react18.useCallback)(async ({ toolCallId }) => {
|
|
4433
4825
|
await requireBackendMethod(client, "skipToolCall")({
|
|
4434
4826
|
toolCallId
|
|
4435
4827
|
});
|
|
4436
4828
|
}, [
|
|
4437
4829
|
client
|
|
4438
4830
|
]);
|
|
4439
|
-
const regenerate = (0,
|
|
4831
|
+
const regenerate = (0, import_react18.useCallback)(() => {
|
|
4832
|
+
const blocked = latest.current.blocked;
|
|
4833
|
+
if (blocked != null) throw new QuotaBlockedError(blocked);
|
|
4440
4834
|
if (isTurnInFlight()) return;
|
|
4441
4835
|
regenerateNext.current = true;
|
|
4442
4836
|
turnInFlight.current = true;
|
|
@@ -4451,7 +4845,7 @@ function useAgentChat(options) {
|
|
|
4451
4845
|
isWorking,
|
|
4452
4846
|
refresh: refreshBackground
|
|
4453
4847
|
};
|
|
4454
|
-
const setThreadModel = (0,
|
|
4848
|
+
const setThreadModel = (0, import_react18.useCallback)(async (model) => {
|
|
4455
4849
|
const threadId = latest.current.threadId ?? createdThreadId.current;
|
|
4456
4850
|
if (threadId === void 0) {
|
|
4457
4851
|
throw new Error("setThreadModel: this chat has no thread yet");
|
|
@@ -4465,7 +4859,7 @@ function useAgentChat(options) {
|
|
|
4465
4859
|
}, [
|
|
4466
4860
|
client
|
|
4467
4861
|
]);
|
|
4468
|
-
const getThreadId = (0,
|
|
4862
|
+
const getThreadId = (0, import_react18.useCallback)(() => latest.current.threadId ?? createdThreadId.current, []);
|
|
4469
4863
|
const status = connection.status === "reconnecting" ? "reconnecting" : chat.status;
|
|
4470
4864
|
return {
|
|
4471
4865
|
...chat,
|
|
@@ -4508,6 +4902,16 @@ function useAgentChat(options) {
|
|
|
4508
4902
|
};
|
|
4509
4903
|
}
|
|
4510
4904
|
__name(useAgentChat, "useAgentChat");
|
|
4905
|
+
var QuotaBlockedError = class extends Error {
|
|
4906
|
+
static {
|
|
4907
|
+
__name(this, "QuotaBlockedError");
|
|
4908
|
+
}
|
|
4909
|
+
block;
|
|
4910
|
+
constructor(block) {
|
|
4911
|
+
super(block.reason ?? `The ${block.period === "day" ? "daily" : "monthly"} quota is used up`), this.block = block;
|
|
4912
|
+
this.name = "QuotaBlockedError";
|
|
4913
|
+
}
|
|
4914
|
+
};
|
|
4511
4915
|
async function mergeHeaders(options) {
|
|
4512
4916
|
const dynamic = await options.getHeaders?.() ?? {};
|
|
4513
4917
|
return {
|
|
@@ -4527,7 +4931,9 @@ __name(mergeHeaders, "mergeHeaders");
|
|
|
4527
4931
|
MessageItem,
|
|
4528
4932
|
MessageItemView,
|
|
4529
4933
|
MessageList,
|
|
4934
|
+
QuotaBlockedError,
|
|
4530
4935
|
SPEECH_LANGUAGES,
|
|
4936
|
+
acceptsFile,
|
|
4531
4937
|
applyCompletion,
|
|
4532
4938
|
approvalCountdown,
|
|
4533
4939
|
backgroundRunsFromThread,
|
|
@@ -4538,7 +4944,10 @@ __name(mergeHeaders, "mergeHeaders");
|
|
|
4538
4944
|
describeTimestamp,
|
|
4539
4945
|
describeToolCall,
|
|
4540
4946
|
describeUsage,
|
|
4947
|
+
dragHasFiles,
|
|
4541
4948
|
extractMessageText,
|
|
4949
|
+
fileKind,
|
|
4950
|
+
filesFromClipboard,
|
|
4542
4951
|
fillTemplate,
|
|
4543
4952
|
filterAutocompleteItems,
|
|
4544
4953
|
findActiveTrigger,
|
|
@@ -4548,6 +4957,7 @@ __name(mergeHeaders, "mergeHeaders");
|
|
|
4548
4957
|
inferResultView,
|
|
4549
4958
|
isActionCall,
|
|
4550
4959
|
loadStoredSpeechLang,
|
|
4960
|
+
messageFiles,
|
|
4551
4961
|
notifyThreads,
|
|
4552
4962
|
onThreadsEvent,
|
|
4553
4963
|
persistSpeechLang,
|
|
@@ -4563,11 +4973,13 @@ __name(mergeHeaders, "mergeHeaders");
|
|
|
4563
4973
|
useAgentChat,
|
|
4564
4974
|
useAgents,
|
|
4565
4975
|
useApprovalCountdown,
|
|
4976
|
+
useAttachments,
|
|
4566
4977
|
useChatTranscript,
|
|
4567
4978
|
useComposerAutocomplete,
|
|
4568
4979
|
useElapsed,
|
|
4569
4980
|
useMessageFeedback,
|
|
4570
4981
|
useModels,
|
|
4982
|
+
useQuota,
|
|
4571
4983
|
useSpeechRecognition,
|
|
4572
4984
|
useStickToBottom,
|
|
4573
4985
|
useThreads,
|