@dudousxd/nestjs-agent-react 0.20.0 → 0.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -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 /agent/chat` → the turn's SSE stream. Throws {@link AgentHttpError} on a non-2xx. */
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.baseUrl()}/agent/chat`, {
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", "/agent/chat", response.statusText);
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 /agent/chat/:runId/stream[?after=<seq>]` → the run's SSE stream, or `null` when nothing is
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 = `/agent/chat/${encodeURIComponent(request.runId)}/stream`;
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.baseUrl()}${path}${query}`, {
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, response.statusText);
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", `/agent/messages/${encodeURIComponent(messageId)}/feedback`, input);
187
+ return this.request("POST", `/messages/${encodeURIComponent(messageId)}/feedback`, input);
181
188
  }
182
189
  listThreads() {
183
- return this.request("GET", "/agent/threads");
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", `/agent/skills${query}`);
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,42 @@ var AgentClient = class {
199
206
  */
200
207
  listTools(agent) {
201
208
  const query = agent === void 0 ? "" : `?agent=${encodeURIComponent(agent)}`;
202
- return this.request("GET", `/agent/tools${query}`);
209
+ return this.request("GET", `/tools${query}`);
203
210
  }
204
211
  getThread(id) {
205
- return this.request("GET", `/agent/threads/${encodeURIComponent(id)}`);
212
+ return this.request("GET", `/threads/${encodeURIComponent(id)}`);
206
213
  }
207
214
  deleteThread(id) {
208
- return this.request("DELETE", `/agent/threads/${encodeURIComponent(id)}`);
215
+ return this.request("DELETE", `/threads/${encodeURIComponent(id)}`);
209
216
  }
210
217
  forkFromMessage(threadId, messageId) {
211
- return this.request("POST", `/agent/threads/${encodeURIComponent(threadId)}/fork-from/${encodeURIComponent(messageId)}`);
218
+ return this.request("POST", `/threads/${encodeURIComponent(threadId)}/fork-from/${encodeURIComponent(messageId)}`);
212
219
  }
213
220
  renameThread(id, title) {
214
221
  return this.updateThread(id, {
215
222
  title
216
223
  });
217
224
  }
218
- /** General `PATCH /agent/threads/:threadId` — title and/or the thread's pinned default agent. */
225
+ /** General `PATCH <path>/threads/:threadId` — title and/or the thread's pinned default agent. */
219
226
  updateThread(id, patch) {
220
- return this.request("PATCH", `/agent/threads/${encodeURIComponent(id)}`, patch);
227
+ return this.request("PATCH", `/threads/${encodeURIComponent(id)}`, patch);
221
228
  }
222
229
  /**
223
230
  * Uploads a file (image/PDF) for a vision-capable model turn. Multipart, field name `file` —
224
- * mirrors the backend's `POST /agent/attachments`. The returned {@link MessageAttachment} is
231
+ * mirrors the backend's `POST <path>/attachments`. The returned {@link MessageAttachment} is
225
232
  * what a caller then rides on `sendMessage({ text }, { body: { attachments: [...] } })`.
226
233
  */
227
234
  async uploadAttachment(file, options = {}) {
228
- if (this.options.attachments !== void 0) {
229
- return this.options.attachments(file, options, this.connection());
235
+ const upload = this.options.attachments?.upload;
236
+ if (upload !== void 0) {
237
+ return upload(file, options, this.connection());
230
238
  }
231
239
  if (options.onProgress !== void 0 && this.options.fetch === void 0 && typeof XMLHttpRequest !== "undefined") {
232
240
  return this.uploadWithProgress(file, options);
233
241
  }
234
242
  const formData = new FormData();
235
243
  formData.append("file", file);
236
- const response = await this.fetchImpl()(`${this.baseUrl()}/agent/attachments`, {
244
+ const response = await this.fetchImpl()(`${this.root()}/attachments`, {
237
245
  method: "POST",
238
246
  headers: {
239
247
  accept: "application/json",
@@ -245,7 +253,7 @@ var AgentClient = class {
245
253
  signal: options.signal
246
254
  } : {}
247
255
  });
248
- const attachment = await this.handleResponse(response, "POST", "/agent/attachments");
256
+ const attachment = await this.handleResponse(response, "POST", `${this.agentPath()}/attachments`);
249
257
  options.onProgress?.(1);
250
258
  return attachment;
251
259
  }
@@ -254,7 +262,7 @@ var AgentClient = class {
254
262
  accept: "application/json",
255
263
  ...await this.resolveHeaders()
256
264
  };
257
- const url = `${this.baseUrl()}/agent/attachments`;
265
+ const url = `${this.root()}/attachments`;
258
266
  return new Promise((resolve, reject) => {
259
267
  const xhr = new XMLHttpRequest();
260
268
  xhr.open("POST", url);
@@ -265,7 +273,7 @@ var AgentClient = class {
265
273
  };
266
274
  xhr.onload = () => {
267
275
  if (xhr.status < 200 || xhr.status >= 300) {
268
- reject(new AgentHttpError(xhr.status, "POST", "/agent/attachments", xhr.statusText));
276
+ reject(new AgentHttpError(xhr.status, "POST", `${this.agentPath()}/attachments`, xhr.statusText));
269
277
  return;
270
278
  }
271
279
  onProgress?.(1);
@@ -288,39 +296,39 @@ var AgentClient = class {
288
296
  });
289
297
  }
290
298
  promoteThread(id) {
291
- return this.request("POST", `/agent/threads/${encodeURIComponent(id)}/promote`);
299
+ return this.request("POST", `/threads/${encodeURIComponent(id)}/promote`);
292
300
  }
293
301
  truncateFromMessage(threadId, messageId) {
294
- return this.request("DELETE", `/agent/threads/${encodeURIComponent(threadId)}/from/${encodeURIComponent(messageId)}`);
302
+ return this.request("DELETE", `/threads/${encodeURIComponent(threadId)}/from/${encodeURIComponent(messageId)}`);
295
303
  }
296
- /** `GET /agent/models?agent=` — the models this caller may pick, grouped by provider. */
304
+ /** `GET <path>/models?agent=` — the models this caller may pick, grouped by provider. */
297
305
  listModels(agent) {
298
306
  const query = agent === void 0 ? "" : `?agent=${encodeURIComponent(agent)}`;
299
- return this.request("GET", `/agent/models${query}`);
307
+ return this.request("GET", `/models${query}`);
300
308
  }
301
- /** `GET /agent/agents` — the registered agents, the default one flagged. */
309
+ /** `GET <path>/agents` — the registered agents, the default one flagged. */
302
310
  listAgents() {
303
- return this.request("GET", "/agent/agents");
311
+ return this.request("GET", "/agents");
304
312
  }
305
- /** `GET /agent/quota` — the caller's budget windows and the one blocking sends, if any. */
313
+ /** `GET <path>/quota` — the caller's budget windows and the one blocking sends, if any. */
306
314
  getQuota() {
307
- return this.request("GET", "/agent/quota");
315
+ return this.request("GET", "/quota");
308
316
  }
309
317
  getQuotaToday() {
310
- return this.request("GET", "/agent/quota/today");
318
+ return this.request("GET", "/quota/today");
311
319
  }
312
320
  cancelStream(runId) {
313
- return this.request("POST", `/agent/chat/${encodeURIComponent(runId)}/cancel`);
321
+ return this.request("POST", `/chat/${encodeURIComponent(runId)}/cancel`);
314
322
  }
315
323
  /**
316
324
  * `remember` approves later calls of the same tool in the same thread; `via` names the surface
317
325
  * the decision came through (the server records `'web'` when omitted).
318
326
  */
319
327
  approveToolCall(input) {
320
- return this.request("POST", "/agent/tool-call/approve", input);
328
+ return this.request("POST", "/tool-call/approve", input);
321
329
  }
322
330
  rejectToolCall(input) {
323
- return this.request("POST", "/agent/tool-call/reject", input);
331
+ return this.request("POST", "/tool-call/reject", input);
324
332
  }
325
333
  /**
326
334
  * Settle a parked question set. `answers` is questionId → chosen option values; a question left
@@ -329,7 +337,7 @@ var AgentClient = class {
329
337
  * answer — which is the point of the surface, so it is a valid submission rather than a blank.
330
338
  */
331
339
  answerToolCall(input) {
332
- return this.request("POST", "/agent/tool-call/answer", input);
340
+ return this.request("POST", "/tool-call/answer", input);
333
341
  }
334
342
  /**
335
343
  * Decline to answer and let the agent proceed on its own pre-picked values. Lands on the same
@@ -337,7 +345,7 @@ var AgentClient = class {
337
345
  * evidence the user chose them.
338
346
  */
339
347
  skipToolCall(input) {
340
- return this.request("POST", "/agent/tool-call/skip", input);
348
+ return this.request("POST", "/tool-call/skip", input);
341
349
  }
342
350
  fetchImpl() {
343
351
  return this.options.fetch ?? globalThis.fetch;
@@ -346,13 +354,21 @@ var AgentClient = class {
346
354
  connection() {
347
355
  return {
348
356
  baseUrl: this.baseUrl(),
357
+ path: this.agentPath(),
349
358
  headers: /* @__PURE__ */ __name(() => this.resolveHeaders(), "headers"),
350
359
  fetch: this.fetchImpl(),
351
360
  ...this.credentials()
352
361
  };
353
362
  }
354
363
  baseUrl() {
355
- return (this.options.baseUrl ?? "").replace(/\/$/, "");
364
+ return (this.options.baseUrl ?? "").replace(/\/+$/, "");
365
+ }
366
+ agentPath() {
367
+ return normalizeAgentPath(this.options.path);
368
+ }
369
+ /** Origin + agent path: what every route hangs off. */
370
+ root() {
371
+ return `${this.baseUrl()}${this.agentPath()}`;
356
372
  }
357
373
  async resolveHeaders() {
358
374
  const dynamic = await this.options.getHeaders?.() ?? {};
@@ -366,7 +382,8 @@ var AgentClient = class {
366
382
  credentials: this.options.credentials
367
383
  } : {};
368
384
  }
369
- async request(method, path, body) {
385
+ async request(method, route, body) {
386
+ const path = `${this.agentPath()}${route}`;
370
387
  const response = await this.fetchImpl()(`${this.baseUrl()}${path}`, {
371
388
  method,
372
389
  headers: {
@@ -497,6 +514,9 @@ var AgentChatTransport = class {
497
514
  ...options.baseUrl !== void 0 ? {
498
515
  baseUrl: options.baseUrl
499
516
  } : {},
517
+ ...options.path !== void 0 ? {
518
+ path: options.path
519
+ } : {},
500
520
  ...options.headers !== void 0 ? {
501
521
  headers: options.headers
502
522
  } : {},
@@ -1202,7 +1222,7 @@ function dragHasFiles(data) {
1202
1222
  __name(dragHasFiles, "dragHasFiles");
1203
1223
 
1204
1224
  // src/attachments/use-attachments.ts
1205
- var import_react2 = require("react");
1225
+ var import_react6 = require("react");
1206
1226
 
1207
1227
  // src/backend.ts
1208
1228
  var AgentBackendUnsupportedError = class extends Error {
@@ -1224,6 +1244,570 @@ function requireBackendMethod(backend, name) {
1224
1244
  }
1225
1245
  __name(requireBackendMethod, "requireBackendMethod");
1226
1246
 
1247
+ // src/provider.tsx
1248
+ var import_react5 = require("react");
1249
+
1250
+ // src/components/ambient-ui.ts
1251
+ var import_react2 = require("react");
1252
+ function sharedContext(key) {
1253
+ const symbol = Symbol.for(key);
1254
+ const holder = globalThis;
1255
+ const existing = holder[symbol];
1256
+ if (existing !== void 0) return existing;
1257
+ const created = (0, import_react2.createContext)(null);
1258
+ holder[symbol] = created;
1259
+ return created;
1260
+ }
1261
+ __name(sharedContext, "sharedContext");
1262
+ var AmbientRenderUiContext = sharedContext("@dudousxd/nestjs-agent-react:ambient-render-ui");
1263
+ function useAmbientRenderUi() {
1264
+ return (0, import_react2.useContext)(AmbientRenderUiContext);
1265
+ }
1266
+ __name(useAmbientRenderUi, "useAmbientRenderUi");
1267
+
1268
+ // src/genui/generative-ui.tsx
1269
+ var import_react4 = require("react");
1270
+
1271
+ // src/genui/use-generative-ui.ts
1272
+ var import_react3 = require("react");
1273
+
1274
+ // src/genui/types.ts
1275
+ var GENUI_TREE_COMPONENT = "genui:tree";
1276
+
1277
+ // src/genui/use-generative-ui.ts
1278
+ function isRecord(value) {
1279
+ return typeof value === "object" && value !== null && !Array.isArray(value);
1280
+ }
1281
+ __name(isRecord, "isRecord");
1282
+ function toGenerativeUIItem(part) {
1283
+ if (!isRecord(part)) return null;
1284
+ const source = part.type === "data-ui" && isRecord(part.data) ? part.data : part;
1285
+ if (typeof source.component !== "string") return null;
1286
+ const id = typeof source.id === "string" ? source.id : typeof part.id === "string" ? part.id : null;
1287
+ if (id === null) return null;
1288
+ return {
1289
+ id,
1290
+ component: source.component,
1291
+ props: isRecord(source.props) ? source.props : {},
1292
+ version: typeof source.version === "number" ? source.version : null,
1293
+ toolCallId: typeof source.toolCallId === "string" ? source.toolCallId : null
1294
+ };
1295
+ }
1296
+ __name(toGenerativeUIItem, "toGenerativeUIItem");
1297
+ var resolverCaches = /* @__PURE__ */ new WeakMap();
1298
+ function resolveCached(resolve, name, version) {
1299
+ let cache = resolverCaches.get(resolve);
1300
+ if (cache === void 0) {
1301
+ cache = /* @__PURE__ */ new Map();
1302
+ resolverCaches.set(resolve, cache);
1303
+ }
1304
+ const key = `${name}@${version ?? ""}`;
1305
+ const hit = cache.get(key);
1306
+ if (hit !== void 0) return hit;
1307
+ let entry;
1308
+ try {
1309
+ const result = resolve(name, version);
1310
+ if (result instanceof Promise) {
1311
+ entry = {
1312
+ resolution: {
1313
+ status: "loading"
1314
+ },
1315
+ settled: null
1316
+ };
1317
+ entry.settled = result.then((Component2) => {
1318
+ entry.resolution = Component2 ? {
1319
+ status: "ready",
1320
+ Component: Component2
1321
+ } : {
1322
+ status: "unknown"
1323
+ };
1324
+ }, (error) => {
1325
+ entry.resolution = {
1326
+ status: "error",
1327
+ error
1328
+ };
1329
+ });
1330
+ } else {
1331
+ entry = {
1332
+ resolution: result ? {
1333
+ status: "ready",
1334
+ Component: result
1335
+ } : {
1336
+ status: "unknown"
1337
+ },
1338
+ settled: null
1339
+ };
1340
+ }
1341
+ } catch (error) {
1342
+ entry = {
1343
+ resolution: {
1344
+ status: "error",
1345
+ error
1346
+ },
1347
+ settled: null
1348
+ };
1349
+ }
1350
+ cache.set(key, entry);
1351
+ return entry;
1352
+ }
1353
+ __name(resolveCached, "resolveCached");
1354
+ function useResolvedComponent(name, version, registry, resolve, fallbackTree) {
1355
+ const [, setTick] = (0, import_react3.useState)(0);
1356
+ const own = registry[name];
1357
+ const entry = own !== void 0 || resolve === void 0 ? null : resolveCached(resolve, name, version);
1358
+ const pending = entry?.resolution.status === "loading" ? entry.settled : null;
1359
+ (0, import_react3.useEffect)(() => {
1360
+ if (pending === null) return;
1361
+ let live = true;
1362
+ void pending.then(() => {
1363
+ if (live) setTick((tick) => tick + 1);
1364
+ });
1365
+ return () => {
1366
+ live = false;
1367
+ };
1368
+ }, [
1369
+ pending
1370
+ ]);
1371
+ if (own !== void 0) return {
1372
+ status: "ready",
1373
+ Component: own
1374
+ };
1375
+ if (entry !== null && entry.resolution.status !== "unknown") return entry.resolution;
1376
+ if (name === GENUI_TREE_COMPONENT && fallbackTree !== void 0) {
1377
+ return {
1378
+ status: "ready",
1379
+ Component: fallbackTree
1380
+ };
1381
+ }
1382
+ return {
1383
+ status: "unknown"
1384
+ };
1385
+ }
1386
+ __name(useResolvedComponent, "useResolvedComponent");
1387
+ function useValidatedProps(catalog, name, props) {
1388
+ const checked = catalog?.has(name) === true;
1389
+ const immediate = (0, import_react3.useMemo)(() => {
1390
+ if (!checked || catalog === void 0) return {
1391
+ status: "ok",
1392
+ props
1393
+ };
1394
+ const result = catalog.validateSync?.(name, props);
1395
+ if (result === void 0) return null;
1396
+ return result.ok ? {
1397
+ status: "ok",
1398
+ props: result.value
1399
+ } : {
1400
+ status: "invalid",
1401
+ issues: result.issues
1402
+ };
1403
+ }, [
1404
+ checked,
1405
+ catalog,
1406
+ name,
1407
+ props
1408
+ ]);
1409
+ const [late, setLate] = (0, import_react3.useState)(null);
1410
+ (0, import_react3.useEffect)(() => {
1411
+ if (immediate !== null || catalog === void 0) return;
1412
+ let live = true;
1413
+ catalog.validate(name, props).then((result) => {
1414
+ if (!live) return;
1415
+ setLate({
1416
+ props,
1417
+ result: result.ok ? {
1418
+ status: "ok",
1419
+ props: result.value
1420
+ } : {
1421
+ status: "invalid",
1422
+ issues: result.issues
1423
+ }
1424
+ });
1425
+ }, (error) => {
1426
+ if (!live) return;
1427
+ setLate({
1428
+ props,
1429
+ result: {
1430
+ status: "invalid",
1431
+ issues: [
1432
+ {
1433
+ path: [],
1434
+ message: error instanceof Error ? error.message : String(error)
1435
+ }
1436
+ ]
1437
+ }
1438
+ });
1439
+ });
1440
+ return () => {
1441
+ live = false;
1442
+ };
1443
+ }, [
1444
+ immediate,
1445
+ catalog,
1446
+ name,
1447
+ props
1448
+ ]);
1449
+ if (immediate !== null) return immediate;
1450
+ return late !== null && late.props === props ? late.result : {
1451
+ status: "pending"
1452
+ };
1453
+ }
1454
+ __name(useValidatedProps, "useValidatedProps");
1455
+ function useGenerativeUIState(part, options, fallbackTree) {
1456
+ const item = (0, import_react3.useMemo)(() => toGenerativeUIItem(part), [
1457
+ part
1458
+ ]);
1459
+ const name = item?.component ?? "";
1460
+ const resolution = useResolvedComponent(name, item?.version ?? null, options.registry, item === null ? void 0 : options.resolveComponent, fallbackTree);
1461
+ const empty = (0, import_react3.useMemo)(() => ({}), []);
1462
+ const validation = useValidatedProps(item === null || name === GENUI_TREE_COMPONENT ? void 0 : options.catalog, name, item?.props ?? empty);
1463
+ if (item === null) return null;
1464
+ if (resolution.status === "loading") return {
1465
+ status: "loading",
1466
+ item
1467
+ };
1468
+ if (resolution.status === "unknown") return {
1469
+ status: "problem",
1470
+ reason: "unknown",
1471
+ item
1472
+ };
1473
+ if (resolution.status === "error") {
1474
+ return {
1475
+ status: "problem",
1476
+ reason: "error",
1477
+ item,
1478
+ error: resolution.error
1479
+ };
1480
+ }
1481
+ if (validation.status === "pending") return {
1482
+ status: "loading",
1483
+ item
1484
+ };
1485
+ if (validation.status === "invalid") {
1486
+ return {
1487
+ status: "problem",
1488
+ reason: "invalid",
1489
+ item,
1490
+ issues: validation.issues
1491
+ };
1492
+ }
1493
+ return {
1494
+ status: "ready",
1495
+ item,
1496
+ Component: resolution.Component,
1497
+ props: validation.props
1498
+ };
1499
+ }
1500
+ __name(useGenerativeUIState, "useGenerativeUIState");
1501
+
1502
+ // src/genui/generative-ui.tsx
1503
+ var TreeScopeContext = /* @__PURE__ */ (0, import_react4.createContext)(null);
1504
+ function renderFallback(fallback2, problem) {
1505
+ if (typeof fallback2 === "function") return fallback2(problem);
1506
+ return fallback2 ?? null;
1507
+ }
1508
+ __name(renderFallback, "renderFallback");
1509
+ var ItemBoundary = class ItemBoundary2 extends import_react4.Component {
1510
+ static {
1511
+ __name(this, "ItemBoundary");
1512
+ }
1513
+ state = {
1514
+ error: void 0,
1515
+ failed: false
1516
+ };
1517
+ static getDerivedStateFromError(error) {
1518
+ return {
1519
+ error,
1520
+ failed: true
1521
+ };
1522
+ }
1523
+ componentDidCatch(error, _info) {
1524
+ this.props.onError?.(error, this.props.item);
1525
+ }
1526
+ componentDidUpdate(previous) {
1527
+ if (this.state.failed && previous.item !== this.props.item) {
1528
+ this.setState({
1529
+ error: void 0,
1530
+ failed: false
1531
+ });
1532
+ }
1533
+ }
1534
+ render() {
1535
+ if (this.state.failed) {
1536
+ return renderFallback(this.props.fallback, {
1537
+ reason: "error",
1538
+ item: this.props.item,
1539
+ error: this.state.error
1540
+ });
1541
+ }
1542
+ return this.props.children;
1543
+ }
1544
+ };
1545
+ function nodeItem(node, id) {
1546
+ return {
1547
+ id,
1548
+ component: node.type,
1549
+ props: node.props ?? {},
1550
+ version: null,
1551
+ toolCallId: null
1552
+ };
1553
+ }
1554
+ __name(nodeItem, "nodeItem");
1555
+ function TreeNode({ node, id }) {
1556
+ const scope = (0, import_react4.useContext)(TreeScopeContext);
1557
+ const item = (0, import_react4.useMemo)(() => nodeItem(node, id), [
1558
+ node,
1559
+ id
1560
+ ]);
1561
+ const resolution = useResolvedComponent(node.type, null, scope?.options.registry ?? {}, scope?.options.resolveComponent);
1562
+ const validation = useValidatedProps(scope?.options.catalog, node.type, item.props);
1563
+ if (scope === null) return null;
1564
+ if (resolution.status === "loading" || validation.status === "pending") return scope.loading;
1565
+ if (resolution.status === "unknown") {
1566
+ return renderFallback(scope.fallback, {
1567
+ reason: "unknown",
1568
+ item
1569
+ });
1570
+ }
1571
+ if (resolution.status === "error") {
1572
+ return renderFallback(scope.fallback, {
1573
+ reason: "error",
1574
+ item,
1575
+ error: resolution.error
1576
+ });
1577
+ }
1578
+ if (validation.status === "invalid") {
1579
+ return renderFallback(scope.fallback, {
1580
+ reason: "invalid",
1581
+ item,
1582
+ issues: validation.issues
1583
+ });
1584
+ }
1585
+ const Renderer = resolution.Component;
1586
+ const children = Array.isArray(node.children) ? node.children : [];
1587
+ return /* @__PURE__ */ React.createElement(Renderer, validation.props, children.length > 0 ? children.map((child, index) => {
1588
+ const childId = `${id}.${index}`;
1589
+ return /* @__PURE__ */ React.createElement(ItemBoundary, {
1590
+ key: childId,
1591
+ item: nodeItem(child, childId),
1592
+ fallback: scope.fallback,
1593
+ onError: scope.onError
1594
+ }, /* @__PURE__ */ React.createElement(TreeNode, {
1595
+ node: child,
1596
+ id: childId
1597
+ }));
1598
+ }) : void 0);
1599
+ }
1600
+ __name(TreeNode, "TreeNode");
1601
+ function GenuiTree({ root }) {
1602
+ if (root === void 0 || root === null || typeof root.type !== "string") return null;
1603
+ return /* @__PURE__ */ React.createElement(TreeNode, {
1604
+ node: root,
1605
+ id: "root"
1606
+ });
1607
+ }
1608
+ __name(GenuiTree, "GenuiTree");
1609
+ function GenerativeUIScope({ registry, catalog, resolveComponent, fallback: fallback2, loading = null, onError, children }) {
1610
+ const scope = (0, import_react4.useMemo)(() => ({
1611
+ options: {
1612
+ registry,
1613
+ ...catalog !== void 0 ? {
1614
+ catalog
1615
+ } : {},
1616
+ ...resolveComponent !== void 0 ? {
1617
+ resolveComponent
1618
+ } : {}
1619
+ },
1620
+ fallback: fallback2,
1621
+ loading,
1622
+ onError
1623
+ }), [
1624
+ registry,
1625
+ catalog,
1626
+ resolveComponent,
1627
+ fallback2,
1628
+ loading,
1629
+ onError
1630
+ ]);
1631
+ return /* @__PURE__ */ React.createElement(TreeScopeContext.Provider, {
1632
+ value: scope
1633
+ }, children);
1634
+ }
1635
+ __name(GenerativeUIScope, "GenerativeUIScope");
1636
+ var GenuiContext = sharedContext("@dudousxd/nestjs-agent-react:genui-provider");
1637
+ function GenuiProvider({ registry, catalog, resolveComponent, treeRenderer, fallback: fallback2, loading, onError, children }) {
1638
+ const value = (0, import_react4.useMemo)(() => ({
1639
+ ...registry !== void 0 ? {
1640
+ registry
1641
+ } : {},
1642
+ ...catalog !== void 0 ? {
1643
+ catalog
1644
+ } : {},
1645
+ ...resolveComponent !== void 0 ? {
1646
+ resolveComponent
1647
+ } : {},
1648
+ ...treeRenderer !== void 0 ? {
1649
+ treeRenderer
1650
+ } : {},
1651
+ ...fallback2 !== void 0 ? {
1652
+ fallback: fallback2
1653
+ } : {},
1654
+ ...loading !== void 0 ? {
1655
+ loading
1656
+ } : {},
1657
+ ...onError !== void 0 ? {
1658
+ onError
1659
+ } : {}
1660
+ }), [
1661
+ registry,
1662
+ catalog,
1663
+ resolveComponent,
1664
+ treeRenderer,
1665
+ fallback2,
1666
+ loading,
1667
+ onError
1668
+ ]);
1669
+ const renderUi = (0, import_react4.useCallback)((block) => /* @__PURE__ */ React.createElement(GenerativeUI, {
1670
+ part: block
1671
+ }), []);
1672
+ return /* @__PURE__ */ React.createElement(GenuiContext.Provider, {
1673
+ value
1674
+ }, /* @__PURE__ */ React.createElement(AmbientRenderUiContext.Provider, {
1675
+ value: renderUi
1676
+ }, children));
1677
+ }
1678
+ __name(GenuiProvider, "GenuiProvider");
1679
+ var NO_REGISTRY = {};
1680
+ function useMergedOptions(own) {
1681
+ const provided = (0, import_react4.useContext)(GenuiContext);
1682
+ const registry = own.registry ?? provided?.registry ?? NO_REGISTRY;
1683
+ const catalog = own.catalog ?? provided?.catalog;
1684
+ const resolveComponent = own.resolveComponent ?? provided?.resolveComponent;
1685
+ const treeRenderer = own.treeRenderer ?? provided?.treeRenderer;
1686
+ return (0, import_react4.useMemo)(() => ({
1687
+ registry,
1688
+ ...catalog !== void 0 ? {
1689
+ catalog
1690
+ } : {},
1691
+ ...resolveComponent !== void 0 ? {
1692
+ resolveComponent
1693
+ } : {},
1694
+ ...treeRenderer !== void 0 ? {
1695
+ treeRenderer
1696
+ } : {}
1697
+ }), [
1698
+ registry,
1699
+ catalog,
1700
+ resolveComponent,
1701
+ treeRenderer
1702
+ ]);
1703
+ }
1704
+ __name(useMergedOptions, "useMergedOptions");
1705
+ function GenerativeUI({ part, registry, catalog, resolveComponent, treeRenderer, fallback: ownFallback, loading: ownLoading, onError: ownOnError }) {
1706
+ const provided = (0, import_react4.useContext)(GenuiContext);
1707
+ const fallback2 = ownFallback ?? provided?.fallback;
1708
+ const loading = ownLoading ?? provided?.loading ?? null;
1709
+ const onError = ownOnError ?? provided?.onError;
1710
+ const options = useMergedOptions({
1711
+ ...registry !== void 0 ? {
1712
+ registry
1713
+ } : {},
1714
+ ...catalog !== void 0 ? {
1715
+ catalog
1716
+ } : {},
1717
+ ...resolveComponent !== void 0 ? {
1718
+ resolveComponent
1719
+ } : {},
1720
+ ...treeRenderer !== void 0 ? {
1721
+ treeRenderer
1722
+ } : {}
1723
+ });
1724
+ const state = useGenerativeUIState(part, options, options.treeRenderer ?? GenuiTree);
1725
+ if (state === null) return null;
1726
+ if (state.status === "loading") return loading;
1727
+ if (state.status === "problem") {
1728
+ const { status: _status, ...problem } = state;
1729
+ return renderFallback(fallback2, problem);
1730
+ }
1731
+ const Renderer = state.Component;
1732
+ return /* @__PURE__ */ React.createElement(GenerativeUIScope, {
1733
+ ...options,
1734
+ fallback: fallback2,
1735
+ loading,
1736
+ ...onError !== void 0 ? {
1737
+ onError
1738
+ } : {}
1739
+ }, /* @__PURE__ */ React.createElement(ItemBoundary, {
1740
+ item: state.item,
1741
+ fallback: fallback2,
1742
+ onError
1743
+ }, /* @__PURE__ */ React.createElement(Renderer, state.props)));
1744
+ }
1745
+ __name(GenerativeUI, "GenerativeUI");
1746
+
1747
+ // src/provider.tsx
1748
+ var AgentBackendContext = sharedContext("@dudousxd/nestjs-agent-react:agent-backend");
1749
+ function AgentProvider({ backend, baseUrl, path, headers, getHeaders, credentials, fetch, attachments, genui, children }) {
1750
+ const latestHeaders = (0, import_react5.useRef)({
1751
+ headers,
1752
+ getHeaders
1753
+ });
1754
+ latestHeaders.current = {
1755
+ headers,
1756
+ getHeaders
1757
+ };
1758
+ const upload = attachments?.upload;
1759
+ const value = (0, import_react5.useMemo)(() => backend ?? new AgentClient({
1760
+ ...baseUrl !== void 0 ? {
1761
+ baseUrl
1762
+ } : {},
1763
+ ...path !== void 0 ? {
1764
+ path
1765
+ } : {},
1766
+ ...credentials !== void 0 ? {
1767
+ credentials
1768
+ } : {},
1769
+ ...fetch !== void 0 ? {
1770
+ fetch
1771
+ } : {},
1772
+ ...upload !== void 0 ? {
1773
+ attachments: {
1774
+ upload
1775
+ }
1776
+ } : {},
1777
+ getHeaders: /* @__PURE__ */ __name(async () => {
1778
+ const current = latestHeaders.current;
1779
+ const dynamic = await current.getHeaders?.() ?? {};
1780
+ return {
1781
+ ...current.headers,
1782
+ ...dynamic
1783
+ };
1784
+ }, "getHeaders")
1785
+ }), [
1786
+ backend,
1787
+ baseUrl,
1788
+ path,
1789
+ credentials,
1790
+ fetch,
1791
+ upload
1792
+ ]);
1793
+ const content = genui !== void 0 ? /* @__PURE__ */ React.createElement(GenuiProvider, genui, children) : children;
1794
+ return /* @__PURE__ */ React.createElement(AgentBackendContext.Provider, {
1795
+ value
1796
+ }, content);
1797
+ }
1798
+ __name(AgentProvider, "AgentProvider");
1799
+ var fallback;
1800
+ function defaultBackend() {
1801
+ fallback ??= new AgentClient();
1802
+ return fallback;
1803
+ }
1804
+ __name(defaultBackend, "defaultBackend");
1805
+ function useAgentBackend(own) {
1806
+ const provided = (0, import_react5.useContext)(AgentBackendContext);
1807
+ return own ?? provided ?? defaultBackend();
1808
+ }
1809
+ __name(useAgentBackend, "useAgentBackend");
1810
+
1227
1811
  // src/attachments/use-attachments.ts
1228
1812
  var DEFAULT_REJECTION = {
1229
1813
  type: /* @__PURE__ */ __name((file) => `${file.name} is not a supported file type`, "type"),
@@ -1231,23 +1815,30 @@ var DEFAULT_REJECTION = {
1231
1815
  count: /* @__PURE__ */ __name(() => "Too many files", "count")
1232
1816
  };
1233
1817
  var sequence = 0;
1234
- function useAttachments(options) {
1235
- const latest = (0, import_react2.useRef)(options);
1236
- latest.current = options;
1237
- const [items, setItems] = (0, import_react2.useState)([]);
1238
- const itemsRef = (0, import_react2.useRef)(items);
1818
+ function useAttachments(options = {}) {
1819
+ const backend = useAgentBackend(options.backend);
1820
+ const latest = (0, import_react6.useRef)({
1821
+ ...options,
1822
+ backend
1823
+ });
1824
+ latest.current = {
1825
+ ...options,
1826
+ backend
1827
+ };
1828
+ const [items, setItems] = (0, import_react6.useState)([]);
1829
+ const itemsRef = (0, import_react6.useRef)(items);
1239
1830
  itemsRef.current = items;
1240
- const controllers = (0, import_react2.useRef)(/* @__PURE__ */ new Map());
1241
- const [dragDepth, setDragDepth] = (0, import_react2.useState)(0);
1242
- const patch = (0, import_react2.useCallback)((id, change) => {
1831
+ const controllers = (0, import_react6.useRef)(/* @__PURE__ */ new Map());
1832
+ const [dragDepth, setDragDepth] = (0, import_react6.useState)(0);
1833
+ const patch = (0, import_react6.useCallback)((id, change) => {
1243
1834
  setItems((current) => current.map((item) => item.id === id ? {
1244
1835
  ...item,
1245
1836
  ...change
1246
1837
  } : item));
1247
1838
  }, []);
1248
- const start = (0, import_react2.useCallback)((item) => {
1249
- const { upload, backend } = latest.current;
1250
- const run = upload ?? (backend?.uploadAttachment !== void 0 ? backend.uploadAttachment.bind(backend) : void 0);
1839
+ const start = (0, import_react6.useCallback)((item) => {
1840
+ const { upload, backend: backend2 } = latest.current;
1841
+ const run = upload ?? (backend2.uploadAttachment !== void 0 ? backend2.uploadAttachment.bind(backend2) : void 0);
1251
1842
  if (run === void 0) {
1252
1843
  patch(item.id, {
1253
1844
  status: "error",
@@ -1281,7 +1872,7 @@ function useAttachments(options) {
1281
1872
  }, [
1282
1873
  patch
1283
1874
  ]);
1284
- const add = (0, import_react2.useCallback)((files) => {
1875
+ const add = (0, import_react6.useCallback)((files) => {
1285
1876
  if (files == null) return;
1286
1877
  const { accept: accept2, maxBytes, maxFiles, describeRejection } = latest.current;
1287
1878
  const describe = /* @__PURE__ */ __name((reason, file) => describeRejection?.(reason, file) ?? DEFAULT_REJECTION[reason](file), "describe");
@@ -1327,7 +1918,7 @@ function useAttachments(options) {
1327
1918
  }, [
1328
1919
  start
1329
1920
  ]);
1330
- const release = (0, import_react2.useCallback)((item) => {
1921
+ const release = (0, import_react6.useCallback)((item) => {
1331
1922
  if (item === void 0) return;
1332
1923
  controllers.current.get(item.id)?.abort();
1333
1924
  controllers.current.delete(item.id);
@@ -1335,19 +1926,19 @@ function useAttachments(options) {
1335
1926
  URL.revokeObjectURL(item.previewUrl);
1336
1927
  }
1337
1928
  }, []);
1338
- const remove = (0, import_react2.useCallback)((id) => {
1929
+ const remove = (0, import_react6.useCallback)((id) => {
1339
1930
  release(itemsRef.current.find((item) => item.id === id));
1340
1931
  setItems((current) => current.filter((item) => item.id !== id));
1341
1932
  }, [
1342
1933
  release
1343
1934
  ]);
1344
- const clear = (0, import_react2.useCallback)(() => {
1935
+ const clear = (0, import_react6.useCallback)(() => {
1345
1936
  for (const item of itemsRef.current) release(item);
1346
1937
  setItems([]);
1347
1938
  }, [
1348
1939
  release
1349
1940
  ]);
1350
- const retry = (0, import_react2.useCallback)((id) => {
1941
+ const retry = (0, import_react6.useCallback)((id) => {
1351
1942
  const item = itemsRef.current.find((candidate) => candidate.id === id);
1352
1943
  if (item === void 0 || item.status !== "error") return;
1353
1944
  const { error: _previous, ...rest } = item;
@@ -1361,12 +1952,12 @@ function useAttachments(options) {
1361
1952
  }, [
1362
1953
  start
1363
1954
  ]);
1364
- (0, import_react2.useEffect)(() => () => {
1955
+ (0, import_react6.useEffect)(() => () => {
1365
1956
  for (const item of itemsRef.current) release(item);
1366
1957
  }, [
1367
1958
  release
1368
1959
  ]);
1369
- const onPaste = (0, import_react2.useCallback)((event) => {
1960
+ const onPaste = (0, import_react6.useCallback)((event) => {
1370
1961
  const files = filesFromClipboard(event.clipboardData);
1371
1962
  if (files.length === 0) return;
1372
1963
  event.preventDefault();
@@ -1374,7 +1965,7 @@ function useAttachments(options) {
1374
1965
  }, [
1375
1966
  add
1376
1967
  ]);
1377
- const dropZoneProps = (0, import_react2.useMemo)(() => ({
1968
+ const dropZoneProps = (0, import_react6.useMemo)(() => ({
1378
1969
  onDragEnter: /* @__PURE__ */ __name((event) => {
1379
1970
  if (!dragHasFiles(event.dataTransfer)) return;
1380
1971
  event.preventDefault();
@@ -1397,7 +1988,7 @@ function useAttachments(options) {
1397
1988
  add
1398
1989
  ]);
1399
1990
  const accept = options.accept;
1400
- const inputProps = (0, import_react2.useMemo)(() => ({
1991
+ const inputProps = (0, import_react6.useMemo)(() => ({
1401
1992
  type: "file",
1402
1993
  accept: typeof accept === "string" ? accept : accept?.join(","),
1403
1994
  multiple: options.maxFiles === void 0 || options.maxFiles > 1,
@@ -1411,7 +2002,7 @@ function useAttachments(options) {
1411
2002
  options.maxFiles,
1412
2003
  add
1413
2004
  ]);
1414
- return (0, import_react2.useMemo)(() => {
2005
+ return (0, import_react6.useMemo)(() => {
1415
2006
  const ready = items.filter((item) => item.status === "ready" && item.attachment !== void 0);
1416
2007
  const attachments = ready.map((item) => item.attachment);
1417
2008
  return {
@@ -1445,18 +2036,18 @@ function useAttachments(options) {
1445
2036
  __name(useAttachments, "useAttachments");
1446
2037
 
1447
2038
  // src/catalog/use-agents.ts
1448
- var import_react4 = require("react");
2039
+ var import_react8 = require("react");
1449
2040
 
1450
2041
  // src/catalog/use-resource.ts
1451
- var import_react3 = require("react");
2042
+ var import_react7 = require("react");
1452
2043
  function useResource(load2, key, enabled) {
1453
- const [data, setData] = (0, import_react3.useState)(void 0);
1454
- const [isLoading, setIsLoading] = (0, import_react3.useState)(enabled);
1455
- const [error, setError] = (0, import_react3.useState)(null);
1456
- const loadRef = (0, import_react3.useRef)(load2);
2044
+ const [data, setData] = (0, import_react7.useState)(void 0);
2045
+ const [isLoading, setIsLoading] = (0, import_react7.useState)(enabled);
2046
+ const [error, setError] = (0, import_react7.useState)(null);
2047
+ const loadRef = (0, import_react7.useRef)(load2);
1457
2048
  loadRef.current = load2;
1458
- const generation = (0, import_react3.useRef)(0);
1459
- const refresh = (0, import_react3.useCallback)(async () => {
2049
+ const generation = (0, import_react7.useRef)(0);
2050
+ const refresh = (0, import_react7.useCallback)(async () => {
1460
2051
  const mine = ++generation.current;
1461
2052
  setIsLoading(true);
1462
2053
  try {
@@ -1471,7 +2062,7 @@ function useResource(load2, key, enabled) {
1471
2062
  if (mine === generation.current) setIsLoading(false);
1472
2063
  }
1473
2064
  }, []);
1474
- (0, import_react3.useEffect)(() => {
2065
+ (0, import_react7.useEffect)(() => {
1475
2066
  if (!enabled) return;
1476
2067
  void refresh();
1477
2068
  }, [
@@ -1489,10 +2080,11 @@ function useResource(load2, key, enabled) {
1489
2080
  __name(useResource, "useResource");
1490
2081
 
1491
2082
  // src/catalog/use-agents.ts
1492
- function useAgents(options) {
1493
- const { backend, enabled = true } = options;
2083
+ function useAgents(options = {}) {
2084
+ const { enabled = true } = options;
2085
+ const backend = useAgentBackend(options.backend);
1494
2086
  const { data, isLoading, error, refresh } = useResource(() => requireBackendMethod(backend, "listAgents")(), "", enabled);
1495
- return (0, import_react4.useMemo)(() => {
2087
+ return (0, import_react8.useMemo)(() => {
1496
2088
  const agents = data ?? [];
1497
2089
  return {
1498
2090
  agents,
@@ -1511,11 +2103,12 @@ function useAgents(options) {
1511
2103
  __name(useAgents, "useAgents");
1512
2104
 
1513
2105
  // src/catalog/use-models.ts
1514
- var import_react5 = require("react");
1515
- function useModels(options) {
1516
- const { backend, agent, enabled = true } = options;
2106
+ var import_react9 = require("react");
2107
+ function useModels(options = {}) {
2108
+ const { agent, enabled = true } = options;
2109
+ const backend = useAgentBackend(options.backend);
1517
2110
  const { data, isLoading, error, refresh } = useResource(() => requireBackendMethod(backend, "listModels")(agent), `${agent ?? ""}`, enabled);
1518
- return (0, import_react5.useMemo)(() => {
2111
+ return (0, import_react9.useMemo)(() => {
1519
2112
  const providers = data?.providers ?? [];
1520
2113
  const models = providers.flatMap((provider) => provider.models.map((model) => ({
1521
2114
  ...model,
@@ -1545,7 +2138,7 @@ function useModels(options) {
1545
2138
  __name(useModels, "useModels");
1546
2139
 
1547
2140
  // src/quota/use-quota.ts
1548
- var import_react6 = require("react");
2141
+ var import_react10 = require("react");
1549
2142
 
1550
2143
  // src/threads/threads-events.ts
1551
2144
  var listeners = /* @__PURE__ */ new WeakMap();
@@ -1569,10 +2162,11 @@ function onThreadsEvent(backend, listener) {
1569
2162
  __name(onThreadsEvent, "onThreadsEvent");
1570
2163
 
1571
2164
  // src/quota/use-quota.ts
1572
- function useQuota(options) {
1573
- const { backend, enabled = true, pollMs } = options;
2165
+ function useQuota(options = {}) {
2166
+ const { enabled = true, pollMs } = options;
2167
+ const backend = useAgentBackend(options.backend);
1574
2168
  const { data, isLoading, error, refresh } = useResource(() => requireBackendMethod(backend, "getQuota")(), "", enabled);
1575
- (0, import_react6.useEffect)(() => {
2169
+ (0, import_react10.useEffect)(() => {
1576
2170
  if (!enabled) return;
1577
2171
  return onThreadsEvent(backend, (event) => {
1578
2172
  if (event.type === "changed") void refresh();
@@ -1582,7 +2176,7 @@ function useQuota(options) {
1582
2176
  enabled,
1583
2177
  refresh
1584
2178
  ]);
1585
- (0, import_react6.useEffect)(() => {
2179
+ (0, import_react10.useEffect)(() => {
1586
2180
  if (!enabled || pollMs === void 0 || pollMs <= 0) return;
1587
2181
  const timer = setInterval(() => void refresh(), pollMs);
1588
2182
  return () => clearInterval(timer);
@@ -1591,7 +2185,7 @@ function useQuota(options) {
1591
2185
  pollMs,
1592
2186
  refresh
1593
2187
  ]);
1594
- return (0, import_react6.useMemo)(() => {
2188
+ return (0, import_react10.useMemo)(() => {
1595
2189
  const windows = data?.windows ?? [];
1596
2190
  return {
1597
2191
  report: data,
@@ -1613,37 +2207,44 @@ function useQuota(options) {
1613
2207
  __name(useQuota, "useQuota");
1614
2208
 
1615
2209
  // src/feedback/use-message-feedback.ts
1616
- var import_react7 = require("react");
1617
- function useMessageFeedback(options) {
1618
- const latest = (0, import_react7.useRef)(options);
1619
- latest.current = options;
1620
- const [local, setLocal] = (0, import_react7.useState)(/* @__PURE__ */ new Map());
1621
- const [pending, setPending] = (0, import_react7.useState)(/* @__PURE__ */ new Set());
1622
- const [error, setError] = (0, import_react7.useState)(null);
1623
- const localRef = (0, import_react7.useRef)(local);
2210
+ var import_react11 = require("react");
2211
+ function useMessageFeedback(options = {}) {
2212
+ const backend = useAgentBackend(options.backend);
2213
+ const latest = (0, import_react11.useRef)({
2214
+ ...options,
2215
+ backend
2216
+ });
2217
+ latest.current = {
2218
+ ...options,
2219
+ backend
2220
+ };
2221
+ const [local, setLocal] = (0, import_react11.useState)(/* @__PURE__ */ new Map());
2222
+ const [pending, setPending] = (0, import_react11.useState)(/* @__PURE__ */ new Set());
2223
+ const [error, setError] = (0, import_react11.useState)(null);
2224
+ const localRef = (0, import_react11.useRef)(local);
1624
2225
  localRef.current = local;
1625
- const resolved = (0, import_react7.useRef)(/* @__PURE__ */ new Map());
1626
- const feedbackOf = (0, import_react7.useCallback)((message) => {
2226
+ const resolved = (0, import_react11.useRef)(/* @__PURE__ */ new Map());
2227
+ const feedbackOf = (0, import_react11.useCallback)((message) => {
1627
2228
  const mine = local.get(message.id);
1628
2229
  if (mine !== void 0) return mine.feedback;
1629
2230
  return metadataOf(message).feedback ?? null;
1630
2231
  }, [
1631
2232
  local
1632
2233
  ]);
1633
- const isPending = (0, import_react7.useCallback)((message) => pending.has(message.id), [
2234
+ const isPending = (0, import_react11.useCallback)((message) => pending.has(message.id), [
1634
2235
  pending
1635
2236
  ]);
1636
- const storedIdFor = (0, import_react7.useCallback)(async (message) => {
2237
+ const storedIdFor = (0, import_react11.useCallback)(async (message) => {
1637
2238
  const runId = metadataOf(message).runId;
1638
2239
  if (runId === void 0) return message.id;
1639
2240
  const known = resolved.current.get(message.id);
1640
2241
  if (known !== void 0) return known;
1641
- const { backend, threadId } = latest.current;
2242
+ const { backend: backend2, threadId } = latest.current;
1642
2243
  const thread = typeof threadId === "function" ? threadId() : threadId;
1643
2244
  if (thread === void 0) {
1644
2245
  throw new Error("useMessageFeedback: a streamed message needs `threadId` to be rated");
1645
2246
  }
1646
- const detail = await backend.getThread(thread);
2247
+ const detail = await backend2.getThread(thread);
1647
2248
  const row = [
1648
2249
  ...detail.messages
1649
2250
  ].reverse().find((candidate) => candidate.role === "assistant" && candidate.runId === runId);
@@ -1653,7 +2254,7 @@ function useMessageFeedback(options) {
1653
2254
  resolved.current.set(message.id, row.id);
1654
2255
  return row.id;
1655
2256
  }, []);
1656
- const rate = (0, import_react7.useCallback)(async (message, value, comment) => {
2257
+ const rate = (0, import_react11.useCallback)(async (message, value, comment) => {
1657
2258
  const setFeedback = requireBackendMethod(latest.current.backend, "setMessageFeedback");
1658
2259
  const had = localRef.current.get(message.id);
1659
2260
  const optimistic = value === null ? null : {
@@ -1699,7 +2300,7 @@ function useMessageFeedback(options) {
1699
2300
  }, [
1700
2301
  storedIdFor
1701
2302
  ]);
1702
- const toggle = (0, import_react7.useCallback)((message, value) => {
2303
+ const toggle = (0, import_react11.useCallback)((message, value) => {
1703
2304
  const mine = localRef.current.get(message.id);
1704
2305
  const current = mine !== void 0 ? mine.feedback : metadataOf(message).feedback ?? null;
1705
2306
  return rate(message, current?.value === value ? null : value);
@@ -1722,16 +2323,17 @@ function metadataOf(message) {
1722
2323
  __name(metadataOf, "metadataOf");
1723
2324
 
1724
2325
  // src/threads/use-threads.ts
1725
- var import_react8 = require("react");
1726
- function useThreads(options) {
1727
- const { backend, enabled = true } = options;
1728
- const [threads, setThreads] = (0, import_react8.useState)([]);
1729
- const [isLoading, setIsLoading] = (0, import_react8.useState)(enabled);
1730
- const [error, setError] = (0, import_react8.useState)(null);
1731
- const threadsRef = (0, import_react8.useRef)(threads);
2326
+ var import_react12 = require("react");
2327
+ function useThreads(options = {}) {
2328
+ const { enabled = true } = options;
2329
+ const backend = useAgentBackend(options.backend);
2330
+ const [threads, setThreads] = (0, import_react12.useState)([]);
2331
+ const [isLoading, setIsLoading] = (0, import_react12.useState)(enabled);
2332
+ const [error, setError] = (0, import_react12.useState)(null);
2333
+ const threadsRef = (0, import_react12.useRef)(threads);
1732
2334
  threadsRef.current = threads;
1733
- const generation = (0, import_react8.useRef)(0);
1734
- const refresh = (0, import_react8.useCallback)(async () => {
2335
+ const generation = (0, import_react12.useRef)(0);
2336
+ const refresh = (0, import_react12.useCallback)(async () => {
1735
2337
  const mine = ++generation.current;
1736
2338
  setIsLoading(true);
1737
2339
  try {
@@ -1748,7 +2350,7 @@ function useThreads(options) {
1748
2350
  }, [
1749
2351
  backend
1750
2352
  ]);
1751
- (0, import_react8.useEffect)(() => {
2353
+ (0, import_react12.useEffect)(() => {
1752
2354
  if (!enabled) return;
1753
2355
  void refresh();
1754
2356
  return onThreadsEvent(backend, (event) => {
@@ -1768,7 +2370,7 @@ function useThreads(options) {
1768
2370
  enabled,
1769
2371
  refresh
1770
2372
  ]);
1771
- const rename = (0, import_react8.useCallback)(async (id, title) => {
2373
+ const rename = (0, import_react12.useCallback)(async (id, title) => {
1772
2374
  const before = threadsRef.current;
1773
2375
  setThreads((current) => current.map((thread) => thread.id === id ? {
1774
2376
  ...thread,
@@ -1790,7 +2392,7 @@ function useThreads(options) {
1790
2392
  }, [
1791
2393
  backend
1792
2394
  ]);
1793
- const remove = (0, import_react8.useCallback)(async (id) => {
2395
+ const remove = (0, import_react12.useCallback)(async (id) => {
1794
2396
  const before = threadsRef.current;
1795
2397
  setThreads((current) => current.filter((thread) => thread.id !== id));
1796
2398
  try {
@@ -1864,29 +2466,11 @@ function backgroundRunsFromThread(messages) {
1864
2466
  }
1865
2467
  __name(backgroundRunsFromThread, "backgroundRunsFromThread");
1866
2468
 
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
2469
  // src/components/chat-input.tsx
1886
- var import_react11 = __toESM(require("react"), 1);
2470
+ var import_react14 = __toESM(require("react"), 1);
1887
2471
 
1888
2472
  // src/components/use-speech-recognition.ts
1889
- var import_react10 = require("react");
2473
+ var import_react13 = require("react");
1890
2474
  function getRecognitionCtor() {
1891
2475
  if (typeof window === "undefined") return null;
1892
2476
  const scope = window;
@@ -1894,15 +2478,15 @@ function getRecognitionCtor() {
1894
2478
  }
1895
2479
  __name(getRecognitionCtor, "getRecognitionCtor");
1896
2480
  function useSpeechRecognition({ lang = "en-US", onFinalTranscript, onInterimTranscript }) {
1897
- const recognitionRef = (0, import_react10.useRef)(null);
1898
- const [isListening, setIsListening] = (0, import_react10.useState)(false);
1899
- const ctor = (0, import_react10.useMemo)(() => getRecognitionCtor(), []);
2481
+ const recognitionRef = (0, import_react13.useRef)(null);
2482
+ const [isListening, setIsListening] = (0, import_react13.useState)(false);
2483
+ const ctor = (0, import_react13.useMemo)(() => getRecognitionCtor(), []);
1900
2484
  const isSupported = ctor !== null;
1901
- const finalRef = (0, import_react10.useRef)(onFinalTranscript);
1902
- const interimRef = (0, import_react10.useRef)(onInterimTranscript);
2485
+ const finalRef = (0, import_react13.useRef)(onFinalTranscript);
2486
+ const interimRef = (0, import_react13.useRef)(onInterimTranscript);
1903
2487
  finalRef.current = onFinalTranscript;
1904
2488
  interimRef.current = onInterimTranscript;
1905
- (0, import_react10.useEffect)(() => {
2489
+ (0, import_react13.useEffect)(() => {
1906
2490
  if (!ctor) return;
1907
2491
  const recognition = new ctor();
1908
2492
  recognition.lang = lang;
@@ -1941,7 +2525,7 @@ function useSpeechRecognition({ lang = "en-US", onFinalTranscript, onInterimTran
1941
2525
  ctor,
1942
2526
  lang
1943
2527
  ]);
1944
- const start = (0, import_react10.useCallback)(() => {
2528
+ const start = (0, import_react13.useCallback)(() => {
1945
2529
  const recognition = recognitionRef.current;
1946
2530
  if (!recognition) return;
1947
2531
  try {
@@ -1951,7 +2535,7 @@ function useSpeechRecognition({ lang = "en-US", onFinalTranscript, onInterimTran
1951
2535
  console.warn("SpeechRecognition start failed", error);
1952
2536
  }
1953
2537
  }, []);
1954
- const stop = (0, import_react10.useCallback)(() => {
2538
+ const stop = (0, import_react13.useCallback)(() => {
1955
2539
  const recognition = recognitionRef.current;
1956
2540
  if (!recognition) return;
1957
2541
  try {
@@ -1970,8 +2554,8 @@ __name(useSpeechRecognition, "useSpeechRecognition");
1970
2554
 
1971
2555
  // src/components/chat-input.tsx
1972
2556
  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, import_react11.useState)("");
1974
- const [interim, setInterim] = (0, import_react11.useState)("");
2557
+ const [value, setValue] = (0, import_react14.useState)("");
2558
+ const [interim, setInterim] = (0, import_react14.useState)("");
1975
2559
  const speech = useSpeechRecognition({
1976
2560
  lang: speechLang,
1977
2561
  onFinalTranscript: /* @__PURE__ */ __name((text) => {
@@ -1982,7 +2566,7 @@ function ChatInput({ onSubmit, disabled, placeholder, rows = 2, enableSpeech = t
1982
2566
  }, "onFinalTranscript"),
1983
2567
  onInterimTranscript: /* @__PURE__ */ __name((text) => setInterim(text), "onInterimTranscript")
1984
2568
  });
1985
- (0, import_react11.useEffect)(() => {
2569
+ (0, import_react14.useEffect)(() => {
1986
2570
  if (!speech.isListening) setInterim("");
1987
2571
  }, [
1988
2572
  speech.isListening
@@ -2010,9 +2594,9 @@ function ChatInput({ onSubmit, disabled, placeholder, rows = 2, enableSpeech = t
2010
2594
  const displayValue = speech.isListening && interim ? `${value}${value && !value.endsWith(" ") ? " " : ""}${interim}` : value;
2011
2595
  const showMic = enableSpeech && speech.isSupported;
2012
2596
  const showStop = isStreaming && onStop !== void 0;
2013
- return /* @__PURE__ */ import_react11.default.createElement("div", {
2597
+ return /* @__PURE__ */ import_react14.default.createElement("div", {
2014
2598
  className
2015
- }, /* @__PURE__ */ import_react11.default.createElement("textarea", {
2599
+ }, /* @__PURE__ */ import_react14.default.createElement("textarea", {
2016
2600
  className: textareaClassName,
2017
2601
  rows,
2018
2602
  value: displayValue,
@@ -2023,17 +2607,17 @@ function ChatInput({ onSubmit, disabled, placeholder, rows = 2, enableSpeech = t
2023
2607
  }, "onChange"),
2024
2608
  onKeyDown: handleKeyDown,
2025
2609
  placeholder: placeholder ?? "Ask something (Enter to send, Shift+Enter for newline)"
2026
- }), /* @__PURE__ */ import_react11.default.createElement("button", {
2610
+ }), /* @__PURE__ */ import_react14.default.createElement("button", {
2027
2611
  type: "button",
2028
2612
  className: sendButtonClassName,
2029
2613
  onClick: submit,
2030
2614
  disabled: disabled || !value.trim()
2031
- }, sendLabel), showStop ? /* @__PURE__ */ import_react11.default.createElement("button", {
2615
+ }, sendLabel), showStop ? /* @__PURE__ */ import_react14.default.createElement("button", {
2032
2616
  type: "button",
2033
2617
  className: stopButtonClassName,
2034
2618
  onClick: /* @__PURE__ */ __name(() => void onStop(), "onClick"),
2035
2619
  "aria-label": "Stop generating"
2036
- }, stopLabel) : null, showMic ? /* @__PURE__ */ import_react11.default.createElement("button", {
2620
+ }, stopLabel) : null, showMic ? /* @__PURE__ */ import_react14.default.createElement("button", {
2037
2621
  type: "button",
2038
2622
  className: micButtonClassName,
2039
2623
  onClick: toggleMic,
@@ -2046,10 +2630,10 @@ function ChatInput({ onSubmit, disabled, placeholder, rows = 2, enableSpeech = t
2046
2630
  __name(ChatInput, "ChatInput");
2047
2631
 
2048
2632
  // src/components/message-item.tsx
2049
- var import_react14 = __toESM(require("react"), 1);
2633
+ var import_react17 = __toESM(require("react"), 1);
2050
2634
 
2051
2635
  // src/transcript/use-chat-transcript.ts
2052
- var import_react13 = require("react");
2636
+ var import_react16 = require("react");
2053
2637
 
2054
2638
  // src/transcript/model.ts
2055
2639
  var import_nestjs_agent_core2 = require("@dudousxd/nestjs-agent-core");
@@ -2146,21 +2730,21 @@ function fillTemplate(template, context) {
2146
2730
  }).replace(/\s{2,}/g, " ").trim();
2147
2731
  }
2148
2732
  __name(fillTemplate, "fillTemplate");
2149
- function phraseFor(presentation, input, isSettled2, fallback = {
2733
+ function phraseFor(presentation, input, isSettled2, fallback2 = {
2150
2734
  running: "Working",
2151
2735
  done: "Done"
2152
2736
  }) {
2153
- if (presentation === void 0) return isSettled2 ? fallback.done : fallback.running;
2737
+ if (presentation === void 0) return isSettled2 ? fallback2.done : fallback2.running;
2154
2738
  const filled = fillTemplate(isSettled2 ? presentation.done : presentation.running, input);
2155
2739
  return filled === "" ? presentation.label : filled;
2156
2740
  }
2157
2741
  __name(phraseFor, "phraseFor");
2158
2742
 
2159
2743
  // src/presentation/result-view.ts
2160
- function isRecord(value) {
2744
+ function isRecord2(value) {
2161
2745
  return typeof value === "object" && value !== null && !Array.isArray(value);
2162
2746
  }
2163
- __name(isRecord, "isRecord");
2747
+ __name(isRecord2, "isRecord");
2164
2748
  function toText(value) {
2165
2749
  if (value === null || value === void 0) return "\u2014";
2166
2750
  if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
@@ -2171,7 +2755,7 @@ function toText(value) {
2171
2755
  }
2172
2756
  __name(toText, "toText");
2173
2757
  function inferResultView(output) {
2174
- if (!isRecord(output)) return void 0;
2758
+ if (!isRecord2(output)) return void 0;
2175
2759
  for (const [key, value] of Object.entries(output)) {
2176
2760
  if (!Array.isArray(value) || value.length === 0) continue;
2177
2761
  if (value.every((entry) => typeof entry === "string")) {
@@ -2180,12 +2764,12 @@ function inferResultView(output) {
2180
2764
  lines: key
2181
2765
  };
2182
2766
  }
2183
- if (value.every(isRecord)) {
2767
+ if (value.every(isRecord2)) {
2184
2768
  const first = value[0];
2185
2769
  return {
2186
2770
  kind: "table",
2187
2771
  rows: key,
2188
- columns: Object.keys(first).filter((column) => !isRecord(first[column])).map((column) => ({
2772
+ columns: Object.keys(first).filter((column) => !isRecord2(first[column])).map((column) => ({
2189
2773
  path: column,
2190
2774
  label: column
2191
2775
  }))
@@ -2561,7 +3145,7 @@ function isSettled(state) {
2561
3145
  __name(isSettled, "isSettled");
2562
3146
  function toolKind(part) {
2563
3147
  const metadata = part.toolMetadata;
2564
- return isRecord2(metadata) && typeof metadata.toolKind === "string" ? metadata.toolKind : void 0;
3148
+ return isRecord3(metadata) && typeof metadata.toolKind === "string" ? metadata.toolKind : void 0;
2565
3149
  }
2566
3150
  __name(toolKind, "toolKind");
2567
3151
  function isAwaitingApproval(part) {
@@ -2576,7 +3160,7 @@ function isAwaitingApproval(part) {
2576
3160
  __name(isAwaitingApproval, "isAwaitingApproval");
2577
3161
  function toolParentId(part) {
2578
3162
  const metadata = part.toolMetadata;
2579
- return isRecord2(metadata) && typeof metadata.parentId === "string" ? metadata.parentId : null;
3163
+ return isRecord3(metadata) && typeof metadata.parentId === "string" ? metadata.parentId : null;
2580
3164
  }
2581
3165
  __name(toolParentId, "toolParentId");
2582
3166
  function nestToolCalls(calls) {
@@ -2643,12 +3227,12 @@ function buildToolCall(part, options, approval, catalog) {
2643
3227
  __name(buildToolCall, "buildToolCall");
2644
3228
  function readElicitationRequest(part) {
2645
3229
  const input = part.input;
2646
- if (!isRecord2(input) || !Array.isArray(input.questions) || input.questions.length === 0) {
3230
+ if (!isRecord3(input) || !Array.isArray(input.questions) || input.questions.length === 0) {
2647
3231
  return null;
2648
3232
  }
2649
3233
  const questions = [];
2650
3234
  for (const candidate of input.questions) {
2651
- if (!isRecord2(candidate) || typeof candidate.id !== "string" || typeof candidate.prompt !== "string") {
3235
+ if (!isRecord3(candidate) || typeof candidate.id !== "string" || typeof candidate.prompt !== "string") {
2652
3236
  return null;
2653
3237
  }
2654
3238
  const input2 = (0, import_nestjs_agent_core2.readElicitationInput)(candidate.input) ?? null;
@@ -2658,7 +3242,7 @@ function readElicitationRequest(part) {
2658
3242
  }
2659
3243
  const options = [];
2660
3244
  for (const option of rawOptions) {
2661
- if (!isRecord2(option) || typeof option.value !== "string" || typeof option.label !== "string") {
3245
+ if (!isRecord3(option) || typeof option.value !== "string" || typeof option.label !== "string") {
2662
3246
  return null;
2663
3247
  }
2664
3248
  options.push({
@@ -2686,7 +3270,7 @@ function readElicitationRequest(part) {
2686
3270
  __name(readElicitationRequest, "readElicitationRequest");
2687
3271
  function readElicitationOutcome(part) {
2688
3272
  const output = part.output;
2689
- if (!isRecord2(output) || !isRecord2(output.answers) || typeof output.skipped !== "boolean") {
3273
+ if (!isRecord3(output) || !isRecord3(output.answers) || typeof output.skipped !== "boolean") {
2690
3274
  return null;
2691
3275
  }
2692
3276
  const answers = {};
@@ -2823,7 +3407,7 @@ function readApprovals(parts) {
2823
3407
  continue;
2824
3408
  }
2825
3409
  const data = part.data;
2826
- if (!isRecord2(data) || typeof data.id !== "string") {
3410
+ if (!isRecord3(data) || typeof data.id !== "string") {
2827
3411
  continue;
2828
3412
  }
2829
3413
  const approval = entry(data.id);
@@ -2879,7 +3463,7 @@ function statusFromPart(call) {
2879
3463
  __name(statusFromPart, "statusFromPart");
2880
3464
  function readUiComponent(part) {
2881
3465
  const data = part.data;
2882
- if (!isRecord2(data) || typeof data.component !== "string") {
3466
+ if (!isRecord3(data) || typeof data.component !== "string") {
2883
3467
  return null;
2884
3468
  }
2885
3469
  const id = typeof data.id === "string" ? data.id : part.id;
@@ -2889,19 +3473,19 @@ function readUiComponent(part) {
2889
3473
  return {
2890
3474
  id,
2891
3475
  component: data.component,
2892
- props: isRecord2(data.props) ? data.props : {},
3476
+ props: isRecord3(data.props) ? data.props : {},
2893
3477
  version: typeof data.version === "number" ? data.version : null,
2894
3478
  toolCallId: typeof data.toolCallId === "string" ? data.toolCallId : null
2895
3479
  };
2896
3480
  }
2897
3481
  __name(readUiComponent, "readUiComponent");
2898
- function isRecord2(value) {
3482
+ function isRecord3(value) {
2899
3483
  return typeof value === "object" && value !== null;
2900
3484
  }
2901
- __name(isRecord2, "isRecord");
3485
+ __name(isRecord3, "isRecord");
2902
3486
  function readQuery(part) {
2903
3487
  const input = part.input;
2904
- if (!isRecord2(input) || typeof input.query !== "string") {
3488
+ if (!isRecord3(input) || typeof input.query !== "string") {
2905
3489
  return null;
2906
3490
  }
2907
3491
  return input.query;
@@ -2909,12 +3493,12 @@ function readQuery(part) {
2909
3493
  __name(readQuery, "readQuery");
2910
3494
  function readPassages(part) {
2911
3495
  const output = part.output;
2912
- if (!isRecord2(output) || !Array.isArray(output.passages) || output.passages.length === 0) {
3496
+ if (!isRecord3(output) || !Array.isArray(output.passages) || output.passages.length === 0) {
2913
3497
  return null;
2914
3498
  }
2915
3499
  const passages = [];
2916
3500
  for (const candidate of output.passages) {
2917
- if (!isRecord2(candidate) || typeof candidate.id !== "string" || typeof candidate.text !== "string") {
3501
+ if (!isRecord3(candidate) || typeof candidate.id !== "string" || typeof candidate.text !== "string") {
2918
3502
  return null;
2919
3503
  }
2920
3504
  passages.push({
@@ -2924,7 +3508,7 @@ function readPassages(part) {
2924
3508
  ...typeof candidate.source === "string" ? {
2925
3509
  source: candidate.source
2926
3510
  } : {},
2927
- ...isRecord2(candidate.metadata) ? {
3511
+ ...isRecord3(candidate.metadata) ? {
2928
3512
  metadata: candidate.metadata
2929
3513
  } : {}
2930
3514
  });
@@ -3026,11 +3610,11 @@ function formatCostUsd(cost) {
3026
3610
  __name(formatCostUsd, "formatCostUsd");
3027
3611
 
3028
3612
  // src/transcript/use-stick-to-bottom.ts
3029
- var import_react12 = require("react");
3613
+ var import_react15 = require("react");
3030
3614
  function useStickToBottom({ contentKey, threshold = 32 }) {
3031
- const containerRef = (0, import_react12.useRef)(null);
3032
- const [isAtBottom, setIsAtBottom] = (0, import_react12.useState)(true);
3033
- const measure = (0, import_react12.useCallback)(() => {
3615
+ const containerRef = (0, import_react15.useRef)(null);
3616
+ const [isAtBottom, setIsAtBottom] = (0, import_react15.useState)(true);
3617
+ const measure = (0, import_react15.useCallback)(() => {
3034
3618
  const element = containerRef.current;
3035
3619
  if (!element) {
3036
3620
  return;
@@ -3040,7 +3624,7 @@ function useStickToBottom({ contentKey, threshold = 32 }) {
3040
3624
  }, [
3041
3625
  threshold
3042
3626
  ]);
3043
- const scrollToBottom = (0, import_react12.useCallback)(() => {
3627
+ const scrollToBottom = (0, import_react15.useCallback)(() => {
3044
3628
  const element = containerRef.current;
3045
3629
  if (!element) {
3046
3630
  return;
@@ -3048,7 +3632,7 @@ function useStickToBottom({ contentKey, threshold = 32 }) {
3048
3632
  element.scrollTop = element.scrollHeight;
3049
3633
  setIsAtBottom(true);
3050
3634
  }, []);
3051
- const setContainer = (0, import_react12.useCallback)((element) => {
3635
+ const setContainer = (0, import_react15.useCallback)((element) => {
3052
3636
  containerRef.current = element;
3053
3637
  if (element) {
3054
3638
  measure();
@@ -3056,7 +3640,7 @@ function useStickToBottom({ contentKey, threshold = 32 }) {
3056
3640
  }, [
3057
3641
  measure
3058
3642
  ]);
3059
- (0, import_react12.useEffect)(() => {
3643
+ (0, import_react15.useEffect)(() => {
3060
3644
  if (isAtBottom) {
3061
3645
  scrollToBottom();
3062
3646
  }
@@ -3065,7 +3649,7 @@ function useStickToBottom({ contentKey, threshold = 32 }) {
3065
3649
  isAtBottom,
3066
3650
  scrollToBottom
3067
3651
  ]);
3068
- const getContainerProps = (0, import_react12.useCallback)(() => ({
3652
+ const getContainerProps = (0, import_react15.useCallback)(() => ({
3069
3653
  ref: setContainer,
3070
3654
  onScroll: measure
3071
3655
  }), [
@@ -3087,14 +3671,14 @@ var DEFAULT_LOAD_EARLIER_STEP = 50;
3087
3671
  var DEFAULT_COPY_RESET_MS = 1500;
3088
3672
  function useChatTranscript(options) {
3089
3673
  const { messages, status, initialVisibleCount = DEFAULT_VISIBLE_COUNT, loadEarlierStep = DEFAULT_LOAD_EARLIER_STEP, followUps, stickToBottomThreshold } = options;
3090
- const latest = (0, import_react13.useRef)(options);
3674
+ const latest = (0, import_react16.useRef)(options);
3091
3675
  latest.current = options;
3092
- const [visibleCount, setVisibleCount] = (0, import_react13.useState)(initialVisibleCount);
3093
- const [stopRequested, setStopRequested] = (0, import_react13.useState)(false);
3676
+ const [visibleCount, setVisibleCount] = (0, import_react16.useState)(initialVisibleCount);
3677
+ const [stopRequested, setStopRequested] = (0, import_react16.useState)(false);
3094
3678
  const isStreaming = status === "streaming" || status === "reconnecting";
3095
3679
  const isBusy = status === "submitted" || isStreaming;
3096
3680
  const isEmpty = messages.length === 0;
3097
- (0, import_react13.useEffect)(() => {
3681
+ (0, import_react16.useEffect)(() => {
3098
3682
  if (!isBusy) {
3099
3683
  setStopRequested(false);
3100
3684
  }
@@ -3111,7 +3695,7 @@ function useChatTranscript(options) {
3111
3695
  streamingMessageId,
3112
3696
  options
3113
3697
  });
3114
- const stop = (0, import_react13.useCallback)(() => {
3698
+ const stop = (0, import_react16.useCallback)(() => {
3115
3699
  const current = latest.current;
3116
3700
  if (current.status !== "submitted" && current.status !== "streaming" && current.status !== "reconnecting") {
3117
3701
  return;
@@ -3119,8 +3703,8 @@ function useChatTranscript(options) {
3119
3703
  setStopRequested(true);
3120
3704
  void current.onStop?.();
3121
3705
  }, []);
3122
- const loadEarlier = (0, import_react13.useCallback)(() => setVisibleCount((count) => count + (latest.current.loadEarlierStep ?? DEFAULT_LOAD_EARLIER_STEP)), []);
3123
- const showAll = (0, import_react13.useCallback)(() => setVisibleCount(latest.current.messages.length), []);
3706
+ const loadEarlier = (0, import_react16.useCallback)(() => setVisibleCount((count) => count + (latest.current.loadEarlierStep ?? DEFAULT_LOAD_EARLIER_STEP)), []);
3707
+ const showAll = (0, import_react16.useCallback)(() => setVisibleCount(latest.current.messages.length), []);
3124
3708
  const scroll = useStickToBottom({
3125
3709
  contentKey: contentSignature(messages),
3126
3710
  ...stickToBottomThreshold !== void 0 ? {
@@ -3156,7 +3740,7 @@ function useChatTranscript(options) {
3156
3740
  __name(useChatTranscript, "useChatTranscript");
3157
3741
  function useTranscriptItem(options) {
3158
3742
  const { message, isStreaming = false } = options;
3159
- const messagesRef = (0, import_react13.useRef)([
3743
+ const messagesRef = (0, import_react16.useRef)([
3160
3744
  message
3161
3745
  ]);
3162
3746
  if (messagesRef.current[0] !== message) {
@@ -3174,13 +3758,13 @@ function useTranscriptItem(options) {
3174
3758
  }
3175
3759
  __name(useTranscriptItem, "useTranscriptItem");
3176
3760
  function useTranscriptItems({ messages, visibleStart, streamingMessageId, options }) {
3177
- const [drafts, setDrafts] = (0, import_react13.useState)(() => /* @__PURE__ */ new Map());
3178
- const [copied, setCopied] = (0, import_react13.useState)(() => /* @__PURE__ */ new Set());
3179
- const [openReasoning, setOpenReasoning] = (0, import_react13.useState)(() => /* @__PURE__ */ new Map());
3180
- const [picks, setPicks] = (0, import_react13.useState)(() => /* @__PURE__ */ new Map());
3181
- const [settling, setSettling] = (0, import_react13.useState)(() => /* @__PURE__ */ new Map());
3182
- const [settleErrors, setSettleErrors] = (0, import_react13.useState)(() => /* @__PURE__ */ new Map());
3183
- const latest = (0, import_react13.useRef)({
3761
+ const [drafts, setDrafts] = (0, import_react16.useState)(() => /* @__PURE__ */ new Map());
3762
+ const [copied, setCopied] = (0, import_react16.useState)(() => /* @__PURE__ */ new Set());
3763
+ const [openReasoning, setOpenReasoning] = (0, import_react16.useState)(() => /* @__PURE__ */ new Map());
3764
+ const [picks, setPicks] = (0, import_react16.useState)(() => /* @__PURE__ */ new Map());
3765
+ const [settling, setSettling] = (0, import_react16.useState)(() => /* @__PURE__ */ new Map());
3766
+ const [settleErrors, setSettleErrors] = (0, import_react16.useState)(() => /* @__PURE__ */ new Map());
3767
+ const latest = (0, import_react16.useRef)({
3184
3768
  options,
3185
3769
  drafts,
3186
3770
  picks,
@@ -3192,23 +3776,23 @@ function useTranscriptItems({ messages, visibleStart, streamingMessageId, option
3192
3776
  picks,
3193
3777
  messages
3194
3778
  };
3195
- const copyTimers = (0, import_react13.useRef)(/* @__PURE__ */ new Map());
3196
- (0, import_react13.useEffect)(() => () => {
3779
+ const copyTimers = (0, import_react16.useRef)(/* @__PURE__ */ new Map());
3780
+ (0, import_react16.useEffect)(() => () => {
3197
3781
  for (const timer of copyTimers.current.values()) {
3198
3782
  clearTimeout(timer);
3199
3783
  }
3200
3784
  copyTimers.current.clear();
3201
3785
  }, []);
3202
- const callbackCache = (0, import_react13.useRef)(/* @__PURE__ */ new Map());
3203
- const reasoningToggleCache = (0, import_react13.useRef)(/* @__PURE__ */ new Map());
3204
- const toggleReasoning = (0, import_react13.useCallback)((key, open) => {
3786
+ const callbackCache = (0, import_react16.useRef)(/* @__PURE__ */ new Map());
3787
+ const reasoningToggleCache = (0, import_react16.useRef)(/* @__PURE__ */ new Map());
3788
+ const toggleReasoning = (0, import_react16.useCallback)((key, open) => {
3205
3789
  setOpenReasoning((current) => {
3206
3790
  const next = new Map(current);
3207
3791
  next.set(key, open ?? !(current.get(key) ?? false));
3208
3792
  return next;
3209
3793
  });
3210
3794
  }, []);
3211
- const stableToggle = (0, import_react13.useCallback)((key) => {
3795
+ const stableToggle = (0, import_react16.useCallback)((key) => {
3212
3796
  let cached = reasoningToggleCache.current.get(key);
3213
3797
  if (!cached) {
3214
3798
  cached = /* @__PURE__ */ __name((open) => toggleReasoning(key, open), "cached");
@@ -3218,10 +3802,10 @@ function useTranscriptItems({ messages, visibleStart, streamingMessageId, option
3218
3802
  }, [
3219
3803
  toggleReasoning
3220
3804
  ]);
3221
- const pick = (0, import_react13.useCallback)((toolCallId, questionId, values) => {
3805
+ const pick = (0, import_react16.useCallback)((toolCallId, questionId, values) => {
3222
3806
  setPicks((current) => new Map(current).set(pickKey(toolCallId, questionId), values));
3223
3807
  }, []);
3224
- const settle = (0, import_react13.useCallback)((toolCallId, action, send) => {
3808
+ const settle = (0, import_react16.useCallback)((toolCallId, action, send) => {
3225
3809
  setSettleErrors((current) => {
3226
3810
  if (!current.has(toolCallId)) {
3227
3811
  return current;
@@ -3245,7 +3829,7 @@ function useTranscriptItems({ messages, visibleStart, streamingMessageId, option
3245
3829
  failed(error);
3246
3830
  }
3247
3831
  }, []);
3248
- const answer = (0, import_react13.useCallback)((toolCallId) => {
3832
+ const answer = (0, import_react16.useCallback)((toolCallId) => {
3249
3833
  const current = latest.current;
3250
3834
  const onAnswer = current.options.onAnswer;
3251
3835
  if (!onAnswer) {
@@ -3255,7 +3839,7 @@ function useTranscriptItems({ messages, visibleStart, streamingMessageId, option
3255
3839
  }, [
3256
3840
  settle
3257
3841
  ]);
3258
- const skip = (0, import_react13.useCallback)((toolCallId) => {
3842
+ const skip = (0, import_react16.useCallback)((toolCallId) => {
3259
3843
  const onSkip = latest.current.options.onSkip;
3260
3844
  if (onSkip) {
3261
3845
  settle(toolCallId, "skip", () => onSkip(toolCallId));
@@ -3263,7 +3847,7 @@ function useTranscriptItems({ messages, visibleStart, streamingMessageId, option
3263
3847
  }, [
3264
3848
  settle
3265
3849
  ]);
3266
- const approve = (0, import_react13.useCallback)((toolCallId, options2) => {
3850
+ const approve = (0, import_react16.useCallback)((toolCallId, options2) => {
3267
3851
  const onApprove = latest.current.options.onApprove;
3268
3852
  if (onApprove) {
3269
3853
  settle(toolCallId, "approve", () => options2 === void 0 ? onApprove(toolCallId) : onApprove(toolCallId, options2));
@@ -3271,7 +3855,7 @@ function useTranscriptItems({ messages, visibleStart, streamingMessageId, option
3271
3855
  }, [
3272
3856
  settle
3273
3857
  ]);
3274
- const reject = (0, import_react13.useCallback)((toolCallId) => {
3858
+ const reject = (0, import_react16.useCallback)((toolCallId) => {
3275
3859
  const onReject = latest.current.options.onReject;
3276
3860
  if (onReject) {
3277
3861
  settle(toolCallId, "reject", () => onReject(toolCallId));
@@ -3279,7 +3863,7 @@ function useTranscriptItems({ messages, visibleStart, streamingMessageId, option
3279
3863
  }, [
3280
3864
  settle
3281
3865
  ]);
3282
- const callbacksFor = (0, import_react13.useCallback)((id) => {
3866
+ const callbacksFor = (0, import_react16.useCallback)((id) => {
3283
3867
  const cached = callbackCache.current.get(id);
3284
3868
  if (cached) {
3285
3869
  return cached;
@@ -3521,7 +4105,7 @@ function MessageItem({ message, isStreaming = false, editable, onEditSubmit, reg
3521
4105
  getCreatedAt: /* @__PURE__ */ __name(() => createdAt, "getCreatedAt")
3522
4106
  } : {}
3523
4107
  });
3524
- return /* @__PURE__ */ import_react14.default.createElement(MessageItemView, {
4108
+ return /* @__PURE__ */ import_react17.default.createElement(MessageItemView, {
3525
4109
  item,
3526
4110
  ...slots
3527
4111
  });
@@ -3534,51 +4118,51 @@ function MessageItemView({ item, ...given }) {
3534
4118
  renderUi: ambientRenderUi
3535
4119
  } : given;
3536
4120
  const { classNames } = slots;
3537
- const actionRow = /* @__PURE__ */ import_react14.default.createElement("div", {
4121
+ const actionRow = /* @__PURE__ */ import_react17.default.createElement("div", {
3538
4122
  className: classNames?.actions,
3539
4123
  "data-actions-for": item.role
3540
- }, item.copy.available ? /* @__PURE__ */ import_react14.default.createElement("button", {
4124
+ }, item.copy.available ? /* @__PURE__ */ import_react17.default.createElement("button", {
3541
4125
  type: "button",
3542
4126
  onClick: item.copy.copy,
3543
4127
  className: classNames?.actionButton,
3544
4128
  title: item.copy.copied ? "Copied!" : "Copy message text"
3545
- }, item.copy.copied ? "Copied" : "Copy") : null, item.fork.available ? /* @__PURE__ */ import_react14.default.createElement("button", {
4129
+ }, item.copy.copied ? "Copied" : "Copy") : null, item.fork.available ? /* @__PURE__ */ import_react17.default.createElement("button", {
3546
4130
  type: "button",
3547
4131
  onClick: item.fork.run,
3548
4132
  className: classNames?.actionButton,
3549
4133
  title: "Fork thread from this message"
3550
- }, "Fork") : null, item.regenerate.available ? /* @__PURE__ */ import_react14.default.createElement("button", {
4134
+ }, "Fork") : null, item.regenerate.available ? /* @__PURE__ */ import_react17.default.createElement("button", {
3551
4135
  type: "button",
3552
4136
  onClick: item.regenerate.run,
3553
4137
  className: classNames?.actionButton,
3554
4138
  title: "Regenerate response"
3555
- }, "Regenerate") : null, slots.meta, !item.isUser && item.usage ? /* @__PURE__ */ import_react14.default.createElement("span", {
4139
+ }, "Regenerate") : null, slots.meta, !item.isUser && item.usage ? /* @__PURE__ */ import_react17.default.createElement("span", {
3556
4140
  className: classNames?.usage,
3557
4141
  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__ */ import_react14.default.createElement("span", {
4142
+ }, item.usage.costLabel, " \xB7 ", item.usage.tokensLabel) : null, item.timestamp ? /* @__PURE__ */ import_react17.default.createElement("span", {
3559
4143
  className: classNames?.timestamp,
3560
4144
  title: item.timestamp.absolute
3561
4145
  }, item.timestamp.relative) : null);
3562
4146
  if (item.edit.available) {
3563
- return /* @__PURE__ */ import_react14.default.createElement(EditableUserBubble, {
4147
+ return /* @__PURE__ */ import_react17.default.createElement(EditableUserBubble, {
3564
4148
  item,
3565
4149
  slots,
3566
4150
  actions: actionRow
3567
4151
  });
3568
4152
  }
3569
4153
  const className = joinClasses(classNames?.root, classNames?.byRole?.[item.role]);
3570
- return /* @__PURE__ */ import_react14.default.createElement("div", {
4154
+ return /* @__PURE__ */ import_react17.default.createElement("div", {
3571
4155
  className,
3572
4156
  "data-role": item.role,
3573
4157
  "data-streaming": item.isStreaming ? "true" : void 0
3574
- }, /* @__PURE__ */ import_react14.default.createElement("div", null, renderBlocks(item, slots)), actionRow);
4158
+ }, /* @__PURE__ */ import_react17.default.createElement("div", null, renderBlocks(item, slots)), actionRow);
3575
4159
  }
3576
4160
  __name(MessageItemView, "MessageItemView");
3577
4161
  function renderBlocks(item, slots) {
3578
4162
  const nodes = [];
3579
4163
  for (const block of item.blocks) {
3580
4164
  if (block.kind === "text") {
3581
- nodes.push(/* @__PURE__ */ import_react14.default.createElement("div", {
4165
+ nodes.push(/* @__PURE__ */ import_react17.default.createElement("div", {
3582
4166
  key: block.key,
3583
4167
  className: slots.classNames?.text
3584
4168
  }, slots.renderText ? slots.renderText(block.text, {
@@ -3599,7 +4183,7 @@ function renderBlocks(item, slots) {
3599
4183
  continue;
3600
4184
  }
3601
4185
  if (block.kind === "ui" && slots.renderUi) {
3602
- nodes.push(/* @__PURE__ */ import_react14.default.createElement("div", {
4186
+ nodes.push(/* @__PURE__ */ import_react17.default.createElement("div", {
3603
4187
  key: block.key,
3604
4188
  "data-slot": "ui",
3605
4189
  "data-component": block.component
@@ -3610,18 +4194,18 @@ function renderBlocks(item, slots) {
3610
4194
  }
3611
4195
  __name(renderBlocks, "renderBlocks");
3612
4196
  function renderFilesBlock(block, slots) {
3613
- return /* @__PURE__ */ import_react14.default.createElement("div", {
4197
+ return /* @__PURE__ */ import_react17.default.createElement("div", {
3614
4198
  key: block.key,
3615
4199
  className: slots.classNames?.files,
3616
4200
  "data-files": "true"
3617
- }, slots.renderFiles ? slots.renderFiles(block.files) : block.files.map((file) => /* @__PURE__ */ import_react14.default.createElement("a", {
4201
+ }, slots.renderFiles ? slots.renderFiles(block.files) : block.files.map((file) => /* @__PURE__ */ import_react17.default.createElement("a", {
3618
4202
  key: file.url,
3619
4203
  href: file.url,
3620
4204
  target: "_blank",
3621
4205
  rel: "noreferrer",
3622
4206
  className: slots.classNames?.file,
3623
4207
  title: file.filename ?? file.mediaType
3624
- }, file.isImage ? /* @__PURE__ */ import_react14.default.createElement("img", {
4208
+ }, file.isImage ? /* @__PURE__ */ import_react17.default.createElement("img", {
3625
4209
  src: file.url,
3626
4210
  alt: file.filename ?? "image",
3627
4211
  className: slots.classNames?.fileImage
@@ -3629,17 +4213,17 @@ function renderFilesBlock(block, slots) {
3629
4213
  }
3630
4214
  __name(renderFilesBlock, "renderFilesBlock");
3631
4215
  function renderReasoningBlock(block, slots) {
3632
- return /* @__PURE__ */ import_react14.default.createElement("div", {
4216
+ return /* @__PURE__ */ import_react17.default.createElement("div", {
3633
4217
  key: block.key,
3634
4218
  className: slots.classNames?.reasoning,
3635
4219
  "data-reasoning": "true",
3636
4220
  "data-streaming": block.isStreaming ? "true" : void 0
3637
- }, /* @__PURE__ */ import_react14.default.createElement("button", {
4221
+ }, /* @__PURE__ */ import_react17.default.createElement("button", {
3638
4222
  type: "button",
3639
4223
  className: slots.classNames?.reasoningToggle,
3640
4224
  onClick: /* @__PURE__ */ __name(() => block.toggle(), "onClick"),
3641
4225
  "aria-expanded": block.isOpen
3642
- }, slots.reasoningLabel ?? "Reasoning"), block.isOpen ? /* @__PURE__ */ import_react14.default.createElement("div", {
4226
+ }, slots.reasoningLabel ?? "Reasoning"), block.isOpen ? /* @__PURE__ */ import_react17.default.createElement("div", {
3643
4227
  className: slots.classNames?.reasoningText
3644
4228
  }, slots.renderReasoning ? slots.renderReasoning(block.text, {
3645
4229
  isStreaming: block.isStreaming,
@@ -3650,7 +4234,7 @@ __name(renderReasoningBlock, "renderReasoningBlock");
3650
4234
  function renderToolBlock(item, block, slots) {
3651
4235
  if (slots.renderToolGroup) {
3652
4236
  return [
3653
- /* @__PURE__ */ import_react14.default.createElement(import_react14.default.Fragment, {
4237
+ /* @__PURE__ */ import_react17.default.createElement(import_react17.default.Fragment, {
3654
4238
  key: block.key
3655
4239
  }, slots.renderToolGroup(block.parts, block.key))
3656
4240
  ];
@@ -3661,7 +4245,7 @@ function renderToolBlock(item, block, slots) {
3661
4245
  const renderToolPart = slots.renderToolPart;
3662
4246
  return block.parts.map((part) => {
3663
4247
  const partKey = `${item.id}-${part.toolCallId}`;
3664
- return /* @__PURE__ */ import_react14.default.createElement(import_react14.default.Fragment, {
4248
+ return /* @__PURE__ */ import_react17.default.createElement(import_react17.default.Fragment, {
3665
4249
  key: partKey
3666
4250
  }, renderToolPart(part, partKey));
3667
4251
  });
@@ -3671,14 +4255,14 @@ function EditableUserBubble({ item, slots, actions }) {
3671
4255
  const { classNames } = slots;
3672
4256
  const { edit } = item;
3673
4257
  if (!edit.isEditing) {
3674
- return /* @__PURE__ */ import_react14.default.createElement("div", {
4258
+ return /* @__PURE__ */ import_react17.default.createElement("div", {
3675
4259
  className: joinClasses(classNames?.root, classNames?.byRole?.user),
3676
4260
  "data-role": "user"
3677
- }, /* @__PURE__ */ import_react14.default.createElement("div", {
4261
+ }, /* @__PURE__ */ import_react17.default.createElement("div", {
3678
4262
  className: classNames?.text
3679
4263
  }, slots.renderText ? slots.renderText(item.text, {
3680
4264
  isStreaming: false
3681
- }) : item.text), /* @__PURE__ */ import_react14.default.createElement("button", {
4265
+ }) : item.text), /* @__PURE__ */ import_react17.default.createElement("button", {
3682
4266
  type: "button",
3683
4267
  onClick: edit.start,
3684
4268
  className: classNames?.actionButton,
@@ -3686,18 +4270,18 @@ function EditableUserBubble({ item, slots, actions }) {
3686
4270
  }, "Edit"), actions);
3687
4271
  }
3688
4272
  const textareaProps = edit.getTextareaProps();
3689
- return /* @__PURE__ */ import_react14.default.createElement("div", {
4273
+ return /* @__PURE__ */ import_react17.default.createElement("div", {
3690
4274
  "data-editing": "true"
3691
- }, /* @__PURE__ */ import_react14.default.createElement("textarea", {
4275
+ }, /* @__PURE__ */ import_react17.default.createElement("textarea", {
3692
4276
  ...textareaProps,
3693
4277
  rows: Math.min(8, edit.draft.split("\n").length + 1),
3694
4278
  className: classNames?.editTextarea
3695
- }), /* @__PURE__ */ import_react14.default.createElement("div", {
4279
+ }), /* @__PURE__ */ import_react17.default.createElement("div", {
3696
4280
  className: classNames?.editActions
3697
- }, /* @__PURE__ */ import_react14.default.createElement("button", {
4281
+ }, /* @__PURE__ */ import_react17.default.createElement("button", {
3698
4282
  type: "button",
3699
4283
  onClick: edit.cancel
3700
- }, "Cancel"), /* @__PURE__ */ import_react14.default.createElement("button", {
4284
+ }, "Cancel"), /* @__PURE__ */ import_react17.default.createElement("button", {
3701
4285
  type: "button",
3702
4286
  onClick: edit.save,
3703
4287
  disabled: !edit.canSave
@@ -3907,11 +4491,11 @@ function createSkillsSource(options) {
3907
4491
  if (cached) {
3908
4492
  return cached;
3909
4493
  }
3910
- const listSkills = options.client.listSkills;
4494
+ const listSkills = options.backend.listSkills;
3911
4495
  if (listSkills === void 0) {
3912
4496
  return Promise.reject(new AgentBackendUnsupportedError("listSkills"));
3913
4497
  }
3914
- const pending = listSkills.call(options.client, threadId).then((entries) => entries.map(toItem)).catch((error) => {
4498
+ const pending = listSkills.call(options.backend, threadId).then((entries) => entries.map(toItem)).catch((error) => {
3915
4499
  byThread.delete(key);
3916
4500
  throw error;
3917
4501
  });
@@ -3941,35 +4525,35 @@ function toItem(entry) {
3941
4525
  __name(toItem, "toItem");
3942
4526
 
3943
4527
  // src/composer/use-composer-autocomplete.ts
3944
- var import_react15 = require("react");
4528
+ var import_react18 = require("react");
3945
4529
  function useComposerAutocomplete(options) {
3946
4530
  const { value, sources, acceptOnTab = true } = options;
3947
- const latest = (0, import_react15.useRef)(options);
4531
+ const latest = (0, import_react18.useRef)(options);
3948
4532
  latest.current = options;
3949
- const inputRef = (0, import_react15.useRef)(null);
3950
- const [caret, setCaret] = (0, import_react15.useState)(value.length);
3951
- const [items, setItems] = (0, import_react15.useState)([]);
3952
- const [isLoading, setLoading] = (0, import_react15.useState)(false);
3953
- const [error, setError] = (0, import_react15.useState)(null);
3954
- const [activeIndex, setActiveIndex] = (0, import_react15.useState)(0);
3955
- const [dismissedIndex, setDismissedIndex] = (0, import_react15.useState)(null);
4533
+ const inputRef = (0, import_react18.useRef)(null);
4534
+ const [caret, setCaret] = (0, import_react18.useState)(value.length);
4535
+ const [items, setItems] = (0, import_react18.useState)([]);
4536
+ const [isLoading, setLoading] = (0, import_react18.useState)(false);
4537
+ const [error, setError] = (0, import_react18.useState)(null);
4538
+ const [activeIndex, setActiveIndex] = (0, import_react18.useState)(0);
4539
+ const [dismissedIndex, setDismissedIndex] = (0, import_react18.useState)(null);
3956
4540
  const safeCaret = Math.min(caret, value.length);
3957
- const match = (0, import_react15.useMemo)(() => findActiveTrigger(value, safeCaret, sources), [
4541
+ const match = (0, import_react18.useMemo)(() => findActiveTrigger(value, safeCaret, sources), [
3958
4542
  value,
3959
4543
  safeCaret,
3960
4544
  sources
3961
4545
  ]);
3962
4546
  const isActive = match !== null && dismissedIndex !== match.index;
3963
- const matchRef = (0, import_react15.useRef)(match);
4547
+ const matchRef = (0, import_react18.useRef)(match);
3964
4548
  matchRef.current = match;
3965
- const caretRef = (0, import_react15.useRef)(safeCaret);
4549
+ const caretRef = (0, import_react18.useRef)(safeCaret);
3966
4550
  caretRef.current = safeCaret;
3967
- const itemsRef = (0, import_react15.useRef)(items);
4551
+ const itemsRef = (0, import_react18.useRef)(items);
3968
4552
  itemsRef.current = items;
3969
- const activeIndexRef = (0, import_react15.useRef)(activeIndex);
4553
+ const activeIndexRef = (0, import_react18.useRef)(activeIndex);
3970
4554
  activeIndexRef.current = activeIndex;
3971
4555
  const requestKey = isActive && match ? `${match.source.id}\0${match.query}` : null;
3972
- (0, import_react15.useEffect)(() => {
4556
+ (0, import_react18.useEffect)(() => {
3973
4557
  const current = matchRef.current;
3974
4558
  if (requestKey === null || current === null) {
3975
4559
  setItems([]);
@@ -4017,25 +4601,25 @@ function useComposerAutocomplete(options) {
4017
4601
  ]);
4018
4602
  const isOpen = isActive;
4019
4603
  const activeItem = isOpen ? items[activeIndex] ?? null : null;
4020
- const reactId = (0, import_react15.useId)();
4604
+ const reactId = (0, import_react18.useId)();
4021
4605
  const listboxId = options.id ?? `agent-autocomplete-${reactId}`;
4022
- const optionId = (0, import_react15.useCallback)((index) => `${listboxId}-option-${index}`, [
4606
+ const optionId = (0, import_react18.useCallback)((index) => `${listboxId}-option-${index}`, [
4023
4607
  listboxId
4024
4608
  ]);
4025
- const highlight = (0, import_react15.useCallback)((index) => {
4609
+ const highlight = (0, import_react18.useCallback)((index) => {
4026
4610
  const total = itemsRef.current.length;
4027
4611
  if (total === 0) return;
4028
4612
  setActiveIndex((index % total + total) % total);
4029
4613
  }, []);
4030
- const moveHighlight = (0, import_react15.useCallback)((delta) => highlight(activeIndexRef.current + delta), [
4614
+ const moveHighlight = (0, import_react18.useCallback)((delta) => highlight(activeIndexRef.current + delta), [
4031
4615
  highlight
4032
4616
  ]);
4033
- const dismiss = (0, import_react15.useCallback)(() => {
4617
+ const dismiss = (0, import_react18.useCallback)(() => {
4034
4618
  const current = matchRef.current;
4035
4619
  if (current) setDismissedIndex(current.index);
4036
4620
  }, []);
4037
- const pendingCaret = (0, import_react15.useRef)(null);
4038
- const accept = (0, import_react15.useCallback)((item) => {
4621
+ const pendingCaret = (0, import_react18.useRef)(null);
4622
+ const accept = (0, import_react18.useCallback)((item) => {
4039
4623
  const current = matchRef.current;
4040
4624
  if (!current) return;
4041
4625
  const chosen = item ?? itemsRef.current[activeIndexRef.current];
@@ -4046,16 +4630,16 @@ function useComposerAutocomplete(options) {
4046
4630
  setDismissedIndex(null);
4047
4631
  pendingCaret.current = edit.caret;
4048
4632
  }, []);
4049
- (0, import_react15.useLayoutEffect)(() => {
4633
+ (0, import_react18.useLayoutEffect)(() => {
4050
4634
  const position = pendingCaret.current;
4051
4635
  if (position === null) return;
4052
4636
  pendingCaret.current = null;
4053
4637
  inputRef.current?.setSelectionRange(position, position);
4054
4638
  });
4055
- const readCaret = (0, import_react15.useCallback)((element) => {
4639
+ const readCaret = (0, import_react18.useCallback)((element) => {
4056
4640
  setCaret(element.selectionStart ?? element.value.length);
4057
4641
  }, []);
4058
- const onKeyDown = (0, import_react15.useCallback)((event) => {
4642
+ const onKeyDown = (0, import_react18.useCallback)((event) => {
4059
4643
  if (!isOpen) return;
4060
4644
  const hasItems = itemsRef.current.length > 0;
4061
4645
  switch (event.key) {
@@ -4093,23 +4677,23 @@ function useComposerAutocomplete(options) {
4093
4677
  dismiss,
4094
4678
  moveHighlight
4095
4679
  ]);
4096
- const onChange = (0, import_react15.useCallback)((event) => {
4680
+ const onChange = (0, import_react18.useCallback)((event) => {
4097
4681
  readCaret(event.target);
4098
4682
  const next = findActiveTrigger(event.target.value, event.target.selectionStart ?? event.target.value.length, latest.current.sources);
4099
4683
  setDismissedIndex((current) => current !== null && next?.index === current ? current : null);
4100
4684
  }, [
4101
4685
  readCaret
4102
4686
  ]);
4103
- const onSelect = (0, import_react15.useCallback)((event) => readCaret(event.currentTarget), [
4687
+ const onSelect = (0, import_react18.useCallback)((event) => readCaret(event.currentTarget), [
4104
4688
  readCaret
4105
4689
  ]);
4106
- const onClick = (0, import_react15.useCallback)((event) => readCaret(event.currentTarget), [
4690
+ const onClick = (0, import_react18.useCallback)((event) => readCaret(event.currentTarget), [
4107
4691
  readCaret
4108
4692
  ]);
4109
- const setInput = (0, import_react15.useCallback)((element) => {
4693
+ const setInput = (0, import_react18.useCallback)((element) => {
4110
4694
  inputRef.current = element;
4111
4695
  }, []);
4112
- const getInputProps = (0, import_react15.useCallback)(() => ({
4696
+ const getInputProps = (0, import_react18.useCallback)(() => ({
4113
4697
  ref: setInput,
4114
4698
  onChange,
4115
4699
  onKeyDown,
@@ -4137,7 +4721,7 @@ function useComposerAutocomplete(options) {
4137
4721
  activeIndex,
4138
4722
  optionId
4139
4723
  ]);
4140
- const getListboxProps = (0, import_react15.useCallback)(() => ({
4724
+ const getListboxProps = (0, import_react18.useCallback)(() => ({
4141
4725
  id: listboxId,
4142
4726
  role: "listbox",
4143
4727
  "aria-label": match?.source.label ?? match?.source.id ?? "Suggestions"
@@ -4145,7 +4729,7 @@ function useComposerAutocomplete(options) {
4145
4729
  listboxId,
4146
4730
  match
4147
4731
  ]);
4148
- const getOptionProps = (0, import_react15.useCallback)((index) => ({
4732
+ const getOptionProps = (0, import_react18.useCallback)((index) => ({
4149
4733
  id: optionId(index),
4150
4734
  role: "option",
4151
4735
  "aria-selected": index === activeIndex
@@ -4179,7 +4763,7 @@ function isPromise(value) {
4179
4763
  __name(isPromise, "isPromise");
4180
4764
 
4181
4765
  // src/presentation/use-tool-catalog.ts
4182
- var import_react16 = require("react");
4766
+ var import_react19 = require("react");
4183
4767
  var shared = /* @__PURE__ */ new WeakMap();
4184
4768
  function load(client, agent) {
4185
4769
  let byAgent = shared.get(client);
@@ -4201,13 +4785,14 @@ function load(client, agent) {
4201
4785
  return request;
4202
4786
  }
4203
4787
  __name(load, "load");
4204
- function useToolCatalog(options) {
4205
- const { client, agent, enabled = true } = options;
4206
- const [entries, setEntries] = (0, import_react16.useState)([]);
4207
- const [isLoading, setLoading] = (0, import_react16.useState)(enabled);
4208
- const [error, setError] = (0, import_react16.useState)(null);
4209
- const [generation, setGeneration] = (0, import_react16.useState)(0);
4210
- (0, import_react16.useEffect)(() => {
4788
+ function useToolCatalog(options = {}) {
4789
+ const { agent, enabled = true } = options;
4790
+ const client = useAgentBackend(options.backend);
4791
+ const [entries, setEntries] = (0, import_react19.useState)([]);
4792
+ const [isLoading, setLoading] = (0, import_react19.useState)(enabled);
4793
+ const [error, setError] = (0, import_react19.useState)(null);
4794
+ const [generation, setGeneration] = (0, import_react19.useState)(0);
4795
+ (0, import_react19.useEffect)(() => {
4211
4796
  if (!enabled) {
4212
4797
  setLoading(false);
4213
4798
  return;
@@ -4233,14 +4818,14 @@ function useToolCatalog(options) {
4233
4818
  enabled,
4234
4819
  generation
4235
4820
  ]);
4236
- const refresh = (0, import_react16.useCallback)(() => {
4821
+ const refresh = (0, import_react19.useCallback)(() => {
4237
4822
  shared.get(client)?.delete(agent ?? "");
4238
4823
  setGeneration((current) => current + 1);
4239
4824
  }, [
4240
4825
  client,
4241
4826
  agent
4242
4827
  ]);
4243
- const catalog = (0, import_react16.useMemo)(() => toolCatalogFrom(entries), [
4828
+ const catalog = (0, import_react19.useMemo)(() => toolCatalogFrom(entries), [
4244
4829
  entries
4245
4830
  ]);
4246
4831
  return {
@@ -4254,7 +4839,7 @@ function useToolCatalog(options) {
4254
4839
  __name(useToolCatalog, "useToolCatalog");
4255
4840
 
4256
4841
  // src/approvals/countdown.ts
4257
- var import_react17 = require("react");
4842
+ var import_react20 = require("react");
4258
4843
  function approvalCountdown(expiresAt, now = Date.now()) {
4259
4844
  const deadline = expiresAt == null ? Number.NaN : Date.parse(expiresAt);
4260
4845
  if (!Number.isFinite(deadline)) {
@@ -4272,10 +4857,10 @@ function approvalCountdown(expiresAt, now = Date.now()) {
4272
4857
  __name(approvalCountdown, "approvalCountdown");
4273
4858
  function useApprovalCountdown(expiresAt, options = {}) {
4274
4859
  const { intervalMs = 1e3 } = options;
4275
- const nowRef = (0, import_react17.useRef)(options.now ?? Date.now);
4860
+ const nowRef = (0, import_react20.useRef)(options.now ?? Date.now);
4276
4861
  nowRef.current = options.now ?? Date.now;
4277
- const [state, setState] = (0, import_react17.useState)(() => approvalCountdown(expiresAt, nowRef.current()));
4278
- (0, import_react17.useEffect)(() => {
4862
+ const [state, setState] = (0, import_react20.useState)(() => approvalCountdown(expiresAt, nowRef.current()));
4863
+ (0, import_react20.useEffect)(() => {
4279
4864
  const read = /* @__PURE__ */ __name(() => approvalCountdown(expiresAt, nowRef.current()), "read");
4280
4865
  const first = read();
4281
4866
  setState(first);
@@ -4522,44 +5107,27 @@ function sumUsage(rows) {
4522
5107
  __name(sumUsage, "sumUsage");
4523
5108
 
4524
5109
  // src/use-agent-chat.ts
4525
- var import_react18 = require("@ai-sdk/react");
4526
- var import_react19 = require("react");
4527
- function useAgentChat(options) {
4528
- const latest = (0, import_react19.useRef)(options);
5110
+ var import_react21 = require("@ai-sdk/react");
5111
+ var import_react22 = require("react");
5112
+ function useAgentChat(options = {}) {
5113
+ const latest = (0, import_react22.useRef)(options);
4529
5114
  latest.current = options;
4530
- const [runId, setRunId] = (0, import_react19.useState)(options.resumeRunId);
4531
- const runIdRef = (0, import_react19.useRef)(runId);
5115
+ const [runId, setRunId] = (0, import_react22.useState)(options.resumeRunId);
5116
+ const runIdRef = (0, import_react22.useRef)(runId);
4532
5117
  runIdRef.current = runId;
4533
- const settlingRunIdRef = (0, import_react19.useRef)(void 0);
4534
- const autoResumeRunIdRef = (0, import_react19.useRef)(void 0);
4535
- const [autoResume, setAutoResume] = (0, import_react19.useState)(false);
4536
- const [activeRunId, setActiveRunId] = (0, import_react19.useState)(null);
4537
- const regenerateNext = (0, import_react19.useRef)(false);
4538
- const createdThreadId = (0, import_react19.useRef)(void 0);
4539
- const client = (0, import_react19.useMemo)(() => {
4540
- if (options.backend) return options.backend;
4541
- if (options.client) return options.client;
4542
- return new AgentClient({
4543
- ...options.baseUrl !== void 0 ? {
4544
- baseUrl: options.baseUrl
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)({
5118
+ const settlingRunIdRef = (0, import_react22.useRef)(void 0);
5119
+ const autoResumeRunIdRef = (0, import_react22.useRef)(void 0);
5120
+ const [autoResume, setAutoResume] = (0, import_react22.useState)(false);
5121
+ const [activeRunId, setActiveRunId] = (0, import_react22.useState)(null);
5122
+ const regenerateNext = (0, import_react22.useRef)(false);
5123
+ const createdThreadId = (0, import_react22.useRef)(void 0);
5124
+ const resolved = useAgentBackend(options.backend);
5125
+ const client = (0, import_react22.useRef)(resolved).current;
5126
+ const [connection, setConnection] = (0, import_react22.useState)({
4559
5127
  status: "live"
4560
5128
  });
4561
- const resyncAfterSettle = (0, import_react19.useRef)(false);
4562
- (0, import_react19.useEffect)(() => {
5129
+ const resyncAfterSettle = (0, import_react22.useRef)(false);
5130
+ (0, import_react22.useEffect)(() => {
4563
5131
  if (!options.resume || options.threadId === void 0) return;
4564
5132
  let cancelled = false;
4565
5133
  const threadId = options.threadId;
@@ -4579,7 +5147,7 @@ function useAgentChat(options) {
4579
5147
  options.resume,
4580
5148
  options.threadId
4581
5149
  ]);
4582
- const transport = (0, import_react19.useMemo)(() => {
5150
+ const transport = (0, import_react22.useMemo)(() => {
4583
5151
  function onMeta(meta) {
4584
5152
  settlingRunIdRef.current = meta.runId;
4585
5153
  setRunId(meta.runId);
@@ -4634,8 +5202,8 @@ function useAgentChat(options) {
4634
5202
  }, "onAttemptStart")
4635
5203
  });
4636
5204
  }, []);
4637
- const backgroundRef = (0, import_react19.useRef)(() => Promise.resolve());
4638
- const chat = (0, import_react18.useChat)({
5205
+ const backgroundRef = (0, import_react22.useRef)(() => Promise.resolve());
5206
+ const chat = (0, import_react21.useChat)({
4639
5207
  transport,
4640
5208
  resume: options.resumeRunId !== void 0 || autoResume,
4641
5209
  ...options.threadId !== void 0 ? {
@@ -4683,7 +5251,7 @@ function useAgentChat(options) {
4683
5251
  }
4684
5252
  }, "onFinish")
4685
5253
  });
4686
- const chatRef = (0, import_react19.useRef)(chat);
5254
+ const chatRef = (0, import_react22.useRef)(chat);
4687
5255
  chatRef.current = chat;
4688
5256
  async function resyncFromThread() {
4689
5257
  const threadId = latest.current.threadId ?? createdThreadId.current;
@@ -4695,11 +5263,11 @@ function useAgentChat(options) {
4695
5263
  }
4696
5264
  }
4697
5265
  __name(resyncFromThread, "resyncFromThread");
4698
- const turnInFlight = (0, import_react19.useRef)(false);
4699
- const isTurnInFlight = (0, import_react19.useCallback)(() => turnInFlight.current || transport.isAttemptLive, [
5266
+ const turnInFlight = (0, import_react22.useRef)(false);
5267
+ const isTurnInFlight = (0, import_react22.useCallback)(() => turnInFlight.current || transport.isAttemptLive, [
4700
5268
  transport
4701
5269
  ]);
4702
- const sendMessage = (0, import_react19.useCallback)(async (...args) => {
5270
+ const sendMessage = (0, import_react22.useCallback)(async (...args) => {
4703
5271
  const blocked = latest.current.blocked;
4704
5272
  if (blocked != null) throw new QuotaBlockedError(blocked);
4705
5273
  if (isTurnInFlight()) return;
@@ -4712,15 +5280,15 @@ function useAgentChat(options) {
4712
5280
  }, [
4713
5281
  isTurnInFlight
4714
5282
  ]);
4715
- const addToolResult = (0, import_react19.useCallback)(({ tool, toolCallId, output }) => chatRef.current.addToolResult({
5283
+ const addToolResult = (0, import_react22.useCallback)(({ tool, toolCallId, output }) => chatRef.current.addToolResult({
4716
5284
  tool,
4717
5285
  toolCallId,
4718
5286
  output
4719
5287
  }), []);
4720
- const [threads, setThreads] = (0, import_react19.useState)([]);
4721
- const [quota, setQuota] = (0, import_react19.useState)(null);
4722
- const [backgroundRuns, setBackgroundRuns] = (0, import_react19.useState)([]);
4723
- const refreshBackground = (0, import_react19.useCallback)(async () => {
5288
+ const [threads, setThreads] = (0, import_react22.useState)([]);
5289
+ const [quota, setQuota] = (0, import_react22.useState)(null);
5290
+ const [backgroundRuns, setBackgroundRuns] = (0, import_react22.useState)([]);
5291
+ const refreshBackground = (0, import_react22.useCallback)(async () => {
4724
5292
  const threadId = latest.current.threadId ?? createdThreadId.current;
4725
5293
  if (threadId === void 0) {
4726
5294
  return;
@@ -4745,7 +5313,7 @@ function useAgentChat(options) {
4745
5313
  ]);
4746
5314
  backgroundRef.current = refreshBackground;
4747
5315
  const isWorking = backgroundRuns.some((run) => run.status === "running");
4748
- (0, import_react19.useEffect)(() => {
5316
+ (0, import_react22.useEffect)(() => {
4749
5317
  if (options.background !== true || options.threadId === void 0) {
4750
5318
  return;
4751
5319
  }
@@ -4755,7 +5323,7 @@ function useAgentChat(options) {
4755
5323
  options.threadId,
4756
5324
  refreshBackground
4757
5325
  ]);
4758
- (0, import_react19.useEffect)(() => {
5326
+ (0, import_react22.useEffect)(() => {
4759
5327
  const every = latest.current.backgroundPollMs ?? 5e3;
4760
5328
  if (latest.current.background !== true || !isWorking || every <= 0) {
4761
5329
  return;
@@ -4766,26 +5334,26 @@ function useAgentChat(options) {
4766
5334
  isWorking,
4767
5335
  refreshBackground
4768
5336
  ]);
4769
- const loadThreads = (0, import_react19.useCallback)(async () => {
5337
+ const loadThreads = (0, import_react22.useCallback)(async () => {
4770
5338
  const list = await client.listThreads();
4771
5339
  setThreads(list);
4772
5340
  return list;
4773
5341
  }, [
4774
5342
  client
4775
5343
  ]);
4776
- const loadThread = (0, import_react19.useCallback)((id) => client.getThread(id), [
5344
+ const loadThread = (0, import_react22.useCallback)((id) => client.getThread(id), [
4777
5345
  client
4778
5346
  ]);
4779
- const deleteThread = (0, import_react19.useCallback)(async (id) => {
5347
+ const deleteThread = (0, import_react22.useCallback)(async (id) => {
4780
5348
  await client.deleteThread(id);
4781
5349
  setThreads((current) => current.filter((thread) => thread.id !== id));
4782
5350
  }, [
4783
5351
  client
4784
5352
  ]);
4785
- const forkThread = (0, import_react19.useCallback)((threadId, messageId) => requireBackendMethod(client, "forkFromMessage")(threadId, messageId), [
5353
+ const forkThread = (0, import_react22.useCallback)((threadId, messageId) => requireBackendMethod(client, "forkFromMessage")(threadId, messageId), [
4786
5354
  client
4787
5355
  ]);
4788
- const renameThread = (0, import_react19.useCallback)(async (id, title) => {
5356
+ const renameThread = (0, import_react22.useCallback)(async (id, title) => {
4789
5357
  await client.updateThread(id, {
4790
5358
  title
4791
5359
  });
@@ -4796,24 +5364,24 @@ function useAgentChat(options) {
4796
5364
  }, [
4797
5365
  client
4798
5366
  ]);
4799
- const promoteThread = (0, import_react19.useCallback)(async (id) => {
5367
+ const promoteThread = (0, import_react22.useCallback)(async (id) => {
4800
5368
  await requireBackendMethod(client, "promoteThread")(id);
4801
5369
  await loadThreads();
4802
5370
  }, [
4803
5371
  client,
4804
5372
  loadThreads
4805
5373
  ]);
4806
- const truncateFromMessage = (0, import_react19.useCallback)((threadId, messageId) => requireBackendMethod(client, "truncateFromMessage")(threadId, messageId).then(() => void 0), [
5374
+ const truncateFromMessage = (0, import_react22.useCallback)((threadId, messageId) => requireBackendMethod(client, "truncateFromMessage")(threadId, messageId).then(() => void 0), [
4807
5375
  client
4808
5376
  ]);
4809
- const loadQuota = (0, import_react19.useCallback)(async () => {
5377
+ const loadQuota = (0, import_react22.useCallback)(async () => {
4810
5378
  const today = await requireBackendMethod(client, "getQuotaToday")();
4811
5379
  setQuota(today);
4812
5380
  return today;
4813
5381
  }, [
4814
5382
  client
4815
5383
  ]);
4816
- const cancel = (0, import_react19.useCallback)(async () => {
5384
+ const cancel = (0, import_react22.useCallback)(async () => {
4817
5385
  chatRef.current.stop();
4818
5386
  const activeRunId2 = runIdRef.current;
4819
5387
  if (activeRunId2) {
@@ -4825,7 +5393,7 @@ function useAgentChat(options) {
4825
5393
  }, [
4826
5394
  client
4827
5395
  ]);
4828
- const approve = (0, import_react19.useCallback)(async ({ toolCallId, remember, via }) => {
5396
+ const approve = (0, import_react22.useCallback)(async ({ toolCallId, remember, via }) => {
4829
5397
  await requireBackendMethod(client, "approveToolCall")({
4830
5398
  toolCallId,
4831
5399
  ...remember === true ? {
@@ -4838,7 +5406,7 @@ function useAgentChat(options) {
4838
5406
  }, [
4839
5407
  client
4840
5408
  ]);
4841
- const reject = (0, import_react19.useCallback)(async ({ toolCallId, reason, via }) => {
5409
+ const reject = (0, import_react22.useCallback)(async ({ toolCallId, reason, via }) => {
4842
5410
  await requireBackendMethod(client, "rejectToolCall")({
4843
5411
  toolCallId,
4844
5412
  ...reason !== void 0 ? {
@@ -4851,7 +5419,7 @@ function useAgentChat(options) {
4851
5419
  }, [
4852
5420
  client
4853
5421
  ]);
4854
- const answer = (0, import_react19.useCallback)(async ({ toolCallId, answers }) => {
5422
+ const answer = (0, import_react22.useCallback)(async ({ toolCallId, answers }) => {
4855
5423
  await requireBackendMethod(client, "answerToolCall")({
4856
5424
  toolCallId,
4857
5425
  ...answers !== void 0 ? {
@@ -4861,14 +5429,14 @@ function useAgentChat(options) {
4861
5429
  }, [
4862
5430
  client
4863
5431
  ]);
4864
- const skip = (0, import_react19.useCallback)(async ({ toolCallId }) => {
5432
+ const skip = (0, import_react22.useCallback)(async ({ toolCallId }) => {
4865
5433
  await requireBackendMethod(client, "skipToolCall")({
4866
5434
  toolCallId
4867
5435
  });
4868
5436
  }, [
4869
5437
  client
4870
5438
  ]);
4871
- const regenerate = (0, import_react19.useCallback)(() => {
5439
+ const regenerate = (0, import_react22.useCallback)(() => {
4872
5440
  const blocked = latest.current.blocked;
4873
5441
  if (blocked != null) throw new QuotaBlockedError(blocked);
4874
5442
  if (isTurnInFlight()) return;
@@ -4885,7 +5453,7 @@ function useAgentChat(options) {
4885
5453
  isWorking,
4886
5454
  refresh: refreshBackground
4887
5455
  };
4888
- const setThreadModel = (0, import_react19.useCallback)(async (model) => {
5456
+ const setThreadModel = (0, import_react22.useCallback)(async (model) => {
4889
5457
  const threadId = latest.current.threadId ?? createdThreadId.current;
4890
5458
  if (threadId === void 0) {
4891
5459
  throw new Error("setThreadModel: this chat has no thread yet");
@@ -4899,7 +5467,7 @@ function useAgentChat(options) {
4899
5467
  }, [
4900
5468
  client
4901
5469
  ]);
4902
- const getThreadId = (0, import_react19.useCallback)(() => latest.current.threadId ?? createdThreadId.current, []);
5470
+ const getThreadId = (0, import_react22.useCallback)(() => latest.current.threadId ?? createdThreadId.current, []);
4903
5471
  const status = connection.status === "reconnecting" ? "reconnecting" : chat.status;
4904
5472
  return {
4905
5473
  ...chat,
@@ -4919,10 +5487,8 @@ function useAgentChat(options) {
4919
5487
  */
4920
5488
  getThreadId,
4921
5489
  setThreadModel,
4922
- /** The backend this chat talks to — pass it to `useThreads`, `useMessageFeedback`, … */
5490
+ /** The backend this chat talks to — the same one every other hook under the provider uses. */
4923
5491
  backend: client,
4924
- /** Same object as {@link backend}; kept for callers that read it under its old name. */
4925
- client,
4926
5492
  threads,
4927
5493
  loadThreads,
4928
5494
  loadThread,
@@ -4952,20 +5518,13 @@ var QuotaBlockedError = class extends Error {
4952
5518
  this.name = "QuotaBlockedError";
4953
5519
  }
4954
5520
  };
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
5521
  // Annotate the CommonJS export names for ESM import in node:
4964
5522
  0 && (module.exports = {
4965
5523
  AgentBackendUnsupportedError,
4966
5524
  AgentChatTransport,
4967
5525
  AgentClient,
4968
5526
  AgentHttpError,
5527
+ AgentProvider,
4969
5528
  AmbientRenderUiContext,
4970
5529
  ChatInput,
4971
5530
  DEFAULT_SPEECH_LANG,
@@ -5011,6 +5570,7 @@ __name(mergeHeaders, "mergeHeaders");
5011
5570
  storedThreadToUiMessages,
5012
5571
  toolCallState,
5013
5572
  toolCatalogFrom,
5573
+ useAgentBackend,
5014
5574
  useAgentChat,
5015
5575
  useAgents,
5016
5576
  useAmbientRenderUi,