@athenaintel/react 0.6.0 → 0.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -7650,7 +7650,7 @@ const toAppendMessage = (messages, message) => {
7650
7650
  startRun: message.startRun
7651
7651
  };
7652
7652
  };
7653
- const getThreadState = (runtime, threadListItemState) => {
7653
+ const getThreadState$1 = (runtime, threadListItemState) => {
7654
7654
  const lastMessage = runtime.messages.at(-1);
7655
7655
  return Object.freeze({
7656
7656
  threadId: threadListItemState.id,
@@ -7673,7 +7673,7 @@ class ThreadRuntimeImpl {
7673
7673
  __publicField(this, "_eventSubscriptionSubjects", /* @__PURE__ */ new Map());
7674
7674
  const stateBinding = new ShallowMemoizeSubject({
7675
7675
  path: threadBinding.path,
7676
- getState: () => getThreadState(threadBinding.getState(), threadListItemBinding.getState()),
7676
+ getState: () => getThreadState$1(threadBinding.getState(), threadListItemBinding.getState()),
7677
7677
  subscribe: (callback) => {
7678
7678
  const sub1 = threadBinding.subscribe(callback);
7679
7679
  const sub2 = threadListItemBinding.subscribe(callback);
@@ -20637,6 +20637,73 @@ const parseLangGraphState = (state) => {
20637
20637
  }
20638
20638
  return result;
20639
20639
  };
20640
+ function getAuthHeaders(auth) {
20641
+ if (auth.token) {
20642
+ return { Authorization: `Bearer ${auth.token}` };
20643
+ }
20644
+ if (auth.apiKey) {
20645
+ return { "X-API-KEY": auth.apiKey };
20646
+ }
20647
+ return {};
20648
+ }
20649
+ function getAgoraBaseUrl(backendUrl) {
20650
+ const stripped = backendUrl.replace(/\/api\/assistant-ui\/?$/, "");
20651
+ if (stripped === backendUrl) {
20652
+ return backendUrl.replace(/\/$/, "");
20653
+ }
20654
+ return stripped;
20655
+ }
20656
+ async function listThreads(backendUrl, auth, opts = {}) {
20657
+ const base2 = getAgoraBaseUrl(backendUrl);
20658
+ const res = await fetch(`${base2}/api/conversations/threads/list`, {
20659
+ method: "POST",
20660
+ headers: { "Content-Type": "application/json", ...getAuthHeaders(auth) },
20661
+ body: JSON.stringify({ limit: opts.limit ?? 50, offset: opts.offset ?? 0 })
20662
+ });
20663
+ if (!res.ok) {
20664
+ throw new Error(`[AthenaSDK] Failed to list threads: ${res.status}`);
20665
+ }
20666
+ return res.json();
20667
+ }
20668
+ function deserializeMessage(msg) {
20669
+ if (msg && typeof msg === "object" && "lc" in msg && "kwargs" in msg && msg.type === "constructor") {
20670
+ const kwargs = msg.kwargs;
20671
+ const deserializedToolCalls = Array.isArray(kwargs.tool_calls) ? kwargs.tool_calls.map((tc) => {
20672
+ if (tc && typeof tc === "object" && "lc" in tc && "kwargs" in tc) {
20673
+ return tc.kwargs;
20674
+ }
20675
+ return tc;
20676
+ }) : kwargs.tool_calls;
20677
+ return { ...kwargs, tool_calls: deserializedToolCalls };
20678
+ }
20679
+ return msg;
20680
+ }
20681
+ async function getThreadState(backendUrl, auth, threadId) {
20682
+ const base2 = getAgoraBaseUrl(backendUrl);
20683
+ const res = await fetch(`${base2}/api/unstable/threads/${threadId}`, {
20684
+ method: "GET",
20685
+ headers: { ...getAuthHeaders(auth) }
20686
+ });
20687
+ if (!res.ok) {
20688
+ throw new Error(`[AthenaSDK] Failed to get thread state: ${res.status}`);
20689
+ }
20690
+ const data = await res.json();
20691
+ if (Array.isArray(data.messages)) {
20692
+ data.messages = data.messages.map(deserializeMessage);
20693
+ }
20694
+ return data;
20695
+ }
20696
+ async function archiveThread(backendUrl, auth, threadId) {
20697
+ const base2 = getAgoraBaseUrl(backendUrl);
20698
+ const res = await fetch(`${base2}/api/conversations/threads/archive`, {
20699
+ method: "POST",
20700
+ headers: { "Content-Type": "application/json", ...getAuthHeaders(auth) },
20701
+ body: JSON.stringify({ thread_id: threadId })
20702
+ });
20703
+ if (!res.ok) {
20704
+ throw new Error(`[AthenaSDK] Failed to archive thread: ${res.status}`);
20705
+ }
20706
+ }
20640
20707
  const DEFAULT_API_URL = "https://sync.athenaintel.com/api/chat";
20641
20708
  const DEFAULT_BACKEND_URL = "https://api.athenaintel.com/api/assistant-ui";
20642
20709
  const DEFAULT_MODEL = "claude-sonnet-4-6-low";
@@ -20937,15 +21004,33 @@ const useAthenaRuntime = (config2) => {
20937
21004
  }
20938
21005
  });
20939
21006
  const hasResumedRef = React.useRef(false);
21007
+ const prevThreadIdRef = React.useRef(threadId);
21008
+ if (prevThreadIdRef.current !== threadId) {
21009
+ prevThreadIdRef.current = threadId;
21010
+ hasResumedRef.current = false;
21011
+ }
20940
21012
  React.useEffect(() => {
20941
21013
  if (isExistingThread && !hasResumedRef.current) {
20942
21014
  hasResumedRef.current = true;
20943
- try {
20944
- runtime.thread.unstable_resumeRun({ parentId: null });
20945
- } catch {
20946
- }
21015
+ (async () => {
21016
+ try {
21017
+ const auth = { apiKey: apiKeyRef.current, token: tokenRef.current };
21018
+ const state = await getThreadState(backendUrl, auth, threadId);
21019
+ runtime.thread.importExternalState({
21020
+ messages: state.messages
21021
+ });
21022
+ } catch (err) {
21023
+ if (process.env.NODE_ENV !== "production") {
21024
+ console.error("[AthenaSDK] Failed to load thread state:", err);
21025
+ }
21026
+ try {
21027
+ runtime.thread.unstable_resumeRun({ parentId: null });
21028
+ } catch {
21029
+ }
21030
+ }
21031
+ })();
20947
21032
  }
20948
- }, [isExistingThread, runtime]);
21033
+ }, [isExistingThread, runtime, threadId, backendUrl]);
20949
21034
  return runtime;
20950
21035
  };
20951
21036
  function r(e) {
@@ -24179,50 +24264,13 @@ function useAthenaConfig() {
24179
24264
  }
24180
24265
  return ctx;
24181
24266
  }
24182
- function getAuthHeaders(auth) {
24183
- if (auth.token) {
24184
- return { Authorization: `Bearer ${auth.token}` };
24185
- }
24186
- if (auth.apiKey) {
24187
- return { "X-API-KEY": auth.apiKey };
24188
- }
24189
- return {};
24190
- }
24191
- function getAgoraBaseUrl(backendUrl) {
24192
- return backendUrl.replace(/\/api\/assistant-ui\/?$/, "");
24193
- }
24194
- async function listThreads(backendUrl, auth, opts = {}) {
24195
- const base2 = getAgoraBaseUrl(backendUrl);
24196
- const res = await fetch(`${base2}/api/conversations/threads/list`, {
24197
- method: "POST",
24198
- headers: { "Content-Type": "application/json", ...getAuthHeaders(auth) },
24199
- body: JSON.stringify({ limit: opts.limit ?? 50, offset: opts.offset ?? 0 })
24200
- });
24201
- if (!res.ok) {
24202
- throw new Error(`[AthenaSDK] Failed to list threads: ${res.status}`);
24203
- }
24204
- return res.json();
24205
- }
24206
- async function archiveThread(backendUrl, auth, threadId) {
24207
- const base2 = getAgoraBaseUrl(backendUrl);
24208
- const res = await fetch(`${base2}/api/conversations/threads/archive`, {
24209
- method: "POST",
24210
- headers: { "Content-Type": "application/json", ...getAuthHeaders(auth) },
24211
- body: JSON.stringify({ thread_id: threadId })
24212
- });
24213
- if (!res.ok) {
24214
- throw new Error(`[AthenaSDK] Failed to archive thread: ${res.status}`);
24215
- }
24216
- }
24217
24267
  const AthenaThreadIdContext = React.createContext(void 0);
24218
24268
  function useAthenaThreadId() {
24219
24269
  return React.useContext(AthenaThreadIdContext);
24220
24270
  }
24221
24271
  function useAthenaThreadListAdapter(config2) {
24222
24272
  const configRef = React.useRef(config2);
24223
- React.useEffect(() => {
24224
- configRef.current = config2;
24225
- }, [config2]);
24273
+ configRef.current = config2;
24226
24274
  const auth = React.useMemo(
24227
24275
  () => ({ apiKey: config2.apiKey, token: config2.token }),
24228
24276
  [config2.apiKey, config2.token]
@@ -24265,7 +24313,9 @@ function useAthenaThreadListAdapter(config2) {
24265
24313
  await archiveThread(configRef.current.backendUrl, auth, remoteId);
24266
24314
  },
24267
24315
  async generateTitle(_remoteId, _messages) {
24268
- return new Response("").body;
24316
+ return new ReadableStream({ start(c) {
24317
+ c.close();
24318
+ } });
24269
24319
  },
24270
24320
  async fetch(remoteId) {
24271
24321
  return {
@@ -24523,7 +24573,7 @@ function AthenaWithThreadList({
24523
24573
  apiKey,
24524
24574
  token
24525
24575
  });
24526
- const runtimeConfig = React.useMemo(() => ({
24576
+ const runtimeConfigRef = React.useRef({
24527
24577
  apiUrl,
24528
24578
  backendUrl,
24529
24579
  apiKey,
@@ -24535,10 +24585,23 @@ function AthenaWithThreadList({
24535
24585
  workbench,
24536
24586
  knowledgeBase,
24537
24587
  systemPrompt
24538
- }), [apiUrl, backendUrl, apiKey, token, model, agent2, tools, frontendToolIds, workbench, knowledgeBase, systemPrompt]);
24588
+ });
24589
+ runtimeConfigRef.current = {
24590
+ apiUrl,
24591
+ backendUrl,
24592
+ apiKey,
24593
+ token,
24594
+ model,
24595
+ agent: agent2,
24596
+ tools,
24597
+ frontendToolIds,
24598
+ workbench,
24599
+ knowledgeBase,
24600
+ systemPrompt
24601
+ };
24539
24602
  const runtimeHook = React.useCallback(
24540
- () => useAthenaRuntimeHook(runtimeConfig),
24541
- [runtimeConfig]
24603
+ () => useAthenaRuntimeHook(runtimeConfigRef.current),
24604
+ []
24542
24605
  );
24543
24606
  const runtime = useRemoteThreadListRuntime({
24544
24607
  runtimeHook,
@@ -61660,6 +61723,7 @@ function AssetToolCard({
61660
61723
  assetId && isComplete && !isCancelled && CREATE_ASSET_TOOLS.includes(toolName.toLowerCase()) && /* @__PURE__ */ jsxRuntime.jsxs(
61661
61724
  "button",
61662
61725
  {
61726
+ type: "button",
61663
61727
  onClick: () => openAsset(assetId, { name: title ?? void 0, type: assetType }),
61664
61728
  className: "flex shrink-0 items-center gap-1 rounded-md border border-border/60 px-2 py-0.5 text-[11px] font-medium text-muted-foreground transition-colors hover:bg-muted/50 hover:text-foreground",
61665
61729
  children: [
@@ -61672,6 +61736,7 @@ function AssetToolCard({
61672
61736
  !isCancelled && /* @__PURE__ */ jsxRuntime.jsx(
61673
61737
  "button",
61674
61738
  {
61739
+ type: "button",
61675
61740
  onClick: () => setDetailsOpen((o) => !o),
61676
61741
  className: cn(
61677
61742
  "flex size-5 shrink-0 items-center justify-center rounded transition-all",
@@ -61703,6 +61768,7 @@ function AssetOpenLink({ assetId, toolName }) {
61703
61768
  return /* @__PURE__ */ jsxRuntime.jsx(
61704
61769
  "button",
61705
61770
  {
61771
+ type: "button",
61706
61772
  onClick: (e) => {
61707
61773
  e.stopPropagation();
61708
61774
  openAsset(assetId, { type: assetType });
@@ -62127,7 +62193,7 @@ function ToolCard({
62127
62193
  "flex size-8 shrink-0 items-center justify-center rounded-lg",
62128
62194
  isRunning && "bg-blue-50 text-blue-600",
62129
62195
  isComplete && "bg-emerald-50 text-emerald-600",
62130
- isError && "bg-red-50 text-red-500"
62196
+ isError && "bg-destructive/10 text-destructive"
62131
62197
  ),
62132
62198
  children: isRunning ? /* @__PURE__ */ jsxRuntime.jsx(Loader, { className: "size-4 animate-spin" }) : isError ? /* @__PURE__ */ jsxRuntime.jsx(CircleAlert, { className: "size-4" }) : /* @__PURE__ */ jsxRuntime.jsx(Icon2, { className: "size-4" })
62133
62199
  }
@@ -62146,7 +62212,7 @@ function ToolCard({
62146
62212
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-1.5 w-6 animate-pulse rounded-full bg-blue-100" })
62147
62213
  ] })
62148
62214
  ] }),
62149
- error2 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-t border-border/40 bg-red-50/50 px-4 py-2.5", children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[12px] leading-relaxed text-red-600", children: error2 }) }),
62215
+ error2 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-t border-border/40 bg-destructive/10 px-4 py-2.5", children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[12px] leading-relaxed text-destructive", children: error2 }) }),
62150
62216
  children
62151
62217
  ] });
62152
62218
  }
@@ -62392,6 +62458,7 @@ function CreateAssetToolUIImpl({
62392
62458
  children: assetId && isComplete && !isCancelled && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-t border-border/40 px-4 py-2", children: /* @__PURE__ */ jsxRuntime.jsxs(
62393
62459
  "button",
62394
62460
  {
62461
+ type: "button",
62395
62462
  onClick: handleOpen,
62396
62463
  className: "flex items-center gap-1.5 rounded-md border border-border/60 px-3 py-1.5 text-xs font-medium text-muted-foreground transition-colors hover:bg-muted/50 hover:text-foreground",
62397
62464
  children: [
@@ -62547,12 +62614,12 @@ const RunPythonCodeToolUIImpl = ({
62547
62614
  ] }),
62548
62615
  /* @__PURE__ */ jsxRuntime.jsx("pre", { className: "max-h-48 overflow-auto whitespace-pre-wrap break-words rounded-md bg-muted/30 p-2 text-[11px] leading-relaxed font-mono text-foreground/80", children: [parsed.value, parsed.stdout, parsed.stderr].filter(Boolean).join("\n") })
62549
62616
  ] }),
62550
- isComplete && hasError && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border-t border-border/40 bg-red-50/50 px-4 py-2.5", children: [
62617
+ isComplete && hasError && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border-t border-border/40 bg-destructive/10 px-4 py-2.5", children: [
62551
62618
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5 mb-1", children: [
62552
- /* @__PURE__ */ jsxRuntime.jsx(TriangleAlert, { className: "size-3 text-red-500" }),
62553
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[11px] font-medium text-red-600", children: parsed.exception ? `${parsed.exception.name}: ${parsed.exception.value}` : "Error" })
62619
+ /* @__PURE__ */ jsxRuntime.jsx(TriangleAlert, { className: "size-3 text-destructive" }),
62620
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[11px] font-medium text-destructive", children: parsed.exception ? `${parsed.exception.name}: ${parsed.exception.value}` : "Error" })
62554
62621
  ] }),
62555
- /* @__PURE__ */ jsxRuntime.jsx("pre", { className: "max-h-48 overflow-auto whitespace-pre-wrap break-words rounded-md bg-red-50 p-2 text-[11px] leading-relaxed font-mono text-red-600/80", children: ((_a2 = parsed.exception) == null ? void 0 : _a2.traceback) ?? parsed.error })
62622
+ /* @__PURE__ */ jsxRuntime.jsx("pre", { className: "max-h-48 overflow-auto whitespace-pre-wrap break-words rounded-md bg-destructive/5 p-2 text-[11px] leading-relaxed font-mono text-destructive/80", children: ((_a2 = parsed.exception) == null ? void 0 : _a2.traceback) ?? parsed.error })
62556
62623
  ] }),
62557
62624
  isComplete && hasImage && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border-t border-border/40 px-4 py-2.5", children: [
62558
62625
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5 mb-1.5", children: [
@@ -62573,6 +62640,7 @@ const RunPythonCodeToolUIImpl = ({
62573
62640
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 flex flex-wrap gap-1.5", children: parsed.createdAssets.map((a) => /* @__PURE__ */ jsxRuntime.jsxs(
62574
62641
  "button",
62575
62642
  {
62643
+ type: "button",
62576
62644
  onClick: () => openAsset(a.asset_id),
62577
62645
  className: "flex items-center gap-1 rounded-md border border-border/60 px-2 py-1 text-[11px] font-medium text-muted-foreground transition-colors hover:bg-muted/50 hover:text-foreground",
62578
62646
  children: [
@@ -62627,6 +62695,7 @@ const OpenAssetToolUIImpl = ({
62627
62695
  children: assetId && isComplete && !isCancelled && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-t border-border/40 px-4 py-2", children: /* @__PURE__ */ jsxRuntime.jsxs(
62628
62696
  "button",
62629
62697
  {
62698
+ type: "button",
62630
62699
  onClick: () => openAsset(assetId),
62631
62700
  className: "flex items-center gap-1.5 rounded-md border border-border/60 px-3 py-1.5 text-xs font-medium text-muted-foreground transition-colors hover:bg-muted/50 hover:text-foreground",
62632
62701
  children: [