@athenaintel/react 0.12.3 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -20,10 +20,9 @@ var __privateWrapper = (obj, member, setter, getter) => ({
20
20
  var _focused, _cleanup, _setup, _a2, _provider, _providerCalled, _b, _online, _cleanup2, _setup2, _c, _gcTimeout, _d, _initialState, _revertState, _cache, _client, _retryer, _defaultOptions, _abortSignalConsumed, _Query_instances, isInitialPausedFetch_fn, dispatch_fn, _e, _client2, _currentQuery, _currentQueryInitialState, _currentResult, _currentResultState, _currentResultOptions, _currentThenable, _selectError, _selectFn, _selectResult, _lastQueryWithDefinedData, _staleTimeoutId, _refetchIntervalId, _currentRefetchInterval, _trackedProps, _QueryObserver_instances, executeFetch_fn, updateStaleTimeout_fn, computeRefetchInterval_fn, updateRefetchInterval_fn, updateTimers_fn, clearStaleTimeout_fn, clearRefetchInterval_fn, updateQuery_fn, notify_fn, _f, _client3, _observers, _mutationCache, _retryer2, _Mutation_instances, dispatch_fn2, _g, _mutations, _scopes, _mutationId, _h, _queries, _i, _queryCache, _mutationCache2, _defaultOptions2, _queryDefaults, _mutationDefaults, _mountCount, _unsubscribeFocus, _unsubscribeOnline, _j;
21
21
  import { jsx, Fragment as Fragment$1, jsxs } from "react/jsx-runtime";
22
22
  import * as React from "react";
23
- import React__default, { useEffect, useSyncExternalStore, useCallback, useMemo, useState, useRef, useContext, createContext, useLayoutEffect, useReducer, useDebugValue, forwardRef, createRef, memo, createElement, version as version$2, useImperativeHandle } from "react";
23
+ import React__default, { useEffect, useSyncExternalStore, useCallback, useMemo, useState, useRef, useContext, createContext, useLayoutEffect, useReducer, useDebugValue, forwardRef, createRef, memo, createElement, version as version$2, useImperativeHandle, Component, Fragment as Fragment$2 } from "react";
24
24
  import { fromThreadMessageLike, bindExternalStoreMessage, getExternalStoreMessages, INTERNAL, useAssistantTransportRuntime, Tools, useAui, useAuiState as useAuiState$1, AuiProvider, useRemoteThreadListRuntime, AssistantRuntimeProvider, MessagePartPrimitive, MessagePrimitive, useScrollLock, ActionBarPrimitive, AuiIf, ActionBarMorePrimitive, ThreadPrimitive, ComposerPrimitive, ErrorPrimitive, ThreadListPrimitive, ThreadListItemPrimitive } from "@assistant-ui/react";
25
25
  import { A as AthenaAuthContext } from "./AthenaAuthContext-DQsdayH2.js";
26
- import { LocalStorageSession } from "@assistant-ui/react-statewire/local-storage";
27
26
  import { resource, withKey } from "@assistant-ui/tap";
28
27
  import { StatewireSendError, StatewireSSE, StatewireWS } from "statewire";
29
28
  import "@assistant-ui/core";
@@ -34,11 +33,64 @@ import { useAuiState } from "@assistant-ui/store";
34
33
  import * as ReactDOM from "react-dom";
35
34
  import ReactDOM__default, { flushSync } from "react-dom";
36
35
  import { A as AthenaContext, u as useAthenaConfig } from "./AthenaContext-MOslgOmE.js";
37
- const version$1 = "0.12.3";
36
+ const version$1 = "0.13.0";
38
37
  const packageJson = {
39
38
  version: version$1
40
39
  };
41
40
  const ATHENA_REACT_SDK_VERSION = packageJson.version;
41
+ const BENIGN_BROWSER_EXCEPTION_SIGNATURES = /* @__PURE__ */ new Set([
42
+ "TypeError: Failed to fetch",
43
+ // fetch — Chromium
44
+ "TypeError: Load failed",
45
+ // fetch — Safari / WebKit
46
+ "TypeError: NetworkError when attempting to fetch resource.",
47
+ // fetch — Firefox
48
+ "AxiosError: Network Error",
49
+ // axios — no response received
50
+ "Error: ResizeObserver loop limit exceeded",
51
+ // Chromium
52
+ "Error: ResizeObserver loop completed with undelivered notifications.",
53
+ // Safari / Firefox
54
+ "TimeoutError: signal timed out",
55
+ // AbortSignal.timeout() on handled requests
56
+ "NegotiationError: negotiation timed out"
57
+ // WebRTC negotiation on flaky networks
58
+ ]);
59
+ const BENIGN_MESSAGE_PATTERNS = [
60
+ // assistant-ui useClientLookup recoverable races — the library retries.
61
+ /\(ignore if recovered\)$/,
62
+ // Drift-proof ResizeObserver loop diagnostics across engines.
63
+ /^ResizeObserver loop /
64
+ ];
65
+ const FORMULA_ERROR_CODE_TYPE_PATTERN = /^#[A-Z0-9/_]{1,14}[!?]?$/;
66
+ function isBenignBrowserExceptionEntry(exception) {
67
+ var _a3, _b2;
68
+ const type = (_a3 = exception.type) == null ? void 0 : _a3.trim();
69
+ const value = (_b2 = exception.value) == null ? void 0 : _b2.trim();
70
+ if (type === "AggregateError" && !value) return true;
71
+ if (type !== void 0 && FORMULA_ERROR_CODE_TYPE_PATTERN.test(type)) return true;
72
+ if (type === void 0 || value === void 0) return false;
73
+ if (BENIGN_BROWSER_EXCEPTION_SIGNATURES.has(`${type}: ${value}`)) return true;
74
+ return BENIGN_MESSAGE_PATTERNS.some((pattern) => pattern.test(value));
75
+ }
76
+ function isBenignBrowserException(captureResult) {
77
+ var _a3, _b2, _c2;
78
+ if (captureResult.event !== "$exception") return false;
79
+ const exceptionList = (_a3 = captureResult.properties) == null ? void 0 : _a3.$exception_list;
80
+ if (Array.isArray(exceptionList) && exceptionList.length > 0) {
81
+ return exceptionList.every(isBenignBrowserExceptionEntry);
82
+ }
83
+ return isBenignBrowserExceptionEntry({
84
+ type: (_b2 = captureResult.properties) == null ? void 0 : _b2.$exception_type,
85
+ value: (_c2 = captureResult.properties) == null ? void 0 : _c2.$exception_message
86
+ });
87
+ }
88
+ const dropBenignBrowserExceptions = (captureResult) => {
89
+ if (captureResult && isBenignBrowserException(captureResult)) {
90
+ return null;
91
+ }
92
+ return captureResult;
93
+ };
42
94
  const DEFAULT_CAPTURE_GATE_CONFIG = {
43
95
  globalMaxPerWindow: 50,
44
96
  globalWindowMs: 1e4,
@@ -447,6 +499,7 @@ async function initializePostHog(apiKey, host, debug) {
447
499
  posthog.init(apiKey, {
448
500
  api_host: host,
449
501
  autocapture: true,
502
+ before_send: dropBenignBrowserExceptions,
450
503
  capture_pageview: false,
451
504
  session_recording: {
452
505
  recordCrossOriginIframes: true,
@@ -510,6 +563,8 @@ const ATHENA_SDK_ERROR_CODES = {
510
563
  stream_failed: "stream_failed",
511
564
  /** The selected collab agent / channel was refused by the backend. */
512
565
  collab_agent_rejected: "collab_agent_rejected",
566
+ /** A React render error crashed the chat surface (caught by the SDK's error boundary). */
567
+ chat_render_crash: "chat_render_crash",
513
568
  /** Anything else. */
514
569
  unknown: "unknown"
515
570
  };
@@ -5892,7 +5947,7 @@ const cn = function() {
5892
5947
  }
5893
5948
  return twMerge.mergeString(result);
5894
5949
  };
5895
- function isRecord$2(value) {
5950
+ function isRecord$3(value) {
5896
5951
  return typeof value === "object" && value !== null && !Array.isArray(value);
5897
5952
  }
5898
5953
  var _a$2;
@@ -10568,10 +10623,10 @@ const autoCloseInFlightSubgraphMessages = (msgs) => {
10568
10623
  const beginIds = /* @__PURE__ */ new Set();
10569
10624
  const endIds = /* @__PURE__ */ new Set();
10570
10625
  for (const message of msgs) {
10571
- if (!isRecord$2(message)) continue;
10626
+ if (!isRecord$3(message)) continue;
10572
10627
  if (message.type === "ai" && Array.isArray(message.tool_calls)) {
10573
10628
  for (const toolCall of message.tool_calls) {
10574
- if (!isRecord$2(toolCall)) continue;
10629
+ if (!isRecord$3(toolCall)) continue;
10575
10630
  const id = toolCall.id;
10576
10631
  if (typeof id === "string") beginIds.add(id);
10577
10632
  }
@@ -10633,7 +10688,7 @@ const contentToParts = (content) => {
10633
10688
  const getNumberAtPath = (value, path) => {
10634
10689
  let current = value;
10635
10690
  for (const segment of path) {
10636
- if (!isRecord$2(current)) {
10691
+ if (!isRecord$3(current)) {
10637
10692
  return void 0;
10638
10693
  }
10639
10694
  current = current[segment];
@@ -10654,7 +10709,7 @@ const buildCustomMetadata = ({
10654
10709
  }) => {
10655
10710
  const customMetadata = additionalKwargs ? { ...additionalKwargs } : {};
10656
10711
  const reasoningTokens = extractReasoningTokens({ usageMetadata, responseMetadata });
10657
- const existingAthenaMetadata = isRecord$2(customMetadata._athena) ? customMetadata._athena : void 0;
10712
+ const existingAthenaMetadata = isRecord$3(customMetadata._athena) ? customMetadata._athena : void 0;
10658
10713
  const athenaMetadata = {
10659
10714
  ...existingAthenaMetadata ?? {}
10660
10715
  };
@@ -10673,9 +10728,9 @@ const buildCustomMetadata = ({
10673
10728
  return Object.keys(customMetadata).length > 0 ? customMetadata : void 0;
10674
10729
  };
10675
10730
  const getSubgraphMessages = (artifact) => {
10676
- if (!isRecord$2(artifact)) return void 0;
10731
+ if (!isRecord$3(artifact)) return void 0;
10677
10732
  const subgraphState = artifact.subgraph_state;
10678
- if (!isRecord$2(subgraphState)) return void 0;
10733
+ if (!isRecord$3(subgraphState)) return void 0;
10679
10734
  const messages = subgraphState.messages;
10680
10735
  return Array.isArray(messages) && messages.length > 0 ? messages : void 0;
10681
10736
  };
@@ -11427,7 +11482,104 @@ const useAthenaRuntime = (config2) => {
11427
11482
  }, [isExistingThread, runtime, threadId, backendUrl, resolvedStatusApiUrl]);
11428
11483
  return runtime;
11429
11484
  };
11485
+ const RUN_CONFIG_CUSTOM_KEYS = [
11486
+ "agent",
11487
+ "agent_catalog_asset_ids",
11488
+ "allowed_tab_ids",
11489
+ "app_id",
11490
+ "async_subagents",
11491
+ "catalog_asset_ids",
11492
+ "channel",
11493
+ "client_tools",
11494
+ "collab_agent_id",
11495
+ "collab_channel_id",
11496
+ "compiled_subagents",
11497
+ "declined_toolkit_ids",
11498
+ "deterministic",
11499
+ "device_id",
11500
+ "drive_mounts",
11501
+ "dry_run",
11502
+ "enable_interpreter",
11503
+ "enable_persistent_fs",
11504
+ "enable_sandbox",
11505
+ "enable_skills",
11506
+ "enabled_toolkits",
11507
+ "enabled_tools",
11508
+ "environment",
11509
+ "environment_asset_id",
11510
+ "environment_id",
11511
+ "environment_name",
11512
+ "excluded_middleware",
11513
+ "excluded_tools",
11514
+ "extra_middleware",
11515
+ "frontend_available",
11516
+ "github_identity",
11517
+ "interpreter_max_ptc_calls",
11518
+ "interpreter_mode",
11519
+ "interpreter_ptc",
11520
+ "interpreter_ptc_exclusive",
11521
+ "interpreter_runtime",
11522
+ "interpreter_subagents",
11523
+ "interpreter_timeout_seconds",
11524
+ "interrupt_on",
11525
+ "knowledge_base",
11526
+ "max_tokens",
11527
+ "mcp_server_configs",
11528
+ "mcp_servers",
11529
+ "memory",
11530
+ "middleware",
11531
+ "model",
11532
+ "office_context",
11533
+ "panel_config",
11534
+ "permissions",
11535
+ "recursion_limit",
11536
+ "run_label",
11537
+ "runtime",
11538
+ "sandbox_runtime",
11539
+ "secret_asset_ids",
11540
+ "session_id",
11541
+ "session_tab_id",
11542
+ "session_vm_retention",
11543
+ "skill_asset_ids",
11544
+ "skills",
11545
+ "skip_title_generation",
11546
+ "source_aop_id",
11547
+ "start_channel",
11548
+ "structured_output",
11549
+ "subagents",
11550
+ "system_prompt",
11551
+ "temperature",
11552
+ "tool_description_overrides",
11553
+ "tool_limit_override",
11554
+ "trigger_type",
11555
+ "voice_update_handle",
11556
+ "workbench",
11557
+ "workspace_id"
11558
+ ];
11559
+ new Set(
11560
+ RUN_CONFIG_CUSTOM_KEYS
11561
+ );
11562
+ const KNOWN_START_CHANNELS = [
11563
+ "api",
11564
+ "chrome_extension",
11565
+ "default_voice",
11566
+ "email",
11567
+ "mobile_app",
11568
+ "orchestration",
11569
+ "programmatic",
11570
+ "slack",
11571
+ "sms",
11572
+ "task",
11573
+ "teams",
11574
+ "voice",
11575
+ "web"
11576
+ ];
11577
+ new Set(
11578
+ KNOWN_START_CHANNELS
11579
+ );
11430
11580
  const CLIENT_TOOL_INTERRUPT_SOURCE = "client_tool";
11581
+ const CLIENT_TOOL_RESULT_STATUS_SUCCESS = "success";
11582
+ const CLIENT_TOOL_RESULT_STATUS_ERROR = "error";
11431
11583
  function isClientToolCallRequest(value) {
11432
11584
  if (!value || typeof value !== "object" || Array.isArray(value)) return false;
11433
11585
  const candidate = value;
@@ -11451,11 +11603,14 @@ function clientToolResultsResumeValue(results) {
11451
11603
  return { client_tool_results: results };
11452
11604
  }
11453
11605
  function clientToolSuccessEnvelope(result) {
11454
- return { status: "success", result: result === void 0 ? null : result };
11606
+ return {
11607
+ status: CLIENT_TOOL_RESULT_STATUS_SUCCESS,
11608
+ result: result === void 0 ? null : result
11609
+ };
11455
11610
  }
11456
11611
  function clientToolErrorEnvelope(error2) {
11457
11612
  const message = error2 instanceof Error ? error2.message : typeof error2 === "string" ? error2 : "Client tool execution failed.";
11458
- return { status: "error", error: message };
11613
+ return { status: CLIENT_TOOL_RESULT_STATUS_ERROR, error: message };
11459
11614
  }
11460
11615
  function createClientToolRequestTracker() {
11461
11616
  const handled = /* @__PURE__ */ new Set();
@@ -11473,6 +11628,170 @@ function createClientToolRequestTracker() {
11473
11628
  }
11474
11629
  };
11475
11630
  }
11631
+ const CLIENT_TOOL_WRITE_DECLINED_MESSAGE = "The user declined this edit. Do not retry it; ask the user how to proceed.";
11632
+ function defaultMissingClientToolMessage(toolName) {
11633
+ return `This surface has no tool named '${toolName}'.`;
11634
+ }
11635
+ function clientToolClaimKey(threadId, requestId) {
11636
+ return `${threadId}:${requestId}`;
11637
+ }
11638
+ function jsonSafeClientToolResult(value) {
11639
+ const serialized = JSON.stringify(value);
11640
+ return serialized === void 0 ? null : JSON.parse(serialized);
11641
+ }
11642
+ function isPendingClientToolRequest(request) {
11643
+ if (request.type !== "interrupt" || "response" in request) return false;
11644
+ return isClientToolInterrupt(request.payload);
11645
+ }
11646
+ async function executeClientToolBatch(options) {
11647
+ const {
11648
+ calls,
11649
+ tools,
11650
+ isLive,
11651
+ confirmWrites,
11652
+ writeDeclinedMessage = CLIENT_TOOL_WRITE_DECLINED_MESSAGE,
11653
+ missingToolMessage = defaultMissingClientToolMessage,
11654
+ onCallSettled,
11655
+ onExecutionStart
11656
+ } = options;
11657
+ const registry2 = new Map(tools.map((tool) => [tool.name, tool]));
11658
+ let writesDeclined = false;
11659
+ const writeToolNames = calls.filter((call) => {
11660
+ var _a3;
11661
+ return ((_a3 = registry2.get(call.tool_name)) == null ? void 0 : _a3.requiresWrite) === true;
11662
+ }).map((call) => call.tool_name);
11663
+ if (writeToolNames.length > 0 && confirmWrites) {
11664
+ const decision = await confirmWrites({ writeToolNames });
11665
+ if (decision === "abandoned" || !isLive()) {
11666
+ return null;
11667
+ }
11668
+ writesDeclined = decision === "declined";
11669
+ }
11670
+ onExecutionStart == null ? void 0 : onExecutionStart();
11671
+ const results = {};
11672
+ for (const call of calls) {
11673
+ if (!isLive()) return null;
11674
+ const tool = registry2.get(call.tool_name);
11675
+ let envelope;
11676
+ let status = "success";
11677
+ let errorType;
11678
+ if (!tool) {
11679
+ envelope = clientToolErrorEnvelope(missingToolMessage(call.tool_name));
11680
+ status = "error";
11681
+ errorType = "UnknownClientTool";
11682
+ } else if (tool.requiresWrite === true && writesDeclined) {
11683
+ envelope = clientToolErrorEnvelope(writeDeclinedMessage);
11684
+ status = "declined";
11685
+ } else {
11686
+ try {
11687
+ envelope = clientToolSuccessEnvelope(
11688
+ jsonSafeClientToolResult(
11689
+ await tool.run(clientToolCallArgs(call), {
11690
+ toolCallId: call.interrupt_id
11691
+ })
11692
+ )
11693
+ );
11694
+ } catch (error2) {
11695
+ envelope = clientToolErrorEnvelope(error2);
11696
+ status = "error";
11697
+ errorType = error2 instanceof Error ? error2.name : typeof error2;
11698
+ }
11699
+ }
11700
+ results[call.interrupt_id] = envelope;
11701
+ onCallSettled == null ? void 0 : onCallSettled({
11702
+ toolName: call.tool_name,
11703
+ status,
11704
+ ...errorType !== void 0 ? { errorType } : {}
11705
+ });
11706
+ }
11707
+ return isLive() ? results : null;
11708
+ }
11709
+ function useStatewireClientToolBridge(options) {
11710
+ const { threadId, tracker, inputRequests, logLabel = "[AthenaSDK]" } = options;
11711
+ const optionsRef = useRef(options);
11712
+ optionsRef.current = options;
11713
+ const pendingRequest = inputRequests == null ? void 0 : inputRequests.find(isPendingClientToolRequest);
11714
+ const ownedClaimsRef = useRef(/* @__PURE__ */ new Set());
11715
+ const startedClaimsRef = useRef(/* @__PURE__ */ new Set());
11716
+ const activeRef = useRef(true);
11717
+ const releaseClaim = useCallback(
11718
+ (claim) => {
11719
+ const owned = ownedClaimsRef.current.delete(claim);
11720
+ startedClaimsRef.current.delete(claim);
11721
+ if (owned) tracker.release(claim);
11722
+ },
11723
+ [tracker]
11724
+ );
11725
+ useEffect(() => {
11726
+ activeRef.current = true;
11727
+ const ownedClaims = ownedClaimsRef.current;
11728
+ const startedClaims = startedClaimsRef.current;
11729
+ return () => {
11730
+ activeRef.current = false;
11731
+ for (const claim of ownedClaims) {
11732
+ if (startedClaims.has(claim)) continue;
11733
+ ownedClaims.delete(claim);
11734
+ tracker.release(claim);
11735
+ }
11736
+ };
11737
+ }, [tracker]);
11738
+ const liveRequestIdsRef = useRef(/* @__PURE__ */ new Set());
11739
+ liveRequestIdsRef.current = new Set((inputRequests ?? []).map((request) => request.id));
11740
+ const executeRequest = useCallback(
11741
+ async (request) => {
11742
+ const payload = request.payload;
11743
+ if (!isClientToolInterrupt(payload)) return;
11744
+ const claim = clientToolClaimKey(threadId, request.id);
11745
+ const {
11746
+ tools,
11747
+ confirmWrites,
11748
+ writeDeclinedMessage,
11749
+ missingToolMessage,
11750
+ onCallSettled,
11751
+ sendResume
11752
+ } = optionsRef.current;
11753
+ const results = await executeClientToolBatch({
11754
+ calls: payload.context.requests,
11755
+ tools,
11756
+ // Live while the request still exists AND this surface may answer it:
11757
+ // mounted, or already past the point of no return (handlers started —
11758
+ // the detached execution must finish and settle, never re-execute).
11759
+ // After unmount the request-id snapshot freezes at its last observed
11760
+ // state, which keeps a started batch's own request visible to it.
11761
+ isLive: () => liveRequestIdsRef.current.has(request.id) && (activeRef.current || startedClaimsRef.current.has(claim)),
11762
+ onExecutionStart: () => {
11763
+ startedClaimsRef.current.add(claim);
11764
+ },
11765
+ ...confirmWrites ? {
11766
+ confirmWrites: ({ writeToolNames }) => confirmWrites({ requestId: request.id, writeToolNames })
11767
+ } : {},
11768
+ ...writeDeclinedMessage !== void 0 ? { writeDeclinedMessage } : {},
11769
+ ...missingToolMessage ? { missingToolMessage } : {},
11770
+ ...onCallSettled ? { onCallSettled } : {}
11771
+ });
11772
+ if (results === null) {
11773
+ releaseClaim(claim);
11774
+ return;
11775
+ }
11776
+ try {
11777
+ sendResume(request.id, clientToolResultsResumeValue(results));
11778
+ ownedClaimsRef.current.delete(claim);
11779
+ startedClaimsRef.current.delete(claim);
11780
+ } catch (error2) {
11781
+ releaseClaim(claim);
11782
+ console.error(`${logLabel} failed to resume client tool results:`, error2);
11783
+ }
11784
+ },
11785
+ [logLabel, releaseClaim, threadId]
11786
+ );
11787
+ useEffect(() => {
11788
+ if (!pendingRequest) return;
11789
+ const claim = clientToolClaimKey(threadId, pendingRequest.id);
11790
+ if (!tracker.claim(claim)) return;
11791
+ ownedClaimsRef.current.add(claim);
11792
+ void executeRequest(pendingRequest);
11793
+ }, [executeRequest, pendingRequest, threadId, tracker]);
11794
+ }
11476
11795
  const AUTH_DENIAL_PARK_THRESHOLD = 8;
11477
11796
  const initialAuthDenialTrackerState = () => ({
11478
11797
  lastAttempt: null,
@@ -11570,6 +11889,125 @@ function projectDeepAgentConnection(connection, { awaitingFirstSend = false } =
11570
11889
  if (connection.status === "connecting" && awaitingFirstSend) return { status: "ready" };
11571
11890
  return { status: connection.status };
11572
11891
  }
11892
+ const preStreamState = { messages: [], todos: [] };
11893
+ Object.freeze(preStreamState.messages);
11894
+ Object.freeze(preStreamState.todos);
11895
+ const DEEP_AGENT_PRE_STREAM_STATE = Object.freeze(preStreamState);
11896
+ function readDeepAgentStreamValues(state) {
11897
+ return typeof state === "object" && state !== null ? state : DEEP_AGENT_PRE_STREAM_STATE;
11898
+ }
11899
+ function isRecord$2(value) {
11900
+ return typeof value === "object" && value !== null && !Array.isArray(value);
11901
+ }
11902
+ function isPendingInterrupt(request) {
11903
+ return request.type === "interrupt" && !("response" in request);
11904
+ }
11905
+ function isApprovalCardInterrupt(request) {
11906
+ if (!isPendingInterrupt(request)) return false;
11907
+ return !hasClientToolInterruptSource(request.payload);
11908
+ }
11909
+ function asHitlApproval(value) {
11910
+ if (!isRecord$2(value)) return null;
11911
+ return value.type === "hitl" && value.source === "hitl_approval" && typeof value.message === "string" ? value : null;
11912
+ }
11913
+ const DEFAULT_INTERRUPT_PAUSED_MESSAGE = "The agent is paused and waiting for input.";
11914
+ function readInterruptMessage(value, fallback = DEFAULT_INTERRUPT_PAUSED_MESSAGE) {
11915
+ if (isRecord$2(value) && typeof value.message === "string" && value.message.length > 0) {
11916
+ return value.message;
11917
+ }
11918
+ return fallback;
11919
+ }
11920
+ function readAbandonedInputRequests(state) {
11921
+ const abandoned = readDeepAgentStreamValues(state).abandonedInputRequests;
11922
+ return Array.isArray(abandoned) ? abandoned : void 0;
11923
+ }
11924
+ function findAbandonedInterrupt(abandoned) {
11925
+ return abandoned == null ? void 0 : abandoned.find(
11926
+ (request) => isRecord$2(request) && request.type === "interrupt" && typeof request.id === "string"
11927
+ );
11928
+ }
11929
+ const HITL_REJECT_REASON = "User rejected the action.";
11930
+ function hitlResumeApprove() {
11931
+ return { action: "approve" };
11932
+ }
11933
+ function hitlResumeReject(reason = HITL_REJECT_REASON) {
11934
+ return { action: "reject", reason };
11935
+ }
11936
+ function hitlResumeContinue() {
11937
+ return { action: "continue" };
11938
+ }
11939
+ function useApprovalResumeLock(options) {
11940
+ const { requestId, isRunning, sendResume, pendingResumeGraceMs } = options;
11941
+ const [pending, setPending] = useState(false);
11942
+ const prevRequestIdRef = useRef(requestId);
11943
+ if (prevRequestIdRef.current !== requestId) {
11944
+ prevRequestIdRef.current = requestId;
11945
+ if (pending) setPending(false);
11946
+ }
11947
+ const sawResumeRunRef = useRef(false);
11948
+ useEffect(() => {
11949
+ if (!pending) {
11950
+ sawResumeRunRef.current = false;
11951
+ return;
11952
+ }
11953
+ if (isRunning) {
11954
+ sawResumeRunRef.current = true;
11955
+ return;
11956
+ }
11957
+ if (sawResumeRunRef.current) {
11958
+ sawResumeRunRef.current = false;
11959
+ setPending(false);
11960
+ }
11961
+ }, [pending, isRunning]);
11962
+ useEffect(() => {
11963
+ if (!pending || pendingResumeGraceMs === void 0) return;
11964
+ const timer = setTimeout(() => {
11965
+ if (!sawResumeRunRef.current) setPending(false);
11966
+ }, pendingResumeGraceMs);
11967
+ return () => clearTimeout(timer);
11968
+ }, [pending, requestId, pendingResumeGraceMs]);
11969
+ const sendResumeRef = useRef(sendResume);
11970
+ sendResumeRef.current = sendResume;
11971
+ const pendingRef = useRef(pending);
11972
+ pendingRef.current = pending;
11973
+ const resume = useCallback(
11974
+ (value) => {
11975
+ if (requestId === void 0 || pendingRef.current) return;
11976
+ setPending(true);
11977
+ pendingRef.current = true;
11978
+ sendResumeRef.current(requestId, value);
11979
+ },
11980
+ [requestId]
11981
+ );
11982
+ return { pending, resume };
11983
+ }
11984
+ function queueEntryText(parts) {
11985
+ return parts.flatMap(
11986
+ (part) => part.type === "text" && typeof part.text === "string" ? [part.text] : []
11987
+ ).join("\n\n");
11988
+ }
11989
+ function queueLaneFlags(status) {
11990
+ return {
11991
+ isRunning: status === "running",
11992
+ isContinuable: status === "stopped" || status === "error"
11993
+ };
11994
+ }
11995
+ function buildStatewireQueueRows(options) {
11996
+ const { queue, steerQueue, isContinuable } = options;
11997
+ return [
11998
+ ...isContinuable ? steerQueue.map((item) => ({ item, lane: "steer" })) : [],
11999
+ ...queue.map((item) => ({ item, lane: "queue" }))
12000
+ ];
12001
+ }
12002
+ function showQueueRowSendNow(options) {
12003
+ const { lane, index: index2, isRunning, isContinuable } = options;
12004
+ return lane === "queue" && (isContinuable || isRunning && index2 === 0);
12005
+ }
12006
+ function hasStatewireThreadExtras(extras) {
12007
+ if (!extras || typeof extras !== "object") return false;
12008
+ const candidate = extras;
12009
+ return typeof candidate.sendCommand === "function" && Array.isArray(candidate.inputRequests) && typeof candidate.runs === "object" && candidate.runs !== null;
12010
+ }
11573
12011
  const buildOptimisticHumanContent = (parts) => {
11574
12012
  const imageParts = parts.filter(
11575
12013
  (part) => part.type === "image"
@@ -11819,10 +12257,11 @@ function isLangGraphState(value) {
11819
12257
  }
11820
12258
  function convertDeepAgentState(state, { laneProjection = "both" } = {}) {
11821
12259
  var _a3, _b2;
11822
- const status = (_b2 = (_a3 = state == null ? void 0 : state.runs) == null ? void 0 : _a3[0]) == null ? void 0 : _b2.status;
12260
+ const values = readDeepAgentStreamValues(state);
12261
+ const status = (_b2 = (_a3 = values.runs) == null ? void 0 : _a3[0]) == null ? void 0 : _b2.status;
11823
12262
  const isRunning = status === "running";
11824
- const laneTail = status === "stopped" || status === "error" ? [] : laneTailMessages(state, laneProjection);
11825
- const stateMessages = isLangGraphState(state) ? sanitizeLangChainMessages(state.messages) : [];
12263
+ const laneTail = status === "stopped" || status === "error" ? [] : laneTailMessages(values, laneProjection);
12264
+ const stateMessages = isLangGraphState(values) ? sanitizeLangChainMessages(values.messages) : [];
11826
12265
  return {
11827
12266
  messages: messageConverter.toThreadMessages(
11828
12267
  [...withPendingAssistantMessage(stateMessages, isRunning), ...laneTail],
@@ -11840,6 +12279,132 @@ function registerDeepAgentRunConfig(aui, getRunConfig) {
11840
12279
  })
11841
12280
  });
11842
12281
  }
12282
+ const browserGlobals = globalThis;
12283
+ function requireLocalStorage() {
12284
+ const storage = browserGlobals.localStorage;
12285
+ if (!storage) {
12286
+ throw new Error("statewire: QuotaSafeLocalStorageSession requires localStorage");
12287
+ }
12288
+ return storage;
12289
+ }
12290
+ const SESSION_PREFIX = "aui:statewire-session:";
12291
+ const SESSION_LOCK_PREFIX = "aui:statewire-session-lock:";
12292
+ function isStorageQuotaError(error2) {
12293
+ if (typeof DOMException !== "undefined" && error2 instanceof DOMException) {
12294
+ return error2.name === "QuotaExceededError" || error2.name === "NS_ERROR_DOM_QUOTA_REACHED" || error2.code === 22 || error2.code === 1014;
12295
+ }
12296
+ if (error2 instanceof Error) {
12297
+ return /exceeded the quota|quotaexceedederror|ns_error_dom_quota_reached/i.test(error2.message);
12298
+ }
12299
+ return false;
12300
+ }
12301
+ function readEvictionMeta(raw) {
12302
+ if (!raw) return { savedAt: 0, hasPendingCommands: false };
12303
+ try {
12304
+ const parsed = JSON.parse(raw);
12305
+ return {
12306
+ savedAt: typeof (parsed == null ? void 0 : parsed.savedAt) === "number" ? parsed.savedAt : 0,
12307
+ hasPendingCommands: Array.isArray(parsed == null ? void 0 : parsed.commands) && parsed.commands.length > 0
12308
+ };
12309
+ } catch {
12310
+ return { savedAt: 0, hasPendingCommands: false };
12311
+ }
12312
+ }
12313
+ function evictOldestStatewireSessions(currentKey) {
12314
+ const storage = requireLocalStorage();
12315
+ const candidates = [];
12316
+ for (let i = 0; i < storage.length; i++) {
12317
+ const key = storage.key(i);
12318
+ if (!key || !key.startsWith(SESSION_PREFIX) || key === currentKey) continue;
12319
+ candidates.push({ key, ...readEvictionMeta(storage.getItem(key)) });
12320
+ }
12321
+ candidates.sort(
12322
+ (a, b) => Number(a.hasPendingCommands) - Number(b.hasPendingCommands) || a.savedAt - b.savedAt
12323
+ );
12324
+ const evictCount = Math.min(candidates.length, Math.max(1, Math.ceil(candidates.length / 2)));
12325
+ let removed = 0;
12326
+ for (const { key } of candidates.slice(0, evictCount)) {
12327
+ try {
12328
+ storage.removeItem(key);
12329
+ removed++;
12330
+ } catch {
12331
+ }
12332
+ }
12333
+ return removed;
12334
+ }
12335
+ function createQuotaSafeSessionStorage({
12336
+ storageKey,
12337
+ lockName
12338
+ }) {
12339
+ return {
12340
+ load: () => {
12341
+ const raw = requireLocalStorage().getItem(storageKey);
12342
+ if (raw === null) return null;
12343
+ return JSON.parse(raw);
12344
+ },
12345
+ save: (record2) => {
12346
+ const storage = requireLocalStorage();
12347
+ const serialized = JSON.stringify({ ...record2, savedAt: Date.now() });
12348
+ try {
12349
+ storage.setItem(storageKey, serialized);
12350
+ } catch (error2) {
12351
+ if (!isStorageQuotaError(error2)) throw error2;
12352
+ evictOldestStatewireSessions(storageKey);
12353
+ try {
12354
+ storage.setItem(storageKey, serialized);
12355
+ } catch (retryError) {
12356
+ if (!isStorageQuotaError(retryError)) throw retryError;
12357
+ console.warn(
12358
+ "[statewire] session save skipped — localStorage quota exhausted even after evicting old statewire sessions; the lane will not survive a reload",
12359
+ { storageKey }
12360
+ );
12361
+ }
12362
+ }
12363
+ },
12364
+ // localStorage is shared across tabs: record mutations serialize through a
12365
+ // per-key Web Lock, and `subscribe` mirrors other sharers' saves. In
12366
+ // browsers `globalThis` IS `window`, so the storage events land here.
12367
+ lock: (fn) => {
12368
+ var _a3;
12369
+ const locks = (_a3 = browserGlobals.navigator) == null ? void 0 : _a3.locks;
12370
+ if (!locks) {
12371
+ throw new Error(
12372
+ "statewire: QuotaSafeLocalStorageSession requires the Web Locks API (navigator.locks)"
12373
+ );
12374
+ }
12375
+ return locks.request(lockName, async () => fn());
12376
+ },
12377
+ subscribe: (listener) => {
12378
+ var _a3;
12379
+ const onStorage = (event) => {
12380
+ if (event.key === storageKey) listener();
12381
+ };
12382
+ (_a3 = browserGlobals.addEventListener) == null ? void 0 : _a3.call(browserGlobals, "storage", onStorage);
12383
+ return () => {
12384
+ var _a4;
12385
+ return (_a4 = browserGlobals.removeEventListener) == null ? void 0 : _a4.call(browserGlobals, "storage", onStorage);
12386
+ };
12387
+ }
12388
+ };
12389
+ }
12390
+ const useQuotaSafeLocalStorageSession = ({
12391
+ threadId,
12392
+ key = (id) => id
12393
+ }) => {
12394
+ var _a3;
12395
+ requireLocalStorage();
12396
+ if (((_a3 = browserGlobals.navigator) == null ? void 0 : _a3.locks) === void 0)
12397
+ throw new Error(
12398
+ "statewire: QuotaSafeLocalStorageSession requires the Web Locks API (navigator.locks)"
12399
+ );
12400
+ const storageKey = SESSION_PREFIX + key(threadId);
12401
+ const lockName = SESSION_LOCK_PREFIX + key(threadId);
12402
+ return useMemo(
12403
+ () => createQuotaSafeSessionStorage({ storageKey, lockName }),
12404
+ [storageKey, lockName]
12405
+ );
12406
+ };
12407
+ const QuotaSafeLocalStorageSession = resource(useQuotaSafeLocalStorageSession);
11843
12408
  function useDeepAgentThreadStatus() {
11844
12409
  return useAuiState((s) => {
11845
12410
  var _a3;
@@ -11879,6 +12444,7 @@ function useDeepAgentThread({
11879
12444
  capabilities,
11880
12445
  laneProjection = "both",
11881
12446
  adapters,
12447
+ diagnostics,
11882
12448
  onError,
11883
12449
  onStateChange,
11884
12450
  onCommandChange,
@@ -11909,6 +12475,8 @@ function useDeepAgentThread({
11909
12475
  onRawConnectionChangeRef.current = onRawConnectionChange;
11910
12476
  const headersRef = useRef(headers);
11911
12477
  headersRef.current = headers;
12478
+ const diagnosticsRef = useRef(diagnostics);
12479
+ diagnosticsRef.current = diagnostics;
11912
12480
  const lastRunningRef = useRef(null);
11913
12481
  const lastLegacyRunActiveRef = useRef(null);
11914
12482
  const appliedStateRunConfigThreadRef = useRef(null);
@@ -12039,7 +12607,11 @@ function useDeepAgentThread({
12039
12607
  // A never-started chat has no server session yet: the transport
12040
12608
  // makes no network calls until the first command send.
12041
12609
  ...preloadRef.current.preload && { isNew: true },
12042
- headers: (ctx) => headersRef.current(ctx),
12610
+ headers: (ctx) => {
12611
+ var _a3;
12612
+ (_a3 = diagnosticsRef.current) == null ? void 0 : _a3.observeAuthResolve(ctx);
12613
+ return headersRef.current(ctx);
12614
+ },
12043
12615
  ...sessionStore && { sessionStore }
12044
12616
  },
12045
12617
  { sse }
@@ -12054,7 +12626,8 @@ function useDeepAgentThread({
12054
12626
  // former `runs: true` opt-in is gone) — the converter only maps app-owned
12055
12627
  // keys, including the `run/stop` runId stamp the lib projects itself.
12056
12628
  converter: (state, meta) => {
12057
- var _a3, _b2, _c2, _d2;
12629
+ var _a3, _b2, _c2, _d2, _e2;
12630
+ (_a3 = diagnosticsRef.current) == null ? void 0 : _a3.observeConnection(meta.connection);
12058
12631
  if (authDenialRef.current.attachId !== attachIdRef.current) {
12059
12632
  authDenialRef.current = {
12060
12633
  attachId: attachIdRef.current,
@@ -12073,7 +12646,7 @@ function useDeepAgentThread({
12073
12646
  );
12074
12647
  });
12075
12648
  }
12076
- 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)) {
12649
+ 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)) {
12077
12650
  awaitingFirstSendRef.current = {
12078
12651
  threadId: awaitingFirstSendRef.current.threadId,
12079
12652
  awaiting: false
@@ -12092,7 +12665,7 @@ function useDeepAgentThread({
12092
12665
  (_a4 = onConnectionChangeRef.current) == null ? void 0 : _a4.call(onConnectionChangeRef, connection);
12093
12666
  });
12094
12667
  }
12095
- return converter(state, ((_d2 = (_c2 = state == null ? void 0 : state.runs) == null ? void 0 : _c2[0]) == null ? void 0 : _d2.status) === "running");
12668
+ return converter(state, ((_e2 = (_d2 = state == null ? void 0 : state.runs) == null ? void 0 : _d2[0]) == null ? void 0 : _e2.status) === "running");
12096
12669
  },
12097
12670
  // Makes the server's dispatch record concrete in state (after the
12098
12671
  // optimistic folds); the lib's post-converter dispatch merge turns off.
@@ -12108,19 +12681,29 @@ function useDeepAgentThread({
12108
12681
  // deliberate user stop.
12109
12682
  stopPayload: () => ({ reason: "user_stop" }),
12110
12683
  onError: (error2) => {
12111
- var _a3;
12112
- return (_a3 = onErrorRef.current) == null ? void 0 : _a3.call(onErrorRef, error2);
12684
+ var _a3, _b2;
12685
+ (_a3 = diagnosticsRef.current) == null ? void 0 : _a3.observeError(error2);
12686
+ (_b2 = onErrorRef.current) == null ? void 0 : _b2.call(onErrorRef, error2);
12113
12687
  },
12114
12688
  ...onStateChange && {
12689
+ // The lib types the observed state `NonNullable`, but the runtime
12690
+ // delivers `undefined` where the wire has no snapshot (pre-attach and
12691
+ // replay boundaries republish it) — normalize so the type is true and
12692
+ // host observers never crash on a field read.
12115
12693
  onStateChange: ((state, ctx) => {
12116
12694
  var _a3;
12117
- return (_a3 = onStateChangeRef.current) == null ? void 0 : _a3.call(onStateChangeRef, state, ctx);
12695
+ return (_a3 = onStateChangeRef.current) == null ? void 0 : _a3.call(
12696
+ onStateChangeRef,
12697
+ readDeepAgentStreamValues(state),
12698
+ ctx
12699
+ );
12118
12700
  })
12119
12701
  },
12120
- ...onCommandChange && {
12702
+ ...(onCommandChange || diagnostics) && {
12121
12703
  onCommandChange: ((update, ctx) => {
12122
- var _a3;
12123
- return (_a3 = onCommandChangeRef.current) == null ? void 0 : _a3.call(onCommandChangeRef, update, ctx);
12704
+ var _a3, _b2;
12705
+ (_a3 = diagnosticsRef.current) == null ? void 0 : _a3.observeCommand(update);
12706
+ (_b2 = onCommandChangeRef.current) == null ? void 0 : _b2.call(onCommandChangeRef, update, ctx);
12124
12707
  })
12125
12708
  },
12126
12709
  ...onRawConnectionChange && {
@@ -12134,6 +12717,66 @@ function useDeepAgentThread({
12134
12717
  }
12135
12718
  });
12136
12719
  }
12720
+ function canPersistDeepAgentSession() {
12721
+ try {
12722
+ const storage = globalThis.localStorage;
12723
+ if (!storage) return false;
12724
+ const probeKey = "__athena_statewire_session_probe__";
12725
+ storage.setItem(probeKey, probeKey);
12726
+ storage.removeItem(probeKey);
12727
+ return true;
12728
+ } catch {
12729
+ return false;
12730
+ }
12731
+ }
12732
+ function logUnhandledStatewireError(surface, error2) {
12733
+ if (isStatewireChannelTeardown(error2)) {
12734
+ console.debug(`[${surface}] statewire channel teardown:`, error2);
12735
+ return;
12736
+ }
12737
+ console.error(`[${surface}] statewire transport error:`, error2);
12738
+ }
12739
+ function useDeepAgentRuntime(options) {
12740
+ const { surface, session = false, useClient, runConfig, onError, ...threadOptions } = options;
12741
+ const [canPersistLocalSession] = useState(canPersistDeepAgentSession);
12742
+ const onErrorRef = useRef(onError);
12743
+ onErrorRef.current = onError;
12744
+ const surfaceRef = useRef(surface);
12745
+ surfaceRef.current = surface;
12746
+ const thread = useDeepAgentThread({
12747
+ ...threadOptions,
12748
+ ...session !== false && session.kind === "local-storage" && canPersistLocalSession && {
12749
+ storage: {
12750
+ session: QuotaSafeLocalStorageSession({
12751
+ threadId: threadOptions.threadId,
12752
+ key: session.key
12753
+ })
12754
+ }
12755
+ },
12756
+ ...session !== false && session.kind === "session-store" && { sessionStore: session.store },
12757
+ onError: (error2) => {
12758
+ const handler = onErrorRef.current;
12759
+ if (handler) {
12760
+ handler(error2);
12761
+ return;
12762
+ }
12763
+ logUnhandledStatewireError(surfaceRef.current, error2);
12764
+ }
12765
+ });
12766
+ const client = useClient(thread);
12767
+ const getRunConfigRef = useRef(runConfig == null ? void 0 : runConfig.get);
12768
+ getRunConfigRef.current = runConfig == null ? void 0 : runConfig.get;
12769
+ const hasRunConfig = runConfig !== void 0;
12770
+ const runConfigKey = runConfig == null ? void 0 : runConfig.key;
12771
+ useEffect(() => {
12772
+ if (!hasRunConfig) return void 0;
12773
+ return registerDeepAgentRunConfig(client, () => {
12774
+ var _a3;
12775
+ return ((_a3 = getRunConfigRef.current) == null ? void 0 : _a3.call(getRunConfigRef)) ?? {};
12776
+ });
12777
+ }, [client, hasRunConfig, runConfigKey]);
12778
+ return client;
12779
+ }
12137
12780
  function isStandardSchema(schema2) {
12138
12781
  return typeof schema2 === "object" && schema2 !== null && "~standard" in schema2 && typeof schema2["~standard"] === "object";
12139
12782
  }
@@ -12236,18 +12879,7 @@ function useAthenaStatewireRuntime(config2) {
12236
12879
  onLegacyReadOnly,
12237
12880
  onRunningChange
12238
12881
  } = config2;
12239
- const tokenRef = useRef(token);
12240
- tokenRef.current = token;
12241
- const getTokenRef = useRef(getToken);
12242
- getTokenRef.current = getToken;
12243
- const apiKeyRef = useRef(apiKey);
12244
- apiKeyRef.current = apiKey;
12245
- const onErrorRef = useRef(onError);
12246
- onErrorRef.current = onError;
12247
12882
  const clientTools = useStatewireClientTools(frontendToolkit);
12248
- const clientToolsRef = useRef(clientTools);
12249
- clientToolsRef.current = clientTools;
12250
- const [canPersistSession] = useState(() => typeof localStorage !== "undefined");
12251
12883
  useEffect(() => {
12252
12884
  if (agent2 && !parseCollabAgentRef(agent2)) {
12253
12885
  athenaDiagnostics.emit("sdk.config.warning", {
@@ -12270,16 +12902,22 @@ function useAthenaStatewireRuntime(config2) {
12270
12902
  { thread_id: threadId, is_new_chat: isNewChat }
12271
12903
  );
12272
12904
  }
12273
- const thread = useDeepAgentThread({
12905
+ const auiTools = useMemo(() => Tools({ toolkit: frontendToolkit }), [frontendToolkit]);
12906
+ const useSdkClient = (thread) => useAui({ thread, tools: auiTools });
12907
+ return useDeepAgentRuntime({
12908
+ surface: "AthenaSDK",
12274
12909
  threadId,
12275
12910
  baseUrl: syncUrl,
12911
+ // Option closures are re-read per render by the core, so credential
12912
+ // rotation (new `token`/`getToken`/`apiKey` props) reaches the next
12913
+ // request without remounting the thread.
12276
12914
  headers: async () => {
12277
- const currentToken = getTokenRef.current ? await getTokenRef.current() ?? tokenRef.current : tokenRef.current;
12915
+ const currentToken = getToken ? await getToken() ?? token : token;
12278
12916
  if (currentToken) {
12279
12917
  return { Authorization: `Bearer ${currentToken}` };
12280
12918
  }
12281
- if (apiKeyRef.current) {
12282
- return { "X-API-KEY": apiKeyRef.current };
12919
+ if (apiKey) {
12920
+ return { "X-API-KEY": apiKey };
12283
12921
  }
12284
12922
  return {};
12285
12923
  },
@@ -12289,16 +12927,12 @@ function useAthenaStatewireRuntime(config2) {
12289
12927
  laneProjection: "steer-only",
12290
12928
  // Durable session: a reload resumes the lane and resends whatever the
12291
12929
  // server has not marked durable. Scoped by host — a thread id is only
12292
- // meaningful against the backend that minted it.
12293
- ...canPersistSession && {
12294
- storage: {
12295
- session: LocalStorageSession({
12296
- threadId,
12297
- key: (id) => `${syncUrl}:${id}`
12298
- })
12299
- }
12300
- },
12930
+ // meaningful against the backend that minted it. (Consumers server-render
12931
+ // this SDK; the core's availability probe keeps those sessions
12932
+ // process-local, as before the seam existed.)
12933
+ session: { kind: "local-storage", key: (id) => `${syncUrl}:${id}` },
12301
12934
  capabilities: { edit: true, reload: true, continue: true },
12935
+ useClient: useSdkClient,
12302
12936
  onStateChange: () => {
12303
12937
  const endSpan = attachSpanRef.current;
12304
12938
  if (endSpan) {
@@ -12327,6 +12961,26 @@ function useAthenaStatewireRuntime(config2) {
12327
12961
  onLegacyReadOnly == null ? void 0 : onLegacyReadOnly(legacyReadOnly);
12328
12962
  },
12329
12963
  onRunningChange,
12964
+ // The runConfig getter is pulled at command-send time through the core's
12965
+ // per-render ref, so it reads the latest props — consumers commonly pass
12966
+ // fresh array literals per render, which must not thrash the registration
12967
+ // (no `key`: the provider registers once per client).
12968
+ runConfig: {
12969
+ get: () => buildStatewireRunConfig({
12970
+ model,
12971
+ agent: agent2,
12972
+ channel,
12973
+ tools,
12974
+ frontendToolIds,
12975
+ workbench,
12976
+ knowledgeBase,
12977
+ systemPrompt,
12978
+ customToolConfigs,
12979
+ appId,
12980
+ extraRunConfig,
12981
+ clientTools: statewireClientToolWireEntries(clientTools)
12982
+ })
12983
+ },
12330
12984
  onError: (error2) => {
12331
12985
  if (!isStatewireChannelTeardown(error2)) {
12332
12986
  athenaDiagnostics.error(
@@ -12340,60 +12994,17 @@ function useAthenaStatewireRuntime(config2) {
12340
12994
  { thread_id: threadId }
12341
12995
  );
12342
12996
  }
12343
- if (onErrorRef.current) {
12344
- onErrorRef.current(error2);
12345
- return;
12346
- }
12347
- if (isStatewireChannelTeardown(error2)) {
12348
- console.debug("[AthenaSDK] statewire channel teardown:", error2);
12997
+ if (onError) {
12998
+ onError(error2);
12349
12999
  return;
12350
13000
  }
12351
- console.error("[AthenaSDK] statewire transport error:", error2);
13001
+ logUnhandledStatewireError("AthenaSDK", error2);
12352
13002
  }
12353
13003
  });
12354
- const auiTools = useMemo(() => Tools({ toolkit: frontendToolkit }), [frontendToolkit]);
12355
- const aui = useAui({ thread, tools: auiTools });
12356
- const runConfigInputsRef = useRef({
12357
- model,
12358
- agent: agent2,
12359
- channel,
12360
- tools,
12361
- frontendToolIds,
12362
- workbench,
12363
- knowledgeBase,
12364
- systemPrompt,
12365
- customToolConfigs,
12366
- appId,
12367
- extraRunConfig
12368
- });
12369
- runConfigInputsRef.current = {
12370
- model,
12371
- agent: agent2,
12372
- channel,
12373
- tools,
12374
- frontendToolIds,
12375
- workbench,
12376
- knowledgeBase,
12377
- systemPrompt,
12378
- customToolConfigs,
12379
- appId,
12380
- extraRunConfig
12381
- };
12382
- useEffect(
12383
- () => registerDeepAgentRunConfig(
12384
- aui,
12385
- () => buildStatewireRunConfig({
12386
- ...runConfigInputsRef.current,
12387
- clientTools: statewireClientToolWireEntries(clientToolsRef.current)
12388
- })
12389
- ),
12390
- [aui]
12391
- );
12392
- return aui;
12393
13004
  }
12394
13005
  function readDetailMessage(detail) {
12395
13006
  if (typeof detail === "string" && detail.length > 0) return detail;
12396
- if (!isRecord$2(detail)) return null;
13007
+ if (!isRecord$3(detail)) return null;
12397
13008
  const message = detail.message;
12398
13009
  return typeof message === "string" && message.length > 0 ? message : null;
12399
13010
  }
@@ -12427,99 +13038,32 @@ function useAthenaStatewireLifecycle() {
12427
13038
  return useContext(AthenaStatewireLifecycleContext);
12428
13039
  }
12429
13040
  const clientToolRequests = createClientToolRequestTracker();
12430
- function requestKey(threadId, requestId) {
12431
- return `${threadId}:${requestId}`;
12432
- }
12433
- function jsonSafeResult(value) {
12434
- const serialized = JSON.stringify(value);
12435
- return serialized === void 0 ? null : JSON.parse(serialized);
12436
- }
12437
- function isPendingClientToolRequest(request) {
12438
- if (request.type !== "interrupt" || "response" in request) return false;
12439
- return isClientToolInterrupt(request.payload);
12440
- }
12441
13041
  function StatewireClientToolBridge({
12442
13042
  tools,
12443
13043
  threadId
12444
13044
  }) {
12445
13045
  const sendCommand = useStatewireSendCommand();
12446
13046
  const inputRequests = useStatewireRuns().inputRequests;
12447
- const toolsRef = useRef(tools);
12448
- toolsRef.current = tools;
12449
- const pendingRequest = inputRequests == null ? void 0 : inputRequests.find(isPendingClientToolRequest);
12450
- const ownedClaimsRef = useRef(/* @__PURE__ */ new Set());
12451
- const activeRef = useRef(true);
12452
- const releaseClaim = useCallback((claim) => {
12453
- ownedClaimsRef.current.delete(claim);
12454
- clientToolRequests.release(claim);
12455
- }, []);
12456
- useEffect(() => {
12457
- activeRef.current = true;
12458
- return () => {
12459
- activeRef.current = false;
12460
- for (const claim of ownedClaimsRef.current) clientToolRequests.release(claim);
12461
- ownedClaimsRef.current.clear();
12462
- };
12463
- }, []);
12464
- const liveRequestIdsRef = useRef(/* @__PURE__ */ new Set());
12465
- liveRequestIdsRef.current = new Set((inputRequests ?? []).map((request) => request.id));
12466
- const executeRequest = useCallback(
12467
- async (request) => {
12468
- const payload = request.payload;
12469
- if (!isClientToolInterrupt(payload)) return;
12470
- const calls = payload.context.requests;
12471
- const registry2 = new Map(toolsRef.current.map((tool) => [tool.name, tool]));
12472
- const results = {};
12473
- for (const call of calls) {
12474
- if (!activeRef.current || !liveRequestIdsRef.current.has(request.id)) {
12475
- releaseClaim(requestKey(threadId, request.id));
12476
- return;
12477
- }
12478
- const tool = registry2.get(call.tool_name);
12479
- if (!tool) {
12480
- results[call.interrupt_id] = clientToolErrorEnvelope(
12481
- `This surface has no tool named '${call.tool_name}'.`
12482
- );
12483
- continue;
12484
- }
12485
- try {
12486
- results[call.interrupt_id] = clientToolSuccessEnvelope(
12487
- jsonSafeResult(
12488
- await tool.handler(clientToolCallArgs(call), {
12489
- toolCallId: call.interrupt_id
12490
- })
12491
- )
12492
- );
12493
- } catch (error2) {
12494
- results[call.interrupt_id] = clientToolErrorEnvelope(error2);
12495
- }
12496
- }
12497
- if (!activeRef.current || !liveRequestIdsRef.current.has(request.id)) {
12498
- releaseClaim(requestKey(threadId, request.id));
12499
- return;
12500
- }
12501
- try {
12502
- const wireValue = clientToolResultsResumeValue(results);
12503
- sendCommand({
12504
- type: "run/input",
12505
- requestId: request.id,
12506
- response: { type: "resume", value: wireValue }
12507
- });
12508
- ownedClaimsRef.current.delete(requestKey(threadId, request.id));
12509
- } catch (error2) {
12510
- releaseClaim(requestKey(threadId, request.id));
12511
- console.error("[AthenaSDK] failed to resume client tool results:", error2);
12512
- }
12513
- },
12514
- [releaseClaim, sendCommand, threadId]
13047
+ const bridgeTools = useMemo(
13048
+ () => tools.map((tool) => ({
13049
+ name: tool.name,
13050
+ run: (args, context) => tool.handler(args, context)
13051
+ })),
13052
+ [tools]
12515
13053
  );
12516
- useEffect(() => {
12517
- if (!pendingRequest) return;
12518
- const claim = requestKey(threadId, pendingRequest.id);
12519
- if (!clientToolRequests.claim(claim)) return;
12520
- ownedClaimsRef.current.add(claim);
12521
- void executeRequest(pendingRequest);
12522
- }, [executeRequest, pendingRequest, threadId]);
13054
+ useStatewireClientToolBridge({
13055
+ threadId,
13056
+ tools: bridgeTools,
13057
+ tracker: clientToolRequests,
13058
+ inputRequests,
13059
+ sendResume: (requestId, value) => {
13060
+ sendCommand({
13061
+ type: "run/input",
13062
+ requestId,
13063
+ response: { type: "resume", value }
13064
+ });
13065
+ }
13066
+ });
12523
13067
  return null;
12524
13068
  }
12525
13069
  const ATHENA_TRANSPORTS = {
@@ -20374,7 +20918,7 @@ const useAthenaConfigValue = ({
20374
20918
  apiKey,
20375
20919
  token,
20376
20920
  enabledToolkits,
20377
- transport = "legacy",
20921
+ transport,
20378
20922
  linkClicks,
20379
20923
  citationLinks
20380
20924
  }) => {
@@ -20449,6 +20993,7 @@ function AthenaStandalone({
20449
20993
  apiKey,
20450
20994
  token,
20451
20995
  enabledToolkits: tools,
20996
+ transport: "legacy",
20452
20997
  linkClicks,
20453
20998
  citationLinks
20454
20999
  });
@@ -20754,6 +21299,7 @@ function AthenaWithThreadList({
20754
21299
  apiKey,
20755
21300
  token,
20756
21301
  enabledToolkits: tools,
21302
+ transport: "legacy",
20757
21303
  linkClicks,
20758
21304
  citationLinks
20759
21305
  });
@@ -38355,24 +38901,24 @@ const NodeViewWrapper = React__default.forwardRef((props, ref) => {
38355
38901
  } })
38356
38902
  );
38357
38903
  });
38358
- function isClassComponent(Component) {
38359
- return !!(typeof Component === "function" && Component.prototype && Component.prototype.isReactComponent);
38904
+ function isClassComponent(Component2) {
38905
+ return !!(typeof Component2 === "function" && Component2.prototype && Component2.prototype.isReactComponent);
38360
38906
  }
38361
- function isForwardRefComponent(Component) {
38362
- return !!(typeof Component === "object" && Component.$$typeof && (Component.$$typeof.toString() === "Symbol(react.forward_ref)" || Component.$$typeof.description === "react.forward_ref"));
38907
+ function isForwardRefComponent(Component2) {
38908
+ return !!(typeof Component2 === "object" && Component2.$$typeof && (Component2.$$typeof.toString() === "Symbol(react.forward_ref)" || Component2.$$typeof.description === "react.forward_ref"));
38363
38909
  }
38364
- function isMemoComponent(Component) {
38365
- return !!(typeof Component === "object" && Component.$$typeof && (Component.$$typeof.toString() === "Symbol(react.memo)" || Component.$$typeof.description === "react.memo"));
38910
+ function isMemoComponent(Component2) {
38911
+ return !!(typeof Component2 === "object" && Component2.$$typeof && (Component2.$$typeof.toString() === "Symbol(react.memo)" || Component2.$$typeof.description === "react.memo"));
38366
38912
  }
38367
- function canReceiveRef(Component) {
38368
- if (isClassComponent(Component)) {
38913
+ function canReceiveRef(Component2) {
38914
+ if (isClassComponent(Component2)) {
38369
38915
  return true;
38370
38916
  }
38371
- if (isForwardRefComponent(Component)) {
38917
+ if (isForwardRefComponent(Component2)) {
38372
38918
  return true;
38373
38919
  }
38374
- if (isMemoComponent(Component)) {
38375
- const wrappedComponent = Component.type;
38920
+ if (isMemoComponent(Component2)) {
38921
+ const wrappedComponent = Component2.type;
38376
38922
  if (wrappedComponent) {
38377
38923
  return isClassComponent(wrappedComponent) || isForwardRefComponent(wrappedComponent);
38378
38924
  }
@@ -38419,11 +38965,11 @@ class ReactRenderer {
38419
38965
  */
38420
38966
  render() {
38421
38967
  var _a3;
38422
- const Component = this.component;
38968
+ const Component2 = this.component;
38423
38969
  const props = this.props;
38424
38970
  const editor = this.editor;
38425
38971
  const isReact19 = isReact19Plus();
38426
- const componentCanReceiveRef = canReceiveRef(Component);
38972
+ const componentCanReceiveRef = canReceiveRef(Component2);
38427
38973
  const elementProps = { ...props };
38428
38974
  if (elementProps.ref && !(isReact19 || componentCanReceiveRef)) {
38429
38975
  delete elementProps.ref;
@@ -38433,7 +38979,7 @@ class ReactRenderer {
38433
38979
  this.ref = ref;
38434
38980
  };
38435
38981
  }
38436
- this.reactElement = React__default.createElement(Component, { ...elementProps });
38982
+ this.reactElement = React__default.createElement(Component2, { ...elementProps });
38437
38983
  (_a3 = editor === null || editor === void 0 ? void 0 : editor.contentComponent) === null || _a3 === void 0 ? void 0 : _a3.setRenderer(this.id, this);
38438
38984
  }
38439
38985
  /**
@@ -38517,9 +39063,9 @@ class ReactNodeView extends NodeView {
38517
39063
  }
38518
39064
  };
38519
39065
  const context = { onDragStart, nodeViewContentRef };
38520
- const Component = this.component;
39066
+ const Component2 = this.component;
38521
39067
  const ReactNodeViewProvider = memo((componentProps) => {
38522
- return React__default.createElement(ReactNodeViewContext.Provider, { value: context }, createElement(Component, componentProps));
39068
+ return React__default.createElement(ReactNodeViewContext.Provider, { value: context }, createElement(Component2, componentProps));
38523
39069
  });
38524
39070
  ReactNodeViewProvider.displayName = "ReactNodeView";
38525
39071
  let as = this.node.isInline ? "span" : "div";
@@ -51586,7 +52132,7 @@ const Icon = forwardRef(
51586
52132
  * See the LICENSE file in the root directory of this source tree.
51587
52133
  */
51588
52134
  const createLucideIcon = (iconName, iconNode) => {
51589
- const Component = forwardRef(
52135
+ const Component2 = forwardRef(
51590
52136
  ({ className, ...props }, ref) => createElement(Icon, {
51591
52137
  ref,
51592
52138
  iconNode,
@@ -51598,8 +52144,8 @@ const createLucideIcon = (iconName, iconNode) => {
51598
52144
  ...props
51599
52145
  })
51600
52146
  );
51601
- Component.displayName = toPascalCase(iconName);
51602
- return Component;
52147
+ Component2.displayName = toPascalCase(iconName);
52148
+ return Component2;
51603
52149
  };
51604
52150
  /**
51605
52151
  * @license lucide-react v0.575.0 - ISC
@@ -52780,7 +53326,7 @@ const DEFAULT_PILL_STYLE = "border-gray-300 bg-gray-50 text-gray-800 dark:border
52780
53326
  function MentionNodeView({ node }) {
52781
53327
  const { type, name, params } = node.attrs;
52782
53328
  const config2 = getMentionConfig(type);
52783
- const icon = isRecord$2(params) && typeof params.icon === "string" ? params.icon : (config2 == null ? void 0 : config2.style.icon) ?? "📎";
53329
+ const icon = isRecord$3(params) && typeof params.icon === "string" ? params.icon : (config2 == null ? void 0 : config2.style.icon) ?? "📎";
52784
53330
  const pillStyle = PILL_STYLES[type] ?? DEFAULT_PILL_STYLE;
52785
53331
  return /* @__PURE__ */ jsx(NodeViewWrapper, { as: "span", children: /* @__PURE__ */ jsxs(
52786
53332
  "span",
@@ -56232,102 +56778,103 @@ function Button({
56232
56778
  }
56233
56779
  );
56234
56780
  }
56235
- function hasStatewireThreadExtras(extras) {
56236
- if (!isRecord$2(extras)) return false;
56237
- return typeof extras.sendCommand === "function" && Array.isArray(extras.inputRequests) && isRecord$2(extras.runs);
56238
- }
56239
- function isPendingInterrupt(request) {
56240
- return request.type === "interrupt" && !("response" in request);
56241
- }
56242
- function isApprovalCardInterrupt(request) {
56243
- if (!isPendingInterrupt(request)) return false;
56244
- return !hasClientToolInterruptSource(request.payload);
56245
- }
56246
- function asHitlApproval(value) {
56247
- if (!isRecord$2(value)) return null;
56248
- return value.type === "hitl" && value.source === "hitl_approval" && typeof value.message === "string" ? value : null;
56249
- }
56250
- function readInterruptMessage(value) {
56251
- if (isRecord$2(value) && typeof value.message === "string" && value.message.length > 0) {
56252
- return value.message;
56781
+ class AthenaChatErrorBoundary extends Component {
56782
+ constructor(props) {
56783
+ super(props);
56784
+ __publicField(this, "handleRetry", () => {
56785
+ this.setState((prev) => ({ error: null, retrySeq: prev.retrySeq + 1 }));
56786
+ });
56787
+ this.state = { error: null, retrySeq: 0 };
56788
+ }
56789
+ static getDerivedStateFromError(error2) {
56790
+ return { error: error2 };
56791
+ }
56792
+ componentDidCatch(error2, errorInfo) {
56793
+ var _a3;
56794
+ athenaDiagnostics.error(
56795
+ "sdk.error",
56796
+ error2,
56797
+ {
56798
+ code: "chat_render_crash",
56799
+ message: "The chat surface crashed while rendering",
56800
+ hint: "Inspect component_stack — a custom tool UI or message component is the usual culprit."
56801
+ },
56802
+ { component_stack: ((_a3 = errorInfo.componentStack) == null ? void 0 : _a3.slice(0, 2e3)) ?? null }
56803
+ );
56804
+ }
56805
+ render() {
56806
+ if (this.state.error !== null) {
56807
+ return /* @__PURE__ */ jsxs("div", { className: "flex h-full min-h-48 flex-col items-center justify-center gap-3 p-6 text-center", children: [
56808
+ /* @__PURE__ */ jsx(CircleAlert, { className: "size-6 text-destructive" }),
56809
+ /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
56810
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-foreground", children: "The chat hit an error" }),
56811
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: "Your conversation is safe on the server — reload the chat to continue." })
56812
+ ] }),
56813
+ /* @__PURE__ */ jsxs(Button, { variant: "outline", size: "sm", onClick: this.handleRetry, children: [
56814
+ /* @__PURE__ */ jsx(RefreshCw, { className: "mr-1.5 size-3.5" }),
56815
+ "Reload chat"
56816
+ ] })
56817
+ ] });
56818
+ }
56819
+ return /* @__PURE__ */ jsx(Fragment$2, { children: this.props.children }, this.state.retrySeq);
56253
56820
  }
56254
- return "The agent is paused and waiting for input.";
56255
56821
  }
56256
56822
  const PENDING_RESUME_GRACE_MS = 15e3;
56257
- const StatewireApprovalCard = () => {
56823
+ const StatewireApprovalCard = (props) => {
56258
56824
  const extras = useAuiState$1((s) => s.thread.extras);
56259
56825
  if (!hasStatewireThreadExtras(extras)) return null;
56260
- return /* @__PURE__ */ jsx(StatewireApprovalCardInner, {});
56826
+ return /* @__PURE__ */ jsx(StatewireApprovalCardInner, { ...props });
56261
56827
  };
56262
- const StatewireApprovalCardInner = () => {
56828
+ const StatewireApprovalCardInner = ({
56829
+ classNames,
56830
+ fallbackMessage,
56831
+ interruptPredicate = isApprovalCardInterrupt
56832
+ }) => {
56263
56833
  var _a3, _b2, _c2, _d2, _e2;
56264
56834
  const sendCommand = useStatewireSendCommand();
56265
- const request = (_a3 = useStatewireRuns().inputRequests) == null ? void 0 : _a3.find(isApprovalCardInterrupt);
56835
+ const request = (_a3 = useStatewireRuns().inputRequests) == null ? void 0 : _a3.find(interruptPredicate);
56266
56836
  const requestId = request == null ? void 0 : request.id;
56267
- const abandoned = useStatewireState(
56268
- (s) => s.abandonedInputRequests
56269
- );
56270
- const abandonedInterrupt = abandoned == null ? void 0 : abandoned.find((r2) => r2.type === "interrupt");
56837
+ const abandoned = useStatewireState(readAbandonedInputRequests);
56838
+ const abandonedInterrupt = findAbandonedInterrupt(abandoned);
56271
56839
  const [dismissedId, setDismissedId] = useState();
56272
- const [pending, setPending] = useState(false);
56273
- const prevRequestIdRef = useRef(requestId);
56274
- if (prevRequestIdRef.current !== requestId) {
56275
- prevRequestIdRef.current = requestId;
56276
- if (pending) setPending(false);
56277
- }
56278
56840
  const isRunning = useAuiState$1((s) => s.thread.isRunning);
56279
- const sawResumeRunRef = useRef(false);
56280
- useEffect(() => {
56281
- if (!pending) {
56282
- sawResumeRunRef.current = false;
56283
- return;
56284
- }
56285
- if (isRunning) {
56286
- sawResumeRunRef.current = true;
56287
- return;
56288
- }
56289
- if (sawResumeRunRef.current) {
56290
- sawResumeRunRef.current = false;
56291
- setPending(false);
56292
- }
56293
- }, [pending, isRunning]);
56294
- useEffect(() => {
56295
- if (!pending) return;
56296
- const timer = setTimeout(() => {
56297
- if (!sawResumeRunRef.current) setPending(false);
56298
- }, PENDING_RESUME_GRACE_MS);
56299
- return () => clearTimeout(timer);
56300
- }, [pending, requestId]);
56301
- const resume = useCallback(
56302
- (value) => {
56303
- if (requestId === void 0) return;
56304
- setPending(true);
56305
- sendCommand({
56306
- type: "run/input",
56307
- requestId,
56308
- response: { type: "resume", value }
56309
- });
56310
- },
56311
- [sendCommand, requestId]
56312
- );
56841
+ const { pending, resume } = useApprovalResumeLock({
56842
+ requestId,
56843
+ isRunning,
56844
+ pendingResumeGraceMs: PENDING_RESUME_GRACE_MS,
56845
+ sendResume: (id, value) => sendCommand({
56846
+ type: "run/input",
56847
+ requestId: id,
56848
+ response: { type: "resume", value }
56849
+ })
56850
+ });
56313
56851
  if (!request) {
56314
56852
  if (!abandonedInterrupt || abandonedInterrupt.id === dismissedId) return null;
56315
- return /* @__PURE__ */ 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: [
56316
- /* @__PURE__ */ jsx("p", { children: "Approval was cancelled — the run moved on." }),
56317
- /* @__PURE__ */ jsx(
56318
- "button",
56319
- {
56320
- type: "button",
56321
- "aria-label": "Dismiss cancelled approval",
56322
- onClick: () => setDismissedId(abandonedInterrupt.id),
56323
- className: "shrink-0 rounded-md p-1 hover:bg-amber-100",
56324
- children: /* @__PURE__ */ jsx(X, { className: "size-3.5" })
56325
- }
56326
- )
56327
- ] });
56853
+ return /* @__PURE__ */ jsxs(
56854
+ "div",
56855
+ {
56856
+ className: cn(
56857
+ "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",
56858
+ classNames == null ? void 0 : classNames.abandoned
56859
+ ),
56860
+ children: [
56861
+ /* @__PURE__ */ jsx("p", { children: "Approval was cancelled — the run moved on." }),
56862
+ /* @__PURE__ */ jsx(
56863
+ "button",
56864
+ {
56865
+ type: "button",
56866
+ "aria-label": "Dismiss cancelled approval",
56867
+ onClick: () => setDismissedId(abandonedInterrupt.id),
56868
+ className: "shrink-0 rounded-md p-1 hover:bg-amber-100",
56869
+ children: /* @__PURE__ */ jsx(X, { className: "size-3.5" })
56870
+ }
56871
+ )
56872
+ ]
56873
+ }
56874
+ );
56328
56875
  }
56329
56876
  const hitl = asHitlApproval(request.payload);
56330
- const message = readInterruptMessage(request.payload);
56877
+ const message = readInterruptMessage(request.payload, fallbackMessage);
56331
56878
  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);
56332
56879
  const toolArgs = (_d2 = hitl == null ? void 0 : hitl.context) == null ? void 0 : _d2.tool_args;
56333
56880
  const pendingCount = ((_e2 = hitl == null ? void 0 : hitl.context) == null ? void 0 : _e2.pending_action_count) ?? 1;
@@ -56335,7 +56882,10 @@ const StatewireApprovalCardInner = () => {
56335
56882
  "section",
56336
56883
  {
56337
56884
  "aria-label": hitl ? "Approval required" : "Input required",
56338
- className: "aui-approval-card w-full rounded-2xl border border-amber-300 bg-amber-50 px-4 py-3 text-amber-900",
56885
+ className: cn(
56886
+ "aui-approval-card w-full rounded-2xl border border-amber-300 bg-amber-50 px-4 py-3 text-amber-900",
56887
+ classNames == null ? void 0 : classNames.root
56888
+ ),
56339
56889
  children: /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-3", children: [
56340
56890
  /* @__PURE__ */ jsx(TriangleAlert, { className: "mt-0.5 size-4 shrink-0" }),
56341
56891
  /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
@@ -56357,7 +56907,7 @@ const StatewireApprovalCardInner = () => {
56357
56907
  {
56358
56908
  size: "sm",
56359
56909
  disabled: pending,
56360
- onClick: () => resume({ action: "approve" }),
56910
+ onClick: () => resume(hitlResumeApprove()),
56361
56911
  className: "bg-green-600 text-white hover:bg-green-700",
56362
56912
  children: [
56363
56913
  /* @__PURE__ */ jsx(Check, {}),
@@ -56371,31 +56921,18 @@ const StatewireApprovalCardInner = () => {
56371
56921
  size: "sm",
56372
56922
  variant: "outline",
56373
56923
  disabled: pending,
56374
- onClick: () => resume({ action: "reject", reason: "User rejected the action." }),
56924
+ onClick: () => resume(hitlResumeReject()),
56375
56925
  children: [
56376
56926
  /* @__PURE__ */ jsx(X, {}),
56377
56927
  "Reject"
56378
56928
  ]
56379
56929
  }
56380
56930
  )
56381
- ] }) : /* @__PURE__ */ jsx(
56382
- Button,
56383
- {
56384
- size: "sm",
56385
- disabled: pending,
56386
- onClick: () => resume({ action: "continue" }),
56387
- children: "Continue"
56388
- }
56389
- ) })
56931
+ ] }) : /* @__PURE__ */ jsx(Button, { size: "sm", disabled: pending, onClick: () => resume(hitlResumeContinue()), children: "Continue" }) })
56390
56932
  ] })
56391
56933
  }
56392
56934
  );
56393
56935
  };
56394
- function queueItemText(parts) {
56395
- return parts.flatMap(
56396
- (part) => part.type === "text" && typeof part.text === "string" ? [part.text] : []
56397
- ).join("\n\n");
56398
- }
56399
56936
  const StatewireQueuedMessages = () => {
56400
56937
  const extras = useAuiState$1((s) => s.thread.extras);
56401
56938
  if (!hasStatewireThreadExtras(extras)) return null;
@@ -56406,12 +56943,8 @@ const StatewireQueuedMessagesInner = () => {
56406
56943
  const status = useDeepAgentThreadStatus();
56407
56944
  const aui = useAui();
56408
56945
  const [expanded, setExpanded] = useState(true);
56409
- const isRunning = status === "running";
56410
- const isContinuable = status === "stopped" || status === "error";
56411
- const rows = [
56412
- ...isContinuable ? steerQueue.map((item) => ({ item, lane: "steer" })) : [],
56413
- ...queue.map((item) => ({ item, lane: "queue" }))
56414
- ];
56946
+ const { isRunning, isContinuable } = queueLaneFlags(status);
56947
+ const rows = buildStatewireQueueRows({ queue, steerQueue, isContinuable });
56415
56948
  if (rows.length === 0) return null;
56416
56949
  const queueHead = queue[0];
56417
56950
  return /* @__PURE__ */ jsxs(
@@ -56459,8 +56992,8 @@ const StatewireQueuedMessagesInner = () => {
56459
56992
  className: "max-h-40 overflow-y-auto",
56460
56993
  "data-testid": "athena-statewire-queue",
56461
56994
  children: rows.map(({ item, lane }, index2) => {
56462
- const text2 = queueItemText(item.parts);
56463
- const showSendNow = lane === "queue" && (isContinuable || isRunning && index2 === 0);
56995
+ const text2 = queueEntryText(item.parts);
56996
+ const showSendNow = showQueueRowSendNow({ lane, index: index2, isRunning, isContinuable });
56464
56997
  return /* @__PURE__ */ jsxs(
56465
56998
  "li",
56466
56999
  {
@@ -58647,8 +59180,8 @@ function StudioPtcToolUI({
58647
59180
  );
58648
59181
  }
58649
59182
  function createStudioPtcToolUI(displayName, config2) {
58650
- const Component = (props) => /* @__PURE__ */ jsx(StudioPtcToolUI, { config: config2, ...props });
58651
- const Memoized = memo(Component);
59183
+ const Component2 = (props) => /* @__PURE__ */ jsx(StudioPtcToolUI, { config: config2, ...props });
59184
+ const Memoized = memo(Component2);
58652
59185
  Memoized.displayName = displayName;
58653
59186
  return Memoized;
58654
59187
  }
@@ -60521,7 +61054,7 @@ const SetRowColumnDimensionsToolUI = memo(
60521
61054
  );
60522
61055
  SetRowColumnDimensionsToolUI.displayName = "SetRowColumnDimensionsToolUI";
60523
61056
  function createAssetToolUI(config2) {
60524
- const Component = (props) => /* @__PURE__ */ jsx(
61057
+ const Component2 = (props) => /* @__PURE__ */ jsx(
60525
61058
  CreateAssetToolUIImpl,
60526
61059
  {
60527
61060
  icon: config2.icon,
@@ -60531,7 +61064,7 @@ function createAssetToolUI(config2) {
60531
61064
  ...props
60532
61065
  }
60533
61066
  );
60534
- const Memoized = memo(Component);
61067
+ const Memoized = memo(Component2);
60535
61068
  Memoized.displayName = `CreateAssetToolUI(${config2.assetType})`;
60536
61069
  return Memoized;
60537
61070
  }
@@ -62031,15 +62564,15 @@ const AthenaDefaultUserMessage = () => {
62031
62564
  return /* @__PURE__ */ jsx(AthenaUserMessage, { TextComponent });
62032
62565
  };
62033
62566
  const getReasoningTokensFromMetadata = (metadata) => {
62034
- if (!isRecord$2(metadata)) {
62567
+ if (!isRecord$3(metadata)) {
62035
62568
  return void 0;
62036
62569
  }
62037
62570
  const customMetadata = metadata.custom;
62038
- if (!isRecord$2(customMetadata)) {
62571
+ if (!isRecord$3(customMetadata)) {
62039
62572
  return void 0;
62040
62573
  }
62041
62574
  const athenaMetadata = customMetadata._athena;
62042
- if (!isRecord$2(athenaMetadata)) {
62575
+ if (!isRecord$3(athenaMetadata)) {
62043
62576
  return void 0;
62044
62577
  }
62045
62578
  const reasoningTokens = athenaMetadata.reasoningTokens;
@@ -62134,7 +62667,7 @@ const AthenaChat = ({
62134
62667
  );
62135
62668
  const AssistantMessageComponent = (components == null ? void 0 : components.AssistantMessage) ?? AthenaDefaultAssistantMessage;
62136
62669
  const UserMessageComponent = (components == null ? void 0 : components.UserMessage) ?? AthenaDefaultUserMessage;
62137
- return /* @__PURE__ */ jsx(AthenaChatDefaultComponentsContext.Provider, { value: defaultComponentsContextValue, children: /* @__PURE__ */ jsxs(
62670
+ return /* @__PURE__ */ jsx(AthenaChatDefaultComponentsContext.Provider, { value: defaultComponentsContextValue, children: /* @__PURE__ */ jsx(AthenaChatErrorBoundary, { children: /* @__PURE__ */ jsxs(
62138
62671
  ThreadPrimitive.Root,
62139
62672
  {
62140
62673
  className: `aui-root aui-thread-root @container flex h-full flex-col bg-background ${className ?? ""}`,
@@ -62185,7 +62718,7 @@ const AthenaChat = ({
62185
62718
  )
62186
62719
  ]
62187
62720
  }
62188
- ) });
62721
+ ) }) });
62189
62722
  };
62190
62723
  const ThreadLoadingOverlay = () => {
62191
62724
  const remoteId = useAthenaThreadId();
@@ -63580,6 +64113,7 @@ export {
63580
64113
  AthenaAssistantActionBar,
63581
64114
  AthenaAssistantMessage,
63582
64115
  AthenaChat,
64116
+ AthenaChatErrorBoundary,
63583
64117
  AthenaLayout,
63584
64118
  AthenaProvider,
63585
64119
  AthenaReasoningPart,