@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.js
CHANGED
|
@@ -125,6 +125,9 @@ var AgentClient = class {
|
|
|
125
125
|
* what a caller then rides on `sendMessage({ text }, { body: { attachments: [...] } })`.
|
|
126
126
|
*/
|
|
127
127
|
async uploadAttachment(file, options = {}) {
|
|
128
|
+
if (options.onProgress !== void 0 && this.options.fetch === void 0 && typeof XMLHttpRequest !== "undefined") {
|
|
129
|
+
return this.uploadWithProgress(file, options);
|
|
130
|
+
}
|
|
128
131
|
const formData = new FormData();
|
|
129
132
|
formData.append("file", file);
|
|
130
133
|
const response = await this.fetchImpl()(`${this.baseUrl()}/agent/attachments`, {
|
|
@@ -139,7 +142,47 @@ var AgentClient = class {
|
|
|
139
142
|
signal: options.signal
|
|
140
143
|
} : {}
|
|
141
144
|
});
|
|
142
|
-
|
|
145
|
+
const attachment = await this.handleResponse(response, "POST", "/agent/attachments");
|
|
146
|
+
options.onProgress?.(1);
|
|
147
|
+
return attachment;
|
|
148
|
+
}
|
|
149
|
+
async uploadWithProgress(file, { signal, onProgress }) {
|
|
150
|
+
const headers = {
|
|
151
|
+
accept: "application/json",
|
|
152
|
+
...await this.resolveHeaders()
|
|
153
|
+
};
|
|
154
|
+
const url = `${this.baseUrl()}/agent/attachments`;
|
|
155
|
+
return new Promise((resolve, reject) => {
|
|
156
|
+
const xhr = new XMLHttpRequest();
|
|
157
|
+
xhr.open("POST", url);
|
|
158
|
+
for (const [name, value] of Object.entries(headers)) xhr.setRequestHeader(name, value);
|
|
159
|
+
xhr.withCredentials = this.options.credentials === "include";
|
|
160
|
+
xhr.upload.onprogress = (event) => {
|
|
161
|
+
if (event.lengthComputable && event.total > 0) onProgress?.(event.loaded / event.total);
|
|
162
|
+
};
|
|
163
|
+
xhr.onload = () => {
|
|
164
|
+
if (xhr.status < 200 || xhr.status >= 300) {
|
|
165
|
+
reject(new AgentHttpError(xhr.status, "POST", "/agent/attachments", xhr.statusText));
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
onProgress?.(1);
|
|
169
|
+
resolve(JSON.parse(xhr.responseText));
|
|
170
|
+
};
|
|
171
|
+
xhr.onerror = () => reject(new TypeError("Network error while uploading the attachment"));
|
|
172
|
+
xhr.onabort = () => reject(new DOMException("The upload was aborted", "AbortError"));
|
|
173
|
+
if (signal !== void 0) {
|
|
174
|
+
if (signal.aborted) {
|
|
175
|
+
reject(new DOMException("The upload was aborted", "AbortError"));
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
signal.addEventListener("abort", () => xhr.abort(), {
|
|
179
|
+
once: true
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
const formData = new FormData();
|
|
183
|
+
formData.append("file", file);
|
|
184
|
+
xhr.send(formData);
|
|
185
|
+
});
|
|
143
186
|
}
|
|
144
187
|
promoteThread(id) {
|
|
145
188
|
return this.request("POST", `/agent/threads/${encodeURIComponent(id)}/promote`);
|
|
@@ -156,6 +199,10 @@ var AgentClient = class {
|
|
|
156
199
|
listAgents() {
|
|
157
200
|
return this.request("GET", "/agent/agents");
|
|
158
201
|
}
|
|
202
|
+
/** `GET /agent/quota` — the caller's budget windows and the one blocking sends, if any. */
|
|
203
|
+
getQuota() {
|
|
204
|
+
return this.request("GET", "/agent/quota");
|
|
205
|
+
}
|
|
159
206
|
getQuotaToday() {
|
|
160
207
|
return this.request("GET", "/agent/quota/today");
|
|
161
208
|
}
|
|
@@ -983,6 +1030,68 @@ function delay(ms, signal) {
|
|
|
983
1030
|
}
|
|
984
1031
|
__name(delay, "delay");
|
|
985
1032
|
|
|
1033
|
+
// src/attachments/files.ts
|
|
1034
|
+
function fileKind(mediaType) {
|
|
1035
|
+
const type = mediaType.toLowerCase();
|
|
1036
|
+
if (type.startsWith("image/")) return "image";
|
|
1037
|
+
if (type === "application/pdf") return "pdf";
|
|
1038
|
+
if (type.startsWith("text/") || type === "application/json") return "text";
|
|
1039
|
+
if (type.startsWith("audio/")) return "audio";
|
|
1040
|
+
if (type.startsWith("video/")) return "video";
|
|
1041
|
+
return "other";
|
|
1042
|
+
}
|
|
1043
|
+
__name(fileKind, "fileKind");
|
|
1044
|
+
function messageFiles(message) {
|
|
1045
|
+
const files = [];
|
|
1046
|
+
for (const part of message.parts) {
|
|
1047
|
+
if (part.type !== "file") continue;
|
|
1048
|
+
const file = part;
|
|
1049
|
+
const filename = file.filename ?? null;
|
|
1050
|
+
const dot = filename?.lastIndexOf(".") ?? -1;
|
|
1051
|
+
const mediaId = file.providerMetadata?.agent?.mediaId;
|
|
1052
|
+
files.push({
|
|
1053
|
+
url: file.url,
|
|
1054
|
+
mediaType: file.mediaType,
|
|
1055
|
+
filename,
|
|
1056
|
+
kind: fileKind(file.mediaType),
|
|
1057
|
+
extension: filename !== null && dot > 0 ? filename.slice(dot + 1).toLowerCase() : null,
|
|
1058
|
+
mediaId: typeof mediaId === "string" ? mediaId : null
|
|
1059
|
+
});
|
|
1060
|
+
}
|
|
1061
|
+
return files;
|
|
1062
|
+
}
|
|
1063
|
+
__name(messageFiles, "messageFiles");
|
|
1064
|
+
function acceptsFile(accept, file) {
|
|
1065
|
+
const rules = (typeof accept === "string" ? accept.split(",") : accept ?? []).map((rule) => rule.trim().toLowerCase()).filter((rule) => rule.length > 0);
|
|
1066
|
+
if (rules.length === 0) return true;
|
|
1067
|
+
const type = file.type.toLowerCase();
|
|
1068
|
+
const name = file.name.toLowerCase();
|
|
1069
|
+
return rules.some((rule) => {
|
|
1070
|
+
if (rule.startsWith(".")) return name.endsWith(rule);
|
|
1071
|
+
if (rule.endsWith("/*")) return type.startsWith(rule.slice(0, -1));
|
|
1072
|
+
return type === rule;
|
|
1073
|
+
});
|
|
1074
|
+
}
|
|
1075
|
+
__name(acceptsFile, "acceptsFile");
|
|
1076
|
+
function filesFromClipboard(data) {
|
|
1077
|
+
if (!data) return [];
|
|
1078
|
+
const files = [];
|
|
1079
|
+
for (const item of Array.from(data.items ?? [])) {
|
|
1080
|
+
if (item.kind !== "file") continue;
|
|
1081
|
+
const file = item.getAsFile();
|
|
1082
|
+
if (file !== null) files.push(file);
|
|
1083
|
+
}
|
|
1084
|
+
return files.length > 0 ? files : Array.from(data.files ?? []);
|
|
1085
|
+
}
|
|
1086
|
+
__name(filesFromClipboard, "filesFromClipboard");
|
|
1087
|
+
function dragHasFiles(data) {
|
|
1088
|
+
return Array.from(data?.types ?? []).includes("Files");
|
|
1089
|
+
}
|
|
1090
|
+
__name(dragHasFiles, "dragHasFiles");
|
|
1091
|
+
|
|
1092
|
+
// src/attachments/use-attachments.ts
|
|
1093
|
+
import { useCallback, useEffect as useEffect2, useMemo, useRef as useRef2, useState as useState2 } from "react";
|
|
1094
|
+
|
|
986
1095
|
// src/backend.ts
|
|
987
1096
|
var AgentBackendUnsupportedError = class extends Error {
|
|
988
1097
|
static {
|
|
@@ -1003,19 +1112,239 @@ function requireBackendMethod(backend, name) {
|
|
|
1003
1112
|
}
|
|
1004
1113
|
__name(requireBackendMethod, "requireBackendMethod");
|
|
1005
1114
|
|
|
1115
|
+
// src/attachments/use-attachments.ts
|
|
1116
|
+
var DEFAULT_REJECTION = {
|
|
1117
|
+
type: /* @__PURE__ */ __name((file) => `${file.name} is not a supported file type`, "type"),
|
|
1118
|
+
size: /* @__PURE__ */ __name((file) => `${file.name} is too large`, "size"),
|
|
1119
|
+
count: /* @__PURE__ */ __name(() => "Too many files", "count")
|
|
1120
|
+
};
|
|
1121
|
+
var sequence = 0;
|
|
1122
|
+
function useAttachments(options) {
|
|
1123
|
+
const latest = useRef2(options);
|
|
1124
|
+
latest.current = options;
|
|
1125
|
+
const [items, setItems] = useState2([]);
|
|
1126
|
+
const itemsRef = useRef2(items);
|
|
1127
|
+
itemsRef.current = items;
|
|
1128
|
+
const controllers = useRef2(/* @__PURE__ */ new Map());
|
|
1129
|
+
const [dragDepth, setDragDepth] = useState2(0);
|
|
1130
|
+
const patch = useCallback((id, change) => {
|
|
1131
|
+
setItems((current) => current.map((item) => item.id === id ? {
|
|
1132
|
+
...item,
|
|
1133
|
+
...change
|
|
1134
|
+
} : item));
|
|
1135
|
+
}, []);
|
|
1136
|
+
const start = useCallback((item) => {
|
|
1137
|
+
const { upload, backend } = latest.current;
|
|
1138
|
+
const run = upload ?? (backend?.uploadAttachment !== void 0 ? backend.uploadAttachment.bind(backend) : void 0);
|
|
1139
|
+
if (run === void 0) {
|
|
1140
|
+
patch(item.id, {
|
|
1141
|
+
status: "error",
|
|
1142
|
+
error: new AgentBackendUnsupportedError("uploadAttachment").message
|
|
1143
|
+
});
|
|
1144
|
+
return;
|
|
1145
|
+
}
|
|
1146
|
+
const controller = new AbortController();
|
|
1147
|
+
controllers.current.set(item.id, controller);
|
|
1148
|
+
run(item.file, {
|
|
1149
|
+
signal: controller.signal,
|
|
1150
|
+
onProgress: /* @__PURE__ */ __name((fraction) => patch(item.id, {
|
|
1151
|
+
progress: Math.max(0, Math.min(1, fraction))
|
|
1152
|
+
}), "onProgress")
|
|
1153
|
+
}).then((attachment) => {
|
|
1154
|
+
if (controller.signal.aborted) return;
|
|
1155
|
+
controllers.current.delete(item.id);
|
|
1156
|
+
patch(item.id, {
|
|
1157
|
+
status: "ready",
|
|
1158
|
+
progress: 1,
|
|
1159
|
+
attachment
|
|
1160
|
+
});
|
|
1161
|
+
}, (error) => {
|
|
1162
|
+
if (controller.signal.aborted) return;
|
|
1163
|
+
controllers.current.delete(item.id);
|
|
1164
|
+
patch(item.id, {
|
|
1165
|
+
status: "error",
|
|
1166
|
+
error: error instanceof Error ? error.message : String(error)
|
|
1167
|
+
});
|
|
1168
|
+
});
|
|
1169
|
+
}, [
|
|
1170
|
+
patch
|
|
1171
|
+
]);
|
|
1172
|
+
const add = useCallback((files) => {
|
|
1173
|
+
if (files == null) return;
|
|
1174
|
+
const { accept: accept2, maxBytes, maxFiles, describeRejection } = latest.current;
|
|
1175
|
+
const describe = /* @__PURE__ */ __name((reason, file) => describeRejection?.(reason, file) ?? DEFAULT_REJECTION[reason](file), "describe");
|
|
1176
|
+
let room = maxFiles === void 0 ? Number.POSITIVE_INFINITY : maxFiles - itemsRef.current.filter((item) => item.status !== "rejected").length;
|
|
1177
|
+
const staged = [];
|
|
1178
|
+
for (const file of Array.from(files)) {
|
|
1179
|
+
sequence += 1;
|
|
1180
|
+
const base = {
|
|
1181
|
+
id: `att-${sequence}`,
|
|
1182
|
+
file,
|
|
1183
|
+
name: file.name,
|
|
1184
|
+
size: file.size,
|
|
1185
|
+
type: file.type,
|
|
1186
|
+
progress: 0
|
|
1187
|
+
};
|
|
1188
|
+
const reason = !acceptsFile(accept2, file) ? "type" : maxBytes !== void 0 && file.size > maxBytes ? "size" : room <= 0 ? "count" : void 0;
|
|
1189
|
+
if (reason !== void 0) {
|
|
1190
|
+
staged.push({
|
|
1191
|
+
...base,
|
|
1192
|
+
status: "rejected",
|
|
1193
|
+
error: describe(reason, file)
|
|
1194
|
+
});
|
|
1195
|
+
continue;
|
|
1196
|
+
}
|
|
1197
|
+
room -= 1;
|
|
1198
|
+
const previewUrl = file.type.startsWith("image/") && typeof URL.createObjectURL === "function" ? URL.createObjectURL(file) : void 0;
|
|
1199
|
+
staged.push({
|
|
1200
|
+
...base,
|
|
1201
|
+
status: "uploading",
|
|
1202
|
+
...previewUrl ? {
|
|
1203
|
+
previewUrl
|
|
1204
|
+
} : {}
|
|
1205
|
+
});
|
|
1206
|
+
}
|
|
1207
|
+
if (staged.length === 0) return;
|
|
1208
|
+
setItems((current) => [
|
|
1209
|
+
...current,
|
|
1210
|
+
...staged
|
|
1211
|
+
]);
|
|
1212
|
+
for (const item of staged) {
|
|
1213
|
+
if (item.status === "uploading") start(item);
|
|
1214
|
+
}
|
|
1215
|
+
}, [
|
|
1216
|
+
start
|
|
1217
|
+
]);
|
|
1218
|
+
const release = useCallback((item) => {
|
|
1219
|
+
if (item === void 0) return;
|
|
1220
|
+
controllers.current.get(item.id)?.abort();
|
|
1221
|
+
controllers.current.delete(item.id);
|
|
1222
|
+
if (item.previewUrl !== void 0 && typeof URL.revokeObjectURL === "function") {
|
|
1223
|
+
URL.revokeObjectURL(item.previewUrl);
|
|
1224
|
+
}
|
|
1225
|
+
}, []);
|
|
1226
|
+
const remove = useCallback((id) => {
|
|
1227
|
+
release(itemsRef.current.find((item) => item.id === id));
|
|
1228
|
+
setItems((current) => current.filter((item) => item.id !== id));
|
|
1229
|
+
}, [
|
|
1230
|
+
release
|
|
1231
|
+
]);
|
|
1232
|
+
const clear = useCallback(() => {
|
|
1233
|
+
for (const item of itemsRef.current) release(item);
|
|
1234
|
+
setItems([]);
|
|
1235
|
+
}, [
|
|
1236
|
+
release
|
|
1237
|
+
]);
|
|
1238
|
+
const retry = useCallback((id) => {
|
|
1239
|
+
const item = itemsRef.current.find((candidate) => candidate.id === id);
|
|
1240
|
+
if (item === void 0 || item.status !== "error") return;
|
|
1241
|
+
const { error: _previous, ...rest } = item;
|
|
1242
|
+
const again = {
|
|
1243
|
+
...rest,
|
|
1244
|
+
status: "uploading",
|
|
1245
|
+
progress: 0
|
|
1246
|
+
};
|
|
1247
|
+
setItems((current) => current.map((candidate) => candidate.id === id ? again : candidate));
|
|
1248
|
+
start(again);
|
|
1249
|
+
}, [
|
|
1250
|
+
start
|
|
1251
|
+
]);
|
|
1252
|
+
useEffect2(() => () => {
|
|
1253
|
+
for (const item of itemsRef.current) release(item);
|
|
1254
|
+
}, [
|
|
1255
|
+
release
|
|
1256
|
+
]);
|
|
1257
|
+
const onPaste = useCallback((event) => {
|
|
1258
|
+
const files = filesFromClipboard(event.clipboardData);
|
|
1259
|
+
if (files.length === 0) return;
|
|
1260
|
+
event.preventDefault();
|
|
1261
|
+
add(files);
|
|
1262
|
+
}, [
|
|
1263
|
+
add
|
|
1264
|
+
]);
|
|
1265
|
+
const dropZoneProps = useMemo(() => ({
|
|
1266
|
+
onDragEnter: /* @__PURE__ */ __name((event) => {
|
|
1267
|
+
if (!dragHasFiles(event.dataTransfer)) return;
|
|
1268
|
+
event.preventDefault();
|
|
1269
|
+
setDragDepth((depth) => depth + 1);
|
|
1270
|
+
}, "onDragEnter"),
|
|
1271
|
+
onDragOver: /* @__PURE__ */ __name((event) => {
|
|
1272
|
+
if (dragHasFiles(event.dataTransfer)) event.preventDefault();
|
|
1273
|
+
}, "onDragOver"),
|
|
1274
|
+
onDragLeave: /* @__PURE__ */ __name((event) => {
|
|
1275
|
+
if (!dragHasFiles(event.dataTransfer)) return;
|
|
1276
|
+
setDragDepth((depth) => Math.max(0, depth - 1));
|
|
1277
|
+
}, "onDragLeave"),
|
|
1278
|
+
onDrop: /* @__PURE__ */ __name((event) => {
|
|
1279
|
+
if (!dragHasFiles(event.dataTransfer)) return;
|
|
1280
|
+
event.preventDefault();
|
|
1281
|
+
setDragDepth(0);
|
|
1282
|
+
add(event.dataTransfer?.files);
|
|
1283
|
+
}, "onDrop")
|
|
1284
|
+
}), [
|
|
1285
|
+
add
|
|
1286
|
+
]);
|
|
1287
|
+
const accept = options.accept;
|
|
1288
|
+
const inputProps = useMemo(() => ({
|
|
1289
|
+
type: "file",
|
|
1290
|
+
accept: typeof accept === "string" ? accept : accept?.join(","),
|
|
1291
|
+
multiple: options.maxFiles === void 0 || options.maxFiles > 1,
|
|
1292
|
+
onChange: /* @__PURE__ */ __name((event) => {
|
|
1293
|
+
const input = event.currentTarget;
|
|
1294
|
+
add(input.files);
|
|
1295
|
+
input.value = "";
|
|
1296
|
+
}, "onChange")
|
|
1297
|
+
}), [
|
|
1298
|
+
accept,
|
|
1299
|
+
options.maxFiles,
|
|
1300
|
+
add
|
|
1301
|
+
]);
|
|
1302
|
+
return useMemo(() => {
|
|
1303
|
+
const ready = items.filter((item) => item.status === "ready" && item.attachment !== void 0);
|
|
1304
|
+
const attachments = ready.map((item) => item.attachment);
|
|
1305
|
+
return {
|
|
1306
|
+
items,
|
|
1307
|
+
add,
|
|
1308
|
+
remove,
|
|
1309
|
+
retry,
|
|
1310
|
+
clear,
|
|
1311
|
+
isUploading: items.some((item) => item.status === "uploading"),
|
|
1312
|
+
attachments,
|
|
1313
|
+
refs: attachments.map((attachment) => ({
|
|
1314
|
+
mediaId: attachment.mediaId
|
|
1315
|
+
})),
|
|
1316
|
+
inputProps,
|
|
1317
|
+
dropZoneProps,
|
|
1318
|
+
isDragging: dragDepth > 0,
|
|
1319
|
+
onPaste
|
|
1320
|
+
};
|
|
1321
|
+
}, [
|
|
1322
|
+
items,
|
|
1323
|
+
add,
|
|
1324
|
+
remove,
|
|
1325
|
+
retry,
|
|
1326
|
+
clear,
|
|
1327
|
+
inputProps,
|
|
1328
|
+
dropZoneProps,
|
|
1329
|
+
dragDepth,
|
|
1330
|
+
onPaste
|
|
1331
|
+
]);
|
|
1332
|
+
}
|
|
1333
|
+
__name(useAttachments, "useAttachments");
|
|
1334
|
+
|
|
1006
1335
|
// src/catalog/use-agents.ts
|
|
1007
|
-
import { useMemo } from "react";
|
|
1336
|
+
import { useMemo as useMemo2 } from "react";
|
|
1008
1337
|
|
|
1009
1338
|
// src/catalog/use-resource.ts
|
|
1010
|
-
import { useCallback, useEffect as
|
|
1339
|
+
import { useCallback as useCallback2, useEffect as useEffect3, useRef as useRef3, useState as useState3 } from "react";
|
|
1011
1340
|
function useResource(load2, key, enabled) {
|
|
1012
|
-
const [data, setData] =
|
|
1013
|
-
const [isLoading, setIsLoading] =
|
|
1014
|
-
const [error, setError] =
|
|
1015
|
-
const loadRef =
|
|
1341
|
+
const [data, setData] = useState3(void 0);
|
|
1342
|
+
const [isLoading, setIsLoading] = useState3(enabled);
|
|
1343
|
+
const [error, setError] = useState3(null);
|
|
1344
|
+
const loadRef = useRef3(load2);
|
|
1016
1345
|
loadRef.current = load2;
|
|
1017
|
-
const generation =
|
|
1018
|
-
const refresh =
|
|
1346
|
+
const generation = useRef3(0);
|
|
1347
|
+
const refresh = useCallback2(async () => {
|
|
1019
1348
|
const mine = ++generation.current;
|
|
1020
1349
|
setIsLoading(true);
|
|
1021
1350
|
try {
|
|
@@ -1030,7 +1359,7 @@ function useResource(load2, key, enabled) {
|
|
|
1030
1359
|
if (mine === generation.current) setIsLoading(false);
|
|
1031
1360
|
}
|
|
1032
1361
|
}, []);
|
|
1033
|
-
|
|
1362
|
+
useEffect3(() => {
|
|
1034
1363
|
if (!enabled) return;
|
|
1035
1364
|
void refresh();
|
|
1036
1365
|
}, [
|
|
@@ -1051,7 +1380,7 @@ __name(useResource, "useResource");
|
|
|
1051
1380
|
function useAgents(options) {
|
|
1052
1381
|
const { backend, enabled = true } = options;
|
|
1053
1382
|
const { data, isLoading, error, refresh } = useResource(() => requireBackendMethod(backend, "listAgents")(), "", enabled);
|
|
1054
|
-
return
|
|
1383
|
+
return useMemo2(() => {
|
|
1055
1384
|
const agents = data ?? [];
|
|
1056
1385
|
return {
|
|
1057
1386
|
agents,
|
|
@@ -1070,11 +1399,11 @@ function useAgents(options) {
|
|
|
1070
1399
|
__name(useAgents, "useAgents");
|
|
1071
1400
|
|
|
1072
1401
|
// src/catalog/use-models.ts
|
|
1073
|
-
import { useMemo as
|
|
1402
|
+
import { useMemo as useMemo3 } from "react";
|
|
1074
1403
|
function useModels(options) {
|
|
1075
1404
|
const { backend, agent, enabled = true } = options;
|
|
1076
1405
|
const { data, isLoading, error, refresh } = useResource(() => requireBackendMethod(backend, "listModels")(agent), `${agent ?? ""}`, enabled);
|
|
1077
|
-
return
|
|
1406
|
+
return useMemo3(() => {
|
|
1078
1407
|
const providers = data?.providers ?? [];
|
|
1079
1408
|
const models = providers.flatMap((provider) => provider.models.map((model) => ({
|
|
1080
1409
|
...model,
|
|
@@ -1103,28 +1432,96 @@ function useModels(options) {
|
|
|
1103
1432
|
}
|
|
1104
1433
|
__name(useModels, "useModels");
|
|
1105
1434
|
|
|
1435
|
+
// src/quota/use-quota.ts
|
|
1436
|
+
import { useEffect as useEffect4, useMemo as useMemo4 } from "react";
|
|
1437
|
+
|
|
1438
|
+
// src/threads/threads-events.ts
|
|
1439
|
+
var listeners = /* @__PURE__ */ new WeakMap();
|
|
1440
|
+
function notifyThreads(backend, event) {
|
|
1441
|
+
for (const listener of listeners.get(backend) ?? []) {
|
|
1442
|
+
listener(event);
|
|
1443
|
+
}
|
|
1444
|
+
}
|
|
1445
|
+
__name(notifyThreads, "notifyThreads");
|
|
1446
|
+
function onThreadsEvent(backend, listener) {
|
|
1447
|
+
let set = listeners.get(backend);
|
|
1448
|
+
if (set === void 0) {
|
|
1449
|
+
set = /* @__PURE__ */ new Set();
|
|
1450
|
+
listeners.set(backend, set);
|
|
1451
|
+
}
|
|
1452
|
+
set.add(listener);
|
|
1453
|
+
return () => {
|
|
1454
|
+
set.delete(listener);
|
|
1455
|
+
};
|
|
1456
|
+
}
|
|
1457
|
+
__name(onThreadsEvent, "onThreadsEvent");
|
|
1458
|
+
|
|
1459
|
+
// src/quota/use-quota.ts
|
|
1460
|
+
function useQuota(options) {
|
|
1461
|
+
const { backend, enabled = true, pollMs } = options;
|
|
1462
|
+
const { data, isLoading, error, refresh } = useResource(() => requireBackendMethod(backend, "getQuota")(), "", enabled);
|
|
1463
|
+
useEffect4(() => {
|
|
1464
|
+
if (!enabled) return;
|
|
1465
|
+
return onThreadsEvent(backend, (event) => {
|
|
1466
|
+
if (event.type === "changed") void refresh();
|
|
1467
|
+
});
|
|
1468
|
+
}, [
|
|
1469
|
+
backend,
|
|
1470
|
+
enabled,
|
|
1471
|
+
refresh
|
|
1472
|
+
]);
|
|
1473
|
+
useEffect4(() => {
|
|
1474
|
+
if (!enabled || pollMs === void 0 || pollMs <= 0) return;
|
|
1475
|
+
const timer = setInterval(() => void refresh(), pollMs);
|
|
1476
|
+
return () => clearInterval(timer);
|
|
1477
|
+
}, [
|
|
1478
|
+
enabled,
|
|
1479
|
+
pollMs,
|
|
1480
|
+
refresh
|
|
1481
|
+
]);
|
|
1482
|
+
return useMemo4(() => {
|
|
1483
|
+
const windows = data?.windows ?? [];
|
|
1484
|
+
return {
|
|
1485
|
+
report: data,
|
|
1486
|
+
windows,
|
|
1487
|
+
day: windows.find((window2) => window2.period === "day"),
|
|
1488
|
+
month: windows.find((window2) => window2.period === "month"),
|
|
1489
|
+
blocked: data?.blocked ?? null,
|
|
1490
|
+
isLoading,
|
|
1491
|
+
error,
|
|
1492
|
+
refresh
|
|
1493
|
+
};
|
|
1494
|
+
}, [
|
|
1495
|
+
data,
|
|
1496
|
+
isLoading,
|
|
1497
|
+
error,
|
|
1498
|
+
refresh
|
|
1499
|
+
]);
|
|
1500
|
+
}
|
|
1501
|
+
__name(useQuota, "useQuota");
|
|
1502
|
+
|
|
1106
1503
|
// src/feedback/use-message-feedback.ts
|
|
1107
|
-
import { useCallback as
|
|
1504
|
+
import { useCallback as useCallback3, useRef as useRef4, useState as useState4 } from "react";
|
|
1108
1505
|
function useMessageFeedback(options) {
|
|
1109
|
-
const latest =
|
|
1506
|
+
const latest = useRef4(options);
|
|
1110
1507
|
latest.current = options;
|
|
1111
|
-
const [local, setLocal] =
|
|
1112
|
-
const [pending, setPending] =
|
|
1113
|
-
const [error, setError] =
|
|
1114
|
-
const localRef =
|
|
1508
|
+
const [local, setLocal] = useState4(/* @__PURE__ */ new Map());
|
|
1509
|
+
const [pending, setPending] = useState4(/* @__PURE__ */ new Set());
|
|
1510
|
+
const [error, setError] = useState4(null);
|
|
1511
|
+
const localRef = useRef4(local);
|
|
1115
1512
|
localRef.current = local;
|
|
1116
|
-
const resolved =
|
|
1117
|
-
const feedbackOf =
|
|
1513
|
+
const resolved = useRef4(/* @__PURE__ */ new Map());
|
|
1514
|
+
const feedbackOf = useCallback3((message) => {
|
|
1118
1515
|
const mine = local.get(message.id);
|
|
1119
1516
|
if (mine !== void 0) return mine.feedback;
|
|
1120
1517
|
return metadataOf(message).feedback ?? null;
|
|
1121
1518
|
}, [
|
|
1122
1519
|
local
|
|
1123
1520
|
]);
|
|
1124
|
-
const isPending =
|
|
1521
|
+
const isPending = useCallback3((message) => pending.has(message.id), [
|
|
1125
1522
|
pending
|
|
1126
1523
|
]);
|
|
1127
|
-
const storedIdFor =
|
|
1524
|
+
const storedIdFor = useCallback3(async (message) => {
|
|
1128
1525
|
const runId = metadataOf(message).runId;
|
|
1129
1526
|
if (runId === void 0) return message.id;
|
|
1130
1527
|
const known = resolved.current.get(message.id);
|
|
@@ -1144,7 +1541,7 @@ function useMessageFeedback(options) {
|
|
|
1144
1541
|
resolved.current.set(message.id, row.id);
|
|
1145
1542
|
return row.id;
|
|
1146
1543
|
}, []);
|
|
1147
|
-
const rate =
|
|
1544
|
+
const rate = useCallback3(async (message, value, comment) => {
|
|
1148
1545
|
const setFeedback = requireBackendMethod(latest.current.backend, "setMessageFeedback");
|
|
1149
1546
|
const had = localRef.current.get(message.id);
|
|
1150
1547
|
const optimistic = value === null ? null : {
|
|
@@ -1190,7 +1587,7 @@ function useMessageFeedback(options) {
|
|
|
1190
1587
|
}, [
|
|
1191
1588
|
storedIdFor
|
|
1192
1589
|
]);
|
|
1193
|
-
const toggle =
|
|
1590
|
+
const toggle = useCallback3((message, value) => {
|
|
1194
1591
|
const mine = localRef.current.get(message.id);
|
|
1195
1592
|
const current = mine !== void 0 ? mine.feedback : metadataOf(message).feedback ?? null;
|
|
1196
1593
|
return rate(message, current?.value === value ? null : value);
|
|
@@ -1212,38 +1609,17 @@ function metadataOf(message) {
|
|
|
1212
1609
|
}
|
|
1213
1610
|
__name(metadataOf, "metadataOf");
|
|
1214
1611
|
|
|
1215
|
-
// src/threads/threads-events.ts
|
|
1216
|
-
var listeners = /* @__PURE__ */ new WeakMap();
|
|
1217
|
-
function notifyThreads(backend, event) {
|
|
1218
|
-
for (const listener of listeners.get(backend) ?? []) {
|
|
1219
|
-
listener(event);
|
|
1220
|
-
}
|
|
1221
|
-
}
|
|
1222
|
-
__name(notifyThreads, "notifyThreads");
|
|
1223
|
-
function onThreadsEvent(backend, listener) {
|
|
1224
|
-
let set = listeners.get(backend);
|
|
1225
|
-
if (set === void 0) {
|
|
1226
|
-
set = /* @__PURE__ */ new Set();
|
|
1227
|
-
listeners.set(backend, set);
|
|
1228
|
-
}
|
|
1229
|
-
set.add(listener);
|
|
1230
|
-
return () => {
|
|
1231
|
-
set.delete(listener);
|
|
1232
|
-
};
|
|
1233
|
-
}
|
|
1234
|
-
__name(onThreadsEvent, "onThreadsEvent");
|
|
1235
|
-
|
|
1236
1612
|
// src/threads/use-threads.ts
|
|
1237
|
-
import { useCallback as
|
|
1613
|
+
import { useCallback as useCallback4, useEffect as useEffect5, useRef as useRef5, useState as useState5 } from "react";
|
|
1238
1614
|
function useThreads(options) {
|
|
1239
1615
|
const { backend, enabled = true } = options;
|
|
1240
|
-
const [threads, setThreads] =
|
|
1241
|
-
const [isLoading, setIsLoading] =
|
|
1242
|
-
const [error, setError] =
|
|
1243
|
-
const threadsRef =
|
|
1616
|
+
const [threads, setThreads] = useState5([]);
|
|
1617
|
+
const [isLoading, setIsLoading] = useState5(enabled);
|
|
1618
|
+
const [error, setError] = useState5(null);
|
|
1619
|
+
const threadsRef = useRef5(threads);
|
|
1244
1620
|
threadsRef.current = threads;
|
|
1245
|
-
const generation =
|
|
1246
|
-
const refresh =
|
|
1621
|
+
const generation = useRef5(0);
|
|
1622
|
+
const refresh = useCallback4(async () => {
|
|
1247
1623
|
const mine = ++generation.current;
|
|
1248
1624
|
setIsLoading(true);
|
|
1249
1625
|
try {
|
|
@@ -1260,7 +1636,7 @@ function useThreads(options) {
|
|
|
1260
1636
|
}, [
|
|
1261
1637
|
backend
|
|
1262
1638
|
]);
|
|
1263
|
-
|
|
1639
|
+
useEffect5(() => {
|
|
1264
1640
|
if (!enabled) return;
|
|
1265
1641
|
void refresh();
|
|
1266
1642
|
return onThreadsEvent(backend, (event) => {
|
|
@@ -1280,7 +1656,7 @@ function useThreads(options) {
|
|
|
1280
1656
|
enabled,
|
|
1281
1657
|
refresh
|
|
1282
1658
|
]);
|
|
1283
|
-
const rename =
|
|
1659
|
+
const rename = useCallback4(async (id, title) => {
|
|
1284
1660
|
const before = threadsRef.current;
|
|
1285
1661
|
setThreads((current) => current.map((thread) => thread.id === id ? {
|
|
1286
1662
|
...thread,
|
|
@@ -1302,7 +1678,7 @@ function useThreads(options) {
|
|
|
1302
1678
|
}, [
|
|
1303
1679
|
backend
|
|
1304
1680
|
]);
|
|
1305
|
-
const remove =
|
|
1681
|
+
const remove = useCallback4(async (id) => {
|
|
1306
1682
|
const before = threadsRef.current;
|
|
1307
1683
|
setThreads((current) => current.filter((thread) => thread.id !== id));
|
|
1308
1684
|
try {
|
|
@@ -1377,10 +1753,10 @@ function backgroundRunsFromThread(messages) {
|
|
|
1377
1753
|
__name(backgroundRunsFromThread, "backgroundRunsFromThread");
|
|
1378
1754
|
|
|
1379
1755
|
// src/components/chat-input.tsx
|
|
1380
|
-
import React2, { useEffect as
|
|
1756
|
+
import React2, { useEffect as useEffect7, useState as useState7 } from "react";
|
|
1381
1757
|
|
|
1382
1758
|
// src/components/use-speech-recognition.ts
|
|
1383
|
-
import { useCallback as
|
|
1759
|
+
import { useCallback as useCallback5, useEffect as useEffect6, useMemo as useMemo5, useRef as useRef6, useState as useState6 } from "react";
|
|
1384
1760
|
function getRecognitionCtor() {
|
|
1385
1761
|
if (typeof window === "undefined") return null;
|
|
1386
1762
|
const scope = window;
|
|
@@ -1388,15 +1764,15 @@ function getRecognitionCtor() {
|
|
|
1388
1764
|
}
|
|
1389
1765
|
__name(getRecognitionCtor, "getRecognitionCtor");
|
|
1390
1766
|
function useSpeechRecognition({ lang = "en-US", onFinalTranscript, onInterimTranscript }) {
|
|
1391
|
-
const recognitionRef =
|
|
1392
|
-
const [isListening, setIsListening] =
|
|
1393
|
-
const ctor =
|
|
1767
|
+
const recognitionRef = useRef6(null);
|
|
1768
|
+
const [isListening, setIsListening] = useState6(false);
|
|
1769
|
+
const ctor = useMemo5(() => getRecognitionCtor(), []);
|
|
1394
1770
|
const isSupported = ctor !== null;
|
|
1395
|
-
const finalRef =
|
|
1396
|
-
const interimRef =
|
|
1771
|
+
const finalRef = useRef6(onFinalTranscript);
|
|
1772
|
+
const interimRef = useRef6(onInterimTranscript);
|
|
1397
1773
|
finalRef.current = onFinalTranscript;
|
|
1398
1774
|
interimRef.current = onInterimTranscript;
|
|
1399
|
-
|
|
1775
|
+
useEffect6(() => {
|
|
1400
1776
|
if (!ctor) return;
|
|
1401
1777
|
const recognition = new ctor();
|
|
1402
1778
|
recognition.lang = lang;
|
|
@@ -1435,7 +1811,7 @@ function useSpeechRecognition({ lang = "en-US", onFinalTranscript, onInterimTran
|
|
|
1435
1811
|
ctor,
|
|
1436
1812
|
lang
|
|
1437
1813
|
]);
|
|
1438
|
-
const start =
|
|
1814
|
+
const start = useCallback5(() => {
|
|
1439
1815
|
const recognition = recognitionRef.current;
|
|
1440
1816
|
if (!recognition) return;
|
|
1441
1817
|
try {
|
|
@@ -1445,7 +1821,7 @@ function useSpeechRecognition({ lang = "en-US", onFinalTranscript, onInterimTran
|
|
|
1445
1821
|
console.warn("SpeechRecognition start failed", error);
|
|
1446
1822
|
}
|
|
1447
1823
|
}, []);
|
|
1448
|
-
const stop =
|
|
1824
|
+
const stop = useCallback5(() => {
|
|
1449
1825
|
const recognition = recognitionRef.current;
|
|
1450
1826
|
if (!recognition) return;
|
|
1451
1827
|
try {
|
|
@@ -1464,8 +1840,8 @@ __name(useSpeechRecognition, "useSpeechRecognition");
|
|
|
1464
1840
|
|
|
1465
1841
|
// src/components/chat-input.tsx
|
|
1466
1842
|
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 }) {
|
|
1467
|
-
const [value, setValue] =
|
|
1468
|
-
const [interim, setInterim] =
|
|
1843
|
+
const [value, setValue] = useState7("");
|
|
1844
|
+
const [interim, setInterim] = useState7("");
|
|
1469
1845
|
const speech = useSpeechRecognition({
|
|
1470
1846
|
lang: speechLang,
|
|
1471
1847
|
onFinalTranscript: /* @__PURE__ */ __name((text) => {
|
|
@@ -1476,7 +1852,7 @@ function ChatInput({ onSubmit, disabled, placeholder, rows = 2, enableSpeech = t
|
|
|
1476
1852
|
}, "onFinalTranscript"),
|
|
1477
1853
|
onInterimTranscript: /* @__PURE__ */ __name((text) => setInterim(text), "onInterimTranscript")
|
|
1478
1854
|
});
|
|
1479
|
-
|
|
1855
|
+
useEffect7(() => {
|
|
1480
1856
|
if (!speech.isListening) setInterim("");
|
|
1481
1857
|
}, [
|
|
1482
1858
|
speech.isListening
|
|
@@ -1543,7 +1919,7 @@ __name(ChatInput, "ChatInput");
|
|
|
1543
1919
|
import React3 from "react";
|
|
1544
1920
|
|
|
1545
1921
|
// src/transcript/use-chat-transcript.ts
|
|
1546
|
-
import { useCallback as
|
|
1922
|
+
import { useCallback as useCallback7, useEffect as useEffect9, useRef as useRef8, useState as useState9 } from "react";
|
|
1547
1923
|
|
|
1548
1924
|
// src/transcript/model.ts
|
|
1549
1925
|
import { readElicitationInput, validateElicitationAnswer as validateElicitationAnswer2 } from "@dudousxd/nestjs-agent-core";
|
|
@@ -2520,11 +2896,11 @@ function formatCostUsd(cost) {
|
|
|
2520
2896
|
__name(formatCostUsd, "formatCostUsd");
|
|
2521
2897
|
|
|
2522
2898
|
// src/transcript/use-stick-to-bottom.ts
|
|
2523
|
-
import { useCallback as
|
|
2899
|
+
import { useCallback as useCallback6, useEffect as useEffect8, useRef as useRef7, useState as useState8 } from "react";
|
|
2524
2900
|
function useStickToBottom({ contentKey, threshold = 32 }) {
|
|
2525
|
-
const containerRef =
|
|
2526
|
-
const [isAtBottom, setIsAtBottom] =
|
|
2527
|
-
const measure =
|
|
2901
|
+
const containerRef = useRef7(null);
|
|
2902
|
+
const [isAtBottom, setIsAtBottom] = useState8(true);
|
|
2903
|
+
const measure = useCallback6(() => {
|
|
2528
2904
|
const element = containerRef.current;
|
|
2529
2905
|
if (!element) {
|
|
2530
2906
|
return;
|
|
@@ -2534,7 +2910,7 @@ function useStickToBottom({ contentKey, threshold = 32 }) {
|
|
|
2534
2910
|
}, [
|
|
2535
2911
|
threshold
|
|
2536
2912
|
]);
|
|
2537
|
-
const scrollToBottom =
|
|
2913
|
+
const scrollToBottom = useCallback6(() => {
|
|
2538
2914
|
const element = containerRef.current;
|
|
2539
2915
|
if (!element) {
|
|
2540
2916
|
return;
|
|
@@ -2542,7 +2918,7 @@ function useStickToBottom({ contentKey, threshold = 32 }) {
|
|
|
2542
2918
|
element.scrollTop = element.scrollHeight;
|
|
2543
2919
|
setIsAtBottom(true);
|
|
2544
2920
|
}, []);
|
|
2545
|
-
const setContainer =
|
|
2921
|
+
const setContainer = useCallback6((element) => {
|
|
2546
2922
|
containerRef.current = element;
|
|
2547
2923
|
if (element) {
|
|
2548
2924
|
measure();
|
|
@@ -2550,7 +2926,7 @@ function useStickToBottom({ contentKey, threshold = 32 }) {
|
|
|
2550
2926
|
}, [
|
|
2551
2927
|
measure
|
|
2552
2928
|
]);
|
|
2553
|
-
|
|
2929
|
+
useEffect8(() => {
|
|
2554
2930
|
if (isAtBottom) {
|
|
2555
2931
|
scrollToBottom();
|
|
2556
2932
|
}
|
|
@@ -2559,7 +2935,7 @@ function useStickToBottom({ contentKey, threshold = 32 }) {
|
|
|
2559
2935
|
isAtBottom,
|
|
2560
2936
|
scrollToBottom
|
|
2561
2937
|
]);
|
|
2562
|
-
const getContainerProps =
|
|
2938
|
+
const getContainerProps = useCallback6(() => ({
|
|
2563
2939
|
ref: setContainer,
|
|
2564
2940
|
onScroll: measure
|
|
2565
2941
|
}), [
|
|
@@ -2581,14 +2957,14 @@ var DEFAULT_LOAD_EARLIER_STEP = 50;
|
|
|
2581
2957
|
var DEFAULT_COPY_RESET_MS = 1500;
|
|
2582
2958
|
function useChatTranscript(options) {
|
|
2583
2959
|
const { messages, status, initialVisibleCount = DEFAULT_VISIBLE_COUNT, loadEarlierStep = DEFAULT_LOAD_EARLIER_STEP, followUps, stickToBottomThreshold } = options;
|
|
2584
|
-
const latest =
|
|
2960
|
+
const latest = useRef8(options);
|
|
2585
2961
|
latest.current = options;
|
|
2586
|
-
const [visibleCount, setVisibleCount] =
|
|
2587
|
-
const [stopRequested, setStopRequested] =
|
|
2962
|
+
const [visibleCount, setVisibleCount] = useState9(initialVisibleCount);
|
|
2963
|
+
const [stopRequested, setStopRequested] = useState9(false);
|
|
2588
2964
|
const isStreaming = status === "streaming" || status === "reconnecting";
|
|
2589
2965
|
const isBusy = status === "submitted" || isStreaming;
|
|
2590
2966
|
const isEmpty = messages.length === 0;
|
|
2591
|
-
|
|
2967
|
+
useEffect9(() => {
|
|
2592
2968
|
if (!isBusy) {
|
|
2593
2969
|
setStopRequested(false);
|
|
2594
2970
|
}
|
|
@@ -2605,7 +2981,7 @@ function useChatTranscript(options) {
|
|
|
2605
2981
|
streamingMessageId,
|
|
2606
2982
|
options
|
|
2607
2983
|
});
|
|
2608
|
-
const stop =
|
|
2984
|
+
const stop = useCallback7(() => {
|
|
2609
2985
|
const current = latest.current;
|
|
2610
2986
|
if (current.status !== "submitted" && current.status !== "streaming" && current.status !== "reconnecting") {
|
|
2611
2987
|
return;
|
|
@@ -2613,8 +2989,8 @@ function useChatTranscript(options) {
|
|
|
2613
2989
|
setStopRequested(true);
|
|
2614
2990
|
void current.onStop?.();
|
|
2615
2991
|
}, []);
|
|
2616
|
-
const loadEarlier =
|
|
2617
|
-
const showAll =
|
|
2992
|
+
const loadEarlier = useCallback7(() => setVisibleCount((count) => count + (latest.current.loadEarlierStep ?? DEFAULT_LOAD_EARLIER_STEP)), []);
|
|
2993
|
+
const showAll = useCallback7(() => setVisibleCount(latest.current.messages.length), []);
|
|
2618
2994
|
const scroll = useStickToBottom({
|
|
2619
2995
|
contentKey: contentSignature(messages),
|
|
2620
2996
|
...stickToBottomThreshold !== void 0 ? {
|
|
@@ -2650,7 +3026,7 @@ function useChatTranscript(options) {
|
|
|
2650
3026
|
__name(useChatTranscript, "useChatTranscript");
|
|
2651
3027
|
function useTranscriptItem(options) {
|
|
2652
3028
|
const { message, isStreaming = false } = options;
|
|
2653
|
-
const messagesRef =
|
|
3029
|
+
const messagesRef = useRef8([
|
|
2654
3030
|
message
|
|
2655
3031
|
]);
|
|
2656
3032
|
if (messagesRef.current[0] !== message) {
|
|
@@ -2668,13 +3044,13 @@ function useTranscriptItem(options) {
|
|
|
2668
3044
|
}
|
|
2669
3045
|
__name(useTranscriptItem, "useTranscriptItem");
|
|
2670
3046
|
function useTranscriptItems({ messages, visibleStart, streamingMessageId, options }) {
|
|
2671
|
-
const [drafts, setDrafts] =
|
|
2672
|
-
const [copied, setCopied] =
|
|
2673
|
-
const [openReasoning, setOpenReasoning] =
|
|
2674
|
-
const [picks, setPicks] =
|
|
2675
|
-
const [settling, setSettling] =
|
|
2676
|
-
const [settleErrors, setSettleErrors] =
|
|
2677
|
-
const latest =
|
|
3047
|
+
const [drafts, setDrafts] = useState9(() => /* @__PURE__ */ new Map());
|
|
3048
|
+
const [copied, setCopied] = useState9(() => /* @__PURE__ */ new Set());
|
|
3049
|
+
const [openReasoning, setOpenReasoning] = useState9(() => /* @__PURE__ */ new Map());
|
|
3050
|
+
const [picks, setPicks] = useState9(() => /* @__PURE__ */ new Map());
|
|
3051
|
+
const [settling, setSettling] = useState9(() => /* @__PURE__ */ new Map());
|
|
3052
|
+
const [settleErrors, setSettleErrors] = useState9(() => /* @__PURE__ */ new Map());
|
|
3053
|
+
const latest = useRef8({
|
|
2678
3054
|
options,
|
|
2679
3055
|
drafts,
|
|
2680
3056
|
picks,
|
|
@@ -2686,23 +3062,23 @@ function useTranscriptItems({ messages, visibleStart, streamingMessageId, option
|
|
|
2686
3062
|
picks,
|
|
2687
3063
|
messages
|
|
2688
3064
|
};
|
|
2689
|
-
const copyTimers =
|
|
2690
|
-
|
|
3065
|
+
const copyTimers = useRef8(/* @__PURE__ */ new Map());
|
|
3066
|
+
useEffect9(() => () => {
|
|
2691
3067
|
for (const timer of copyTimers.current.values()) {
|
|
2692
3068
|
clearTimeout(timer);
|
|
2693
3069
|
}
|
|
2694
3070
|
copyTimers.current.clear();
|
|
2695
3071
|
}, []);
|
|
2696
|
-
const callbackCache =
|
|
2697
|
-
const reasoningToggleCache =
|
|
2698
|
-
const toggleReasoning =
|
|
3072
|
+
const callbackCache = useRef8(/* @__PURE__ */ new Map());
|
|
3073
|
+
const reasoningToggleCache = useRef8(/* @__PURE__ */ new Map());
|
|
3074
|
+
const toggleReasoning = useCallback7((key, open) => {
|
|
2699
3075
|
setOpenReasoning((current) => {
|
|
2700
3076
|
const next = new Map(current);
|
|
2701
3077
|
next.set(key, open ?? !(current.get(key) ?? false));
|
|
2702
3078
|
return next;
|
|
2703
3079
|
});
|
|
2704
3080
|
}, []);
|
|
2705
|
-
const stableToggle =
|
|
3081
|
+
const stableToggle = useCallback7((key) => {
|
|
2706
3082
|
let cached = reasoningToggleCache.current.get(key);
|
|
2707
3083
|
if (!cached) {
|
|
2708
3084
|
cached = /* @__PURE__ */ __name((open) => toggleReasoning(key, open), "cached");
|
|
@@ -2712,10 +3088,10 @@ function useTranscriptItems({ messages, visibleStart, streamingMessageId, option
|
|
|
2712
3088
|
}, [
|
|
2713
3089
|
toggleReasoning
|
|
2714
3090
|
]);
|
|
2715
|
-
const pick =
|
|
3091
|
+
const pick = useCallback7((toolCallId, questionId, values) => {
|
|
2716
3092
|
setPicks((current) => new Map(current).set(pickKey(toolCallId, questionId), values));
|
|
2717
3093
|
}, []);
|
|
2718
|
-
const settle =
|
|
3094
|
+
const settle = useCallback7((toolCallId, action, send) => {
|
|
2719
3095
|
setSettleErrors((current) => {
|
|
2720
3096
|
if (!current.has(toolCallId)) {
|
|
2721
3097
|
return current;
|
|
@@ -2739,7 +3115,7 @@ function useTranscriptItems({ messages, visibleStart, streamingMessageId, option
|
|
|
2739
3115
|
failed(error);
|
|
2740
3116
|
}
|
|
2741
3117
|
}, []);
|
|
2742
|
-
const answer =
|
|
3118
|
+
const answer = useCallback7((toolCallId) => {
|
|
2743
3119
|
const current = latest.current;
|
|
2744
3120
|
const onAnswer = current.options.onAnswer;
|
|
2745
3121
|
if (!onAnswer) {
|
|
@@ -2749,7 +3125,7 @@ function useTranscriptItems({ messages, visibleStart, streamingMessageId, option
|
|
|
2749
3125
|
}, [
|
|
2750
3126
|
settle
|
|
2751
3127
|
]);
|
|
2752
|
-
const skip =
|
|
3128
|
+
const skip = useCallback7((toolCallId) => {
|
|
2753
3129
|
const onSkip = latest.current.options.onSkip;
|
|
2754
3130
|
if (onSkip) {
|
|
2755
3131
|
settle(toolCallId, "skip", () => onSkip(toolCallId));
|
|
@@ -2757,7 +3133,7 @@ function useTranscriptItems({ messages, visibleStart, streamingMessageId, option
|
|
|
2757
3133
|
}, [
|
|
2758
3134
|
settle
|
|
2759
3135
|
]);
|
|
2760
|
-
const approve =
|
|
3136
|
+
const approve = useCallback7((toolCallId, options2) => {
|
|
2761
3137
|
const onApprove = latest.current.options.onApprove;
|
|
2762
3138
|
if (onApprove) {
|
|
2763
3139
|
settle(toolCallId, "approve", () => options2 === void 0 ? onApprove(toolCallId) : onApprove(toolCallId, options2));
|
|
@@ -2765,7 +3141,7 @@ function useTranscriptItems({ messages, visibleStart, streamingMessageId, option
|
|
|
2765
3141
|
}, [
|
|
2766
3142
|
settle
|
|
2767
3143
|
]);
|
|
2768
|
-
const reject =
|
|
3144
|
+
const reject = useCallback7((toolCallId) => {
|
|
2769
3145
|
const onReject = latest.current.options.onReject;
|
|
2770
3146
|
if (onReject) {
|
|
2771
3147
|
settle(toolCallId, "reject", () => onReject(toolCallId));
|
|
@@ -2773,7 +3149,7 @@ function useTranscriptItems({ messages, visibleStart, streamingMessageId, option
|
|
|
2773
3149
|
}, [
|
|
2774
3150
|
settle
|
|
2775
3151
|
]);
|
|
2776
|
-
const callbacksFor =
|
|
3152
|
+
const callbacksFor = useCallback7((id) => {
|
|
2777
3153
|
const cached = callbackCache.current.get(id);
|
|
2778
3154
|
if (cached) {
|
|
2779
3155
|
return cached;
|
|
@@ -3430,35 +3806,35 @@ function toItem(entry) {
|
|
|
3430
3806
|
__name(toItem, "toItem");
|
|
3431
3807
|
|
|
3432
3808
|
// src/composer/use-composer-autocomplete.ts
|
|
3433
|
-
import { useCallback as
|
|
3809
|
+
import { useCallback as useCallback8, useEffect as useEffect10, useId, useLayoutEffect, useMemo as useMemo6, useRef as useRef9, useState as useState10 } from "react";
|
|
3434
3810
|
function useComposerAutocomplete(options) {
|
|
3435
3811
|
const { value, sources, acceptOnTab = true } = options;
|
|
3436
|
-
const latest =
|
|
3812
|
+
const latest = useRef9(options);
|
|
3437
3813
|
latest.current = options;
|
|
3438
|
-
const inputRef =
|
|
3439
|
-
const [caret, setCaret] =
|
|
3440
|
-
const [items, setItems] =
|
|
3441
|
-
const [isLoading, setLoading] =
|
|
3442
|
-
const [error, setError] =
|
|
3443
|
-
const [activeIndex, setActiveIndex] =
|
|
3444
|
-
const [dismissedIndex, setDismissedIndex] =
|
|
3814
|
+
const inputRef = useRef9(null);
|
|
3815
|
+
const [caret, setCaret] = useState10(value.length);
|
|
3816
|
+
const [items, setItems] = useState10([]);
|
|
3817
|
+
const [isLoading, setLoading] = useState10(false);
|
|
3818
|
+
const [error, setError] = useState10(null);
|
|
3819
|
+
const [activeIndex, setActiveIndex] = useState10(0);
|
|
3820
|
+
const [dismissedIndex, setDismissedIndex] = useState10(null);
|
|
3445
3821
|
const safeCaret = Math.min(caret, value.length);
|
|
3446
|
-
const match =
|
|
3822
|
+
const match = useMemo6(() => findActiveTrigger(value, safeCaret, sources), [
|
|
3447
3823
|
value,
|
|
3448
3824
|
safeCaret,
|
|
3449
3825
|
sources
|
|
3450
3826
|
]);
|
|
3451
3827
|
const isActive = match !== null && dismissedIndex !== match.index;
|
|
3452
|
-
const matchRef =
|
|
3828
|
+
const matchRef = useRef9(match);
|
|
3453
3829
|
matchRef.current = match;
|
|
3454
|
-
const caretRef =
|
|
3830
|
+
const caretRef = useRef9(safeCaret);
|
|
3455
3831
|
caretRef.current = safeCaret;
|
|
3456
|
-
const itemsRef =
|
|
3832
|
+
const itemsRef = useRef9(items);
|
|
3457
3833
|
itemsRef.current = items;
|
|
3458
|
-
const activeIndexRef =
|
|
3834
|
+
const activeIndexRef = useRef9(activeIndex);
|
|
3459
3835
|
activeIndexRef.current = activeIndex;
|
|
3460
3836
|
const requestKey = isActive && match ? `${match.source.id}\0${match.query}` : null;
|
|
3461
|
-
|
|
3837
|
+
useEffect10(() => {
|
|
3462
3838
|
const current = matchRef.current;
|
|
3463
3839
|
if (requestKey === null || current === null) {
|
|
3464
3840
|
setItems([]);
|
|
@@ -3508,23 +3884,23 @@ function useComposerAutocomplete(options) {
|
|
|
3508
3884
|
const activeItem = isOpen ? items[activeIndex] ?? null : null;
|
|
3509
3885
|
const reactId = useId();
|
|
3510
3886
|
const listboxId = options.id ?? `agent-autocomplete-${reactId}`;
|
|
3511
|
-
const optionId =
|
|
3887
|
+
const optionId = useCallback8((index) => `${listboxId}-option-${index}`, [
|
|
3512
3888
|
listboxId
|
|
3513
3889
|
]);
|
|
3514
|
-
const highlight =
|
|
3890
|
+
const highlight = useCallback8((index) => {
|
|
3515
3891
|
const total = itemsRef.current.length;
|
|
3516
3892
|
if (total === 0) return;
|
|
3517
3893
|
setActiveIndex((index % total + total) % total);
|
|
3518
3894
|
}, []);
|
|
3519
|
-
const moveHighlight =
|
|
3895
|
+
const moveHighlight = useCallback8((delta) => highlight(activeIndexRef.current + delta), [
|
|
3520
3896
|
highlight
|
|
3521
3897
|
]);
|
|
3522
|
-
const dismiss =
|
|
3898
|
+
const dismiss = useCallback8(() => {
|
|
3523
3899
|
const current = matchRef.current;
|
|
3524
3900
|
if (current) setDismissedIndex(current.index);
|
|
3525
3901
|
}, []);
|
|
3526
|
-
const pendingCaret =
|
|
3527
|
-
const accept =
|
|
3902
|
+
const pendingCaret = useRef9(null);
|
|
3903
|
+
const accept = useCallback8((item) => {
|
|
3528
3904
|
const current = matchRef.current;
|
|
3529
3905
|
if (!current) return;
|
|
3530
3906
|
const chosen = item ?? itemsRef.current[activeIndexRef.current];
|
|
@@ -3541,10 +3917,10 @@ function useComposerAutocomplete(options) {
|
|
|
3541
3917
|
pendingCaret.current = null;
|
|
3542
3918
|
inputRef.current?.setSelectionRange(position, position);
|
|
3543
3919
|
});
|
|
3544
|
-
const readCaret =
|
|
3920
|
+
const readCaret = useCallback8((element) => {
|
|
3545
3921
|
setCaret(element.selectionStart ?? element.value.length);
|
|
3546
3922
|
}, []);
|
|
3547
|
-
const onKeyDown =
|
|
3923
|
+
const onKeyDown = useCallback8((event) => {
|
|
3548
3924
|
if (!isOpen) return;
|
|
3549
3925
|
const hasItems = itemsRef.current.length > 0;
|
|
3550
3926
|
switch (event.key) {
|
|
@@ -3582,23 +3958,23 @@ function useComposerAutocomplete(options) {
|
|
|
3582
3958
|
dismiss,
|
|
3583
3959
|
moveHighlight
|
|
3584
3960
|
]);
|
|
3585
|
-
const onChange =
|
|
3961
|
+
const onChange = useCallback8((event) => {
|
|
3586
3962
|
readCaret(event.target);
|
|
3587
3963
|
const next = findActiveTrigger(event.target.value, event.target.selectionStart ?? event.target.value.length, latest.current.sources);
|
|
3588
3964
|
setDismissedIndex((current) => current !== null && next?.index === current ? current : null);
|
|
3589
3965
|
}, [
|
|
3590
3966
|
readCaret
|
|
3591
3967
|
]);
|
|
3592
|
-
const onSelect =
|
|
3968
|
+
const onSelect = useCallback8((event) => readCaret(event.currentTarget), [
|
|
3593
3969
|
readCaret
|
|
3594
3970
|
]);
|
|
3595
|
-
const onClick =
|
|
3971
|
+
const onClick = useCallback8((event) => readCaret(event.currentTarget), [
|
|
3596
3972
|
readCaret
|
|
3597
3973
|
]);
|
|
3598
|
-
const setInput =
|
|
3974
|
+
const setInput = useCallback8((element) => {
|
|
3599
3975
|
inputRef.current = element;
|
|
3600
3976
|
}, []);
|
|
3601
|
-
const getInputProps =
|
|
3977
|
+
const getInputProps = useCallback8(() => ({
|
|
3602
3978
|
ref: setInput,
|
|
3603
3979
|
onChange,
|
|
3604
3980
|
onKeyDown,
|
|
@@ -3626,7 +4002,7 @@ function useComposerAutocomplete(options) {
|
|
|
3626
4002
|
activeIndex,
|
|
3627
4003
|
optionId
|
|
3628
4004
|
]);
|
|
3629
|
-
const getListboxProps =
|
|
4005
|
+
const getListboxProps = useCallback8(() => ({
|
|
3630
4006
|
id: listboxId,
|
|
3631
4007
|
role: "listbox",
|
|
3632
4008
|
"aria-label": match?.source.label ?? match?.source.id ?? "Suggestions"
|
|
@@ -3634,7 +4010,7 @@ function useComposerAutocomplete(options) {
|
|
|
3634
4010
|
listboxId,
|
|
3635
4011
|
match
|
|
3636
4012
|
]);
|
|
3637
|
-
const getOptionProps =
|
|
4013
|
+
const getOptionProps = useCallback8((index) => ({
|
|
3638
4014
|
id: optionId(index),
|
|
3639
4015
|
role: "option",
|
|
3640
4016
|
"aria-selected": index === activeIndex
|
|
@@ -3668,7 +4044,7 @@ function isPromise(value) {
|
|
|
3668
4044
|
__name(isPromise, "isPromise");
|
|
3669
4045
|
|
|
3670
4046
|
// src/presentation/use-tool-catalog.ts
|
|
3671
|
-
import { useCallback as
|
|
4047
|
+
import { useCallback as useCallback9, useEffect as useEffect11, useMemo as useMemo7, useState as useState11 } from "react";
|
|
3672
4048
|
var shared = /* @__PURE__ */ new WeakMap();
|
|
3673
4049
|
function load(client, agent) {
|
|
3674
4050
|
let byAgent = shared.get(client);
|
|
@@ -3692,11 +4068,11 @@ function load(client, agent) {
|
|
|
3692
4068
|
__name(load, "load");
|
|
3693
4069
|
function useToolCatalog(options) {
|
|
3694
4070
|
const { client, agent, enabled = true } = options;
|
|
3695
|
-
const [entries, setEntries] =
|
|
3696
|
-
const [isLoading, setLoading] =
|
|
3697
|
-
const [error, setError] =
|
|
3698
|
-
const [generation, setGeneration] =
|
|
3699
|
-
|
|
4071
|
+
const [entries, setEntries] = useState11([]);
|
|
4072
|
+
const [isLoading, setLoading] = useState11(enabled);
|
|
4073
|
+
const [error, setError] = useState11(null);
|
|
4074
|
+
const [generation, setGeneration] = useState11(0);
|
|
4075
|
+
useEffect11(() => {
|
|
3700
4076
|
if (!enabled) {
|
|
3701
4077
|
setLoading(false);
|
|
3702
4078
|
return;
|
|
@@ -3722,14 +4098,14 @@ function useToolCatalog(options) {
|
|
|
3722
4098
|
enabled,
|
|
3723
4099
|
generation
|
|
3724
4100
|
]);
|
|
3725
|
-
const refresh =
|
|
4101
|
+
const refresh = useCallback9(() => {
|
|
3726
4102
|
shared.get(client)?.delete(agent ?? "");
|
|
3727
4103
|
setGeneration((current) => current + 1);
|
|
3728
4104
|
}, [
|
|
3729
4105
|
client,
|
|
3730
4106
|
agent
|
|
3731
4107
|
]);
|
|
3732
|
-
const catalog =
|
|
4108
|
+
const catalog = useMemo7(() => toolCatalogFrom(entries), [
|
|
3733
4109
|
entries
|
|
3734
4110
|
]);
|
|
3735
4111
|
return {
|
|
@@ -3743,7 +4119,7 @@ function useToolCatalog(options) {
|
|
|
3743
4119
|
__name(useToolCatalog, "useToolCatalog");
|
|
3744
4120
|
|
|
3745
4121
|
// src/approvals/countdown.ts
|
|
3746
|
-
import { useEffect as
|
|
4122
|
+
import { useEffect as useEffect12, useRef as useRef10, useState as useState12 } from "react";
|
|
3747
4123
|
function approvalCountdown(expiresAt, now = Date.now()) {
|
|
3748
4124
|
const deadline = expiresAt == null ? Number.NaN : Date.parse(expiresAt);
|
|
3749
4125
|
if (!Number.isFinite(deadline)) {
|
|
@@ -3761,10 +4137,10 @@ function approvalCountdown(expiresAt, now = Date.now()) {
|
|
|
3761
4137
|
__name(approvalCountdown, "approvalCountdown");
|
|
3762
4138
|
function useApprovalCountdown(expiresAt, options = {}) {
|
|
3763
4139
|
const { intervalMs = 1e3 } = options;
|
|
3764
|
-
const nowRef =
|
|
4140
|
+
const nowRef = useRef10(options.now ?? Date.now);
|
|
3765
4141
|
nowRef.current = options.now ?? Date.now;
|
|
3766
|
-
const [state, setState] =
|
|
3767
|
-
|
|
4142
|
+
const [state, setState] = useState12(() => approvalCountdown(expiresAt, nowRef.current()));
|
|
4143
|
+
useEffect12(() => {
|
|
3768
4144
|
const read = /* @__PURE__ */ __name(() => approvalCountdown(expiresAt, nowRef.current()), "read");
|
|
3769
4145
|
const first = read();
|
|
3770
4146
|
setState(first);
|
|
@@ -3827,7 +4203,13 @@ function storedMessageToUiMessage(message) {
|
|
|
3827
4203
|
type: "file",
|
|
3828
4204
|
mediaType: attachment.contentType,
|
|
3829
4205
|
filename: attachment.name,
|
|
3830
|
-
url: attachment.url
|
|
4206
|
+
url: attachment.url,
|
|
4207
|
+
// The stored id rides along, so a replayed file can be referenced again (`messageFiles`).
|
|
4208
|
+
providerMetadata: {
|
|
4209
|
+
agent: {
|
|
4210
|
+
mediaId: attachment.mediaId
|
|
4211
|
+
}
|
|
4212
|
+
}
|
|
3831
4213
|
});
|
|
3832
4214
|
}
|
|
3833
4215
|
const toolCallIds = new Set((message.toolCalls ?? []).map((call) => call.id));
|
|
@@ -4006,20 +4388,20 @@ __name(sumUsage, "sumUsage");
|
|
|
4006
4388
|
|
|
4007
4389
|
// src/use-agent-chat.ts
|
|
4008
4390
|
import { useChat } from "@ai-sdk/react";
|
|
4009
|
-
import { useCallback as
|
|
4391
|
+
import { useCallback as useCallback10, useEffect as useEffect13, useMemo as useMemo8, useRef as useRef11, useState as useState13 } from "react";
|
|
4010
4392
|
function useAgentChat(options) {
|
|
4011
|
-
const latest =
|
|
4393
|
+
const latest = useRef11(options);
|
|
4012
4394
|
latest.current = options;
|
|
4013
|
-
const [runId, setRunId] =
|
|
4014
|
-
const runIdRef =
|
|
4395
|
+
const [runId, setRunId] = useState13(options.resumeRunId);
|
|
4396
|
+
const runIdRef = useRef11(runId);
|
|
4015
4397
|
runIdRef.current = runId;
|
|
4016
|
-
const settlingRunIdRef =
|
|
4017
|
-
const autoResumeRunIdRef =
|
|
4018
|
-
const [autoResume, setAutoResume] =
|
|
4019
|
-
const [activeRunId, setActiveRunId] =
|
|
4020
|
-
const regenerateNext =
|
|
4021
|
-
const createdThreadId =
|
|
4022
|
-
const client =
|
|
4398
|
+
const settlingRunIdRef = useRef11(void 0);
|
|
4399
|
+
const autoResumeRunIdRef = useRef11(void 0);
|
|
4400
|
+
const [autoResume, setAutoResume] = useState13(false);
|
|
4401
|
+
const [activeRunId, setActiveRunId] = useState13(null);
|
|
4402
|
+
const regenerateNext = useRef11(false);
|
|
4403
|
+
const createdThreadId = useRef11(void 0);
|
|
4404
|
+
const client = useMemo8(() => {
|
|
4023
4405
|
if (options.backend) return options.backend;
|
|
4024
4406
|
if (options.client) return options.client;
|
|
4025
4407
|
return new AgentClient({
|
|
@@ -4035,11 +4417,11 @@ function useAgentChat(options) {
|
|
|
4035
4417
|
getHeaders: /* @__PURE__ */ __name(async () => mergeHeaders(latest.current), "getHeaders")
|
|
4036
4418
|
});
|
|
4037
4419
|
}, []);
|
|
4038
|
-
const [connection, setConnection] =
|
|
4420
|
+
const [connection, setConnection] = useState13({
|
|
4039
4421
|
status: "live"
|
|
4040
4422
|
});
|
|
4041
|
-
const resyncAfterSettle =
|
|
4042
|
-
|
|
4423
|
+
const resyncAfterSettle = useRef11(false);
|
|
4424
|
+
useEffect13(() => {
|
|
4043
4425
|
if (!options.resume || options.threadId === void 0) return;
|
|
4044
4426
|
let cancelled = false;
|
|
4045
4427
|
const threadId = options.threadId;
|
|
@@ -4059,7 +4441,7 @@ function useAgentChat(options) {
|
|
|
4059
4441
|
options.resume,
|
|
4060
4442
|
options.threadId
|
|
4061
4443
|
]);
|
|
4062
|
-
const transport =
|
|
4444
|
+
const transport = useMemo8(() => {
|
|
4063
4445
|
function onMeta(meta) {
|
|
4064
4446
|
settlingRunIdRef.current = meta.runId;
|
|
4065
4447
|
setRunId(meta.runId);
|
|
@@ -4114,7 +4496,7 @@ function useAgentChat(options) {
|
|
|
4114
4496
|
}, "onAttemptStart")
|
|
4115
4497
|
});
|
|
4116
4498
|
}, []);
|
|
4117
|
-
const backgroundRef =
|
|
4499
|
+
const backgroundRef = useRef11(() => Promise.resolve());
|
|
4118
4500
|
const chat = useChat({
|
|
4119
4501
|
transport,
|
|
4120
4502
|
resume: options.resumeRunId !== void 0 || autoResume,
|
|
@@ -4163,7 +4545,7 @@ function useAgentChat(options) {
|
|
|
4163
4545
|
}
|
|
4164
4546
|
}, "onFinish")
|
|
4165
4547
|
});
|
|
4166
|
-
const chatRef =
|
|
4548
|
+
const chatRef = useRef11(chat);
|
|
4167
4549
|
chatRef.current = chat;
|
|
4168
4550
|
async function resyncFromThread() {
|
|
4169
4551
|
const threadId = latest.current.threadId ?? createdThreadId.current;
|
|
@@ -4175,11 +4557,13 @@ function useAgentChat(options) {
|
|
|
4175
4557
|
}
|
|
4176
4558
|
}
|
|
4177
4559
|
__name(resyncFromThread, "resyncFromThread");
|
|
4178
|
-
const turnInFlight =
|
|
4179
|
-
const isTurnInFlight =
|
|
4560
|
+
const turnInFlight = useRef11(false);
|
|
4561
|
+
const isTurnInFlight = useCallback10(() => turnInFlight.current || transport.isAttemptLive, [
|
|
4180
4562
|
transport
|
|
4181
4563
|
]);
|
|
4182
|
-
const sendMessage =
|
|
4564
|
+
const sendMessage = useCallback10(async (...args) => {
|
|
4565
|
+
const blocked = latest.current.blocked;
|
|
4566
|
+
if (blocked != null) throw new QuotaBlockedError(blocked);
|
|
4183
4567
|
if (isTurnInFlight()) return;
|
|
4184
4568
|
turnInFlight.current = true;
|
|
4185
4569
|
try {
|
|
@@ -4190,15 +4574,15 @@ function useAgentChat(options) {
|
|
|
4190
4574
|
}, [
|
|
4191
4575
|
isTurnInFlight
|
|
4192
4576
|
]);
|
|
4193
|
-
const addToolResult =
|
|
4577
|
+
const addToolResult = useCallback10(({ tool, toolCallId, output }) => chatRef.current.addToolResult({
|
|
4194
4578
|
tool,
|
|
4195
4579
|
toolCallId,
|
|
4196
4580
|
output
|
|
4197
4581
|
}), []);
|
|
4198
|
-
const [threads, setThreads] =
|
|
4199
|
-
const [quota, setQuota] =
|
|
4200
|
-
const [backgroundRuns, setBackgroundRuns] =
|
|
4201
|
-
const refreshBackground =
|
|
4582
|
+
const [threads, setThreads] = useState13([]);
|
|
4583
|
+
const [quota, setQuota] = useState13(null);
|
|
4584
|
+
const [backgroundRuns, setBackgroundRuns] = useState13([]);
|
|
4585
|
+
const refreshBackground = useCallback10(async () => {
|
|
4202
4586
|
const threadId = latest.current.threadId ?? createdThreadId.current;
|
|
4203
4587
|
if (threadId === void 0) {
|
|
4204
4588
|
return;
|
|
@@ -4223,7 +4607,7 @@ function useAgentChat(options) {
|
|
|
4223
4607
|
]);
|
|
4224
4608
|
backgroundRef.current = refreshBackground;
|
|
4225
4609
|
const isWorking = backgroundRuns.some((run) => run.status === "running");
|
|
4226
|
-
|
|
4610
|
+
useEffect13(() => {
|
|
4227
4611
|
if (options.background !== true || options.threadId === void 0) {
|
|
4228
4612
|
return;
|
|
4229
4613
|
}
|
|
@@ -4233,7 +4617,7 @@ function useAgentChat(options) {
|
|
|
4233
4617
|
options.threadId,
|
|
4234
4618
|
refreshBackground
|
|
4235
4619
|
]);
|
|
4236
|
-
|
|
4620
|
+
useEffect13(() => {
|
|
4237
4621
|
const every = latest.current.backgroundPollMs ?? 5e3;
|
|
4238
4622
|
if (latest.current.background !== true || !isWorking || every <= 0) {
|
|
4239
4623
|
return;
|
|
@@ -4244,26 +4628,26 @@ function useAgentChat(options) {
|
|
|
4244
4628
|
isWorking,
|
|
4245
4629
|
refreshBackground
|
|
4246
4630
|
]);
|
|
4247
|
-
const loadThreads =
|
|
4631
|
+
const loadThreads = useCallback10(async () => {
|
|
4248
4632
|
const list = await client.listThreads();
|
|
4249
4633
|
setThreads(list);
|
|
4250
4634
|
return list;
|
|
4251
4635
|
}, [
|
|
4252
4636
|
client
|
|
4253
4637
|
]);
|
|
4254
|
-
const loadThread =
|
|
4638
|
+
const loadThread = useCallback10((id) => client.getThread(id), [
|
|
4255
4639
|
client
|
|
4256
4640
|
]);
|
|
4257
|
-
const deleteThread =
|
|
4641
|
+
const deleteThread = useCallback10(async (id) => {
|
|
4258
4642
|
await client.deleteThread(id);
|
|
4259
4643
|
setThreads((current) => current.filter((thread) => thread.id !== id));
|
|
4260
4644
|
}, [
|
|
4261
4645
|
client
|
|
4262
4646
|
]);
|
|
4263
|
-
const forkThread =
|
|
4647
|
+
const forkThread = useCallback10((threadId, messageId) => requireBackendMethod(client, "forkFromMessage")(threadId, messageId), [
|
|
4264
4648
|
client
|
|
4265
4649
|
]);
|
|
4266
|
-
const renameThread =
|
|
4650
|
+
const renameThread = useCallback10(async (id, title) => {
|
|
4267
4651
|
await client.updateThread(id, {
|
|
4268
4652
|
title
|
|
4269
4653
|
});
|
|
@@ -4274,24 +4658,24 @@ function useAgentChat(options) {
|
|
|
4274
4658
|
}, [
|
|
4275
4659
|
client
|
|
4276
4660
|
]);
|
|
4277
|
-
const promoteThread =
|
|
4661
|
+
const promoteThread = useCallback10(async (id) => {
|
|
4278
4662
|
await requireBackendMethod(client, "promoteThread")(id);
|
|
4279
4663
|
await loadThreads();
|
|
4280
4664
|
}, [
|
|
4281
4665
|
client,
|
|
4282
4666
|
loadThreads
|
|
4283
4667
|
]);
|
|
4284
|
-
const truncateFromMessage =
|
|
4668
|
+
const truncateFromMessage = useCallback10((threadId, messageId) => requireBackendMethod(client, "truncateFromMessage")(threadId, messageId).then(() => void 0), [
|
|
4285
4669
|
client
|
|
4286
4670
|
]);
|
|
4287
|
-
const loadQuota =
|
|
4671
|
+
const loadQuota = useCallback10(async () => {
|
|
4288
4672
|
const today = await requireBackendMethod(client, "getQuotaToday")();
|
|
4289
4673
|
setQuota(today);
|
|
4290
4674
|
return today;
|
|
4291
4675
|
}, [
|
|
4292
4676
|
client
|
|
4293
4677
|
]);
|
|
4294
|
-
const cancel =
|
|
4678
|
+
const cancel = useCallback10(async () => {
|
|
4295
4679
|
chatRef.current.stop();
|
|
4296
4680
|
const activeRunId2 = runIdRef.current;
|
|
4297
4681
|
if (activeRunId2) {
|
|
@@ -4303,7 +4687,7 @@ function useAgentChat(options) {
|
|
|
4303
4687
|
}, [
|
|
4304
4688
|
client
|
|
4305
4689
|
]);
|
|
4306
|
-
const approve =
|
|
4690
|
+
const approve = useCallback10(async ({ toolCallId, remember, via }) => {
|
|
4307
4691
|
await requireBackendMethod(client, "approveToolCall")({
|
|
4308
4692
|
toolCallId,
|
|
4309
4693
|
...remember === true ? {
|
|
@@ -4316,7 +4700,7 @@ function useAgentChat(options) {
|
|
|
4316
4700
|
}, [
|
|
4317
4701
|
client
|
|
4318
4702
|
]);
|
|
4319
|
-
const reject =
|
|
4703
|
+
const reject = useCallback10(async ({ toolCallId, reason, via }) => {
|
|
4320
4704
|
await requireBackendMethod(client, "rejectToolCall")({
|
|
4321
4705
|
toolCallId,
|
|
4322
4706
|
...reason !== void 0 ? {
|
|
@@ -4329,7 +4713,7 @@ function useAgentChat(options) {
|
|
|
4329
4713
|
}, [
|
|
4330
4714
|
client
|
|
4331
4715
|
]);
|
|
4332
|
-
const answer =
|
|
4716
|
+
const answer = useCallback10(async ({ toolCallId, answers }) => {
|
|
4333
4717
|
await requireBackendMethod(client, "answerToolCall")({
|
|
4334
4718
|
toolCallId,
|
|
4335
4719
|
...answers !== void 0 ? {
|
|
@@ -4339,14 +4723,16 @@ function useAgentChat(options) {
|
|
|
4339
4723
|
}, [
|
|
4340
4724
|
client
|
|
4341
4725
|
]);
|
|
4342
|
-
const skip =
|
|
4726
|
+
const skip = useCallback10(async ({ toolCallId }) => {
|
|
4343
4727
|
await requireBackendMethod(client, "skipToolCall")({
|
|
4344
4728
|
toolCallId
|
|
4345
4729
|
});
|
|
4346
4730
|
}, [
|
|
4347
4731
|
client
|
|
4348
4732
|
]);
|
|
4349
|
-
const regenerate =
|
|
4733
|
+
const regenerate = useCallback10(() => {
|
|
4734
|
+
const blocked = latest.current.blocked;
|
|
4735
|
+
if (blocked != null) throw new QuotaBlockedError(blocked);
|
|
4350
4736
|
if (isTurnInFlight()) return;
|
|
4351
4737
|
regenerateNext.current = true;
|
|
4352
4738
|
turnInFlight.current = true;
|
|
@@ -4361,7 +4747,7 @@ function useAgentChat(options) {
|
|
|
4361
4747
|
isWorking,
|
|
4362
4748
|
refresh: refreshBackground
|
|
4363
4749
|
};
|
|
4364
|
-
const setThreadModel =
|
|
4750
|
+
const setThreadModel = useCallback10(async (model) => {
|
|
4365
4751
|
const threadId = latest.current.threadId ?? createdThreadId.current;
|
|
4366
4752
|
if (threadId === void 0) {
|
|
4367
4753
|
throw new Error("setThreadModel: this chat has no thread yet");
|
|
@@ -4375,7 +4761,7 @@ function useAgentChat(options) {
|
|
|
4375
4761
|
}, [
|
|
4376
4762
|
client
|
|
4377
4763
|
]);
|
|
4378
|
-
const getThreadId =
|
|
4764
|
+
const getThreadId = useCallback10(() => latest.current.threadId ?? createdThreadId.current, []);
|
|
4379
4765
|
const status = connection.status === "reconnecting" ? "reconnecting" : chat.status;
|
|
4380
4766
|
return {
|
|
4381
4767
|
...chat,
|
|
@@ -4418,6 +4804,16 @@ function useAgentChat(options) {
|
|
|
4418
4804
|
};
|
|
4419
4805
|
}
|
|
4420
4806
|
__name(useAgentChat, "useAgentChat");
|
|
4807
|
+
var QuotaBlockedError = class extends Error {
|
|
4808
|
+
static {
|
|
4809
|
+
__name(this, "QuotaBlockedError");
|
|
4810
|
+
}
|
|
4811
|
+
block;
|
|
4812
|
+
constructor(block) {
|
|
4813
|
+
super(block.reason ?? `The ${block.period === "day" ? "daily" : "monthly"} quota is used up`), this.block = block;
|
|
4814
|
+
this.name = "QuotaBlockedError";
|
|
4815
|
+
}
|
|
4816
|
+
};
|
|
4421
4817
|
async function mergeHeaders(options) {
|
|
4422
4818
|
const dynamic = await options.getHeaders?.() ?? {};
|
|
4423
4819
|
return {
|
|
@@ -4436,7 +4832,9 @@ export {
|
|
|
4436
4832
|
MessageItem,
|
|
4437
4833
|
MessageItemView,
|
|
4438
4834
|
MessageList,
|
|
4835
|
+
QuotaBlockedError,
|
|
4439
4836
|
SPEECH_LANGUAGES,
|
|
4837
|
+
acceptsFile,
|
|
4440
4838
|
applyCompletion,
|
|
4441
4839
|
approvalCountdown,
|
|
4442
4840
|
backgroundRunsFromThread,
|
|
@@ -4447,7 +4845,10 @@ export {
|
|
|
4447
4845
|
describeTimestamp,
|
|
4448
4846
|
describeToolCall,
|
|
4449
4847
|
describeUsage,
|
|
4848
|
+
dragHasFiles,
|
|
4450
4849
|
extractMessageText,
|
|
4850
|
+
fileKind,
|
|
4851
|
+
filesFromClipboard,
|
|
4451
4852
|
fillTemplate,
|
|
4452
4853
|
filterAutocompleteItems,
|
|
4453
4854
|
findActiveTrigger,
|
|
@@ -4457,6 +4858,7 @@ export {
|
|
|
4457
4858
|
inferResultView,
|
|
4458
4859
|
isActionCall,
|
|
4459
4860
|
loadStoredSpeechLang,
|
|
4861
|
+
messageFiles,
|
|
4460
4862
|
notifyThreads,
|
|
4461
4863
|
onThreadsEvent,
|
|
4462
4864
|
persistSpeechLang,
|
|
@@ -4472,11 +4874,13 @@ export {
|
|
|
4472
4874
|
useAgentChat,
|
|
4473
4875
|
useAgents,
|
|
4474
4876
|
useApprovalCountdown,
|
|
4877
|
+
useAttachments,
|
|
4475
4878
|
useChatTranscript,
|
|
4476
4879
|
useComposerAutocomplete,
|
|
4477
4880
|
useElapsed,
|
|
4478
4881
|
useMessageFeedback,
|
|
4479
4882
|
useModels,
|
|
4883
|
+
useQuota,
|
|
4480
4884
|
useSpeechRecognition,
|
|
4481
4885
|
useStickToBottom,
|
|
4482
4886
|
useThreads,
|