@athenaintel/react 0.12.3 → 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.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.12.4";
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 = {
@@ -38355,24 +38899,24 @@ const NodeViewWrapper = React__default.forwardRef((props, ref) => {
38355
38899
  } })
38356
38900
  );
38357
38901
  });
38358
- function isClassComponent(Component) {
38359
- return !!(typeof Component === "function" && Component.prototype && Component.prototype.isReactComponent);
38902
+ function isClassComponent(Component2) {
38903
+ return !!(typeof Component2 === "function" && Component2.prototype && Component2.prototype.isReactComponent);
38360
38904
  }
38361
- function isForwardRefComponent(Component) {
38362
- return !!(typeof Component === "object" && Component.$$typeof && (Component.$$typeof.toString() === "Symbol(react.forward_ref)" || Component.$$typeof.description === "react.forward_ref"));
38905
+ function isForwardRefComponent(Component2) {
38906
+ return !!(typeof Component2 === "object" && Component2.$$typeof && (Component2.$$typeof.toString() === "Symbol(react.forward_ref)" || Component2.$$typeof.description === "react.forward_ref"));
38363
38907
  }
38364
- function isMemoComponent(Component) {
38365
- return !!(typeof Component === "object" && Component.$$typeof && (Component.$$typeof.toString() === "Symbol(react.memo)" || Component.$$typeof.description === "react.memo"));
38908
+ function isMemoComponent(Component2) {
38909
+ return !!(typeof Component2 === "object" && Component2.$$typeof && (Component2.$$typeof.toString() === "Symbol(react.memo)" || Component2.$$typeof.description === "react.memo"));
38366
38910
  }
38367
- function canReceiveRef(Component) {
38368
- if (isClassComponent(Component)) {
38911
+ function canReceiveRef(Component2) {
38912
+ if (isClassComponent(Component2)) {
38369
38913
  return true;
38370
38914
  }
38371
- if (isForwardRefComponent(Component)) {
38915
+ if (isForwardRefComponent(Component2)) {
38372
38916
  return true;
38373
38917
  }
38374
- if (isMemoComponent(Component)) {
38375
- const wrappedComponent = Component.type;
38918
+ if (isMemoComponent(Component2)) {
38919
+ const wrappedComponent = Component2.type;
38376
38920
  if (wrappedComponent) {
38377
38921
  return isClassComponent(wrappedComponent) || isForwardRefComponent(wrappedComponent);
38378
38922
  }
@@ -38419,11 +38963,11 @@ class ReactRenderer {
38419
38963
  */
38420
38964
  render() {
38421
38965
  var _a3;
38422
- const Component = this.component;
38966
+ const Component2 = this.component;
38423
38967
  const props = this.props;
38424
38968
  const editor = this.editor;
38425
38969
  const isReact19 = isReact19Plus();
38426
- const componentCanReceiveRef = canReceiveRef(Component);
38970
+ const componentCanReceiveRef = canReceiveRef(Component2);
38427
38971
  const elementProps = { ...props };
38428
38972
  if (elementProps.ref && !(isReact19 || componentCanReceiveRef)) {
38429
38973
  delete elementProps.ref;
@@ -38433,7 +38977,7 @@ class ReactRenderer {
38433
38977
  this.ref = ref;
38434
38978
  };
38435
38979
  }
38436
- this.reactElement = React__default.createElement(Component, { ...elementProps });
38980
+ this.reactElement = React__default.createElement(Component2, { ...elementProps });
38437
38981
  (_a3 = editor === null || editor === void 0 ? void 0 : editor.contentComponent) === null || _a3 === void 0 ? void 0 : _a3.setRenderer(this.id, this);
38438
38982
  }
38439
38983
  /**
@@ -38517,9 +39061,9 @@ class ReactNodeView extends NodeView {
38517
39061
  }
38518
39062
  };
38519
39063
  const context = { onDragStart, nodeViewContentRef };
38520
- const Component = this.component;
39064
+ const Component2 = this.component;
38521
39065
  const ReactNodeViewProvider = memo((componentProps) => {
38522
- return React__default.createElement(ReactNodeViewContext.Provider, { value: context }, createElement(Component, componentProps));
39066
+ return React__default.createElement(ReactNodeViewContext.Provider, { value: context }, createElement(Component2, componentProps));
38523
39067
  });
38524
39068
  ReactNodeViewProvider.displayName = "ReactNodeView";
38525
39069
  let as = this.node.isInline ? "span" : "div";
@@ -51586,7 +52130,7 @@ const Icon = forwardRef(
51586
52130
  * See the LICENSE file in the root directory of this source tree.
51587
52131
  */
51588
52132
  const createLucideIcon = (iconName, iconNode) => {
51589
- const Component = forwardRef(
52133
+ const Component2 = forwardRef(
51590
52134
  ({ className, ...props }, ref) => createElement(Icon, {
51591
52135
  ref,
51592
52136
  iconNode,
@@ -51598,8 +52142,8 @@ const createLucideIcon = (iconName, iconNode) => {
51598
52142
  ...props
51599
52143
  })
51600
52144
  );
51601
- Component.displayName = toPascalCase(iconName);
51602
- return Component;
52145
+ Component2.displayName = toPascalCase(iconName);
52146
+ return Component2;
51603
52147
  };
51604
52148
  /**
51605
52149
  * @license lucide-react v0.575.0 - ISC
@@ -52780,7 +53324,7 @@ const DEFAULT_PILL_STYLE = "border-gray-300 bg-gray-50 text-gray-800 dark:border
52780
53324
  function MentionNodeView({ node }) {
52781
53325
  const { type, name, params } = node.attrs;
52782
53326
  const config2 = getMentionConfig(type);
52783
- const icon = isRecord$2(params) && typeof params.icon === "string" ? params.icon : (config2 == null ? void 0 : config2.style.icon) ?? "📎";
53327
+ const icon = isRecord$3(params) && typeof params.icon === "string" ? params.icon : (config2 == null ? void 0 : config2.style.icon) ?? "📎";
52784
53328
  const pillStyle = PILL_STYLES[type] ?? DEFAULT_PILL_STYLE;
52785
53329
  return /* @__PURE__ */ jsx(NodeViewWrapper, { as: "span", children: /* @__PURE__ */ jsxs(
52786
53330
  "span",
@@ -56232,102 +56776,103 @@ function Button({
56232
56776
  }
56233
56777
  );
56234
56778
  }
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;
56779
+ class AthenaChatErrorBoundary extends Component {
56780
+ constructor(props) {
56781
+ super(props);
56782
+ __publicField(this, "handleRetry", () => {
56783
+ this.setState((prev) => ({ error: null, retrySeq: prev.retrySeq + 1 }));
56784
+ });
56785
+ this.state = { error: null, retrySeq: 0 };
56786
+ }
56787
+ static getDerivedStateFromError(error2) {
56788
+ return { error: error2 };
56789
+ }
56790
+ componentDidCatch(error2, errorInfo) {
56791
+ var _a3;
56792
+ athenaDiagnostics.error(
56793
+ "sdk.error",
56794
+ error2,
56795
+ {
56796
+ code: "chat_render_crash",
56797
+ message: "The chat surface crashed while rendering",
56798
+ hint: "Inspect component_stack — a custom tool UI or message component is the usual culprit."
56799
+ },
56800
+ { component_stack: ((_a3 = errorInfo.componentStack) == null ? void 0 : _a3.slice(0, 2e3)) ?? null }
56801
+ );
56802
+ }
56803
+ render() {
56804
+ if (this.state.error !== null) {
56805
+ return /* @__PURE__ */ jsxs("div", { className: "flex h-full min-h-48 flex-col items-center justify-center gap-3 p-6 text-center", children: [
56806
+ /* @__PURE__ */ jsx(CircleAlert, { className: "size-6 text-destructive" }),
56807
+ /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
56808
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-foreground", children: "The chat hit an error" }),
56809
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: "Your conversation is safe on the server — reload the chat to continue." })
56810
+ ] }),
56811
+ /* @__PURE__ */ jsxs(Button, { variant: "outline", size: "sm", onClick: this.handleRetry, children: [
56812
+ /* @__PURE__ */ jsx(RefreshCw, { className: "mr-1.5 size-3.5" }),
56813
+ "Reload chat"
56814
+ ] })
56815
+ ] });
56816
+ }
56817
+ return /* @__PURE__ */ jsx(Fragment$2, { children: this.props.children }, this.state.retrySeq);
56253
56818
  }
56254
- return "The agent is paused and waiting for input.";
56255
56819
  }
56256
56820
  const PENDING_RESUME_GRACE_MS = 15e3;
56257
- const StatewireApprovalCard = () => {
56821
+ const StatewireApprovalCard = (props) => {
56258
56822
  const extras = useAuiState$1((s) => s.thread.extras);
56259
56823
  if (!hasStatewireThreadExtras(extras)) return null;
56260
- return /* @__PURE__ */ jsx(StatewireApprovalCardInner, {});
56824
+ return /* @__PURE__ */ jsx(StatewireApprovalCardInner, { ...props });
56261
56825
  };
56262
- const StatewireApprovalCardInner = () => {
56826
+ const StatewireApprovalCardInner = ({
56827
+ classNames,
56828
+ fallbackMessage,
56829
+ interruptPredicate = isApprovalCardInterrupt
56830
+ }) => {
56263
56831
  var _a3, _b2, _c2, _d2, _e2;
56264
56832
  const sendCommand = useStatewireSendCommand();
56265
- const request = (_a3 = useStatewireRuns().inputRequests) == null ? void 0 : _a3.find(isApprovalCardInterrupt);
56833
+ const request = (_a3 = useStatewireRuns().inputRequests) == null ? void 0 : _a3.find(interruptPredicate);
56266
56834
  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");
56835
+ const abandoned = useStatewireState(readAbandonedInputRequests);
56836
+ const abandonedInterrupt = findAbandonedInterrupt(abandoned);
56271
56837
  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
56838
  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
- );
56839
+ const { pending, resume } = useApprovalResumeLock({
56840
+ requestId,
56841
+ isRunning,
56842
+ pendingResumeGraceMs: PENDING_RESUME_GRACE_MS,
56843
+ sendResume: (id, value) => sendCommand({
56844
+ type: "run/input",
56845
+ requestId: id,
56846
+ response: { type: "resume", value }
56847
+ })
56848
+ });
56313
56849
  if (!request) {
56314
56850
  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
- ] });
56851
+ return /* @__PURE__ */ jsxs(
56852
+ "div",
56853
+ {
56854
+ className: cn(
56855
+ "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",
56856
+ classNames == null ? void 0 : classNames.abandoned
56857
+ ),
56858
+ children: [
56859
+ /* @__PURE__ */ jsx("p", { children: "Approval was cancelled — the run moved on." }),
56860
+ /* @__PURE__ */ jsx(
56861
+ "button",
56862
+ {
56863
+ type: "button",
56864
+ "aria-label": "Dismiss cancelled approval",
56865
+ onClick: () => setDismissedId(abandonedInterrupt.id),
56866
+ className: "shrink-0 rounded-md p-1 hover:bg-amber-100",
56867
+ children: /* @__PURE__ */ jsx(X, { className: "size-3.5" })
56868
+ }
56869
+ )
56870
+ ]
56871
+ }
56872
+ );
56328
56873
  }
56329
56874
  const hitl = asHitlApproval(request.payload);
56330
- const message = readInterruptMessage(request.payload);
56875
+ const message = readInterruptMessage(request.payload, fallbackMessage);
56331
56876
  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
56877
  const toolArgs = (_d2 = hitl == null ? void 0 : hitl.context) == null ? void 0 : _d2.tool_args;
56333
56878
  const pendingCount = ((_e2 = hitl == null ? void 0 : hitl.context) == null ? void 0 : _e2.pending_action_count) ?? 1;
@@ -56335,7 +56880,10 @@ const StatewireApprovalCardInner = () => {
56335
56880
  "section",
56336
56881
  {
56337
56882
  "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",
56883
+ className: cn(
56884
+ "aui-approval-card w-full rounded-2xl border border-amber-300 bg-amber-50 px-4 py-3 text-amber-900",
56885
+ classNames == null ? void 0 : classNames.root
56886
+ ),
56339
56887
  children: /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-3", children: [
56340
56888
  /* @__PURE__ */ jsx(TriangleAlert, { className: "mt-0.5 size-4 shrink-0" }),
56341
56889
  /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
@@ -56357,7 +56905,7 @@ const StatewireApprovalCardInner = () => {
56357
56905
  {
56358
56906
  size: "sm",
56359
56907
  disabled: pending,
56360
- onClick: () => resume({ action: "approve" }),
56908
+ onClick: () => resume(hitlResumeApprove()),
56361
56909
  className: "bg-green-600 text-white hover:bg-green-700",
56362
56910
  children: [
56363
56911
  /* @__PURE__ */ jsx(Check, {}),
@@ -56371,31 +56919,18 @@ const StatewireApprovalCardInner = () => {
56371
56919
  size: "sm",
56372
56920
  variant: "outline",
56373
56921
  disabled: pending,
56374
- onClick: () => resume({ action: "reject", reason: "User rejected the action." }),
56922
+ onClick: () => resume(hitlResumeReject()),
56375
56923
  children: [
56376
56924
  /* @__PURE__ */ jsx(X, {}),
56377
56925
  "Reject"
56378
56926
  ]
56379
56927
  }
56380
56928
  )
56381
- ] }) : /* @__PURE__ */ jsx(
56382
- Button,
56383
- {
56384
- size: "sm",
56385
- disabled: pending,
56386
- onClick: () => resume({ action: "continue" }),
56387
- children: "Continue"
56388
- }
56389
- ) })
56929
+ ] }) : /* @__PURE__ */ jsx(Button, { size: "sm", disabled: pending, onClick: () => resume(hitlResumeContinue()), children: "Continue" }) })
56390
56930
  ] })
56391
56931
  }
56392
56932
  );
56393
56933
  };
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
56934
  const StatewireQueuedMessages = () => {
56400
56935
  const extras = useAuiState$1((s) => s.thread.extras);
56401
56936
  if (!hasStatewireThreadExtras(extras)) return null;
@@ -56406,12 +56941,8 @@ const StatewireQueuedMessagesInner = () => {
56406
56941
  const status = useDeepAgentThreadStatus();
56407
56942
  const aui = useAui();
56408
56943
  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
- ];
56944
+ const { isRunning, isContinuable } = queueLaneFlags(status);
56945
+ const rows = buildStatewireQueueRows({ queue, steerQueue, isContinuable });
56415
56946
  if (rows.length === 0) return null;
56416
56947
  const queueHead = queue[0];
56417
56948
  return /* @__PURE__ */ jsxs(
@@ -56459,8 +56990,8 @@ const StatewireQueuedMessagesInner = () => {
56459
56990
  className: "max-h-40 overflow-y-auto",
56460
56991
  "data-testid": "athena-statewire-queue",
56461
56992
  children: rows.map(({ item, lane }, index2) => {
56462
- const text2 = queueItemText(item.parts);
56463
- const showSendNow = lane === "queue" && (isContinuable || isRunning && index2 === 0);
56993
+ const text2 = queueEntryText(item.parts);
56994
+ const showSendNow = showQueueRowSendNow({ lane, index: index2, isRunning, isContinuable });
56464
56995
  return /* @__PURE__ */ jsxs(
56465
56996
  "li",
56466
56997
  {
@@ -58647,8 +59178,8 @@ function StudioPtcToolUI({
58647
59178
  );
58648
59179
  }
58649
59180
  function createStudioPtcToolUI(displayName, config2) {
58650
- const Component = (props) => /* @__PURE__ */ jsx(StudioPtcToolUI, { config: config2, ...props });
58651
- const Memoized = memo(Component);
59181
+ const Component2 = (props) => /* @__PURE__ */ jsx(StudioPtcToolUI, { config: config2, ...props });
59182
+ const Memoized = memo(Component2);
58652
59183
  Memoized.displayName = displayName;
58653
59184
  return Memoized;
58654
59185
  }
@@ -60521,7 +61052,7 @@ const SetRowColumnDimensionsToolUI = memo(
60521
61052
  );
60522
61053
  SetRowColumnDimensionsToolUI.displayName = "SetRowColumnDimensionsToolUI";
60523
61054
  function createAssetToolUI(config2) {
60524
- const Component = (props) => /* @__PURE__ */ jsx(
61055
+ const Component2 = (props) => /* @__PURE__ */ jsx(
60525
61056
  CreateAssetToolUIImpl,
60526
61057
  {
60527
61058
  icon: config2.icon,
@@ -60531,7 +61062,7 @@ function createAssetToolUI(config2) {
60531
61062
  ...props
60532
61063
  }
60533
61064
  );
60534
- const Memoized = memo(Component);
61065
+ const Memoized = memo(Component2);
60535
61066
  Memoized.displayName = `CreateAssetToolUI(${config2.assetType})`;
60536
61067
  return Memoized;
60537
61068
  }
@@ -62031,15 +62562,15 @@ const AthenaDefaultUserMessage = () => {
62031
62562
  return /* @__PURE__ */ jsx(AthenaUserMessage, { TextComponent });
62032
62563
  };
62033
62564
  const getReasoningTokensFromMetadata = (metadata) => {
62034
- if (!isRecord$2(metadata)) {
62565
+ if (!isRecord$3(metadata)) {
62035
62566
  return void 0;
62036
62567
  }
62037
62568
  const customMetadata = metadata.custom;
62038
- if (!isRecord$2(customMetadata)) {
62569
+ if (!isRecord$3(customMetadata)) {
62039
62570
  return void 0;
62040
62571
  }
62041
62572
  const athenaMetadata = customMetadata._athena;
62042
- if (!isRecord$2(athenaMetadata)) {
62573
+ if (!isRecord$3(athenaMetadata)) {
62043
62574
  return void 0;
62044
62575
  }
62045
62576
  const reasoningTokens = athenaMetadata.reasoningTokens;
@@ -62134,7 +62665,7 @@ const AthenaChat = ({
62134
62665
  );
62135
62666
  const AssistantMessageComponent = (components == null ? void 0 : components.AssistantMessage) ?? AthenaDefaultAssistantMessage;
62136
62667
  const UserMessageComponent = (components == null ? void 0 : components.UserMessage) ?? AthenaDefaultUserMessage;
62137
- return /* @__PURE__ */ jsx(AthenaChatDefaultComponentsContext.Provider, { value: defaultComponentsContextValue, children: /* @__PURE__ */ jsxs(
62668
+ return /* @__PURE__ */ jsx(AthenaChatDefaultComponentsContext.Provider, { value: defaultComponentsContextValue, children: /* @__PURE__ */ jsx(AthenaChatErrorBoundary, { children: /* @__PURE__ */ jsxs(
62138
62669
  ThreadPrimitive.Root,
62139
62670
  {
62140
62671
  className: `aui-root aui-thread-root @container flex h-full flex-col bg-background ${className ?? ""}`,
@@ -62185,7 +62716,7 @@ const AthenaChat = ({
62185
62716
  )
62186
62717
  ]
62187
62718
  }
62188
- ) });
62719
+ ) }) });
62189
62720
  };
62190
62721
  const ThreadLoadingOverlay = () => {
62191
62722
  const remoteId = useAthenaThreadId();
@@ -63580,6 +64111,7 @@ export {
63580
64111
  AthenaAssistantActionBar,
63581
64112
  AthenaAssistantMessage,
63582
64113
  AthenaChat,
64114
+ AthenaChatErrorBoundary,
63583
64115
  AthenaLayout,
63584
64116
  AthenaProvider,
63585
64117
  AthenaReasoningPart,