@agents24/chat-react 0.5.32 → 0.5.34

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.
@@ -49,6 +49,10 @@ __export(runtime_exports, {
49
49
  module.exports = __toCommonJS(runtime_exports);
50
50
 
51
51
  // src/runtime/use-agent-chat-runtime.ts
52
+ var import_react2 = require("@agents24/react");
53
+ var React2 = __toESM(require("react"), 1);
54
+
55
+ // src/runtime/use-agent-chat-hitl.ts
52
56
  var import_react = require("@agents24/react");
53
57
  var React = __toESM(require("react"), 1);
54
58
 
@@ -106,6 +110,9 @@ function waitForMcpOauthComplete({
106
110
  popupNonce,
107
111
  requireConnectionId = false,
108
112
  serverId,
113
+ runId,
114
+ interruptId,
115
+ signal,
109
116
  timeoutMs = 12e4
110
117
  }) {
111
118
  if (!popup) return Promise.reject(new Error("Could not open the MCP authorization popup."));
@@ -114,6 +121,8 @@ function waitForMcpOauthComplete({
114
121
  const expectedPopupNonce = String(popupNonce || "").trim();
115
122
  if (!expectedServerId) return Promise.reject(new Error("MCP authorization is missing its server identity."));
116
123
  if (!expectedPopupNonce) return Promise.reject(new Error("MCP authorization is missing its popup binding."));
124
+ const aborted = () => new DOMException("MCP authorization detached.", "AbortError");
125
+ if (signal?.aborted) return Promise.reject(aborted());
117
126
  const returnFocusTo = typeof document !== "undefined" ? document.activeElement : null;
118
127
  return new Promise((resolve, reject) => {
119
128
  let settled = false;
@@ -123,14 +132,20 @@ function waitForMcpOauthComplete({
123
132
  window.clearTimeout(timeout);
124
133
  window.clearInterval(closeTimer);
125
134
  window.removeEventListener("message", onMessage);
126
- returnFocusTo?.focus?.();
135
+ signal?.removeEventListener("abort", onAbort);
136
+ if (!signal?.aborted) returnFocusTo?.focus?.();
127
137
  if (result instanceof Error) reject(result);
128
138
  else resolve(result);
129
139
  };
140
+ const onAbort = () => finish(aborted());
130
141
  const onMessage = (event) => {
131
142
  if (event.source !== popup || event.origin !== expectedOrigin) return;
132
143
  const data = event.data;
133
- if (data?.type !== "agents24.mcp.callback" || data.server_id !== expectedServerId || data.popup_nonce !== expectedPopupNonce) return;
144
+ if (data?.type !== "agents24.mcp.callback" || data.server_id !== expectedServerId || data.popup_nonce !== expectedPopupNonce || runId !== void 0 && data.run_id !== runId || interruptId !== void 0 && data.interrupt_id !== interruptId) return;
145
+ if (data.success === false) {
146
+ finish(new Error("MCP authorization could not be completed."));
147
+ return;
148
+ }
134
149
  const code = String(data.code || "").trim();
135
150
  if (!code || code.length > 2048) return;
136
151
  const connectionId = String(data.connection_id || "").trim();
@@ -150,9 +165,152 @@ function waitForMcpOauthComplete({
150
165
  if (popup.closed) finish(new Error("MCP authorization window was closed before connecting."));
151
166
  }, 500);
152
167
  window.addEventListener("message", onMessage);
168
+ signal?.addEventListener("abort", onAbort, { once: true });
153
169
  });
154
170
  }
155
171
 
172
+ // src/runtime/use-agent-chat-hitl.ts
173
+ function detach(operation) {
174
+ operation.abort.abort();
175
+ operation.popup?.close();
176
+ }
177
+ function useAgentChatHitl(options) {
178
+ const mcp = (0, import_react.useAgentMcp)();
179
+ const latest = React.useRef(options);
180
+ latest.current = options;
181
+ const mounted = React.useRef(true);
182
+ const operations = React.useRef(/* @__PURE__ */ new Map());
183
+ const [states, setStates] = React.useState({});
184
+ React.useEffect(() => {
185
+ mounted.current = true;
186
+ const active = operations.current;
187
+ return () => {
188
+ mounted.current = false;
189
+ for (const operation of active.values()) detach(operation);
190
+ active.clear();
191
+ };
192
+ }, []);
193
+ React.useEffect(() => {
194
+ for (const [key, operation] of operations.current) {
195
+ if (operation.isCurrent()) continue;
196
+ detach(operation);
197
+ operations.current.delete(key);
198
+ setStates((current) => {
199
+ const next = { ...current };
200
+ delete next[key];
201
+ return next;
202
+ });
203
+ }
204
+ });
205
+ React.useEffect(() => {
206
+ setStates({});
207
+ }, [options.client, options.controller.activeThreadId]);
208
+ const onHitlAction = React.useCallback(async (part, response) => {
209
+ const captured = latest.current;
210
+ const { controller, client, bootstrap, selectionGeneration } = captured;
211
+ const key = part.interruptId || part.id;
212
+ if (operations.current.has(key)) return;
213
+ const generation = selectionGeneration.current;
214
+ const threadId = controller.activeThreadId;
215
+ const runId = controller.messages.find((message) => message.parts.includes(part))?.runId || controller.activeRunId;
216
+ const operation = {
217
+ abort: new AbortController(),
218
+ phase: part.hitlKind === "mcp_auth" && response.action === "connect" ? "connecting" : "resuming",
219
+ isCurrent() {
220
+ const current = latest.current;
221
+ return mounted.current && !operation.abort.signal.aborted && current.client === client && current.selectionGeneration.current === generation && current.controller.activeThreadId === threadId && (!current.controller.activeRunId || current.controller.activeRunId === runId) && !["cancelling", "cancelled", "failed", "completed"].includes(current.controller.runState) && (operation.phase === "resuming" || current.controller.messages.some((message) => message.runId === runId && message.parts.some((candidate) => candidate.type === "hitl" && candidate.interruptId === part.interruptId && candidate.status === "pending")));
222
+ }
223
+ };
224
+ if (!operation.isCurrent()) return;
225
+ captured.clearOperationError();
226
+ operations.current.set(key, operation);
227
+ setStates((current) => ({ ...current, [key]: { action: response.action, status: operation.phase } }));
228
+ try {
229
+ if (operation.phase === "connecting") {
230
+ if (!runId) throw new Error("MCP authorization is missing its paused run.");
231
+ if (!bootstrap) throw new Error("MCP authorization requires runtime bootstrap.");
232
+ if (!captured.mcpRedirectUri) throw new Error("mcpRedirectUri is required for MCP Connect.");
233
+ const serverId = String(part.presentation.server_id || "").trim();
234
+ if (!serverId) throw new Error("MCP authorization is missing its server identity.");
235
+ const serverEmbed = bootstrap.authentication.modes.includes("server_embed");
236
+ const popupNonce = browserChatCrypto().randomUUID();
237
+ const popup = window.open("about:blank", "agents24-mcp", "popup,width=560,height=720");
238
+ if (!popup) throw new Error("Allow popups to connect this MCP account.");
239
+ operation.popup = popup;
240
+ popup.document.title = "Connecting to MCP";
241
+ popup.document.body.textContent = "Opening secure connection\u2026";
242
+ const proof = await createMcpPkceProof();
243
+ if (!operation.isCurrent()) return;
244
+ const started = await mcp.startAuthorization({
245
+ runId,
246
+ serverId,
247
+ interruptId: part.interruptId,
248
+ redirectUri: captured.mcpRedirectUri,
249
+ popupNonce,
250
+ codeChallenge: proof.challenge,
251
+ signal: operation.abort.signal
252
+ });
253
+ if (!operation.isCurrent()) return;
254
+ if (!started.callback_origin) throw new Error("MCP authorization did not return a callback origin.");
255
+ const completionPromise = waitForMcpOauthComplete({
256
+ popup,
257
+ callbackOrigin: started.callback_origin,
258
+ popupNonce,
259
+ serverId,
260
+ runId,
261
+ interruptId: part.interruptId,
262
+ signal: operation.abort.signal,
263
+ requireConnectionId: serverEmbed || Boolean(captured.completeMcpAuthorization)
264
+ });
265
+ void completionPromise.catch(() => void 0);
266
+ popup.location.replace(started.authorization_url);
267
+ const completion = await completionPromise;
268
+ if (!operation.isCurrent()) return;
269
+ if (captured.completeMcpAuthorization) {
270
+ await captured.completeMcpAuthorization({ completion, codeVerifier: proof.verifier, serverId });
271
+ } else if (serverEmbed) {
272
+ validateMcpCallbackResult({ server_id: completion.serverId, connection_id: completion.connectionId || "" }, serverId);
273
+ } else {
274
+ const redeemed = await mcp.redeemCallback({
275
+ code: completion.code,
276
+ codeVerifier: proof.verifier,
277
+ signal: operation.abort.signal
278
+ });
279
+ if (!operation.isCurrent()) return;
280
+ validateMcpCallbackResult(redeemed, serverId);
281
+ }
282
+ popup.close();
283
+ }
284
+ if (!operation.isCurrent()) return;
285
+ operation.phase = "resuming";
286
+ setStates((current) => ({ ...current, [key]: { action: response.action, status: "resuming" } }));
287
+ await controller.resumeHitl(part, response);
288
+ } catch (error) {
289
+ if (!operation.isCurrent()) return;
290
+ captured.onError(error);
291
+ setStates((current) => ({ ...current, [key]: {
292
+ action: response.action,
293
+ status: "error",
294
+ error: error instanceof Error ? error.message : String(error)
295
+ } }));
296
+ throw error;
297
+ } finally {
298
+ const ownsState = operation.isCurrent();
299
+ detach(operation);
300
+ if (operations.current.get(key) === operation) {
301
+ operations.current.delete(key);
302
+ if (ownsState) setStates((current) => {
303
+ if (current[key]?.status === "error") return current;
304
+ const next = { ...current };
305
+ delete next[key];
306
+ return next;
307
+ });
308
+ }
309
+ }
310
+ }, [mcp]);
311
+ return { onHitlAction, getHitlActionState: (part) => states[part.interruptId || part.id] };
312
+ }
313
+
156
314
  // src/runtime/input-contract.ts
157
315
  var import_client = require("@agents24/client");
158
316
  var import_client2 = require("@agents24/client");
@@ -267,9 +425,6 @@ function modelsFromEffectivePolicy(policy) {
267
425
  models
268
426
  };
269
427
  }
270
- function hitlKey(part) {
271
- return part.interruptId || part.id;
272
- }
273
428
  function useAgentChatRuntime(options) {
274
429
  const {
275
430
  activeThreadId,
@@ -281,47 +436,43 @@ function useAgentChatRuntime(options) {
281
436
  onActiveThreadIdChange,
282
437
  onModelChange
283
438
  } = options;
284
- const controller = (0, import_react.useAgentChat)(
439
+ const controller = (0, import_react2.useAgentChat)(
285
440
  activeThreadId === void 0 ? { client } : { activeThreadId, client }
286
441
  );
287
- const attachments = (0, import_react.useAgentAttachments)();
288
- const mcp = (0, import_react.useAgentMcp)();
289
- const [bootstrap, setBootstrap] = React.useState(null);
290
- const bootstrapRef = React.useRef(bootstrap);
442
+ const attachments = (0, import_react2.useAgentAttachments)();
443
+ const [bootstrap, setBootstrap] = React2.useState(null);
444
+ const bootstrapRef = React2.useRef(bootstrap);
291
445
  bootstrapRef.current = bootstrap;
292
- const [effectivePolicy, setEffectivePolicy] = React.useState(null);
293
- const [isBootstrapping, setIsBootstrapping] = React.useState(true);
294
- const [bootstrapError, setBootstrapError] = React.useState(null);
295
- const [localOperationError, setLocalOperationError] = React.useState(null);
296
- const [selectedModelId, setSelectedModelId] = React.useState(modelId ?? null);
297
- const selectedModelIdRef = React.useRef(selectedModelId);
446
+ const [effectivePolicy, setEffectivePolicy] = React2.useState(null);
447
+ const [isBootstrapping, setIsBootstrapping] = React2.useState(true);
448
+ const [bootstrapError, setBootstrapError] = React2.useState(null);
449
+ const [localOperationError, setLocalOperationError] = React2.useState(null);
450
+ const [selectedModelId, setSelectedModelId] = React2.useState(modelId ?? null);
451
+ const selectedModelIdRef = React2.useRef(selectedModelId);
298
452
  selectedModelIdRef.current = selectedModelId;
299
- const [selectedAgentId, setSelectedAgentId] = React.useState(null);
300
- const selectedAgentIdRef = React.useRef(null);
453
+ const [selectedAgentId, setSelectedAgentId] = React2.useState(null);
454
+ const selectedAgentIdRef = React2.useRef(null);
301
455
  selectedAgentIdRef.current = selectedAgentId;
302
- const [isChangingAgent, setIsChangingAgent] = React.useState(false);
303
- const agentChangePromiseRef = React.useRef(null);
304
- const [isSubmitting, setIsSubmitting] = React.useState(false);
305
- const submitPromiseRef = React.useRef(null);
306
- const [hitlStates, setHitlStates] = React.useState({});
307
- const hitlStatesRef = React.useRef(hitlStates);
308
- hitlStatesRef.current = hitlStates;
309
- const mountedRef = React.useRef(true);
310
- const clientRef = React.useRef(client);
456
+ const [isChangingAgent, setIsChangingAgent] = React2.useState(false);
457
+ const agentChangePromiseRef = React2.useRef(null);
458
+ const [isSubmitting, setIsSubmitting] = React2.useState(false);
459
+ const submitPromiseRef = React2.useRef(null);
460
+ const mountedRef = React2.useRef(true);
461
+ const clientRef = React2.useRef(client);
311
462
  clientRef.current = client;
312
- const bootstrapPromiseRef = React.useRef(null);
313
- React.useEffect(() => {
463
+ const bootstrapPromiseRef = React2.useRef(null);
464
+ React2.useEffect(() => {
314
465
  mountedRef.current = true;
315
466
  return () => {
316
467
  mountedRef.current = false;
317
468
  };
318
469
  }, []);
319
- const previousControlledThreadRef = React.useRef(activeThreadId);
320
- const threadSelectionGenerationRef = React.useRef(0);
321
- const controlledSyncTargetRef = React.useRef(null);
322
- const previousControllerThreadRef = React.useRef(controller.activeThreadId);
323
- const pendingThreadTransitionRef = React.useRef(null);
324
- const lastReportedThreadRef = React.useRef(activeThreadId ?? controller.activeThreadId);
470
+ const previousControlledThreadRef = React2.useRef(activeThreadId);
471
+ const threadSelectionGenerationRef = React2.useRef(0);
472
+ const controlledSyncTargetRef = React2.useRef(null);
473
+ const previousControllerThreadRef = React2.useRef(controller.activeThreadId);
474
+ const pendingThreadTransitionRef = React2.useRef(null);
475
+ const lastReportedThreadRef = React2.useRef(activeThreadId ?? controller.activeThreadId);
325
476
  if (activeThreadId !== previousControlledThreadRef.current) {
326
477
  threadSelectionGenerationRef.current += 1;
327
478
  previousControlledThreadRef.current = activeThreadId;
@@ -330,12 +481,12 @@ function useAgentChatRuntime(options) {
330
481
  lastReportedThreadRef.current = activeThreadId;
331
482
  }
332
483
  }
333
- const reportActiveThread = React.useCallback((threadId, reason) => {
484
+ const reportActiveThread = React2.useCallback((threadId, reason) => {
334
485
  if (lastReportedThreadRef.current === threadId) return;
335
486
  lastReportedThreadRef.current = threadId;
336
487
  onActiveThreadIdChange?.({ threadId, reason });
337
488
  }, [onActiveThreadIdChange]);
338
- const retryBootstrap = React.useCallback(() => {
489
+ const retryBootstrap = React2.useCallback(() => {
339
490
  if (bootstrapPromiseRef.current?.client === client) return bootstrapPromiseRef.current.promise;
340
491
  const requestClient = client;
341
492
  const request = (async () => {
@@ -373,7 +524,7 @@ function useAgentChatRuntime(options) {
373
524
  });
374
525
  return request;
375
526
  }, [client, controller.refreshThreads, modelId]);
376
- const refreshEffectivePolicy = React.useCallback(async () => {
527
+ const refreshEffectivePolicy = React2.useCallback(async () => {
377
528
  if (bootstrap?.features.agents) {
378
529
  const refreshed = await client.bootstrap({ agentId: selectedAgentIdRef.current || void 0 });
379
530
  if (!mountedRef.current || clientRef.current !== client) return;
@@ -390,22 +541,18 @@ function useAgentChatRuntime(options) {
390
541
  setSelectedModelId((current) => available.models.some((item) => item.id === current) ? current : available.defaultModelId);
391
542
  }
392
543
  }, [bootstrap, client, modelId]);
393
- React.useEffect(() => {
544
+ React2.useEffect(() => {
394
545
  void retryBootstrap();
395
546
  }, [retryBootstrap]);
396
- React.useEffect(() => {
547
+ React2.useEffect(() => {
397
548
  if (modelId !== void 0) setSelectedModelId(modelId);
398
549
  }, [modelId]);
399
- React.useEffect(() => {
400
- hitlStatesRef.current = {};
401
- setHitlStates({});
402
- }, [client, controller.activeThreadId]);
403
- React.useEffect(() => {
550
+ React2.useEffect(() => {
404
551
  if (controlledSyncTargetRef.current?.value === null && controller.activeThreadId) {
405
552
  controller.startNewThread();
406
553
  }
407
554
  }, [activeThreadId, controller.activeThreadId, controller.startNewThread]);
408
- React.useEffect(() => {
555
+ React2.useEffect(() => {
409
556
  const previous = previousControllerThreadRef.current;
410
557
  const current = controller.activeThreadId;
411
558
  previousControllerThreadRef.current = current;
@@ -418,11 +565,11 @@ function useAgentChatRuntime(options) {
418
565
  if (pendingTransition && current === pendingTransition.value) return;
419
566
  if (previous === null && current !== null) reportActiveThread(current, "created");
420
567
  }, [activeThreadId, controller.activeThreadId, reportActiveThread]);
421
- const clearOperationError = React.useCallback(() => {
568
+ const clearOperationError = React2.useCallback(() => {
422
569
  setLocalOperationError(null);
423
570
  controller.clearOperationError();
424
571
  }, [controller.clearOperationError]);
425
- const submit = React.useCallback((input) => {
572
+ const submit = React2.useCallback((input) => {
426
573
  if (submitPromiseRef.current) return submitPromiseRef.current;
427
574
  clearOperationError();
428
575
  setIsSubmitting(true);
@@ -463,86 +610,24 @@ function useAgentChatRuntime(options) {
463
610
  void request.then(clearRequest, clearRequest);
464
611
  return request;
465
612
  }, [bootstrap, clearOperationError, controller.activeThreadId, controller.submit, refreshEffectivePolicy]);
466
- const completeMcp = React.useCallback(async (part) => {
467
- if (!mcpRedirectUri) throw new Error("mcpRedirectUri is required for MCP Connect.");
468
- const serverId = String(part.presentation.server_id || "").trim();
469
- if (!serverId) throw new Error("MCP authorization is missing its server identity.");
470
- const runId = controller.activeRunId || controller.messages.find((message) => message.parts.includes(part))?.runId;
471
- if (!runId) throw new Error("MCP authorization is missing its paused run.");
472
- const popupNonce = browserChatCrypto().randomUUID();
473
- const proof = await createMcpPkceProof();
474
- const popup = window.open("about:blank", "agents24-mcp", "popup,width=560,height=720");
475
- if (!popup) throw new Error("Allow popups to connect this MCP account.");
476
- popup.document.title = "Connecting to MCP";
477
- popup.document.body.textContent = "Opening secure connection\u2026";
478
- try {
479
- const started = await mcp.startAuthorization({
480
- runId,
481
- serverId,
482
- interruptId: part.interruptId,
483
- redirectUri: mcpRedirectUri,
484
- popupNonce,
485
- codeChallenge: proof.challenge
486
- });
487
- if (!started.callback_origin) throw new Error("MCP authorization did not return a callback origin.");
488
- popup.location.replace(started.authorization_url);
489
- const completion = await waitForMcpOauthComplete({
490
- popup,
491
- callbackOrigin: started.callback_origin,
492
- popupNonce,
493
- requireConnectionId: Boolean(completeMcpAuthorization),
494
- serverId
495
- });
496
- if (completeMcpAuthorization) {
497
- await completeMcpAuthorization({ completion, codeVerifier: proof.verifier, serverId });
498
- } else {
499
- const redeemed = await mcp.redeemCallback({ code: completion.code, codeVerifier: proof.verifier });
500
- validateMcpCallbackResult(redeemed, serverId);
501
- }
502
- } finally {
503
- popup.close();
504
- }
505
- }, [completeMcpAuthorization, controller.activeRunId, controller.messages, mcp, mcpRedirectUri]);
506
- const onHitlAction = React.useCallback(async (part, response) => {
507
- const action = response.action;
508
- const key = hitlKey(part);
509
- const current = hitlStatesRef.current[key];
510
- if (current?.status === "connecting" || current?.status === "resuming") return;
511
- clearOperationError();
512
- const pending = {
513
- action,
514
- status: part.hitlKind === "mcp_auth" && action === "connect" ? "connecting" : "resuming"
515
- };
516
- hitlStatesRef.current = { ...hitlStatesRef.current, [key]: pending };
517
- setHitlStates(hitlStatesRef.current);
518
- try {
519
- if (part.hitlKind === "mcp_auth" && action === "connect") await completeMcp(part);
520
- await controller.resumeHitl(part, response);
521
- setHitlStates((states) => {
522
- const next = { ...states };
523
- delete next[key];
524
- hitlStatesRef.current = next;
525
- return next;
526
- });
527
- } catch (error) {
528
- setLocalOperationError(error);
529
- const failedState = {
530
- ...hitlStatesRef.current,
531
- [key]: { action, error: agentChatRuntimeErrorMessage(error), status: "error" }
532
- };
533
- hitlStatesRef.current = failedState;
534
- setHitlStates(failedState);
535
- throw error;
536
- }
537
- }, [clearOperationError, completeMcp, controller.resumeHitl]);
538
- const newThread = React.useCallback(() => {
613
+ const { onHitlAction, getHitlActionState } = useAgentChatHitl({
614
+ client,
615
+ bootstrap,
616
+ controller,
617
+ selectionGeneration: threadSelectionGenerationRef,
618
+ completeMcpAuthorization,
619
+ mcpRedirectUri,
620
+ clearOperationError,
621
+ onError: setLocalOperationError
622
+ });
623
+ const newThread = React2.useCallback(() => {
539
624
  threadSelectionGenerationRef.current += 1;
540
625
  clearOperationError();
541
626
  pendingThreadTransitionRef.current = null;
542
627
  reportActiveThread(null, "new");
543
628
  controller.startNewThread();
544
629
  }, [clearOperationError, controller.startNewThread, reportActiveThread]);
545
- const openThread = React.useCallback(async (threadId) => {
630
+ const openThread = React2.useCallback(async (threadId) => {
546
631
  const requestGeneration = ++threadSelectionGenerationRef.current;
547
632
  clearOperationError();
548
633
  pendingThreadTransitionRef.current = { reason: "opened", value: threadId };
@@ -572,7 +657,7 @@ function useAgentChatRuntime(options) {
572
657
  if (requestGeneration === threadSelectionGenerationRef.current) pendingThreadTransitionRef.current = null;
573
658
  }
574
659
  }, [clearOperationError, client, controller.openThread, reportActiveThread]);
575
- const deleteThread = React.useCallback(async (threadId) => {
660
+ const deleteThread = React2.useCallback(async (threadId) => {
576
661
  clearOperationError();
577
662
  const wasActive = controller.activeThreadId === threadId;
578
663
  if (wasActive) threadSelectionGenerationRef.current += 1;
@@ -589,7 +674,7 @@ function useAgentChatRuntime(options) {
589
674
  }
590
675
  }
591
676
  }, [clearOperationError, controller.activeThreadId, controller.deleteThread, reportActiveThread]);
592
- const changeModel = React.useCallback((nextModelId) => {
677
+ const changeModel = React2.useCallback((nextModelId) => {
593
678
  if (modelId === void 0) setSelectedModelId(nextModelId);
594
679
  onModelChange?.(nextModelId);
595
680
  if (controller.activeThreadId && selectedAgentId && client.threads.setRuntimeSelection) {
@@ -600,7 +685,7 @@ function useAgentChatRuntime(options) {
600
685
  }).catch(setLocalOperationError);
601
686
  }
602
687
  }, [client.threads, controller.activeThreadId, modelId, onModelChange, selectedAgentId]);
603
- const resolveAttachmentContent = React.useCallback(async (attachment, signal) => {
688
+ const resolveAttachmentContent = React2.useCallback(async (attachment, signal) => {
604
689
  const attachmentId = typeof attachment.id === "string" ? attachment.id.trim() : "";
605
690
  if (!attachmentId) throw new Error("Attachment content identity is unavailable.");
606
691
  const access = await attachments.createContentAccess({
@@ -610,7 +695,7 @@ function useAgentChatRuntime(options) {
610
695
  });
611
696
  return { url: access.url, validUntil: access.valid_until || null };
612
697
  }, [attachments.createContentAccess]);
613
- const changeAgent = React.useCallback((nextAgentId) => {
698
+ const changeAgent = React2.useCallback((nextAgentId) => {
614
699
  if (agentChangePromiseRef.current) return agentChangePromiseRef.current;
615
700
  if (nextAgentId === selectedAgentIdRef.current || !canChangeAgentRuntime(controller.runState, controller.activeRunId)) return Promise.resolve();
616
701
  clearOperationError();
@@ -677,7 +762,7 @@ function useAgentChatRuntime(options) {
677
762
  deleteThread,
678
763
  errorMessage: agentChatRuntimeErrorMessage(fatalError || operationError),
679
764
  fatalError,
680
- getHitlActionState: (part) => hitlStates[hitlKey(part)],
765
+ getHitlActionState,
681
766
  isBootstrapping,
682
767
  isChangingAgent,
683
768
  isSubmitting: isSubmitting || controller.isSubmitting,
@@ -696,11 +781,11 @@ function useAgentChatRuntime(options) {
696
781
  }
697
782
 
698
783
  // src/runtime/use-delegation-tasks.ts
699
- var React2 = __toESM(require("react"), 1);
784
+ var React3 = __toESM(require("react"), 1);
700
785
  function useDelegationTasks({ threadId, source, pollIntervalMs = 2e3 }) {
701
- const [state, setState] = React2.useState({ threadId: null, tasks: [], error: null, loading: false });
702
- const [revision, refresh] = React2.useReducer((value) => value + 1, 0);
703
- React2.useEffect(() => {
786
+ const [state, setState] = React3.useState({ threadId: null, tasks: [], error: null, loading: false });
787
+ const [revision, refresh] = React3.useReducer((value) => value + 1, 0);
788
+ React3.useEffect(() => {
704
789
  if (!threadId) {
705
790
  setState({ threadId: null, tasks: [], error: null, loading: false });
706
791
  return;