@dudousxd/nestjs-agent-react 0.20.0 → 0.22.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 +110 -85
- package/dist/{client-0Wd-WPsu.d.cts → client-CYlhK7XD.d.cts} +36 -24
- package/dist/{client-0Wd-WPsu.d.ts → client-CYlhK7XD.d.ts} +36 -24
- package/dist/{model-gHqjNjLJ.d.cts → generative-ui-9AJNVKBZ.d.cts} +165 -1
- package/dist/{model-gHqjNjLJ.d.ts → generative-ui-9AJNVKBZ.d.ts} +165 -1
- package/dist/genui-json-render.d.cts +1 -2
- package/dist/genui-json-render.d.ts +1 -2
- package/dist/genui.d.cts +2 -3
- package/dist/genui.d.ts +2 -3
- package/dist/index.cjs +1304 -491
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +259 -167
- package/dist/index.d.ts +259 -167
- package/dist/index.js +1264 -453
- package/dist/index.js.map +1 -1
- package/dist/media.cjs +13 -16
- package/dist/media.cjs.map +1 -1
- package/dist/media.d.cts +6 -23
- package/dist/media.d.ts +6 -23
- package/dist/media.js +12 -14
- package/dist/media.js.map +1 -1
- package/package.json +1 -1
- package/dist/generative-ui-BhXFni8j.d.ts +0 -167
- package/dist/generative-ui-C53b3FoA.d.cts +0 -167
package/dist/index.cjs
CHANGED
|
@@ -35,6 +35,7 @@ __export(src_exports, {
|
|
|
35
35
|
AgentChatTransport: () => AgentChatTransport,
|
|
36
36
|
AgentClient: () => AgentClient,
|
|
37
37
|
AgentHttpError: () => AgentHttpError,
|
|
38
|
+
AgentProvider: () => AgentProvider,
|
|
38
39
|
AmbientRenderUiContext: () => AmbientRenderUiContext,
|
|
39
40
|
ChatInput: () => ChatInput,
|
|
40
41
|
DEFAULT_SPEECH_LANG: () => DEFAULT_SPEECH_LANG,
|
|
@@ -80,6 +81,7 @@ __export(src_exports, {
|
|
|
80
81
|
storedThreadToUiMessages: () => storedThreadToUiMessages,
|
|
81
82
|
toolCallState: () => toolCallState,
|
|
82
83
|
toolCatalogFrom: () => toolCatalogFrom,
|
|
84
|
+
useAgentBackend: () => useAgentBackend,
|
|
83
85
|
useAgentChat: () => useAgentChat,
|
|
84
86
|
useAgents: () => useAgents,
|
|
85
87
|
useAmbientRenderUi: () => useAmbientRenderUi,
|
|
@@ -114,6 +116,11 @@ var AgentHttpError = class extends Error {
|
|
|
114
116
|
this.name = "AgentHttpError";
|
|
115
117
|
}
|
|
116
118
|
};
|
|
119
|
+
function normalizeAgentPath(path) {
|
|
120
|
+
const trimmed = (path ?? "agent").replace(/^\/+|\/+$/g, "");
|
|
121
|
+
return trimmed === "" ? "" : `/${trimmed}`;
|
|
122
|
+
}
|
|
123
|
+
__name(normalizeAgentPath, "normalizeAgentPath");
|
|
117
124
|
var HEADER_RUN_ID = "x-agent-run-id";
|
|
118
125
|
var HEADER_THREAD_ID = "x-agent-thread-id";
|
|
119
126
|
var AgentClient = class {
|
|
@@ -124,9 +131,9 @@ var AgentClient = class {
|
|
|
124
131
|
constructor(options = {}) {
|
|
125
132
|
this.options = options;
|
|
126
133
|
}
|
|
127
|
-
/** `POST
|
|
134
|
+
/** `POST <path>/chat` → the turn's SSE stream. Throws {@link AgentHttpError} on a non-2xx. */
|
|
128
135
|
async openChatStream(request) {
|
|
129
|
-
const response = await this.fetchImpl()(`${this.
|
|
136
|
+
const response = await this.fetchImpl()(`${this.root()}/chat`, {
|
|
130
137
|
method: "POST",
|
|
131
138
|
headers: {
|
|
132
139
|
"content-type": "application/json",
|
|
@@ -141,18 +148,18 @@ var AgentClient = class {
|
|
|
141
148
|
} : {}
|
|
142
149
|
});
|
|
143
150
|
if (!response.ok || !response.body) {
|
|
144
|
-
throw new AgentHttpError(response.status, "POST",
|
|
151
|
+
throw new AgentHttpError(response.status, "POST", `${this.agentPath()}/chat`, response.statusText);
|
|
145
152
|
}
|
|
146
153
|
return streamResponse(response);
|
|
147
154
|
}
|
|
148
155
|
/**
|
|
149
|
-
* `GET
|
|
156
|
+
* `GET <path>/chat/:runId/stream[?after=<seq>]` → the run's SSE stream, or `null` when nothing is
|
|
150
157
|
* streaming under that id (404).
|
|
151
158
|
*/
|
|
152
159
|
async resumeChatStream(request) {
|
|
153
|
-
const path = `/
|
|
160
|
+
const path = `/chat/${encodeURIComponent(request.runId)}/stream`;
|
|
154
161
|
const query = request.after !== void 0 && request.after > 0 ? `?after=${request.after}` : "";
|
|
155
|
-
const response = await this.fetchImpl()(`${this.
|
|
162
|
+
const response = await this.fetchImpl()(`${this.root()}${path}${query}`, {
|
|
156
163
|
method: "GET",
|
|
157
164
|
headers: {
|
|
158
165
|
accept: "text/event-stream",
|
|
@@ -168,7 +175,7 @@ var AgentClient = class {
|
|
|
168
175
|
return null;
|
|
169
176
|
}
|
|
170
177
|
if (!response.ok || !response.body) {
|
|
171
|
-
throw new AgentHttpError(response.status, "GET", path
|
|
178
|
+
throw new AgentHttpError(response.status, "GET", `${this.agentPath()}${path}`, response.statusText);
|
|
172
179
|
}
|
|
173
180
|
return streamResponse(response);
|
|
174
181
|
}
|
|
@@ -177,10 +184,10 @@ var AgentClient = class {
|
|
|
177
184
|
* the stored rating.
|
|
178
185
|
*/
|
|
179
186
|
setMessageFeedback(messageId, input) {
|
|
180
|
-
return this.request("POST", `/
|
|
187
|
+
return this.request("POST", `/messages/${encodeURIComponent(messageId)}/feedback`, input);
|
|
181
188
|
}
|
|
182
189
|
listThreads() {
|
|
183
|
-
return this.request("GET", "/
|
|
190
|
+
return this.request("GET", "/threads");
|
|
184
191
|
}
|
|
185
192
|
/**
|
|
186
193
|
* The skills this caller can invoke right now, scope-resolved — the same list, built by the same
|
|
@@ -190,7 +197,7 @@ var AgentClient = class {
|
|
|
190
197
|
*/
|
|
191
198
|
listSkills(threadId) {
|
|
192
199
|
const query = threadId === void 0 ? "" : `?threadId=${encodeURIComponent(threadId)}`;
|
|
193
|
-
return this.request("GET", `/
|
|
200
|
+
return this.request("GET", `/skills${query}`);
|
|
194
201
|
}
|
|
195
202
|
/**
|
|
196
203
|
* The tools this caller can reach through `agent` (the default agent when omitted), each with the
|
|
@@ -199,41 +206,37 @@ var AgentClient = class {
|
|
|
199
206
|
*/
|
|
200
207
|
listTools(agent) {
|
|
201
208
|
const query = agent === void 0 ? "" : `?agent=${encodeURIComponent(agent)}`;
|
|
202
|
-
return this.request("GET", `/
|
|
209
|
+
return this.request("GET", `/tools${query}`);
|
|
203
210
|
}
|
|
204
211
|
getThread(id) {
|
|
205
|
-
return this.request("GET", `/
|
|
212
|
+
return this.request("GET", `/threads/${encodeURIComponent(id)}`);
|
|
206
213
|
}
|
|
207
214
|
deleteThread(id) {
|
|
208
|
-
return this.request("DELETE", `/
|
|
215
|
+
return this.request("DELETE", `/threads/${encodeURIComponent(id)}`);
|
|
209
216
|
}
|
|
210
217
|
forkFromMessage(threadId, messageId) {
|
|
211
|
-
return this.request("POST", `/
|
|
212
|
-
}
|
|
213
|
-
renameThread(id, title) {
|
|
214
|
-
return this.updateThread(id, {
|
|
215
|
-
title
|
|
216
|
-
});
|
|
218
|
+
return this.request("POST", `/threads/${encodeURIComponent(threadId)}/fork-from/${encodeURIComponent(messageId)}`);
|
|
217
219
|
}
|
|
218
|
-
/** General `PATCH
|
|
220
|
+
/** General `PATCH <path>/threads/:threadId` — title and/or the thread's pinned default agent. */
|
|
219
221
|
updateThread(id, patch) {
|
|
220
|
-
return this.request("PATCH", `/
|
|
222
|
+
return this.request("PATCH", `/threads/${encodeURIComponent(id)}`, patch);
|
|
221
223
|
}
|
|
222
224
|
/**
|
|
223
225
|
* Uploads a file (image/PDF) for a vision-capable model turn. Multipart, field name `file` —
|
|
224
|
-
* mirrors the backend's `POST
|
|
226
|
+
* mirrors the backend's `POST <path>/attachments`. The returned {@link MessageAttachment} is
|
|
225
227
|
* what a caller then rides on `sendMessage({ text }, { body: { attachments: [...] } })`.
|
|
226
228
|
*/
|
|
227
229
|
async uploadAttachment(file, options = {}) {
|
|
228
|
-
|
|
229
|
-
|
|
230
|
+
const upload = this.options.attachments?.upload;
|
|
231
|
+
if (upload !== void 0) {
|
|
232
|
+
return upload(file, options, this.connection());
|
|
230
233
|
}
|
|
231
234
|
if (options.onProgress !== void 0 && this.options.fetch === void 0 && typeof XMLHttpRequest !== "undefined") {
|
|
232
235
|
return this.uploadWithProgress(file, options);
|
|
233
236
|
}
|
|
234
237
|
const formData = new FormData();
|
|
235
238
|
formData.append("file", file);
|
|
236
|
-
const response = await this.fetchImpl()(`${this.
|
|
239
|
+
const response = await this.fetchImpl()(`${this.root()}/attachments`, {
|
|
237
240
|
method: "POST",
|
|
238
241
|
headers: {
|
|
239
242
|
accept: "application/json",
|
|
@@ -245,7 +248,7 @@ var AgentClient = class {
|
|
|
245
248
|
signal: options.signal
|
|
246
249
|
} : {}
|
|
247
250
|
});
|
|
248
|
-
const attachment = await this.handleResponse(response, "POST",
|
|
251
|
+
const attachment = await this.handleResponse(response, "POST", `${this.agentPath()}/attachments`);
|
|
249
252
|
options.onProgress?.(1);
|
|
250
253
|
return attachment;
|
|
251
254
|
}
|
|
@@ -254,7 +257,7 @@ var AgentClient = class {
|
|
|
254
257
|
accept: "application/json",
|
|
255
258
|
...await this.resolveHeaders()
|
|
256
259
|
};
|
|
257
|
-
const url = `${this.
|
|
260
|
+
const url = `${this.root()}/attachments`;
|
|
258
261
|
return new Promise((resolve, reject) => {
|
|
259
262
|
const xhr = new XMLHttpRequest();
|
|
260
263
|
xhr.open("POST", url);
|
|
@@ -265,7 +268,7 @@ var AgentClient = class {
|
|
|
265
268
|
};
|
|
266
269
|
xhr.onload = () => {
|
|
267
270
|
if (xhr.status < 200 || xhr.status >= 300) {
|
|
268
|
-
reject(new AgentHttpError(xhr.status, "POST",
|
|
271
|
+
reject(new AgentHttpError(xhr.status, "POST", `${this.agentPath()}/attachments`, xhr.statusText));
|
|
269
272
|
return;
|
|
270
273
|
}
|
|
271
274
|
onProgress?.(1);
|
|
@@ -288,39 +291,36 @@ var AgentClient = class {
|
|
|
288
291
|
});
|
|
289
292
|
}
|
|
290
293
|
promoteThread(id) {
|
|
291
|
-
return this.request("POST", `/
|
|
294
|
+
return this.request("POST", `/threads/${encodeURIComponent(id)}/promote`);
|
|
292
295
|
}
|
|
293
296
|
truncateFromMessage(threadId, messageId) {
|
|
294
|
-
return this.request("DELETE", `/
|
|
297
|
+
return this.request("DELETE", `/threads/${encodeURIComponent(threadId)}/from/${encodeURIComponent(messageId)}`);
|
|
295
298
|
}
|
|
296
|
-
/** `GET
|
|
299
|
+
/** `GET <path>/models?agent=` — the models this caller may pick, grouped by provider. */
|
|
297
300
|
listModels(agent) {
|
|
298
301
|
const query = agent === void 0 ? "" : `?agent=${encodeURIComponent(agent)}`;
|
|
299
|
-
return this.request("GET", `/
|
|
302
|
+
return this.request("GET", `/models${query}`);
|
|
300
303
|
}
|
|
301
|
-
/** `GET
|
|
304
|
+
/** `GET <path>/agents` — the registered agents, the default one flagged. */
|
|
302
305
|
listAgents() {
|
|
303
|
-
return this.request("GET", "/
|
|
306
|
+
return this.request("GET", "/agents");
|
|
304
307
|
}
|
|
305
|
-
/** `GET
|
|
308
|
+
/** `GET <path>/quota` — the caller's budget windows and the one blocking sends, if any. */
|
|
306
309
|
getQuota() {
|
|
307
|
-
return this.request("GET", "/
|
|
308
|
-
}
|
|
309
|
-
getQuotaToday() {
|
|
310
|
-
return this.request("GET", "/agent/quota/today");
|
|
310
|
+
return this.request("GET", "/quota");
|
|
311
311
|
}
|
|
312
312
|
cancelStream(runId) {
|
|
313
|
-
return this.request("POST", `/
|
|
313
|
+
return this.request("POST", `/chat/${encodeURIComponent(runId)}/cancel`);
|
|
314
314
|
}
|
|
315
315
|
/**
|
|
316
316
|
* `remember` approves later calls of the same tool in the same thread; `via` names the surface
|
|
317
317
|
* the decision came through (the server records `'web'` when omitted).
|
|
318
318
|
*/
|
|
319
319
|
approveToolCall(input) {
|
|
320
|
-
return this.request("POST", "/
|
|
320
|
+
return this.request("POST", "/tool-call/approve", input);
|
|
321
321
|
}
|
|
322
322
|
rejectToolCall(input) {
|
|
323
|
-
return this.request("POST", "/
|
|
323
|
+
return this.request("POST", "/tool-call/reject", input);
|
|
324
324
|
}
|
|
325
325
|
/**
|
|
326
326
|
* Settle a parked question set. `answers` is questionId → chosen option values; a question left
|
|
@@ -329,7 +329,7 @@ var AgentClient = class {
|
|
|
329
329
|
* answer — which is the point of the surface, so it is a valid submission rather than a blank.
|
|
330
330
|
*/
|
|
331
331
|
answerToolCall(input) {
|
|
332
|
-
return this.request("POST", "/
|
|
332
|
+
return this.request("POST", "/tool-call/answer", input);
|
|
333
333
|
}
|
|
334
334
|
/**
|
|
335
335
|
* Decline to answer and let the agent proceed on its own pre-picked values. Lands on the same
|
|
@@ -337,7 +337,7 @@ var AgentClient = class {
|
|
|
337
337
|
* evidence the user chose them.
|
|
338
338
|
*/
|
|
339
339
|
skipToolCall(input) {
|
|
340
|
-
return this.request("POST", "/
|
|
340
|
+
return this.request("POST", "/tool-call/skip", input);
|
|
341
341
|
}
|
|
342
342
|
fetchImpl() {
|
|
343
343
|
return this.options.fetch ?? globalThis.fetch;
|
|
@@ -346,13 +346,21 @@ var AgentClient = class {
|
|
|
346
346
|
connection() {
|
|
347
347
|
return {
|
|
348
348
|
baseUrl: this.baseUrl(),
|
|
349
|
+
path: this.agentPath(),
|
|
349
350
|
headers: /* @__PURE__ */ __name(() => this.resolveHeaders(), "headers"),
|
|
350
351
|
fetch: this.fetchImpl(),
|
|
351
352
|
...this.credentials()
|
|
352
353
|
};
|
|
353
354
|
}
|
|
354
355
|
baseUrl() {
|
|
355
|
-
return (this.options.baseUrl ?? "").replace(
|
|
356
|
+
return (this.options.baseUrl ?? "").replace(/\/+$/, "");
|
|
357
|
+
}
|
|
358
|
+
agentPath() {
|
|
359
|
+
return normalizeAgentPath(this.options.path);
|
|
360
|
+
}
|
|
361
|
+
/** Origin + agent path: what every route hangs off. */
|
|
362
|
+
root() {
|
|
363
|
+
return `${this.baseUrl()}${this.agentPath()}`;
|
|
356
364
|
}
|
|
357
365
|
async resolveHeaders() {
|
|
358
366
|
const dynamic = await this.options.getHeaders?.() ?? {};
|
|
@@ -366,7 +374,8 @@ var AgentClient = class {
|
|
|
366
374
|
credentials: this.options.credentials
|
|
367
375
|
} : {};
|
|
368
376
|
}
|
|
369
|
-
async request(method,
|
|
377
|
+
async request(method, route, body) {
|
|
378
|
+
const path = `${this.agentPath()}${route}`;
|
|
370
379
|
const response = await this.fetchImpl()(`${this.baseUrl()}${path}`, {
|
|
371
380
|
method,
|
|
372
381
|
headers: {
|
|
@@ -497,6 +506,9 @@ var AgentChatTransport = class {
|
|
|
497
506
|
...options.baseUrl !== void 0 ? {
|
|
498
507
|
baseUrl: options.baseUrl
|
|
499
508
|
} : {},
|
|
509
|
+
...options.path !== void 0 ? {
|
|
510
|
+
path: options.path
|
|
511
|
+
} : {},
|
|
500
512
|
...options.headers !== void 0 ? {
|
|
501
513
|
headers: options.headers
|
|
502
514
|
} : {},
|
|
@@ -708,13 +720,14 @@ var AgentChatTransport = class {
|
|
|
708
720
|
function ensureStarted() {
|
|
709
721
|
if (started) return;
|
|
710
722
|
started = true;
|
|
711
|
-
controller.enqueue(
|
|
723
|
+
controller.enqueue({
|
|
712
724
|
type: "start",
|
|
713
725
|
messageMetadata: {
|
|
714
|
-
|
|
726
|
+
...streamRunId !== void 0 ? {
|
|
727
|
+
runId: streamRunId
|
|
728
|
+
} : {},
|
|
729
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
715
730
|
}
|
|
716
|
-
} : {
|
|
717
|
-
type: "start"
|
|
718
731
|
});
|
|
719
732
|
}
|
|
720
733
|
__name(ensureStarted, "ensureStarted");
|
|
@@ -1202,7 +1215,7 @@ function dragHasFiles(data) {
|
|
|
1202
1215
|
__name(dragHasFiles, "dragHasFiles");
|
|
1203
1216
|
|
|
1204
1217
|
// src/attachments/use-attachments.ts
|
|
1205
|
-
var
|
|
1218
|
+
var import_react6 = require("react");
|
|
1206
1219
|
|
|
1207
1220
|
// src/backend.ts
|
|
1208
1221
|
var AgentBackendUnsupportedError = class extends Error {
|
|
@@ -1224,6 +1237,570 @@ function requireBackendMethod(backend, name) {
|
|
|
1224
1237
|
}
|
|
1225
1238
|
__name(requireBackendMethod, "requireBackendMethod");
|
|
1226
1239
|
|
|
1240
|
+
// src/provider.tsx
|
|
1241
|
+
var import_react5 = require("react");
|
|
1242
|
+
|
|
1243
|
+
// src/components/ambient-ui.ts
|
|
1244
|
+
var import_react2 = require("react");
|
|
1245
|
+
function sharedContext(key) {
|
|
1246
|
+
const symbol = Symbol.for(key);
|
|
1247
|
+
const holder = globalThis;
|
|
1248
|
+
const existing = holder[symbol];
|
|
1249
|
+
if (existing !== void 0) return existing;
|
|
1250
|
+
const created = (0, import_react2.createContext)(null);
|
|
1251
|
+
holder[symbol] = created;
|
|
1252
|
+
return created;
|
|
1253
|
+
}
|
|
1254
|
+
__name(sharedContext, "sharedContext");
|
|
1255
|
+
var AmbientRenderUiContext = sharedContext("@dudousxd/nestjs-agent-react:ambient-render-ui");
|
|
1256
|
+
function useAmbientRenderUi() {
|
|
1257
|
+
return (0, import_react2.useContext)(AmbientRenderUiContext);
|
|
1258
|
+
}
|
|
1259
|
+
__name(useAmbientRenderUi, "useAmbientRenderUi");
|
|
1260
|
+
|
|
1261
|
+
// src/genui/generative-ui.tsx
|
|
1262
|
+
var import_react4 = require("react");
|
|
1263
|
+
|
|
1264
|
+
// src/genui/use-generative-ui.ts
|
|
1265
|
+
var import_react3 = require("react");
|
|
1266
|
+
|
|
1267
|
+
// src/genui/types.ts
|
|
1268
|
+
var GENUI_TREE_COMPONENT = "genui:tree";
|
|
1269
|
+
|
|
1270
|
+
// src/genui/use-generative-ui.ts
|
|
1271
|
+
function isRecord(value) {
|
|
1272
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1273
|
+
}
|
|
1274
|
+
__name(isRecord, "isRecord");
|
|
1275
|
+
function toGenerativeUIItem(part) {
|
|
1276
|
+
if (!isRecord(part)) return null;
|
|
1277
|
+
const source = part.type === "data-ui" && isRecord(part.data) ? part.data : part;
|
|
1278
|
+
if (typeof source.component !== "string") return null;
|
|
1279
|
+
const id = typeof source.id === "string" ? source.id : typeof part.id === "string" ? part.id : null;
|
|
1280
|
+
if (id === null) return null;
|
|
1281
|
+
return {
|
|
1282
|
+
id,
|
|
1283
|
+
component: source.component,
|
|
1284
|
+
props: isRecord(source.props) ? source.props : {},
|
|
1285
|
+
version: typeof source.version === "number" ? source.version : null,
|
|
1286
|
+
toolCallId: typeof source.toolCallId === "string" ? source.toolCallId : null
|
|
1287
|
+
};
|
|
1288
|
+
}
|
|
1289
|
+
__name(toGenerativeUIItem, "toGenerativeUIItem");
|
|
1290
|
+
var resolverCaches = /* @__PURE__ */ new WeakMap();
|
|
1291
|
+
function resolveCached(resolve, name, version) {
|
|
1292
|
+
let cache = resolverCaches.get(resolve);
|
|
1293
|
+
if (cache === void 0) {
|
|
1294
|
+
cache = /* @__PURE__ */ new Map();
|
|
1295
|
+
resolverCaches.set(resolve, cache);
|
|
1296
|
+
}
|
|
1297
|
+
const key = `${name}@${version ?? ""}`;
|
|
1298
|
+
const hit = cache.get(key);
|
|
1299
|
+
if (hit !== void 0) return hit;
|
|
1300
|
+
let entry;
|
|
1301
|
+
try {
|
|
1302
|
+
const result = resolve(name, version);
|
|
1303
|
+
if (result instanceof Promise) {
|
|
1304
|
+
entry = {
|
|
1305
|
+
resolution: {
|
|
1306
|
+
status: "loading"
|
|
1307
|
+
},
|
|
1308
|
+
settled: null
|
|
1309
|
+
};
|
|
1310
|
+
entry.settled = result.then((Component2) => {
|
|
1311
|
+
entry.resolution = Component2 ? {
|
|
1312
|
+
status: "ready",
|
|
1313
|
+
Component: Component2
|
|
1314
|
+
} : {
|
|
1315
|
+
status: "unknown"
|
|
1316
|
+
};
|
|
1317
|
+
}, (error) => {
|
|
1318
|
+
entry.resolution = {
|
|
1319
|
+
status: "error",
|
|
1320
|
+
error
|
|
1321
|
+
};
|
|
1322
|
+
});
|
|
1323
|
+
} else {
|
|
1324
|
+
entry = {
|
|
1325
|
+
resolution: result ? {
|
|
1326
|
+
status: "ready",
|
|
1327
|
+
Component: result
|
|
1328
|
+
} : {
|
|
1329
|
+
status: "unknown"
|
|
1330
|
+
},
|
|
1331
|
+
settled: null
|
|
1332
|
+
};
|
|
1333
|
+
}
|
|
1334
|
+
} catch (error) {
|
|
1335
|
+
entry = {
|
|
1336
|
+
resolution: {
|
|
1337
|
+
status: "error",
|
|
1338
|
+
error
|
|
1339
|
+
},
|
|
1340
|
+
settled: null
|
|
1341
|
+
};
|
|
1342
|
+
}
|
|
1343
|
+
cache.set(key, entry);
|
|
1344
|
+
return entry;
|
|
1345
|
+
}
|
|
1346
|
+
__name(resolveCached, "resolveCached");
|
|
1347
|
+
function useResolvedComponent(name, version, registry, resolve, fallbackTree) {
|
|
1348
|
+
const [, setTick] = (0, import_react3.useState)(0);
|
|
1349
|
+
const own = registry[name];
|
|
1350
|
+
const entry = own !== void 0 || resolve === void 0 ? null : resolveCached(resolve, name, version);
|
|
1351
|
+
const pending = entry?.resolution.status === "loading" ? entry.settled : null;
|
|
1352
|
+
(0, import_react3.useEffect)(() => {
|
|
1353
|
+
if (pending === null) return;
|
|
1354
|
+
let live = true;
|
|
1355
|
+
void pending.then(() => {
|
|
1356
|
+
if (live) setTick((tick) => tick + 1);
|
|
1357
|
+
});
|
|
1358
|
+
return () => {
|
|
1359
|
+
live = false;
|
|
1360
|
+
};
|
|
1361
|
+
}, [
|
|
1362
|
+
pending
|
|
1363
|
+
]);
|
|
1364
|
+
if (own !== void 0) return {
|
|
1365
|
+
status: "ready",
|
|
1366
|
+
Component: own
|
|
1367
|
+
};
|
|
1368
|
+
if (entry !== null && entry.resolution.status !== "unknown") return entry.resolution;
|
|
1369
|
+
if (name === GENUI_TREE_COMPONENT && fallbackTree !== void 0) {
|
|
1370
|
+
return {
|
|
1371
|
+
status: "ready",
|
|
1372
|
+
Component: fallbackTree
|
|
1373
|
+
};
|
|
1374
|
+
}
|
|
1375
|
+
return {
|
|
1376
|
+
status: "unknown"
|
|
1377
|
+
};
|
|
1378
|
+
}
|
|
1379
|
+
__name(useResolvedComponent, "useResolvedComponent");
|
|
1380
|
+
function useValidatedProps(catalog, name, props) {
|
|
1381
|
+
const checked = catalog?.has(name) === true;
|
|
1382
|
+
const immediate = (0, import_react3.useMemo)(() => {
|
|
1383
|
+
if (!checked || catalog === void 0) return {
|
|
1384
|
+
status: "ok",
|
|
1385
|
+
props
|
|
1386
|
+
};
|
|
1387
|
+
const result = catalog.validateSync?.(name, props);
|
|
1388
|
+
if (result === void 0) return null;
|
|
1389
|
+
return result.ok ? {
|
|
1390
|
+
status: "ok",
|
|
1391
|
+
props: result.value
|
|
1392
|
+
} : {
|
|
1393
|
+
status: "invalid",
|
|
1394
|
+
issues: result.issues
|
|
1395
|
+
};
|
|
1396
|
+
}, [
|
|
1397
|
+
checked,
|
|
1398
|
+
catalog,
|
|
1399
|
+
name,
|
|
1400
|
+
props
|
|
1401
|
+
]);
|
|
1402
|
+
const [late, setLate] = (0, import_react3.useState)(null);
|
|
1403
|
+
(0, import_react3.useEffect)(() => {
|
|
1404
|
+
if (immediate !== null || catalog === void 0) return;
|
|
1405
|
+
let live = true;
|
|
1406
|
+
catalog.validate(name, props).then((result) => {
|
|
1407
|
+
if (!live) return;
|
|
1408
|
+
setLate({
|
|
1409
|
+
props,
|
|
1410
|
+
result: result.ok ? {
|
|
1411
|
+
status: "ok",
|
|
1412
|
+
props: result.value
|
|
1413
|
+
} : {
|
|
1414
|
+
status: "invalid",
|
|
1415
|
+
issues: result.issues
|
|
1416
|
+
}
|
|
1417
|
+
});
|
|
1418
|
+
}, (error) => {
|
|
1419
|
+
if (!live) return;
|
|
1420
|
+
setLate({
|
|
1421
|
+
props,
|
|
1422
|
+
result: {
|
|
1423
|
+
status: "invalid",
|
|
1424
|
+
issues: [
|
|
1425
|
+
{
|
|
1426
|
+
path: [],
|
|
1427
|
+
message: error instanceof Error ? error.message : String(error)
|
|
1428
|
+
}
|
|
1429
|
+
]
|
|
1430
|
+
}
|
|
1431
|
+
});
|
|
1432
|
+
});
|
|
1433
|
+
return () => {
|
|
1434
|
+
live = false;
|
|
1435
|
+
};
|
|
1436
|
+
}, [
|
|
1437
|
+
immediate,
|
|
1438
|
+
catalog,
|
|
1439
|
+
name,
|
|
1440
|
+
props
|
|
1441
|
+
]);
|
|
1442
|
+
if (immediate !== null) return immediate;
|
|
1443
|
+
return late !== null && late.props === props ? late.result : {
|
|
1444
|
+
status: "pending"
|
|
1445
|
+
};
|
|
1446
|
+
}
|
|
1447
|
+
__name(useValidatedProps, "useValidatedProps");
|
|
1448
|
+
function useGenerativeUIState(part, options, fallbackTree) {
|
|
1449
|
+
const item = (0, import_react3.useMemo)(() => toGenerativeUIItem(part), [
|
|
1450
|
+
part
|
|
1451
|
+
]);
|
|
1452
|
+
const name = item?.component ?? "";
|
|
1453
|
+
const resolution = useResolvedComponent(name, item?.version ?? null, options.registry, item === null ? void 0 : options.resolveComponent, fallbackTree);
|
|
1454
|
+
const empty = (0, import_react3.useMemo)(() => ({}), []);
|
|
1455
|
+
const validation = useValidatedProps(item === null || name === GENUI_TREE_COMPONENT ? void 0 : options.catalog, name, item?.props ?? empty);
|
|
1456
|
+
if (item === null) return null;
|
|
1457
|
+
if (resolution.status === "loading") return {
|
|
1458
|
+
status: "loading",
|
|
1459
|
+
item
|
|
1460
|
+
};
|
|
1461
|
+
if (resolution.status === "unknown") return {
|
|
1462
|
+
status: "problem",
|
|
1463
|
+
reason: "unknown",
|
|
1464
|
+
item
|
|
1465
|
+
};
|
|
1466
|
+
if (resolution.status === "error") {
|
|
1467
|
+
return {
|
|
1468
|
+
status: "problem",
|
|
1469
|
+
reason: "error",
|
|
1470
|
+
item,
|
|
1471
|
+
error: resolution.error
|
|
1472
|
+
};
|
|
1473
|
+
}
|
|
1474
|
+
if (validation.status === "pending") return {
|
|
1475
|
+
status: "loading",
|
|
1476
|
+
item
|
|
1477
|
+
};
|
|
1478
|
+
if (validation.status === "invalid") {
|
|
1479
|
+
return {
|
|
1480
|
+
status: "problem",
|
|
1481
|
+
reason: "invalid",
|
|
1482
|
+
item,
|
|
1483
|
+
issues: validation.issues
|
|
1484
|
+
};
|
|
1485
|
+
}
|
|
1486
|
+
return {
|
|
1487
|
+
status: "ready",
|
|
1488
|
+
item,
|
|
1489
|
+
Component: resolution.Component,
|
|
1490
|
+
props: validation.props
|
|
1491
|
+
};
|
|
1492
|
+
}
|
|
1493
|
+
__name(useGenerativeUIState, "useGenerativeUIState");
|
|
1494
|
+
|
|
1495
|
+
// src/genui/generative-ui.tsx
|
|
1496
|
+
var TreeScopeContext = /* @__PURE__ */ (0, import_react4.createContext)(null);
|
|
1497
|
+
function renderFallback(fallback2, problem) {
|
|
1498
|
+
if (typeof fallback2 === "function") return fallback2(problem);
|
|
1499
|
+
return fallback2 ?? null;
|
|
1500
|
+
}
|
|
1501
|
+
__name(renderFallback, "renderFallback");
|
|
1502
|
+
var ItemBoundary = class ItemBoundary2 extends import_react4.Component {
|
|
1503
|
+
static {
|
|
1504
|
+
__name(this, "ItemBoundary");
|
|
1505
|
+
}
|
|
1506
|
+
state = {
|
|
1507
|
+
error: void 0,
|
|
1508
|
+
failed: false
|
|
1509
|
+
};
|
|
1510
|
+
static getDerivedStateFromError(error) {
|
|
1511
|
+
return {
|
|
1512
|
+
error,
|
|
1513
|
+
failed: true
|
|
1514
|
+
};
|
|
1515
|
+
}
|
|
1516
|
+
componentDidCatch(error, _info) {
|
|
1517
|
+
this.props.onError?.(error, this.props.item);
|
|
1518
|
+
}
|
|
1519
|
+
componentDidUpdate(previous) {
|
|
1520
|
+
if (this.state.failed && previous.item !== this.props.item) {
|
|
1521
|
+
this.setState({
|
|
1522
|
+
error: void 0,
|
|
1523
|
+
failed: false
|
|
1524
|
+
});
|
|
1525
|
+
}
|
|
1526
|
+
}
|
|
1527
|
+
render() {
|
|
1528
|
+
if (this.state.failed) {
|
|
1529
|
+
return renderFallback(this.props.fallback, {
|
|
1530
|
+
reason: "error",
|
|
1531
|
+
item: this.props.item,
|
|
1532
|
+
error: this.state.error
|
|
1533
|
+
});
|
|
1534
|
+
}
|
|
1535
|
+
return this.props.children;
|
|
1536
|
+
}
|
|
1537
|
+
};
|
|
1538
|
+
function nodeItem(node, id) {
|
|
1539
|
+
return {
|
|
1540
|
+
id,
|
|
1541
|
+
component: node.type,
|
|
1542
|
+
props: node.props ?? {},
|
|
1543
|
+
version: null,
|
|
1544
|
+
toolCallId: null
|
|
1545
|
+
};
|
|
1546
|
+
}
|
|
1547
|
+
__name(nodeItem, "nodeItem");
|
|
1548
|
+
function TreeNode({ node, id }) {
|
|
1549
|
+
const scope = (0, import_react4.useContext)(TreeScopeContext);
|
|
1550
|
+
const item = (0, import_react4.useMemo)(() => nodeItem(node, id), [
|
|
1551
|
+
node,
|
|
1552
|
+
id
|
|
1553
|
+
]);
|
|
1554
|
+
const resolution = useResolvedComponent(node.type, null, scope?.options.registry ?? {}, scope?.options.resolveComponent);
|
|
1555
|
+
const validation = useValidatedProps(scope?.options.catalog, node.type, item.props);
|
|
1556
|
+
if (scope === null) return null;
|
|
1557
|
+
if (resolution.status === "loading" || validation.status === "pending") return scope.loading;
|
|
1558
|
+
if (resolution.status === "unknown") {
|
|
1559
|
+
return renderFallback(scope.fallback, {
|
|
1560
|
+
reason: "unknown",
|
|
1561
|
+
item
|
|
1562
|
+
});
|
|
1563
|
+
}
|
|
1564
|
+
if (resolution.status === "error") {
|
|
1565
|
+
return renderFallback(scope.fallback, {
|
|
1566
|
+
reason: "error",
|
|
1567
|
+
item,
|
|
1568
|
+
error: resolution.error
|
|
1569
|
+
});
|
|
1570
|
+
}
|
|
1571
|
+
if (validation.status === "invalid") {
|
|
1572
|
+
return renderFallback(scope.fallback, {
|
|
1573
|
+
reason: "invalid",
|
|
1574
|
+
item,
|
|
1575
|
+
issues: validation.issues
|
|
1576
|
+
});
|
|
1577
|
+
}
|
|
1578
|
+
const Renderer = resolution.Component;
|
|
1579
|
+
const children = Array.isArray(node.children) ? node.children : [];
|
|
1580
|
+
return /* @__PURE__ */ React.createElement(Renderer, validation.props, children.length > 0 ? children.map((child, index) => {
|
|
1581
|
+
const childId = `${id}.${index}`;
|
|
1582
|
+
return /* @__PURE__ */ React.createElement(ItemBoundary, {
|
|
1583
|
+
key: childId,
|
|
1584
|
+
item: nodeItem(child, childId),
|
|
1585
|
+
fallback: scope.fallback,
|
|
1586
|
+
onError: scope.onError
|
|
1587
|
+
}, /* @__PURE__ */ React.createElement(TreeNode, {
|
|
1588
|
+
node: child,
|
|
1589
|
+
id: childId
|
|
1590
|
+
}));
|
|
1591
|
+
}) : void 0);
|
|
1592
|
+
}
|
|
1593
|
+
__name(TreeNode, "TreeNode");
|
|
1594
|
+
function GenuiTree({ root }) {
|
|
1595
|
+
if (root === void 0 || root === null || typeof root.type !== "string") return null;
|
|
1596
|
+
return /* @__PURE__ */ React.createElement(TreeNode, {
|
|
1597
|
+
node: root,
|
|
1598
|
+
id: "root"
|
|
1599
|
+
});
|
|
1600
|
+
}
|
|
1601
|
+
__name(GenuiTree, "GenuiTree");
|
|
1602
|
+
function GenerativeUIScope({ registry, catalog, resolveComponent, fallback: fallback2, loading = null, onError, children }) {
|
|
1603
|
+
const scope = (0, import_react4.useMemo)(() => ({
|
|
1604
|
+
options: {
|
|
1605
|
+
registry,
|
|
1606
|
+
...catalog !== void 0 ? {
|
|
1607
|
+
catalog
|
|
1608
|
+
} : {},
|
|
1609
|
+
...resolveComponent !== void 0 ? {
|
|
1610
|
+
resolveComponent
|
|
1611
|
+
} : {}
|
|
1612
|
+
},
|
|
1613
|
+
fallback: fallback2,
|
|
1614
|
+
loading,
|
|
1615
|
+
onError
|
|
1616
|
+
}), [
|
|
1617
|
+
registry,
|
|
1618
|
+
catalog,
|
|
1619
|
+
resolveComponent,
|
|
1620
|
+
fallback2,
|
|
1621
|
+
loading,
|
|
1622
|
+
onError
|
|
1623
|
+
]);
|
|
1624
|
+
return /* @__PURE__ */ React.createElement(TreeScopeContext.Provider, {
|
|
1625
|
+
value: scope
|
|
1626
|
+
}, children);
|
|
1627
|
+
}
|
|
1628
|
+
__name(GenerativeUIScope, "GenerativeUIScope");
|
|
1629
|
+
var GenuiContext = sharedContext("@dudousxd/nestjs-agent-react:genui-provider");
|
|
1630
|
+
function GenuiProvider({ registry, catalog, resolveComponent, treeRenderer, fallback: fallback2, loading, onError, children }) {
|
|
1631
|
+
const value = (0, import_react4.useMemo)(() => ({
|
|
1632
|
+
...registry !== void 0 ? {
|
|
1633
|
+
registry
|
|
1634
|
+
} : {},
|
|
1635
|
+
...catalog !== void 0 ? {
|
|
1636
|
+
catalog
|
|
1637
|
+
} : {},
|
|
1638
|
+
...resolveComponent !== void 0 ? {
|
|
1639
|
+
resolveComponent
|
|
1640
|
+
} : {},
|
|
1641
|
+
...treeRenderer !== void 0 ? {
|
|
1642
|
+
treeRenderer
|
|
1643
|
+
} : {},
|
|
1644
|
+
...fallback2 !== void 0 ? {
|
|
1645
|
+
fallback: fallback2
|
|
1646
|
+
} : {},
|
|
1647
|
+
...loading !== void 0 ? {
|
|
1648
|
+
loading
|
|
1649
|
+
} : {},
|
|
1650
|
+
...onError !== void 0 ? {
|
|
1651
|
+
onError
|
|
1652
|
+
} : {}
|
|
1653
|
+
}), [
|
|
1654
|
+
registry,
|
|
1655
|
+
catalog,
|
|
1656
|
+
resolveComponent,
|
|
1657
|
+
treeRenderer,
|
|
1658
|
+
fallback2,
|
|
1659
|
+
loading,
|
|
1660
|
+
onError
|
|
1661
|
+
]);
|
|
1662
|
+
const renderUi = (0, import_react4.useCallback)((block) => /* @__PURE__ */ React.createElement(GenerativeUI, {
|
|
1663
|
+
part: block
|
|
1664
|
+
}), []);
|
|
1665
|
+
return /* @__PURE__ */ React.createElement(GenuiContext.Provider, {
|
|
1666
|
+
value
|
|
1667
|
+
}, /* @__PURE__ */ React.createElement(AmbientRenderUiContext.Provider, {
|
|
1668
|
+
value: renderUi
|
|
1669
|
+
}, children));
|
|
1670
|
+
}
|
|
1671
|
+
__name(GenuiProvider, "GenuiProvider");
|
|
1672
|
+
var NO_REGISTRY = {};
|
|
1673
|
+
function useMergedOptions(own) {
|
|
1674
|
+
const provided = (0, import_react4.useContext)(GenuiContext);
|
|
1675
|
+
const registry = own.registry ?? provided?.registry ?? NO_REGISTRY;
|
|
1676
|
+
const catalog = own.catalog ?? provided?.catalog;
|
|
1677
|
+
const resolveComponent = own.resolveComponent ?? provided?.resolveComponent;
|
|
1678
|
+
const treeRenderer = own.treeRenderer ?? provided?.treeRenderer;
|
|
1679
|
+
return (0, import_react4.useMemo)(() => ({
|
|
1680
|
+
registry,
|
|
1681
|
+
...catalog !== void 0 ? {
|
|
1682
|
+
catalog
|
|
1683
|
+
} : {},
|
|
1684
|
+
...resolveComponent !== void 0 ? {
|
|
1685
|
+
resolveComponent
|
|
1686
|
+
} : {},
|
|
1687
|
+
...treeRenderer !== void 0 ? {
|
|
1688
|
+
treeRenderer
|
|
1689
|
+
} : {}
|
|
1690
|
+
}), [
|
|
1691
|
+
registry,
|
|
1692
|
+
catalog,
|
|
1693
|
+
resolveComponent,
|
|
1694
|
+
treeRenderer
|
|
1695
|
+
]);
|
|
1696
|
+
}
|
|
1697
|
+
__name(useMergedOptions, "useMergedOptions");
|
|
1698
|
+
function GenerativeUI({ part, registry, catalog, resolveComponent, treeRenderer, fallback: ownFallback, loading: ownLoading, onError: ownOnError }) {
|
|
1699
|
+
const provided = (0, import_react4.useContext)(GenuiContext);
|
|
1700
|
+
const fallback2 = ownFallback ?? provided?.fallback;
|
|
1701
|
+
const loading = ownLoading ?? provided?.loading ?? null;
|
|
1702
|
+
const onError = ownOnError ?? provided?.onError;
|
|
1703
|
+
const options = useMergedOptions({
|
|
1704
|
+
...registry !== void 0 ? {
|
|
1705
|
+
registry
|
|
1706
|
+
} : {},
|
|
1707
|
+
...catalog !== void 0 ? {
|
|
1708
|
+
catalog
|
|
1709
|
+
} : {},
|
|
1710
|
+
...resolveComponent !== void 0 ? {
|
|
1711
|
+
resolveComponent
|
|
1712
|
+
} : {},
|
|
1713
|
+
...treeRenderer !== void 0 ? {
|
|
1714
|
+
treeRenderer
|
|
1715
|
+
} : {}
|
|
1716
|
+
});
|
|
1717
|
+
const state = useGenerativeUIState(part, options, options.treeRenderer ?? GenuiTree);
|
|
1718
|
+
if (state === null) return null;
|
|
1719
|
+
if (state.status === "loading") return loading;
|
|
1720
|
+
if (state.status === "problem") {
|
|
1721
|
+
const { status: _status, ...problem } = state;
|
|
1722
|
+
return renderFallback(fallback2, problem);
|
|
1723
|
+
}
|
|
1724
|
+
const Renderer = state.Component;
|
|
1725
|
+
return /* @__PURE__ */ React.createElement(GenerativeUIScope, {
|
|
1726
|
+
...options,
|
|
1727
|
+
fallback: fallback2,
|
|
1728
|
+
loading,
|
|
1729
|
+
...onError !== void 0 ? {
|
|
1730
|
+
onError
|
|
1731
|
+
} : {}
|
|
1732
|
+
}, /* @__PURE__ */ React.createElement(ItemBoundary, {
|
|
1733
|
+
item: state.item,
|
|
1734
|
+
fallback: fallback2,
|
|
1735
|
+
onError
|
|
1736
|
+
}, /* @__PURE__ */ React.createElement(Renderer, state.props)));
|
|
1737
|
+
}
|
|
1738
|
+
__name(GenerativeUI, "GenerativeUI");
|
|
1739
|
+
|
|
1740
|
+
// src/provider.tsx
|
|
1741
|
+
var AgentBackendContext = sharedContext("@dudousxd/nestjs-agent-react:agent-backend");
|
|
1742
|
+
function AgentProvider({ backend, baseUrl, path, headers, getHeaders, credentials, fetch, attachments, genui, children }) {
|
|
1743
|
+
const latestHeaders = (0, import_react5.useRef)({
|
|
1744
|
+
headers,
|
|
1745
|
+
getHeaders
|
|
1746
|
+
});
|
|
1747
|
+
latestHeaders.current = {
|
|
1748
|
+
headers,
|
|
1749
|
+
getHeaders
|
|
1750
|
+
};
|
|
1751
|
+
const upload = attachments?.upload;
|
|
1752
|
+
const value = (0, import_react5.useMemo)(() => backend ?? new AgentClient({
|
|
1753
|
+
...baseUrl !== void 0 ? {
|
|
1754
|
+
baseUrl
|
|
1755
|
+
} : {},
|
|
1756
|
+
...path !== void 0 ? {
|
|
1757
|
+
path
|
|
1758
|
+
} : {},
|
|
1759
|
+
...credentials !== void 0 ? {
|
|
1760
|
+
credentials
|
|
1761
|
+
} : {},
|
|
1762
|
+
...fetch !== void 0 ? {
|
|
1763
|
+
fetch
|
|
1764
|
+
} : {},
|
|
1765
|
+
...upload !== void 0 ? {
|
|
1766
|
+
attachments: {
|
|
1767
|
+
upload
|
|
1768
|
+
}
|
|
1769
|
+
} : {},
|
|
1770
|
+
getHeaders: /* @__PURE__ */ __name(async () => {
|
|
1771
|
+
const current = latestHeaders.current;
|
|
1772
|
+
const dynamic = await current.getHeaders?.() ?? {};
|
|
1773
|
+
return {
|
|
1774
|
+
...current.headers,
|
|
1775
|
+
...dynamic
|
|
1776
|
+
};
|
|
1777
|
+
}, "getHeaders")
|
|
1778
|
+
}), [
|
|
1779
|
+
backend,
|
|
1780
|
+
baseUrl,
|
|
1781
|
+
path,
|
|
1782
|
+
credentials,
|
|
1783
|
+
fetch,
|
|
1784
|
+
upload
|
|
1785
|
+
]);
|
|
1786
|
+
const content = genui !== void 0 ? /* @__PURE__ */ React.createElement(GenuiProvider, genui, children) : children;
|
|
1787
|
+
return /* @__PURE__ */ React.createElement(AgentBackendContext.Provider, {
|
|
1788
|
+
value
|
|
1789
|
+
}, content);
|
|
1790
|
+
}
|
|
1791
|
+
__name(AgentProvider, "AgentProvider");
|
|
1792
|
+
var fallback;
|
|
1793
|
+
function defaultBackend() {
|
|
1794
|
+
fallback ??= new AgentClient();
|
|
1795
|
+
return fallback;
|
|
1796
|
+
}
|
|
1797
|
+
__name(defaultBackend, "defaultBackend");
|
|
1798
|
+
function useAgentBackend(own) {
|
|
1799
|
+
const provided = (0, import_react5.useContext)(AgentBackendContext);
|
|
1800
|
+
return own ?? provided ?? defaultBackend();
|
|
1801
|
+
}
|
|
1802
|
+
__name(useAgentBackend, "useAgentBackend");
|
|
1803
|
+
|
|
1227
1804
|
// src/attachments/use-attachments.ts
|
|
1228
1805
|
var DEFAULT_REJECTION = {
|
|
1229
1806
|
type: /* @__PURE__ */ __name((file) => `${file.name} is not a supported file type`, "type"),
|
|
@@ -1231,23 +1808,30 @@ var DEFAULT_REJECTION = {
|
|
|
1231
1808
|
count: /* @__PURE__ */ __name(() => "Too many files", "count")
|
|
1232
1809
|
};
|
|
1233
1810
|
var sequence = 0;
|
|
1234
|
-
function useAttachments(options) {
|
|
1235
|
-
const
|
|
1236
|
-
latest
|
|
1237
|
-
|
|
1238
|
-
|
|
1811
|
+
function useAttachments(options = {}) {
|
|
1812
|
+
const backend = useAgentBackend(options.backend);
|
|
1813
|
+
const latest = (0, import_react6.useRef)({
|
|
1814
|
+
...options,
|
|
1815
|
+
backend
|
|
1816
|
+
});
|
|
1817
|
+
latest.current = {
|
|
1818
|
+
...options,
|
|
1819
|
+
backend
|
|
1820
|
+
};
|
|
1821
|
+
const [items, setItems] = (0, import_react6.useState)([]);
|
|
1822
|
+
const itemsRef = (0, import_react6.useRef)(items);
|
|
1239
1823
|
itemsRef.current = items;
|
|
1240
|
-
const controllers = (0,
|
|
1241
|
-
const [dragDepth, setDragDepth] = (0,
|
|
1242
|
-
const patch = (0,
|
|
1824
|
+
const controllers = (0, import_react6.useRef)(/* @__PURE__ */ new Map());
|
|
1825
|
+
const [dragDepth, setDragDepth] = (0, import_react6.useState)(0);
|
|
1826
|
+
const patch = (0, import_react6.useCallback)((id, change) => {
|
|
1243
1827
|
setItems((current) => current.map((item) => item.id === id ? {
|
|
1244
1828
|
...item,
|
|
1245
1829
|
...change
|
|
1246
1830
|
} : item));
|
|
1247
1831
|
}, []);
|
|
1248
|
-
const start = (0,
|
|
1249
|
-
const { upload, backend } = latest.current;
|
|
1250
|
-
const run = upload ?? (
|
|
1832
|
+
const start = (0, import_react6.useCallback)((item) => {
|
|
1833
|
+
const { upload, backend: backend2 } = latest.current;
|
|
1834
|
+
const run = upload ?? (backend2.uploadAttachment !== void 0 ? backend2.uploadAttachment.bind(backend2) : void 0);
|
|
1251
1835
|
if (run === void 0) {
|
|
1252
1836
|
patch(item.id, {
|
|
1253
1837
|
status: "error",
|
|
@@ -1281,7 +1865,7 @@ function useAttachments(options) {
|
|
|
1281
1865
|
}, [
|
|
1282
1866
|
patch
|
|
1283
1867
|
]);
|
|
1284
|
-
const add = (0,
|
|
1868
|
+
const add = (0, import_react6.useCallback)((files) => {
|
|
1285
1869
|
if (files == null) return;
|
|
1286
1870
|
const { accept: accept2, maxBytes, maxFiles, describeRejection } = latest.current;
|
|
1287
1871
|
const describe = /* @__PURE__ */ __name((reason, file) => describeRejection?.(reason, file) ?? DEFAULT_REJECTION[reason](file), "describe");
|
|
@@ -1327,7 +1911,7 @@ function useAttachments(options) {
|
|
|
1327
1911
|
}, [
|
|
1328
1912
|
start
|
|
1329
1913
|
]);
|
|
1330
|
-
const release = (0,
|
|
1914
|
+
const release = (0, import_react6.useCallback)((item) => {
|
|
1331
1915
|
if (item === void 0) return;
|
|
1332
1916
|
controllers.current.get(item.id)?.abort();
|
|
1333
1917
|
controllers.current.delete(item.id);
|
|
@@ -1335,19 +1919,19 @@ function useAttachments(options) {
|
|
|
1335
1919
|
URL.revokeObjectURL(item.previewUrl);
|
|
1336
1920
|
}
|
|
1337
1921
|
}, []);
|
|
1338
|
-
const remove = (0,
|
|
1922
|
+
const remove = (0, import_react6.useCallback)((id) => {
|
|
1339
1923
|
release(itemsRef.current.find((item) => item.id === id));
|
|
1340
1924
|
setItems((current) => current.filter((item) => item.id !== id));
|
|
1341
1925
|
}, [
|
|
1342
1926
|
release
|
|
1343
1927
|
]);
|
|
1344
|
-
const clear = (0,
|
|
1928
|
+
const clear = (0, import_react6.useCallback)(() => {
|
|
1345
1929
|
for (const item of itemsRef.current) release(item);
|
|
1346
1930
|
setItems([]);
|
|
1347
1931
|
}, [
|
|
1348
1932
|
release
|
|
1349
1933
|
]);
|
|
1350
|
-
const retry = (0,
|
|
1934
|
+
const retry = (0, import_react6.useCallback)((id) => {
|
|
1351
1935
|
const item = itemsRef.current.find((candidate) => candidate.id === id);
|
|
1352
1936
|
if (item === void 0 || item.status !== "error") return;
|
|
1353
1937
|
const { error: _previous, ...rest } = item;
|
|
@@ -1361,12 +1945,12 @@ function useAttachments(options) {
|
|
|
1361
1945
|
}, [
|
|
1362
1946
|
start
|
|
1363
1947
|
]);
|
|
1364
|
-
(0,
|
|
1948
|
+
(0, import_react6.useEffect)(() => () => {
|
|
1365
1949
|
for (const item of itemsRef.current) release(item);
|
|
1366
1950
|
}, [
|
|
1367
1951
|
release
|
|
1368
1952
|
]);
|
|
1369
|
-
const onPaste = (0,
|
|
1953
|
+
const onPaste = (0, import_react6.useCallback)((event) => {
|
|
1370
1954
|
const files = filesFromClipboard(event.clipboardData);
|
|
1371
1955
|
if (files.length === 0) return;
|
|
1372
1956
|
event.preventDefault();
|
|
@@ -1374,7 +1958,7 @@ function useAttachments(options) {
|
|
|
1374
1958
|
}, [
|
|
1375
1959
|
add
|
|
1376
1960
|
]);
|
|
1377
|
-
const dropZoneProps = (0,
|
|
1961
|
+
const dropZoneProps = (0, import_react6.useMemo)(() => ({
|
|
1378
1962
|
onDragEnter: /* @__PURE__ */ __name((event) => {
|
|
1379
1963
|
if (!dragHasFiles(event.dataTransfer)) return;
|
|
1380
1964
|
event.preventDefault();
|
|
@@ -1397,7 +1981,7 @@ function useAttachments(options) {
|
|
|
1397
1981
|
add
|
|
1398
1982
|
]);
|
|
1399
1983
|
const accept = options.accept;
|
|
1400
|
-
const inputProps = (0,
|
|
1984
|
+
const inputProps = (0, import_react6.useMemo)(() => ({
|
|
1401
1985
|
type: "file",
|
|
1402
1986
|
accept: typeof accept === "string" ? accept : accept?.join(","),
|
|
1403
1987
|
multiple: options.maxFiles === void 0 || options.maxFiles > 1,
|
|
@@ -1411,7 +1995,7 @@ function useAttachments(options) {
|
|
|
1411
1995
|
options.maxFiles,
|
|
1412
1996
|
add
|
|
1413
1997
|
]);
|
|
1414
|
-
return (0,
|
|
1998
|
+
return (0, import_react6.useMemo)(() => {
|
|
1415
1999
|
const ready = items.filter((item) => item.status === "ready" && item.attachment !== void 0);
|
|
1416
2000
|
const attachments = ready.map((item) => item.attachment);
|
|
1417
2001
|
return {
|
|
@@ -1445,18 +2029,18 @@ function useAttachments(options) {
|
|
|
1445
2029
|
__name(useAttachments, "useAttachments");
|
|
1446
2030
|
|
|
1447
2031
|
// src/catalog/use-agents.ts
|
|
1448
|
-
var
|
|
2032
|
+
var import_react8 = require("react");
|
|
1449
2033
|
|
|
1450
2034
|
// src/catalog/use-resource.ts
|
|
1451
|
-
var
|
|
2035
|
+
var import_react7 = require("react");
|
|
1452
2036
|
function useResource(load2, key, enabled) {
|
|
1453
|
-
const [data, setData] = (0,
|
|
1454
|
-
const [isLoading, setIsLoading] = (0,
|
|
1455
|
-
const [error, setError] = (0,
|
|
1456
|
-
const loadRef = (0,
|
|
2037
|
+
const [data, setData] = (0, import_react7.useState)(void 0);
|
|
2038
|
+
const [isLoading, setIsLoading] = (0, import_react7.useState)(enabled);
|
|
2039
|
+
const [error, setError] = (0, import_react7.useState)(null);
|
|
2040
|
+
const loadRef = (0, import_react7.useRef)(load2);
|
|
1457
2041
|
loadRef.current = load2;
|
|
1458
|
-
const generation = (0,
|
|
1459
|
-
const refresh = (0,
|
|
2042
|
+
const generation = (0, import_react7.useRef)(0);
|
|
2043
|
+
const refresh = (0, import_react7.useCallback)(async () => {
|
|
1460
2044
|
const mine = ++generation.current;
|
|
1461
2045
|
setIsLoading(true);
|
|
1462
2046
|
try {
|
|
@@ -1471,7 +2055,7 @@ function useResource(load2, key, enabled) {
|
|
|
1471
2055
|
if (mine === generation.current) setIsLoading(false);
|
|
1472
2056
|
}
|
|
1473
2057
|
}, []);
|
|
1474
|
-
(0,
|
|
2058
|
+
(0, import_react7.useEffect)(() => {
|
|
1475
2059
|
if (!enabled) return;
|
|
1476
2060
|
void refresh();
|
|
1477
2061
|
}, [
|
|
@@ -1489,10 +2073,11 @@ function useResource(load2, key, enabled) {
|
|
|
1489
2073
|
__name(useResource, "useResource");
|
|
1490
2074
|
|
|
1491
2075
|
// src/catalog/use-agents.ts
|
|
1492
|
-
function useAgents(options) {
|
|
1493
|
-
const {
|
|
2076
|
+
function useAgents(options = {}) {
|
|
2077
|
+
const { enabled = true } = options;
|
|
2078
|
+
const backend = useAgentBackend(options.backend);
|
|
1494
2079
|
const { data, isLoading, error, refresh } = useResource(() => requireBackendMethod(backend, "listAgents")(), "", enabled);
|
|
1495
|
-
return (0,
|
|
2080
|
+
return (0, import_react8.useMemo)(() => {
|
|
1496
2081
|
const agents = data ?? [];
|
|
1497
2082
|
return {
|
|
1498
2083
|
agents,
|
|
@@ -1511,11 +2096,12 @@ function useAgents(options) {
|
|
|
1511
2096
|
__name(useAgents, "useAgents");
|
|
1512
2097
|
|
|
1513
2098
|
// src/catalog/use-models.ts
|
|
1514
|
-
var
|
|
1515
|
-
function useModels(options) {
|
|
1516
|
-
const {
|
|
2099
|
+
var import_react9 = require("react");
|
|
2100
|
+
function useModels(options = {}) {
|
|
2101
|
+
const { agent, enabled = true } = options;
|
|
2102
|
+
const backend = useAgentBackend(options.backend);
|
|
1517
2103
|
const { data, isLoading, error, refresh } = useResource(() => requireBackendMethod(backend, "listModels")(agent), `${agent ?? ""}`, enabled);
|
|
1518
|
-
return (0,
|
|
2104
|
+
return (0, import_react9.useMemo)(() => {
|
|
1519
2105
|
const providers = data?.providers ?? [];
|
|
1520
2106
|
const models = providers.flatMap((provider) => provider.models.map((model) => ({
|
|
1521
2107
|
...model,
|
|
@@ -1545,7 +2131,7 @@ function useModels(options) {
|
|
|
1545
2131
|
__name(useModels, "useModels");
|
|
1546
2132
|
|
|
1547
2133
|
// src/quota/use-quota.ts
|
|
1548
|
-
var
|
|
2134
|
+
var import_react10 = require("react");
|
|
1549
2135
|
|
|
1550
2136
|
// src/threads/threads-events.ts
|
|
1551
2137
|
var listeners = /* @__PURE__ */ new WeakMap();
|
|
@@ -1569,10 +2155,11 @@ function onThreadsEvent(backend, listener) {
|
|
|
1569
2155
|
__name(onThreadsEvent, "onThreadsEvent");
|
|
1570
2156
|
|
|
1571
2157
|
// src/quota/use-quota.ts
|
|
1572
|
-
function useQuota(options) {
|
|
1573
|
-
const {
|
|
2158
|
+
function useQuota(options = {}) {
|
|
2159
|
+
const { enabled = true, pollMs } = options;
|
|
2160
|
+
const backend = useAgentBackend(options.backend);
|
|
1574
2161
|
const { data, isLoading, error, refresh } = useResource(() => requireBackendMethod(backend, "getQuota")(), "", enabled);
|
|
1575
|
-
(0,
|
|
2162
|
+
(0, import_react10.useEffect)(() => {
|
|
1576
2163
|
if (!enabled) return;
|
|
1577
2164
|
return onThreadsEvent(backend, (event) => {
|
|
1578
2165
|
if (event.type === "changed") void refresh();
|
|
@@ -1582,7 +2169,7 @@ function useQuota(options) {
|
|
|
1582
2169
|
enabled,
|
|
1583
2170
|
refresh
|
|
1584
2171
|
]);
|
|
1585
|
-
(0,
|
|
2172
|
+
(0, import_react10.useEffect)(() => {
|
|
1586
2173
|
if (!enabled || pollMs === void 0 || pollMs <= 0) return;
|
|
1587
2174
|
const timer = setInterval(() => void refresh(), pollMs);
|
|
1588
2175
|
return () => clearInterval(timer);
|
|
@@ -1591,7 +2178,7 @@ function useQuota(options) {
|
|
|
1591
2178
|
pollMs,
|
|
1592
2179
|
refresh
|
|
1593
2180
|
]);
|
|
1594
|
-
return (0,
|
|
2181
|
+
return (0, import_react10.useMemo)(() => {
|
|
1595
2182
|
const windows = data?.windows ?? [];
|
|
1596
2183
|
return {
|
|
1597
2184
|
report: data,
|
|
@@ -1613,37 +2200,44 @@ function useQuota(options) {
|
|
|
1613
2200
|
__name(useQuota, "useQuota");
|
|
1614
2201
|
|
|
1615
2202
|
// src/feedback/use-message-feedback.ts
|
|
1616
|
-
var
|
|
1617
|
-
function useMessageFeedback(options) {
|
|
1618
|
-
const
|
|
1619
|
-
latest
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
2203
|
+
var import_react11 = require("react");
|
|
2204
|
+
function useMessageFeedback(options = {}) {
|
|
2205
|
+
const backend = useAgentBackend(options.backend);
|
|
2206
|
+
const latest = (0, import_react11.useRef)({
|
|
2207
|
+
...options,
|
|
2208
|
+
backend
|
|
2209
|
+
});
|
|
2210
|
+
latest.current = {
|
|
2211
|
+
...options,
|
|
2212
|
+
backend
|
|
2213
|
+
};
|
|
2214
|
+
const [local, setLocal] = (0, import_react11.useState)(/* @__PURE__ */ new Map());
|
|
2215
|
+
const [pending, setPending] = (0, import_react11.useState)(/* @__PURE__ */ new Set());
|
|
2216
|
+
const [error, setError] = (0, import_react11.useState)(null);
|
|
2217
|
+
const localRef = (0, import_react11.useRef)(local);
|
|
1624
2218
|
localRef.current = local;
|
|
1625
|
-
const resolved = (0,
|
|
1626
|
-
const feedbackOf = (0,
|
|
2219
|
+
const resolved = (0, import_react11.useRef)(/* @__PURE__ */ new Map());
|
|
2220
|
+
const feedbackOf = (0, import_react11.useCallback)((message) => {
|
|
1627
2221
|
const mine = local.get(message.id);
|
|
1628
2222
|
if (mine !== void 0) return mine.feedback;
|
|
1629
2223
|
return metadataOf(message).feedback ?? null;
|
|
1630
2224
|
}, [
|
|
1631
2225
|
local
|
|
1632
2226
|
]);
|
|
1633
|
-
const isPending = (0,
|
|
2227
|
+
const isPending = (0, import_react11.useCallback)((message) => pending.has(message.id), [
|
|
1634
2228
|
pending
|
|
1635
2229
|
]);
|
|
1636
|
-
const storedIdFor = (0,
|
|
2230
|
+
const storedIdFor = (0, import_react11.useCallback)(async (message) => {
|
|
1637
2231
|
const runId = metadataOf(message).runId;
|
|
1638
2232
|
if (runId === void 0) return message.id;
|
|
1639
2233
|
const known = resolved.current.get(message.id);
|
|
1640
2234
|
if (known !== void 0) return known;
|
|
1641
|
-
const { backend, threadId } = latest.current;
|
|
2235
|
+
const { backend: backend2, threadId } = latest.current;
|
|
1642
2236
|
const thread = typeof threadId === "function" ? threadId() : threadId;
|
|
1643
2237
|
if (thread === void 0) {
|
|
1644
2238
|
throw new Error("useMessageFeedback: a streamed message needs `threadId` to be rated");
|
|
1645
2239
|
}
|
|
1646
|
-
const detail = await
|
|
2240
|
+
const detail = await backend2.getThread(thread);
|
|
1647
2241
|
const row = [
|
|
1648
2242
|
...detail.messages
|
|
1649
2243
|
].reverse().find((candidate) => candidate.role === "assistant" && candidate.runId === runId);
|
|
@@ -1653,7 +2247,7 @@ function useMessageFeedback(options) {
|
|
|
1653
2247
|
resolved.current.set(message.id, row.id);
|
|
1654
2248
|
return row.id;
|
|
1655
2249
|
}, []);
|
|
1656
|
-
const rate = (0,
|
|
2250
|
+
const rate = (0, import_react11.useCallback)(async (message, value, comment) => {
|
|
1657
2251
|
const setFeedback = requireBackendMethod(latest.current.backend, "setMessageFeedback");
|
|
1658
2252
|
const had = localRef.current.get(message.id);
|
|
1659
2253
|
const optimistic = value === null ? null : {
|
|
@@ -1699,7 +2293,7 @@ function useMessageFeedback(options) {
|
|
|
1699
2293
|
}, [
|
|
1700
2294
|
storedIdFor
|
|
1701
2295
|
]);
|
|
1702
|
-
const toggle = (0,
|
|
2296
|
+
const toggle = (0, import_react11.useCallback)((message, value) => {
|
|
1703
2297
|
const mine = localRef.current.get(message.id);
|
|
1704
2298
|
const current = mine !== void 0 ? mine.feedback : metadataOf(message).feedback ?? null;
|
|
1705
2299
|
return rate(message, current?.value === value ? null : value);
|
|
@@ -1722,16 +2316,17 @@ function metadataOf(message) {
|
|
|
1722
2316
|
__name(metadataOf, "metadataOf");
|
|
1723
2317
|
|
|
1724
2318
|
// src/threads/use-threads.ts
|
|
1725
|
-
var
|
|
1726
|
-
function useThreads(options) {
|
|
1727
|
-
const {
|
|
1728
|
-
const
|
|
1729
|
-
const [
|
|
1730
|
-
const [
|
|
1731
|
-
const
|
|
2319
|
+
var import_react12 = require("react");
|
|
2320
|
+
function useThreads(options = {}) {
|
|
2321
|
+
const { enabled = true } = options;
|
|
2322
|
+
const backend = useAgentBackend(options.backend);
|
|
2323
|
+
const [threads, setThreads] = (0, import_react12.useState)([]);
|
|
2324
|
+
const [isLoading, setIsLoading] = (0, import_react12.useState)(enabled);
|
|
2325
|
+
const [error, setError] = (0, import_react12.useState)(null);
|
|
2326
|
+
const threadsRef = (0, import_react12.useRef)(threads);
|
|
1732
2327
|
threadsRef.current = threads;
|
|
1733
|
-
const generation = (0,
|
|
1734
|
-
const refresh = (0,
|
|
2328
|
+
const generation = (0, import_react12.useRef)(0);
|
|
2329
|
+
const refresh = (0, import_react12.useCallback)(async () => {
|
|
1735
2330
|
const mine = ++generation.current;
|
|
1736
2331
|
setIsLoading(true);
|
|
1737
2332
|
try {
|
|
@@ -1748,7 +2343,7 @@ function useThreads(options) {
|
|
|
1748
2343
|
}, [
|
|
1749
2344
|
backend
|
|
1750
2345
|
]);
|
|
1751
|
-
(0,
|
|
2346
|
+
(0, import_react12.useEffect)(() => {
|
|
1752
2347
|
if (!enabled) return;
|
|
1753
2348
|
void refresh();
|
|
1754
2349
|
return onThreadsEvent(backend, (event) => {
|
|
@@ -1768,7 +2363,7 @@ function useThreads(options) {
|
|
|
1768
2363
|
enabled,
|
|
1769
2364
|
refresh
|
|
1770
2365
|
]);
|
|
1771
|
-
const rename = (0,
|
|
2366
|
+
const rename = (0, import_react12.useCallback)(async (id, title) => {
|
|
1772
2367
|
const before = threadsRef.current;
|
|
1773
2368
|
setThreads((current) => current.map((thread) => thread.id === id ? {
|
|
1774
2369
|
...thread,
|
|
@@ -1790,7 +2385,7 @@ function useThreads(options) {
|
|
|
1790
2385
|
}, [
|
|
1791
2386
|
backend
|
|
1792
2387
|
]);
|
|
1793
|
-
const remove = (0,
|
|
2388
|
+
const remove = (0, import_react12.useCallback)(async (id) => {
|
|
1794
2389
|
const before = threadsRef.current;
|
|
1795
2390
|
setThreads((current) => current.filter((thread) => thread.id !== id));
|
|
1796
2391
|
try {
|
|
@@ -1864,29 +2459,11 @@ function backgroundRunsFromThread(messages) {
|
|
|
1864
2459
|
}
|
|
1865
2460
|
__name(backgroundRunsFromThread, "backgroundRunsFromThread");
|
|
1866
2461
|
|
|
1867
|
-
// src/components/ambient-ui.ts
|
|
1868
|
-
var import_react9 = require("react");
|
|
1869
|
-
function sharedContext(key) {
|
|
1870
|
-
const symbol = Symbol.for(key);
|
|
1871
|
-
const holder = globalThis;
|
|
1872
|
-
const existing = holder[symbol];
|
|
1873
|
-
if (existing !== void 0) return existing;
|
|
1874
|
-
const created = (0, import_react9.createContext)(null);
|
|
1875
|
-
holder[symbol] = created;
|
|
1876
|
-
return created;
|
|
1877
|
-
}
|
|
1878
|
-
__name(sharedContext, "sharedContext");
|
|
1879
|
-
var AmbientRenderUiContext = sharedContext("@dudousxd/nestjs-agent-react:ambient-render-ui");
|
|
1880
|
-
function useAmbientRenderUi() {
|
|
1881
|
-
return (0, import_react9.useContext)(AmbientRenderUiContext);
|
|
1882
|
-
}
|
|
1883
|
-
__name(useAmbientRenderUi, "useAmbientRenderUi");
|
|
1884
|
-
|
|
1885
2462
|
// src/components/chat-input.tsx
|
|
1886
|
-
var
|
|
2463
|
+
var import_react14 = __toESM(require("react"), 1);
|
|
1887
2464
|
|
|
1888
2465
|
// src/components/use-speech-recognition.ts
|
|
1889
|
-
var
|
|
2466
|
+
var import_react13 = require("react");
|
|
1890
2467
|
function getRecognitionCtor() {
|
|
1891
2468
|
if (typeof window === "undefined") return null;
|
|
1892
2469
|
const scope = window;
|
|
@@ -1894,15 +2471,15 @@ function getRecognitionCtor() {
|
|
|
1894
2471
|
}
|
|
1895
2472
|
__name(getRecognitionCtor, "getRecognitionCtor");
|
|
1896
2473
|
function useSpeechRecognition({ lang = "en-US", onFinalTranscript, onInterimTranscript }) {
|
|
1897
|
-
const recognitionRef = (0,
|
|
1898
|
-
const [isListening, setIsListening] = (0,
|
|
1899
|
-
const ctor = (0,
|
|
2474
|
+
const recognitionRef = (0, import_react13.useRef)(null);
|
|
2475
|
+
const [isListening, setIsListening] = (0, import_react13.useState)(false);
|
|
2476
|
+
const ctor = (0, import_react13.useMemo)(() => getRecognitionCtor(), []);
|
|
1900
2477
|
const isSupported = ctor !== null;
|
|
1901
|
-
const finalRef = (0,
|
|
1902
|
-
const interimRef = (0,
|
|
2478
|
+
const finalRef = (0, import_react13.useRef)(onFinalTranscript);
|
|
2479
|
+
const interimRef = (0, import_react13.useRef)(onInterimTranscript);
|
|
1903
2480
|
finalRef.current = onFinalTranscript;
|
|
1904
2481
|
interimRef.current = onInterimTranscript;
|
|
1905
|
-
(0,
|
|
2482
|
+
(0, import_react13.useEffect)(() => {
|
|
1906
2483
|
if (!ctor) return;
|
|
1907
2484
|
const recognition = new ctor();
|
|
1908
2485
|
recognition.lang = lang;
|
|
@@ -1941,7 +2518,7 @@ function useSpeechRecognition({ lang = "en-US", onFinalTranscript, onInterimTran
|
|
|
1941
2518
|
ctor,
|
|
1942
2519
|
lang
|
|
1943
2520
|
]);
|
|
1944
|
-
const start = (0,
|
|
2521
|
+
const start = (0, import_react13.useCallback)(() => {
|
|
1945
2522
|
const recognition = recognitionRef.current;
|
|
1946
2523
|
if (!recognition) return;
|
|
1947
2524
|
try {
|
|
@@ -1951,7 +2528,7 @@ function useSpeechRecognition({ lang = "en-US", onFinalTranscript, onInterimTran
|
|
|
1951
2528
|
console.warn("SpeechRecognition start failed", error);
|
|
1952
2529
|
}
|
|
1953
2530
|
}, []);
|
|
1954
|
-
const stop = (0,
|
|
2531
|
+
const stop = (0, import_react13.useCallback)(() => {
|
|
1955
2532
|
const recognition = recognitionRef.current;
|
|
1956
2533
|
if (!recognition) return;
|
|
1957
2534
|
try {
|
|
@@ -1970,8 +2547,8 @@ __name(useSpeechRecognition, "useSpeechRecognition");
|
|
|
1970
2547
|
|
|
1971
2548
|
// src/components/chat-input.tsx
|
|
1972
2549
|
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 }) {
|
|
1973
|
-
const [value, setValue] = (0,
|
|
1974
|
-
const [interim, setInterim] = (0,
|
|
2550
|
+
const [value, setValue] = (0, import_react14.useState)("");
|
|
2551
|
+
const [interim, setInterim] = (0, import_react14.useState)("");
|
|
1975
2552
|
const speech = useSpeechRecognition({
|
|
1976
2553
|
lang: speechLang,
|
|
1977
2554
|
onFinalTranscript: /* @__PURE__ */ __name((text) => {
|
|
@@ -1982,7 +2559,7 @@ function ChatInput({ onSubmit, disabled, placeholder, rows = 2, enableSpeech = t
|
|
|
1982
2559
|
}, "onFinalTranscript"),
|
|
1983
2560
|
onInterimTranscript: /* @__PURE__ */ __name((text) => setInterim(text), "onInterimTranscript")
|
|
1984
2561
|
});
|
|
1985
|
-
(0,
|
|
2562
|
+
(0, import_react14.useEffect)(() => {
|
|
1986
2563
|
if (!speech.isListening) setInterim("");
|
|
1987
2564
|
}, [
|
|
1988
2565
|
speech.isListening
|
|
@@ -2010,9 +2587,9 @@ function ChatInput({ onSubmit, disabled, placeholder, rows = 2, enableSpeech = t
|
|
|
2010
2587
|
const displayValue = speech.isListening && interim ? `${value}${value && !value.endsWith(" ") ? " " : ""}${interim}` : value;
|
|
2011
2588
|
const showMic = enableSpeech && speech.isSupported;
|
|
2012
2589
|
const showStop = isStreaming && onStop !== void 0;
|
|
2013
|
-
return /* @__PURE__ */
|
|
2590
|
+
return /* @__PURE__ */ import_react14.default.createElement("div", {
|
|
2014
2591
|
className
|
|
2015
|
-
}, /* @__PURE__ */
|
|
2592
|
+
}, /* @__PURE__ */ import_react14.default.createElement("textarea", {
|
|
2016
2593
|
className: textareaClassName,
|
|
2017
2594
|
rows,
|
|
2018
2595
|
value: displayValue,
|
|
@@ -2023,17 +2600,17 @@ function ChatInput({ onSubmit, disabled, placeholder, rows = 2, enableSpeech = t
|
|
|
2023
2600
|
}, "onChange"),
|
|
2024
2601
|
onKeyDown: handleKeyDown,
|
|
2025
2602
|
placeholder: placeholder ?? "Ask something (Enter to send, Shift+Enter for newline)"
|
|
2026
|
-
}), /* @__PURE__ */
|
|
2603
|
+
}), /* @__PURE__ */ import_react14.default.createElement("button", {
|
|
2027
2604
|
type: "button",
|
|
2028
2605
|
className: sendButtonClassName,
|
|
2029
2606
|
onClick: submit,
|
|
2030
2607
|
disabled: disabled || !value.trim()
|
|
2031
|
-
}, sendLabel), showStop ? /* @__PURE__ */
|
|
2608
|
+
}, sendLabel), showStop ? /* @__PURE__ */ import_react14.default.createElement("button", {
|
|
2032
2609
|
type: "button",
|
|
2033
2610
|
className: stopButtonClassName,
|
|
2034
2611
|
onClick: /* @__PURE__ */ __name(() => void onStop(), "onClick"),
|
|
2035
2612
|
"aria-label": "Stop generating"
|
|
2036
|
-
}, stopLabel) : null, showMic ? /* @__PURE__ */
|
|
2613
|
+
}, stopLabel) : null, showMic ? /* @__PURE__ */ import_react14.default.createElement("button", {
|
|
2037
2614
|
type: "button",
|
|
2038
2615
|
className: micButtonClassName,
|
|
2039
2616
|
onClick: toggleMic,
|
|
@@ -2046,10 +2623,10 @@ function ChatInput({ onSubmit, disabled, placeholder, rows = 2, enableSpeech = t
|
|
|
2046
2623
|
__name(ChatInput, "ChatInput");
|
|
2047
2624
|
|
|
2048
2625
|
// src/components/message-item.tsx
|
|
2049
|
-
var
|
|
2626
|
+
var import_react17 = __toESM(require("react"), 1);
|
|
2050
2627
|
|
|
2051
2628
|
// src/transcript/use-chat-transcript.ts
|
|
2052
|
-
var
|
|
2629
|
+
var import_react16 = require("react");
|
|
2053
2630
|
|
|
2054
2631
|
// src/transcript/model.ts
|
|
2055
2632
|
var import_nestjs_agent_core2 = require("@dudousxd/nestjs-agent-core");
|
|
@@ -2146,21 +2723,21 @@ function fillTemplate(template, context) {
|
|
|
2146
2723
|
}).replace(/\s{2,}/g, " ").trim();
|
|
2147
2724
|
}
|
|
2148
2725
|
__name(fillTemplate, "fillTemplate");
|
|
2149
|
-
function phraseFor(presentation, input, isSettled2,
|
|
2726
|
+
function phraseFor(presentation, input, isSettled2, fallback2 = {
|
|
2150
2727
|
running: "Working",
|
|
2151
2728
|
done: "Done"
|
|
2152
2729
|
}) {
|
|
2153
|
-
if (presentation === void 0) return isSettled2 ?
|
|
2730
|
+
if (presentation === void 0) return isSettled2 ? fallback2.done : fallback2.running;
|
|
2154
2731
|
const filled = fillTemplate(isSettled2 ? presentation.done : presentation.running, input);
|
|
2155
2732
|
return filled === "" ? presentation.label : filled;
|
|
2156
2733
|
}
|
|
2157
2734
|
__name(phraseFor, "phraseFor");
|
|
2158
2735
|
|
|
2159
2736
|
// src/presentation/result-view.ts
|
|
2160
|
-
function
|
|
2737
|
+
function isRecord2(value) {
|
|
2161
2738
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2162
2739
|
}
|
|
2163
|
-
__name(
|
|
2740
|
+
__name(isRecord2, "isRecord");
|
|
2164
2741
|
function toText(value) {
|
|
2165
2742
|
if (value === null || value === void 0) return "\u2014";
|
|
2166
2743
|
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
@@ -2171,7 +2748,7 @@ function toText(value) {
|
|
|
2171
2748
|
}
|
|
2172
2749
|
__name(toText, "toText");
|
|
2173
2750
|
function inferResultView(output) {
|
|
2174
|
-
if (!
|
|
2751
|
+
if (!isRecord2(output)) return void 0;
|
|
2175
2752
|
for (const [key, value] of Object.entries(output)) {
|
|
2176
2753
|
if (!Array.isArray(value) || value.length === 0) continue;
|
|
2177
2754
|
if (value.every((entry) => typeof entry === "string")) {
|
|
@@ -2180,12 +2757,12 @@ function inferResultView(output) {
|
|
|
2180
2757
|
lines: key
|
|
2181
2758
|
};
|
|
2182
2759
|
}
|
|
2183
|
-
if (value.every(
|
|
2760
|
+
if (value.every(isRecord2)) {
|
|
2184
2761
|
const first = value[0];
|
|
2185
2762
|
return {
|
|
2186
2763
|
kind: "table",
|
|
2187
2764
|
rows: key,
|
|
2188
|
-
columns: Object.keys(first).filter((column) => !
|
|
2765
|
+
columns: Object.keys(first).filter((column) => !isRecord2(first[column])).map((column) => ({
|
|
2189
2766
|
path: column,
|
|
2190
2767
|
label: column
|
|
2191
2768
|
}))
|
|
@@ -2561,7 +3138,7 @@ function isSettled(state) {
|
|
|
2561
3138
|
__name(isSettled, "isSettled");
|
|
2562
3139
|
function toolKind(part) {
|
|
2563
3140
|
const metadata = part.toolMetadata;
|
|
2564
|
-
return
|
|
3141
|
+
return isRecord3(metadata) && typeof metadata.toolKind === "string" ? metadata.toolKind : void 0;
|
|
2565
3142
|
}
|
|
2566
3143
|
__name(toolKind, "toolKind");
|
|
2567
3144
|
function isAwaitingApproval(part) {
|
|
@@ -2576,7 +3153,7 @@ function isAwaitingApproval(part) {
|
|
|
2576
3153
|
__name(isAwaitingApproval, "isAwaitingApproval");
|
|
2577
3154
|
function toolParentId(part) {
|
|
2578
3155
|
const metadata = part.toolMetadata;
|
|
2579
|
-
return
|
|
3156
|
+
return isRecord3(metadata) && typeof metadata.parentId === "string" ? metadata.parentId : null;
|
|
2580
3157
|
}
|
|
2581
3158
|
__name(toolParentId, "toolParentId");
|
|
2582
3159
|
function nestToolCalls(calls) {
|
|
@@ -2643,12 +3220,12 @@ function buildToolCall(part, options, approval, catalog) {
|
|
|
2643
3220
|
__name(buildToolCall, "buildToolCall");
|
|
2644
3221
|
function readElicitationRequest(part) {
|
|
2645
3222
|
const input = part.input;
|
|
2646
|
-
if (!
|
|
3223
|
+
if (!isRecord3(input) || !Array.isArray(input.questions) || input.questions.length === 0) {
|
|
2647
3224
|
return null;
|
|
2648
3225
|
}
|
|
2649
3226
|
const questions = [];
|
|
2650
3227
|
for (const candidate of input.questions) {
|
|
2651
|
-
if (!
|
|
3228
|
+
if (!isRecord3(candidate) || typeof candidate.id !== "string" || typeof candidate.prompt !== "string") {
|
|
2652
3229
|
return null;
|
|
2653
3230
|
}
|
|
2654
3231
|
const input2 = (0, import_nestjs_agent_core2.readElicitationInput)(candidate.input) ?? null;
|
|
@@ -2658,7 +3235,7 @@ function readElicitationRequest(part) {
|
|
|
2658
3235
|
}
|
|
2659
3236
|
const options = [];
|
|
2660
3237
|
for (const option of rawOptions) {
|
|
2661
|
-
if (!
|
|
3238
|
+
if (!isRecord3(option) || typeof option.value !== "string" || typeof option.label !== "string") {
|
|
2662
3239
|
return null;
|
|
2663
3240
|
}
|
|
2664
3241
|
options.push({
|
|
@@ -2686,7 +3263,7 @@ function readElicitationRequest(part) {
|
|
|
2686
3263
|
__name(readElicitationRequest, "readElicitationRequest");
|
|
2687
3264
|
function readElicitationOutcome(part) {
|
|
2688
3265
|
const output = part.output;
|
|
2689
|
-
if (!
|
|
3266
|
+
if (!isRecord3(output) || !isRecord3(output.answers) || typeof output.skipped !== "boolean") {
|
|
2690
3267
|
return null;
|
|
2691
3268
|
}
|
|
2692
3269
|
const answers = {};
|
|
@@ -2823,7 +3400,7 @@ function readApprovals(parts) {
|
|
|
2823
3400
|
continue;
|
|
2824
3401
|
}
|
|
2825
3402
|
const data = part.data;
|
|
2826
|
-
if (!
|
|
3403
|
+
if (!isRecord3(data) || typeof data.id !== "string") {
|
|
2827
3404
|
continue;
|
|
2828
3405
|
}
|
|
2829
3406
|
const approval = entry(data.id);
|
|
@@ -2879,7 +3456,7 @@ function statusFromPart(call) {
|
|
|
2879
3456
|
__name(statusFromPart, "statusFromPart");
|
|
2880
3457
|
function readUiComponent(part) {
|
|
2881
3458
|
const data = part.data;
|
|
2882
|
-
if (!
|
|
3459
|
+
if (!isRecord3(data) || typeof data.component !== "string") {
|
|
2883
3460
|
return null;
|
|
2884
3461
|
}
|
|
2885
3462
|
const id = typeof data.id === "string" ? data.id : part.id;
|
|
@@ -2889,19 +3466,19 @@ function readUiComponent(part) {
|
|
|
2889
3466
|
return {
|
|
2890
3467
|
id,
|
|
2891
3468
|
component: data.component,
|
|
2892
|
-
props:
|
|
3469
|
+
props: isRecord3(data.props) ? data.props : {},
|
|
2893
3470
|
version: typeof data.version === "number" ? data.version : null,
|
|
2894
3471
|
toolCallId: typeof data.toolCallId === "string" ? data.toolCallId : null
|
|
2895
3472
|
};
|
|
2896
3473
|
}
|
|
2897
3474
|
__name(readUiComponent, "readUiComponent");
|
|
2898
|
-
function
|
|
3475
|
+
function isRecord3(value) {
|
|
2899
3476
|
return typeof value === "object" && value !== null;
|
|
2900
3477
|
}
|
|
2901
|
-
__name(
|
|
3478
|
+
__name(isRecord3, "isRecord");
|
|
2902
3479
|
function readQuery(part) {
|
|
2903
3480
|
const input = part.input;
|
|
2904
|
-
if (!
|
|
3481
|
+
if (!isRecord3(input) || typeof input.query !== "string") {
|
|
2905
3482
|
return null;
|
|
2906
3483
|
}
|
|
2907
3484
|
return input.query;
|
|
@@ -2909,12 +3486,12 @@ function readQuery(part) {
|
|
|
2909
3486
|
__name(readQuery, "readQuery");
|
|
2910
3487
|
function readPassages(part) {
|
|
2911
3488
|
const output = part.output;
|
|
2912
|
-
if (!
|
|
3489
|
+
if (!isRecord3(output) || !Array.isArray(output.passages) || output.passages.length === 0) {
|
|
2913
3490
|
return null;
|
|
2914
3491
|
}
|
|
2915
3492
|
const passages = [];
|
|
2916
3493
|
for (const candidate of output.passages) {
|
|
2917
|
-
if (!
|
|
3494
|
+
if (!isRecord3(candidate) || typeof candidate.id !== "string" || typeof candidate.text !== "string") {
|
|
2918
3495
|
return null;
|
|
2919
3496
|
}
|
|
2920
3497
|
passages.push({
|
|
@@ -2924,7 +3501,7 @@ function readPassages(part) {
|
|
|
2924
3501
|
...typeof candidate.source === "string" ? {
|
|
2925
3502
|
source: candidate.source
|
|
2926
3503
|
} : {},
|
|
2927
|
-
...
|
|
3504
|
+
...isRecord3(candidate.metadata) ? {
|
|
2928
3505
|
metadata: candidate.metadata
|
|
2929
3506
|
} : {}
|
|
2930
3507
|
});
|
|
@@ -3026,11 +3603,11 @@ function formatCostUsd(cost) {
|
|
|
3026
3603
|
__name(formatCostUsd, "formatCostUsd");
|
|
3027
3604
|
|
|
3028
3605
|
// src/transcript/use-stick-to-bottom.ts
|
|
3029
|
-
var
|
|
3606
|
+
var import_react15 = require("react");
|
|
3030
3607
|
function useStickToBottom({ contentKey, threshold = 32 }) {
|
|
3031
|
-
const containerRef = (0,
|
|
3032
|
-
const [isAtBottom, setIsAtBottom] = (0,
|
|
3033
|
-
const measure = (0,
|
|
3608
|
+
const containerRef = (0, import_react15.useRef)(null);
|
|
3609
|
+
const [isAtBottom, setIsAtBottom] = (0, import_react15.useState)(true);
|
|
3610
|
+
const measure = (0, import_react15.useCallback)(() => {
|
|
3034
3611
|
const element = containerRef.current;
|
|
3035
3612
|
if (!element) {
|
|
3036
3613
|
return;
|
|
@@ -3040,7 +3617,7 @@ function useStickToBottom({ contentKey, threshold = 32 }) {
|
|
|
3040
3617
|
}, [
|
|
3041
3618
|
threshold
|
|
3042
3619
|
]);
|
|
3043
|
-
const scrollToBottom = (0,
|
|
3620
|
+
const scrollToBottom = (0, import_react15.useCallback)(() => {
|
|
3044
3621
|
const element = containerRef.current;
|
|
3045
3622
|
if (!element) {
|
|
3046
3623
|
return;
|
|
@@ -3048,7 +3625,7 @@ function useStickToBottom({ contentKey, threshold = 32 }) {
|
|
|
3048
3625
|
element.scrollTop = element.scrollHeight;
|
|
3049
3626
|
setIsAtBottom(true);
|
|
3050
3627
|
}, []);
|
|
3051
|
-
const setContainer = (0,
|
|
3628
|
+
const setContainer = (0, import_react15.useCallback)((element) => {
|
|
3052
3629
|
containerRef.current = element;
|
|
3053
3630
|
if (element) {
|
|
3054
3631
|
measure();
|
|
@@ -3056,7 +3633,7 @@ function useStickToBottom({ contentKey, threshold = 32 }) {
|
|
|
3056
3633
|
}, [
|
|
3057
3634
|
measure
|
|
3058
3635
|
]);
|
|
3059
|
-
(0,
|
|
3636
|
+
(0, import_react15.useEffect)(() => {
|
|
3060
3637
|
if (isAtBottom) {
|
|
3061
3638
|
scrollToBottom();
|
|
3062
3639
|
}
|
|
@@ -3065,7 +3642,7 @@ function useStickToBottom({ contentKey, threshold = 32 }) {
|
|
|
3065
3642
|
isAtBottom,
|
|
3066
3643
|
scrollToBottom
|
|
3067
3644
|
]);
|
|
3068
|
-
const getContainerProps = (0,
|
|
3645
|
+
const getContainerProps = (0, import_react15.useCallback)(() => ({
|
|
3069
3646
|
ref: setContainer,
|
|
3070
3647
|
onScroll: measure
|
|
3071
3648
|
}), [
|
|
@@ -3087,14 +3664,14 @@ var DEFAULT_LOAD_EARLIER_STEP = 50;
|
|
|
3087
3664
|
var DEFAULT_COPY_RESET_MS = 1500;
|
|
3088
3665
|
function useChatTranscript(options) {
|
|
3089
3666
|
const { messages, status, initialVisibleCount = DEFAULT_VISIBLE_COUNT, loadEarlierStep = DEFAULT_LOAD_EARLIER_STEP, followUps, stickToBottomThreshold } = options;
|
|
3090
|
-
const latest = (0,
|
|
3667
|
+
const latest = (0, import_react16.useRef)(options);
|
|
3091
3668
|
latest.current = options;
|
|
3092
|
-
const [visibleCount, setVisibleCount] = (0,
|
|
3093
|
-
const [stopRequested, setStopRequested] = (0,
|
|
3669
|
+
const [visibleCount, setVisibleCount] = (0, import_react16.useState)(initialVisibleCount);
|
|
3670
|
+
const [stopRequested, setStopRequested] = (0, import_react16.useState)(false);
|
|
3094
3671
|
const isStreaming = status === "streaming" || status === "reconnecting";
|
|
3095
3672
|
const isBusy = status === "submitted" || isStreaming;
|
|
3096
3673
|
const isEmpty = messages.length === 0;
|
|
3097
|
-
(0,
|
|
3674
|
+
(0, import_react16.useEffect)(() => {
|
|
3098
3675
|
if (!isBusy) {
|
|
3099
3676
|
setStopRequested(false);
|
|
3100
3677
|
}
|
|
@@ -3111,7 +3688,7 @@ function useChatTranscript(options) {
|
|
|
3111
3688
|
streamingMessageId,
|
|
3112
3689
|
options
|
|
3113
3690
|
});
|
|
3114
|
-
const stop = (0,
|
|
3691
|
+
const stop = (0, import_react16.useCallback)(() => {
|
|
3115
3692
|
const current = latest.current;
|
|
3116
3693
|
if (current.status !== "submitted" && current.status !== "streaming" && current.status !== "reconnecting") {
|
|
3117
3694
|
return;
|
|
@@ -3119,8 +3696,8 @@ function useChatTranscript(options) {
|
|
|
3119
3696
|
setStopRequested(true);
|
|
3120
3697
|
void current.onStop?.();
|
|
3121
3698
|
}, []);
|
|
3122
|
-
const loadEarlier = (0,
|
|
3123
|
-
const showAll = (0,
|
|
3699
|
+
const loadEarlier = (0, import_react16.useCallback)(() => setVisibleCount((count) => count + (latest.current.loadEarlierStep ?? DEFAULT_LOAD_EARLIER_STEP)), []);
|
|
3700
|
+
const showAll = (0, import_react16.useCallback)(() => setVisibleCount(latest.current.messages.length), []);
|
|
3124
3701
|
const scroll = useStickToBottom({
|
|
3125
3702
|
contentKey: contentSignature(messages),
|
|
3126
3703
|
...stickToBottomThreshold !== void 0 ? {
|
|
@@ -3156,7 +3733,7 @@ function useChatTranscript(options) {
|
|
|
3156
3733
|
__name(useChatTranscript, "useChatTranscript");
|
|
3157
3734
|
function useTranscriptItem(options) {
|
|
3158
3735
|
const { message, isStreaming = false } = options;
|
|
3159
|
-
const messagesRef = (0,
|
|
3736
|
+
const messagesRef = (0, import_react16.useRef)([
|
|
3160
3737
|
message
|
|
3161
3738
|
]);
|
|
3162
3739
|
if (messagesRef.current[0] !== message) {
|
|
@@ -3174,41 +3751,45 @@ function useTranscriptItem(options) {
|
|
|
3174
3751
|
}
|
|
3175
3752
|
__name(useTranscriptItem, "useTranscriptItem");
|
|
3176
3753
|
function useTranscriptItems({ messages, visibleStart, streamingMessageId, options }) {
|
|
3177
|
-
const [drafts, setDrafts] = (0,
|
|
3178
|
-
const [copied, setCopied] = (0,
|
|
3179
|
-
const [openReasoning, setOpenReasoning] = (0,
|
|
3180
|
-
const [picks, setPicks] = (0,
|
|
3181
|
-
const [settling, setSettling] = (0,
|
|
3182
|
-
const [settleErrors, setSettleErrors] = (0,
|
|
3183
|
-
const
|
|
3754
|
+
const [drafts, setDrafts] = (0, import_react16.useState)(() => /* @__PURE__ */ new Map());
|
|
3755
|
+
const [copied, setCopied] = (0, import_react16.useState)(() => /* @__PURE__ */ new Set());
|
|
3756
|
+
const [openReasoning, setOpenReasoning] = (0, import_react16.useState)(() => /* @__PURE__ */ new Map());
|
|
3757
|
+
const [picks, setPicks] = (0, import_react16.useState)(() => /* @__PURE__ */ new Map());
|
|
3758
|
+
const [settling, setSettling] = (0, import_react16.useState)(() => /* @__PURE__ */ new Map());
|
|
3759
|
+
const [settleErrors, setSettleErrors] = (0, import_react16.useState)(() => /* @__PURE__ */ new Map());
|
|
3760
|
+
const backend = useAgentBackend();
|
|
3761
|
+
const handlers = settleHandlers(options, backend);
|
|
3762
|
+
const latest = (0, import_react16.useRef)({
|
|
3184
3763
|
options,
|
|
3764
|
+
handlers,
|
|
3185
3765
|
drafts,
|
|
3186
3766
|
picks,
|
|
3187
3767
|
messages
|
|
3188
3768
|
});
|
|
3189
3769
|
latest.current = {
|
|
3190
3770
|
options,
|
|
3771
|
+
handlers,
|
|
3191
3772
|
drafts,
|
|
3192
3773
|
picks,
|
|
3193
3774
|
messages
|
|
3194
3775
|
};
|
|
3195
|
-
const copyTimers = (0,
|
|
3196
|
-
(0,
|
|
3776
|
+
const copyTimers = (0, import_react16.useRef)(/* @__PURE__ */ new Map());
|
|
3777
|
+
(0, import_react16.useEffect)(() => () => {
|
|
3197
3778
|
for (const timer of copyTimers.current.values()) {
|
|
3198
3779
|
clearTimeout(timer);
|
|
3199
3780
|
}
|
|
3200
3781
|
copyTimers.current.clear();
|
|
3201
3782
|
}, []);
|
|
3202
|
-
const callbackCache = (0,
|
|
3203
|
-
const reasoningToggleCache = (0,
|
|
3204
|
-
const toggleReasoning = (0,
|
|
3783
|
+
const callbackCache = (0, import_react16.useRef)(/* @__PURE__ */ new Map());
|
|
3784
|
+
const reasoningToggleCache = (0, import_react16.useRef)(/* @__PURE__ */ new Map());
|
|
3785
|
+
const toggleReasoning = (0, import_react16.useCallback)((key, open) => {
|
|
3205
3786
|
setOpenReasoning((current) => {
|
|
3206
3787
|
const next = new Map(current);
|
|
3207
3788
|
next.set(key, open ?? !(current.get(key) ?? false));
|
|
3208
3789
|
return next;
|
|
3209
3790
|
});
|
|
3210
3791
|
}, []);
|
|
3211
|
-
const stableToggle = (0,
|
|
3792
|
+
const stableToggle = (0, import_react16.useCallback)((key) => {
|
|
3212
3793
|
let cached = reasoningToggleCache.current.get(key);
|
|
3213
3794
|
if (!cached) {
|
|
3214
3795
|
cached = /* @__PURE__ */ __name((open) => toggleReasoning(key, open), "cached");
|
|
@@ -3218,10 +3799,10 @@ function useTranscriptItems({ messages, visibleStart, streamingMessageId, option
|
|
|
3218
3799
|
}, [
|
|
3219
3800
|
toggleReasoning
|
|
3220
3801
|
]);
|
|
3221
|
-
const pick = (0,
|
|
3802
|
+
const pick = (0, import_react16.useCallback)((toolCallId, questionId, values) => {
|
|
3222
3803
|
setPicks((current) => new Map(current).set(pickKey(toolCallId, questionId), values));
|
|
3223
3804
|
}, []);
|
|
3224
|
-
const settle = (0,
|
|
3805
|
+
const settle = (0, import_react16.useCallback)((toolCallId, action, send) => {
|
|
3225
3806
|
setSettleErrors((current) => {
|
|
3226
3807
|
if (!current.has(toolCallId)) {
|
|
3227
3808
|
return current;
|
|
@@ -3245,41 +3826,53 @@ function useTranscriptItems({ messages, visibleStart, streamingMessageId, option
|
|
|
3245
3826
|
failed(error);
|
|
3246
3827
|
}
|
|
3247
3828
|
}, []);
|
|
3248
|
-
const answer = (0,
|
|
3829
|
+
const answer = (0, import_react16.useCallback)((toolCallId) => {
|
|
3249
3830
|
const current = latest.current;
|
|
3250
|
-
const onAnswer = current.
|
|
3831
|
+
const onAnswer = current.handlers.onAnswer;
|
|
3251
3832
|
if (!onAnswer) {
|
|
3252
3833
|
return;
|
|
3253
3834
|
}
|
|
3254
|
-
settle(toolCallId, "answer", () => onAnswer(
|
|
3835
|
+
settle(toolCallId, "answer", () => onAnswer({
|
|
3836
|
+
toolCallId,
|
|
3837
|
+
answers: answersFor(current.picks, toolCallId)
|
|
3838
|
+
}));
|
|
3255
3839
|
}, [
|
|
3256
3840
|
settle
|
|
3257
3841
|
]);
|
|
3258
|
-
const skip = (0,
|
|
3259
|
-
const onSkip = latest.current.
|
|
3842
|
+
const skip = (0, import_react16.useCallback)((toolCallId) => {
|
|
3843
|
+
const onSkip = latest.current.handlers.onSkip;
|
|
3260
3844
|
if (onSkip) {
|
|
3261
|
-
settle(toolCallId, "skip", () => onSkip(
|
|
3845
|
+
settle(toolCallId, "skip", () => onSkip({
|
|
3846
|
+
toolCallId
|
|
3847
|
+
}));
|
|
3262
3848
|
}
|
|
3263
3849
|
}, [
|
|
3264
3850
|
settle
|
|
3265
3851
|
]);
|
|
3266
|
-
const approve = (0,
|
|
3267
|
-
const onApprove = latest.current.
|
|
3852
|
+
const approve = (0, import_react16.useCallback)((toolCallId, options2) => {
|
|
3853
|
+
const onApprove = latest.current.handlers.onApprove;
|
|
3268
3854
|
if (onApprove) {
|
|
3269
|
-
settle(toolCallId, "approve", () =>
|
|
3855
|
+
settle(toolCallId, "approve", () => onApprove({
|
|
3856
|
+
toolCallId,
|
|
3857
|
+
...options2?.remember === true ? {
|
|
3858
|
+
remember: true
|
|
3859
|
+
} : {}
|
|
3860
|
+
}));
|
|
3270
3861
|
}
|
|
3271
3862
|
}, [
|
|
3272
3863
|
settle
|
|
3273
3864
|
]);
|
|
3274
|
-
const reject = (0,
|
|
3275
|
-
const onReject = latest.current.
|
|
3865
|
+
const reject = (0, import_react16.useCallback)((toolCallId) => {
|
|
3866
|
+
const onReject = latest.current.handlers.onReject;
|
|
3276
3867
|
if (onReject) {
|
|
3277
|
-
settle(toolCallId, "reject", () => onReject(
|
|
3868
|
+
settle(toolCallId, "reject", () => onReject({
|
|
3869
|
+
toolCallId
|
|
3870
|
+
}));
|
|
3278
3871
|
}
|
|
3279
3872
|
}, [
|
|
3280
3873
|
settle
|
|
3281
3874
|
]);
|
|
3282
|
-
const callbacksFor = (0,
|
|
3875
|
+
const callbacksFor = (0, import_react16.useCallback)((id) => {
|
|
3283
3876
|
const cached = callbackCache.current.get(id);
|
|
3284
3877
|
if (cached) {
|
|
3285
3878
|
return cached;
|
|
@@ -3329,13 +3922,20 @@ function useTranscriptItems({ messages, visibleStart, streamingMessageId, option
|
|
|
3329
3922
|
return;
|
|
3330
3923
|
}
|
|
3331
3924
|
created.cancelEdit();
|
|
3332
|
-
void latest.current.options.onEditSubmit?.(
|
|
3925
|
+
void latest.current.options.onEditSubmit?.({
|
|
3926
|
+
messageId: id,
|
|
3927
|
+
text: next
|
|
3928
|
+
});
|
|
3333
3929
|
}, "save"),
|
|
3334
3930
|
fork: /* @__PURE__ */ __name(() => {
|
|
3335
|
-
void latest.current.options.onFork?.(
|
|
3931
|
+
void latest.current.options.onFork?.({
|
|
3932
|
+
messageId: id
|
|
3933
|
+
});
|
|
3336
3934
|
}, "fork"),
|
|
3337
3935
|
regenerate: /* @__PURE__ */ __name(() => {
|
|
3338
|
-
void latest.current.options.onRegenerate?.(
|
|
3936
|
+
void latest.current.options.onRegenerate?.({
|
|
3937
|
+
messageId: id
|
|
3938
|
+
});
|
|
3339
3939
|
}, "regenerate"),
|
|
3340
3940
|
textareaRef: /* @__PURE__ */ __name((element) => {
|
|
3341
3941
|
if (!element) {
|
|
@@ -3372,7 +3972,7 @@ function useTranscriptItems({ messages, visibleStart, streamingMessageId, option
|
|
|
3372
3972
|
const draft = drafts.get(message.id);
|
|
3373
3973
|
const isEditing = draft !== void 0;
|
|
3374
3974
|
const text = extractMessageText(message.parts);
|
|
3375
|
-
const usage = options.getUsage
|
|
3975
|
+
const usage = (options.getUsage ?? usageFromMetadata)(message);
|
|
3376
3976
|
const isUser = message.role === "user";
|
|
3377
3977
|
const isAssistant = message.role === "assistant";
|
|
3378
3978
|
const isLastAssistant = isAssistant && message.id === lastAssistantId;
|
|
@@ -3394,22 +3994,22 @@ function useTranscriptItems({ messages, visibleStart, streamingMessageId, option
|
|
|
3394
3994
|
...options.toolCatalog !== void 0 ? {
|
|
3395
3995
|
toolCatalog: options.toolCatalog
|
|
3396
3996
|
} : {},
|
|
3397
|
-
...
|
|
3997
|
+
...handlers.onAnswer !== void 0 ? {
|
|
3398
3998
|
elicitation: {
|
|
3399
3999
|
picked: /* @__PURE__ */ __name((toolCallId, questionId) => picks.get(pickKey(toolCallId, questionId)), "picked"),
|
|
3400
4000
|
pick,
|
|
3401
4001
|
canAnswer: true,
|
|
3402
|
-
canSkip:
|
|
4002
|
+
canSkip: handlers.onSkip !== void 0,
|
|
3403
4003
|
answer,
|
|
3404
4004
|
skip,
|
|
3405
4005
|
submitting: /* @__PURE__ */ __name((toolCallId) => settling.get(toolCallId) ?? null, "submitting"),
|
|
3406
4006
|
errorOf: /* @__PURE__ */ __name((toolCallId) => settleErrors.get(toolCallId) ?? null, "errorOf")
|
|
3407
4007
|
}
|
|
3408
4008
|
} : {},
|
|
3409
|
-
...
|
|
4009
|
+
...handlers.onApprove !== void 0 || handlers.onReject !== void 0 ? {
|
|
3410
4010
|
approval: {
|
|
3411
|
-
canApprove:
|
|
3412
|
-
canReject:
|
|
4011
|
+
canApprove: handlers.onApprove !== void 0,
|
|
4012
|
+
canReject: handlers.onReject !== void 0,
|
|
3413
4013
|
approve,
|
|
3414
4014
|
reject,
|
|
3415
4015
|
submitting: /* @__PURE__ */ __name((toolCallId) => settling.get(toolCallId) ?? null, "submitting"),
|
|
@@ -3419,7 +4019,7 @@ function useTranscriptItems({ messages, visibleStart, streamingMessageId, option
|
|
|
3419
4019
|
}),
|
|
3420
4020
|
text,
|
|
3421
4021
|
usage: usage ? describeUsage(usage) : null,
|
|
3422
|
-
timestamp: describeTimestamp(options.getCreatedAt
|
|
4022
|
+
timestamp: describeTimestamp((options.getCreatedAt ?? createdAtFromMetadata)(message)),
|
|
3423
4023
|
copy: {
|
|
3424
4024
|
available: text.length > 0,
|
|
3425
4025
|
copied: copied.has(message.id),
|
|
@@ -3454,6 +4054,43 @@ function useTranscriptItems({ messages, visibleStart, streamingMessageId, option
|
|
|
3454
4054
|
return items;
|
|
3455
4055
|
}
|
|
3456
4056
|
__name(useTranscriptItems, "useTranscriptItems");
|
|
4057
|
+
function settleHandlers(options, backend) {
|
|
4058
|
+
const pick = /* @__PURE__ */ __name((own, fallback2) => own === null ? void 0 : own ?? fallback2, "pick");
|
|
4059
|
+
return {
|
|
4060
|
+
onAnswer: pick(options.onAnswer, backend.answerToolCall ? async (input) => {
|
|
4061
|
+
await backend.answerToolCall?.(input);
|
|
4062
|
+
} : void 0),
|
|
4063
|
+
onSkip: pick(options.onSkip, backend.skipToolCall ? async (input) => {
|
|
4064
|
+
await backend.skipToolCall?.(input);
|
|
4065
|
+
} : void 0),
|
|
4066
|
+
onApprove: pick(options.onApprove, backend.approveToolCall ? async (input) => {
|
|
4067
|
+
await backend.approveToolCall?.(input);
|
|
4068
|
+
} : void 0),
|
|
4069
|
+
onReject: pick(options.onReject, backend.rejectToolCall ? async (input) => {
|
|
4070
|
+
await backend.rejectToolCall?.(input);
|
|
4071
|
+
} : void 0)
|
|
4072
|
+
};
|
|
4073
|
+
}
|
|
4074
|
+
__name(settleHandlers, "settleHandlers");
|
|
4075
|
+
function metadataOf2(message) {
|
|
4076
|
+
const metadata = message.metadata;
|
|
4077
|
+
return metadata !== null && typeof metadata === "object" ? metadata : {};
|
|
4078
|
+
}
|
|
4079
|
+
__name(metadataOf2, "metadataOf");
|
|
4080
|
+
function usageFromMetadata(message) {
|
|
4081
|
+
const usage = metadataOf2(message).usage;
|
|
4082
|
+
if (usage === void 0) return null;
|
|
4083
|
+
return {
|
|
4084
|
+
inputTokens: usage.inputTokens,
|
|
4085
|
+
outputTokens: usage.outputTokens,
|
|
4086
|
+
costUsd: usage.costUsd ?? null
|
|
4087
|
+
};
|
|
4088
|
+
}
|
|
4089
|
+
__name(usageFromMetadata, "usageFromMetadata");
|
|
4090
|
+
function createdAtFromMetadata(message) {
|
|
4091
|
+
return metadataOf2(message).createdAt ?? null;
|
|
4092
|
+
}
|
|
4093
|
+
__name(createdAtFromMetadata, "createdAtFromMetadata");
|
|
3457
4094
|
function pickKey(toolCallId, questionId) {
|
|
3458
4095
|
return `${toolCallId}|${questionId}`;
|
|
3459
4096
|
}
|
|
@@ -3503,7 +4140,7 @@ function MessageItem({ message, isStreaming = false, editable, onEditSubmit, reg
|
|
|
3503
4140
|
editable
|
|
3504
4141
|
} : {},
|
|
3505
4142
|
...onEditSubmit ? {
|
|
3506
|
-
onEditSubmit
|
|
4143
|
+
onEditSubmit
|
|
3507
4144
|
} : {},
|
|
3508
4145
|
...onFork ? {
|
|
3509
4146
|
onFork
|
|
@@ -3512,7 +4149,7 @@ function MessageItem({ message, isStreaming = false, editable, onEditSubmit, reg
|
|
|
3512
4149
|
regeneratable
|
|
3513
4150
|
} : {},
|
|
3514
4151
|
...onRegenerate ? {
|
|
3515
|
-
onRegenerate
|
|
4152
|
+
onRegenerate
|
|
3516
4153
|
} : {},
|
|
3517
4154
|
...usage != null ? {
|
|
3518
4155
|
getUsage: /* @__PURE__ */ __name(() => usage, "getUsage")
|
|
@@ -3521,7 +4158,7 @@ function MessageItem({ message, isStreaming = false, editable, onEditSubmit, reg
|
|
|
3521
4158
|
getCreatedAt: /* @__PURE__ */ __name(() => createdAt, "getCreatedAt")
|
|
3522
4159
|
} : {}
|
|
3523
4160
|
});
|
|
3524
|
-
return /* @__PURE__ */
|
|
4161
|
+
return /* @__PURE__ */ import_react17.default.createElement(MessageItemView, {
|
|
3525
4162
|
item,
|
|
3526
4163
|
...slots
|
|
3527
4164
|
});
|
|
@@ -3534,51 +4171,51 @@ function MessageItemView({ item, ...given }) {
|
|
|
3534
4171
|
renderUi: ambientRenderUi
|
|
3535
4172
|
} : given;
|
|
3536
4173
|
const { classNames } = slots;
|
|
3537
|
-
const actionRow = /* @__PURE__ */
|
|
4174
|
+
const actionRow = /* @__PURE__ */ import_react17.default.createElement("div", {
|
|
3538
4175
|
className: classNames?.actions,
|
|
3539
4176
|
"data-actions-for": item.role
|
|
3540
|
-
}, item.copy.available ? /* @__PURE__ */
|
|
4177
|
+
}, item.copy.available ? /* @__PURE__ */ import_react17.default.createElement("button", {
|
|
3541
4178
|
type: "button",
|
|
3542
4179
|
onClick: item.copy.copy,
|
|
3543
4180
|
className: classNames?.actionButton,
|
|
3544
4181
|
title: item.copy.copied ? "Copied!" : "Copy message text"
|
|
3545
|
-
}, item.copy.copied ? "Copied" : "Copy") : null, item.fork.available ? /* @__PURE__ */
|
|
4182
|
+
}, item.copy.copied ? "Copied" : "Copy") : null, item.fork.available ? /* @__PURE__ */ import_react17.default.createElement("button", {
|
|
3546
4183
|
type: "button",
|
|
3547
4184
|
onClick: item.fork.run,
|
|
3548
4185
|
className: classNames?.actionButton,
|
|
3549
4186
|
title: "Fork thread from this message"
|
|
3550
|
-
}, "Fork") : null, item.regenerate.available ? /* @__PURE__ */
|
|
4187
|
+
}, "Fork") : null, item.regenerate.available ? /* @__PURE__ */ import_react17.default.createElement("button", {
|
|
3551
4188
|
type: "button",
|
|
3552
4189
|
onClick: item.regenerate.run,
|
|
3553
4190
|
className: classNames?.actionButton,
|
|
3554
4191
|
title: "Regenerate response"
|
|
3555
|
-
}, "Regenerate") : null, slots.meta, !item.isUser && item.usage ? /* @__PURE__ */
|
|
4192
|
+
}, "Regenerate") : null, slots.meta, !item.isUser && item.usage ? /* @__PURE__ */ import_react17.default.createElement("span", {
|
|
3556
4193
|
className: classNames?.usage,
|
|
3557
4194
|
title: `Input ${item.usage.inputTokens.toLocaleString()} \xB7 Output ${item.usage.outputTokens.toLocaleString()} tokens`
|
|
3558
|
-
}, item.usage.costLabel, " \xB7 ", item.usage.tokensLabel) : null, item.timestamp ? /* @__PURE__ */
|
|
4195
|
+
}, item.usage.costLabel, " \xB7 ", item.usage.tokensLabel) : null, item.timestamp ? /* @__PURE__ */ import_react17.default.createElement("span", {
|
|
3559
4196
|
className: classNames?.timestamp,
|
|
3560
4197
|
title: item.timestamp.absolute
|
|
3561
4198
|
}, item.timestamp.relative) : null);
|
|
3562
4199
|
if (item.edit.available) {
|
|
3563
|
-
return /* @__PURE__ */
|
|
4200
|
+
return /* @__PURE__ */ import_react17.default.createElement(EditableUserBubble, {
|
|
3564
4201
|
item,
|
|
3565
4202
|
slots,
|
|
3566
4203
|
actions: actionRow
|
|
3567
4204
|
});
|
|
3568
4205
|
}
|
|
3569
4206
|
const className = joinClasses(classNames?.root, classNames?.byRole?.[item.role]);
|
|
3570
|
-
return /* @__PURE__ */
|
|
4207
|
+
return /* @__PURE__ */ import_react17.default.createElement("div", {
|
|
3571
4208
|
className,
|
|
3572
4209
|
"data-role": item.role,
|
|
3573
4210
|
"data-streaming": item.isStreaming ? "true" : void 0
|
|
3574
|
-
}, /* @__PURE__ */
|
|
4211
|
+
}, /* @__PURE__ */ import_react17.default.createElement("div", null, renderBlocks(item, slots)), actionRow);
|
|
3575
4212
|
}
|
|
3576
4213
|
__name(MessageItemView, "MessageItemView");
|
|
3577
4214
|
function renderBlocks(item, slots) {
|
|
3578
4215
|
const nodes = [];
|
|
3579
4216
|
for (const block of item.blocks) {
|
|
3580
4217
|
if (block.kind === "text") {
|
|
3581
|
-
nodes.push(/* @__PURE__ */
|
|
4218
|
+
nodes.push(/* @__PURE__ */ import_react17.default.createElement("div", {
|
|
3582
4219
|
key: block.key,
|
|
3583
4220
|
className: slots.classNames?.text
|
|
3584
4221
|
}, slots.renderText ? slots.renderText(block.text, {
|
|
@@ -3599,7 +4236,7 @@ function renderBlocks(item, slots) {
|
|
|
3599
4236
|
continue;
|
|
3600
4237
|
}
|
|
3601
4238
|
if (block.kind === "ui" && slots.renderUi) {
|
|
3602
|
-
nodes.push(/* @__PURE__ */
|
|
4239
|
+
nodes.push(/* @__PURE__ */ import_react17.default.createElement("div", {
|
|
3603
4240
|
key: block.key,
|
|
3604
4241
|
"data-slot": "ui",
|
|
3605
4242
|
"data-component": block.component
|
|
@@ -3610,18 +4247,18 @@ function renderBlocks(item, slots) {
|
|
|
3610
4247
|
}
|
|
3611
4248
|
__name(renderBlocks, "renderBlocks");
|
|
3612
4249
|
function renderFilesBlock(block, slots) {
|
|
3613
|
-
return /* @__PURE__ */
|
|
4250
|
+
return /* @__PURE__ */ import_react17.default.createElement("div", {
|
|
3614
4251
|
key: block.key,
|
|
3615
4252
|
className: slots.classNames?.files,
|
|
3616
4253
|
"data-files": "true"
|
|
3617
|
-
}, slots.renderFiles ? slots.renderFiles(block.files) : block.files.map((file) => /* @__PURE__ */
|
|
4254
|
+
}, slots.renderFiles ? slots.renderFiles(block.files) : block.files.map((file) => /* @__PURE__ */ import_react17.default.createElement("a", {
|
|
3618
4255
|
key: file.url,
|
|
3619
4256
|
href: file.url,
|
|
3620
4257
|
target: "_blank",
|
|
3621
4258
|
rel: "noreferrer",
|
|
3622
4259
|
className: slots.classNames?.file,
|
|
3623
4260
|
title: file.filename ?? file.mediaType
|
|
3624
|
-
}, file.isImage ? /* @__PURE__ */
|
|
4261
|
+
}, file.isImage ? /* @__PURE__ */ import_react17.default.createElement("img", {
|
|
3625
4262
|
src: file.url,
|
|
3626
4263
|
alt: file.filename ?? "image",
|
|
3627
4264
|
className: slots.classNames?.fileImage
|
|
@@ -3629,17 +4266,17 @@ function renderFilesBlock(block, slots) {
|
|
|
3629
4266
|
}
|
|
3630
4267
|
__name(renderFilesBlock, "renderFilesBlock");
|
|
3631
4268
|
function renderReasoningBlock(block, slots) {
|
|
3632
|
-
return /* @__PURE__ */
|
|
4269
|
+
return /* @__PURE__ */ import_react17.default.createElement("div", {
|
|
3633
4270
|
key: block.key,
|
|
3634
4271
|
className: slots.classNames?.reasoning,
|
|
3635
4272
|
"data-reasoning": "true",
|
|
3636
4273
|
"data-streaming": block.isStreaming ? "true" : void 0
|
|
3637
|
-
}, /* @__PURE__ */
|
|
4274
|
+
}, /* @__PURE__ */ import_react17.default.createElement("button", {
|
|
3638
4275
|
type: "button",
|
|
3639
4276
|
className: slots.classNames?.reasoningToggle,
|
|
3640
4277
|
onClick: /* @__PURE__ */ __name(() => block.toggle(), "onClick"),
|
|
3641
4278
|
"aria-expanded": block.isOpen
|
|
3642
|
-
}, slots.reasoningLabel ?? "Reasoning"), block.isOpen ? /* @__PURE__ */
|
|
4279
|
+
}, slots.reasoningLabel ?? "Reasoning"), block.isOpen ? /* @__PURE__ */ import_react17.default.createElement("div", {
|
|
3643
4280
|
className: slots.classNames?.reasoningText
|
|
3644
4281
|
}, slots.renderReasoning ? slots.renderReasoning(block.text, {
|
|
3645
4282
|
isStreaming: block.isStreaming,
|
|
@@ -3650,7 +4287,7 @@ __name(renderReasoningBlock, "renderReasoningBlock");
|
|
|
3650
4287
|
function renderToolBlock(item, block, slots) {
|
|
3651
4288
|
if (slots.renderToolGroup) {
|
|
3652
4289
|
return [
|
|
3653
|
-
/* @__PURE__ */
|
|
4290
|
+
/* @__PURE__ */ import_react17.default.createElement(import_react17.default.Fragment, {
|
|
3654
4291
|
key: block.key
|
|
3655
4292
|
}, slots.renderToolGroup(block.parts, block.key))
|
|
3656
4293
|
];
|
|
@@ -3661,7 +4298,7 @@ function renderToolBlock(item, block, slots) {
|
|
|
3661
4298
|
const renderToolPart = slots.renderToolPart;
|
|
3662
4299
|
return block.parts.map((part) => {
|
|
3663
4300
|
const partKey = `${item.id}-${part.toolCallId}`;
|
|
3664
|
-
return /* @__PURE__ */
|
|
4301
|
+
return /* @__PURE__ */ import_react17.default.createElement(import_react17.default.Fragment, {
|
|
3665
4302
|
key: partKey
|
|
3666
4303
|
}, renderToolPart(part, partKey));
|
|
3667
4304
|
});
|
|
@@ -3671,14 +4308,14 @@ function EditableUserBubble({ item, slots, actions }) {
|
|
|
3671
4308
|
const { classNames } = slots;
|
|
3672
4309
|
const { edit } = item;
|
|
3673
4310
|
if (!edit.isEditing) {
|
|
3674
|
-
return /* @__PURE__ */
|
|
4311
|
+
return /* @__PURE__ */ import_react17.default.createElement("div", {
|
|
3675
4312
|
className: joinClasses(classNames?.root, classNames?.byRole?.user),
|
|
3676
4313
|
"data-role": "user"
|
|
3677
|
-
}, /* @__PURE__ */
|
|
4314
|
+
}, /* @__PURE__ */ import_react17.default.createElement("div", {
|
|
3678
4315
|
className: classNames?.text
|
|
3679
4316
|
}, slots.renderText ? slots.renderText(item.text, {
|
|
3680
4317
|
isStreaming: false
|
|
3681
|
-
}) : item.text), /* @__PURE__ */
|
|
4318
|
+
}) : item.text), /* @__PURE__ */ import_react17.default.createElement("button", {
|
|
3682
4319
|
type: "button",
|
|
3683
4320
|
onClick: edit.start,
|
|
3684
4321
|
className: classNames?.actionButton,
|
|
@@ -3686,18 +4323,18 @@ function EditableUserBubble({ item, slots, actions }) {
|
|
|
3686
4323
|
}, "Edit"), actions);
|
|
3687
4324
|
}
|
|
3688
4325
|
const textareaProps = edit.getTextareaProps();
|
|
3689
|
-
return /* @__PURE__ */
|
|
4326
|
+
return /* @__PURE__ */ import_react17.default.createElement("div", {
|
|
3690
4327
|
"data-editing": "true"
|
|
3691
|
-
}, /* @__PURE__ */
|
|
4328
|
+
}, /* @__PURE__ */ import_react17.default.createElement("textarea", {
|
|
3692
4329
|
...textareaProps,
|
|
3693
4330
|
rows: Math.min(8, edit.draft.split("\n").length + 1),
|
|
3694
4331
|
className: classNames?.editTextarea
|
|
3695
|
-
}), /* @__PURE__ */
|
|
4332
|
+
}), /* @__PURE__ */ import_react17.default.createElement("div", {
|
|
3696
4333
|
className: classNames?.editActions
|
|
3697
|
-
}, /* @__PURE__ */
|
|
4334
|
+
}, /* @__PURE__ */ import_react17.default.createElement("button", {
|
|
3698
4335
|
type: "button",
|
|
3699
4336
|
onClick: edit.cancel
|
|
3700
|
-
}, "Cancel"), /* @__PURE__ */
|
|
4337
|
+
}, "Cancel"), /* @__PURE__ */ import_react17.default.createElement("button", {
|
|
3701
4338
|
type: "button",
|
|
3702
4339
|
onClick: edit.save,
|
|
3703
4340
|
disabled: !edit.canSave
|
|
@@ -3907,11 +4544,11 @@ function createSkillsSource(options) {
|
|
|
3907
4544
|
if (cached) {
|
|
3908
4545
|
return cached;
|
|
3909
4546
|
}
|
|
3910
|
-
const listSkills = options.
|
|
4547
|
+
const listSkills = options.backend.listSkills;
|
|
3911
4548
|
if (listSkills === void 0) {
|
|
3912
4549
|
return Promise.reject(new AgentBackendUnsupportedError("listSkills"));
|
|
3913
4550
|
}
|
|
3914
|
-
const pending = listSkills.call(options.
|
|
4551
|
+
const pending = listSkills.call(options.backend, threadId).then((entries) => entries.map(toItem)).catch((error) => {
|
|
3915
4552
|
byThread.delete(key);
|
|
3916
4553
|
throw error;
|
|
3917
4554
|
});
|
|
@@ -3941,35 +4578,35 @@ function toItem(entry) {
|
|
|
3941
4578
|
__name(toItem, "toItem");
|
|
3942
4579
|
|
|
3943
4580
|
// src/composer/use-composer-autocomplete.ts
|
|
3944
|
-
var
|
|
4581
|
+
var import_react18 = require("react");
|
|
3945
4582
|
function useComposerAutocomplete(options) {
|
|
3946
4583
|
const { value, sources, acceptOnTab = true } = options;
|
|
3947
|
-
const latest = (0,
|
|
4584
|
+
const latest = (0, import_react18.useRef)(options);
|
|
3948
4585
|
latest.current = options;
|
|
3949
|
-
const inputRef = (0,
|
|
3950
|
-
const [caret, setCaret] = (0,
|
|
3951
|
-
const [items, setItems] = (0,
|
|
3952
|
-
const [isLoading, setLoading] = (0,
|
|
3953
|
-
const [error, setError] = (0,
|
|
3954
|
-
const [activeIndex, setActiveIndex] = (0,
|
|
3955
|
-
const [dismissedIndex, setDismissedIndex] = (0,
|
|
4586
|
+
const inputRef = (0, import_react18.useRef)(null);
|
|
4587
|
+
const [caret, setCaret] = (0, import_react18.useState)(value.length);
|
|
4588
|
+
const [items, setItems] = (0, import_react18.useState)([]);
|
|
4589
|
+
const [isLoading, setLoading] = (0, import_react18.useState)(false);
|
|
4590
|
+
const [error, setError] = (0, import_react18.useState)(null);
|
|
4591
|
+
const [activeIndex, setActiveIndex] = (0, import_react18.useState)(0);
|
|
4592
|
+
const [dismissedIndex, setDismissedIndex] = (0, import_react18.useState)(null);
|
|
3956
4593
|
const safeCaret = Math.min(caret, value.length);
|
|
3957
|
-
const match = (0,
|
|
4594
|
+
const match = (0, import_react18.useMemo)(() => findActiveTrigger(value, safeCaret, sources), [
|
|
3958
4595
|
value,
|
|
3959
4596
|
safeCaret,
|
|
3960
4597
|
sources
|
|
3961
4598
|
]);
|
|
3962
4599
|
const isActive = match !== null && dismissedIndex !== match.index;
|
|
3963
|
-
const matchRef = (0,
|
|
4600
|
+
const matchRef = (0, import_react18.useRef)(match);
|
|
3964
4601
|
matchRef.current = match;
|
|
3965
|
-
const caretRef = (0,
|
|
4602
|
+
const caretRef = (0, import_react18.useRef)(safeCaret);
|
|
3966
4603
|
caretRef.current = safeCaret;
|
|
3967
|
-
const itemsRef = (0,
|
|
4604
|
+
const itemsRef = (0, import_react18.useRef)(items);
|
|
3968
4605
|
itemsRef.current = items;
|
|
3969
|
-
const activeIndexRef = (0,
|
|
4606
|
+
const activeIndexRef = (0, import_react18.useRef)(activeIndex);
|
|
3970
4607
|
activeIndexRef.current = activeIndex;
|
|
3971
4608
|
const requestKey = isActive && match ? `${match.source.id}\0${match.query}` : null;
|
|
3972
|
-
(0,
|
|
4609
|
+
(0, import_react18.useEffect)(() => {
|
|
3973
4610
|
const current = matchRef.current;
|
|
3974
4611
|
if (requestKey === null || current === null) {
|
|
3975
4612
|
setItems([]);
|
|
@@ -4017,25 +4654,25 @@ function useComposerAutocomplete(options) {
|
|
|
4017
4654
|
]);
|
|
4018
4655
|
const isOpen = isActive;
|
|
4019
4656
|
const activeItem = isOpen ? items[activeIndex] ?? null : null;
|
|
4020
|
-
const reactId = (0,
|
|
4657
|
+
const reactId = (0, import_react18.useId)();
|
|
4021
4658
|
const listboxId = options.id ?? `agent-autocomplete-${reactId}`;
|
|
4022
|
-
const optionId = (0,
|
|
4659
|
+
const optionId = (0, import_react18.useCallback)((index) => `${listboxId}-option-${index}`, [
|
|
4023
4660
|
listboxId
|
|
4024
4661
|
]);
|
|
4025
|
-
const highlight = (0,
|
|
4662
|
+
const highlight = (0, import_react18.useCallback)((index) => {
|
|
4026
4663
|
const total = itemsRef.current.length;
|
|
4027
4664
|
if (total === 0) return;
|
|
4028
4665
|
setActiveIndex((index % total + total) % total);
|
|
4029
4666
|
}, []);
|
|
4030
|
-
const moveHighlight = (0,
|
|
4667
|
+
const moveHighlight = (0, import_react18.useCallback)((delta) => highlight(activeIndexRef.current + delta), [
|
|
4031
4668
|
highlight
|
|
4032
4669
|
]);
|
|
4033
|
-
const dismiss = (0,
|
|
4670
|
+
const dismiss = (0, import_react18.useCallback)(() => {
|
|
4034
4671
|
const current = matchRef.current;
|
|
4035
4672
|
if (current) setDismissedIndex(current.index);
|
|
4036
4673
|
}, []);
|
|
4037
|
-
const pendingCaret = (0,
|
|
4038
|
-
const accept = (0,
|
|
4674
|
+
const pendingCaret = (0, import_react18.useRef)(null);
|
|
4675
|
+
const accept = (0, import_react18.useCallback)((item) => {
|
|
4039
4676
|
const current = matchRef.current;
|
|
4040
4677
|
if (!current) return;
|
|
4041
4678
|
const chosen = item ?? itemsRef.current[activeIndexRef.current];
|
|
@@ -4046,16 +4683,16 @@ function useComposerAutocomplete(options) {
|
|
|
4046
4683
|
setDismissedIndex(null);
|
|
4047
4684
|
pendingCaret.current = edit.caret;
|
|
4048
4685
|
}, []);
|
|
4049
|
-
(0,
|
|
4686
|
+
(0, import_react18.useLayoutEffect)(() => {
|
|
4050
4687
|
const position = pendingCaret.current;
|
|
4051
4688
|
if (position === null) return;
|
|
4052
4689
|
pendingCaret.current = null;
|
|
4053
4690
|
inputRef.current?.setSelectionRange(position, position);
|
|
4054
4691
|
});
|
|
4055
|
-
const readCaret = (0,
|
|
4692
|
+
const readCaret = (0, import_react18.useCallback)((element) => {
|
|
4056
4693
|
setCaret(element.selectionStart ?? element.value.length);
|
|
4057
4694
|
}, []);
|
|
4058
|
-
const onKeyDown = (0,
|
|
4695
|
+
const onKeyDown = (0, import_react18.useCallback)((event) => {
|
|
4059
4696
|
if (!isOpen) return;
|
|
4060
4697
|
const hasItems = itemsRef.current.length > 0;
|
|
4061
4698
|
switch (event.key) {
|
|
@@ -4093,23 +4730,23 @@ function useComposerAutocomplete(options) {
|
|
|
4093
4730
|
dismiss,
|
|
4094
4731
|
moveHighlight
|
|
4095
4732
|
]);
|
|
4096
|
-
const onChange = (0,
|
|
4733
|
+
const onChange = (0, import_react18.useCallback)((event) => {
|
|
4097
4734
|
readCaret(event.target);
|
|
4098
4735
|
const next = findActiveTrigger(event.target.value, event.target.selectionStart ?? event.target.value.length, latest.current.sources);
|
|
4099
4736
|
setDismissedIndex((current) => current !== null && next?.index === current ? current : null);
|
|
4100
4737
|
}, [
|
|
4101
4738
|
readCaret
|
|
4102
4739
|
]);
|
|
4103
|
-
const onSelect = (0,
|
|
4740
|
+
const onSelect = (0, import_react18.useCallback)((event) => readCaret(event.currentTarget), [
|
|
4104
4741
|
readCaret
|
|
4105
4742
|
]);
|
|
4106
|
-
const onClick = (0,
|
|
4743
|
+
const onClick = (0, import_react18.useCallback)((event) => readCaret(event.currentTarget), [
|
|
4107
4744
|
readCaret
|
|
4108
4745
|
]);
|
|
4109
|
-
const setInput = (0,
|
|
4746
|
+
const setInput = (0, import_react18.useCallback)((element) => {
|
|
4110
4747
|
inputRef.current = element;
|
|
4111
4748
|
}, []);
|
|
4112
|
-
const getInputProps = (0,
|
|
4749
|
+
const getInputProps = (0, import_react18.useCallback)(() => ({
|
|
4113
4750
|
ref: setInput,
|
|
4114
4751
|
onChange,
|
|
4115
4752
|
onKeyDown,
|
|
@@ -4137,7 +4774,7 @@ function useComposerAutocomplete(options) {
|
|
|
4137
4774
|
activeIndex,
|
|
4138
4775
|
optionId
|
|
4139
4776
|
]);
|
|
4140
|
-
const getListboxProps = (0,
|
|
4777
|
+
const getListboxProps = (0, import_react18.useCallback)(() => ({
|
|
4141
4778
|
id: listboxId,
|
|
4142
4779
|
role: "listbox",
|
|
4143
4780
|
"aria-label": match?.source.label ?? match?.source.id ?? "Suggestions"
|
|
@@ -4145,7 +4782,7 @@ function useComposerAutocomplete(options) {
|
|
|
4145
4782
|
listboxId,
|
|
4146
4783
|
match
|
|
4147
4784
|
]);
|
|
4148
|
-
const getOptionProps = (0,
|
|
4785
|
+
const getOptionProps = (0, import_react18.useCallback)((index) => ({
|
|
4149
4786
|
id: optionId(index),
|
|
4150
4787
|
role: "option",
|
|
4151
4788
|
"aria-selected": index === activeIndex
|
|
@@ -4179,7 +4816,7 @@ function isPromise(value) {
|
|
|
4179
4816
|
__name(isPromise, "isPromise");
|
|
4180
4817
|
|
|
4181
4818
|
// src/presentation/use-tool-catalog.ts
|
|
4182
|
-
var
|
|
4819
|
+
var import_react19 = require("react");
|
|
4183
4820
|
var shared = /* @__PURE__ */ new WeakMap();
|
|
4184
4821
|
function load(client, agent) {
|
|
4185
4822
|
let byAgent = shared.get(client);
|
|
@@ -4201,13 +4838,14 @@ function load(client, agent) {
|
|
|
4201
4838
|
return request;
|
|
4202
4839
|
}
|
|
4203
4840
|
__name(load, "load");
|
|
4204
|
-
function useToolCatalog(options) {
|
|
4205
|
-
const {
|
|
4206
|
-
const
|
|
4207
|
-
const [
|
|
4208
|
-
const [
|
|
4209
|
-
const [
|
|
4210
|
-
(0,
|
|
4841
|
+
function useToolCatalog(options = {}) {
|
|
4842
|
+
const { agent, enabled = true } = options;
|
|
4843
|
+
const client = useAgentBackend(options.backend);
|
|
4844
|
+
const [entries, setEntries] = (0, import_react19.useState)([]);
|
|
4845
|
+
const [isLoading, setLoading] = (0, import_react19.useState)(enabled);
|
|
4846
|
+
const [error, setError] = (0, import_react19.useState)(null);
|
|
4847
|
+
const [generation, setGeneration] = (0, import_react19.useState)(0);
|
|
4848
|
+
(0, import_react19.useEffect)(() => {
|
|
4211
4849
|
if (!enabled) {
|
|
4212
4850
|
setLoading(false);
|
|
4213
4851
|
return;
|
|
@@ -4216,7 +4854,7 @@ function useToolCatalog(options) {
|
|
|
4216
4854
|
setLoading(true);
|
|
4217
4855
|
load(client, agent).then((loaded) => {
|
|
4218
4856
|
if (cancelled) return;
|
|
4219
|
-
setEntries(loaded);
|
|
4857
|
+
setEntries(Array.isArray(loaded) ? loaded : []);
|
|
4220
4858
|
setError(null);
|
|
4221
4859
|
setLoading(false);
|
|
4222
4860
|
}, (failure) => {
|
|
@@ -4233,14 +4871,14 @@ function useToolCatalog(options) {
|
|
|
4233
4871
|
enabled,
|
|
4234
4872
|
generation
|
|
4235
4873
|
]);
|
|
4236
|
-
const refresh = (0,
|
|
4874
|
+
const refresh = (0, import_react19.useCallback)(() => {
|
|
4237
4875
|
shared.get(client)?.delete(agent ?? "");
|
|
4238
4876
|
setGeneration((current) => current + 1);
|
|
4239
4877
|
}, [
|
|
4240
4878
|
client,
|
|
4241
4879
|
agent
|
|
4242
4880
|
]);
|
|
4243
|
-
const catalog = (0,
|
|
4881
|
+
const catalog = (0, import_react19.useMemo)(() => toolCatalogFrom(entries), [
|
|
4244
4882
|
entries
|
|
4245
4883
|
]);
|
|
4246
4884
|
return {
|
|
@@ -4254,7 +4892,7 @@ function useToolCatalog(options) {
|
|
|
4254
4892
|
__name(useToolCatalog, "useToolCatalog");
|
|
4255
4893
|
|
|
4256
4894
|
// src/approvals/countdown.ts
|
|
4257
|
-
var
|
|
4895
|
+
var import_react20 = require("react");
|
|
4258
4896
|
function approvalCountdown(expiresAt, now = Date.now()) {
|
|
4259
4897
|
const deadline = expiresAt == null ? Number.NaN : Date.parse(expiresAt);
|
|
4260
4898
|
if (!Number.isFinite(deadline)) {
|
|
@@ -4272,10 +4910,10 @@ function approvalCountdown(expiresAt, now = Date.now()) {
|
|
|
4272
4910
|
__name(approvalCountdown, "approvalCountdown");
|
|
4273
4911
|
function useApprovalCountdown(expiresAt, options = {}) {
|
|
4274
4912
|
const { intervalMs = 1e3 } = options;
|
|
4275
|
-
const nowRef = (0,
|
|
4913
|
+
const nowRef = (0, import_react20.useRef)(options.now ?? Date.now);
|
|
4276
4914
|
nowRef.current = options.now ?? Date.now;
|
|
4277
|
-
const [state, setState] = (0,
|
|
4278
|
-
(0,
|
|
4915
|
+
const [state, setState] = (0, import_react20.useState)(() => approvalCountdown(expiresAt, nowRef.current()));
|
|
4916
|
+
(0, import_react20.useEffect)(() => {
|
|
4279
4917
|
const read = /* @__PURE__ */ __name(() => approvalCountdown(expiresAt, nowRef.current()), "read");
|
|
4280
4918
|
const first = read();
|
|
4281
4919
|
setState(first);
|
|
@@ -4444,14 +5082,27 @@ function storedMessageToUiMessage(message) {
|
|
|
4444
5082
|
});
|
|
4445
5083
|
parts.push(...pushedByCall.get(call.id) ?? []);
|
|
4446
5084
|
}
|
|
5085
|
+
const metadata = {
|
|
5086
|
+
...message.feedback !== void 0 ? {
|
|
5087
|
+
feedback: message.feedback
|
|
5088
|
+
} : {},
|
|
5089
|
+
...message.createdAt ? {
|
|
5090
|
+
createdAt: message.createdAt
|
|
5091
|
+
} : {},
|
|
5092
|
+
...message.usage !== void 0 ? {
|
|
5093
|
+
usage: {
|
|
5094
|
+
inputTokens: message.usage.inputTokens,
|
|
5095
|
+
outputTokens: message.usage.outputTokens,
|
|
5096
|
+
costUsd: message.usage.costUsd ?? null
|
|
5097
|
+
}
|
|
5098
|
+
} : {}
|
|
5099
|
+
};
|
|
4447
5100
|
return {
|
|
4448
5101
|
id: message.id,
|
|
4449
5102
|
role: message.role,
|
|
4450
5103
|
parts,
|
|
4451
|
-
...
|
|
4452
|
-
metadata
|
|
4453
|
-
feedback: message.feedback
|
|
4454
|
-
}
|
|
5104
|
+
...Object.keys(metadata).length > 0 ? {
|
|
5105
|
+
metadata
|
|
4455
5106
|
} : {}
|
|
4456
5107
|
};
|
|
4457
5108
|
}
|
|
@@ -4489,12 +5140,16 @@ function mergeTurn(rows) {
|
|
|
4489
5140
|
const parts = rows.flatMap((row) => storedMessageToUiMessage(row).parts);
|
|
4490
5141
|
const usage = sumUsage(rows);
|
|
4491
5142
|
const feedback = lastRow.feedback;
|
|
5143
|
+
const createdAt = rows[0]?.createdAt;
|
|
4492
5144
|
const metadata = {
|
|
4493
5145
|
...usage !== void 0 ? {
|
|
4494
5146
|
usage
|
|
4495
5147
|
} : {},
|
|
4496
5148
|
...feedback !== void 0 ? {
|
|
4497
5149
|
feedback
|
|
5150
|
+
} : {},
|
|
5151
|
+
...createdAt ? {
|
|
5152
|
+
createdAt
|
|
4498
5153
|
} : {}
|
|
4499
5154
|
};
|
|
4500
5155
|
return {
|
|
@@ -4522,69 +5177,63 @@ function sumUsage(rows) {
|
|
|
4522
5177
|
__name(sumUsage, "sumUsage");
|
|
4523
5178
|
|
|
4524
5179
|
// src/use-agent-chat.ts
|
|
4525
|
-
var
|
|
4526
|
-
var
|
|
4527
|
-
|
|
4528
|
-
|
|
5180
|
+
var import_react21 = require("@ai-sdk/react");
|
|
5181
|
+
var import_react22 = require("react");
|
|
5182
|
+
var localChatSequence = 0;
|
|
5183
|
+
function localChatId() {
|
|
5184
|
+
localChatSequence += 1;
|
|
5185
|
+
return `local-chat-${localChatSequence}`;
|
|
5186
|
+
}
|
|
5187
|
+
__name(localChatId, "localChatId");
|
|
5188
|
+
function useAgentChat(options = {}) {
|
|
5189
|
+
const latest = (0, import_react22.useRef)(options);
|
|
4529
5190
|
latest.current = options;
|
|
4530
|
-
const
|
|
4531
|
-
const
|
|
5191
|
+
const resolved = useAgentBackend(options.backend);
|
|
5192
|
+
const client = (0, import_react22.useRef)(resolved).current;
|
|
5193
|
+
const createdThreadId = (0, import_react22.useRef)(void 0);
|
|
5194
|
+
const chatIdRef = (0, import_react22.useRef)(options.threadId ?? localChatId());
|
|
5195
|
+
const boundThreadRef = (0, import_react22.useRef)(options.threadId);
|
|
5196
|
+
if (options.threadId !== boundThreadRef.current) {
|
|
5197
|
+
boundThreadRef.current = options.threadId;
|
|
5198
|
+
const adopting = options.threadId !== void 0 && options.threadId === createdThreadId.current;
|
|
5199
|
+
if (!adopting) {
|
|
5200
|
+
chatIdRef.current = options.threadId ?? localChatId();
|
|
5201
|
+
createdThreadId.current = void 0;
|
|
5202
|
+
}
|
|
5203
|
+
}
|
|
5204
|
+
const chatId = chatIdRef.current;
|
|
5205
|
+
const [runId, setRunId] = (0, import_react22.useState)(options.resumeRunId);
|
|
5206
|
+
const runIdRef = (0, import_react22.useRef)(runId);
|
|
4532
5207
|
runIdRef.current = runId;
|
|
4533
|
-
const settlingRunIdRef = (0,
|
|
4534
|
-
const autoResumeRunIdRef = (0,
|
|
4535
|
-
const [
|
|
4536
|
-
const [
|
|
4537
|
-
const
|
|
4538
|
-
const
|
|
4539
|
-
const
|
|
4540
|
-
|
|
4541
|
-
|
|
4542
|
-
|
|
4543
|
-
|
|
4544
|
-
|
|
4545
|
-
|
|
4546
|
-
...options.credentials !== void 0 ? {
|
|
4547
|
-
credentials: options.credentials
|
|
4548
|
-
} : {},
|
|
4549
|
-
...options.fetch !== void 0 ? {
|
|
4550
|
-
fetch: options.fetch
|
|
4551
|
-
} : {},
|
|
4552
|
-
...options.attachments !== void 0 ? {
|
|
4553
|
-
attachments: options.attachments
|
|
4554
|
-
} : {},
|
|
4555
|
-
getHeaders: /* @__PURE__ */ __name(async () => mergeHeaders(latest.current), "getHeaders")
|
|
4556
|
-
});
|
|
4557
|
-
}, []);
|
|
4558
|
-
const [connection, setConnection] = (0, import_react19.useState)({
|
|
5208
|
+
const settlingRunIdRef = (0, import_react22.useRef)(void 0);
|
|
5209
|
+
const autoResumeRunIdRef = (0, import_react22.useRef)(void 0);
|
|
5210
|
+
const [activeRunId, setActiveRunId] = (0, import_react22.useState)(null);
|
|
5211
|
+
const [isLoadingHistory, setIsLoadingHistory] = (0, import_react22.useState)(false);
|
|
5212
|
+
const [historyError, setHistoryError] = (0, import_react22.useState)(null);
|
|
5213
|
+
const [threadModel, setThreadModel] = (0, import_react22.useState)(null);
|
|
5214
|
+
const [pickedModel, setPickedModel] = (0, import_react22.useState)(void 0);
|
|
5215
|
+
const pickedModelRef = (0, import_react22.useRef)(pickedModel);
|
|
5216
|
+
pickedModelRef.current = pickedModel;
|
|
5217
|
+
const pendingPin = (0, import_react22.useRef)(void 0);
|
|
5218
|
+
const regenerateNext = (0, import_react22.useRef)(false);
|
|
5219
|
+
const currentThreadId = (0, import_react22.useCallback)(() => latest.current.threadId ?? createdThreadId.current, []);
|
|
5220
|
+
const [connection, setConnection] = (0, import_react22.useState)({
|
|
4559
5221
|
status: "live"
|
|
4560
5222
|
});
|
|
4561
|
-
const resyncAfterSettle = (0,
|
|
4562
|
-
(0,
|
|
4563
|
-
if (!options.resume || options.threadId === void 0) return;
|
|
4564
|
-
let cancelled = false;
|
|
4565
|
-
const threadId = options.threadId;
|
|
4566
|
-
void client.getThread(threadId).then((thread) => {
|
|
4567
|
-
if (cancelled) return;
|
|
4568
|
-
setActiveRunId(thread.activeRunId ?? null);
|
|
4569
|
-
if (thread.activeRunId != null) {
|
|
4570
|
-
autoResumeRunIdRef.current = thread.activeRunId;
|
|
4571
|
-
setAutoResume(true);
|
|
4572
|
-
}
|
|
4573
|
-
});
|
|
4574
|
-
return () => {
|
|
4575
|
-
cancelled = true;
|
|
4576
|
-
};
|
|
4577
|
-
}, [
|
|
4578
|
-
client,
|
|
4579
|
-
options.resume,
|
|
4580
|
-
options.threadId
|
|
4581
|
-
]);
|
|
4582
|
-
const transport = (0, import_react19.useMemo)(() => {
|
|
5223
|
+
const resyncAfterSettle = (0, import_react22.useRef)(false);
|
|
5224
|
+
const transport = (0, import_react22.useMemo)(() => {
|
|
4583
5225
|
function onMeta(meta) {
|
|
4584
5226
|
settlingRunIdRef.current = meta.runId;
|
|
4585
5227
|
setRunId(meta.runId);
|
|
4586
5228
|
if (latest.current.threadId === void 0 && meta.threadId && createdThreadId.current !== meta.threadId) {
|
|
4587
5229
|
createdThreadId.current = meta.threadId;
|
|
5230
|
+
const pin = pendingPin.current;
|
|
5231
|
+
if (pin !== void 0) {
|
|
5232
|
+
pendingPin.current = void 0;
|
|
5233
|
+
void client.updateThread(meta.threadId, {
|
|
5234
|
+
model: pin.model
|
|
5235
|
+
}).catch(() => void 0);
|
|
5236
|
+
}
|
|
4588
5237
|
latest.current.onThreadCreated?.(meta.threadId);
|
|
4589
5238
|
notifyThreads(client, {
|
|
4590
5239
|
type: "changed"
|
|
@@ -4611,13 +5260,14 @@ function useAgentChat(options) {
|
|
|
4611
5260
|
const pageContext = current.getPageContext?.() ?? null;
|
|
4612
5261
|
const regenerate2 = regenerateNext.current;
|
|
4613
5262
|
regenerateNext.current = false;
|
|
4614
|
-
const threadId =
|
|
5263
|
+
const threadId = currentThreadId();
|
|
5264
|
+
const model = current.model ?? pickedModelRef.current;
|
|
4615
5265
|
return {
|
|
4616
5266
|
...threadId !== void 0 ? {
|
|
4617
5267
|
threadId
|
|
4618
5268
|
} : {},
|
|
4619
|
-
...
|
|
4620
|
-
model
|
|
5269
|
+
...model !== void 0 ? {
|
|
5270
|
+
model
|
|
4621
5271
|
} : {},
|
|
4622
5272
|
...pageContext ? {
|
|
4623
5273
|
pageContext
|
|
@@ -4634,13 +5284,11 @@ function useAgentChat(options) {
|
|
|
4634
5284
|
}, "onAttemptStart")
|
|
4635
5285
|
});
|
|
4636
5286
|
}, []);
|
|
4637
|
-
const backgroundRef = (0,
|
|
4638
|
-
const chat = (0,
|
|
5287
|
+
const backgroundRef = (0, import_react22.useRef)(() => Promise.resolve());
|
|
5288
|
+
const chat = (0, import_react21.useChat)({
|
|
4639
5289
|
transport,
|
|
4640
|
-
|
|
4641
|
-
|
|
4642
|
-
id: options.threadId
|
|
4643
|
-
} : {},
|
|
5290
|
+
id: chatId,
|
|
5291
|
+
resume: options.resumeRunId !== void 0,
|
|
4644
5292
|
...options.initialMessages !== void 0 ? {
|
|
4645
5293
|
messages: options.initialMessages
|
|
4646
5294
|
} : {},
|
|
@@ -4650,7 +5298,7 @@ function useAgentChat(options) {
|
|
|
4650
5298
|
const title = part.data?.title;
|
|
4651
5299
|
if (typeof title === "string") {
|
|
4652
5300
|
latest.current.onTitle?.(title);
|
|
4653
|
-
const threadId =
|
|
5301
|
+
const threadId = currentThreadId();
|
|
4654
5302
|
if (threadId !== void 0) notifyThreads(client, {
|
|
4655
5303
|
type: "title",
|
|
4656
5304
|
threadId,
|
|
@@ -4683,10 +5331,10 @@ function useAgentChat(options) {
|
|
|
4683
5331
|
}
|
|
4684
5332
|
}, "onFinish")
|
|
4685
5333
|
});
|
|
4686
|
-
const chatRef = (0,
|
|
5334
|
+
const chatRef = (0, import_react22.useRef)(chat);
|
|
4687
5335
|
chatRef.current = chat;
|
|
4688
5336
|
async function resyncFromThread() {
|
|
4689
|
-
const threadId =
|
|
5337
|
+
const threadId = currentThreadId();
|
|
4690
5338
|
if (threadId === void 0) return;
|
|
4691
5339
|
try {
|
|
4692
5340
|
const thread = await client.getThread(threadId);
|
|
@@ -4695,13 +5343,75 @@ function useAgentChat(options) {
|
|
|
4695
5343
|
}
|
|
4696
5344
|
}
|
|
4697
5345
|
__name(resyncFromThread, "resyncFromThread");
|
|
4698
|
-
const
|
|
4699
|
-
|
|
5346
|
+
const firstChatId = (0, import_react22.useRef)(chatId);
|
|
5347
|
+
(0, import_react22.useEffect)(() => {
|
|
5348
|
+
if (chatId === firstChatId.current) return;
|
|
5349
|
+
firstChatId.current = chatId;
|
|
5350
|
+
setRunId(void 0);
|
|
5351
|
+
setActiveRunId(null);
|
|
5352
|
+
setThreadModel(null);
|
|
5353
|
+
setBackgroundRuns([]);
|
|
5354
|
+
setHistoryError(null);
|
|
5355
|
+
autoResumeRunIdRef.current = void 0;
|
|
5356
|
+
pendingPin.current = void 0;
|
|
5357
|
+
}, [
|
|
5358
|
+
chatId
|
|
5359
|
+
]);
|
|
5360
|
+
(0, import_react22.useEffect)(() => {
|
|
5361
|
+
const threadId = options.threadId;
|
|
5362
|
+
if (threadId === void 0) return;
|
|
5363
|
+
if (threadId === createdThreadId.current) return;
|
|
5364
|
+
const current = latest.current;
|
|
5365
|
+
const wantHistory = current.history !== false && current.initialMessages === void 0;
|
|
5366
|
+
const wantResume = current.resume !== false && current.resumeRunId === void 0;
|
|
5367
|
+
if (!wantHistory && !wantResume) return;
|
|
5368
|
+
let cancelled = false;
|
|
5369
|
+
if (wantHistory) setIsLoadingHistory(true);
|
|
5370
|
+
client.getThread(threadId).then((thread) => {
|
|
5371
|
+
if (cancelled || thread == null) return;
|
|
5372
|
+
const active = thread.activeRunId ?? null;
|
|
5373
|
+
const stored = Array.isArray(thread.messages) ? thread.messages : [];
|
|
5374
|
+
setActiveRunId(active);
|
|
5375
|
+
setThreadModel(thread.model ?? null);
|
|
5376
|
+
setHistoryError(null);
|
|
5377
|
+
const resuming = wantResume && active !== null;
|
|
5378
|
+
if (wantHistory && chatRef.current.messages.length === 0) {
|
|
5379
|
+
const rows = resuming ? stored.filter((message) => !(message.role === "assistant" && message.runId === active)) : stored;
|
|
5380
|
+
chatRef.current.setMessages(storedThreadToUiMessages(rows));
|
|
5381
|
+
}
|
|
5382
|
+
if (resuming) {
|
|
5383
|
+
autoResumeRunIdRef.current = active;
|
|
5384
|
+
void chatRef.current.resumeStream();
|
|
5385
|
+
}
|
|
5386
|
+
}, (error) => {
|
|
5387
|
+
if (cancelled) return;
|
|
5388
|
+
setHistoryError(error instanceof Error ? error : new Error(String(error)));
|
|
5389
|
+
}).finally(() => {
|
|
5390
|
+
if (!cancelled) setIsLoadingHistory(false);
|
|
5391
|
+
});
|
|
5392
|
+
return () => {
|
|
5393
|
+
cancelled = true;
|
|
5394
|
+
setIsLoadingHistory(false);
|
|
5395
|
+
};
|
|
5396
|
+
}, [
|
|
5397
|
+
client,
|
|
5398
|
+
chatId,
|
|
5399
|
+
options.threadId
|
|
5400
|
+
]);
|
|
5401
|
+
const turnInFlight = (0, import_react22.useRef)(false);
|
|
5402
|
+
const isTurnInFlight = (0, import_react22.useCallback)(() => turnInFlight.current || transport.isAttemptLive, [
|
|
4700
5403
|
transport
|
|
4701
5404
|
]);
|
|
4702
|
-
const
|
|
4703
|
-
|
|
4704
|
-
|
|
5405
|
+
const quota = useQuota({
|
|
5406
|
+
backend: client,
|
|
5407
|
+
enabled: options.quota !== false && typeof client.getQuota === "function"
|
|
5408
|
+
});
|
|
5409
|
+
const blocked = options.blocked !== void 0 ? options.blocked : quota.blocked;
|
|
5410
|
+
const blockedRef = (0, import_react22.useRef)(blocked);
|
|
5411
|
+
blockedRef.current = blocked;
|
|
5412
|
+
const sendMessage = (0, import_react22.useCallback)(async (...args) => {
|
|
5413
|
+
const block = blockedRef.current;
|
|
5414
|
+
if (block != null) throw new QuotaBlockedError(block);
|
|
4705
5415
|
if (isTurnInFlight()) return;
|
|
4706
5416
|
turnInFlight.current = true;
|
|
4707
5417
|
try {
|
|
@@ -4712,16 +5422,14 @@ function useAgentChat(options) {
|
|
|
4712
5422
|
}, [
|
|
4713
5423
|
isTurnInFlight
|
|
4714
5424
|
]);
|
|
4715
|
-
const addToolResult = (0,
|
|
5425
|
+
const addToolResult = (0, import_react22.useCallback)(({ tool, toolCallId, output }) => chatRef.current.addToolResult({
|
|
4716
5426
|
tool,
|
|
4717
5427
|
toolCallId,
|
|
4718
5428
|
output
|
|
4719
5429
|
}), []);
|
|
4720
|
-
const [
|
|
4721
|
-
const
|
|
4722
|
-
|
|
4723
|
-
const refreshBackground = (0, import_react19.useCallback)(async () => {
|
|
4724
|
-
const threadId = latest.current.threadId ?? createdThreadId.current;
|
|
5430
|
+
const [backgroundRuns, setBackgroundRuns] = (0, import_react22.useState)([]);
|
|
5431
|
+
const refreshBackground = (0, import_react22.useCallback)(async () => {
|
|
5432
|
+
const threadId = currentThreadId();
|
|
4725
5433
|
if (threadId === void 0) {
|
|
4726
5434
|
return;
|
|
4727
5435
|
}
|
|
@@ -4741,11 +5449,12 @@ function useAgentChat(options) {
|
|
|
4741
5449
|
];
|
|
4742
5450
|
});
|
|
4743
5451
|
}, [
|
|
4744
|
-
client
|
|
5452
|
+
client,
|
|
5453
|
+
currentThreadId
|
|
4745
5454
|
]);
|
|
4746
5455
|
backgroundRef.current = refreshBackground;
|
|
4747
5456
|
const isWorking = backgroundRuns.some((run) => run.status === "running");
|
|
4748
|
-
(0,
|
|
5457
|
+
(0, import_react22.useEffect)(() => {
|
|
4749
5458
|
if (options.background !== true || options.threadId === void 0) {
|
|
4750
5459
|
return;
|
|
4751
5460
|
}
|
|
@@ -4753,9 +5462,10 @@ function useAgentChat(options) {
|
|
|
4753
5462
|
}, [
|
|
4754
5463
|
options.background,
|
|
4755
5464
|
options.threadId,
|
|
5465
|
+
chatId,
|
|
4756
5466
|
refreshBackground
|
|
4757
5467
|
]);
|
|
4758
|
-
(0,
|
|
5468
|
+
(0, import_react22.useEffect)(() => {
|
|
4759
5469
|
const every = latest.current.backgroundPollMs ?? 5e3;
|
|
4760
5470
|
if (latest.current.background !== true || !isWorking || every <= 0) {
|
|
4761
5471
|
return;
|
|
@@ -4766,66 +5476,19 @@ function useAgentChat(options) {
|
|
|
4766
5476
|
isWorking,
|
|
4767
5477
|
refreshBackground
|
|
4768
5478
|
]);
|
|
4769
|
-
const
|
|
4770
|
-
const list = await client.listThreads();
|
|
4771
|
-
setThreads(list);
|
|
4772
|
-
return list;
|
|
4773
|
-
}, [
|
|
4774
|
-
client
|
|
4775
|
-
]);
|
|
4776
|
-
const loadThread = (0, import_react19.useCallback)((id) => client.getThread(id), [
|
|
4777
|
-
client
|
|
4778
|
-
]);
|
|
4779
|
-
const deleteThread = (0, import_react19.useCallback)(async (id) => {
|
|
4780
|
-
await client.deleteThread(id);
|
|
4781
|
-
setThreads((current) => current.filter((thread) => thread.id !== id));
|
|
4782
|
-
}, [
|
|
4783
|
-
client
|
|
4784
|
-
]);
|
|
4785
|
-
const forkThread = (0, import_react19.useCallback)((threadId, messageId) => requireBackendMethod(client, "forkFromMessage")(threadId, messageId), [
|
|
4786
|
-
client
|
|
4787
|
-
]);
|
|
4788
|
-
const renameThread = (0, import_react19.useCallback)(async (id, title) => {
|
|
4789
|
-
await client.updateThread(id, {
|
|
4790
|
-
title
|
|
4791
|
-
});
|
|
4792
|
-
setThreads((current) => current.map((thread) => thread.id === id ? {
|
|
4793
|
-
...thread,
|
|
4794
|
-
title
|
|
4795
|
-
} : thread));
|
|
4796
|
-
}, [
|
|
4797
|
-
client
|
|
4798
|
-
]);
|
|
4799
|
-
const promoteThread = (0, import_react19.useCallback)(async (id) => {
|
|
4800
|
-
await requireBackendMethod(client, "promoteThread")(id);
|
|
4801
|
-
await loadThreads();
|
|
4802
|
-
}, [
|
|
4803
|
-
client,
|
|
4804
|
-
loadThreads
|
|
4805
|
-
]);
|
|
4806
|
-
const truncateFromMessage = (0, import_react19.useCallback)((threadId, messageId) => requireBackendMethod(client, "truncateFromMessage")(threadId, messageId).then(() => void 0), [
|
|
4807
|
-
client
|
|
4808
|
-
]);
|
|
4809
|
-
const loadQuota = (0, import_react19.useCallback)(async () => {
|
|
4810
|
-
const today = await requireBackendMethod(client, "getQuotaToday")();
|
|
4811
|
-
setQuota(today);
|
|
4812
|
-
return today;
|
|
4813
|
-
}, [
|
|
4814
|
-
client
|
|
4815
|
-
]);
|
|
4816
|
-
const cancel = (0, import_react19.useCallback)(async () => {
|
|
5479
|
+
const cancel = (0, import_react22.useCallback)(async () => {
|
|
4817
5480
|
chatRef.current.stop();
|
|
4818
|
-
const
|
|
4819
|
-
if (
|
|
5481
|
+
const active = runIdRef.current;
|
|
5482
|
+
if (active) {
|
|
4820
5483
|
try {
|
|
4821
|
-
await client.cancelStream(
|
|
5484
|
+
await client.cancelStream(active);
|
|
4822
5485
|
} catch {
|
|
4823
5486
|
}
|
|
4824
5487
|
}
|
|
4825
5488
|
}, [
|
|
4826
5489
|
client
|
|
4827
5490
|
]);
|
|
4828
|
-
const approve = (0,
|
|
5491
|
+
const approve = (0, import_react22.useCallback)(async ({ toolCallId, remember, via }) => {
|
|
4829
5492
|
await requireBackendMethod(client, "approveToolCall")({
|
|
4830
5493
|
toolCallId,
|
|
4831
5494
|
...remember === true ? {
|
|
@@ -4838,7 +5501,7 @@ function useAgentChat(options) {
|
|
|
4838
5501
|
}, [
|
|
4839
5502
|
client
|
|
4840
5503
|
]);
|
|
4841
|
-
const reject = (0,
|
|
5504
|
+
const reject = (0, import_react22.useCallback)(async ({ toolCallId, reason, via }) => {
|
|
4842
5505
|
await requireBackendMethod(client, "rejectToolCall")({
|
|
4843
5506
|
toolCallId,
|
|
4844
5507
|
...reason !== void 0 ? {
|
|
@@ -4851,7 +5514,7 @@ function useAgentChat(options) {
|
|
|
4851
5514
|
}, [
|
|
4852
5515
|
client
|
|
4853
5516
|
]);
|
|
4854
|
-
const answer = (0,
|
|
5517
|
+
const answer = (0, import_react22.useCallback)(async ({ toolCallId, answers }) => {
|
|
4855
5518
|
await requireBackendMethod(client, "answerToolCall")({
|
|
4856
5519
|
toolCallId,
|
|
4857
5520
|
...answers !== void 0 ? {
|
|
@@ -4861,16 +5524,16 @@ function useAgentChat(options) {
|
|
|
4861
5524
|
}, [
|
|
4862
5525
|
client
|
|
4863
5526
|
]);
|
|
4864
|
-
const skip = (0,
|
|
5527
|
+
const skip = (0, import_react22.useCallback)(async ({ toolCallId }) => {
|
|
4865
5528
|
await requireBackendMethod(client, "skipToolCall")({
|
|
4866
5529
|
toolCallId
|
|
4867
5530
|
});
|
|
4868
5531
|
}, [
|
|
4869
5532
|
client
|
|
4870
5533
|
]);
|
|
4871
|
-
const regenerate = (0,
|
|
4872
|
-
const
|
|
4873
|
-
if (
|
|
5534
|
+
const regenerate = (0, import_react22.useCallback)((_input) => {
|
|
5535
|
+
const block = blockedRef.current;
|
|
5536
|
+
if (block != null) throw new QuotaBlockedError(block);
|
|
4874
5537
|
if (isTurnInFlight()) return;
|
|
4875
5538
|
regenerateNext.current = true;
|
|
4876
5539
|
turnInFlight.current = true;
|
|
@@ -4880,15 +5543,78 @@ function useAgentChat(options) {
|
|
|
4880
5543
|
}, [
|
|
4881
5544
|
isTurnInFlight
|
|
4882
5545
|
]);
|
|
4883
|
-
const
|
|
4884
|
-
|
|
4885
|
-
|
|
4886
|
-
|
|
4887
|
-
|
|
4888
|
-
|
|
4889
|
-
|
|
5546
|
+
const storedIdOf = (0, import_react22.useCallback)(async (messageId, threadId) => {
|
|
5547
|
+
const message = chatRef.current.messages.find((candidate) => candidate.id === messageId);
|
|
5548
|
+
const runOf = message?.metadata?.runId;
|
|
5549
|
+
if (runOf === void 0) return messageId;
|
|
5550
|
+
const thread = await client.getThread(threadId);
|
|
5551
|
+
const row = [
|
|
5552
|
+
...thread.messages
|
|
5553
|
+
].reverse().find((candidate) => candidate.role === "assistant" && candidate.runId === runOf);
|
|
5554
|
+
return row?.id ?? messageId;
|
|
5555
|
+
}, [
|
|
5556
|
+
client
|
|
5557
|
+
]);
|
|
5558
|
+
const fork = (0, import_react22.useCallback)(async ({ messageId, threadId }) => {
|
|
5559
|
+
const source = threadId ?? currentThreadId();
|
|
5560
|
+
if (source === void 0) throw new Error("fork: this chat has no thread yet");
|
|
5561
|
+
const stored = await storedIdOf(messageId, source);
|
|
5562
|
+
const forked = await requireBackendMethod(client, "forkFromMessage")(source, stored);
|
|
5563
|
+
notifyThreads(client, {
|
|
5564
|
+
type: "changed"
|
|
5565
|
+
});
|
|
5566
|
+
latest.current.onThreadCreated?.(forked.id);
|
|
5567
|
+
return forked;
|
|
5568
|
+
}, [
|
|
5569
|
+
client,
|
|
5570
|
+
currentThreadId,
|
|
5571
|
+
storedIdOf
|
|
5572
|
+
]);
|
|
5573
|
+
const truncateFrom = (0, import_react22.useCallback)(async ({ messageId, threadId }) => {
|
|
5574
|
+
const target = threadId ?? currentThreadId();
|
|
5575
|
+
if (target === void 0) throw new Error("truncateFrom: this chat has no thread yet");
|
|
5576
|
+
const stored = await storedIdOf(messageId, target);
|
|
5577
|
+
await requireBackendMethod(client, "truncateFromMessage")(target, stored);
|
|
5578
|
+
}, [
|
|
5579
|
+
client,
|
|
5580
|
+
currentThreadId,
|
|
5581
|
+
storedIdOf
|
|
5582
|
+
]);
|
|
5583
|
+
const promote = (0, import_react22.useCallback)(async ({ threadId } = {}) => {
|
|
5584
|
+
const target = threadId ?? currentThreadId();
|
|
5585
|
+
if (target === void 0) throw new Error("promote: this chat has no thread yet");
|
|
5586
|
+
await requireBackendMethod(client, "promoteThread")(target);
|
|
5587
|
+
notifyThreads(client, {
|
|
5588
|
+
type: "changed"
|
|
5589
|
+
});
|
|
5590
|
+
}, [
|
|
5591
|
+
client,
|
|
5592
|
+
currentThreadId
|
|
5593
|
+
]);
|
|
5594
|
+
const [modelsWanted, setModelsWanted] = (0, import_react22.useState)(false);
|
|
5595
|
+
const modelsWantedRef = (0, import_react22.useRef)(modelsWanted);
|
|
5596
|
+
modelsWantedRef.current = modelsWanted;
|
|
5597
|
+
const catalog = useModels({
|
|
5598
|
+
backend: client,
|
|
5599
|
+
...options.agent !== void 0 ? {
|
|
5600
|
+
agent: options.agent
|
|
5601
|
+
} : {},
|
|
5602
|
+
enabled: modelsWanted && typeof client.listModels === "function"
|
|
5603
|
+
});
|
|
5604
|
+
const wantModels = (0, import_react22.useCallback)(() => {
|
|
5605
|
+
if (modelsWantedRef.current) return;
|
|
5606
|
+
modelsWantedRef.current = true;
|
|
5607
|
+
queueMicrotask(() => setModelsWanted(true));
|
|
5608
|
+
}, []);
|
|
5609
|
+
const selectModel = (0, import_react22.useCallback)((id) => setPickedModel(id), []);
|
|
5610
|
+
const pinToThread = (0, import_react22.useCallback)(async (model) => {
|
|
5611
|
+
const threadId = currentThreadId();
|
|
5612
|
+
setThreadModel(model);
|
|
4890
5613
|
if (threadId === void 0) {
|
|
4891
|
-
|
|
5614
|
+
pendingPin.current = {
|
|
5615
|
+
model
|
|
5616
|
+
};
|
|
5617
|
+
return;
|
|
4892
5618
|
}
|
|
4893
5619
|
await client.updateThread(threadId, {
|
|
4894
5620
|
model
|
|
@@ -4897,10 +5623,99 @@ function useAgentChat(options) {
|
|
|
4897
5623
|
type: "changed"
|
|
4898
5624
|
});
|
|
4899
5625
|
}, [
|
|
4900
|
-
client
|
|
5626
|
+
client,
|
|
5627
|
+
currentThreadId
|
|
4901
5628
|
]);
|
|
4902
|
-
const
|
|
5629
|
+
const models = {
|
|
5630
|
+
get list() {
|
|
5631
|
+
wantModels();
|
|
5632
|
+
return catalog.models;
|
|
5633
|
+
},
|
|
5634
|
+
get providers() {
|
|
5635
|
+
wantModels();
|
|
5636
|
+
return catalog.providers;
|
|
5637
|
+
},
|
|
5638
|
+
selected: options.model ?? pickedModel ?? threadModel ?? catalog.defaultModel ?? null,
|
|
5639
|
+
select: selectModel,
|
|
5640
|
+
pinToThread,
|
|
5641
|
+
isLoading: modelsWanted && catalog.isLoading,
|
|
5642
|
+
error: catalog.error
|
|
5643
|
+
};
|
|
4903
5644
|
const status = connection.status === "reconnecting" ? "reconnecting" : chat.status;
|
|
5645
|
+
const isBusy = status === "submitted" || status === "streaming" || status === "reconnecting";
|
|
5646
|
+
const files = useAttachments({
|
|
5647
|
+
...options.composer,
|
|
5648
|
+
backend: client
|
|
5649
|
+
});
|
|
5650
|
+
const [text, setText] = (0, import_react22.useState)("");
|
|
5651
|
+
const blockedBy = blocked != null ? "quota" : files.isUploading ? "uploading" : isBusy ? "busy" : text.trim().length === 0 && files.attachments.length === 0 ? "empty" : null;
|
|
5652
|
+
const composerRef = (0, import_react22.useRef)({
|
|
5653
|
+
text,
|
|
5654
|
+
files,
|
|
5655
|
+
blockedBy
|
|
5656
|
+
});
|
|
5657
|
+
composerRef.current = {
|
|
5658
|
+
text,
|
|
5659
|
+
files,
|
|
5660
|
+
blockedBy
|
|
5661
|
+
};
|
|
5662
|
+
const submit = (0, import_react22.useCallback)(async () => {
|
|
5663
|
+
const current = composerRef.current;
|
|
5664
|
+
if (current.blockedBy !== null) return;
|
|
5665
|
+
const refs = current.files.refs;
|
|
5666
|
+
const draft = current.text.trim();
|
|
5667
|
+
setText("");
|
|
5668
|
+
current.files.clear();
|
|
5669
|
+
await sendMessage({
|
|
5670
|
+
text: draft
|
|
5671
|
+
}, refs.length > 0 ? {
|
|
5672
|
+
body: {
|
|
5673
|
+
attachments: refs
|
|
5674
|
+
}
|
|
5675
|
+
} : void 0);
|
|
5676
|
+
}, [
|
|
5677
|
+
sendMessage
|
|
5678
|
+
]);
|
|
5679
|
+
const composer = {
|
|
5680
|
+
text,
|
|
5681
|
+
setText,
|
|
5682
|
+
files,
|
|
5683
|
+
canSend: blockedBy === null,
|
|
5684
|
+
blockedBy,
|
|
5685
|
+
submit
|
|
5686
|
+
};
|
|
5687
|
+
const ownCatalog = options.transcript?.toolCatalog;
|
|
5688
|
+
const tools = useToolCatalog({
|
|
5689
|
+
backend: client,
|
|
5690
|
+
...options.agent !== void 0 ? {
|
|
5691
|
+
agent: options.agent
|
|
5692
|
+
} : {},
|
|
5693
|
+
enabled: ownCatalog === void 0 && typeof client.listTools === "function"
|
|
5694
|
+
});
|
|
5695
|
+
const canFork = typeof client.forkFromMessage === "function";
|
|
5696
|
+
const transcript = useChatTranscript({
|
|
5697
|
+
messages: chat.messages,
|
|
5698
|
+
status,
|
|
5699
|
+
onStop: cancel,
|
|
5700
|
+
onApprove: approve,
|
|
5701
|
+
onReject: reject,
|
|
5702
|
+
onAnswer: answer,
|
|
5703
|
+
onSkip: skip,
|
|
5704
|
+
regeneratable: true,
|
|
5705
|
+
onRegenerate: regenerate,
|
|
5706
|
+
...canFork ? {
|
|
5707
|
+
onFork: /* @__PURE__ */ __name((input) => fork(input).then(() => void 0), "onFork")
|
|
5708
|
+
} : {},
|
|
5709
|
+
...ownCatalog === void 0 ? {
|
|
5710
|
+
toolCatalog: tools.catalog
|
|
5711
|
+
} : {},
|
|
5712
|
+
...options.transcript
|
|
5713
|
+
});
|
|
5714
|
+
const background = {
|
|
5715
|
+
runs: backgroundRuns,
|
|
5716
|
+
isWorking,
|
|
5717
|
+
refresh: refreshBackground
|
|
5718
|
+
};
|
|
4904
5719
|
return {
|
|
4905
5720
|
...chat,
|
|
4906
5721
|
status,
|
|
@@ -4911,34 +5726,38 @@ function useAgentChat(options) {
|
|
|
4911
5726
|
/** Sub-agents this conversation started and did not wait for. */
|
|
4912
5727
|
background,
|
|
4913
5728
|
runId,
|
|
4914
|
-
/** The
|
|
5729
|
+
/** The loaded thread's running turn, or `null` once read with none. */
|
|
4915
5730
|
activeRunId,
|
|
5731
|
+
/** The thread's history is being read. */
|
|
5732
|
+
isLoadingHistory,
|
|
5733
|
+
/** Reading the thread's history failed. */
|
|
5734
|
+
historyError,
|
|
4916
5735
|
/**
|
|
4917
5736
|
* The thread this chat is on right now: the `threadId` option, else the one the backend created
|
|
4918
5737
|
* on the first send. A getter, because the created id is learned mid-stream.
|
|
4919
5738
|
*/
|
|
4920
|
-
getThreadId,
|
|
4921
|
-
|
|
4922
|
-
/** The backend this chat talks to — pass it to `useThreads`, `useMessageFeedback`, … */
|
|
5739
|
+
getThreadId: currentThreadId,
|
|
5740
|
+
/** The backend this chat talks to — the same one every other hook under the provider uses. */
|
|
4923
5741
|
backend: client,
|
|
4924
|
-
/**
|
|
4925
|
-
|
|
4926
|
-
|
|
4927
|
-
|
|
4928
|
-
|
|
4929
|
-
|
|
4930
|
-
|
|
4931
|
-
renameThread,
|
|
4932
|
-
promoteThread,
|
|
4933
|
-
truncateFromMessage,
|
|
5742
|
+
/** The transcript model, with every action already bound to this chat. */
|
|
5743
|
+
transcript,
|
|
5744
|
+
/** A headless composer: draft, files, send gate, `submit()`. */
|
|
5745
|
+
composer,
|
|
5746
|
+
/** The model picker: `list`, `selected`, `select(id)`, `pinToThread(id)`. */
|
|
5747
|
+
models,
|
|
5748
|
+
/** The caller's budget (`GET <base>/quota`); `quota.blocked` gates sends. */
|
|
4934
5749
|
quota,
|
|
4935
|
-
|
|
5750
|
+
/** The window blocking sends right now (the `blocked` option, else the quota report's). */
|
|
5751
|
+
blocked,
|
|
4936
5752
|
cancel,
|
|
4937
5753
|
approve,
|
|
4938
5754
|
reject,
|
|
4939
5755
|
answer,
|
|
4940
5756
|
skip,
|
|
4941
|
-
regenerate
|
|
5757
|
+
regenerate,
|
|
5758
|
+
fork,
|
|
5759
|
+
truncateFrom,
|
|
5760
|
+
promote
|
|
4942
5761
|
};
|
|
4943
5762
|
}
|
|
4944
5763
|
__name(useAgentChat, "useAgentChat");
|
|
@@ -4952,20 +5771,13 @@ var QuotaBlockedError = class extends Error {
|
|
|
4952
5771
|
this.name = "QuotaBlockedError";
|
|
4953
5772
|
}
|
|
4954
5773
|
};
|
|
4955
|
-
async function mergeHeaders(options) {
|
|
4956
|
-
const dynamic = await options.getHeaders?.() ?? {};
|
|
4957
|
-
return {
|
|
4958
|
-
...options.headers,
|
|
4959
|
-
...dynamic
|
|
4960
|
-
};
|
|
4961
|
-
}
|
|
4962
|
-
__name(mergeHeaders, "mergeHeaders");
|
|
4963
5774
|
// Annotate the CommonJS export names for ESM import in node:
|
|
4964
5775
|
0 && (module.exports = {
|
|
4965
5776
|
AgentBackendUnsupportedError,
|
|
4966
5777
|
AgentChatTransport,
|
|
4967
5778
|
AgentClient,
|
|
4968
5779
|
AgentHttpError,
|
|
5780
|
+
AgentProvider,
|
|
4969
5781
|
AmbientRenderUiContext,
|
|
4970
5782
|
ChatInput,
|
|
4971
5783
|
DEFAULT_SPEECH_LANG,
|
|
@@ -5011,6 +5823,7 @@ __name(mergeHeaders, "mergeHeaders");
|
|
|
5011
5823
|
storedThreadToUiMessages,
|
|
5012
5824
|
toolCallState,
|
|
5013
5825
|
toolCatalogFrom,
|
|
5826
|
+
useAgentBackend,
|
|
5014
5827
|
useAgentChat,
|
|
5015
5828
|
useAgents,
|
|
5016
5829
|
useAmbientRenderUi,
|