@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.js CHANGED
@@ -14,6 +14,11 @@ var AgentHttpError = class extends Error {
14
14
  this.name = "AgentHttpError";
15
15
  }
16
16
  };
17
+ function normalizeAgentPath(path) {
18
+ const trimmed = (path ?? "agent").replace(/^\/+|\/+$/g, "");
19
+ return trimmed === "" ? "" : `/${trimmed}`;
20
+ }
21
+ __name(normalizeAgentPath, "normalizeAgentPath");
17
22
  var HEADER_RUN_ID = "x-agent-run-id";
18
23
  var HEADER_THREAD_ID = "x-agent-thread-id";
19
24
  var AgentClient = class {
@@ -24,9 +29,9 @@ var AgentClient = class {
24
29
  constructor(options = {}) {
25
30
  this.options = options;
26
31
  }
27
- /** `POST /agent/chat` → the turn's SSE stream. Throws {@link AgentHttpError} on a non-2xx. */
32
+ /** `POST <path>/chat` → the turn's SSE stream. Throws {@link AgentHttpError} on a non-2xx. */
28
33
  async openChatStream(request) {
29
- const response = await this.fetchImpl()(`${this.baseUrl()}/agent/chat`, {
34
+ const response = await this.fetchImpl()(`${this.root()}/chat`, {
30
35
  method: "POST",
31
36
  headers: {
32
37
  "content-type": "application/json",
@@ -41,18 +46,18 @@ var AgentClient = class {
41
46
  } : {}
42
47
  });
43
48
  if (!response.ok || !response.body) {
44
- throw new AgentHttpError(response.status, "POST", "/agent/chat", response.statusText);
49
+ throw new AgentHttpError(response.status, "POST", `${this.agentPath()}/chat`, response.statusText);
45
50
  }
46
51
  return streamResponse(response);
47
52
  }
48
53
  /**
49
- * `GET /agent/chat/:runId/stream[?after=<seq>]` → the run's SSE stream, or `null` when nothing is
54
+ * `GET <path>/chat/:runId/stream[?after=<seq>]` → the run's SSE stream, or `null` when nothing is
50
55
  * streaming under that id (404).
51
56
  */
52
57
  async resumeChatStream(request) {
53
- const path = `/agent/chat/${encodeURIComponent(request.runId)}/stream`;
58
+ const path = `/chat/${encodeURIComponent(request.runId)}/stream`;
54
59
  const query = request.after !== void 0 && request.after > 0 ? `?after=${request.after}` : "";
55
- const response = await this.fetchImpl()(`${this.baseUrl()}${path}${query}`, {
60
+ const response = await this.fetchImpl()(`${this.root()}${path}${query}`, {
56
61
  method: "GET",
57
62
  headers: {
58
63
  accept: "text/event-stream",
@@ -68,7 +73,7 @@ var AgentClient = class {
68
73
  return null;
69
74
  }
70
75
  if (!response.ok || !response.body) {
71
- throw new AgentHttpError(response.status, "GET", path, response.statusText);
76
+ throw new AgentHttpError(response.status, "GET", `${this.agentPath()}${path}`, response.statusText);
72
77
  }
73
78
  return streamResponse(response);
74
79
  }
@@ -77,10 +82,10 @@ var AgentClient = class {
77
82
  * the stored rating.
78
83
  */
79
84
  setMessageFeedback(messageId, input) {
80
- return this.request("POST", `/agent/messages/${encodeURIComponent(messageId)}/feedback`, input);
85
+ return this.request("POST", `/messages/${encodeURIComponent(messageId)}/feedback`, input);
81
86
  }
82
87
  listThreads() {
83
- return this.request("GET", "/agent/threads");
88
+ return this.request("GET", "/threads");
84
89
  }
85
90
  /**
86
91
  * The skills this caller can invoke right now, scope-resolved — the same list, built by the same
@@ -90,7 +95,7 @@ var AgentClient = class {
90
95
  */
91
96
  listSkills(threadId) {
92
97
  const query = threadId === void 0 ? "" : `?threadId=${encodeURIComponent(threadId)}`;
93
- return this.request("GET", `/agent/skills${query}`);
98
+ return this.request("GET", `/skills${query}`);
94
99
  }
95
100
  /**
96
101
  * The tools this caller can reach through `agent` (the default agent when omitted), each with the
@@ -99,41 +104,42 @@ var AgentClient = class {
99
104
  */
100
105
  listTools(agent) {
101
106
  const query = agent === void 0 ? "" : `?agent=${encodeURIComponent(agent)}`;
102
- return this.request("GET", `/agent/tools${query}`);
107
+ return this.request("GET", `/tools${query}`);
103
108
  }
104
109
  getThread(id) {
105
- return this.request("GET", `/agent/threads/${encodeURIComponent(id)}`);
110
+ return this.request("GET", `/threads/${encodeURIComponent(id)}`);
106
111
  }
107
112
  deleteThread(id) {
108
- return this.request("DELETE", `/agent/threads/${encodeURIComponent(id)}`);
113
+ return this.request("DELETE", `/threads/${encodeURIComponent(id)}`);
109
114
  }
110
115
  forkFromMessage(threadId, messageId) {
111
- return this.request("POST", `/agent/threads/${encodeURIComponent(threadId)}/fork-from/${encodeURIComponent(messageId)}`);
116
+ return this.request("POST", `/threads/${encodeURIComponent(threadId)}/fork-from/${encodeURIComponent(messageId)}`);
112
117
  }
113
118
  renameThread(id, title) {
114
119
  return this.updateThread(id, {
115
120
  title
116
121
  });
117
122
  }
118
- /** General `PATCH /agent/threads/:threadId` — title and/or the thread's pinned default agent. */
123
+ /** General `PATCH <path>/threads/:threadId` — title and/or the thread's pinned default agent. */
119
124
  updateThread(id, patch) {
120
- return this.request("PATCH", `/agent/threads/${encodeURIComponent(id)}`, patch);
125
+ return this.request("PATCH", `/threads/${encodeURIComponent(id)}`, patch);
121
126
  }
122
127
  /**
123
128
  * Uploads a file (image/PDF) for a vision-capable model turn. Multipart, field name `file` —
124
- * mirrors the backend's `POST /agent/attachments`. The returned {@link MessageAttachment} is
129
+ * mirrors the backend's `POST <path>/attachments`. The returned {@link MessageAttachment} is
125
130
  * what a caller then rides on `sendMessage({ text }, { body: { attachments: [...] } })`.
126
131
  */
127
132
  async uploadAttachment(file, options = {}) {
128
- if (this.options.attachments !== void 0) {
129
- return this.options.attachments(file, options, this.connection());
133
+ const upload = this.options.attachments?.upload;
134
+ if (upload !== void 0) {
135
+ return upload(file, options, this.connection());
130
136
  }
131
137
  if (options.onProgress !== void 0 && this.options.fetch === void 0 && typeof XMLHttpRequest !== "undefined") {
132
138
  return this.uploadWithProgress(file, options);
133
139
  }
134
140
  const formData = new FormData();
135
141
  formData.append("file", file);
136
- const response = await this.fetchImpl()(`${this.baseUrl()}/agent/attachments`, {
142
+ const response = await this.fetchImpl()(`${this.root()}/attachments`, {
137
143
  method: "POST",
138
144
  headers: {
139
145
  accept: "application/json",
@@ -145,7 +151,7 @@ var AgentClient = class {
145
151
  signal: options.signal
146
152
  } : {}
147
153
  });
148
- const attachment = await this.handleResponse(response, "POST", "/agent/attachments");
154
+ const attachment = await this.handleResponse(response, "POST", `${this.agentPath()}/attachments`);
149
155
  options.onProgress?.(1);
150
156
  return attachment;
151
157
  }
@@ -154,7 +160,7 @@ var AgentClient = class {
154
160
  accept: "application/json",
155
161
  ...await this.resolveHeaders()
156
162
  };
157
- const url = `${this.baseUrl()}/agent/attachments`;
163
+ const url = `${this.root()}/attachments`;
158
164
  return new Promise((resolve, reject) => {
159
165
  const xhr = new XMLHttpRequest();
160
166
  xhr.open("POST", url);
@@ -165,7 +171,7 @@ var AgentClient = class {
165
171
  };
166
172
  xhr.onload = () => {
167
173
  if (xhr.status < 200 || xhr.status >= 300) {
168
- reject(new AgentHttpError(xhr.status, "POST", "/agent/attachments", xhr.statusText));
174
+ reject(new AgentHttpError(xhr.status, "POST", `${this.agentPath()}/attachments`, xhr.statusText));
169
175
  return;
170
176
  }
171
177
  onProgress?.(1);
@@ -188,39 +194,39 @@ var AgentClient = class {
188
194
  });
189
195
  }
190
196
  promoteThread(id) {
191
- return this.request("POST", `/agent/threads/${encodeURIComponent(id)}/promote`);
197
+ return this.request("POST", `/threads/${encodeURIComponent(id)}/promote`);
192
198
  }
193
199
  truncateFromMessage(threadId, messageId) {
194
- return this.request("DELETE", `/agent/threads/${encodeURIComponent(threadId)}/from/${encodeURIComponent(messageId)}`);
200
+ return this.request("DELETE", `/threads/${encodeURIComponent(threadId)}/from/${encodeURIComponent(messageId)}`);
195
201
  }
196
- /** `GET /agent/models?agent=` — the models this caller may pick, grouped by provider. */
202
+ /** `GET <path>/models?agent=` — the models this caller may pick, grouped by provider. */
197
203
  listModels(agent) {
198
204
  const query = agent === void 0 ? "" : `?agent=${encodeURIComponent(agent)}`;
199
- return this.request("GET", `/agent/models${query}`);
205
+ return this.request("GET", `/models${query}`);
200
206
  }
201
- /** `GET /agent/agents` — the registered agents, the default one flagged. */
207
+ /** `GET <path>/agents` — the registered agents, the default one flagged. */
202
208
  listAgents() {
203
- return this.request("GET", "/agent/agents");
209
+ return this.request("GET", "/agents");
204
210
  }
205
- /** `GET /agent/quota` — the caller's budget windows and the one blocking sends, if any. */
211
+ /** `GET <path>/quota` — the caller's budget windows and the one blocking sends, if any. */
206
212
  getQuota() {
207
- return this.request("GET", "/agent/quota");
213
+ return this.request("GET", "/quota");
208
214
  }
209
215
  getQuotaToday() {
210
- return this.request("GET", "/agent/quota/today");
216
+ return this.request("GET", "/quota/today");
211
217
  }
212
218
  cancelStream(runId) {
213
- return this.request("POST", `/agent/chat/${encodeURIComponent(runId)}/cancel`);
219
+ return this.request("POST", `/chat/${encodeURIComponent(runId)}/cancel`);
214
220
  }
215
221
  /**
216
222
  * `remember` approves later calls of the same tool in the same thread; `via` names the surface
217
223
  * the decision came through (the server records `'web'` when omitted).
218
224
  */
219
225
  approveToolCall(input) {
220
- return this.request("POST", "/agent/tool-call/approve", input);
226
+ return this.request("POST", "/tool-call/approve", input);
221
227
  }
222
228
  rejectToolCall(input) {
223
- return this.request("POST", "/agent/tool-call/reject", input);
229
+ return this.request("POST", "/tool-call/reject", input);
224
230
  }
225
231
  /**
226
232
  * Settle a parked question set. `answers` is questionId → chosen option values; a question left
@@ -229,7 +235,7 @@ var AgentClient = class {
229
235
  * answer — which is the point of the surface, so it is a valid submission rather than a blank.
230
236
  */
231
237
  answerToolCall(input) {
232
- return this.request("POST", "/agent/tool-call/answer", input);
238
+ return this.request("POST", "/tool-call/answer", input);
233
239
  }
234
240
  /**
235
241
  * Decline to answer and let the agent proceed on its own pre-picked values. Lands on the same
@@ -237,7 +243,7 @@ var AgentClient = class {
237
243
  * evidence the user chose them.
238
244
  */
239
245
  skipToolCall(input) {
240
- return this.request("POST", "/agent/tool-call/skip", input);
246
+ return this.request("POST", "/tool-call/skip", input);
241
247
  }
242
248
  fetchImpl() {
243
249
  return this.options.fetch ?? globalThis.fetch;
@@ -246,13 +252,21 @@ var AgentClient = class {
246
252
  connection() {
247
253
  return {
248
254
  baseUrl: this.baseUrl(),
255
+ path: this.agentPath(),
249
256
  headers: /* @__PURE__ */ __name(() => this.resolveHeaders(), "headers"),
250
257
  fetch: this.fetchImpl(),
251
258
  ...this.credentials()
252
259
  };
253
260
  }
254
261
  baseUrl() {
255
- return (this.options.baseUrl ?? "").replace(/\/$/, "");
262
+ return (this.options.baseUrl ?? "").replace(/\/+$/, "");
263
+ }
264
+ agentPath() {
265
+ return normalizeAgentPath(this.options.path);
266
+ }
267
+ /** Origin + agent path: what every route hangs off. */
268
+ root() {
269
+ return `${this.baseUrl()}${this.agentPath()}`;
256
270
  }
257
271
  async resolveHeaders() {
258
272
  const dynamic = await this.options.getHeaders?.() ?? {};
@@ -266,7 +280,8 @@ var AgentClient = class {
266
280
  credentials: this.options.credentials
267
281
  } : {};
268
282
  }
269
- async request(method, path, body) {
283
+ async request(method, route, body) {
284
+ const path = `${this.agentPath()}${route}`;
270
285
  const response = await this.fetchImpl()(`${this.baseUrl()}${path}`, {
271
286
  method,
272
287
  headers: {
@@ -397,6 +412,9 @@ var AgentChatTransport = class {
397
412
  ...options.baseUrl !== void 0 ? {
398
413
  baseUrl: options.baseUrl
399
414
  } : {},
415
+ ...options.path !== void 0 ? {
416
+ path: options.path
417
+ } : {},
400
418
  ...options.headers !== void 0 ? {
401
419
  headers: options.headers
402
420
  } : {},
@@ -1102,7 +1120,7 @@ function dragHasFiles(data) {
1102
1120
  __name(dragHasFiles, "dragHasFiles");
1103
1121
 
1104
1122
  // src/attachments/use-attachments.ts
1105
- import { useCallback, useEffect as useEffect2, useMemo, useRef as useRef2, useState as useState2 } from "react";
1123
+ import { useCallback as useCallback2, useEffect as useEffect3, useMemo as useMemo4, useRef as useRef3, useState as useState3 } from "react";
1106
1124
 
1107
1125
  // src/backend.ts
1108
1126
  var AgentBackendUnsupportedError = class extends Error {
@@ -1124,6 +1142,570 @@ function requireBackendMethod(backend, name) {
1124
1142
  }
1125
1143
  __name(requireBackendMethod, "requireBackendMethod");
1126
1144
 
1145
+ // src/provider.tsx
1146
+ import { useContext as useContext3, useMemo as useMemo3, useRef as useRef2 } from "react";
1147
+
1148
+ // src/components/ambient-ui.ts
1149
+ import { createContext, useContext } from "react";
1150
+ function sharedContext(key) {
1151
+ const symbol = Symbol.for(key);
1152
+ const holder = globalThis;
1153
+ const existing = holder[symbol];
1154
+ if (existing !== void 0) return existing;
1155
+ const created = createContext(null);
1156
+ holder[symbol] = created;
1157
+ return created;
1158
+ }
1159
+ __name(sharedContext, "sharedContext");
1160
+ var AmbientRenderUiContext = sharedContext("@dudousxd/nestjs-agent-react:ambient-render-ui");
1161
+ function useAmbientRenderUi() {
1162
+ return useContext(AmbientRenderUiContext);
1163
+ }
1164
+ __name(useAmbientRenderUi, "useAmbientRenderUi");
1165
+
1166
+ // src/genui/generative-ui.tsx
1167
+ import { Component, createContext as createContext2, useCallback, useContext as useContext2, useMemo as useMemo2 } from "react";
1168
+
1169
+ // src/genui/use-generative-ui.ts
1170
+ import { useEffect as useEffect2, useMemo, useState as useState2 } from "react";
1171
+
1172
+ // src/genui/types.ts
1173
+ var GENUI_TREE_COMPONENT = "genui:tree";
1174
+
1175
+ // src/genui/use-generative-ui.ts
1176
+ function isRecord(value) {
1177
+ return typeof value === "object" && value !== null && !Array.isArray(value);
1178
+ }
1179
+ __name(isRecord, "isRecord");
1180
+ function toGenerativeUIItem(part) {
1181
+ if (!isRecord(part)) return null;
1182
+ const source = part.type === "data-ui" && isRecord(part.data) ? part.data : part;
1183
+ if (typeof source.component !== "string") return null;
1184
+ const id = typeof source.id === "string" ? source.id : typeof part.id === "string" ? part.id : null;
1185
+ if (id === null) return null;
1186
+ return {
1187
+ id,
1188
+ component: source.component,
1189
+ props: isRecord(source.props) ? source.props : {},
1190
+ version: typeof source.version === "number" ? source.version : null,
1191
+ toolCallId: typeof source.toolCallId === "string" ? source.toolCallId : null
1192
+ };
1193
+ }
1194
+ __name(toGenerativeUIItem, "toGenerativeUIItem");
1195
+ var resolverCaches = /* @__PURE__ */ new WeakMap();
1196
+ function resolveCached(resolve, name, version) {
1197
+ let cache = resolverCaches.get(resolve);
1198
+ if (cache === void 0) {
1199
+ cache = /* @__PURE__ */ new Map();
1200
+ resolverCaches.set(resolve, cache);
1201
+ }
1202
+ const key = `${name}@${version ?? ""}`;
1203
+ const hit = cache.get(key);
1204
+ if (hit !== void 0) return hit;
1205
+ let entry;
1206
+ try {
1207
+ const result = resolve(name, version);
1208
+ if (result instanceof Promise) {
1209
+ entry = {
1210
+ resolution: {
1211
+ status: "loading"
1212
+ },
1213
+ settled: null
1214
+ };
1215
+ entry.settled = result.then((Component2) => {
1216
+ entry.resolution = Component2 ? {
1217
+ status: "ready",
1218
+ Component: Component2
1219
+ } : {
1220
+ status: "unknown"
1221
+ };
1222
+ }, (error) => {
1223
+ entry.resolution = {
1224
+ status: "error",
1225
+ error
1226
+ };
1227
+ });
1228
+ } else {
1229
+ entry = {
1230
+ resolution: result ? {
1231
+ status: "ready",
1232
+ Component: result
1233
+ } : {
1234
+ status: "unknown"
1235
+ },
1236
+ settled: null
1237
+ };
1238
+ }
1239
+ } catch (error) {
1240
+ entry = {
1241
+ resolution: {
1242
+ status: "error",
1243
+ error
1244
+ },
1245
+ settled: null
1246
+ };
1247
+ }
1248
+ cache.set(key, entry);
1249
+ return entry;
1250
+ }
1251
+ __name(resolveCached, "resolveCached");
1252
+ function useResolvedComponent(name, version, registry, resolve, fallbackTree) {
1253
+ const [, setTick] = useState2(0);
1254
+ const own = registry[name];
1255
+ const entry = own !== void 0 || resolve === void 0 ? null : resolveCached(resolve, name, version);
1256
+ const pending = entry?.resolution.status === "loading" ? entry.settled : null;
1257
+ useEffect2(() => {
1258
+ if (pending === null) return;
1259
+ let live = true;
1260
+ void pending.then(() => {
1261
+ if (live) setTick((tick) => tick + 1);
1262
+ });
1263
+ return () => {
1264
+ live = false;
1265
+ };
1266
+ }, [
1267
+ pending
1268
+ ]);
1269
+ if (own !== void 0) return {
1270
+ status: "ready",
1271
+ Component: own
1272
+ };
1273
+ if (entry !== null && entry.resolution.status !== "unknown") return entry.resolution;
1274
+ if (name === GENUI_TREE_COMPONENT && fallbackTree !== void 0) {
1275
+ return {
1276
+ status: "ready",
1277
+ Component: fallbackTree
1278
+ };
1279
+ }
1280
+ return {
1281
+ status: "unknown"
1282
+ };
1283
+ }
1284
+ __name(useResolvedComponent, "useResolvedComponent");
1285
+ function useValidatedProps(catalog, name, props) {
1286
+ const checked = catalog?.has(name) === true;
1287
+ const immediate = useMemo(() => {
1288
+ if (!checked || catalog === void 0) return {
1289
+ status: "ok",
1290
+ props
1291
+ };
1292
+ const result = catalog.validateSync?.(name, props);
1293
+ if (result === void 0) return null;
1294
+ return result.ok ? {
1295
+ status: "ok",
1296
+ props: result.value
1297
+ } : {
1298
+ status: "invalid",
1299
+ issues: result.issues
1300
+ };
1301
+ }, [
1302
+ checked,
1303
+ catalog,
1304
+ name,
1305
+ props
1306
+ ]);
1307
+ const [late, setLate] = useState2(null);
1308
+ useEffect2(() => {
1309
+ if (immediate !== null || catalog === void 0) return;
1310
+ let live = true;
1311
+ catalog.validate(name, props).then((result) => {
1312
+ if (!live) return;
1313
+ setLate({
1314
+ props,
1315
+ result: result.ok ? {
1316
+ status: "ok",
1317
+ props: result.value
1318
+ } : {
1319
+ status: "invalid",
1320
+ issues: result.issues
1321
+ }
1322
+ });
1323
+ }, (error) => {
1324
+ if (!live) return;
1325
+ setLate({
1326
+ props,
1327
+ result: {
1328
+ status: "invalid",
1329
+ issues: [
1330
+ {
1331
+ path: [],
1332
+ message: error instanceof Error ? error.message : String(error)
1333
+ }
1334
+ ]
1335
+ }
1336
+ });
1337
+ });
1338
+ return () => {
1339
+ live = false;
1340
+ };
1341
+ }, [
1342
+ immediate,
1343
+ catalog,
1344
+ name,
1345
+ props
1346
+ ]);
1347
+ if (immediate !== null) return immediate;
1348
+ return late !== null && late.props === props ? late.result : {
1349
+ status: "pending"
1350
+ };
1351
+ }
1352
+ __name(useValidatedProps, "useValidatedProps");
1353
+ function useGenerativeUIState(part, options, fallbackTree) {
1354
+ const item = useMemo(() => toGenerativeUIItem(part), [
1355
+ part
1356
+ ]);
1357
+ const name = item?.component ?? "";
1358
+ const resolution = useResolvedComponent(name, item?.version ?? null, options.registry, item === null ? void 0 : options.resolveComponent, fallbackTree);
1359
+ const empty = useMemo(() => ({}), []);
1360
+ const validation = useValidatedProps(item === null || name === GENUI_TREE_COMPONENT ? void 0 : options.catalog, name, item?.props ?? empty);
1361
+ if (item === null) return null;
1362
+ if (resolution.status === "loading") return {
1363
+ status: "loading",
1364
+ item
1365
+ };
1366
+ if (resolution.status === "unknown") return {
1367
+ status: "problem",
1368
+ reason: "unknown",
1369
+ item
1370
+ };
1371
+ if (resolution.status === "error") {
1372
+ return {
1373
+ status: "problem",
1374
+ reason: "error",
1375
+ item,
1376
+ error: resolution.error
1377
+ };
1378
+ }
1379
+ if (validation.status === "pending") return {
1380
+ status: "loading",
1381
+ item
1382
+ };
1383
+ if (validation.status === "invalid") {
1384
+ return {
1385
+ status: "problem",
1386
+ reason: "invalid",
1387
+ item,
1388
+ issues: validation.issues
1389
+ };
1390
+ }
1391
+ return {
1392
+ status: "ready",
1393
+ item,
1394
+ Component: resolution.Component,
1395
+ props: validation.props
1396
+ };
1397
+ }
1398
+ __name(useGenerativeUIState, "useGenerativeUIState");
1399
+
1400
+ // src/genui/generative-ui.tsx
1401
+ var TreeScopeContext = /* @__PURE__ */ createContext2(null);
1402
+ function renderFallback(fallback2, problem) {
1403
+ if (typeof fallback2 === "function") return fallback2(problem);
1404
+ return fallback2 ?? null;
1405
+ }
1406
+ __name(renderFallback, "renderFallback");
1407
+ var ItemBoundary = class ItemBoundary2 extends Component {
1408
+ static {
1409
+ __name(this, "ItemBoundary");
1410
+ }
1411
+ state = {
1412
+ error: void 0,
1413
+ failed: false
1414
+ };
1415
+ static getDerivedStateFromError(error) {
1416
+ return {
1417
+ error,
1418
+ failed: true
1419
+ };
1420
+ }
1421
+ componentDidCatch(error, _info) {
1422
+ this.props.onError?.(error, this.props.item);
1423
+ }
1424
+ componentDidUpdate(previous) {
1425
+ if (this.state.failed && previous.item !== this.props.item) {
1426
+ this.setState({
1427
+ error: void 0,
1428
+ failed: false
1429
+ });
1430
+ }
1431
+ }
1432
+ render() {
1433
+ if (this.state.failed) {
1434
+ return renderFallback(this.props.fallback, {
1435
+ reason: "error",
1436
+ item: this.props.item,
1437
+ error: this.state.error
1438
+ });
1439
+ }
1440
+ return this.props.children;
1441
+ }
1442
+ };
1443
+ function nodeItem(node, id) {
1444
+ return {
1445
+ id,
1446
+ component: node.type,
1447
+ props: node.props ?? {},
1448
+ version: null,
1449
+ toolCallId: null
1450
+ };
1451
+ }
1452
+ __name(nodeItem, "nodeItem");
1453
+ function TreeNode({ node, id }) {
1454
+ const scope = useContext2(TreeScopeContext);
1455
+ const item = useMemo2(() => nodeItem(node, id), [
1456
+ node,
1457
+ id
1458
+ ]);
1459
+ const resolution = useResolvedComponent(node.type, null, scope?.options.registry ?? {}, scope?.options.resolveComponent);
1460
+ const validation = useValidatedProps(scope?.options.catalog, node.type, item.props);
1461
+ if (scope === null) return null;
1462
+ if (resolution.status === "loading" || validation.status === "pending") return scope.loading;
1463
+ if (resolution.status === "unknown") {
1464
+ return renderFallback(scope.fallback, {
1465
+ reason: "unknown",
1466
+ item
1467
+ });
1468
+ }
1469
+ if (resolution.status === "error") {
1470
+ return renderFallback(scope.fallback, {
1471
+ reason: "error",
1472
+ item,
1473
+ error: resolution.error
1474
+ });
1475
+ }
1476
+ if (validation.status === "invalid") {
1477
+ return renderFallback(scope.fallback, {
1478
+ reason: "invalid",
1479
+ item,
1480
+ issues: validation.issues
1481
+ });
1482
+ }
1483
+ const Renderer = resolution.Component;
1484
+ const children = Array.isArray(node.children) ? node.children : [];
1485
+ return /* @__PURE__ */ React.createElement(Renderer, validation.props, children.length > 0 ? children.map((child, index) => {
1486
+ const childId = `${id}.${index}`;
1487
+ return /* @__PURE__ */ React.createElement(ItemBoundary, {
1488
+ key: childId,
1489
+ item: nodeItem(child, childId),
1490
+ fallback: scope.fallback,
1491
+ onError: scope.onError
1492
+ }, /* @__PURE__ */ React.createElement(TreeNode, {
1493
+ node: child,
1494
+ id: childId
1495
+ }));
1496
+ }) : void 0);
1497
+ }
1498
+ __name(TreeNode, "TreeNode");
1499
+ function GenuiTree({ root }) {
1500
+ if (root === void 0 || root === null || typeof root.type !== "string") return null;
1501
+ return /* @__PURE__ */ React.createElement(TreeNode, {
1502
+ node: root,
1503
+ id: "root"
1504
+ });
1505
+ }
1506
+ __name(GenuiTree, "GenuiTree");
1507
+ function GenerativeUIScope({ registry, catalog, resolveComponent, fallback: fallback2, loading = null, onError, children }) {
1508
+ const scope = useMemo2(() => ({
1509
+ options: {
1510
+ registry,
1511
+ ...catalog !== void 0 ? {
1512
+ catalog
1513
+ } : {},
1514
+ ...resolveComponent !== void 0 ? {
1515
+ resolveComponent
1516
+ } : {}
1517
+ },
1518
+ fallback: fallback2,
1519
+ loading,
1520
+ onError
1521
+ }), [
1522
+ registry,
1523
+ catalog,
1524
+ resolveComponent,
1525
+ fallback2,
1526
+ loading,
1527
+ onError
1528
+ ]);
1529
+ return /* @__PURE__ */ React.createElement(TreeScopeContext.Provider, {
1530
+ value: scope
1531
+ }, children);
1532
+ }
1533
+ __name(GenerativeUIScope, "GenerativeUIScope");
1534
+ var GenuiContext = sharedContext("@dudousxd/nestjs-agent-react:genui-provider");
1535
+ function GenuiProvider({ registry, catalog, resolveComponent, treeRenderer, fallback: fallback2, loading, onError, children }) {
1536
+ const value = useMemo2(() => ({
1537
+ ...registry !== void 0 ? {
1538
+ registry
1539
+ } : {},
1540
+ ...catalog !== void 0 ? {
1541
+ catalog
1542
+ } : {},
1543
+ ...resolveComponent !== void 0 ? {
1544
+ resolveComponent
1545
+ } : {},
1546
+ ...treeRenderer !== void 0 ? {
1547
+ treeRenderer
1548
+ } : {},
1549
+ ...fallback2 !== void 0 ? {
1550
+ fallback: fallback2
1551
+ } : {},
1552
+ ...loading !== void 0 ? {
1553
+ loading
1554
+ } : {},
1555
+ ...onError !== void 0 ? {
1556
+ onError
1557
+ } : {}
1558
+ }), [
1559
+ registry,
1560
+ catalog,
1561
+ resolveComponent,
1562
+ treeRenderer,
1563
+ fallback2,
1564
+ loading,
1565
+ onError
1566
+ ]);
1567
+ const renderUi = useCallback((block) => /* @__PURE__ */ React.createElement(GenerativeUI, {
1568
+ part: block
1569
+ }), []);
1570
+ return /* @__PURE__ */ React.createElement(GenuiContext.Provider, {
1571
+ value
1572
+ }, /* @__PURE__ */ React.createElement(AmbientRenderUiContext.Provider, {
1573
+ value: renderUi
1574
+ }, children));
1575
+ }
1576
+ __name(GenuiProvider, "GenuiProvider");
1577
+ var NO_REGISTRY = {};
1578
+ function useMergedOptions(own) {
1579
+ const provided = useContext2(GenuiContext);
1580
+ const registry = own.registry ?? provided?.registry ?? NO_REGISTRY;
1581
+ const catalog = own.catalog ?? provided?.catalog;
1582
+ const resolveComponent = own.resolveComponent ?? provided?.resolveComponent;
1583
+ const treeRenderer = own.treeRenderer ?? provided?.treeRenderer;
1584
+ return useMemo2(() => ({
1585
+ registry,
1586
+ ...catalog !== void 0 ? {
1587
+ catalog
1588
+ } : {},
1589
+ ...resolveComponent !== void 0 ? {
1590
+ resolveComponent
1591
+ } : {},
1592
+ ...treeRenderer !== void 0 ? {
1593
+ treeRenderer
1594
+ } : {}
1595
+ }), [
1596
+ registry,
1597
+ catalog,
1598
+ resolveComponent,
1599
+ treeRenderer
1600
+ ]);
1601
+ }
1602
+ __name(useMergedOptions, "useMergedOptions");
1603
+ function GenerativeUI({ part, registry, catalog, resolveComponent, treeRenderer, fallback: ownFallback, loading: ownLoading, onError: ownOnError }) {
1604
+ const provided = useContext2(GenuiContext);
1605
+ const fallback2 = ownFallback ?? provided?.fallback;
1606
+ const loading = ownLoading ?? provided?.loading ?? null;
1607
+ const onError = ownOnError ?? provided?.onError;
1608
+ const options = useMergedOptions({
1609
+ ...registry !== void 0 ? {
1610
+ registry
1611
+ } : {},
1612
+ ...catalog !== void 0 ? {
1613
+ catalog
1614
+ } : {},
1615
+ ...resolveComponent !== void 0 ? {
1616
+ resolveComponent
1617
+ } : {},
1618
+ ...treeRenderer !== void 0 ? {
1619
+ treeRenderer
1620
+ } : {}
1621
+ });
1622
+ const state = useGenerativeUIState(part, options, options.treeRenderer ?? GenuiTree);
1623
+ if (state === null) return null;
1624
+ if (state.status === "loading") return loading;
1625
+ if (state.status === "problem") {
1626
+ const { status: _status, ...problem } = state;
1627
+ return renderFallback(fallback2, problem);
1628
+ }
1629
+ const Renderer = state.Component;
1630
+ return /* @__PURE__ */ React.createElement(GenerativeUIScope, {
1631
+ ...options,
1632
+ fallback: fallback2,
1633
+ loading,
1634
+ ...onError !== void 0 ? {
1635
+ onError
1636
+ } : {}
1637
+ }, /* @__PURE__ */ React.createElement(ItemBoundary, {
1638
+ item: state.item,
1639
+ fallback: fallback2,
1640
+ onError
1641
+ }, /* @__PURE__ */ React.createElement(Renderer, state.props)));
1642
+ }
1643
+ __name(GenerativeUI, "GenerativeUI");
1644
+
1645
+ // src/provider.tsx
1646
+ var AgentBackendContext = sharedContext("@dudousxd/nestjs-agent-react:agent-backend");
1647
+ function AgentProvider({ backend, baseUrl, path, headers, getHeaders, credentials, fetch, attachments, genui, children }) {
1648
+ const latestHeaders = useRef2({
1649
+ headers,
1650
+ getHeaders
1651
+ });
1652
+ latestHeaders.current = {
1653
+ headers,
1654
+ getHeaders
1655
+ };
1656
+ const upload = attachments?.upload;
1657
+ const value = useMemo3(() => backend ?? new AgentClient({
1658
+ ...baseUrl !== void 0 ? {
1659
+ baseUrl
1660
+ } : {},
1661
+ ...path !== void 0 ? {
1662
+ path
1663
+ } : {},
1664
+ ...credentials !== void 0 ? {
1665
+ credentials
1666
+ } : {},
1667
+ ...fetch !== void 0 ? {
1668
+ fetch
1669
+ } : {},
1670
+ ...upload !== void 0 ? {
1671
+ attachments: {
1672
+ upload
1673
+ }
1674
+ } : {},
1675
+ getHeaders: /* @__PURE__ */ __name(async () => {
1676
+ const current = latestHeaders.current;
1677
+ const dynamic = await current.getHeaders?.() ?? {};
1678
+ return {
1679
+ ...current.headers,
1680
+ ...dynamic
1681
+ };
1682
+ }, "getHeaders")
1683
+ }), [
1684
+ backend,
1685
+ baseUrl,
1686
+ path,
1687
+ credentials,
1688
+ fetch,
1689
+ upload
1690
+ ]);
1691
+ const content = genui !== void 0 ? /* @__PURE__ */ React.createElement(GenuiProvider, genui, children) : children;
1692
+ return /* @__PURE__ */ React.createElement(AgentBackendContext.Provider, {
1693
+ value
1694
+ }, content);
1695
+ }
1696
+ __name(AgentProvider, "AgentProvider");
1697
+ var fallback;
1698
+ function defaultBackend() {
1699
+ fallback ??= new AgentClient();
1700
+ return fallback;
1701
+ }
1702
+ __name(defaultBackend, "defaultBackend");
1703
+ function useAgentBackend(own) {
1704
+ const provided = useContext3(AgentBackendContext);
1705
+ return own ?? provided ?? defaultBackend();
1706
+ }
1707
+ __name(useAgentBackend, "useAgentBackend");
1708
+
1127
1709
  // src/attachments/use-attachments.ts
1128
1710
  var DEFAULT_REJECTION = {
1129
1711
  type: /* @__PURE__ */ __name((file) => `${file.name} is not a supported file type`, "type"),
@@ -1131,23 +1713,30 @@ var DEFAULT_REJECTION = {
1131
1713
  count: /* @__PURE__ */ __name(() => "Too many files", "count")
1132
1714
  };
1133
1715
  var sequence = 0;
1134
- function useAttachments(options) {
1135
- const latest = useRef2(options);
1136
- latest.current = options;
1137
- const [items, setItems] = useState2([]);
1138
- const itemsRef = useRef2(items);
1716
+ function useAttachments(options = {}) {
1717
+ const backend = useAgentBackend(options.backend);
1718
+ const latest = useRef3({
1719
+ ...options,
1720
+ backend
1721
+ });
1722
+ latest.current = {
1723
+ ...options,
1724
+ backend
1725
+ };
1726
+ const [items, setItems] = useState3([]);
1727
+ const itemsRef = useRef3(items);
1139
1728
  itemsRef.current = items;
1140
- const controllers = useRef2(/* @__PURE__ */ new Map());
1141
- const [dragDepth, setDragDepth] = useState2(0);
1142
- const patch = useCallback((id, change) => {
1729
+ const controllers = useRef3(/* @__PURE__ */ new Map());
1730
+ const [dragDepth, setDragDepth] = useState3(0);
1731
+ const patch = useCallback2((id, change) => {
1143
1732
  setItems((current) => current.map((item) => item.id === id ? {
1144
1733
  ...item,
1145
1734
  ...change
1146
1735
  } : item));
1147
1736
  }, []);
1148
- const start = useCallback((item) => {
1149
- const { upload, backend } = latest.current;
1150
- const run = upload ?? (backend?.uploadAttachment !== void 0 ? backend.uploadAttachment.bind(backend) : void 0);
1737
+ const start = useCallback2((item) => {
1738
+ const { upload, backend: backend2 } = latest.current;
1739
+ const run = upload ?? (backend2.uploadAttachment !== void 0 ? backend2.uploadAttachment.bind(backend2) : void 0);
1151
1740
  if (run === void 0) {
1152
1741
  patch(item.id, {
1153
1742
  status: "error",
@@ -1181,7 +1770,7 @@ function useAttachments(options) {
1181
1770
  }, [
1182
1771
  patch
1183
1772
  ]);
1184
- const add = useCallback((files) => {
1773
+ const add = useCallback2((files) => {
1185
1774
  if (files == null) return;
1186
1775
  const { accept: accept2, maxBytes, maxFiles, describeRejection } = latest.current;
1187
1776
  const describe = /* @__PURE__ */ __name((reason, file) => describeRejection?.(reason, file) ?? DEFAULT_REJECTION[reason](file), "describe");
@@ -1227,7 +1816,7 @@ function useAttachments(options) {
1227
1816
  }, [
1228
1817
  start
1229
1818
  ]);
1230
- const release = useCallback((item) => {
1819
+ const release = useCallback2((item) => {
1231
1820
  if (item === void 0) return;
1232
1821
  controllers.current.get(item.id)?.abort();
1233
1822
  controllers.current.delete(item.id);
@@ -1235,19 +1824,19 @@ function useAttachments(options) {
1235
1824
  URL.revokeObjectURL(item.previewUrl);
1236
1825
  }
1237
1826
  }, []);
1238
- const remove = useCallback((id) => {
1827
+ const remove = useCallback2((id) => {
1239
1828
  release(itemsRef.current.find((item) => item.id === id));
1240
1829
  setItems((current) => current.filter((item) => item.id !== id));
1241
1830
  }, [
1242
1831
  release
1243
1832
  ]);
1244
- const clear = useCallback(() => {
1833
+ const clear = useCallback2(() => {
1245
1834
  for (const item of itemsRef.current) release(item);
1246
1835
  setItems([]);
1247
1836
  }, [
1248
1837
  release
1249
1838
  ]);
1250
- const retry = useCallback((id) => {
1839
+ const retry = useCallback2((id) => {
1251
1840
  const item = itemsRef.current.find((candidate) => candidate.id === id);
1252
1841
  if (item === void 0 || item.status !== "error") return;
1253
1842
  const { error: _previous, ...rest } = item;
@@ -1261,12 +1850,12 @@ function useAttachments(options) {
1261
1850
  }, [
1262
1851
  start
1263
1852
  ]);
1264
- useEffect2(() => () => {
1853
+ useEffect3(() => () => {
1265
1854
  for (const item of itemsRef.current) release(item);
1266
1855
  }, [
1267
1856
  release
1268
1857
  ]);
1269
- const onPaste = useCallback((event) => {
1858
+ const onPaste = useCallback2((event) => {
1270
1859
  const files = filesFromClipboard(event.clipboardData);
1271
1860
  if (files.length === 0) return;
1272
1861
  event.preventDefault();
@@ -1274,7 +1863,7 @@ function useAttachments(options) {
1274
1863
  }, [
1275
1864
  add
1276
1865
  ]);
1277
- const dropZoneProps = useMemo(() => ({
1866
+ const dropZoneProps = useMemo4(() => ({
1278
1867
  onDragEnter: /* @__PURE__ */ __name((event) => {
1279
1868
  if (!dragHasFiles(event.dataTransfer)) return;
1280
1869
  event.preventDefault();
@@ -1297,7 +1886,7 @@ function useAttachments(options) {
1297
1886
  add
1298
1887
  ]);
1299
1888
  const accept = options.accept;
1300
- const inputProps = useMemo(() => ({
1889
+ const inputProps = useMemo4(() => ({
1301
1890
  type: "file",
1302
1891
  accept: typeof accept === "string" ? accept : accept?.join(","),
1303
1892
  multiple: options.maxFiles === void 0 || options.maxFiles > 1,
@@ -1311,7 +1900,7 @@ function useAttachments(options) {
1311
1900
  options.maxFiles,
1312
1901
  add
1313
1902
  ]);
1314
- return useMemo(() => {
1903
+ return useMemo4(() => {
1315
1904
  const ready = items.filter((item) => item.status === "ready" && item.attachment !== void 0);
1316
1905
  const attachments = ready.map((item) => item.attachment);
1317
1906
  return {
@@ -1345,18 +1934,18 @@ function useAttachments(options) {
1345
1934
  __name(useAttachments, "useAttachments");
1346
1935
 
1347
1936
  // src/catalog/use-agents.ts
1348
- import { useMemo as useMemo2 } from "react";
1937
+ import { useMemo as useMemo5 } from "react";
1349
1938
 
1350
1939
  // src/catalog/use-resource.ts
1351
- import { useCallback as useCallback2, useEffect as useEffect3, useRef as useRef3, useState as useState3 } from "react";
1940
+ import { useCallback as useCallback3, useEffect as useEffect4, useRef as useRef4, useState as useState4 } from "react";
1352
1941
  function useResource(load2, key, enabled) {
1353
- const [data, setData] = useState3(void 0);
1354
- const [isLoading, setIsLoading] = useState3(enabled);
1355
- const [error, setError] = useState3(null);
1356
- const loadRef = useRef3(load2);
1942
+ const [data, setData] = useState4(void 0);
1943
+ const [isLoading, setIsLoading] = useState4(enabled);
1944
+ const [error, setError] = useState4(null);
1945
+ const loadRef = useRef4(load2);
1357
1946
  loadRef.current = load2;
1358
- const generation = useRef3(0);
1359
- const refresh = useCallback2(async () => {
1947
+ const generation = useRef4(0);
1948
+ const refresh = useCallback3(async () => {
1360
1949
  const mine = ++generation.current;
1361
1950
  setIsLoading(true);
1362
1951
  try {
@@ -1371,7 +1960,7 @@ function useResource(load2, key, enabled) {
1371
1960
  if (mine === generation.current) setIsLoading(false);
1372
1961
  }
1373
1962
  }, []);
1374
- useEffect3(() => {
1963
+ useEffect4(() => {
1375
1964
  if (!enabled) return;
1376
1965
  void refresh();
1377
1966
  }, [
@@ -1389,10 +1978,11 @@ function useResource(load2, key, enabled) {
1389
1978
  __name(useResource, "useResource");
1390
1979
 
1391
1980
  // src/catalog/use-agents.ts
1392
- function useAgents(options) {
1393
- const { backend, enabled = true } = options;
1981
+ function useAgents(options = {}) {
1982
+ const { enabled = true } = options;
1983
+ const backend = useAgentBackend(options.backend);
1394
1984
  const { data, isLoading, error, refresh } = useResource(() => requireBackendMethod(backend, "listAgents")(), "", enabled);
1395
- return useMemo2(() => {
1985
+ return useMemo5(() => {
1396
1986
  const agents = data ?? [];
1397
1987
  return {
1398
1988
  agents,
@@ -1411,11 +2001,12 @@ function useAgents(options) {
1411
2001
  __name(useAgents, "useAgents");
1412
2002
 
1413
2003
  // src/catalog/use-models.ts
1414
- import { useMemo as useMemo3 } from "react";
1415
- function useModels(options) {
1416
- const { backend, agent, enabled = true } = options;
2004
+ import { useMemo as useMemo6 } from "react";
2005
+ function useModels(options = {}) {
2006
+ const { agent, enabled = true } = options;
2007
+ const backend = useAgentBackend(options.backend);
1417
2008
  const { data, isLoading, error, refresh } = useResource(() => requireBackendMethod(backend, "listModels")(agent), `${agent ?? ""}`, enabled);
1418
- return useMemo3(() => {
2009
+ return useMemo6(() => {
1419
2010
  const providers = data?.providers ?? [];
1420
2011
  const models = providers.flatMap((provider) => provider.models.map((model) => ({
1421
2012
  ...model,
@@ -1445,7 +2036,7 @@ function useModels(options) {
1445
2036
  __name(useModels, "useModels");
1446
2037
 
1447
2038
  // src/quota/use-quota.ts
1448
- import { useEffect as useEffect4, useMemo as useMemo4 } from "react";
2039
+ import { useEffect as useEffect5, useMemo as useMemo7 } from "react";
1449
2040
 
1450
2041
  // src/threads/threads-events.ts
1451
2042
  var listeners = /* @__PURE__ */ new WeakMap();
@@ -1469,10 +2060,11 @@ function onThreadsEvent(backend, listener) {
1469
2060
  __name(onThreadsEvent, "onThreadsEvent");
1470
2061
 
1471
2062
  // src/quota/use-quota.ts
1472
- function useQuota(options) {
1473
- const { backend, enabled = true, pollMs } = options;
2063
+ function useQuota(options = {}) {
2064
+ const { enabled = true, pollMs } = options;
2065
+ const backend = useAgentBackend(options.backend);
1474
2066
  const { data, isLoading, error, refresh } = useResource(() => requireBackendMethod(backend, "getQuota")(), "", enabled);
1475
- useEffect4(() => {
2067
+ useEffect5(() => {
1476
2068
  if (!enabled) return;
1477
2069
  return onThreadsEvent(backend, (event) => {
1478
2070
  if (event.type === "changed") void refresh();
@@ -1482,7 +2074,7 @@ function useQuota(options) {
1482
2074
  enabled,
1483
2075
  refresh
1484
2076
  ]);
1485
- useEffect4(() => {
2077
+ useEffect5(() => {
1486
2078
  if (!enabled || pollMs === void 0 || pollMs <= 0) return;
1487
2079
  const timer = setInterval(() => void refresh(), pollMs);
1488
2080
  return () => clearInterval(timer);
@@ -1491,7 +2083,7 @@ function useQuota(options) {
1491
2083
  pollMs,
1492
2084
  refresh
1493
2085
  ]);
1494
- return useMemo4(() => {
2086
+ return useMemo7(() => {
1495
2087
  const windows = data?.windows ?? [];
1496
2088
  return {
1497
2089
  report: data,
@@ -1513,37 +2105,44 @@ function useQuota(options) {
1513
2105
  __name(useQuota, "useQuota");
1514
2106
 
1515
2107
  // src/feedback/use-message-feedback.ts
1516
- import { useCallback as useCallback3, useRef as useRef4, useState as useState4 } from "react";
1517
- function useMessageFeedback(options) {
1518
- const latest = useRef4(options);
1519
- latest.current = options;
1520
- const [local, setLocal] = useState4(/* @__PURE__ */ new Map());
1521
- const [pending, setPending] = useState4(/* @__PURE__ */ new Set());
1522
- const [error, setError] = useState4(null);
1523
- const localRef = useRef4(local);
2108
+ import { useCallback as useCallback4, useRef as useRef5, useState as useState5 } from "react";
2109
+ function useMessageFeedback(options = {}) {
2110
+ const backend = useAgentBackend(options.backend);
2111
+ const latest = useRef5({
2112
+ ...options,
2113
+ backend
2114
+ });
2115
+ latest.current = {
2116
+ ...options,
2117
+ backend
2118
+ };
2119
+ const [local, setLocal] = useState5(/* @__PURE__ */ new Map());
2120
+ const [pending, setPending] = useState5(/* @__PURE__ */ new Set());
2121
+ const [error, setError] = useState5(null);
2122
+ const localRef = useRef5(local);
1524
2123
  localRef.current = local;
1525
- const resolved = useRef4(/* @__PURE__ */ new Map());
1526
- const feedbackOf = useCallback3((message) => {
2124
+ const resolved = useRef5(/* @__PURE__ */ new Map());
2125
+ const feedbackOf = useCallback4((message) => {
1527
2126
  const mine = local.get(message.id);
1528
2127
  if (mine !== void 0) return mine.feedback;
1529
2128
  return metadataOf(message).feedback ?? null;
1530
2129
  }, [
1531
2130
  local
1532
2131
  ]);
1533
- const isPending = useCallback3((message) => pending.has(message.id), [
2132
+ const isPending = useCallback4((message) => pending.has(message.id), [
1534
2133
  pending
1535
2134
  ]);
1536
- const storedIdFor = useCallback3(async (message) => {
2135
+ const storedIdFor = useCallback4(async (message) => {
1537
2136
  const runId = metadataOf(message).runId;
1538
2137
  if (runId === void 0) return message.id;
1539
2138
  const known = resolved.current.get(message.id);
1540
2139
  if (known !== void 0) return known;
1541
- const { backend, threadId } = latest.current;
2140
+ const { backend: backend2, threadId } = latest.current;
1542
2141
  const thread = typeof threadId === "function" ? threadId() : threadId;
1543
2142
  if (thread === void 0) {
1544
2143
  throw new Error("useMessageFeedback: a streamed message needs `threadId` to be rated");
1545
2144
  }
1546
- const detail = await backend.getThread(thread);
2145
+ const detail = await backend2.getThread(thread);
1547
2146
  const row = [
1548
2147
  ...detail.messages
1549
2148
  ].reverse().find((candidate) => candidate.role === "assistant" && candidate.runId === runId);
@@ -1553,7 +2152,7 @@ function useMessageFeedback(options) {
1553
2152
  resolved.current.set(message.id, row.id);
1554
2153
  return row.id;
1555
2154
  }, []);
1556
- const rate = useCallback3(async (message, value, comment) => {
2155
+ const rate = useCallback4(async (message, value, comment) => {
1557
2156
  const setFeedback = requireBackendMethod(latest.current.backend, "setMessageFeedback");
1558
2157
  const had = localRef.current.get(message.id);
1559
2158
  const optimistic = value === null ? null : {
@@ -1599,7 +2198,7 @@ function useMessageFeedback(options) {
1599
2198
  }, [
1600
2199
  storedIdFor
1601
2200
  ]);
1602
- const toggle = useCallback3((message, value) => {
2201
+ const toggle = useCallback4((message, value) => {
1603
2202
  const mine = localRef.current.get(message.id);
1604
2203
  const current = mine !== void 0 ? mine.feedback : metadataOf(message).feedback ?? null;
1605
2204
  return rate(message, current?.value === value ? null : value);
@@ -1622,16 +2221,17 @@ function metadataOf(message) {
1622
2221
  __name(metadataOf, "metadataOf");
1623
2222
 
1624
2223
  // src/threads/use-threads.ts
1625
- import { useCallback as useCallback4, useEffect as useEffect5, useRef as useRef5, useState as useState5 } from "react";
1626
- function useThreads(options) {
1627
- const { backend, enabled = true } = options;
1628
- const [threads, setThreads] = useState5([]);
1629
- const [isLoading, setIsLoading] = useState5(enabled);
1630
- const [error, setError] = useState5(null);
1631
- const threadsRef = useRef5(threads);
2224
+ import { useCallback as useCallback5, useEffect as useEffect6, useRef as useRef6, useState as useState6 } from "react";
2225
+ function useThreads(options = {}) {
2226
+ const { enabled = true } = options;
2227
+ const backend = useAgentBackend(options.backend);
2228
+ const [threads, setThreads] = useState6([]);
2229
+ const [isLoading, setIsLoading] = useState6(enabled);
2230
+ const [error, setError] = useState6(null);
2231
+ const threadsRef = useRef6(threads);
1632
2232
  threadsRef.current = threads;
1633
- const generation = useRef5(0);
1634
- const refresh = useCallback4(async () => {
2233
+ const generation = useRef6(0);
2234
+ const refresh = useCallback5(async () => {
1635
2235
  const mine = ++generation.current;
1636
2236
  setIsLoading(true);
1637
2237
  try {
@@ -1648,7 +2248,7 @@ function useThreads(options) {
1648
2248
  }, [
1649
2249
  backend
1650
2250
  ]);
1651
- useEffect5(() => {
2251
+ useEffect6(() => {
1652
2252
  if (!enabled) return;
1653
2253
  void refresh();
1654
2254
  return onThreadsEvent(backend, (event) => {
@@ -1668,7 +2268,7 @@ function useThreads(options) {
1668
2268
  enabled,
1669
2269
  refresh
1670
2270
  ]);
1671
- const rename = useCallback4(async (id, title) => {
2271
+ const rename = useCallback5(async (id, title) => {
1672
2272
  const before = threadsRef.current;
1673
2273
  setThreads((current) => current.map((thread) => thread.id === id ? {
1674
2274
  ...thread,
@@ -1690,7 +2290,7 @@ function useThreads(options) {
1690
2290
  }, [
1691
2291
  backend
1692
2292
  ]);
1693
- const remove = useCallback4(async (id) => {
2293
+ const remove = useCallback5(async (id) => {
1694
2294
  const before = threadsRef.current;
1695
2295
  setThreads((current) => current.filter((thread) => thread.id !== id));
1696
2296
  try {
@@ -1764,29 +2364,11 @@ function backgroundRunsFromThread(messages) {
1764
2364
  }
1765
2365
  __name(backgroundRunsFromThread, "backgroundRunsFromThread");
1766
2366
 
1767
- // src/components/ambient-ui.ts
1768
- import { createContext, useContext } from "react";
1769
- function sharedContext(key) {
1770
- const symbol = Symbol.for(key);
1771
- const holder = globalThis;
1772
- const existing = holder[symbol];
1773
- if (existing !== void 0) return existing;
1774
- const created = createContext(null);
1775
- holder[symbol] = created;
1776
- return created;
1777
- }
1778
- __name(sharedContext, "sharedContext");
1779
- var AmbientRenderUiContext = sharedContext("@dudousxd/nestjs-agent-react:ambient-render-ui");
1780
- function useAmbientRenderUi() {
1781
- return useContext(AmbientRenderUiContext);
1782
- }
1783
- __name(useAmbientRenderUi, "useAmbientRenderUi");
1784
-
1785
2367
  // src/components/chat-input.tsx
1786
- import React2, { useEffect as useEffect7, useState as useState7 } from "react";
2368
+ import React2, { useEffect as useEffect8, useState as useState8 } from "react";
1787
2369
 
1788
2370
  // src/components/use-speech-recognition.ts
1789
- import { useCallback as useCallback5, useEffect as useEffect6, useMemo as useMemo5, useRef as useRef6, useState as useState6 } from "react";
2371
+ import { useCallback as useCallback6, useEffect as useEffect7, useMemo as useMemo8, useRef as useRef7, useState as useState7 } from "react";
1790
2372
  function getRecognitionCtor() {
1791
2373
  if (typeof window === "undefined") return null;
1792
2374
  const scope = window;
@@ -1794,15 +2376,15 @@ function getRecognitionCtor() {
1794
2376
  }
1795
2377
  __name(getRecognitionCtor, "getRecognitionCtor");
1796
2378
  function useSpeechRecognition({ lang = "en-US", onFinalTranscript, onInterimTranscript }) {
1797
- const recognitionRef = useRef6(null);
1798
- const [isListening, setIsListening] = useState6(false);
1799
- const ctor = useMemo5(() => getRecognitionCtor(), []);
2379
+ const recognitionRef = useRef7(null);
2380
+ const [isListening, setIsListening] = useState7(false);
2381
+ const ctor = useMemo8(() => getRecognitionCtor(), []);
1800
2382
  const isSupported = ctor !== null;
1801
- const finalRef = useRef6(onFinalTranscript);
1802
- const interimRef = useRef6(onInterimTranscript);
2383
+ const finalRef = useRef7(onFinalTranscript);
2384
+ const interimRef = useRef7(onInterimTranscript);
1803
2385
  finalRef.current = onFinalTranscript;
1804
2386
  interimRef.current = onInterimTranscript;
1805
- useEffect6(() => {
2387
+ useEffect7(() => {
1806
2388
  if (!ctor) return;
1807
2389
  const recognition = new ctor();
1808
2390
  recognition.lang = lang;
@@ -1841,7 +2423,7 @@ function useSpeechRecognition({ lang = "en-US", onFinalTranscript, onInterimTran
1841
2423
  ctor,
1842
2424
  lang
1843
2425
  ]);
1844
- const start = useCallback5(() => {
2426
+ const start = useCallback6(() => {
1845
2427
  const recognition = recognitionRef.current;
1846
2428
  if (!recognition) return;
1847
2429
  try {
@@ -1851,7 +2433,7 @@ function useSpeechRecognition({ lang = "en-US", onFinalTranscript, onInterimTran
1851
2433
  console.warn("SpeechRecognition start failed", error);
1852
2434
  }
1853
2435
  }, []);
1854
- const stop = useCallback5(() => {
2436
+ const stop = useCallback6(() => {
1855
2437
  const recognition = recognitionRef.current;
1856
2438
  if (!recognition) return;
1857
2439
  try {
@@ -1870,8 +2452,8 @@ __name(useSpeechRecognition, "useSpeechRecognition");
1870
2452
 
1871
2453
  // src/components/chat-input.tsx
1872
2454
  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 }) {
1873
- const [value, setValue] = useState7("");
1874
- const [interim, setInterim] = useState7("");
2455
+ const [value, setValue] = useState8("");
2456
+ const [interim, setInterim] = useState8("");
1875
2457
  const speech = useSpeechRecognition({
1876
2458
  lang: speechLang,
1877
2459
  onFinalTranscript: /* @__PURE__ */ __name((text) => {
@@ -1882,7 +2464,7 @@ function ChatInput({ onSubmit, disabled, placeholder, rows = 2, enableSpeech = t
1882
2464
  }, "onFinalTranscript"),
1883
2465
  onInterimTranscript: /* @__PURE__ */ __name((text) => setInterim(text), "onInterimTranscript")
1884
2466
  });
1885
- useEffect7(() => {
2467
+ useEffect8(() => {
1886
2468
  if (!speech.isListening) setInterim("");
1887
2469
  }, [
1888
2470
  speech.isListening
@@ -1949,7 +2531,7 @@ __name(ChatInput, "ChatInput");
1949
2531
  import React3 from "react";
1950
2532
 
1951
2533
  // src/transcript/use-chat-transcript.ts
1952
- import { useCallback as useCallback7, useEffect as useEffect9, useRef as useRef8, useState as useState9 } from "react";
2534
+ import { useCallback as useCallback8, useEffect as useEffect10, useRef as useRef9, useState as useState10 } from "react";
1953
2535
 
1954
2536
  // src/transcript/model.ts
1955
2537
  import { readElicitationInput, validateElicitationAnswer as validateElicitationAnswer2 } from "@dudousxd/nestjs-agent-core";
@@ -2046,21 +2628,21 @@ function fillTemplate(template, context) {
2046
2628
  }).replace(/\s{2,}/g, " ").trim();
2047
2629
  }
2048
2630
  __name(fillTemplate, "fillTemplate");
2049
- function phraseFor(presentation, input, isSettled2, fallback = {
2631
+ function phraseFor(presentation, input, isSettled2, fallback2 = {
2050
2632
  running: "Working",
2051
2633
  done: "Done"
2052
2634
  }) {
2053
- if (presentation === void 0) return isSettled2 ? fallback.done : fallback.running;
2635
+ if (presentation === void 0) return isSettled2 ? fallback2.done : fallback2.running;
2054
2636
  const filled = fillTemplate(isSettled2 ? presentation.done : presentation.running, input);
2055
2637
  return filled === "" ? presentation.label : filled;
2056
2638
  }
2057
2639
  __name(phraseFor, "phraseFor");
2058
2640
 
2059
2641
  // src/presentation/result-view.ts
2060
- function isRecord(value) {
2642
+ function isRecord2(value) {
2061
2643
  return typeof value === "object" && value !== null && !Array.isArray(value);
2062
2644
  }
2063
- __name(isRecord, "isRecord");
2645
+ __name(isRecord2, "isRecord");
2064
2646
  function toText(value) {
2065
2647
  if (value === null || value === void 0) return "\u2014";
2066
2648
  if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
@@ -2071,7 +2653,7 @@ function toText(value) {
2071
2653
  }
2072
2654
  __name(toText, "toText");
2073
2655
  function inferResultView(output) {
2074
- if (!isRecord(output)) return void 0;
2656
+ if (!isRecord2(output)) return void 0;
2075
2657
  for (const [key, value] of Object.entries(output)) {
2076
2658
  if (!Array.isArray(value) || value.length === 0) continue;
2077
2659
  if (value.every((entry) => typeof entry === "string")) {
@@ -2080,12 +2662,12 @@ function inferResultView(output) {
2080
2662
  lines: key
2081
2663
  };
2082
2664
  }
2083
- if (value.every(isRecord)) {
2665
+ if (value.every(isRecord2)) {
2084
2666
  const first = value[0];
2085
2667
  return {
2086
2668
  kind: "table",
2087
2669
  rows: key,
2088
- columns: Object.keys(first).filter((column) => !isRecord(first[column])).map((column) => ({
2670
+ columns: Object.keys(first).filter((column) => !isRecord2(first[column])).map((column) => ({
2089
2671
  path: column,
2090
2672
  label: column
2091
2673
  }))
@@ -2461,7 +3043,7 @@ function isSettled(state) {
2461
3043
  __name(isSettled, "isSettled");
2462
3044
  function toolKind(part) {
2463
3045
  const metadata = part.toolMetadata;
2464
- return isRecord2(metadata) && typeof metadata.toolKind === "string" ? metadata.toolKind : void 0;
3046
+ return isRecord3(metadata) && typeof metadata.toolKind === "string" ? metadata.toolKind : void 0;
2465
3047
  }
2466
3048
  __name(toolKind, "toolKind");
2467
3049
  function isAwaitingApproval(part) {
@@ -2476,7 +3058,7 @@ function isAwaitingApproval(part) {
2476
3058
  __name(isAwaitingApproval, "isAwaitingApproval");
2477
3059
  function toolParentId(part) {
2478
3060
  const metadata = part.toolMetadata;
2479
- return isRecord2(metadata) && typeof metadata.parentId === "string" ? metadata.parentId : null;
3061
+ return isRecord3(metadata) && typeof metadata.parentId === "string" ? metadata.parentId : null;
2480
3062
  }
2481
3063
  __name(toolParentId, "toolParentId");
2482
3064
  function nestToolCalls(calls) {
@@ -2543,12 +3125,12 @@ function buildToolCall(part, options, approval, catalog) {
2543
3125
  __name(buildToolCall, "buildToolCall");
2544
3126
  function readElicitationRequest(part) {
2545
3127
  const input = part.input;
2546
- if (!isRecord2(input) || !Array.isArray(input.questions) || input.questions.length === 0) {
3128
+ if (!isRecord3(input) || !Array.isArray(input.questions) || input.questions.length === 0) {
2547
3129
  return null;
2548
3130
  }
2549
3131
  const questions = [];
2550
3132
  for (const candidate of input.questions) {
2551
- if (!isRecord2(candidate) || typeof candidate.id !== "string" || typeof candidate.prompt !== "string") {
3133
+ if (!isRecord3(candidate) || typeof candidate.id !== "string" || typeof candidate.prompt !== "string") {
2552
3134
  return null;
2553
3135
  }
2554
3136
  const input2 = readElicitationInput(candidate.input) ?? null;
@@ -2558,7 +3140,7 @@ function readElicitationRequest(part) {
2558
3140
  }
2559
3141
  const options = [];
2560
3142
  for (const option of rawOptions) {
2561
- if (!isRecord2(option) || typeof option.value !== "string" || typeof option.label !== "string") {
3143
+ if (!isRecord3(option) || typeof option.value !== "string" || typeof option.label !== "string") {
2562
3144
  return null;
2563
3145
  }
2564
3146
  options.push({
@@ -2586,7 +3168,7 @@ function readElicitationRequest(part) {
2586
3168
  __name(readElicitationRequest, "readElicitationRequest");
2587
3169
  function readElicitationOutcome(part) {
2588
3170
  const output = part.output;
2589
- if (!isRecord2(output) || !isRecord2(output.answers) || typeof output.skipped !== "boolean") {
3171
+ if (!isRecord3(output) || !isRecord3(output.answers) || typeof output.skipped !== "boolean") {
2590
3172
  return null;
2591
3173
  }
2592
3174
  const answers = {};
@@ -2723,7 +3305,7 @@ function readApprovals(parts) {
2723
3305
  continue;
2724
3306
  }
2725
3307
  const data = part.data;
2726
- if (!isRecord2(data) || typeof data.id !== "string") {
3308
+ if (!isRecord3(data) || typeof data.id !== "string") {
2727
3309
  continue;
2728
3310
  }
2729
3311
  const approval = entry(data.id);
@@ -2779,7 +3361,7 @@ function statusFromPart(call) {
2779
3361
  __name(statusFromPart, "statusFromPart");
2780
3362
  function readUiComponent(part) {
2781
3363
  const data = part.data;
2782
- if (!isRecord2(data) || typeof data.component !== "string") {
3364
+ if (!isRecord3(data) || typeof data.component !== "string") {
2783
3365
  return null;
2784
3366
  }
2785
3367
  const id = typeof data.id === "string" ? data.id : part.id;
@@ -2789,19 +3371,19 @@ function readUiComponent(part) {
2789
3371
  return {
2790
3372
  id,
2791
3373
  component: data.component,
2792
- props: isRecord2(data.props) ? data.props : {},
3374
+ props: isRecord3(data.props) ? data.props : {},
2793
3375
  version: typeof data.version === "number" ? data.version : null,
2794
3376
  toolCallId: typeof data.toolCallId === "string" ? data.toolCallId : null
2795
3377
  };
2796
3378
  }
2797
3379
  __name(readUiComponent, "readUiComponent");
2798
- function isRecord2(value) {
3380
+ function isRecord3(value) {
2799
3381
  return typeof value === "object" && value !== null;
2800
3382
  }
2801
- __name(isRecord2, "isRecord");
3383
+ __name(isRecord3, "isRecord");
2802
3384
  function readQuery(part) {
2803
3385
  const input = part.input;
2804
- if (!isRecord2(input) || typeof input.query !== "string") {
3386
+ if (!isRecord3(input) || typeof input.query !== "string") {
2805
3387
  return null;
2806
3388
  }
2807
3389
  return input.query;
@@ -2809,12 +3391,12 @@ function readQuery(part) {
2809
3391
  __name(readQuery, "readQuery");
2810
3392
  function readPassages(part) {
2811
3393
  const output = part.output;
2812
- if (!isRecord2(output) || !Array.isArray(output.passages) || output.passages.length === 0) {
3394
+ if (!isRecord3(output) || !Array.isArray(output.passages) || output.passages.length === 0) {
2813
3395
  return null;
2814
3396
  }
2815
3397
  const passages = [];
2816
3398
  for (const candidate of output.passages) {
2817
- if (!isRecord2(candidate) || typeof candidate.id !== "string" || typeof candidate.text !== "string") {
3399
+ if (!isRecord3(candidate) || typeof candidate.id !== "string" || typeof candidate.text !== "string") {
2818
3400
  return null;
2819
3401
  }
2820
3402
  passages.push({
@@ -2824,7 +3406,7 @@ function readPassages(part) {
2824
3406
  ...typeof candidate.source === "string" ? {
2825
3407
  source: candidate.source
2826
3408
  } : {},
2827
- ...isRecord2(candidate.metadata) ? {
3409
+ ...isRecord3(candidate.metadata) ? {
2828
3410
  metadata: candidate.metadata
2829
3411
  } : {}
2830
3412
  });
@@ -2926,11 +3508,11 @@ function formatCostUsd(cost) {
2926
3508
  __name(formatCostUsd, "formatCostUsd");
2927
3509
 
2928
3510
  // src/transcript/use-stick-to-bottom.ts
2929
- import { useCallback as useCallback6, useEffect as useEffect8, useRef as useRef7, useState as useState8 } from "react";
3511
+ import { useCallback as useCallback7, useEffect as useEffect9, useRef as useRef8, useState as useState9 } from "react";
2930
3512
  function useStickToBottom({ contentKey, threshold = 32 }) {
2931
- const containerRef = useRef7(null);
2932
- const [isAtBottom, setIsAtBottom] = useState8(true);
2933
- const measure = useCallback6(() => {
3513
+ const containerRef = useRef8(null);
3514
+ const [isAtBottom, setIsAtBottom] = useState9(true);
3515
+ const measure = useCallback7(() => {
2934
3516
  const element = containerRef.current;
2935
3517
  if (!element) {
2936
3518
  return;
@@ -2940,7 +3522,7 @@ function useStickToBottom({ contentKey, threshold = 32 }) {
2940
3522
  }, [
2941
3523
  threshold
2942
3524
  ]);
2943
- const scrollToBottom = useCallback6(() => {
3525
+ const scrollToBottom = useCallback7(() => {
2944
3526
  const element = containerRef.current;
2945
3527
  if (!element) {
2946
3528
  return;
@@ -2948,7 +3530,7 @@ function useStickToBottom({ contentKey, threshold = 32 }) {
2948
3530
  element.scrollTop = element.scrollHeight;
2949
3531
  setIsAtBottom(true);
2950
3532
  }, []);
2951
- const setContainer = useCallback6((element) => {
3533
+ const setContainer = useCallback7((element) => {
2952
3534
  containerRef.current = element;
2953
3535
  if (element) {
2954
3536
  measure();
@@ -2956,7 +3538,7 @@ function useStickToBottom({ contentKey, threshold = 32 }) {
2956
3538
  }, [
2957
3539
  measure
2958
3540
  ]);
2959
- useEffect8(() => {
3541
+ useEffect9(() => {
2960
3542
  if (isAtBottom) {
2961
3543
  scrollToBottom();
2962
3544
  }
@@ -2965,7 +3547,7 @@ function useStickToBottom({ contentKey, threshold = 32 }) {
2965
3547
  isAtBottom,
2966
3548
  scrollToBottom
2967
3549
  ]);
2968
- const getContainerProps = useCallback6(() => ({
3550
+ const getContainerProps = useCallback7(() => ({
2969
3551
  ref: setContainer,
2970
3552
  onScroll: measure
2971
3553
  }), [
@@ -2987,14 +3569,14 @@ var DEFAULT_LOAD_EARLIER_STEP = 50;
2987
3569
  var DEFAULT_COPY_RESET_MS = 1500;
2988
3570
  function useChatTranscript(options) {
2989
3571
  const { messages, status, initialVisibleCount = DEFAULT_VISIBLE_COUNT, loadEarlierStep = DEFAULT_LOAD_EARLIER_STEP, followUps, stickToBottomThreshold } = options;
2990
- const latest = useRef8(options);
3572
+ const latest = useRef9(options);
2991
3573
  latest.current = options;
2992
- const [visibleCount, setVisibleCount] = useState9(initialVisibleCount);
2993
- const [stopRequested, setStopRequested] = useState9(false);
3574
+ const [visibleCount, setVisibleCount] = useState10(initialVisibleCount);
3575
+ const [stopRequested, setStopRequested] = useState10(false);
2994
3576
  const isStreaming = status === "streaming" || status === "reconnecting";
2995
3577
  const isBusy = status === "submitted" || isStreaming;
2996
3578
  const isEmpty = messages.length === 0;
2997
- useEffect9(() => {
3579
+ useEffect10(() => {
2998
3580
  if (!isBusy) {
2999
3581
  setStopRequested(false);
3000
3582
  }
@@ -3011,7 +3593,7 @@ function useChatTranscript(options) {
3011
3593
  streamingMessageId,
3012
3594
  options
3013
3595
  });
3014
- const stop = useCallback7(() => {
3596
+ const stop = useCallback8(() => {
3015
3597
  const current = latest.current;
3016
3598
  if (current.status !== "submitted" && current.status !== "streaming" && current.status !== "reconnecting") {
3017
3599
  return;
@@ -3019,8 +3601,8 @@ function useChatTranscript(options) {
3019
3601
  setStopRequested(true);
3020
3602
  void current.onStop?.();
3021
3603
  }, []);
3022
- const loadEarlier = useCallback7(() => setVisibleCount((count) => count + (latest.current.loadEarlierStep ?? DEFAULT_LOAD_EARLIER_STEP)), []);
3023
- const showAll = useCallback7(() => setVisibleCount(latest.current.messages.length), []);
3604
+ const loadEarlier = useCallback8(() => setVisibleCount((count) => count + (latest.current.loadEarlierStep ?? DEFAULT_LOAD_EARLIER_STEP)), []);
3605
+ const showAll = useCallback8(() => setVisibleCount(latest.current.messages.length), []);
3024
3606
  const scroll = useStickToBottom({
3025
3607
  contentKey: contentSignature(messages),
3026
3608
  ...stickToBottomThreshold !== void 0 ? {
@@ -3056,7 +3638,7 @@ function useChatTranscript(options) {
3056
3638
  __name(useChatTranscript, "useChatTranscript");
3057
3639
  function useTranscriptItem(options) {
3058
3640
  const { message, isStreaming = false } = options;
3059
- const messagesRef = useRef8([
3641
+ const messagesRef = useRef9([
3060
3642
  message
3061
3643
  ]);
3062
3644
  if (messagesRef.current[0] !== message) {
@@ -3074,13 +3656,13 @@ function useTranscriptItem(options) {
3074
3656
  }
3075
3657
  __name(useTranscriptItem, "useTranscriptItem");
3076
3658
  function useTranscriptItems({ messages, visibleStart, streamingMessageId, options }) {
3077
- const [drafts, setDrafts] = useState9(() => /* @__PURE__ */ new Map());
3078
- const [copied, setCopied] = useState9(() => /* @__PURE__ */ new Set());
3079
- const [openReasoning, setOpenReasoning] = useState9(() => /* @__PURE__ */ new Map());
3080
- const [picks, setPicks] = useState9(() => /* @__PURE__ */ new Map());
3081
- const [settling, setSettling] = useState9(() => /* @__PURE__ */ new Map());
3082
- const [settleErrors, setSettleErrors] = useState9(() => /* @__PURE__ */ new Map());
3083
- const latest = useRef8({
3659
+ const [drafts, setDrafts] = useState10(() => /* @__PURE__ */ new Map());
3660
+ const [copied, setCopied] = useState10(() => /* @__PURE__ */ new Set());
3661
+ const [openReasoning, setOpenReasoning] = useState10(() => /* @__PURE__ */ new Map());
3662
+ const [picks, setPicks] = useState10(() => /* @__PURE__ */ new Map());
3663
+ const [settling, setSettling] = useState10(() => /* @__PURE__ */ new Map());
3664
+ const [settleErrors, setSettleErrors] = useState10(() => /* @__PURE__ */ new Map());
3665
+ const latest = useRef9({
3084
3666
  options,
3085
3667
  drafts,
3086
3668
  picks,
@@ -3092,23 +3674,23 @@ function useTranscriptItems({ messages, visibleStart, streamingMessageId, option
3092
3674
  picks,
3093
3675
  messages
3094
3676
  };
3095
- const copyTimers = useRef8(/* @__PURE__ */ new Map());
3096
- useEffect9(() => () => {
3677
+ const copyTimers = useRef9(/* @__PURE__ */ new Map());
3678
+ useEffect10(() => () => {
3097
3679
  for (const timer of copyTimers.current.values()) {
3098
3680
  clearTimeout(timer);
3099
3681
  }
3100
3682
  copyTimers.current.clear();
3101
3683
  }, []);
3102
- const callbackCache = useRef8(/* @__PURE__ */ new Map());
3103
- const reasoningToggleCache = useRef8(/* @__PURE__ */ new Map());
3104
- const toggleReasoning = useCallback7((key, open) => {
3684
+ const callbackCache = useRef9(/* @__PURE__ */ new Map());
3685
+ const reasoningToggleCache = useRef9(/* @__PURE__ */ new Map());
3686
+ const toggleReasoning = useCallback8((key, open) => {
3105
3687
  setOpenReasoning((current) => {
3106
3688
  const next = new Map(current);
3107
3689
  next.set(key, open ?? !(current.get(key) ?? false));
3108
3690
  return next;
3109
3691
  });
3110
3692
  }, []);
3111
- const stableToggle = useCallback7((key) => {
3693
+ const stableToggle = useCallback8((key) => {
3112
3694
  let cached = reasoningToggleCache.current.get(key);
3113
3695
  if (!cached) {
3114
3696
  cached = /* @__PURE__ */ __name((open) => toggleReasoning(key, open), "cached");
@@ -3118,10 +3700,10 @@ function useTranscriptItems({ messages, visibleStart, streamingMessageId, option
3118
3700
  }, [
3119
3701
  toggleReasoning
3120
3702
  ]);
3121
- const pick = useCallback7((toolCallId, questionId, values) => {
3703
+ const pick = useCallback8((toolCallId, questionId, values) => {
3122
3704
  setPicks((current) => new Map(current).set(pickKey(toolCallId, questionId), values));
3123
3705
  }, []);
3124
- const settle = useCallback7((toolCallId, action, send) => {
3706
+ const settle = useCallback8((toolCallId, action, send) => {
3125
3707
  setSettleErrors((current) => {
3126
3708
  if (!current.has(toolCallId)) {
3127
3709
  return current;
@@ -3145,7 +3727,7 @@ function useTranscriptItems({ messages, visibleStart, streamingMessageId, option
3145
3727
  failed(error);
3146
3728
  }
3147
3729
  }, []);
3148
- const answer = useCallback7((toolCallId) => {
3730
+ const answer = useCallback8((toolCallId) => {
3149
3731
  const current = latest.current;
3150
3732
  const onAnswer = current.options.onAnswer;
3151
3733
  if (!onAnswer) {
@@ -3155,7 +3737,7 @@ function useTranscriptItems({ messages, visibleStart, streamingMessageId, option
3155
3737
  }, [
3156
3738
  settle
3157
3739
  ]);
3158
- const skip = useCallback7((toolCallId) => {
3740
+ const skip = useCallback8((toolCallId) => {
3159
3741
  const onSkip = latest.current.options.onSkip;
3160
3742
  if (onSkip) {
3161
3743
  settle(toolCallId, "skip", () => onSkip(toolCallId));
@@ -3163,7 +3745,7 @@ function useTranscriptItems({ messages, visibleStart, streamingMessageId, option
3163
3745
  }, [
3164
3746
  settle
3165
3747
  ]);
3166
- const approve = useCallback7((toolCallId, options2) => {
3748
+ const approve = useCallback8((toolCallId, options2) => {
3167
3749
  const onApprove = latest.current.options.onApprove;
3168
3750
  if (onApprove) {
3169
3751
  settle(toolCallId, "approve", () => options2 === void 0 ? onApprove(toolCallId) : onApprove(toolCallId, options2));
@@ -3171,7 +3753,7 @@ function useTranscriptItems({ messages, visibleStart, streamingMessageId, option
3171
3753
  }, [
3172
3754
  settle
3173
3755
  ]);
3174
- const reject = useCallback7((toolCallId) => {
3756
+ const reject = useCallback8((toolCallId) => {
3175
3757
  const onReject = latest.current.options.onReject;
3176
3758
  if (onReject) {
3177
3759
  settle(toolCallId, "reject", () => onReject(toolCallId));
@@ -3179,7 +3761,7 @@ function useTranscriptItems({ messages, visibleStart, streamingMessageId, option
3179
3761
  }, [
3180
3762
  settle
3181
3763
  ]);
3182
- const callbacksFor = useCallback7((id) => {
3764
+ const callbacksFor = useCallback8((id) => {
3183
3765
  const cached = callbackCache.current.get(id);
3184
3766
  if (cached) {
3185
3767
  return cached;
@@ -3807,11 +4389,11 @@ function createSkillsSource(options) {
3807
4389
  if (cached) {
3808
4390
  return cached;
3809
4391
  }
3810
- const listSkills = options.client.listSkills;
4392
+ const listSkills = options.backend.listSkills;
3811
4393
  if (listSkills === void 0) {
3812
4394
  return Promise.reject(new AgentBackendUnsupportedError("listSkills"));
3813
4395
  }
3814
- const pending = listSkills.call(options.client, threadId).then((entries) => entries.map(toItem)).catch((error) => {
4396
+ const pending = listSkills.call(options.backend, threadId).then((entries) => entries.map(toItem)).catch((error) => {
3815
4397
  byThread.delete(key);
3816
4398
  throw error;
3817
4399
  });
@@ -3841,35 +4423,35 @@ function toItem(entry) {
3841
4423
  __name(toItem, "toItem");
3842
4424
 
3843
4425
  // src/composer/use-composer-autocomplete.ts
3844
- import { useCallback as useCallback8, useEffect as useEffect10, useId, useLayoutEffect, useMemo as useMemo6, useRef as useRef9, useState as useState10 } from "react";
4426
+ import { useCallback as useCallback9, useEffect as useEffect11, useId, useLayoutEffect, useMemo as useMemo9, useRef as useRef10, useState as useState11 } from "react";
3845
4427
  function useComposerAutocomplete(options) {
3846
4428
  const { value, sources, acceptOnTab = true } = options;
3847
- const latest = useRef9(options);
4429
+ const latest = useRef10(options);
3848
4430
  latest.current = options;
3849
- const inputRef = useRef9(null);
3850
- const [caret, setCaret] = useState10(value.length);
3851
- const [items, setItems] = useState10([]);
3852
- const [isLoading, setLoading] = useState10(false);
3853
- const [error, setError] = useState10(null);
3854
- const [activeIndex, setActiveIndex] = useState10(0);
3855
- const [dismissedIndex, setDismissedIndex] = useState10(null);
4431
+ const inputRef = useRef10(null);
4432
+ const [caret, setCaret] = useState11(value.length);
4433
+ const [items, setItems] = useState11([]);
4434
+ const [isLoading, setLoading] = useState11(false);
4435
+ const [error, setError] = useState11(null);
4436
+ const [activeIndex, setActiveIndex] = useState11(0);
4437
+ const [dismissedIndex, setDismissedIndex] = useState11(null);
3856
4438
  const safeCaret = Math.min(caret, value.length);
3857
- const match = useMemo6(() => findActiveTrigger(value, safeCaret, sources), [
4439
+ const match = useMemo9(() => findActiveTrigger(value, safeCaret, sources), [
3858
4440
  value,
3859
4441
  safeCaret,
3860
4442
  sources
3861
4443
  ]);
3862
4444
  const isActive = match !== null && dismissedIndex !== match.index;
3863
- const matchRef = useRef9(match);
4445
+ const matchRef = useRef10(match);
3864
4446
  matchRef.current = match;
3865
- const caretRef = useRef9(safeCaret);
4447
+ const caretRef = useRef10(safeCaret);
3866
4448
  caretRef.current = safeCaret;
3867
- const itemsRef = useRef9(items);
4449
+ const itemsRef = useRef10(items);
3868
4450
  itemsRef.current = items;
3869
- const activeIndexRef = useRef9(activeIndex);
4451
+ const activeIndexRef = useRef10(activeIndex);
3870
4452
  activeIndexRef.current = activeIndex;
3871
4453
  const requestKey = isActive && match ? `${match.source.id}\0${match.query}` : null;
3872
- useEffect10(() => {
4454
+ useEffect11(() => {
3873
4455
  const current = matchRef.current;
3874
4456
  if (requestKey === null || current === null) {
3875
4457
  setItems([]);
@@ -3919,23 +4501,23 @@ function useComposerAutocomplete(options) {
3919
4501
  const activeItem = isOpen ? items[activeIndex] ?? null : null;
3920
4502
  const reactId = useId();
3921
4503
  const listboxId = options.id ?? `agent-autocomplete-${reactId}`;
3922
- const optionId = useCallback8((index) => `${listboxId}-option-${index}`, [
4504
+ const optionId = useCallback9((index) => `${listboxId}-option-${index}`, [
3923
4505
  listboxId
3924
4506
  ]);
3925
- const highlight = useCallback8((index) => {
4507
+ const highlight = useCallback9((index) => {
3926
4508
  const total = itemsRef.current.length;
3927
4509
  if (total === 0) return;
3928
4510
  setActiveIndex((index % total + total) % total);
3929
4511
  }, []);
3930
- const moveHighlight = useCallback8((delta) => highlight(activeIndexRef.current + delta), [
4512
+ const moveHighlight = useCallback9((delta) => highlight(activeIndexRef.current + delta), [
3931
4513
  highlight
3932
4514
  ]);
3933
- const dismiss = useCallback8(() => {
4515
+ const dismiss = useCallback9(() => {
3934
4516
  const current = matchRef.current;
3935
4517
  if (current) setDismissedIndex(current.index);
3936
4518
  }, []);
3937
- const pendingCaret = useRef9(null);
3938
- const accept = useCallback8((item) => {
4519
+ const pendingCaret = useRef10(null);
4520
+ const accept = useCallback9((item) => {
3939
4521
  const current = matchRef.current;
3940
4522
  if (!current) return;
3941
4523
  const chosen = item ?? itemsRef.current[activeIndexRef.current];
@@ -3952,10 +4534,10 @@ function useComposerAutocomplete(options) {
3952
4534
  pendingCaret.current = null;
3953
4535
  inputRef.current?.setSelectionRange(position, position);
3954
4536
  });
3955
- const readCaret = useCallback8((element) => {
4537
+ const readCaret = useCallback9((element) => {
3956
4538
  setCaret(element.selectionStart ?? element.value.length);
3957
4539
  }, []);
3958
- const onKeyDown = useCallback8((event) => {
4540
+ const onKeyDown = useCallback9((event) => {
3959
4541
  if (!isOpen) return;
3960
4542
  const hasItems = itemsRef.current.length > 0;
3961
4543
  switch (event.key) {
@@ -3993,23 +4575,23 @@ function useComposerAutocomplete(options) {
3993
4575
  dismiss,
3994
4576
  moveHighlight
3995
4577
  ]);
3996
- const onChange = useCallback8((event) => {
4578
+ const onChange = useCallback9((event) => {
3997
4579
  readCaret(event.target);
3998
4580
  const next = findActiveTrigger(event.target.value, event.target.selectionStart ?? event.target.value.length, latest.current.sources);
3999
4581
  setDismissedIndex((current) => current !== null && next?.index === current ? current : null);
4000
4582
  }, [
4001
4583
  readCaret
4002
4584
  ]);
4003
- const onSelect = useCallback8((event) => readCaret(event.currentTarget), [
4585
+ const onSelect = useCallback9((event) => readCaret(event.currentTarget), [
4004
4586
  readCaret
4005
4587
  ]);
4006
- const onClick = useCallback8((event) => readCaret(event.currentTarget), [
4588
+ const onClick = useCallback9((event) => readCaret(event.currentTarget), [
4007
4589
  readCaret
4008
4590
  ]);
4009
- const setInput = useCallback8((element) => {
4591
+ const setInput = useCallback9((element) => {
4010
4592
  inputRef.current = element;
4011
4593
  }, []);
4012
- const getInputProps = useCallback8(() => ({
4594
+ const getInputProps = useCallback9(() => ({
4013
4595
  ref: setInput,
4014
4596
  onChange,
4015
4597
  onKeyDown,
@@ -4037,7 +4619,7 @@ function useComposerAutocomplete(options) {
4037
4619
  activeIndex,
4038
4620
  optionId
4039
4621
  ]);
4040
- const getListboxProps = useCallback8(() => ({
4622
+ const getListboxProps = useCallback9(() => ({
4041
4623
  id: listboxId,
4042
4624
  role: "listbox",
4043
4625
  "aria-label": match?.source.label ?? match?.source.id ?? "Suggestions"
@@ -4045,7 +4627,7 @@ function useComposerAutocomplete(options) {
4045
4627
  listboxId,
4046
4628
  match
4047
4629
  ]);
4048
- const getOptionProps = useCallback8((index) => ({
4630
+ const getOptionProps = useCallback9((index) => ({
4049
4631
  id: optionId(index),
4050
4632
  role: "option",
4051
4633
  "aria-selected": index === activeIndex
@@ -4079,7 +4661,7 @@ function isPromise(value) {
4079
4661
  __name(isPromise, "isPromise");
4080
4662
 
4081
4663
  // src/presentation/use-tool-catalog.ts
4082
- import { useCallback as useCallback9, useEffect as useEffect11, useMemo as useMemo7, useState as useState11 } from "react";
4664
+ import { useCallback as useCallback10, useEffect as useEffect12, useMemo as useMemo10, useState as useState12 } from "react";
4083
4665
  var shared = /* @__PURE__ */ new WeakMap();
4084
4666
  function load(client, agent) {
4085
4667
  let byAgent = shared.get(client);
@@ -4101,13 +4683,14 @@ function load(client, agent) {
4101
4683
  return request;
4102
4684
  }
4103
4685
  __name(load, "load");
4104
- function useToolCatalog(options) {
4105
- const { client, agent, enabled = true } = options;
4106
- const [entries, setEntries] = useState11([]);
4107
- const [isLoading, setLoading] = useState11(enabled);
4108
- const [error, setError] = useState11(null);
4109
- const [generation, setGeneration] = useState11(0);
4110
- useEffect11(() => {
4686
+ function useToolCatalog(options = {}) {
4687
+ const { agent, enabled = true } = options;
4688
+ const client = useAgentBackend(options.backend);
4689
+ const [entries, setEntries] = useState12([]);
4690
+ const [isLoading, setLoading] = useState12(enabled);
4691
+ const [error, setError] = useState12(null);
4692
+ const [generation, setGeneration] = useState12(0);
4693
+ useEffect12(() => {
4111
4694
  if (!enabled) {
4112
4695
  setLoading(false);
4113
4696
  return;
@@ -4133,14 +4716,14 @@ function useToolCatalog(options) {
4133
4716
  enabled,
4134
4717
  generation
4135
4718
  ]);
4136
- const refresh = useCallback9(() => {
4719
+ const refresh = useCallback10(() => {
4137
4720
  shared.get(client)?.delete(agent ?? "");
4138
4721
  setGeneration((current) => current + 1);
4139
4722
  }, [
4140
4723
  client,
4141
4724
  agent
4142
4725
  ]);
4143
- const catalog = useMemo7(() => toolCatalogFrom(entries), [
4726
+ const catalog = useMemo10(() => toolCatalogFrom(entries), [
4144
4727
  entries
4145
4728
  ]);
4146
4729
  return {
@@ -4154,7 +4737,7 @@ function useToolCatalog(options) {
4154
4737
  __name(useToolCatalog, "useToolCatalog");
4155
4738
 
4156
4739
  // src/approvals/countdown.ts
4157
- import { useEffect as useEffect12, useRef as useRef10, useState as useState12 } from "react";
4740
+ import { useEffect as useEffect13, useRef as useRef11, useState as useState13 } from "react";
4158
4741
  function approvalCountdown(expiresAt, now = Date.now()) {
4159
4742
  const deadline = expiresAt == null ? Number.NaN : Date.parse(expiresAt);
4160
4743
  if (!Number.isFinite(deadline)) {
@@ -4172,10 +4755,10 @@ function approvalCountdown(expiresAt, now = Date.now()) {
4172
4755
  __name(approvalCountdown, "approvalCountdown");
4173
4756
  function useApprovalCountdown(expiresAt, options = {}) {
4174
4757
  const { intervalMs = 1e3 } = options;
4175
- const nowRef = useRef10(options.now ?? Date.now);
4758
+ const nowRef = useRef11(options.now ?? Date.now);
4176
4759
  nowRef.current = options.now ?? Date.now;
4177
- const [state, setState] = useState12(() => approvalCountdown(expiresAt, nowRef.current()));
4178
- useEffect12(() => {
4760
+ const [state, setState] = useState13(() => approvalCountdown(expiresAt, nowRef.current()));
4761
+ useEffect13(() => {
4179
4762
  const read = /* @__PURE__ */ __name(() => approvalCountdown(expiresAt, nowRef.current()), "read");
4180
4763
  const first = read();
4181
4764
  setState(first);
@@ -4423,43 +5006,26 @@ __name(sumUsage, "sumUsage");
4423
5006
 
4424
5007
  // src/use-agent-chat.ts
4425
5008
  import { useChat } from "@ai-sdk/react";
4426
- import { useCallback as useCallback10, useEffect as useEffect13, useMemo as useMemo8, useRef as useRef11, useState as useState13 } from "react";
4427
- function useAgentChat(options) {
4428
- const latest = useRef11(options);
5009
+ import { useCallback as useCallback11, useEffect as useEffect14, useMemo as useMemo11, useRef as useRef12, useState as useState14 } from "react";
5010
+ function useAgentChat(options = {}) {
5011
+ const latest = useRef12(options);
4429
5012
  latest.current = options;
4430
- const [runId, setRunId] = useState13(options.resumeRunId);
4431
- const runIdRef = useRef11(runId);
5013
+ const [runId, setRunId] = useState14(options.resumeRunId);
5014
+ const runIdRef = useRef12(runId);
4432
5015
  runIdRef.current = runId;
4433
- const settlingRunIdRef = useRef11(void 0);
4434
- const autoResumeRunIdRef = useRef11(void 0);
4435
- const [autoResume, setAutoResume] = useState13(false);
4436
- const [activeRunId, setActiveRunId] = useState13(null);
4437
- const regenerateNext = useRef11(false);
4438
- const createdThreadId = useRef11(void 0);
4439
- const client = useMemo8(() => {
4440
- if (options.backend) return options.backend;
4441
- if (options.client) return options.client;
4442
- return new AgentClient({
4443
- ...options.baseUrl !== void 0 ? {
4444
- baseUrl: options.baseUrl
4445
- } : {},
4446
- ...options.credentials !== void 0 ? {
4447
- credentials: options.credentials
4448
- } : {},
4449
- ...options.fetch !== void 0 ? {
4450
- fetch: options.fetch
4451
- } : {},
4452
- ...options.attachments !== void 0 ? {
4453
- attachments: options.attachments
4454
- } : {},
4455
- getHeaders: /* @__PURE__ */ __name(async () => mergeHeaders(latest.current), "getHeaders")
4456
- });
4457
- }, []);
4458
- const [connection, setConnection] = useState13({
5016
+ const settlingRunIdRef = useRef12(void 0);
5017
+ const autoResumeRunIdRef = useRef12(void 0);
5018
+ const [autoResume, setAutoResume] = useState14(false);
5019
+ const [activeRunId, setActiveRunId] = useState14(null);
5020
+ const regenerateNext = useRef12(false);
5021
+ const createdThreadId = useRef12(void 0);
5022
+ const resolved = useAgentBackend(options.backend);
5023
+ const client = useRef12(resolved).current;
5024
+ const [connection, setConnection] = useState14({
4459
5025
  status: "live"
4460
5026
  });
4461
- const resyncAfterSettle = useRef11(false);
4462
- useEffect13(() => {
5027
+ const resyncAfterSettle = useRef12(false);
5028
+ useEffect14(() => {
4463
5029
  if (!options.resume || options.threadId === void 0) return;
4464
5030
  let cancelled = false;
4465
5031
  const threadId = options.threadId;
@@ -4479,7 +5045,7 @@ function useAgentChat(options) {
4479
5045
  options.resume,
4480
5046
  options.threadId
4481
5047
  ]);
4482
- const transport = useMemo8(() => {
5048
+ const transport = useMemo11(() => {
4483
5049
  function onMeta(meta) {
4484
5050
  settlingRunIdRef.current = meta.runId;
4485
5051
  setRunId(meta.runId);
@@ -4534,7 +5100,7 @@ function useAgentChat(options) {
4534
5100
  }, "onAttemptStart")
4535
5101
  });
4536
5102
  }, []);
4537
- const backgroundRef = useRef11(() => Promise.resolve());
5103
+ const backgroundRef = useRef12(() => Promise.resolve());
4538
5104
  const chat = useChat({
4539
5105
  transport,
4540
5106
  resume: options.resumeRunId !== void 0 || autoResume,
@@ -4583,7 +5149,7 @@ function useAgentChat(options) {
4583
5149
  }
4584
5150
  }, "onFinish")
4585
5151
  });
4586
- const chatRef = useRef11(chat);
5152
+ const chatRef = useRef12(chat);
4587
5153
  chatRef.current = chat;
4588
5154
  async function resyncFromThread() {
4589
5155
  const threadId = latest.current.threadId ?? createdThreadId.current;
@@ -4595,11 +5161,11 @@ function useAgentChat(options) {
4595
5161
  }
4596
5162
  }
4597
5163
  __name(resyncFromThread, "resyncFromThread");
4598
- const turnInFlight = useRef11(false);
4599
- const isTurnInFlight = useCallback10(() => turnInFlight.current || transport.isAttemptLive, [
5164
+ const turnInFlight = useRef12(false);
5165
+ const isTurnInFlight = useCallback11(() => turnInFlight.current || transport.isAttemptLive, [
4600
5166
  transport
4601
5167
  ]);
4602
- const sendMessage = useCallback10(async (...args) => {
5168
+ const sendMessage = useCallback11(async (...args) => {
4603
5169
  const blocked = latest.current.blocked;
4604
5170
  if (blocked != null) throw new QuotaBlockedError(blocked);
4605
5171
  if (isTurnInFlight()) return;
@@ -4612,15 +5178,15 @@ function useAgentChat(options) {
4612
5178
  }, [
4613
5179
  isTurnInFlight
4614
5180
  ]);
4615
- const addToolResult = useCallback10(({ tool, toolCallId, output }) => chatRef.current.addToolResult({
5181
+ const addToolResult = useCallback11(({ tool, toolCallId, output }) => chatRef.current.addToolResult({
4616
5182
  tool,
4617
5183
  toolCallId,
4618
5184
  output
4619
5185
  }), []);
4620
- const [threads, setThreads] = useState13([]);
4621
- const [quota, setQuota] = useState13(null);
4622
- const [backgroundRuns, setBackgroundRuns] = useState13([]);
4623
- const refreshBackground = useCallback10(async () => {
5186
+ const [threads, setThreads] = useState14([]);
5187
+ const [quota, setQuota] = useState14(null);
5188
+ const [backgroundRuns, setBackgroundRuns] = useState14([]);
5189
+ const refreshBackground = useCallback11(async () => {
4624
5190
  const threadId = latest.current.threadId ?? createdThreadId.current;
4625
5191
  if (threadId === void 0) {
4626
5192
  return;
@@ -4645,7 +5211,7 @@ function useAgentChat(options) {
4645
5211
  ]);
4646
5212
  backgroundRef.current = refreshBackground;
4647
5213
  const isWorking = backgroundRuns.some((run) => run.status === "running");
4648
- useEffect13(() => {
5214
+ useEffect14(() => {
4649
5215
  if (options.background !== true || options.threadId === void 0) {
4650
5216
  return;
4651
5217
  }
@@ -4655,7 +5221,7 @@ function useAgentChat(options) {
4655
5221
  options.threadId,
4656
5222
  refreshBackground
4657
5223
  ]);
4658
- useEffect13(() => {
5224
+ useEffect14(() => {
4659
5225
  const every = latest.current.backgroundPollMs ?? 5e3;
4660
5226
  if (latest.current.background !== true || !isWorking || every <= 0) {
4661
5227
  return;
@@ -4666,26 +5232,26 @@ function useAgentChat(options) {
4666
5232
  isWorking,
4667
5233
  refreshBackground
4668
5234
  ]);
4669
- const loadThreads = useCallback10(async () => {
5235
+ const loadThreads = useCallback11(async () => {
4670
5236
  const list = await client.listThreads();
4671
5237
  setThreads(list);
4672
5238
  return list;
4673
5239
  }, [
4674
5240
  client
4675
5241
  ]);
4676
- const loadThread = useCallback10((id) => client.getThread(id), [
5242
+ const loadThread = useCallback11((id) => client.getThread(id), [
4677
5243
  client
4678
5244
  ]);
4679
- const deleteThread = useCallback10(async (id) => {
5245
+ const deleteThread = useCallback11(async (id) => {
4680
5246
  await client.deleteThread(id);
4681
5247
  setThreads((current) => current.filter((thread) => thread.id !== id));
4682
5248
  }, [
4683
5249
  client
4684
5250
  ]);
4685
- const forkThread = useCallback10((threadId, messageId) => requireBackendMethod(client, "forkFromMessage")(threadId, messageId), [
5251
+ const forkThread = useCallback11((threadId, messageId) => requireBackendMethod(client, "forkFromMessage")(threadId, messageId), [
4686
5252
  client
4687
5253
  ]);
4688
- const renameThread = useCallback10(async (id, title) => {
5254
+ const renameThread = useCallback11(async (id, title) => {
4689
5255
  await client.updateThread(id, {
4690
5256
  title
4691
5257
  });
@@ -4696,24 +5262,24 @@ function useAgentChat(options) {
4696
5262
  }, [
4697
5263
  client
4698
5264
  ]);
4699
- const promoteThread = useCallback10(async (id) => {
5265
+ const promoteThread = useCallback11(async (id) => {
4700
5266
  await requireBackendMethod(client, "promoteThread")(id);
4701
5267
  await loadThreads();
4702
5268
  }, [
4703
5269
  client,
4704
5270
  loadThreads
4705
5271
  ]);
4706
- const truncateFromMessage = useCallback10((threadId, messageId) => requireBackendMethod(client, "truncateFromMessage")(threadId, messageId).then(() => void 0), [
5272
+ const truncateFromMessage = useCallback11((threadId, messageId) => requireBackendMethod(client, "truncateFromMessage")(threadId, messageId).then(() => void 0), [
4707
5273
  client
4708
5274
  ]);
4709
- const loadQuota = useCallback10(async () => {
5275
+ const loadQuota = useCallback11(async () => {
4710
5276
  const today = await requireBackendMethod(client, "getQuotaToday")();
4711
5277
  setQuota(today);
4712
5278
  return today;
4713
5279
  }, [
4714
5280
  client
4715
5281
  ]);
4716
- const cancel = useCallback10(async () => {
5282
+ const cancel = useCallback11(async () => {
4717
5283
  chatRef.current.stop();
4718
5284
  const activeRunId2 = runIdRef.current;
4719
5285
  if (activeRunId2) {
@@ -4725,7 +5291,7 @@ function useAgentChat(options) {
4725
5291
  }, [
4726
5292
  client
4727
5293
  ]);
4728
- const approve = useCallback10(async ({ toolCallId, remember, via }) => {
5294
+ const approve = useCallback11(async ({ toolCallId, remember, via }) => {
4729
5295
  await requireBackendMethod(client, "approveToolCall")({
4730
5296
  toolCallId,
4731
5297
  ...remember === true ? {
@@ -4738,7 +5304,7 @@ function useAgentChat(options) {
4738
5304
  }, [
4739
5305
  client
4740
5306
  ]);
4741
- const reject = useCallback10(async ({ toolCallId, reason, via }) => {
5307
+ const reject = useCallback11(async ({ toolCallId, reason, via }) => {
4742
5308
  await requireBackendMethod(client, "rejectToolCall")({
4743
5309
  toolCallId,
4744
5310
  ...reason !== void 0 ? {
@@ -4751,7 +5317,7 @@ function useAgentChat(options) {
4751
5317
  }, [
4752
5318
  client
4753
5319
  ]);
4754
- const answer = useCallback10(async ({ toolCallId, answers }) => {
5320
+ const answer = useCallback11(async ({ toolCallId, answers }) => {
4755
5321
  await requireBackendMethod(client, "answerToolCall")({
4756
5322
  toolCallId,
4757
5323
  ...answers !== void 0 ? {
@@ -4761,14 +5327,14 @@ function useAgentChat(options) {
4761
5327
  }, [
4762
5328
  client
4763
5329
  ]);
4764
- const skip = useCallback10(async ({ toolCallId }) => {
5330
+ const skip = useCallback11(async ({ toolCallId }) => {
4765
5331
  await requireBackendMethod(client, "skipToolCall")({
4766
5332
  toolCallId
4767
5333
  });
4768
5334
  }, [
4769
5335
  client
4770
5336
  ]);
4771
- const regenerate = useCallback10(() => {
5337
+ const regenerate = useCallback11(() => {
4772
5338
  const blocked = latest.current.blocked;
4773
5339
  if (blocked != null) throw new QuotaBlockedError(blocked);
4774
5340
  if (isTurnInFlight()) return;
@@ -4785,7 +5351,7 @@ function useAgentChat(options) {
4785
5351
  isWorking,
4786
5352
  refresh: refreshBackground
4787
5353
  };
4788
- const setThreadModel = useCallback10(async (model) => {
5354
+ const setThreadModel = useCallback11(async (model) => {
4789
5355
  const threadId = latest.current.threadId ?? createdThreadId.current;
4790
5356
  if (threadId === void 0) {
4791
5357
  throw new Error("setThreadModel: this chat has no thread yet");
@@ -4799,7 +5365,7 @@ function useAgentChat(options) {
4799
5365
  }, [
4800
5366
  client
4801
5367
  ]);
4802
- const getThreadId = useCallback10(() => latest.current.threadId ?? createdThreadId.current, []);
5368
+ const getThreadId = useCallback11(() => latest.current.threadId ?? createdThreadId.current, []);
4803
5369
  const status = connection.status === "reconnecting" ? "reconnecting" : chat.status;
4804
5370
  return {
4805
5371
  ...chat,
@@ -4819,10 +5385,8 @@ function useAgentChat(options) {
4819
5385
  */
4820
5386
  getThreadId,
4821
5387
  setThreadModel,
4822
- /** The backend this chat talks to — pass it to `useThreads`, `useMessageFeedback`, … */
5388
+ /** The backend this chat talks to — the same one every other hook under the provider uses. */
4823
5389
  backend: client,
4824
- /** Same object as {@link backend}; kept for callers that read it under its old name. */
4825
- client,
4826
5390
  threads,
4827
5391
  loadThreads,
4828
5392
  loadThread,
@@ -4852,19 +5416,12 @@ var QuotaBlockedError = class extends Error {
4852
5416
  this.name = "QuotaBlockedError";
4853
5417
  }
4854
5418
  };
4855
- async function mergeHeaders(options) {
4856
- const dynamic = await options.getHeaders?.() ?? {};
4857
- return {
4858
- ...options.headers,
4859
- ...dynamic
4860
- };
4861
- }
4862
- __name(mergeHeaders, "mergeHeaders");
4863
5419
  export {
4864
5420
  AgentBackendUnsupportedError,
4865
5421
  AgentChatTransport,
4866
5422
  AgentClient,
4867
5423
  AgentHttpError,
5424
+ AgentProvider,
4868
5425
  AmbientRenderUiContext,
4869
5426
  ChatInput,
4870
5427
  DEFAULT_SPEECH_LANG,
@@ -4910,6 +5467,7 @@ export {
4910
5467
  storedThreadToUiMessages,
4911
5468
  toolCallState,
4912
5469
  toolCatalogFrom,
5470
+ useAgentBackend,
4913
5471
  useAgentChat,
4914
5472
  useAgents,
4915
5473
  useAmbientRenderUi,