@athenaintel/react 0.12.2 → 0.12.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -45,7 +45,6 @@ const jsxRuntime = require("react/jsx-runtime");
45
45
  const React = require("react");
46
46
  const react$1 = require("@assistant-ui/react");
47
47
  const AthenaAuthContext = require("./AthenaAuthContext-B3AwLA5Z.cjs");
48
- const localStorage$1 = require("@assistant-ui/react-statewire/local-storage");
49
48
  const tap = require("@assistant-ui/tap");
50
49
  const statewire = require("statewire");
51
50
  require("@assistant-ui/core");
@@ -73,11 +72,64 @@ function _interopNamespaceDefault(e) {
73
72
  }
74
73
  const React__namespace = /* @__PURE__ */ _interopNamespaceDefault(React);
75
74
  const ReactDOM__namespace = /* @__PURE__ */ _interopNamespaceDefault(ReactDOM);
76
- const version$1 = "0.12.2";
75
+ const version$1 = "0.12.4";
77
76
  const packageJson = {
78
77
  version: version$1
79
78
  };
80
79
  const ATHENA_REACT_SDK_VERSION = packageJson.version;
80
+ const BENIGN_BROWSER_EXCEPTION_SIGNATURES = /* @__PURE__ */ new Set([
81
+ "TypeError: Failed to fetch",
82
+ // fetch — Chromium
83
+ "TypeError: Load failed",
84
+ // fetch — Safari / WebKit
85
+ "TypeError: NetworkError when attempting to fetch resource.",
86
+ // fetch — Firefox
87
+ "AxiosError: Network Error",
88
+ // axios — no response received
89
+ "Error: ResizeObserver loop limit exceeded",
90
+ // Chromium
91
+ "Error: ResizeObserver loop completed with undelivered notifications.",
92
+ // Safari / Firefox
93
+ "TimeoutError: signal timed out",
94
+ // AbortSignal.timeout() on handled requests
95
+ "NegotiationError: negotiation timed out"
96
+ // WebRTC negotiation on flaky networks
97
+ ]);
98
+ const BENIGN_MESSAGE_PATTERNS = [
99
+ // assistant-ui useClientLookup recoverable races — the library retries.
100
+ /\(ignore if recovered\)$/,
101
+ // Drift-proof ResizeObserver loop diagnostics across engines.
102
+ /^ResizeObserver loop /
103
+ ];
104
+ const FORMULA_ERROR_CODE_TYPE_PATTERN = /^#[A-Z0-9/_]{1,14}[!?]?$/;
105
+ function isBenignBrowserExceptionEntry(exception) {
106
+ var _a3, _b2;
107
+ const type = (_a3 = exception.type) == null ? void 0 : _a3.trim();
108
+ const value = (_b2 = exception.value) == null ? void 0 : _b2.trim();
109
+ if (type === "AggregateError" && !value) return true;
110
+ if (type !== void 0 && FORMULA_ERROR_CODE_TYPE_PATTERN.test(type)) return true;
111
+ if (type === void 0 || value === void 0) return false;
112
+ if (BENIGN_BROWSER_EXCEPTION_SIGNATURES.has(`${type}: ${value}`)) return true;
113
+ return BENIGN_MESSAGE_PATTERNS.some((pattern) => pattern.test(value));
114
+ }
115
+ function isBenignBrowserException(captureResult) {
116
+ var _a3, _b2, _c2;
117
+ if (captureResult.event !== "$exception") return false;
118
+ const exceptionList = (_a3 = captureResult.properties) == null ? void 0 : _a3.$exception_list;
119
+ if (Array.isArray(exceptionList) && exceptionList.length > 0) {
120
+ return exceptionList.every(isBenignBrowserExceptionEntry);
121
+ }
122
+ return isBenignBrowserExceptionEntry({
123
+ type: (_b2 = captureResult.properties) == null ? void 0 : _b2.$exception_type,
124
+ value: (_c2 = captureResult.properties) == null ? void 0 : _c2.$exception_message
125
+ });
126
+ }
127
+ const dropBenignBrowserExceptions = (captureResult) => {
128
+ if (captureResult && isBenignBrowserException(captureResult)) {
129
+ return null;
130
+ }
131
+ return captureResult;
132
+ };
81
133
  const DEFAULT_CAPTURE_GATE_CONFIG = {
82
134
  globalMaxPerWindow: 50,
83
135
  globalWindowMs: 1e4,
@@ -486,6 +538,7 @@ async function initializePostHog(apiKey, host, debug) {
486
538
  posthog.init(apiKey, {
487
539
  api_host: host,
488
540
  autocapture: true,
541
+ before_send: dropBenignBrowserExceptions,
489
542
  capture_pageview: false,
490
543
  session_recording: {
491
544
  recordCrossOriginIframes: true,
@@ -549,6 +602,8 @@ const ATHENA_SDK_ERROR_CODES = {
549
602
  stream_failed: "stream_failed",
550
603
  /** The selected collab agent / channel was refused by the backend. */
551
604
  collab_agent_rejected: "collab_agent_rejected",
605
+ /** A React render error crashed the chat surface (caught by the SDK's error boundary). */
606
+ chat_render_crash: "chat_render_crash",
552
607
  /** Anything else. */
553
608
  unknown: "unknown"
554
609
  };
@@ -5931,7 +5986,7 @@ const cn = function() {
5931
5986
  }
5932
5987
  return twMerge.mergeString(result);
5933
5988
  };
5934
- function isRecord$2(value) {
5989
+ function isRecord$3(value) {
5935
5990
  return typeof value === "object" && value !== null && !Array.isArray(value);
5936
5991
  }
5937
5992
  var _a$2;
@@ -10607,10 +10662,10 @@ const autoCloseInFlightSubgraphMessages = (msgs) => {
10607
10662
  const beginIds = /* @__PURE__ */ new Set();
10608
10663
  const endIds = /* @__PURE__ */ new Set();
10609
10664
  for (const message of msgs) {
10610
- if (!isRecord$2(message)) continue;
10665
+ if (!isRecord$3(message)) continue;
10611
10666
  if (message.type === "ai" && Array.isArray(message.tool_calls)) {
10612
10667
  for (const toolCall of message.tool_calls) {
10613
- if (!isRecord$2(toolCall)) continue;
10668
+ if (!isRecord$3(toolCall)) continue;
10614
10669
  const id = toolCall.id;
10615
10670
  if (typeof id === "string") beginIds.add(id);
10616
10671
  }
@@ -10672,7 +10727,7 @@ const contentToParts = (content) => {
10672
10727
  const getNumberAtPath = (value, path) => {
10673
10728
  let current = value;
10674
10729
  for (const segment of path) {
10675
- if (!isRecord$2(current)) {
10730
+ if (!isRecord$3(current)) {
10676
10731
  return void 0;
10677
10732
  }
10678
10733
  current = current[segment];
@@ -10693,7 +10748,7 @@ const buildCustomMetadata = ({
10693
10748
  }) => {
10694
10749
  const customMetadata = additionalKwargs ? { ...additionalKwargs } : {};
10695
10750
  const reasoningTokens = extractReasoningTokens({ usageMetadata, responseMetadata });
10696
- const existingAthenaMetadata = isRecord$2(customMetadata._athena) ? customMetadata._athena : void 0;
10751
+ const existingAthenaMetadata = isRecord$3(customMetadata._athena) ? customMetadata._athena : void 0;
10697
10752
  const athenaMetadata = {
10698
10753
  ...existingAthenaMetadata ?? {}
10699
10754
  };
@@ -10712,9 +10767,9 @@ const buildCustomMetadata = ({
10712
10767
  return Object.keys(customMetadata).length > 0 ? customMetadata : void 0;
10713
10768
  };
10714
10769
  const getSubgraphMessages = (artifact) => {
10715
- if (!isRecord$2(artifact)) return void 0;
10770
+ if (!isRecord$3(artifact)) return void 0;
10716
10771
  const subgraphState = artifact.subgraph_state;
10717
- if (!isRecord$2(subgraphState)) return void 0;
10772
+ if (!isRecord$3(subgraphState)) return void 0;
10718
10773
  const messages = subgraphState.messages;
10719
10774
  return Array.isArray(messages) && messages.length > 0 ? messages : void 0;
10720
10775
  };
@@ -11466,7 +11521,104 @@ const useAthenaRuntime = (config2) => {
11466
11521
  }, [isExistingThread, runtime, threadId, backendUrl, resolvedStatusApiUrl]);
11467
11522
  return runtime;
11468
11523
  };
11524
+ const RUN_CONFIG_CUSTOM_KEYS = [
11525
+ "agent",
11526
+ "agent_catalog_asset_ids",
11527
+ "allowed_tab_ids",
11528
+ "app_id",
11529
+ "async_subagents",
11530
+ "catalog_asset_ids",
11531
+ "channel",
11532
+ "client_tools",
11533
+ "collab_agent_id",
11534
+ "collab_channel_id",
11535
+ "compiled_subagents",
11536
+ "declined_toolkit_ids",
11537
+ "deterministic",
11538
+ "device_id",
11539
+ "drive_mounts",
11540
+ "dry_run",
11541
+ "enable_interpreter",
11542
+ "enable_persistent_fs",
11543
+ "enable_sandbox",
11544
+ "enable_skills",
11545
+ "enabled_toolkits",
11546
+ "enabled_tools",
11547
+ "environment",
11548
+ "environment_asset_id",
11549
+ "environment_id",
11550
+ "environment_name",
11551
+ "excluded_middleware",
11552
+ "excluded_tools",
11553
+ "extra_middleware",
11554
+ "frontend_available",
11555
+ "github_identity",
11556
+ "interpreter_max_ptc_calls",
11557
+ "interpreter_mode",
11558
+ "interpreter_ptc",
11559
+ "interpreter_ptc_exclusive",
11560
+ "interpreter_runtime",
11561
+ "interpreter_subagents",
11562
+ "interpreter_timeout_seconds",
11563
+ "interrupt_on",
11564
+ "knowledge_base",
11565
+ "max_tokens",
11566
+ "mcp_server_configs",
11567
+ "mcp_servers",
11568
+ "memory",
11569
+ "middleware",
11570
+ "model",
11571
+ "office_context",
11572
+ "panel_config",
11573
+ "permissions",
11574
+ "recursion_limit",
11575
+ "run_label",
11576
+ "runtime",
11577
+ "sandbox_runtime",
11578
+ "secret_asset_ids",
11579
+ "session_id",
11580
+ "session_tab_id",
11581
+ "session_vm_retention",
11582
+ "skill_asset_ids",
11583
+ "skills",
11584
+ "skip_title_generation",
11585
+ "source_aop_id",
11586
+ "start_channel",
11587
+ "structured_output",
11588
+ "subagents",
11589
+ "system_prompt",
11590
+ "temperature",
11591
+ "tool_description_overrides",
11592
+ "tool_limit_override",
11593
+ "trigger_type",
11594
+ "voice_update_handle",
11595
+ "workbench",
11596
+ "workspace_id"
11597
+ ];
11598
+ new Set(
11599
+ RUN_CONFIG_CUSTOM_KEYS
11600
+ );
11601
+ const KNOWN_START_CHANNELS = [
11602
+ "api",
11603
+ "chrome_extension",
11604
+ "default_voice",
11605
+ "email",
11606
+ "mobile_app",
11607
+ "orchestration",
11608
+ "programmatic",
11609
+ "slack",
11610
+ "sms",
11611
+ "task",
11612
+ "teams",
11613
+ "voice",
11614
+ "web"
11615
+ ];
11616
+ new Set(
11617
+ KNOWN_START_CHANNELS
11618
+ );
11469
11619
  const CLIENT_TOOL_INTERRUPT_SOURCE = "client_tool";
11620
+ const CLIENT_TOOL_RESULT_STATUS_SUCCESS = "success";
11621
+ const CLIENT_TOOL_RESULT_STATUS_ERROR = "error";
11470
11622
  function isClientToolCallRequest(value) {
11471
11623
  if (!value || typeof value !== "object" || Array.isArray(value)) return false;
11472
11624
  const candidate = value;
@@ -11490,11 +11642,14 @@ function clientToolResultsResumeValue(results) {
11490
11642
  return { client_tool_results: results };
11491
11643
  }
11492
11644
  function clientToolSuccessEnvelope(result) {
11493
- return { status: "success", result: result === void 0 ? null : result };
11645
+ return {
11646
+ status: CLIENT_TOOL_RESULT_STATUS_SUCCESS,
11647
+ result: result === void 0 ? null : result
11648
+ };
11494
11649
  }
11495
11650
  function clientToolErrorEnvelope(error2) {
11496
11651
  const message = error2 instanceof Error ? error2.message : typeof error2 === "string" ? error2 : "Client tool execution failed.";
11497
- return { status: "error", error: message };
11652
+ return { status: CLIENT_TOOL_RESULT_STATUS_ERROR, error: message };
11498
11653
  }
11499
11654
  function createClientToolRequestTracker() {
11500
11655
  const handled = /* @__PURE__ */ new Set();
@@ -11512,6 +11667,170 @@ function createClientToolRequestTracker() {
11512
11667
  }
11513
11668
  };
11514
11669
  }
11670
+ const CLIENT_TOOL_WRITE_DECLINED_MESSAGE = "The user declined this edit. Do not retry it; ask the user how to proceed.";
11671
+ function defaultMissingClientToolMessage(toolName) {
11672
+ return `This surface has no tool named '${toolName}'.`;
11673
+ }
11674
+ function clientToolClaimKey(threadId, requestId) {
11675
+ return `${threadId}:${requestId}`;
11676
+ }
11677
+ function jsonSafeClientToolResult(value) {
11678
+ const serialized = JSON.stringify(value);
11679
+ return serialized === void 0 ? null : JSON.parse(serialized);
11680
+ }
11681
+ function isPendingClientToolRequest(request) {
11682
+ if (request.type !== "interrupt" || "response" in request) return false;
11683
+ return isClientToolInterrupt(request.payload);
11684
+ }
11685
+ async function executeClientToolBatch(options) {
11686
+ const {
11687
+ calls,
11688
+ tools,
11689
+ isLive,
11690
+ confirmWrites,
11691
+ writeDeclinedMessage = CLIENT_TOOL_WRITE_DECLINED_MESSAGE,
11692
+ missingToolMessage = defaultMissingClientToolMessage,
11693
+ onCallSettled,
11694
+ onExecutionStart
11695
+ } = options;
11696
+ const registry2 = new Map(tools.map((tool) => [tool.name, tool]));
11697
+ let writesDeclined = false;
11698
+ const writeToolNames = calls.filter((call) => {
11699
+ var _a3;
11700
+ return ((_a3 = registry2.get(call.tool_name)) == null ? void 0 : _a3.requiresWrite) === true;
11701
+ }).map((call) => call.tool_name);
11702
+ if (writeToolNames.length > 0 && confirmWrites) {
11703
+ const decision = await confirmWrites({ writeToolNames });
11704
+ if (decision === "abandoned" || !isLive()) {
11705
+ return null;
11706
+ }
11707
+ writesDeclined = decision === "declined";
11708
+ }
11709
+ onExecutionStart == null ? void 0 : onExecutionStart();
11710
+ const results = {};
11711
+ for (const call of calls) {
11712
+ if (!isLive()) return null;
11713
+ const tool = registry2.get(call.tool_name);
11714
+ let envelope;
11715
+ let status = "success";
11716
+ let errorType;
11717
+ if (!tool) {
11718
+ envelope = clientToolErrorEnvelope(missingToolMessage(call.tool_name));
11719
+ status = "error";
11720
+ errorType = "UnknownClientTool";
11721
+ } else if (tool.requiresWrite === true && writesDeclined) {
11722
+ envelope = clientToolErrorEnvelope(writeDeclinedMessage);
11723
+ status = "declined";
11724
+ } else {
11725
+ try {
11726
+ envelope = clientToolSuccessEnvelope(
11727
+ jsonSafeClientToolResult(
11728
+ await tool.run(clientToolCallArgs(call), {
11729
+ toolCallId: call.interrupt_id
11730
+ })
11731
+ )
11732
+ );
11733
+ } catch (error2) {
11734
+ envelope = clientToolErrorEnvelope(error2);
11735
+ status = "error";
11736
+ errorType = error2 instanceof Error ? error2.name : typeof error2;
11737
+ }
11738
+ }
11739
+ results[call.interrupt_id] = envelope;
11740
+ onCallSettled == null ? void 0 : onCallSettled({
11741
+ toolName: call.tool_name,
11742
+ status,
11743
+ ...errorType !== void 0 ? { errorType } : {}
11744
+ });
11745
+ }
11746
+ return isLive() ? results : null;
11747
+ }
11748
+ function useStatewireClientToolBridge(options) {
11749
+ const { threadId, tracker, inputRequests, logLabel = "[AthenaSDK]" } = options;
11750
+ const optionsRef = React.useRef(options);
11751
+ optionsRef.current = options;
11752
+ const pendingRequest = inputRequests == null ? void 0 : inputRequests.find(isPendingClientToolRequest);
11753
+ const ownedClaimsRef = React.useRef(/* @__PURE__ */ new Set());
11754
+ const startedClaimsRef = React.useRef(/* @__PURE__ */ new Set());
11755
+ const activeRef = React.useRef(true);
11756
+ const releaseClaim = React.useCallback(
11757
+ (claim) => {
11758
+ const owned = ownedClaimsRef.current.delete(claim);
11759
+ startedClaimsRef.current.delete(claim);
11760
+ if (owned) tracker.release(claim);
11761
+ },
11762
+ [tracker]
11763
+ );
11764
+ React.useEffect(() => {
11765
+ activeRef.current = true;
11766
+ const ownedClaims = ownedClaimsRef.current;
11767
+ const startedClaims = startedClaimsRef.current;
11768
+ return () => {
11769
+ activeRef.current = false;
11770
+ for (const claim of ownedClaims) {
11771
+ if (startedClaims.has(claim)) continue;
11772
+ ownedClaims.delete(claim);
11773
+ tracker.release(claim);
11774
+ }
11775
+ };
11776
+ }, [tracker]);
11777
+ const liveRequestIdsRef = React.useRef(/* @__PURE__ */ new Set());
11778
+ liveRequestIdsRef.current = new Set((inputRequests ?? []).map((request) => request.id));
11779
+ const executeRequest = React.useCallback(
11780
+ async (request) => {
11781
+ const payload = request.payload;
11782
+ if (!isClientToolInterrupt(payload)) return;
11783
+ const claim = clientToolClaimKey(threadId, request.id);
11784
+ const {
11785
+ tools,
11786
+ confirmWrites,
11787
+ writeDeclinedMessage,
11788
+ missingToolMessage,
11789
+ onCallSettled,
11790
+ sendResume
11791
+ } = optionsRef.current;
11792
+ const results = await executeClientToolBatch({
11793
+ calls: payload.context.requests,
11794
+ tools,
11795
+ // Live while the request still exists AND this surface may answer it:
11796
+ // mounted, or already past the point of no return (handlers started —
11797
+ // the detached execution must finish and settle, never re-execute).
11798
+ // After unmount the request-id snapshot freezes at its last observed
11799
+ // state, which keeps a started batch's own request visible to it.
11800
+ isLive: () => liveRequestIdsRef.current.has(request.id) && (activeRef.current || startedClaimsRef.current.has(claim)),
11801
+ onExecutionStart: () => {
11802
+ startedClaimsRef.current.add(claim);
11803
+ },
11804
+ ...confirmWrites ? {
11805
+ confirmWrites: ({ writeToolNames }) => confirmWrites({ requestId: request.id, writeToolNames })
11806
+ } : {},
11807
+ ...writeDeclinedMessage !== void 0 ? { writeDeclinedMessage } : {},
11808
+ ...missingToolMessage ? { missingToolMessage } : {},
11809
+ ...onCallSettled ? { onCallSettled } : {}
11810
+ });
11811
+ if (results === null) {
11812
+ releaseClaim(claim);
11813
+ return;
11814
+ }
11815
+ try {
11816
+ sendResume(request.id, clientToolResultsResumeValue(results));
11817
+ ownedClaimsRef.current.delete(claim);
11818
+ startedClaimsRef.current.delete(claim);
11819
+ } catch (error2) {
11820
+ releaseClaim(claim);
11821
+ console.error(`${logLabel} failed to resume client tool results:`, error2);
11822
+ }
11823
+ },
11824
+ [logLabel, releaseClaim, threadId]
11825
+ );
11826
+ React.useEffect(() => {
11827
+ if (!pendingRequest) return;
11828
+ const claim = clientToolClaimKey(threadId, pendingRequest.id);
11829
+ if (!tracker.claim(claim)) return;
11830
+ ownedClaimsRef.current.add(claim);
11831
+ void executeRequest(pendingRequest);
11832
+ }, [executeRequest, pendingRequest, threadId, tracker]);
11833
+ }
11515
11834
  const AUTH_DENIAL_PARK_THRESHOLD = 8;
11516
11835
  const initialAuthDenialTrackerState = () => ({
11517
11836
  lastAttempt: null,
@@ -11609,6 +11928,125 @@ function projectDeepAgentConnection(connection, { awaitingFirstSend = false } =
11609
11928
  if (connection.status === "connecting" && awaitingFirstSend) return { status: "ready" };
11610
11929
  return { status: connection.status };
11611
11930
  }
11931
+ const preStreamState = { messages: [], todos: [] };
11932
+ Object.freeze(preStreamState.messages);
11933
+ Object.freeze(preStreamState.todos);
11934
+ const DEEP_AGENT_PRE_STREAM_STATE = Object.freeze(preStreamState);
11935
+ function readDeepAgentStreamValues(state) {
11936
+ return typeof state === "object" && state !== null ? state : DEEP_AGENT_PRE_STREAM_STATE;
11937
+ }
11938
+ function isRecord$2(value) {
11939
+ return typeof value === "object" && value !== null && !Array.isArray(value);
11940
+ }
11941
+ function isPendingInterrupt(request) {
11942
+ return request.type === "interrupt" && !("response" in request);
11943
+ }
11944
+ function isApprovalCardInterrupt(request) {
11945
+ if (!isPendingInterrupt(request)) return false;
11946
+ return !hasClientToolInterruptSource(request.payload);
11947
+ }
11948
+ function asHitlApproval(value) {
11949
+ if (!isRecord$2(value)) return null;
11950
+ return value.type === "hitl" && value.source === "hitl_approval" && typeof value.message === "string" ? value : null;
11951
+ }
11952
+ const DEFAULT_INTERRUPT_PAUSED_MESSAGE = "The agent is paused and waiting for input.";
11953
+ function readInterruptMessage(value, fallback = DEFAULT_INTERRUPT_PAUSED_MESSAGE) {
11954
+ if (isRecord$2(value) && typeof value.message === "string" && value.message.length > 0) {
11955
+ return value.message;
11956
+ }
11957
+ return fallback;
11958
+ }
11959
+ function readAbandonedInputRequests(state) {
11960
+ const abandoned = readDeepAgentStreamValues(state).abandonedInputRequests;
11961
+ return Array.isArray(abandoned) ? abandoned : void 0;
11962
+ }
11963
+ function findAbandonedInterrupt(abandoned) {
11964
+ return abandoned == null ? void 0 : abandoned.find(
11965
+ (request) => isRecord$2(request) && request.type === "interrupt" && typeof request.id === "string"
11966
+ );
11967
+ }
11968
+ const HITL_REJECT_REASON = "User rejected the action.";
11969
+ function hitlResumeApprove() {
11970
+ return { action: "approve" };
11971
+ }
11972
+ function hitlResumeReject(reason = HITL_REJECT_REASON) {
11973
+ return { action: "reject", reason };
11974
+ }
11975
+ function hitlResumeContinue() {
11976
+ return { action: "continue" };
11977
+ }
11978
+ function useApprovalResumeLock(options) {
11979
+ const { requestId, isRunning, sendResume, pendingResumeGraceMs } = options;
11980
+ const [pending, setPending] = React.useState(false);
11981
+ const prevRequestIdRef = React.useRef(requestId);
11982
+ if (prevRequestIdRef.current !== requestId) {
11983
+ prevRequestIdRef.current = requestId;
11984
+ if (pending) setPending(false);
11985
+ }
11986
+ const sawResumeRunRef = React.useRef(false);
11987
+ React.useEffect(() => {
11988
+ if (!pending) {
11989
+ sawResumeRunRef.current = false;
11990
+ return;
11991
+ }
11992
+ if (isRunning) {
11993
+ sawResumeRunRef.current = true;
11994
+ return;
11995
+ }
11996
+ if (sawResumeRunRef.current) {
11997
+ sawResumeRunRef.current = false;
11998
+ setPending(false);
11999
+ }
12000
+ }, [pending, isRunning]);
12001
+ React.useEffect(() => {
12002
+ if (!pending || pendingResumeGraceMs === void 0) return;
12003
+ const timer = setTimeout(() => {
12004
+ if (!sawResumeRunRef.current) setPending(false);
12005
+ }, pendingResumeGraceMs);
12006
+ return () => clearTimeout(timer);
12007
+ }, [pending, requestId, pendingResumeGraceMs]);
12008
+ const sendResumeRef = React.useRef(sendResume);
12009
+ sendResumeRef.current = sendResume;
12010
+ const pendingRef = React.useRef(pending);
12011
+ pendingRef.current = pending;
12012
+ const resume = React.useCallback(
12013
+ (value) => {
12014
+ if (requestId === void 0 || pendingRef.current) return;
12015
+ setPending(true);
12016
+ pendingRef.current = true;
12017
+ sendResumeRef.current(requestId, value);
12018
+ },
12019
+ [requestId]
12020
+ );
12021
+ return { pending, resume };
12022
+ }
12023
+ function queueEntryText(parts) {
12024
+ return parts.flatMap(
12025
+ (part) => part.type === "text" && typeof part.text === "string" ? [part.text] : []
12026
+ ).join("\n\n");
12027
+ }
12028
+ function queueLaneFlags(status) {
12029
+ return {
12030
+ isRunning: status === "running",
12031
+ isContinuable: status === "stopped" || status === "error"
12032
+ };
12033
+ }
12034
+ function buildStatewireQueueRows(options) {
12035
+ const { queue, steerQueue, isContinuable } = options;
12036
+ return [
12037
+ ...isContinuable ? steerQueue.map((item) => ({ item, lane: "steer" })) : [],
12038
+ ...queue.map((item) => ({ item, lane: "queue" }))
12039
+ ];
12040
+ }
12041
+ function showQueueRowSendNow(options) {
12042
+ const { lane, index: index2, isRunning, isContinuable } = options;
12043
+ return lane === "queue" && (isContinuable || isRunning && index2 === 0);
12044
+ }
12045
+ function hasStatewireThreadExtras(extras) {
12046
+ if (!extras || typeof extras !== "object") return false;
12047
+ const candidate = extras;
12048
+ return typeof candidate.sendCommand === "function" && Array.isArray(candidate.inputRequests) && typeof candidate.runs === "object" && candidate.runs !== null;
12049
+ }
11612
12050
  const buildOptimisticHumanContent = (parts) => {
11613
12051
  const imageParts = parts.filter(
11614
12052
  (part) => part.type === "image"
@@ -11858,10 +12296,11 @@ function isLangGraphState(value) {
11858
12296
  }
11859
12297
  function convertDeepAgentState(state, { laneProjection = "both" } = {}) {
11860
12298
  var _a3, _b2;
11861
- const status = (_b2 = (_a3 = state == null ? void 0 : state.runs) == null ? void 0 : _a3[0]) == null ? void 0 : _b2.status;
12299
+ const values = readDeepAgentStreamValues(state);
12300
+ const status = (_b2 = (_a3 = values.runs) == null ? void 0 : _a3[0]) == null ? void 0 : _b2.status;
11862
12301
  const isRunning = status === "running";
11863
- const laneTail = status === "stopped" || status === "error" ? [] : laneTailMessages(state, laneProjection);
11864
- const stateMessages = isLangGraphState(state) ? sanitizeLangChainMessages(state.messages) : [];
12302
+ const laneTail = status === "stopped" || status === "error" ? [] : laneTailMessages(values, laneProjection);
12303
+ const stateMessages = isLangGraphState(values) ? sanitizeLangChainMessages(values.messages) : [];
11865
12304
  return {
11866
12305
  messages: messageConverter.toThreadMessages(
11867
12306
  [...withPendingAssistantMessage(stateMessages, isRunning), ...laneTail],
@@ -11879,6 +12318,132 @@ function registerDeepAgentRunConfig(aui, getRunConfig) {
11879
12318
  })
11880
12319
  });
11881
12320
  }
12321
+ const browserGlobals = globalThis;
12322
+ function requireLocalStorage() {
12323
+ const storage = browserGlobals.localStorage;
12324
+ if (!storage) {
12325
+ throw new Error("statewire: QuotaSafeLocalStorageSession requires localStorage");
12326
+ }
12327
+ return storage;
12328
+ }
12329
+ const SESSION_PREFIX = "aui:statewire-session:";
12330
+ const SESSION_LOCK_PREFIX = "aui:statewire-session-lock:";
12331
+ function isStorageQuotaError(error2) {
12332
+ if (typeof DOMException !== "undefined" && error2 instanceof DOMException) {
12333
+ return error2.name === "QuotaExceededError" || error2.name === "NS_ERROR_DOM_QUOTA_REACHED" || error2.code === 22 || error2.code === 1014;
12334
+ }
12335
+ if (error2 instanceof Error) {
12336
+ return /exceeded the quota|quotaexceedederror|ns_error_dom_quota_reached/i.test(error2.message);
12337
+ }
12338
+ return false;
12339
+ }
12340
+ function readEvictionMeta(raw) {
12341
+ if (!raw) return { savedAt: 0, hasPendingCommands: false };
12342
+ try {
12343
+ const parsed = JSON.parse(raw);
12344
+ return {
12345
+ savedAt: typeof (parsed == null ? void 0 : parsed.savedAt) === "number" ? parsed.savedAt : 0,
12346
+ hasPendingCommands: Array.isArray(parsed == null ? void 0 : parsed.commands) && parsed.commands.length > 0
12347
+ };
12348
+ } catch {
12349
+ return { savedAt: 0, hasPendingCommands: false };
12350
+ }
12351
+ }
12352
+ function evictOldestStatewireSessions(currentKey) {
12353
+ const storage = requireLocalStorage();
12354
+ const candidates = [];
12355
+ for (let i = 0; i < storage.length; i++) {
12356
+ const key = storage.key(i);
12357
+ if (!key || !key.startsWith(SESSION_PREFIX) || key === currentKey) continue;
12358
+ candidates.push({ key, ...readEvictionMeta(storage.getItem(key)) });
12359
+ }
12360
+ candidates.sort(
12361
+ (a, b) => Number(a.hasPendingCommands) - Number(b.hasPendingCommands) || a.savedAt - b.savedAt
12362
+ );
12363
+ const evictCount = Math.min(candidates.length, Math.max(1, Math.ceil(candidates.length / 2)));
12364
+ let removed = 0;
12365
+ for (const { key } of candidates.slice(0, evictCount)) {
12366
+ try {
12367
+ storage.removeItem(key);
12368
+ removed++;
12369
+ } catch {
12370
+ }
12371
+ }
12372
+ return removed;
12373
+ }
12374
+ function createQuotaSafeSessionStorage({
12375
+ storageKey,
12376
+ lockName
12377
+ }) {
12378
+ return {
12379
+ load: () => {
12380
+ const raw = requireLocalStorage().getItem(storageKey);
12381
+ if (raw === null) return null;
12382
+ return JSON.parse(raw);
12383
+ },
12384
+ save: (record2) => {
12385
+ const storage = requireLocalStorage();
12386
+ const serialized = JSON.stringify({ ...record2, savedAt: Date.now() });
12387
+ try {
12388
+ storage.setItem(storageKey, serialized);
12389
+ } catch (error2) {
12390
+ if (!isStorageQuotaError(error2)) throw error2;
12391
+ evictOldestStatewireSessions(storageKey);
12392
+ try {
12393
+ storage.setItem(storageKey, serialized);
12394
+ } catch (retryError) {
12395
+ if (!isStorageQuotaError(retryError)) throw retryError;
12396
+ console.warn(
12397
+ "[statewire] session save skipped — localStorage quota exhausted even after evicting old statewire sessions; the lane will not survive a reload",
12398
+ { storageKey }
12399
+ );
12400
+ }
12401
+ }
12402
+ },
12403
+ // localStorage is shared across tabs: record mutations serialize through a
12404
+ // per-key Web Lock, and `subscribe` mirrors other sharers' saves. In
12405
+ // browsers `globalThis` IS `window`, so the storage events land here.
12406
+ lock: (fn) => {
12407
+ var _a3;
12408
+ const locks = (_a3 = browserGlobals.navigator) == null ? void 0 : _a3.locks;
12409
+ if (!locks) {
12410
+ throw new Error(
12411
+ "statewire: QuotaSafeLocalStorageSession requires the Web Locks API (navigator.locks)"
12412
+ );
12413
+ }
12414
+ return locks.request(lockName, async () => fn());
12415
+ },
12416
+ subscribe: (listener) => {
12417
+ var _a3;
12418
+ const onStorage = (event) => {
12419
+ if (event.key === storageKey) listener();
12420
+ };
12421
+ (_a3 = browserGlobals.addEventListener) == null ? void 0 : _a3.call(browserGlobals, "storage", onStorage);
12422
+ return () => {
12423
+ var _a4;
12424
+ return (_a4 = browserGlobals.removeEventListener) == null ? void 0 : _a4.call(browserGlobals, "storage", onStorage);
12425
+ };
12426
+ }
12427
+ };
12428
+ }
12429
+ const useQuotaSafeLocalStorageSession = ({
12430
+ threadId,
12431
+ key = (id) => id
12432
+ }) => {
12433
+ var _a3;
12434
+ requireLocalStorage();
12435
+ if (((_a3 = browserGlobals.navigator) == null ? void 0 : _a3.locks) === void 0)
12436
+ throw new Error(
12437
+ "statewire: QuotaSafeLocalStorageSession requires the Web Locks API (navigator.locks)"
12438
+ );
12439
+ const storageKey = SESSION_PREFIX + key(threadId);
12440
+ const lockName = SESSION_LOCK_PREFIX + key(threadId);
12441
+ return React.useMemo(
12442
+ () => createQuotaSafeSessionStorage({ storageKey, lockName }),
12443
+ [storageKey, lockName]
12444
+ );
12445
+ };
12446
+ const QuotaSafeLocalStorageSession = tap.resource(useQuotaSafeLocalStorageSession);
11882
12447
  function useDeepAgentThreadStatus() {
11883
12448
  return store.useAuiState((s) => {
11884
12449
  var _a3;
@@ -11918,6 +12483,7 @@ function useDeepAgentThread({
11918
12483
  capabilities,
11919
12484
  laneProjection = "both",
11920
12485
  adapters,
12486
+ diagnostics,
11921
12487
  onError,
11922
12488
  onStateChange,
11923
12489
  onCommandChange,
@@ -11948,6 +12514,8 @@ function useDeepAgentThread({
11948
12514
  onRawConnectionChangeRef.current = onRawConnectionChange;
11949
12515
  const headersRef = React.useRef(headers);
11950
12516
  headersRef.current = headers;
12517
+ const diagnosticsRef = React.useRef(diagnostics);
12518
+ diagnosticsRef.current = diagnostics;
11951
12519
  const lastRunningRef = React.useRef(null);
11952
12520
  const lastLegacyRunActiveRef = React.useRef(null);
11953
12521
  const appliedStateRunConfigThreadRef = React.useRef(null);
@@ -12078,7 +12646,11 @@ function useDeepAgentThread({
12078
12646
  // A never-started chat has no server session yet: the transport
12079
12647
  // makes no network calls until the first command send.
12080
12648
  ...preloadRef.current.preload && { isNew: true },
12081
- headers: (ctx) => headersRef.current(ctx),
12649
+ headers: (ctx) => {
12650
+ var _a3;
12651
+ (_a3 = diagnosticsRef.current) == null ? void 0 : _a3.observeAuthResolve(ctx);
12652
+ return headersRef.current(ctx);
12653
+ },
12082
12654
  ...sessionStore && { sessionStore }
12083
12655
  },
12084
12656
  { sse }
@@ -12093,7 +12665,8 @@ function useDeepAgentThread({
12093
12665
  // former `runs: true` opt-in is gone) — the converter only maps app-owned
12094
12666
  // keys, including the `run/stop` runId stamp the lib projects itself.
12095
12667
  converter: (state, meta) => {
12096
- var _a3, _b2, _c2, _d2;
12668
+ var _a3, _b2, _c2, _d2, _e2;
12669
+ (_a3 = diagnosticsRef.current) == null ? void 0 : _a3.observeConnection(meta.connection);
12097
12670
  if (authDenialRef.current.attachId !== attachIdRef.current) {
12098
12671
  authDenialRef.current = {
12099
12672
  attachId: attachIdRef.current,
@@ -12112,7 +12685,7 @@ function useDeepAgentThread({
12112
12685
  );
12113
12686
  });
12114
12687
  }
12115
- if (awaitingFirstSendRef.current.awaiting && ((((_a3 = state == null ? void 0 : state.runs) == null ? void 0 : _a3.length) ?? 0) > 0 || (((_b2 = state == null ? void 0 : state.messages) == null ? void 0 : _b2.length) ?? 0) > 0)) {
12688
+ if (awaitingFirstSendRef.current.awaiting && ((((_b2 = state == null ? void 0 : state.runs) == null ? void 0 : _b2.length) ?? 0) > 0 || (((_c2 = state == null ? void 0 : state.messages) == null ? void 0 : _c2.length) ?? 0) > 0)) {
12116
12689
  awaitingFirstSendRef.current = {
12117
12690
  threadId: awaitingFirstSendRef.current.threadId,
12118
12691
  awaiting: false
@@ -12131,7 +12704,7 @@ function useDeepAgentThread({
12131
12704
  (_a4 = onConnectionChangeRef.current) == null ? void 0 : _a4.call(onConnectionChangeRef, connection);
12132
12705
  });
12133
12706
  }
12134
- return converter(state, ((_d2 = (_c2 = state == null ? void 0 : state.runs) == null ? void 0 : _c2[0]) == null ? void 0 : _d2.status) === "running");
12707
+ return converter(state, ((_e2 = (_d2 = state == null ? void 0 : state.runs) == null ? void 0 : _d2[0]) == null ? void 0 : _e2.status) === "running");
12135
12708
  },
12136
12709
  // Makes the server's dispatch record concrete in state (after the
12137
12710
  // optimistic folds); the lib's post-converter dispatch merge turns off.
@@ -12147,19 +12720,29 @@ function useDeepAgentThread({
12147
12720
  // deliberate user stop.
12148
12721
  stopPayload: () => ({ reason: "user_stop" }),
12149
12722
  onError: (error2) => {
12150
- var _a3;
12151
- return (_a3 = onErrorRef.current) == null ? void 0 : _a3.call(onErrorRef, error2);
12723
+ var _a3, _b2;
12724
+ (_a3 = diagnosticsRef.current) == null ? void 0 : _a3.observeError(error2);
12725
+ (_b2 = onErrorRef.current) == null ? void 0 : _b2.call(onErrorRef, error2);
12152
12726
  },
12153
12727
  ...onStateChange && {
12728
+ // The lib types the observed state `NonNullable`, but the runtime
12729
+ // delivers `undefined` where the wire has no snapshot (pre-attach and
12730
+ // replay boundaries republish it) — normalize so the type is true and
12731
+ // host observers never crash on a field read.
12154
12732
  onStateChange: ((state, ctx) => {
12155
12733
  var _a3;
12156
- return (_a3 = onStateChangeRef.current) == null ? void 0 : _a3.call(onStateChangeRef, state, ctx);
12734
+ return (_a3 = onStateChangeRef.current) == null ? void 0 : _a3.call(
12735
+ onStateChangeRef,
12736
+ readDeepAgentStreamValues(state),
12737
+ ctx
12738
+ );
12157
12739
  })
12158
12740
  },
12159
- ...onCommandChange && {
12741
+ ...(onCommandChange || diagnostics) && {
12160
12742
  onCommandChange: ((update, ctx) => {
12161
- var _a3;
12162
- return (_a3 = onCommandChangeRef.current) == null ? void 0 : _a3.call(onCommandChangeRef, update, ctx);
12743
+ var _a3, _b2;
12744
+ (_a3 = diagnosticsRef.current) == null ? void 0 : _a3.observeCommand(update);
12745
+ (_b2 = onCommandChangeRef.current) == null ? void 0 : _b2.call(onCommandChangeRef, update, ctx);
12163
12746
  })
12164
12747
  },
12165
12748
  ...onRawConnectionChange && {
@@ -12173,6 +12756,66 @@ function useDeepAgentThread({
12173
12756
  }
12174
12757
  });
12175
12758
  }
12759
+ function canPersistDeepAgentSession() {
12760
+ try {
12761
+ const storage = globalThis.localStorage;
12762
+ if (!storage) return false;
12763
+ const probeKey = "__athena_statewire_session_probe__";
12764
+ storage.setItem(probeKey, probeKey);
12765
+ storage.removeItem(probeKey);
12766
+ return true;
12767
+ } catch {
12768
+ return false;
12769
+ }
12770
+ }
12771
+ function logUnhandledStatewireError(surface, error2) {
12772
+ if (isStatewireChannelTeardown(error2)) {
12773
+ console.debug(`[${surface}] statewire channel teardown:`, error2);
12774
+ return;
12775
+ }
12776
+ console.error(`[${surface}] statewire transport error:`, error2);
12777
+ }
12778
+ function useDeepAgentRuntime(options) {
12779
+ const { surface, session = false, useClient, runConfig, onError, ...threadOptions } = options;
12780
+ const [canPersistLocalSession] = React.useState(canPersistDeepAgentSession);
12781
+ const onErrorRef = React.useRef(onError);
12782
+ onErrorRef.current = onError;
12783
+ const surfaceRef = React.useRef(surface);
12784
+ surfaceRef.current = surface;
12785
+ const thread = useDeepAgentThread({
12786
+ ...threadOptions,
12787
+ ...session !== false && session.kind === "local-storage" && canPersistLocalSession && {
12788
+ storage: {
12789
+ session: QuotaSafeLocalStorageSession({
12790
+ threadId: threadOptions.threadId,
12791
+ key: session.key
12792
+ })
12793
+ }
12794
+ },
12795
+ ...session !== false && session.kind === "session-store" && { sessionStore: session.store },
12796
+ onError: (error2) => {
12797
+ const handler = onErrorRef.current;
12798
+ if (handler) {
12799
+ handler(error2);
12800
+ return;
12801
+ }
12802
+ logUnhandledStatewireError(surfaceRef.current, error2);
12803
+ }
12804
+ });
12805
+ const client = useClient(thread);
12806
+ const getRunConfigRef = React.useRef(runConfig == null ? void 0 : runConfig.get);
12807
+ getRunConfigRef.current = runConfig == null ? void 0 : runConfig.get;
12808
+ const hasRunConfig = runConfig !== void 0;
12809
+ const runConfigKey = runConfig == null ? void 0 : runConfig.key;
12810
+ React.useEffect(() => {
12811
+ if (!hasRunConfig) return void 0;
12812
+ return registerDeepAgentRunConfig(client, () => {
12813
+ var _a3;
12814
+ return ((_a3 = getRunConfigRef.current) == null ? void 0 : _a3.call(getRunConfigRef)) ?? {};
12815
+ });
12816
+ }, [client, hasRunConfig, runConfigKey]);
12817
+ return client;
12818
+ }
12176
12819
  function isStandardSchema(schema2) {
12177
12820
  return typeof schema2 === "object" && schema2 !== null && "~standard" in schema2 && typeof schema2["~standard"] === "object";
12178
12821
  }
@@ -12275,18 +12918,7 @@ function useAthenaStatewireRuntime(config2) {
12275
12918
  onLegacyReadOnly,
12276
12919
  onRunningChange
12277
12920
  } = config2;
12278
- const tokenRef = React.useRef(token);
12279
- tokenRef.current = token;
12280
- const getTokenRef = React.useRef(getToken);
12281
- getTokenRef.current = getToken;
12282
- const apiKeyRef = React.useRef(apiKey);
12283
- apiKeyRef.current = apiKey;
12284
- const onErrorRef = React.useRef(onError);
12285
- onErrorRef.current = onError;
12286
12921
  const clientTools = useStatewireClientTools(frontendToolkit);
12287
- const clientToolsRef = React.useRef(clientTools);
12288
- clientToolsRef.current = clientTools;
12289
- const [canPersistSession] = React.useState(() => typeof localStorage !== "undefined");
12290
12922
  React.useEffect(() => {
12291
12923
  if (agent2 && !parseCollabAgentRef(agent2)) {
12292
12924
  athenaDiagnostics.emit("sdk.config.warning", {
@@ -12309,16 +12941,22 @@ function useAthenaStatewireRuntime(config2) {
12309
12941
  { thread_id: threadId, is_new_chat: isNewChat }
12310
12942
  );
12311
12943
  }
12312
- const thread = useDeepAgentThread({
12944
+ const auiTools = React.useMemo(() => react$1.Tools({ toolkit: frontendToolkit }), [frontendToolkit]);
12945
+ const useSdkClient = (thread) => react$1.useAui({ thread, tools: auiTools });
12946
+ return useDeepAgentRuntime({
12947
+ surface: "AthenaSDK",
12313
12948
  threadId,
12314
12949
  baseUrl: syncUrl,
12950
+ // Option closures are re-read per render by the core, so credential
12951
+ // rotation (new `token`/`getToken`/`apiKey` props) reaches the next
12952
+ // request without remounting the thread.
12315
12953
  headers: async () => {
12316
- const currentToken = getTokenRef.current ? await getTokenRef.current() ?? tokenRef.current : tokenRef.current;
12954
+ const currentToken = getToken ? await getToken() ?? token : token;
12317
12955
  if (currentToken) {
12318
12956
  return { Authorization: `Bearer ${currentToken}` };
12319
12957
  }
12320
- if (apiKeyRef.current) {
12321
- return { "X-API-KEY": apiKeyRef.current };
12958
+ if (apiKey) {
12959
+ return { "X-API-KEY": apiKey };
12322
12960
  }
12323
12961
  return {};
12324
12962
  },
@@ -12328,16 +12966,12 @@ function useAthenaStatewireRuntime(config2) {
12328
12966
  laneProjection: "steer-only",
12329
12967
  // Durable session: a reload resumes the lane and resends whatever the
12330
12968
  // server has not marked durable. Scoped by host — a thread id is only
12331
- // meaningful against the backend that minted it.
12332
- ...canPersistSession && {
12333
- storage: {
12334
- session: localStorage$1.LocalStorageSession({
12335
- threadId,
12336
- key: (id) => `${syncUrl}:${id}`
12337
- })
12338
- }
12339
- },
12969
+ // meaningful against the backend that minted it. (Consumers server-render
12970
+ // this SDK; the core's availability probe keeps those sessions
12971
+ // process-local, as before the seam existed.)
12972
+ session: { kind: "local-storage", key: (id) => `${syncUrl}:${id}` },
12340
12973
  capabilities: { edit: true, reload: true, continue: true },
12974
+ useClient: useSdkClient,
12341
12975
  onStateChange: () => {
12342
12976
  const endSpan = attachSpanRef.current;
12343
12977
  if (endSpan) {
@@ -12366,6 +13000,26 @@ function useAthenaStatewireRuntime(config2) {
12366
13000
  onLegacyReadOnly == null ? void 0 : onLegacyReadOnly(legacyReadOnly);
12367
13001
  },
12368
13002
  onRunningChange,
13003
+ // The runConfig getter is pulled at command-send time through the core's
13004
+ // per-render ref, so it reads the latest props — consumers commonly pass
13005
+ // fresh array literals per render, which must not thrash the registration
13006
+ // (no `key`: the provider registers once per client).
13007
+ runConfig: {
13008
+ get: () => buildStatewireRunConfig({
13009
+ model,
13010
+ agent: agent2,
13011
+ channel,
13012
+ tools,
13013
+ frontendToolIds,
13014
+ workbench,
13015
+ knowledgeBase,
13016
+ systemPrompt,
13017
+ customToolConfigs,
13018
+ appId,
13019
+ extraRunConfig,
13020
+ clientTools: statewireClientToolWireEntries(clientTools)
13021
+ })
13022
+ },
12369
13023
  onError: (error2) => {
12370
13024
  if (!isStatewireChannelTeardown(error2)) {
12371
13025
  athenaDiagnostics.error(
@@ -12379,60 +13033,17 @@ function useAthenaStatewireRuntime(config2) {
12379
13033
  { thread_id: threadId }
12380
13034
  );
12381
13035
  }
12382
- if (onErrorRef.current) {
12383
- onErrorRef.current(error2);
12384
- return;
12385
- }
12386
- if (isStatewireChannelTeardown(error2)) {
12387
- console.debug("[AthenaSDK] statewire channel teardown:", error2);
13036
+ if (onError) {
13037
+ onError(error2);
12388
13038
  return;
12389
13039
  }
12390
- console.error("[AthenaSDK] statewire transport error:", error2);
13040
+ logUnhandledStatewireError("AthenaSDK", error2);
12391
13041
  }
12392
13042
  });
12393
- const auiTools = React.useMemo(() => react$1.Tools({ toolkit: frontendToolkit }), [frontendToolkit]);
12394
- const aui = react$1.useAui({ thread, tools: auiTools });
12395
- const runConfigInputsRef = React.useRef({
12396
- model,
12397
- agent: agent2,
12398
- channel,
12399
- tools,
12400
- frontendToolIds,
12401
- workbench,
12402
- knowledgeBase,
12403
- systemPrompt,
12404
- customToolConfigs,
12405
- appId,
12406
- extraRunConfig
12407
- });
12408
- runConfigInputsRef.current = {
12409
- model,
12410
- agent: agent2,
12411
- channel,
12412
- tools,
12413
- frontendToolIds,
12414
- workbench,
12415
- knowledgeBase,
12416
- systemPrompt,
12417
- customToolConfigs,
12418
- appId,
12419
- extraRunConfig
12420
- };
12421
- React.useEffect(
12422
- () => registerDeepAgentRunConfig(
12423
- aui,
12424
- () => buildStatewireRunConfig({
12425
- ...runConfigInputsRef.current,
12426
- clientTools: statewireClientToolWireEntries(clientToolsRef.current)
12427
- })
12428
- ),
12429
- [aui]
12430
- );
12431
- return aui;
12432
13043
  }
12433
13044
  function readDetailMessage(detail) {
12434
13045
  if (typeof detail === "string" && detail.length > 0) return detail;
12435
- if (!isRecord$2(detail)) return null;
13046
+ if (!isRecord$3(detail)) return null;
12436
13047
  const message = detail.message;
12437
13048
  return typeof message === "string" && message.length > 0 ? message : null;
12438
13049
  }
@@ -12466,99 +13077,32 @@ function useAthenaStatewireLifecycle() {
12466
13077
  return React.useContext(AthenaStatewireLifecycleContext);
12467
13078
  }
12468
13079
  const clientToolRequests = createClientToolRequestTracker();
12469
- function requestKey(threadId, requestId) {
12470
- return `${threadId}:${requestId}`;
12471
- }
12472
- function jsonSafeResult(value) {
12473
- const serialized = JSON.stringify(value);
12474
- return serialized === void 0 ? null : JSON.parse(serialized);
12475
- }
12476
- function isPendingClientToolRequest(request) {
12477
- if (request.type !== "interrupt" || "response" in request) return false;
12478
- return isClientToolInterrupt(request.payload);
12479
- }
12480
13080
  function StatewireClientToolBridge({
12481
13081
  tools,
12482
13082
  threadId
12483
13083
  }) {
12484
13084
  const sendCommand = reactStatewire.useStatewireSendCommand();
12485
13085
  const inputRequests = reactStatewire.useStatewireRuns().inputRequests;
12486
- const toolsRef = React.useRef(tools);
12487
- toolsRef.current = tools;
12488
- const pendingRequest = inputRequests == null ? void 0 : inputRequests.find(isPendingClientToolRequest);
12489
- const ownedClaimsRef = React.useRef(/* @__PURE__ */ new Set());
12490
- const activeRef = React.useRef(true);
12491
- const releaseClaim = React.useCallback((claim) => {
12492
- ownedClaimsRef.current.delete(claim);
12493
- clientToolRequests.release(claim);
12494
- }, []);
12495
- React.useEffect(() => {
12496
- activeRef.current = true;
12497
- return () => {
12498
- activeRef.current = false;
12499
- for (const claim of ownedClaimsRef.current) clientToolRequests.release(claim);
12500
- ownedClaimsRef.current.clear();
12501
- };
12502
- }, []);
12503
- const liveRequestIdsRef = React.useRef(/* @__PURE__ */ new Set());
12504
- liveRequestIdsRef.current = new Set((inputRequests ?? []).map((request) => request.id));
12505
- const executeRequest = React.useCallback(
12506
- async (request) => {
12507
- const payload = request.payload;
12508
- if (!isClientToolInterrupt(payload)) return;
12509
- const calls = payload.context.requests;
12510
- const registry2 = new Map(toolsRef.current.map((tool) => [tool.name, tool]));
12511
- const results = {};
12512
- for (const call of calls) {
12513
- if (!activeRef.current || !liveRequestIdsRef.current.has(request.id)) {
12514
- releaseClaim(requestKey(threadId, request.id));
12515
- return;
12516
- }
12517
- const tool = registry2.get(call.tool_name);
12518
- if (!tool) {
12519
- results[call.interrupt_id] = clientToolErrorEnvelope(
12520
- `This surface has no tool named '${call.tool_name}'.`
12521
- );
12522
- continue;
12523
- }
12524
- try {
12525
- results[call.interrupt_id] = clientToolSuccessEnvelope(
12526
- jsonSafeResult(
12527
- await tool.handler(clientToolCallArgs(call), {
12528
- toolCallId: call.interrupt_id
12529
- })
12530
- )
12531
- );
12532
- } catch (error2) {
12533
- results[call.interrupt_id] = clientToolErrorEnvelope(error2);
12534
- }
12535
- }
12536
- if (!activeRef.current || !liveRequestIdsRef.current.has(request.id)) {
12537
- releaseClaim(requestKey(threadId, request.id));
12538
- return;
12539
- }
12540
- try {
12541
- const wireValue = clientToolResultsResumeValue(results);
12542
- sendCommand({
12543
- type: "run/input",
12544
- requestId: request.id,
12545
- response: { type: "resume", value: wireValue }
12546
- });
12547
- ownedClaimsRef.current.delete(requestKey(threadId, request.id));
12548
- } catch (error2) {
12549
- releaseClaim(requestKey(threadId, request.id));
12550
- console.error("[AthenaSDK] failed to resume client tool results:", error2);
12551
- }
12552
- },
12553
- [releaseClaim, sendCommand, threadId]
13086
+ const bridgeTools = React.useMemo(
13087
+ () => tools.map((tool) => ({
13088
+ name: tool.name,
13089
+ run: (args, context) => tool.handler(args, context)
13090
+ })),
13091
+ [tools]
12554
13092
  );
12555
- React.useEffect(() => {
12556
- if (!pendingRequest) return;
12557
- const claim = requestKey(threadId, pendingRequest.id);
12558
- if (!clientToolRequests.claim(claim)) return;
12559
- ownedClaimsRef.current.add(claim);
12560
- void executeRequest(pendingRequest);
12561
- }, [executeRequest, pendingRequest, threadId]);
13093
+ useStatewireClientToolBridge({
13094
+ threadId,
13095
+ tools: bridgeTools,
13096
+ tracker: clientToolRequests,
13097
+ inputRequests,
13098
+ sendResume: (requestId, value) => {
13099
+ sendCommand({
13100
+ type: "run/input",
13101
+ requestId,
13102
+ response: { type: "resume", value }
13103
+ });
13104
+ }
13105
+ });
12562
13106
  return null;
12563
13107
  }
12564
13108
  const ATHENA_TRANSPORTS = {
@@ -52819,7 +53363,7 @@ const DEFAULT_PILL_STYLE = "border-gray-300 bg-gray-50 text-gray-800 dark:border
52819
53363
  function MentionNodeView({ node }) {
52820
53364
  const { type, name, params } = node.attrs;
52821
53365
  const config2 = getMentionConfig(type);
52822
- const icon = isRecord$2(params) && typeof params.icon === "string" ? params.icon : (config2 == null ? void 0 : config2.style.icon) ?? "📎";
53366
+ const icon = isRecord$3(params) && typeof params.icon === "string" ? params.icon : (config2 == null ? void 0 : config2.style.icon) ?? "📎";
52823
53367
  const pillStyle = PILL_STYLES[type] ?? DEFAULT_PILL_STYLE;
52824
53368
  return /* @__PURE__ */ jsxRuntime.jsx(NodeViewWrapper, { as: "span", children: /* @__PURE__ */ jsxRuntime.jsxs(
52825
53369
  "span",
@@ -56271,102 +56815,103 @@ function Button({
56271
56815
  }
56272
56816
  );
56273
56817
  }
56274
- function hasStatewireThreadExtras(extras) {
56275
- if (!isRecord$2(extras)) return false;
56276
- return typeof extras.sendCommand === "function" && Array.isArray(extras.inputRequests) && isRecord$2(extras.runs);
56277
- }
56278
- function isPendingInterrupt(request) {
56279
- return request.type === "interrupt" && !("response" in request);
56280
- }
56281
- function isApprovalCardInterrupt(request) {
56282
- if (!isPendingInterrupt(request)) return false;
56283
- return !hasClientToolInterruptSource(request.payload);
56284
- }
56285
- function asHitlApproval(value) {
56286
- if (!isRecord$2(value)) return null;
56287
- return value.type === "hitl" && value.source === "hitl_approval" && typeof value.message === "string" ? value : null;
56288
- }
56289
- function readInterruptMessage(value) {
56290
- if (isRecord$2(value) && typeof value.message === "string" && value.message.length > 0) {
56291
- return value.message;
56818
+ class AthenaChatErrorBoundary extends React.Component {
56819
+ constructor(props) {
56820
+ super(props);
56821
+ __publicField(this, "handleRetry", () => {
56822
+ this.setState((prev) => ({ error: null, retrySeq: prev.retrySeq + 1 }));
56823
+ });
56824
+ this.state = { error: null, retrySeq: 0 };
56825
+ }
56826
+ static getDerivedStateFromError(error2) {
56827
+ return { error: error2 };
56828
+ }
56829
+ componentDidCatch(error2, errorInfo) {
56830
+ var _a3;
56831
+ athenaDiagnostics.error(
56832
+ "sdk.error",
56833
+ error2,
56834
+ {
56835
+ code: "chat_render_crash",
56836
+ message: "The chat surface crashed while rendering",
56837
+ hint: "Inspect component_stack — a custom tool UI or message component is the usual culprit."
56838
+ },
56839
+ { component_stack: ((_a3 = errorInfo.componentStack) == null ? void 0 : _a3.slice(0, 2e3)) ?? null }
56840
+ );
56841
+ }
56842
+ render() {
56843
+ if (this.state.error !== null) {
56844
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex h-full min-h-48 flex-col items-center justify-center gap-3 p-6 text-center", children: [
56845
+ /* @__PURE__ */ jsxRuntime.jsx(CircleAlert, { className: "size-6 text-destructive" }),
56846
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1", children: [
56847
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium text-foreground", children: "The chat hit an error" }),
56848
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground", children: "Your conversation is safe on the server — reload the chat to continue." })
56849
+ ] }),
56850
+ /* @__PURE__ */ jsxRuntime.jsxs(Button, { variant: "outline", size: "sm", onClick: this.handleRetry, children: [
56851
+ /* @__PURE__ */ jsxRuntime.jsx(RefreshCw, { className: "mr-1.5 size-3.5" }),
56852
+ "Reload chat"
56853
+ ] })
56854
+ ] });
56855
+ }
56856
+ return /* @__PURE__ */ jsxRuntime.jsx(React.Fragment, { children: this.props.children }, this.state.retrySeq);
56292
56857
  }
56293
- return "The agent is paused and waiting for input.";
56294
56858
  }
56295
56859
  const PENDING_RESUME_GRACE_MS = 15e3;
56296
- const StatewireApprovalCard = () => {
56860
+ const StatewireApprovalCard = (props) => {
56297
56861
  const extras = react$1.useAuiState((s) => s.thread.extras);
56298
56862
  if (!hasStatewireThreadExtras(extras)) return null;
56299
- return /* @__PURE__ */ jsxRuntime.jsx(StatewireApprovalCardInner, {});
56863
+ return /* @__PURE__ */ jsxRuntime.jsx(StatewireApprovalCardInner, { ...props });
56300
56864
  };
56301
- const StatewireApprovalCardInner = () => {
56865
+ const StatewireApprovalCardInner = ({
56866
+ classNames,
56867
+ fallbackMessage,
56868
+ interruptPredicate = isApprovalCardInterrupt
56869
+ }) => {
56302
56870
  var _a3, _b2, _c2, _d2, _e2;
56303
56871
  const sendCommand = reactStatewire.useStatewireSendCommand();
56304
- const request = (_a3 = reactStatewire.useStatewireRuns().inputRequests) == null ? void 0 : _a3.find(isApprovalCardInterrupt);
56872
+ const request = (_a3 = reactStatewire.useStatewireRuns().inputRequests) == null ? void 0 : _a3.find(interruptPredicate);
56305
56873
  const requestId = request == null ? void 0 : request.id;
56306
- const abandoned = reactStatewire.useStatewireState(
56307
- (s) => s.abandonedInputRequests
56308
- );
56309
- const abandonedInterrupt = abandoned == null ? void 0 : abandoned.find((r2) => r2.type === "interrupt");
56874
+ const abandoned = reactStatewire.useStatewireState(readAbandonedInputRequests);
56875
+ const abandonedInterrupt = findAbandonedInterrupt(abandoned);
56310
56876
  const [dismissedId, setDismissedId] = React.useState();
56311
- const [pending, setPending] = React.useState(false);
56312
- const prevRequestIdRef = React.useRef(requestId);
56313
- if (prevRequestIdRef.current !== requestId) {
56314
- prevRequestIdRef.current = requestId;
56315
- if (pending) setPending(false);
56316
- }
56317
56877
  const isRunning = react$1.useAuiState((s) => s.thread.isRunning);
56318
- const sawResumeRunRef = React.useRef(false);
56319
- React.useEffect(() => {
56320
- if (!pending) {
56321
- sawResumeRunRef.current = false;
56322
- return;
56323
- }
56324
- if (isRunning) {
56325
- sawResumeRunRef.current = true;
56326
- return;
56327
- }
56328
- if (sawResumeRunRef.current) {
56329
- sawResumeRunRef.current = false;
56330
- setPending(false);
56331
- }
56332
- }, [pending, isRunning]);
56333
- React.useEffect(() => {
56334
- if (!pending) return;
56335
- const timer = setTimeout(() => {
56336
- if (!sawResumeRunRef.current) setPending(false);
56337
- }, PENDING_RESUME_GRACE_MS);
56338
- return () => clearTimeout(timer);
56339
- }, [pending, requestId]);
56340
- const resume = React.useCallback(
56341
- (value) => {
56342
- if (requestId === void 0) return;
56343
- setPending(true);
56344
- sendCommand({
56345
- type: "run/input",
56346
- requestId,
56347
- response: { type: "resume", value }
56348
- });
56349
- },
56350
- [sendCommand, requestId]
56351
- );
56878
+ const { pending, resume } = useApprovalResumeLock({
56879
+ requestId,
56880
+ isRunning,
56881
+ pendingResumeGraceMs: PENDING_RESUME_GRACE_MS,
56882
+ sendResume: (id, value) => sendCommand({
56883
+ type: "run/input",
56884
+ requestId: id,
56885
+ response: { type: "resume", value }
56886
+ })
56887
+ });
56352
56888
  if (!request) {
56353
56889
  if (!abandonedInterrupt || abandonedInterrupt.id === dismissedId) return null;
56354
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "aui-approval-abandoned flex w-full items-center justify-between gap-3 rounded-xl border border-amber-300 bg-amber-50 px-3 py-2 text-amber-800 text-xs", children: [
56355
- /* @__PURE__ */ jsxRuntime.jsx("p", { children: "Approval was cancelled — the run moved on." }),
56356
- /* @__PURE__ */ jsxRuntime.jsx(
56357
- "button",
56358
- {
56359
- type: "button",
56360
- "aria-label": "Dismiss cancelled approval",
56361
- onClick: () => setDismissedId(abandonedInterrupt.id),
56362
- className: "shrink-0 rounded-md p-1 hover:bg-amber-100",
56363
- children: /* @__PURE__ */ jsxRuntime.jsx(X, { className: "size-3.5" })
56364
- }
56365
- )
56366
- ] });
56890
+ return /* @__PURE__ */ jsxRuntime.jsxs(
56891
+ "div",
56892
+ {
56893
+ className: cn(
56894
+ "aui-approval-abandoned flex w-full items-center justify-between gap-3 rounded-xl border border-amber-300 bg-amber-50 px-3 py-2 text-amber-800 text-xs",
56895
+ classNames == null ? void 0 : classNames.abandoned
56896
+ ),
56897
+ children: [
56898
+ /* @__PURE__ */ jsxRuntime.jsx("p", { children: "Approval was cancelled — the run moved on." }),
56899
+ /* @__PURE__ */ jsxRuntime.jsx(
56900
+ "button",
56901
+ {
56902
+ type: "button",
56903
+ "aria-label": "Dismiss cancelled approval",
56904
+ onClick: () => setDismissedId(abandonedInterrupt.id),
56905
+ className: "shrink-0 rounded-md p-1 hover:bg-amber-100",
56906
+ children: /* @__PURE__ */ jsxRuntime.jsx(X, { className: "size-3.5" })
56907
+ }
56908
+ )
56909
+ ]
56910
+ }
56911
+ );
56367
56912
  }
56368
56913
  const hitl = asHitlApproval(request.payload);
56369
- const message = readInterruptMessage(request.payload);
56914
+ const message = readInterruptMessage(request.payload, fallbackMessage);
56370
56915
  const toolName = ((_b2 = hitl == null ? void 0 : hitl.context) == null ? void 0 : _b2.tool_name) ?? ((_c2 = hitl == null ? void 0 : hitl.context) == null ? void 0 : _c2.tool_id);
56371
56916
  const toolArgs = (_d2 = hitl == null ? void 0 : hitl.context) == null ? void 0 : _d2.tool_args;
56372
56917
  const pendingCount = ((_e2 = hitl == null ? void 0 : hitl.context) == null ? void 0 : _e2.pending_action_count) ?? 1;
@@ -56374,7 +56919,10 @@ const StatewireApprovalCardInner = () => {
56374
56919
  "section",
56375
56920
  {
56376
56921
  "aria-label": hitl ? "Approval required" : "Input required",
56377
- className: "aui-approval-card w-full rounded-2xl border border-amber-300 bg-amber-50 px-4 py-3 text-amber-900",
56922
+ className: cn(
56923
+ "aui-approval-card w-full rounded-2xl border border-amber-300 bg-amber-50 px-4 py-3 text-amber-900",
56924
+ classNames == null ? void 0 : classNames.root
56925
+ ),
56378
56926
  children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-3", children: [
56379
56927
  /* @__PURE__ */ jsxRuntime.jsx(TriangleAlert, { className: "mt-0.5 size-4 shrink-0" }),
56380
56928
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 flex-1", children: [
@@ -56396,7 +56944,7 @@ const StatewireApprovalCardInner = () => {
56396
56944
  {
56397
56945
  size: "sm",
56398
56946
  disabled: pending,
56399
- onClick: () => resume({ action: "approve" }),
56947
+ onClick: () => resume(hitlResumeApprove()),
56400
56948
  className: "bg-green-600 text-white hover:bg-green-700",
56401
56949
  children: [
56402
56950
  /* @__PURE__ */ jsxRuntime.jsx(Check, {}),
@@ -56410,31 +56958,18 @@ const StatewireApprovalCardInner = () => {
56410
56958
  size: "sm",
56411
56959
  variant: "outline",
56412
56960
  disabled: pending,
56413
- onClick: () => resume({ action: "reject", reason: "User rejected the action." }),
56961
+ onClick: () => resume(hitlResumeReject()),
56414
56962
  children: [
56415
56963
  /* @__PURE__ */ jsxRuntime.jsx(X, {}),
56416
56964
  "Reject"
56417
56965
  ]
56418
56966
  }
56419
56967
  )
56420
- ] }) : /* @__PURE__ */ jsxRuntime.jsx(
56421
- Button,
56422
- {
56423
- size: "sm",
56424
- disabled: pending,
56425
- onClick: () => resume({ action: "continue" }),
56426
- children: "Continue"
56427
- }
56428
- ) })
56968
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx(Button, { size: "sm", disabled: pending, onClick: () => resume(hitlResumeContinue()), children: "Continue" }) })
56429
56969
  ] })
56430
56970
  }
56431
56971
  );
56432
56972
  };
56433
- function queueItemText(parts) {
56434
- return parts.flatMap(
56435
- (part) => part.type === "text" && typeof part.text === "string" ? [part.text] : []
56436
- ).join("\n\n");
56437
- }
56438
56973
  const StatewireQueuedMessages = () => {
56439
56974
  const extras = react$1.useAuiState((s) => s.thread.extras);
56440
56975
  if (!hasStatewireThreadExtras(extras)) return null;
@@ -56445,12 +56980,8 @@ const StatewireQueuedMessagesInner = () => {
56445
56980
  const status = useDeepAgentThreadStatus();
56446
56981
  const aui = react$1.useAui();
56447
56982
  const [expanded, setExpanded] = React.useState(true);
56448
- const isRunning = status === "running";
56449
- const isContinuable = status === "stopped" || status === "error";
56450
- const rows = [
56451
- ...isContinuable ? steerQueue.map((item) => ({ item, lane: "steer" })) : [],
56452
- ...queue.map((item) => ({ item, lane: "queue" }))
56453
- ];
56983
+ const { isRunning, isContinuable } = queueLaneFlags(status);
56984
+ const rows = buildStatewireQueueRows({ queue, steerQueue, isContinuable });
56454
56985
  if (rows.length === 0) return null;
56455
56986
  const queueHead = queue[0];
56456
56987
  return /* @__PURE__ */ jsxRuntime.jsxs(
@@ -56498,8 +57029,8 @@ const StatewireQueuedMessagesInner = () => {
56498
57029
  className: "max-h-40 overflow-y-auto",
56499
57030
  "data-testid": "athena-statewire-queue",
56500
57031
  children: rows.map(({ item, lane }, index2) => {
56501
- const text2 = queueItemText(item.parts);
56502
- const showSendNow = lane === "queue" && (isContinuable || isRunning && index2 === 0);
57032
+ const text2 = queueEntryText(item.parts);
57033
+ const showSendNow = showQueueRowSendNow({ lane, index: index2, isRunning, isContinuable });
56503
57034
  return /* @__PURE__ */ jsxRuntime.jsxs(
56504
57035
  "li",
56505
57036
  {
@@ -62070,15 +62601,15 @@ const AthenaDefaultUserMessage = () => {
62070
62601
  return /* @__PURE__ */ jsxRuntime.jsx(AthenaUserMessage, { TextComponent });
62071
62602
  };
62072
62603
  const getReasoningTokensFromMetadata = (metadata) => {
62073
- if (!isRecord$2(metadata)) {
62604
+ if (!isRecord$3(metadata)) {
62074
62605
  return void 0;
62075
62606
  }
62076
62607
  const customMetadata = metadata.custom;
62077
- if (!isRecord$2(customMetadata)) {
62608
+ if (!isRecord$3(customMetadata)) {
62078
62609
  return void 0;
62079
62610
  }
62080
62611
  const athenaMetadata = customMetadata._athena;
62081
- if (!isRecord$2(athenaMetadata)) {
62612
+ if (!isRecord$3(athenaMetadata)) {
62082
62613
  return void 0;
62083
62614
  }
62084
62615
  const reasoningTokens = athenaMetadata.reasoningTokens;
@@ -62173,7 +62704,7 @@ const AthenaChat = ({
62173
62704
  );
62174
62705
  const AssistantMessageComponent = (components == null ? void 0 : components.AssistantMessage) ?? AthenaDefaultAssistantMessage;
62175
62706
  const UserMessageComponent = (components == null ? void 0 : components.UserMessage) ?? AthenaDefaultUserMessage;
62176
- return /* @__PURE__ */ jsxRuntime.jsx(AthenaChatDefaultComponentsContext.Provider, { value: defaultComponentsContextValue, children: /* @__PURE__ */ jsxRuntime.jsxs(
62707
+ return /* @__PURE__ */ jsxRuntime.jsx(AthenaChatDefaultComponentsContext.Provider, { value: defaultComponentsContextValue, children: /* @__PURE__ */ jsxRuntime.jsx(AthenaChatErrorBoundary, { children: /* @__PURE__ */ jsxRuntime.jsxs(
62177
62708
  react$1.ThreadPrimitive.Root,
62178
62709
  {
62179
62710
  className: `aui-root aui-thread-root @container flex h-full flex-col bg-background ${className ?? ""}`,
@@ -62224,7 +62755,7 @@ const AthenaChat = ({
62224
62755
  )
62225
62756
  ]
62226
62757
  }
62227
- ) });
62758
+ ) }) });
62228
62759
  };
62229
62760
  const ThreadLoadingOverlay = () => {
62230
62761
  const remoteId = useAthenaThreadId();
@@ -63619,6 +64150,7 @@ exports.AthenaAssetEmbed = AthenaAssetEmbed;
63619
64150
  exports.AthenaAssistantActionBar = AthenaAssistantActionBar;
63620
64151
  exports.AthenaAssistantMessage = AthenaAssistantMessage;
63621
64152
  exports.AthenaChat = AthenaChat;
64153
+ exports.AthenaChatErrorBoundary = AthenaChatErrorBoundary;
63622
64154
  exports.AthenaLayout = AthenaLayout;
63623
64155
  exports.AthenaProvider = AthenaProvider;
63624
64156
  exports.AthenaReasoningPart = AthenaReasoningPart;