@agents24/react 0.2.22 → 0.2.24

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
@@ -571,11 +571,12 @@ function Agents24Provider({
571
571
  createAbortController,
572
572
  createId = createPortableId,
573
573
  storage,
574
- visibility
574
+ visibility,
575
+ onHitlTiming
575
576
  }) {
576
577
  const value = React2.useMemo(
577
- () => ({ client, createAbortController, createId, storage, visibility: visibility ?? client.visibility }),
578
- [client, createAbortController, createId, storage, visibility]
578
+ () => ({ client, createAbortController, createId, storage, visibility: visibility ?? client.visibility, onHitlTiming }),
579
+ [client, createAbortController, createId, storage, visibility, onHitlTiming]
579
580
  );
580
581
  return /* @__PURE__ */ jsx(Agents24Context.Provider, { value, children });
581
582
  }
@@ -636,6 +637,41 @@ function createRuntimeEventFrameBuffer(apply, scheduleFrame) {
636
637
  };
637
638
  }
638
639
 
640
+ // src/hitl-resolution.ts
641
+ function applyHitlResolution(messages, receipt) {
642
+ return messages.map((message) => message.runId !== receipt.run_id ? message : {
643
+ ...message,
644
+ parts: message.parts.map((part) => part.kind !== "hitl" || part.interruptId !== receipt.interrupt_id ? part : {
645
+ ...part,
646
+ status: receipt.resolution.status,
647
+ resolution: {
648
+ ...receipt.resolution,
649
+ answers: receipt.resolution.answers?.map((answer) => ({
650
+ questionId: answer.question_id,
651
+ selectedOptionIds: [...answer.selected_option_ids],
652
+ ...answer.custom_text ? { customText: answer.custom_text } : {}
653
+ }))
654
+ }
655
+ })
656
+ });
657
+ }
658
+ function findHitlResolution(messages, runId, interruptId) {
659
+ return messages.filter((message) => message.runId === runId).flatMap((message) => message.parts).find((part) => part.kind === "hitl" && part.interruptId === interruptId && part.status !== "pending");
660
+ }
661
+ function preserveResolvedHitlParts(current, incoming) {
662
+ const resolved = current.filter((part) => part.kind === "hitl" && part.status !== "pending");
663
+ if (!resolved.length) return incoming;
664
+ const next = incoming.map((part) => {
665
+ if (part.kind !== "hitl" || part.status !== "pending") return part;
666
+ const known = resolved.find((item) => item.interruptId === part.interruptId);
667
+ return known ? { ...part, status: known.status, resolution: known.resolution } : part;
668
+ });
669
+ for (const part of resolved) if (!next.some((item) => item.kind === "hitl" && item.interruptId === part.interruptId)) {
670
+ next.splice(Math.min(current.indexOf(part), next.length), 0, part);
671
+ }
672
+ return next;
673
+ }
674
+
639
675
  // src/state.ts
640
676
  import {
641
677
  compressionFromContextWindow as compressionFromContextWindow2,
@@ -751,6 +787,7 @@ function reconcileThreadTimeline(current, canonical, activeRunId, streamingMessa
751
787
  const retained = current.filter((message) => !canonicalIds.has(message.id) && (message.isFinal || activeRunId && (!message.runId || message.runId === activeRunId)));
752
788
  const reconciled = mounted.map((message) => {
753
789
  const live = current.find((item) => item.id === message.id);
790
+ if (live && live.runId === message.runId) message = { ...message, parts: preserveResolvedHitlParts(live.parts, message.parts) };
754
791
  return activeRunId && live?.role === "assistant" && live.runId === activeRunId && (live.id === streamingMessageId || !live.isFinal || live.responseCompletion) ? message.responseCompletion && !live.responseCompletion ? { ...message, id: live.id, durableId: message.durableId || live.durableId } : { ...message, ...live, feedback: message.feedback, durableId: message.durableId || live.durableId } : message;
755
792
  });
756
793
  const retainedIds = new Set(retained.map((message) => message.id));
@@ -894,7 +931,7 @@ function applyRuntimeEvent(state, event) {
894
931
  delta,
895
932
  typeof payload.block_id === "string" ? payload.block_id : `${runId || "run"}-assistant-text-${event.seq}`
896
933
  ) : projection.parts.length ? upsertResponseBlockParts(existing?.parts || [], projection.parts) : existing?.parts || [];
897
- const lifecycleParts = reconcileModelTurnParts(projectedParts, event);
934
+ const lifecycleParts = reconcileModelTurnParts(preserveResolvedHitlParts(existing?.parts || [], projectedParts), event);
898
935
  const compressionPart = contextApplies && explicitCompression?.active ? contextCompressionPartFromEvent(event, lifecycleParts) : null;
899
936
  const parts = compressionPart ? upsertResponseBlockParts(lifecycleParts, [compressionPart]) : lifecycleParts;
900
937
  const activeThreadId = eventThreadId || state.activeThreadId;
@@ -1033,7 +1070,7 @@ function captureChatOperation(read, options = {}) {
1033
1070
  const owner = read();
1034
1071
  return () => {
1035
1072
  const current = read();
1036
- return current.generation === owner.generation && (options.adoptThread || current.threadId === owner.threadId) && (!options.run || current.runId === owner.runId) && (!options.stream || current.stream === owner.stream);
1073
+ return current.client === owner.client && current.generation === owner.generation && (options.adoptThread || current.threadId === owner.threadId) && (!options.run || current.runId === owner.runId) && (!options.stream || current.stream === owner.stream);
1037
1074
  };
1038
1075
  }
1039
1076
 
@@ -1382,8 +1419,202 @@ function discardOptimisticSubmission(state, message) {
1382
1419
  };
1383
1420
  }
1384
1421
 
1422
+ // src/use-agent-chat-hitl-submissions.ts
1423
+ import * as React4 from "react";
1424
+
1425
+ // src/hitl-submission.ts
1426
+ var timers = globalThis;
1427
+ async function withHitlDeadline(factory, work, ms = 15e3) {
1428
+ const abort = factory();
1429
+ let timer;
1430
+ try {
1431
+ return await Promise.race([work(abort.signal), new Promise((_, reject) => {
1432
+ timer = timers.setTimeout(() => {
1433
+ abort.abort();
1434
+ reject(new Error("Submission acknowledgement timed out."));
1435
+ }, ms);
1436
+ })]);
1437
+ } finally {
1438
+ timers.clearTimeout(timer);
1439
+ }
1440
+ }
1441
+ function isDefinitiveHitlRejection(error) {
1442
+ const status = error?.status ?? error?.statusCode;
1443
+ return typeof status === "number" && status >= 400 && status < 500 && ![408, 409, 425, 429].includes(status);
1444
+ }
1445
+ function createHitlSubmission(options) {
1446
+ const response = { ...options.response, answers: options.response.answers?.map((answer) => ({
1447
+ ...answer,
1448
+ selected_option_ids: [...answer.selected_option_ids]
1449
+ })) };
1450
+ let pending;
1451
+ let accepted = false;
1452
+ let failed = false;
1453
+ let uncertain = false;
1454
+ const now = options.now ?? Date.now;
1455
+ const publish = (state) => {
1456
+ if (options.isCurrent()) options.changed(state);
1457
+ };
1458
+ const accept = (receipt) => {
1459
+ if (!options.isCurrent() || accepted) return;
1460
+ accepted = true;
1461
+ uncertain = false;
1462
+ options.accept(receipt);
1463
+ publish({ action: receipt.resolution.action || response.action, status: "accepted" });
1464
+ };
1465
+ const retry = () => {
1466
+ if (pending) return pending;
1467
+ if (accepted || !options.isCurrent()) return Promise.resolve();
1468
+ failed = false;
1469
+ uncertain = false;
1470
+ publish({ action: response.action, status: "submitting" });
1471
+ pending = Promise.resolve().then(async () => {
1472
+ try {
1473
+ await withHitlDeadline(options.createAbortController, async (signal) => {
1474
+ const started = now();
1475
+ await options.prepare?.({ signal });
1476
+ options.timing?.("preparation", now() - started);
1477
+ if (!options.isCurrent() || signal.aborted) return;
1478
+ const submitted = now();
1479
+ const receipt = await options.send(response, options.idempotencyKey, signal);
1480
+ options.timing?.("acknowledgement", now() - submitted);
1481
+ accept(receipt);
1482
+ });
1483
+ } catch (error) {
1484
+ if (!options.isCurrent() || accepted) return;
1485
+ if (isDefinitiveHitlRejection(error)) {
1486
+ failed = true;
1487
+ publish({ action: response.action, status: "error", error: error instanceof Error ? error.message : "Submission was rejected." });
1488
+ throw error;
1489
+ }
1490
+ publish({ action: response.action, status: "checking" });
1491
+ for (let attempt = 0; attempt < 2; attempt += 1) {
1492
+ try {
1493
+ const resolved = await withHitlDeadline(options.createAbortController, options.reconcile, 3e3);
1494
+ if (resolved) accept(resolved);
1495
+ } catch {
1496
+ }
1497
+ if (accepted || !options.isCurrent()) return;
1498
+ }
1499
+ uncertain = true;
1500
+ publish({ action: response.action, status: "uncertain", retry });
1501
+ }
1502
+ }).finally(() => {
1503
+ pending = void 0;
1504
+ });
1505
+ return pending;
1506
+ };
1507
+ return { retry, get failed() {
1508
+ return failed;
1509
+ }, get uncertain() {
1510
+ return uncertain;
1511
+ } };
1512
+ }
1513
+
1514
+ // src/use-agent-chat-hitl-submissions.ts
1515
+ function hitlSubmissionKey(threadId, runId, interruptId, generation) {
1516
+ return `${generation}:${threadId}:${runId}:${interruptId}`;
1517
+ }
1518
+ function useAgentChatHitlSubmissions(options) {
1519
+ const latest = React4.useRef(options);
1520
+ latest.current = options;
1521
+ const mounted = React4.useRef(true);
1522
+ const operations = React4.useRef(/* @__PURE__ */ new Map());
1523
+ const [states, setStates] = React4.useState({});
1524
+ const clientRef = React4.useRef(options.client);
1525
+ if (clientRef.current !== options.client) {
1526
+ clientRef.current = options.client;
1527
+ operations.current.clear();
1528
+ }
1529
+ React4.useEffect(() => {
1530
+ mounted.current = true;
1531
+ return () => {
1532
+ mounted.current = false;
1533
+ operations.current.clear();
1534
+ };
1535
+ }, []);
1536
+ const resumeHitl = React4.useCallback((part, response, submission) => {
1537
+ const captured = latest.current;
1538
+ const { client, runtime, stateRef, ownOperation, pageSize } = captured;
1539
+ const threadId = stateRef.current.activeThreadId;
1540
+ const runId = part.runId || stateRef.current.messages.find((message) => message.parts.some((candidate) => candidate.id === part.id))?.runId || stateRef.current.activeRunId;
1541
+ if (!threadId || !runId) return Promise.reject(new Error("No paused run is available to resume."));
1542
+ const isOwned = ownOperation();
1543
+ const isCurrent = () => mounted.current && latest.current.client === client && isOwned() && (!stateRef.current.activeRunId || stateRef.current.activeRunId === runId);
1544
+ const key = hitlSubmissionKey(threadId, runId, part.interruptId, captured.selectionGeneration.current);
1545
+ const live = stateRef.current.messages.filter((message) => message.runId === runId).flatMap((message) => message.parts).find((candidate) => candidate.kind === "hitl" && candidate.interruptId === part.interruptId);
1546
+ if (part.status !== "pending" || live && live.status !== "pending") return Promise.resolve();
1547
+ const previous = operations.current.get(key);
1548
+ if (previous && !previous.failed) return previous.retry();
1549
+ if (["cancelling", "cancelled", "failed", "completed"].includes(stateRef.current.runState)) return Promise.resolve();
1550
+ const operation = createHitlSubmission({
1551
+ response,
1552
+ idempotencyKey: runtime.createId(),
1553
+ prepare: submission?.prepare,
1554
+ createAbortController: runtime.createAbortController,
1555
+ isCurrent,
1556
+ send: (decision, idempotencyKey, signal) => client.hitl.resume({ runId, interruptId: part.interruptId, ...decision, idempotencyKey, signal }),
1557
+ accept: (receipt) => {
1558
+ captured.accept(receipt);
1559
+ if (!["completed", "failed", "cancelled"].includes(receipt.run_status || "")) captured.attach(receipt.run_id);
1560
+ },
1561
+ reconcile: async (signal) => {
1562
+ const [page, detail] = await Promise.all([
1563
+ client.threads.messages.list({ threadId, limit: pageSize, signal }),
1564
+ client.threads.get({ threadId, limit: pageSize, signal })
1565
+ ]);
1566
+ if (!isCurrent()) return null;
1567
+ const part2 = findHitlResolution(threadTimelineToMessages(page.items), runId, capturedPart.interruptId);
1568
+ if (!part2?.resolution) return null;
1569
+ return {
1570
+ run_id: runId,
1571
+ thread_id: threadId,
1572
+ interrupt_id: part2.interruptId,
1573
+ run_status: detail.active_run?.run_id === runId ? detail.active_run.status : detail.last_run_id === runId ? detail.last_run_status || void 0 : void 0,
1574
+ resolution: {
1575
+ ...part2.resolution,
1576
+ status: part2.status,
1577
+ action: part2.resolution.action || null,
1578
+ outcome: part2.resolution.outcome || part2.status,
1579
+ resolved_at: part2.resolution.resolved_at,
1580
+ answers: part2.resolution.answers?.map((answer) => ({
1581
+ question_id: answer.questionId,
1582
+ selected_option_ids: answer.selectedOptionIds,
1583
+ custom_text: answer.customText
1584
+ }))
1585
+ }
1586
+ };
1587
+ },
1588
+ changed: (state) => {
1589
+ if (isCurrent()) setStates((current) => ({ ...current, [key]: state }));
1590
+ },
1591
+ timing: (stage, durationMs) => runtime.onHitlTiming?.({ stage, durationMs })
1592
+ });
1593
+ const capturedPart = part;
1594
+ operations.current.set(key, operation);
1595
+ return operation.retry();
1596
+ }, []);
1597
+ const selection = options.stateRef.current.activeThreadId;
1598
+ const generation = options.selectionGeneration.current;
1599
+ React4.useEffect(() => {
1600
+ const prefix = `${generation}:${selection}:`;
1601
+ for (const key of operations.current.keys()) if (!key.startsWith(prefix)) operations.current.delete(key);
1602
+ setStates((current) => Object.fromEntries(Object.entries(current).filter(([key]) => key.startsWith(prefix))));
1603
+ }, [options.client, selection, generation]);
1604
+ return { resumeHitl, getHitlSubmissionState: (part) => {
1605
+ const runId = part.runId || options.stateRef.current.messages.find((message) => message.parts.some((candidate) => candidate.id === part.id))?.runId || options.stateRef.current.activeRunId;
1606
+ const key = runId ? hitlSubmissionKey(selection, runId, part.interruptId, generation) : null;
1607
+ const state = key && operations.current.has(key) ? states[key] : void 0;
1608
+ if (!state) return void 0;
1609
+ if (part.status !== "pending") {
1610
+ return !options.stateRef.current.activeRunId || ["completed", "failed", "cancelled"].includes(options.stateRef.current.runState) ? void 0 : { action: String(part.resolution?.action || state.action), status: "accepted" };
1611
+ }
1612
+ return state;
1613
+ } };
1614
+ }
1615
+
1385
1616
  // src/use-agent-chat.ts
1386
- import * as React7 from "react";
1617
+ import * as React8 from "react";
1387
1618
 
1388
1619
  // src/refresh-chat-summaries.ts
1389
1620
  async function refreshChatSummaries(input) {
@@ -1433,17 +1664,17 @@ async function refreshChatSummaries(input) {
1433
1664
  }
1434
1665
 
1435
1666
  // src/use-agent-chat-thread-list.ts
1436
- import * as React4 from "react";
1667
+ import * as React5 from "react";
1437
1668
  function summaryToStored(thread) {
1438
1669
  return { ...thread, id: String(thread.id), messages: [], isHydrated: false };
1439
1670
  }
1440
1671
  function useAgentChatThreadList({ client, threadPageSize, stateRef, update, clearOperationError, failOperation }) {
1441
- const [isLoadingThreads, setIsLoadingThreads] = React4.useState(false);
1442
- const [isLoadingMoreThreads, setIsLoadingMoreThreads] = React4.useState(false);
1443
- const [threadTotal, setThreadTotal] = React4.useState();
1444
- const refreshPromiseRef = React4.useRef(null);
1445
- const eventsDuringRefreshRef = React4.useRef(null);
1446
- const refreshThreads = React4.useCallback(() => {
1672
+ const [isLoadingThreads, setIsLoadingThreads] = React5.useState(false);
1673
+ const [isLoadingMoreThreads, setIsLoadingMoreThreads] = React5.useState(false);
1674
+ const [threadTotal, setThreadTotal] = React5.useState();
1675
+ const refreshPromiseRef = React5.useRef(null);
1676
+ const eventsDuringRefreshRef = React5.useRef(null);
1677
+ const refreshThreads = React5.useCallback(() => {
1447
1678
  if (refreshPromiseRef.current) return refreshPromiseRef.current;
1448
1679
  clearOperationError();
1449
1680
  setIsLoadingThreads(true);
@@ -1478,7 +1709,7 @@ function useAgentChatThreadList({ client, threadPageSize, stateRef, update, clea
1478
1709
  }).catch(() => void 0);
1479
1710
  return request;
1480
1711
  }, [clearOperationError, client, failOperation, threadPageSize, update]);
1481
- const loadMoreThreads = React4.useCallback(async () => {
1712
+ const loadMoreThreads = React5.useCallback(async () => {
1482
1713
  if (isLoadingMoreThreads) return;
1483
1714
  const skip = stateRef.current.threads.length;
1484
1715
  if (threadTotal !== void 0 && skip >= threadTotal) return;
@@ -1513,10 +1744,10 @@ function useAgentChatThreadList({ client, threadPageSize, stateRef, update, clea
1513
1744
  }
1514
1745
 
1515
1746
  // src/use-agent-chat-feedback.ts
1516
- import * as React5 from "react";
1747
+ import * as React6 from "react";
1517
1748
  function useAgentChatFeedback({ client, update, clearOperationError, failOperation, ownOperation, refreshMessages }) {
1518
- const mutations = React5.useRef(/* @__PURE__ */ new Map());
1519
- const captureRead = React5.useCallback(() => {
1749
+ const mutations = React6.useRef(/* @__PURE__ */ new Map());
1750
+ const captureRead = React6.useCallback(() => {
1520
1751
  const revisions = new Map([...mutations.current].map(([run, mutation]) => [run, mutation.readRevision]));
1521
1752
  return (incoming, current) => incoming.map((message) => {
1522
1753
  const mutation = message.runId ? mutations.current.get(message.runId) : void 0;
@@ -1525,7 +1756,7 @@ function useAgentChatFeedback({ client, update, clearOperationError, failOperati
1525
1756
  return live ? { ...message, feedback: live.feedback } : message;
1526
1757
  });
1527
1758
  }, []);
1528
- const setFeedback = React5.useCallback(async (message, input) => {
1759
+ const setFeedback = React6.useCallback(async (message, input) => {
1529
1760
  const runId = message.runId;
1530
1761
  if (!runId || message.role !== "assistant" || message.isFinal === false) {
1531
1762
  const error = new Error("Only persisted final responses can receive feedback.");
@@ -1575,7 +1806,7 @@ function useAgentChatFeedback({ client, update, clearOperationError, failOperati
1575
1806
  }
1576
1807
 
1577
1808
  // src/use-agent-chat-queue-actions.ts
1578
- import * as React6 from "react";
1809
+ import * as React7 from "react";
1579
1810
  function useAgentChatQueueActions({
1580
1811
  queue,
1581
1812
  stateRef,
@@ -1586,7 +1817,7 @@ function useAgentChatQueueActions({
1586
1817
  attachRun,
1587
1818
  ownOperation
1588
1819
  }) {
1589
- const steer = React6.useCallback(async (text2) => {
1820
+ const steer = React7.useCallback(async (text2) => {
1590
1821
  const threadId = stateRef.current.activeThreadId;
1591
1822
  if (!threadId || !text2.trim()) throw new Error("An active thread and text are required to steer.");
1592
1823
  const isCurrent = ownOperation();
@@ -1599,7 +1830,7 @@ function useAgentChatQueueActions({
1599
1830
  throw error;
1600
1831
  }
1601
1832
  }, [clearOperationError, createId, failOperation, queue.submit, refreshMessages, stateRef, ownOperation]);
1602
- const editPendingMessage = React6.useCallback(async (message, input) => {
1833
+ const editPendingMessage = React7.useCallback(async (message, input) => {
1603
1834
  await queue.edit(message, {
1604
1835
  text: input.text,
1605
1836
  attachmentIds: input.attachmentIds ?? message.attachment_ids,
@@ -1607,10 +1838,10 @@ function useAgentChatQueueActions({
1607
1838
  requestedModelId: input.requestedModelId
1608
1839
  });
1609
1840
  }, [queue.edit]);
1610
- const steerPendingMessage = React6.useCallback(async (message) => {
1841
+ const steerPendingMessage = React7.useCallback(async (message) => {
1611
1842
  await queue.edit(message, { text: message.text, attachmentIds: message.attachment_ids, mode: "steer" });
1612
1843
  }, [queue.edit]);
1613
- const resumeQueue = React6.useCallback(async () => {
1844
+ const resumeQueue = React7.useCallback(async () => {
1614
1845
  if (!stateRef.current.activeThreadId) return;
1615
1846
  const isCurrent = ownOperation();
1616
1847
  const result = await queue.resume();
@@ -1638,7 +1869,7 @@ function useAgentChat(options = {}) {
1638
1869
  const client = options.client || runtime.client;
1639
1870
  const pageSize = options.pageSize ?? 30;
1640
1871
  const threadPageSize = options.threadPageSize ?? 50;
1641
- const [state, setState] = React7.useState(() => ({
1872
+ const [state, setState] = React8.useState(() => ({
1642
1873
  ...initialAgentChatState,
1643
1874
  activeThreadId: resolveInitialActiveThreadId(
1644
1875
  options,
@@ -1646,37 +1877,51 @@ function useAgentChat(options = {}) {
1646
1877
  ),
1647
1878
  threads: runtime.storage?.loadThreads() ?? []
1648
1879
  }));
1649
- const [isLoadingHistory, setIsLoadingHistory] = React7.useState(false);
1650
- const [isLoadingOlder, setIsLoadingOlder] = React7.useState(false);
1651
- const [isSubmitting, setIsSubmitting] = React7.useState(false);
1652
- const streamControllerRef = React7.useRef(null);
1653
- const threadOpenControllerRef = React7.useRef(null);
1654
- const threadOpenGenerationRef = React7.useRef(0);
1655
- const attachRunRef = React7.useRef(async () => void 0);
1656
- const messageRefreshVersionRef = React7.useRef(0);
1657
- const promotedRunHintRef = React7.useRef(null);
1658
- const promotedAttachRef = React7.useRef(null);
1659
- const olderRequestRef = React7.useRef(null);
1660
- const submissionGenerationRef = React7.useRef(0);
1661
- const stateRef = React7.useRef(state);
1880
+ const [isLoadingHistory, setIsLoadingHistory] = React8.useState(false);
1881
+ const [isLoadingOlder, setIsLoadingOlder] = React8.useState(false);
1882
+ const [isSubmitting, setIsSubmitting] = React8.useState(false);
1883
+ const streamControllerRef = React8.useRef(null);
1884
+ const threadOpenControllerRef = React8.useRef(null);
1885
+ const threadOpenGenerationRef = React8.useRef(0);
1886
+ const attachRunRef = React8.useRef(async () => void 0);
1887
+ const messageRefreshVersionRef = React8.useRef(0);
1888
+ const promotedRunHintRef = React8.useRef(null);
1889
+ const promotedAttachRef = React8.useRef(null);
1890
+ const olderRequestRef = React8.useRef(null);
1891
+ const submissionGenerationRef = React8.useRef(0);
1892
+ const continuationTiming = React8.useRef(/* @__PURE__ */ new Map());
1893
+ const resolutionFences = React8.useRef(/* @__PURE__ */ new Map());
1894
+ const clientIdentityRef = React8.useRef(client);
1895
+ if (clientIdentityRef.current !== client) {
1896
+ resolutionFences.current.clear();
1897
+ continuationTiming.current.clear();
1898
+ clientIdentityRef.current = client;
1899
+ }
1900
+ const stateRef = React8.useRef(state);
1662
1901
  stateRef.current = state;
1663
- const ownOperation = React7.useCallback((options2) => captureChatOperation(() => ({
1902
+ const ownOperation = React8.useCallback((options2) => captureChatOperation(() => ({
1903
+ client: clientIdentityRef.current,
1664
1904
  generation: threadOpenGenerationRef.current,
1665
1905
  threadId: stateRef.current.activeThreadId,
1666
1906
  runId: stateRef.current.activeRunId,
1667
1907
  stream: streamControllerRef.current
1668
1908
  }), options2), []);
1669
- const persist = React7.useCallback((next) => {
1909
+ const persist = React8.useCallback((next) => {
1670
1910
  runtime.storage?.saveThreads(next.threads);
1671
1911
  runtime.storage?.saveActiveThreadId?.(next.activeThreadId);
1672
1912
  }, [runtime.storage]);
1673
- const update = React7.useCallback((updater) => {
1674
- const next = updater(stateRef.current);
1913
+ const update = React8.useCallback((updater) => {
1914
+ let next = updater(stateRef.current);
1915
+ for (const receipt of resolutionFences.current.values()) next = {
1916
+ ...next,
1917
+ messages: applyHitlResolution(next.messages, receipt),
1918
+ threads: next.threads.map((thread) => thread.id !== receipt.thread_id ? thread : { ...thread, messages: applyHitlResolution(thread.messages, receipt) })
1919
+ };
1675
1920
  stateRef.current = next;
1676
1921
  persist(next);
1677
1922
  setState(next);
1678
1923
  }, [persist]);
1679
- const queueTransport = React7.useMemo(() => ({
1924
+ const queueTransport = React8.useMemo(() => ({
1680
1925
  list: (threadId, signal) => client.threads.messages.list({ threadId, limit: pageSize, signal }),
1681
1926
  submit: (input) => client.threads.messages.submit(input),
1682
1927
  edit: (message, input) => client.threads.messages.edit({
@@ -1694,7 +1939,7 @@ function useAgentChat(options = {}) {
1694
1939
  },
1695
1940
  resume: (threadId) => client.threads.resumeQueue({ threadId })
1696
1941
  }), [client, pageSize]);
1697
- const attachPromotion = React7.useCallback((runId, threadId) => {
1942
+ const attachPromotion = React8.useCallback((runId, threadId) => {
1698
1943
  if (stateRef.current.activeThreadId !== threadId) return;
1699
1944
  promotedRunHintRef.current = runId;
1700
1945
  if (stateRef.current.activeRunId === runId || promotedAttachRef.current === runId) return;
@@ -1704,7 +1949,7 @@ function useAgentChat(options = {}) {
1704
1949
  if (isCurrent() && promotedAttachRef.current === runId) promotedAttachRef.current = null;
1705
1950
  });
1706
1951
  }, [ownOperation]);
1707
- const onQueuePromotion = React7.useCallback((message, runId) => {
1952
+ const onQueuePromotion = React8.useCallback((message, runId) => {
1708
1953
  if (stateRef.current.activeThreadId !== message.thread_id) return;
1709
1954
  const userMessage = threadTimelineToMessages([{ ...message, run_id: runId, status: "delivered" }])[0];
1710
1955
  update((current) => current.activeThreadId === message.thread_id ? {
@@ -1729,20 +1974,20 @@ function useAgentChat(options = {}) {
1729
1974
  onDiscard: (message) => update((current) => discardOptimisticSubmission(current, message))
1730
1975
  });
1731
1976
  const { pendingMessages, messageQueue } = queue;
1732
- const eventBuffer = React7.useMemo(
1977
+ const eventBuffer = React8.useMemo(
1733
1978
  () => createRuntimeEventFrameBuffer(
1734
1979
  (events) => update((current) => applyRuntimeEvents(current, events)),
1735
1980
  runtimeEventFrameScheduler()
1736
1981
  ),
1737
1982
  [update]
1738
1983
  );
1739
- const clearOperationError = React7.useCallback((operation) => {
1984
+ const clearOperationError = React8.useCallback((operation) => {
1740
1985
  update((current) => clearAgentChatOperationError(current, operation));
1741
1986
  }, [update]);
1742
- const clearBackgroundError = React7.useCallback(() => {
1987
+ const clearBackgroundError = React8.useCallback(() => {
1743
1988
  update(clearAgentChatBackgroundError);
1744
1989
  }, [update]);
1745
- const failOperation = React7.useCallback((operation, cause) => {
1990
+ const failOperation = React8.useCallback((operation, cause) => {
1746
1991
  update((current) => withAgentChatOperationError(current, operation, cause));
1747
1992
  }, [update]);
1748
1993
  const {
@@ -1753,7 +1998,7 @@ function useAgentChat(options = {}) {
1753
1998
  refreshThreads,
1754
1999
  loadMoreThreads
1755
2000
  } = useAgentChatThreadList({ client, threadPageSize, stateRef, update, clearOperationError, failOperation });
1756
- const invalidateThreadOpen = React7.useCallback(() => {
2001
+ const invalidateThreadOpen = React8.useCallback(() => {
1757
2002
  threadOpenGenerationRef.current += 1;
1758
2003
  threadOpenControllerRef.current?.abort("Thread selection changed.");
1759
2004
  threadOpenControllerRef.current = null;
@@ -1762,26 +2007,28 @@ function useAgentChat(options = {}) {
1762
2007
  promotedRunHintRef.current = null;
1763
2008
  olderRequestRef.current = null;
1764
2009
  queue.reset();
2010
+ resolutionFences.current.clear();
2011
+ continuationTiming.current.clear();
1765
2012
  setIsSubmitting(false);
1766
2013
  setIsLoadingOlder(false);
1767
2014
  setIsLoadingHistory(false);
1768
2015
  }, [queue.reset]);
1769
- const detach = React7.useCallback(() => {
2016
+ const detach = React8.useCallback(() => {
1770
2017
  eventBuffer.flush();
1771
2018
  streamControllerRef.current?.abort();
1772
2019
  streamControllerRef.current = null;
1773
2020
  update((current) => ({ ...current, streamingMessageId: null, runState: current.activeRunId ? "reconnecting" : "idle" }));
1774
2021
  }, [eventBuffer, update]);
1775
- const refreshMessagesRef = React7.useRef(async () => void 0);
2022
+ const refreshMessagesRef = React8.useRef(async () => void 0);
1776
2023
  const { setFeedback, captureRead: captureFeedbackRead } = useAgentChatFeedback({
1777
2024
  client,
1778
2025
  update,
1779
2026
  clearOperationError,
1780
2027
  failOperation,
1781
2028
  ownOperation,
1782
- refreshMessages: React7.useCallback(() => refreshMessagesRef.current(), [])
2029
+ refreshMessages: React8.useCallback(() => refreshMessagesRef.current(), [])
1783
2030
  });
1784
- const refreshMessages = React7.useCallback(async (threadId, promotedRunId, signal) => {
2031
+ const refreshMessages = React8.useCallback(async (threadId, promotedRunId, signal) => {
1785
2032
  const target = threadId || stateRef.current.activeThreadId;
1786
2033
  if (!target) return;
1787
2034
  const isCurrent = ownOperation();
@@ -1804,13 +2051,13 @@ function useAgentChat(options = {}) {
1804
2051
  });
1805
2052
  }, [client, ownOperation, pageSize, queue.hydrate, update, captureFeedbackRead]);
1806
2053
  refreshMessagesRef.current = refreshMessages;
1807
- React7.useEffect(() => () => {
2054
+ React8.useEffect(() => () => {
1808
2055
  threadOpenGenerationRef.current += 1;
1809
2056
  eventBuffer.dispose();
1810
2057
  streamControllerRef.current?.abort();
1811
2058
  threadOpenControllerRef.current?.abort();
1812
2059
  }, [eventBuffer]);
1813
- const openThread = React7.useCallback(async (threadId) => {
2060
+ const openThread = React8.useCallback(async (threadId) => {
1814
2061
  const previousSelection = captureAgentChatThreadSelection(stateRef.current);
1815
2062
  invalidateThreadOpen();
1816
2063
  const requestController = runtime.createAbortController();
@@ -1883,7 +2130,17 @@ function useAgentChat(options = {}) {
1883
2130
  }
1884
2131
  }
1885
2132
  }, [clearOperationError, client, detach, failOperation, pageSize, queue.hydrate, runtime, update, invalidateThreadOpen, ownOperation, captureFeedbackRead]);
1886
- const consumeEvent = React7.useCallback((event) => {
2133
+ const consumeEvent = React8.useCallback((event) => {
2134
+ const timing = continuationTiming.current.get(event.run_id);
2135
+ if (timing && !timing.attached) {
2136
+ timing.attached = true;
2137
+ runtime.onHitlTiming?.({ stage: "attachment", durationMs: Date.now() - timing.acknowledgedAt });
2138
+ }
2139
+ if (timing && !timing.active && ["assistant.delta", "model.turn.started", "tool.started"].includes(event.event)) {
2140
+ timing.active = true;
2141
+ runtime.onHitlTiming?.({ stage: "first_activity", durationMs: Date.now() - timing.acknowledgedAt });
2142
+ }
2143
+ if (["run.completed", "run.cancelled", "run.failed"].includes(event.event)) continuationTiming.current.delete(event.run_id);
1887
2144
  const eventThreadId = typeof event.payload?.thread_id === "string" ? event.payload.thread_id.trim() : "";
1888
2145
  if (eventThreadId && !stateRef.current.activeThreadId) {
1889
2146
  queue.confirmThreadAdmission(eventThreadId);
@@ -1891,8 +2148,8 @@ function useAgentChat(options = {}) {
1891
2148
  setIsSubmitting(false);
1892
2149
  }
1893
2150
  eventBuffer.push(event);
1894
- }, [eventBuffer, update, queue.confirmThreadAdmission]);
1895
- const attachRun = React7.useCallback(async (runId, cursor) => {
2151
+ }, [eventBuffer, update, queue.confirmThreadAdmission, runtime.onHitlTiming]);
2152
+ const attachRun = React8.useCallback(async (runId, cursor) => {
1896
2153
  eventBuffer.flush();
1897
2154
  streamControllerRef.current?.abort();
1898
2155
  const controller = runtime.createAbortController();
@@ -1910,7 +2167,7 @@ function useAgentChat(options = {}) {
1910
2167
  if (!result.detached && result.threadId) await refreshMessages(result.threadId);
1911
2168
  } catch (error) {
1912
2169
  if (isCurrent() && !isAbortLike(error)) {
1913
- update((current) => ({ ...current, runState: "failed", streamingMessageId: null }));
2170
+ update((current) => ({ ...current, runState: "reconnecting", streamingMessageId: null }));
1914
2171
  failOperation("attach_run", error);
1915
2172
  throw error;
1916
2173
  }
@@ -1919,7 +2176,7 @@ function useAgentChat(options = {}) {
1919
2176
  }
1920
2177
  }, [clearOperationError, client, consumeEvent, eventBuffer, failOperation, refreshMessages, runtime, update, ownOperation]);
1921
2178
  attachRunRef.current = attachRun;
1922
- const submit = React7.useCallback(async (input) => {
2179
+ const submit = React8.useCallback(async (input) => {
1923
2180
  if (!input.text.trim() && !input.attachmentIds?.length && !input.uploads?.length) return;
1924
2181
  const existingThreadId = stateRef.current.activeThreadId;
1925
2182
  if (existingThreadId || queue.hasPendingAdmission()) {
@@ -2090,12 +2347,12 @@ function useAgentChat(options = {}) {
2090
2347
  attachRun,
2091
2348
  ownOperation
2092
2349
  });
2093
- const startNewThread = React7.useCallback(() => {
2350
+ const startNewThread = React8.useCallback(() => {
2094
2351
  invalidateThreadOpen();
2095
2352
  detach();
2096
2353
  update((current) => ({ ...initialAgentChatState, threads: current.threads }));
2097
2354
  }, [detach, invalidateThreadOpen, update]);
2098
- const deleteThread = React7.useCallback(async (threadId) => {
2355
+ const deleteThread = React8.useCallback(async (threadId) => {
2099
2356
  const isCurrent = ownOperation();
2100
2357
  clearOperationError();
2101
2358
  try {
@@ -2109,7 +2366,7 @@ function useAgentChat(options = {}) {
2109
2366
  }
2110
2367
  }
2111
2368
  }, [clearOperationError, client, failOperation, ownOperation, runtime, startNewThread, update]);
2112
- const cancelRun = React7.useCallback(async () => {
2369
+ const cancelRun = React8.useCallback(async () => {
2113
2370
  const runId = stateRef.current.activeRunId;
2114
2371
  if (!runId || stateRef.current.runState === "cancelling") return;
2115
2372
  const isCurrent = ownOperation({ run: true, stream: true });
@@ -2150,29 +2407,27 @@ function useAgentChat(options = {}) {
2150
2407
  }
2151
2408
  }
2152
2409
  }, [clearOperationError, client, detach, failOperation, runtime, update, ownOperation]);
2153
- const resumeHitl = React7.useCallback(async (part, response) => {
2154
- const isCurrent = ownOperation({ run: true, stream: true });
2155
- const runId = stateRef.current.activeRunId || stateRef.current.messages.find((message) => message.parts.includes(part))?.runId;
2156
- clearOperationError();
2157
- if (!runId) {
2158
- const error = new Error("No paused run is available to resume.");
2159
- failOperation("resume_hitl", error);
2160
- throw error;
2161
- }
2162
- try {
2163
- const result = await client.hitl.resume({
2164
- runId,
2165
- interruptId: part.interruptId,
2166
- ...response,
2167
- idempotencyKey: runtime.createId()
2410
+ const { resumeHitl, getHitlSubmissionState } = useAgentChatHitlSubmissions({
2411
+ client,
2412
+ runtime,
2413
+ pageSize,
2414
+ stateRef,
2415
+ ownOperation,
2416
+ selectionGeneration: threadOpenGenerationRef,
2417
+ accept: (receipt) => {
2418
+ resolutionFences.current.set(`${receipt.run_id}:${receipt.interrupt_id}`, receipt);
2419
+ continuationTiming.current.set(receipt.run_id, { acknowledgedAt: Date.now(), attached: false, active: false });
2420
+ update((current) => {
2421
+ const status = receipt.run_status;
2422
+ return current.activeRunId === receipt.run_id && (status === "completed" || status === "failed" || status === "cancelled") ? { ...current, activeRunId: null, runState: status, streamingMessageId: null } : current;
2168
2423
  });
2169
- if (isCurrent()) await attachRun(result.run_id || runId);
2170
- } catch (error) {
2171
- if (isCurrent() && !isAbortLike(error)) failOperation("resume_hitl", error);
2172
- throw error;
2424
+ },
2425
+ attach: (runId) => {
2426
+ if (["completed", "failed", "cancelled", "cancelling"].includes(stateRef.current.runState)) return;
2427
+ void attachRunRef.current(runId, stateRef.current.cursor ?? void 0).catch(() => void 0);
2173
2428
  }
2174
- }, [attachRun, clearOperationError, client, failOperation, runtime, ownOperation]);
2175
- const loadOlder = React7.useCallback(() => {
2429
+ });
2430
+ const loadOlder = React8.useCallback(() => {
2176
2431
  const thread = stateRef.current.threads.find((item) => item.id === stateRef.current.activeThreadId);
2177
2432
  if (thread?.nextBeforeTurnIndex == null) return Promise.resolve();
2178
2433
  const cursor = thread.nextBeforeTurnIndex;
@@ -2211,7 +2466,7 @@ function useAgentChat(options = {}) {
2211
2466
  olderRequestRef.current = { key, promise };
2212
2467
  return promise;
2213
2468
  }, [clearOperationError, client, failOperation, ownOperation, pageSize, update, captureFeedbackRead]);
2214
- const regenerate = React7.useCallback(async (message) => {
2469
+ const regenerate = React8.useCallback(async (message) => {
2215
2470
  const index = stateRef.current.messages.findIndex((item) => item.id === message.id);
2216
2471
  const user = stateRef.current.messages.slice(0, index).reverse().find((item) => item.role === "user");
2217
2472
  if (user) await submit({
@@ -2297,7 +2552,7 @@ function useAgentChat(options = {}) {
2297
2552
  }
2298
2553
  }
2299
2554
  });
2300
- React7.useEffect(() => {
2555
+ React8.useEffect(() => {
2301
2556
  const threadId = options.activeThreadId;
2302
2557
  const activeThread2 = stateRef.current.threads.find((thread) => thread.id === stateRef.current.activeThreadId);
2303
2558
  if (shouldHydrateSelectedThread(threadId, stateRef.current.activeThreadId, Boolean(activeThread2?.isHydrated))) {
@@ -2337,6 +2592,7 @@ function useAgentChat(options = {}) {
2337
2592
  resumeQueue,
2338
2593
  steer,
2339
2594
  resumeHitl,
2595
+ getHitlSubmissionState,
2340
2596
  setFeedback,
2341
2597
  startNewThread,
2342
2598
  submit
@@ -2344,15 +2600,15 @@ function useAgentChat(options = {}) {
2344
2600
  }
2345
2601
 
2346
2602
  // src/use-agent-resources.ts
2347
- import * as React8 from "react";
2603
+ import * as React9 from "react";
2348
2604
  function useAgentThreads(options = {}) {
2349
2605
  const { client, createAbortController } = useAgents24Runtime();
2350
- const [threads, setThreads] = React8.useState([]);
2351
- const [total, setTotal] = React8.useState();
2352
- const [isLoading, setIsLoading] = React8.useState(true);
2353
- const [error, setError] = React8.useState(null);
2354
- const controllerRef = React8.useRef(null);
2355
- const load = React8.useCallback(async () => {
2606
+ const [threads, setThreads] = React9.useState([]);
2607
+ const [total, setTotal] = React9.useState();
2608
+ const [isLoading, setIsLoading] = React9.useState(true);
2609
+ const [error, setError] = React9.useState(null);
2610
+ const controllerRef = React9.useRef(null);
2611
+ const load = React9.useCallback(async () => {
2356
2612
  controllerRef.current?.abort();
2357
2613
  const controller = createAbortController();
2358
2614
  controllerRef.current = controller;
@@ -2371,7 +2627,7 @@ function useAgentThreads(options = {}) {
2371
2627
  }
2372
2628
  }
2373
2629
  }, [client, createAbortController, options.limit, options.skip]);
2374
- React8.useEffect(() => {
2630
+ React9.useEffect(() => {
2375
2631
  void load();
2376
2632
  return () => controllerRef.current?.abort();
2377
2633
  }, [load]);
@@ -2379,11 +2635,11 @@ function useAgentThreads(options = {}) {
2379
2635
  }
2380
2636
  function useAgentThread(threadId, options = {}) {
2381
2637
  const { client, createAbortController } = useAgents24Runtime();
2382
- const [thread, setThread] = React8.useState(null);
2383
- const [isLoading, setIsLoading] = React8.useState(Boolean(threadId));
2384
- const [error, setError] = React8.useState(null);
2385
- const controllerRef = React8.useRef(null);
2386
- const load = React8.useCallback(async () => {
2638
+ const [thread, setThread] = React9.useState(null);
2639
+ const [isLoading, setIsLoading] = React9.useState(Boolean(threadId));
2640
+ const [error, setError] = React9.useState(null);
2641
+ const controllerRef = React9.useRef(null);
2642
+ const load = React9.useCallback(async () => {
2387
2643
  if (!threadId) {
2388
2644
  controllerRef.current?.abort();
2389
2645
  controllerRef.current = null;
@@ -2410,7 +2666,7 @@ function useAgentThread(threadId, options = {}) {
2410
2666
  }
2411
2667
  }
2412
2668
  }, [client, createAbortController, options.beforeTurnIndex, options.limit, threadId]);
2413
- React8.useEffect(() => {
2669
+ React9.useEffect(() => {
2414
2670
  void load();
2415
2671
  return () => controllerRef.current?.abort();
2416
2672
  }, [load]);
@@ -2418,11 +2674,11 @@ function useAgentThread(threadId, options = {}) {
2418
2674
  }
2419
2675
  function useThreadComputer(threadId) {
2420
2676
  const { client, createAbortController } = useAgents24Runtime();
2421
- const [computer, setComputer] = React8.useState(null);
2422
- const [isLoading, setIsLoading] = React8.useState(Boolean(threadId));
2423
- const [error, setError] = React8.useState(null);
2424
- const controllerRef = React8.useRef(null);
2425
- const refresh = React8.useCallback(async () => {
2677
+ const [computer, setComputer] = React9.useState(null);
2678
+ const [isLoading, setIsLoading] = React9.useState(Boolean(threadId));
2679
+ const [error, setError] = React9.useState(null);
2680
+ const controllerRef = React9.useRef(null);
2681
+ const refresh = React9.useCallback(async () => {
2426
2682
  controllerRef.current?.abort();
2427
2683
  if (!threadId) {
2428
2684
  setComputer(null);
@@ -2447,19 +2703,19 @@ function useThreadComputer(threadId) {
2447
2703
  }
2448
2704
  }
2449
2705
  }, [client, createAbortController, threadId]);
2450
- React8.useEffect(() => {
2706
+ React9.useEffect(() => {
2451
2707
  void refresh();
2452
2708
  return () => controllerRef.current?.abort();
2453
2709
  }, [refresh]);
2454
- const list = React8.useCallback((input) => {
2710
+ const list = React9.useCallback((input) => {
2455
2711
  if (!threadId) throw new Error("A thread is required to list computer files");
2456
2712
  return client.threads.computer.list({ threadId, ...input });
2457
2713
  }, [client, threadId]);
2458
- const read = React8.useCallback((path) => {
2714
+ const read = React9.useCallback((path) => {
2459
2715
  if (!threadId) throw new Error("A thread is required to read a computer file");
2460
2716
  return client.threads.computer.read({ threadId, path });
2461
2717
  }, [client, threadId]);
2462
- const createContentAccess = React8.useCallback((path, download = false) => {
2718
+ const createContentAccess = React9.useCallback((path, download = false) => {
2463
2719
  if (!threadId) throw new Error("A thread is required to access a computer file");
2464
2720
  return client.threads.computer.createContentAccess({ threadId, path, download });
2465
2721
  }, [client, threadId]);
@@ -2467,16 +2723,16 @@ function useThreadComputer(threadId) {
2467
2723
  }
2468
2724
  function useAgentRun() {
2469
2725
  const { client, createAbortController, createId } = useAgents24Runtime();
2470
- const controllerRef = React8.useRef(null);
2471
- const [isAttached, setIsAttached] = React8.useState(false);
2472
- const [error, setError] = React8.useState(null);
2473
- React8.useEffect(() => () => controllerRef.current?.abort(), []);
2474
- const detach = React8.useCallback(() => {
2726
+ const controllerRef = React9.useRef(null);
2727
+ const [isAttached, setIsAttached] = React9.useState(false);
2728
+ const [error, setError] = React9.useState(null);
2729
+ React9.useEffect(() => () => controllerRef.current?.abort(), []);
2730
+ const detach = React9.useCallback(() => {
2475
2731
  controllerRef.current?.abort();
2476
2732
  controllerRef.current = null;
2477
2733
  setIsAttached(false);
2478
2734
  }, []);
2479
- const attach = React8.useCallback(async (runId, onEvent, cursor) => {
2735
+ const attach = React9.useCallback(async (runId, onEvent, cursor) => {
2480
2736
  detach();
2481
2737
  const controller = createAbortController();
2482
2738
  controllerRef.current = controller;
@@ -2492,7 +2748,7 @@ function useAgentRun() {
2492
2748
  setIsAttached(false);
2493
2749
  }
2494
2750
  }, [client, createAbortController, detach]);
2495
- const cancel = React8.useCallback(async (runId) => {
2751
+ const cancel = React9.useCallback(async (runId) => {
2496
2752
  const result = await client.runs.cancel({ runId, idempotencyKey: createId() });
2497
2753
  detach();
2498
2754
  return result;
@@ -2501,9 +2757,9 @@ function useAgentRun() {
2501
2757
  }
2502
2758
  function useAgentAttachments() {
2503
2759
  const { client, createId } = useAgents24Runtime();
2504
- const [uploads, setUploads] = React8.useState({});
2505
- const [isUploading, setIsUploading] = React8.useState(false);
2506
- const uploadBatch = React8.useCallback(async (input) => {
2760
+ const [uploads, setUploads] = React9.useState({});
2761
+ const [isUploading, setIsUploading] = React9.useState(false);
2762
+ const uploadBatch = React9.useCallback(async (input) => {
2507
2763
  setIsUploading(true);
2508
2764
  try {
2509
2765
  const results = await client.attachments.uploadBatch({ uploads: input.uploads, threadId: input.threadId, requestedAgentId: input.requestedAgentId, idempotencyKey: createId(), signal: input.signal });
@@ -2516,7 +2772,7 @@ function useAgentAttachments() {
2516
2772
  setIsUploading(false);
2517
2773
  }
2518
2774
  }, [client, createId]);
2519
- const createContentAccess = React8.useCallback(
2775
+ const createContentAccess = React9.useCallback(
2520
2776
  (input) => client.attachments.createContentAccess(input),
2521
2777
  [client]
2522
2778
  );
@@ -2524,9 +2780,9 @@ function useAgentAttachments() {
2524
2780
  }
2525
2781
  function useAgentHitl() {
2526
2782
  const { client, createId } = useAgents24Runtime();
2527
- const [isResolving, setIsResolving] = React8.useState(false);
2528
- const [lastResult, setLastResult] = React8.useState(null);
2529
- const resume = React8.useCallback(async (input) => {
2783
+ const [isResolving, setIsResolving] = React9.useState(false);
2784
+ const [lastResult, setLastResult] = React9.useState(null);
2785
+ const resume = React9.useCallback(async (input) => {
2530
2786
  setIsResolving(true);
2531
2787
  try {
2532
2788
  const result = await client.hitl.resume({ ...input, idempotencyKey: createId() });
@@ -2540,8 +2796,8 @@ function useAgentHitl() {
2540
2796
  }
2541
2797
  function useAgentMcp() {
2542
2798
  const { client, createId } = useAgents24Runtime();
2543
- const [isAuthorizing, setIsAuthorizing] = React8.useState(false);
2544
- const startAuthorization = React8.useCallback(async (input) => {
2799
+ const [isAuthorizing, setIsAuthorizing] = React9.useState(false);
2800
+ const startAuthorization = React9.useCallback(async (input) => {
2545
2801
  setIsAuthorizing(true);
2546
2802
  try {
2547
2803
  return await client.mcp.startAuthorization({ ...input, idempotencyKey: createId() });
@@ -2549,13 +2805,14 @@ function useAgentMcp() {
2549
2805
  setIsAuthorizing(false);
2550
2806
  }
2551
2807
  }, [client, createId]);
2552
- const redeemCallback = React8.useCallback(async (input) => client.mcp.redeemCallback({ ...input, idempotencyKey: createId() }), [client, createId]);
2808
+ const redeemCallback = React9.useCallback(async (input) => client.mcp.redeemCallback({ ...input, idempotencyKey: createId() }), [client, createId]);
2553
2809
  return { isAuthorizing, redeemCallback, startAuthorization };
2554
2810
  }
2555
2811
  export {
2556
2812
  Agents24Provider,
2557
2813
  adoptStreamingThread,
2558
2814
  appendStableStreamingTurn,
2815
+ applyHitlResolution,
2559
2816
  applyRuntimeEvent,
2560
2817
  applyRuntimeEvents,
2561
2818
  applyThreadSummaryEvent,
@@ -2569,12 +2826,15 @@ export {
2569
2826
  computerResourceTargets,
2570
2827
  contextCompressionPartFromEvent,
2571
2828
  createChatObservation,
2829
+ createHitlSubmission,
2572
2830
  createPortableId,
2573
2831
  createRuntimeEventFrameBuffer,
2574
2832
  discardOptimisticSubmission,
2833
+ findHitlResolution,
2575
2834
  getThreadActivity,
2576
2835
  initialAgentChatState,
2577
2836
  isAbortLike,
2837
+ isDefinitiveHitlRejection,
2578
2838
  latestThreadContext,
2579
2839
  modelTurnPartFromEvent,
2580
2840
  optimisticSubmissionState,
@@ -2583,6 +2843,7 @@ export {
2583
2843
  preferNewestThreadSummary,
2584
2844
  prependThreadTimeline,
2585
2845
  preserveMountedMessageIds,
2846
+ preserveResolvedHitlParts,
2586
2847
  promoteThreadMessage,
2587
2848
  reconcileRefreshedThreads,
2588
2849
  reconcileThreadTimeline,
@@ -2606,6 +2867,7 @@ export {
2606
2867
  useThreadComputer,
2607
2868
  useThreadMessageQueue,
2608
2869
  withAgentChatBackgroundError,
2609
- withAgentChatOperationError
2870
+ withAgentChatOperationError,
2871
+ withHitlDeadline
2610
2872
  };
2611
2873
  //# sourceMappingURL=index.js.map