dooers-agents-client 0.8.0 → 0.9.2

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/main.cjs CHANGED
@@ -49,6 +49,7 @@ function toThread(w) {
49
49
  owner: toUser(w.owner),
50
50
  users: w.users.map((u) => toUser(u)),
51
51
  title: w.title,
52
+ metadata: w.metadata ?? null,
52
53
  createdAt: w.created_at,
53
54
  updatedAt: w.updated_at,
54
55
  lastEventAt: w.last_event_at
@@ -245,6 +246,8 @@ function toWireContentPart(p) {
245
246
  ref_id: p.refId
246
247
  };
247
248
  if (p.duration != null) w.duration = p.duration;
249
+ if (p.filename?.trim()) w.filename = p.filename.trim();
250
+ if (p.mimeType?.trim()) w.mime_type = p.mimeType.trim();
248
251
  if (p.url) w.url = p.url;
249
252
  return w;
250
253
  }
@@ -253,6 +256,8 @@ function toWireContentPart(p) {
253
256
  type: "image",
254
257
  ref_id: p.refId
255
258
  };
259
+ if (p.filename?.trim()) w.filename = p.filename.trim();
260
+ if (p.mimeType?.trim()) w.mime_type = p.mimeType.trim();
256
261
  if (p.url) w.url = p.url;
257
262
  return w;
258
263
  }
@@ -261,6 +266,8 @@ function toWireContentPart(p) {
261
266
  type: "document",
262
267
  ref_id: p.refId
263
268
  };
269
+ if (p.filename?.trim()) w.filename = p.filename.trim();
270
+ if (p.mimeType?.trim()) w.mime_type = p.mimeType.trim();
264
271
  if (p.url) w.url = p.url;
265
272
  return w;
266
273
  }
@@ -271,6 +278,35 @@ function toWireContentPart(p) {
271
278
  var MAX_RECONNECT_ATTEMPTS = 5;
272
279
  var RECONNECT_DELAYS = [1e3, 2e3, 4e3, 8e3, 16e3];
273
280
  var SEND_MESSAGE_TIMEOUT = 3e4;
281
+ function blobPartFilename(blob, override) {
282
+ const o = (override ?? "").trim();
283
+ if (o) return o;
284
+ const t = (blob.type || "").toLowerCase();
285
+ if (t.includes("webm")) return "recording.webm";
286
+ if (t.includes("ogg")) return "recording.ogg";
287
+ if (t.includes("mpeg") || t.includes("mp3")) return "recording.mp3";
288
+ if (t.includes("mp4") || t.includes("m4a") || t.includes("aac")) return "recording.m4a";
289
+ if (t.startsWith("audio/")) return `recording.${t.split("/")[1]?.split("+")[0] || "bin"}`;
290
+ return "recording.bin";
291
+ }
292
+ async function readHttpErrorMessage(response) {
293
+ const raw = await response.text().catch(() => "") || "";
294
+ const trimmed = raw.trim();
295
+ if (!trimmed) {
296
+ return `Upload failed: ${response.status} ${response.statusText}`.trim();
297
+ }
298
+ try {
299
+ const j = JSON.parse(trimmed);
300
+ const d = j.detail;
301
+ if (typeof d === "string") return d;
302
+ if (Array.isArray(d) && d.length > 0) {
303
+ const first = d[0];
304
+ if (first && typeof first.msg === "string") return first.msg;
305
+ }
306
+ } catch {
307
+ }
308
+ return trimmed.length > 300 ? `${trimmed.slice(0, 300)}\u2026` : trimmed;
309
+ }
274
310
  var AgentServerClient = class {
275
311
  wsUrl;
276
312
  constructor(apiMessagesUrl) {
@@ -364,6 +400,12 @@ var AgentClient = class {
364
400
  url = "";
365
401
  httpBaseUrl = "";
366
402
  agentId = "";
403
+ /** Mirrors ``AgentProvider`` ``agentId`` so HTTP uploads work before WS ``connect`` completes. */
404
+ uploadAgentId = "";
405
+ /** Current chat thread id for ``POST /uploads`` (aligns GCS path with ``hydrate_thread_events``). */
406
+ uploadThreadId = "";
407
+ /** Optional run id for ``POST /uploads`` (metadata only). */
408
+ uploadRunId = "";
367
409
  uploadUrl;
368
410
  config = {
369
411
  organizationId: "",
@@ -378,7 +420,7 @@ var AgentClient = class {
378
420
  subscriptionRefs = /* @__PURE__ */ new Map();
379
421
  // Track optimistic events for reconciliation
380
422
  pendingOptimistic = /* @__PURE__ */ new Map();
381
- // Pending message promises — resolved when event.append arrives with matching clientEventId
423
+ // Pending message promises — keyed by outbound frame id (same as client_event_id for sends).
382
424
  pendingMessages = /* @__PURE__ */ new Map();
383
425
  // Track last event ID per thread for gap recovery on reconnect
384
426
  lastEventIds = /* @__PURE__ */ new Map();
@@ -396,14 +438,40 @@ var AgentClient = class {
396
438
  setUploadUrl(url) {
397
439
  this.uploadUrl = url;
398
440
  }
399
- async upload(file) {
441
+ /** Sync from ``AgentProvider`` ``agentId``; used for ``POST /uploads`` ``agent_id`` (non-WS). */
442
+ setUploadAgentId(agentId) {
443
+ this.uploadAgentId = (agentId ?? "").trim();
444
+ }
445
+ /** Sync active thread id for chat uploads (must match persisted thread for signed URL keys). */
446
+ setUploadThreadId(threadId) {
447
+ this.uploadThreadId = (threadId ?? "").trim();
448
+ }
449
+ setUploadRunId(runId) {
450
+ this.uploadRunId = (runId ?? "").trim();
451
+ }
452
+ async upload(file, options) {
400
453
  if (!this.uploadUrl) {
401
454
  throw new Error("uploadUrl not configured");
402
455
  }
456
+ const aid = (this.uploadAgentId || this.agentId || "").trim();
457
+ if (!aid) {
458
+ throw new Error("agentId is required for upload (set AgentProvider agentId)");
459
+ }
403
460
  const formData = new FormData();
404
- formData.append("file", file);
405
- if (this.agentId) {
406
- formData.append("agent_id", this.agentId);
461
+ if (file instanceof File) {
462
+ const partName = options?.filename?.trim() || file.name.trim() || "upload";
463
+ formData.append("file", file, partName);
464
+ } else {
465
+ formData.append("file", file, blobPartFilename(file, options?.filename));
466
+ }
467
+ formData.append("agent_id", aid);
468
+ const tid = this.uploadThreadId.trim();
469
+ if (tid) {
470
+ formData.append("thread_id", tid);
471
+ }
472
+ const rid = this.uploadRunId.trim();
473
+ if (rid) {
474
+ formData.append("run_id", rid);
407
475
  }
408
476
  const headers = {};
409
477
  if (this.config.authToken) {
@@ -415,7 +483,8 @@ var AgentClient = class {
415
483
  headers
416
484
  });
417
485
  if (!response.ok) {
418
- throw new Error(`Upload failed: ${response.status} ${response.statusText}`);
486
+ const detail = await readHttpErrorMessage(response);
487
+ throw new Error(detail);
419
488
  }
420
489
  const result = await response.json();
421
490
  return {
@@ -429,6 +498,7 @@ var AgentClient = class {
429
498
  connect(url, agentId, config) {
430
499
  this.url = apiMessagesUrlToWebSocketUrl(url);
431
500
  this.agentId = agentId;
501
+ this.uploadAgentId = agentId.trim();
432
502
  this.config = config ?? { organizationId: "", workspaceId: "", userId: "" };
433
503
  this.isIntentionallyClosed = false;
434
504
  try {
@@ -444,16 +514,29 @@ var AgentClient = class {
444
514
  this.callbacks.setConnectionStatus("connecting");
445
515
  this.createConnection();
446
516
  }
517
+ /** Clear the last in-chat send error banner (see ``connection.sendError``). */
518
+ clearSendError() {
519
+ this.callbacks.setSendError(null);
520
+ }
521
+ abortPendingMessages(reason) {
522
+ for (const [clientEventId, pending] of this.pendingMessages) {
523
+ clearTimeout(pending.timer);
524
+ const opt = this.pendingOptimistic.get(clientEventId);
525
+ if (opt?.threadId) {
526
+ this.callbacks.removeOptimistic(opt.threadId, clientEventId);
527
+ }
528
+ this.pendingOptimistic.delete(clientEventId);
529
+ pending.reject(new Error(reason));
530
+ }
531
+ this.pendingMessages.clear();
532
+ }
447
533
  disconnect() {
448
534
  this.isIntentionallyClosed = true;
449
535
  if (this.reconnectTimer) {
450
536
  clearTimeout(this.reconnectTimer);
451
537
  this.reconnectTimer = null;
452
538
  }
453
- for (const [, pending] of this.pendingMessages) {
454
- clearTimeout(pending.timer);
455
- }
456
- this.pendingMessages.clear();
539
+ this.abortPendingMessages("Disconnected");
457
540
  if (this.ws) {
458
541
  this.ws.onopen = null;
459
542
  this.ws.onmessage = null;
@@ -545,6 +628,7 @@ var AgentClient = class {
545
628
  }
546
629
  // --- Messaging ---
547
630
  sendMessage(params) {
631
+ this.callbacks.setSendError(null);
548
632
  const clientEventId = crypto.randomUUID();
549
633
  const content = params.content ? params.content.map(toWireContentPart) : [{ type: "text", text: params.text ?? "" }];
550
634
  const displayContent = params.content ? params.content.map((p) => {
@@ -552,11 +636,27 @@ var AgentClient = class {
552
636
  case "text":
553
637
  return { type: "text", text: p.text };
554
638
  case "audio":
555
- return { type: "audio", duration: p.duration };
639
+ return {
640
+ type: "audio",
641
+ duration: p.duration,
642
+ ...p.url ? { url: p.url } : {},
643
+ ...p.mimeType ? { mimeType: p.mimeType } : {},
644
+ ...p.filename ? { filename: p.filename } : {}
645
+ };
556
646
  case "image":
557
- return { type: "image" };
647
+ return {
648
+ type: "image",
649
+ ...p.url ? { url: p.url } : {},
650
+ ...p.mimeType ? { mimeType: p.mimeType } : {},
651
+ ...p.filename ? { filename: p.filename } : {}
652
+ };
558
653
  case "document":
559
- return { type: "document" };
654
+ return {
655
+ type: "document",
656
+ ...p.url ? { url: p.url } : {},
657
+ ...p.mimeType ? { mimeType: p.mimeType } : {},
658
+ ...p.filename ? { filename: p.filename } : {}
659
+ };
560
660
  default:
561
661
  return { type: "text", text: "" };
562
662
  }
@@ -588,7 +688,7 @@ var AgentClient = class {
588
688
  clientEventId
589
689
  });
590
690
  const promise = this.createPendingPromise(clientEventId);
591
- this.send("event.create", {
691
+ const payload = {
592
692
  thread_id: params.threadId,
593
693
  client_event_id: clientEventId,
594
694
  event: {
@@ -596,23 +696,36 @@ var AgentClient = class {
596
696
  actor: "user",
597
697
  content
598
698
  }
699
+ };
700
+ if (params.metadata) {
701
+ payload.metadata = params.metadata;
702
+ }
703
+ this.sendRaw({
704
+ id: clientEventId,
705
+ type: "event.create",
706
+ payload
599
707
  });
600
708
  return promise;
601
709
  }
602
710
  sendFormResponse(params) {
711
+ this.callbacks.setSendError(null);
603
712
  const clientEventId = crypto.randomUUID();
604
713
  const promise = this.createPendingPromise(clientEventId);
605
- this.send("event.create", {
606
- thread_id: params.threadId,
607
- client_event_id: clientEventId,
608
- event: {
609
- type: "form.response",
610
- actor: "user",
611
- content: [],
612
- data: {
613
- form_event_id: params.formEventId,
614
- cancelled: params.cancelled,
615
- values: params.values
714
+ this.sendRaw({
715
+ id: clientEventId,
716
+ type: "event.create",
717
+ payload: {
718
+ thread_id: params.threadId,
719
+ client_event_id: clientEventId,
720
+ event: {
721
+ type: "form.response",
722
+ actor: "user",
723
+ content: [],
724
+ data: {
725
+ form_event_id: params.formEventId,
726
+ cancelled: params.cancelled,
727
+ values: params.values
728
+ }
616
729
  }
617
730
  }
618
731
  });
@@ -622,14 +735,20 @@ var AgentClient = class {
622
735
  createPendingPromise(clientEventId) {
623
736
  return new Promise((resolve, reject) => {
624
737
  const timer = setTimeout(() => {
738
+ const opt = this.pendingOptimistic.get(clientEventId);
739
+ if (opt?.threadId) {
740
+ this.callbacks.removeOptimistic(opt.threadId, clientEventId);
741
+ }
742
+ this.pendingOptimistic.delete(clientEventId);
625
743
  this.pendingMessages.delete(clientEventId);
626
744
  reject(new Error("Request timed out waiting for server response"));
627
745
  }, SEND_MESSAGE_TIMEOUT);
628
- this.pendingMessages.set(clientEventId, { resolve, timer });
746
+ this.pendingMessages.set(clientEventId, { resolve, reject, timer });
629
747
  });
630
748
  }
631
749
  createConnection() {
632
750
  if (this.ws) {
751
+ this.abortPendingMessages("Connection lost; reconnecting");
633
752
  this.ws.onopen = null;
634
753
  this.ws.onmessage = null;
635
754
  this.ws.onclose = null;
@@ -697,9 +816,26 @@ var AgentClient = class {
697
816
  this.callbacks.setConnectionStatus("error", frame.payload.error?.message);
698
817
  }
699
818
  } else if (!frame.payload.ok && frame.payload.error) {
819
+ const ackId = frame.payload.ack_id;
820
+ const err = frame.payload.error;
821
+ if (ackId) {
822
+ const pending = this.pendingMessages.get(ackId);
823
+ if (pending) {
824
+ clearTimeout(pending.timer);
825
+ this.pendingMessages.delete(ackId);
826
+ const msg = err.message || "Request rejected";
827
+ const opt = this.pendingOptimistic.get(ackId);
828
+ if (opt?.threadId) {
829
+ this.callbacks.removeOptimistic(opt.threadId, ackId);
830
+ }
831
+ this.pendingOptimistic.delete(ackId);
832
+ pending.reject(new Error(msg));
833
+ this.callbacks.setSendError(msg);
834
+ }
835
+ }
700
836
  this.onError?.({
701
- code: frame.payload.error.code,
702
- message: frame.payload.error.message,
837
+ code: err.code,
838
+ message: err.message,
703
839
  frameType: "ack"
704
840
  });
705
841
  }
@@ -736,6 +872,7 @@ var AgentClient = class {
736
872
  case "event.append": {
737
873
  const events = this.resolveEventUrls(frame.payload.events.map(toThreadEvent));
738
874
  const resolvedClientEventIds = [];
875
+ const pendingIdsToResolve = [];
739
876
  for (const event of events) {
740
877
  if (event.clientEventId && this.pendingOptimistic.has(event.clientEventId)) {
741
878
  resolvedClientEventIds.push(event.clientEventId);
@@ -745,8 +882,7 @@ var AgentClient = class {
745
882
  const pendingMessage = this.pendingMessages.get(event.clientEventId);
746
883
  if (pendingMessage) {
747
884
  clearTimeout(pendingMessage.timer);
748
- pendingMessage.resolve({ threadId: frame.payload.thread_id });
749
- this.pendingMessages.delete(event.clientEventId);
885
+ pendingIdsToResolve.push(event.clientEventId);
750
886
  }
751
887
  }
752
888
  }
@@ -759,6 +895,14 @@ var AgentClient = class {
759
895
  } else {
760
896
  this.callbacks.onEventAppend(frame.payload.thread_id, events);
761
897
  }
898
+ const tid = frame.payload.thread_id;
899
+ for (const id of pendingIdsToResolve) {
900
+ const pending = this.pendingMessages.get(id);
901
+ if (pending) {
902
+ pending.resolve({ threadId: tid });
903
+ this.pendingMessages.delete(id);
904
+ }
905
+ }
762
906
  break;
763
907
  }
764
908
  case "event.list.result": {
@@ -811,6 +955,7 @@ var AgentClient = class {
811
955
  }
812
956
  scheduleReconnect() {
813
957
  if (this.reconnectAttempts >= MAX_RECONNECT_ATTEMPTS) {
958
+ this.abortPendingMessages("Connection lost after maximum retries");
814
959
  this.callbacks.setReconnectFailed();
815
960
  this.callbacks.setConnectionStatus("error", "Connection lost after maximum retries");
816
961
  return;
@@ -845,6 +990,43 @@ var AgentClient = class {
845
990
  });
846
991
  }
847
992
  };
993
+ function mergeDisplayContentParts(prev, next) {
994
+ if (!next?.length) return prev;
995
+ if (!prev?.length) return next;
996
+ const out = [];
997
+ const len = Math.max(prev.length, next.length);
998
+ for (let i = 0; i < len; i++) {
999
+ const p = prev[i];
1000
+ const n = next[i];
1001
+ if (!n) {
1002
+ if (p) out.push(p);
1003
+ continue;
1004
+ }
1005
+ if (!p) {
1006
+ out.push(n);
1007
+ continue;
1008
+ }
1009
+ if (p.type !== n.type) {
1010
+ out.push(n);
1011
+ continue;
1012
+ }
1013
+ if (n.type === "image" || n.type === "audio" || n.type === "document") {
1014
+ const url = n.url ?? ("url" in p ? p.url : void 0);
1015
+ out.push({ ...p, ...n, ...url ? { url } : {} });
1016
+ continue;
1017
+ }
1018
+ out.push(n);
1019
+ }
1020
+ return out;
1021
+ }
1022
+ function mergeThreadEventById(prev, next) {
1023
+ const content = mergeDisplayContentParts(prev.content, next.content);
1024
+ return {
1025
+ ...prev,
1026
+ ...next,
1027
+ ...content !== void 0 ? { content } : {}
1028
+ };
1029
+ }
848
1030
  function extractFormStates(events, existing) {
849
1031
  let result = existing;
850
1032
  for (const e of events) {
@@ -867,6 +1049,7 @@ function createAgentStore() {
867
1049
  connection: {
868
1050
  status: "idle",
869
1051
  error: null,
1052
+ sendError: null,
870
1053
  reconnectAttempts: 0,
871
1054
  reconnectFailed: false
872
1055
  },
@@ -895,7 +1078,15 @@ function createAgentStore() {
895
1078
  loadingThreads: /* @__PURE__ */ new Set(),
896
1079
  actions: {
897
1080
  setConnectionStatus: (status, error) => set((s) => ({
898
- connection: { ...s.connection, status, error: error ?? null }
1081
+ connection: {
1082
+ ...s.connection,
1083
+ status,
1084
+ error: error ?? null,
1085
+ ...status === "connected" ? { sendError: null } : {}
1086
+ }
1087
+ })),
1088
+ setSendError: (message) => set((s) => ({
1089
+ connection: { ...s.connection, sendError: message }
899
1090
  })),
900
1091
  setReconnectFailed: () => set((s) => ({
901
1092
  connection: { ...s.connection, reconnectFailed: true }
@@ -983,8 +1174,13 @@ function createAgentStore() {
983
1174
  mergedEvents = snapshotEvents;
984
1175
  } else {
985
1176
  const existingIds = new Set(existing.map((e) => e.id));
1177
+ const snapById = new Map(snapshotEvents.map((e) => [e.id, e]));
1178
+ const mergedExisting = existing.map((e) => {
1179
+ const snap = snapById.get(e.id);
1180
+ return snap ? mergeThreadEventById(e, snap) : e;
1181
+ });
986
1182
  const newFromSnapshot = snapshotEvents.filter((e) => !existingIds.has(e.id));
987
- mergedEvents = newFromSnapshot.length > 0 ? [...existing, ...newFromSnapshot] : existing;
1183
+ mergedEvents = newFromSnapshot.length > 0 ? [...mergedExisting, ...newFromSnapshot] : mergedExisting;
988
1184
  }
989
1185
  const optimistic = { ...s.optimistic };
990
1186
  const optimisticKeys = { ...s.optimisticKeys };
@@ -1008,7 +1204,8 @@ function createAgentStore() {
1008
1204
  const appends = [];
1009
1205
  for (const e of newEvents) {
1010
1206
  if (existingIds.has(e.id)) {
1011
- updates.set(e.id, e);
1207
+ const prev = existing.find((x) => x.id === e.id);
1208
+ updates.set(e.id, mergeThreadEventById(prev, e));
1012
1209
  } else {
1013
1210
  appends.push(e);
1014
1211
  }
@@ -1022,6 +1219,10 @@ function createAgentStore() {
1022
1219
  reconcileEvents: (threadId, newEvents, resolvedClientEventIds) => set((s) => {
1023
1220
  const existing = s.events[threadId] ?? [];
1024
1221
  const existingIds = new Set(existing.map((e) => e.id));
1222
+ const mergedExisting = newEvents.length > 0 ? existing.map((e) => {
1223
+ const up = newEvents.find((n) => n.id === e.id);
1224
+ return up ? mergeThreadEventById(e, up) : e;
1225
+ }) : existing;
1025
1226
  const unique = newEvents.filter((e) => !existingIds.has(e.id));
1026
1227
  let optEvents = s.optimistic[threadId] ?? [];
1027
1228
  let optKeys = s.optimisticKeys[threadId] ?? [];
@@ -1035,7 +1236,7 @@ function createAgentStore() {
1035
1236
  }
1036
1237
  }
1037
1238
  return {
1038
- events: { ...s.events, [threadId]: [...existing, ...unique] },
1239
+ events: { ...s.events, [threadId]: [...mergedExisting, ...unique] },
1039
1240
  optimistic: { ...s.optimistic, [threadId]: optEvents },
1040
1241
  optimisticKeys: { ...s.optimisticKeys, [threadId]: optKeys }
1041
1242
  };
@@ -1085,7 +1286,10 @@ function createAgentStore() {
1085
1286
  const subscriptions = new Set(s.subscriptions);
1086
1287
  subscriptions.add(threadId);
1087
1288
  const loadingThreads = new Set(s.loadingThreads);
1088
- loadingThreads.add(threadId);
1289
+ const alreadyHadEvents = (s.events[threadId]?.length ?? 0) > 0;
1290
+ if (!alreadyHadEvents) {
1291
+ loadingThreads.add(threadId);
1292
+ }
1089
1293
  return { subscriptions, loadingThreads };
1090
1294
  }),
1091
1295
  removeSubscription: (threadId) => set((s) => {
@@ -1229,6 +1433,9 @@ function AgentProvider({
1229
1433
  react.useEffect(() => {
1230
1434
  clientRef.current?.setUploadUrl(uploadUrl);
1231
1435
  }, [uploadUrl]);
1436
+ react.useEffect(() => {
1437
+ clientRef.current?.setUploadAgentId(agentId);
1438
+ }, [agentId]);
1232
1439
  const identityIdsKey = identityIds?.join(",") ?? "";
1233
1440
  react.useEffect(() => {
1234
1441
  if (!url || !agentId) return;
@@ -1398,9 +1605,13 @@ function useConnection() {
1398
1605
  const { client } = useAgentContext();
1399
1606
  const status = useStore((s) => s.connection.status);
1400
1607
  const error = useStore((s) => s.connection.error);
1608
+ const sendError = useStore((s) => s.connection.sendError);
1401
1609
  const reconnectFailed = useStore((s) => s.connection.reconnectFailed);
1402
1610
  const reconnect = react.useCallback(() => client.retry(), [client]);
1403
- return { status, error, reconnectFailed, reconnect };
1611
+ const dismissSendError = react.useCallback(() => {
1612
+ client.clearSendError();
1613
+ }, [client]);
1614
+ return { status, error, sendError, dismissSendError, reconnectFailed, reconnect };
1404
1615
  }
1405
1616
  function useFeedback(targetId, targetType = "event") {
1406
1617
  const { client } = useAgentContext();
@@ -1529,11 +1740,15 @@ function useFormFileUpload() {
1529
1740
  setIsUploading(true);
1530
1741
  setError(null);
1531
1742
  try {
1743
+ const aid = (params.agentId || "").trim();
1744
+ if (!aid) {
1745
+ throw new Error("agentId is required for upload");
1746
+ }
1532
1747
  const formData = new FormData();
1533
1748
  formData.append("file", params.file);
1534
1749
  formData.append("field_id", params.fieldId);
1535
1750
  formData.append("source", "chat");
1536
- formData.append("agent_id", params.agentId);
1751
+ formData.append("agent_id", aid);
1537
1752
  formData.append("run_id", params.runId);
1538
1753
  formData.append("thread_id", params.threadId);
1539
1754
  const response = await fetch(params.uploadUrl, {
@@ -1685,11 +1900,11 @@ function useUpload() {
1685
1900
  const [isUploading, setIsUploading] = react.useState(false);
1686
1901
  const activeCountRef = react.useRef(0);
1687
1902
  const upload = react.useCallback(
1688
- async (file) => {
1903
+ async (file, options) => {
1689
1904
  activeCountRef.current++;
1690
1905
  setIsUploading(true);
1691
1906
  try {
1692
- return await client.upload(file);
1907
+ return await client.upload(file, options);
1693
1908
  } finally {
1694
1909
  activeCountRef.current--;
1695
1910
  if (activeCountRef.current === 0) {
@@ -1709,6 +1924,7 @@ exports.isSettingsFieldGroup = isSettingsFieldGroup;
1709
1924
  exports.toFormElement = toFormElement;
1710
1925
  exports.toFormEventData = toFormEventData;
1711
1926
  exports.toFormResponseEventData = toFormResponseEventData;
1927
+ exports.useAgentContext = useAgentContext;
1712
1928
  exports.useAnalytics = useAnalytics;
1713
1929
  exports.useAudioRecorder = useAudioRecorder;
1714
1930
  exports.useConnection = useConnection;