@athenaintel/react 0.9.4 → 0.9.6

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.d.ts CHANGED
@@ -80,8 +80,11 @@ export declare interface AthenaConfig {
80
80
  apiKey?: string;
81
81
  token?: string | null;
82
82
  backendUrl: string;
83
+ appUrl: string;
83
84
  }
84
85
 
86
+ export declare type AthenaEnvironment = 'production' | 'staging';
87
+
85
88
  /**
86
89
  * Layout that places the chat on the left and the asset panel on the right.
87
90
  * When no assets are open, the chat takes full width. Includes a draggable resize handle.
@@ -96,7 +99,7 @@ export declare interface AthenaLayoutProps {
96
99
  minPercent?: number;
97
100
  }
98
101
 
99
- export declare function AthenaProvider({ children, apiKey, token: tokenProp, agent, model, tools, frontendTools, apiUrl, backendUrl, workbench, knowledgeBase, systemPrompt, threadId: threadIdProp, enableThreadList, theme, }: AthenaProviderProps): JSX.Element | null;
102
+ export declare function AthenaProvider({ children, apiKey, token: tokenProp, agent, model, tools, frontendTools, apiUrl, backendUrl, appUrl, environment, workbench, knowledgeBase, systemPrompt, threadId: threadIdProp, enableThreadList, theme, }: AthenaProviderProps): JSX.Element | null;
100
103
 
101
104
  export declare interface AthenaProviderProps {
102
105
  children: ReactNode;
@@ -117,6 +120,10 @@ export declare interface AthenaProviderProps {
117
120
  apiUrl?: string;
118
121
  /** URL for the Agora backend API. Defaults to Athena production. */
119
122
  backendUrl?: string;
123
+ /** URL for the Athena frontend app origin. Defaults to the matching Athena environment. */
124
+ appUrl?: string;
125
+ /** Athena environment preset used when URLs are not explicitly provided. */
126
+ environment?: AthenaEnvironment;
120
127
  /** Asset IDs to include in the workbench. */
121
128
  workbench?: string[];
122
129
  /** Knowledge base IDs for RAG context. */
@@ -316,9 +323,11 @@ export declare const CreatePresentationToolUI: ToolCallMessagePartComponent;
316
323
 
317
324
  export declare const CreateSheetToolUI: ToolCallMessagePartComponent;
318
325
 
319
- export declare const DEFAULT_API_URL = "https://sync.athenaintel.com/api/chat";
326
+ export declare const DEFAULT_API_URL: string;
327
+
328
+ export declare const DEFAULT_APP_URL: string;
320
329
 
321
- export declare const DEFAULT_BACKEND_URL = "https://api.athenaintel.com/api/assistant-ui";
330
+ export declare const DEFAULT_BACKEND_URL: string;
322
331
 
323
332
  export declare const EmailSearchToolUI: ToolCallMessagePartComponent;
324
333
 
@@ -406,6 +415,8 @@ export declare interface ParentBridgeState {
406
415
  apiUrl: string | null;
407
416
  /** Agora backend URL provided by the Marathon wrapper. */
408
417
  backendUrl: string | null;
418
+ /** Athena frontend origin provided by the parent wrapper. */
419
+ appUrl: string | null;
409
420
  /** True once config has been received from the parent (or timeout fired). */
410
421
  ready: boolean;
411
422
  }
@@ -894,14 +905,14 @@ export declare function useParentAuth(): string | null;
894
905
  * via PostMessage.
895
906
  *
896
907
  * When the app runs inside a Marathon wrapper, the wrapper sends:
897
- * 1. { type: 'athena-config', apiUrl, backendUrl } — correct API URLs for the environment
908
+ * 1. { type: 'athena-config', apiUrl, backendUrl, appUrl } — correct URLs for the environment
898
909
  * 2. { type: 'athena-auth', token } — relayed from the Olympus token-bridge iframe
899
910
  *
900
911
  * When running inside an Olympus inline preview, only athena-auth is sent.
901
912
  * When running standalone (no parent), returns defaults immediately.
902
913
  *
903
914
  * Protocol:
904
- * Parent -> iframe: { type: 'athena-config', apiUrl: string, backendUrl: string }
915
+ * Parent -> iframe: { type: 'athena-config', apiUrl: string, backendUrl: string, appUrl?: string }
905
916
  * Parent -> iframe: { type: 'athena-auth', token: '<propel-access-token>' }
906
917
  * iframe -> Parent: { type: 'athena-auth-ready' }
907
918
  */
package/dist/index.js CHANGED
@@ -16457,6 +16457,106 @@ const INTERNAL = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProp
16457
16457
  useSmoothStatus,
16458
16458
  useToolInvocations
16459
16459
  }, Symbol.toStringTag, { value: "Module" }));
16460
+ const ATHENA_ENVIRONMENT_URLS = {
16461
+ production: {
16462
+ apiUrl: "https://sync.athenaintel.com/api/chat",
16463
+ backendUrl: "https://api.athenaintel.com/api/assistant-ui",
16464
+ appUrl: "https://app.athenaintel.com"
16465
+ },
16466
+ staging: {
16467
+ apiUrl: "https://staging-sync.athenaintel.com/api/chat",
16468
+ backendUrl: "https://staging-api.athenaintel.com/api/assistant-ui",
16469
+ appUrl: "https://staging-app.athenaintel.com"
16470
+ }
16471
+ };
16472
+ const DEFAULT_ATHENA_ENVIRONMENT = "production";
16473
+ const DEFAULT_API_URL = ATHENA_ENVIRONMENT_URLS.production.apiUrl;
16474
+ const DEFAULT_BACKEND_URL = ATHENA_ENVIRONMENT_URLS.production.backendUrl;
16475
+ const DEFAULT_APP_URL = ATHENA_ENVIRONMENT_URLS.production.appUrl;
16476
+ const SPACES_PATHNAME = "/dashboard/spaces/";
16477
+ const normalizeBaseUrl = (url) => url.replace(/\/+$/, "");
16478
+ const getHostname = (value) => {
16479
+ if (!value) return null;
16480
+ try {
16481
+ return new URL(value).hostname;
16482
+ } catch {
16483
+ return null;
16484
+ }
16485
+ };
16486
+ const deriveWorkspaceAppUrl = ({
16487
+ sourceUrl,
16488
+ sourcePort
16489
+ }) => {
16490
+ var _a2;
16491
+ try {
16492
+ const parsedUrl = new URL(sourceUrl);
16493
+ const match2 = parsedUrl.hostname.match(
16494
+ new RegExp(`^(?<prefix>.+)--${sourcePort}\\.(?<domain>app\\.athenaintel\\.com|staging-app\\.athenaintel\\.com)$`)
16495
+ );
16496
+ if (!((_a2 = match2 == null ? void 0 : match2.groups) == null ? void 0 : _a2.prefix) || !match2.groups.domain) {
16497
+ return null;
16498
+ }
16499
+ return `${parsedUrl.protocol}//${match2.groups.prefix}--8082.${match2.groups.domain}`;
16500
+ } catch {
16501
+ return null;
16502
+ }
16503
+ };
16504
+ function getAthenaEnvironmentUrls({
16505
+ environment = DEFAULT_ATHENA_ENVIRONMENT
16506
+ } = {}) {
16507
+ return ATHENA_ENVIRONMENT_URLS[environment];
16508
+ }
16509
+ function deriveAthenaAppUrl({
16510
+ apiUrl,
16511
+ backendUrl
16512
+ }) {
16513
+ if (backendUrl) {
16514
+ const workspaceAppUrl = deriveWorkspaceAppUrl({
16515
+ sourceUrl: backendUrl,
16516
+ sourcePort: "8000"
16517
+ });
16518
+ if (workspaceAppUrl) return workspaceAppUrl;
16519
+ const backendHostname = getHostname(backendUrl);
16520
+ if (backendHostname === "api.athenaintel.com") {
16521
+ return ATHENA_ENVIRONMENT_URLS.production.appUrl;
16522
+ }
16523
+ if (backendHostname === "staging-api.athenaintel.com") {
16524
+ return ATHENA_ENVIRONMENT_URLS.staging.appUrl;
16525
+ }
16526
+ }
16527
+ if (apiUrl) {
16528
+ const workspaceAppUrl = deriveWorkspaceAppUrl({
16529
+ sourceUrl: apiUrl,
16530
+ sourcePort: "8787"
16531
+ });
16532
+ if (workspaceAppUrl) return workspaceAppUrl;
16533
+ const apiHostname = getHostname(apiUrl);
16534
+ if (apiHostname === "sync.athenaintel.com") {
16535
+ return ATHENA_ENVIRONMENT_URLS.production.appUrl;
16536
+ }
16537
+ if (apiHostname === "staging-sync.athenaintel.com") {
16538
+ return ATHENA_ENVIRONMENT_URLS.staging.appUrl;
16539
+ }
16540
+ }
16541
+ return null;
16542
+ }
16543
+ function createAthenaSpacesUrl({
16544
+ appUrl = DEFAULT_APP_URL,
16545
+ assetIds,
16546
+ sessionId
16547
+ }) {
16548
+ const url = new URL(SPACES_PATHNAME, `${normalizeBaseUrl(appUrl)}/`);
16549
+ if (assetIds) {
16550
+ const normalizedAssetIds = (Array.isArray(assetIds) ? assetIds : [assetIds]).map((assetId) => assetId.trim()).filter((assetId) => assetId.length > 0);
16551
+ if (normalizedAssetIds.length > 0) {
16552
+ url.searchParams.set("asset_ids", normalizedAssetIds.join(","));
16553
+ }
16554
+ }
16555
+ if (sessionId) {
16556
+ url.searchParams.set("session_id", sessionId);
16557
+ }
16558
+ return url.toString();
16559
+ }
16460
16560
  function isTrustedOrigin(origin) {
16461
16561
  try {
16462
16562
  const { hostname } = new URL(origin);
@@ -16472,6 +16572,7 @@ function useParentBridge() {
16472
16572
  token: null,
16473
16573
  apiUrl: null,
16474
16574
  backendUrl: null,
16575
+ appUrl: null,
16475
16576
  // If not in an iframe, we're ready immediately (standalone mode)
16476
16577
  ready: !isInIframe
16477
16578
  });
@@ -16487,7 +16588,8 @@ function useParentBridge() {
16487
16588
  setState((prev) => ({
16488
16589
  ...prev,
16489
16590
  apiUrl: typeof event.data.apiUrl === "string" ? event.data.apiUrl : prev.apiUrl,
16490
- backendUrl: typeof event.data.backendUrl === "string" ? event.data.backendUrl : prev.backendUrl
16591
+ backendUrl: typeof event.data.backendUrl === "string" ? event.data.backendUrl : prev.backendUrl,
16592
+ appUrl: typeof event.data.appUrl === "string" ? event.data.appUrl : prev.appUrl
16491
16593
  // Don't set ready here — wait for athena-auth (token) or the timeout.
16492
16594
  // Setting ready on config alone causes a race: the thread list fires
16493
16595
  // before the token arrives, falling back to X-API-KEY.
@@ -20719,8 +20821,6 @@ async function archiveThread(backendUrl, auth, threadId) {
20719
20821
  throw new Error(`[AthenaSDK] Failed to archive thread: ${res.status}`);
20720
20822
  }
20721
20823
  }
20722
- const DEFAULT_API_URL = "https://sync.athenaintel.com/api/chat";
20723
- const DEFAULT_BACKEND_URL = "https://api.athenaintel.com/api/assistant-ui";
20724
20824
  const DEFAULT_MODEL = "claude-opus-4-6-thinking-max-fast";
20725
20825
  const DEFAULT_AGENT = "athena_assist_agent";
20726
20826
  const ATHENA_TRACKING_ID_KEY = "_athena_tracking_id";
@@ -24300,7 +24400,7 @@ function useAthenaThreadListAdapter(config2) {
24300
24400
  );
24301
24401
  return useMemo(() => ({
24302
24402
  async list() {
24303
- if (!auth.token) {
24403
+ if (!auth.token && !auth.apiKey) {
24304
24404
  return { threads: [] };
24305
24405
  }
24306
24406
  try {
@@ -24529,6 +24629,7 @@ function AthenaStandalone({
24529
24629
  children,
24530
24630
  apiUrl,
24531
24631
  backendUrl,
24632
+ appUrl,
24532
24633
  apiKey,
24533
24634
  token,
24534
24635
  model,
@@ -24558,8 +24659,8 @@ function AthenaStandalone({
24558
24659
  threadId
24559
24660
  });
24560
24661
  const athenaConfig = useMemo(
24561
- () => ({ backendUrl, apiKey, token }),
24562
- [backendUrl, apiKey, token]
24662
+ () => ({ backendUrl, appUrl, apiKey, token }),
24663
+ [backendUrl, appUrl, apiKey, token]
24563
24664
  );
24564
24665
  return /* @__PURE__ */ jsx(AssistantRuntimeProvider, { aui, runtime, children: /* @__PURE__ */ jsx(AthenaContext.Provider, { value: athenaConfig, children: /* @__PURE__ */ jsx(TooltipProvider, { children }) }) });
24565
24666
  }
@@ -24584,6 +24685,7 @@ function AthenaWithThreadList({
24584
24685
  children,
24585
24686
  apiUrl,
24586
24687
  backendUrl,
24688
+ appUrl,
24587
24689
  apiKey,
24588
24690
  token,
24589
24691
  model,
@@ -24642,11 +24744,21 @@ function AthenaWithThreadList({
24642
24744
  core.__internal_load();
24643
24745
  }
24644
24746
  }, [runtime]);
24747
+ const previousAuthRefreshKeyRef = useRef(null);
24748
+ const authRefreshKey = `${backendUrl}::${apiKey ?? ""}::${token ?? ""}`;
24749
+ useEffect(() => {
24750
+ const previousAuthRefreshKey = previousAuthRefreshKeyRef.current;
24751
+ previousAuthRefreshKeyRef.current = authRefreshKey;
24752
+ if (previousAuthRefreshKey === null || previousAuthRefreshKey === authRefreshKey) {
24753
+ return;
24754
+ }
24755
+ handleRefresh();
24756
+ }, [authRefreshKey, handleRefresh]);
24645
24757
  const auiTools = useMemo(() => Tools({ toolkit: frontendTools }), [frontendTools]);
24646
24758
  const aui = useAui({ tools: auiTools });
24647
24759
  const athenaConfig = useMemo(
24648
- () => ({ backendUrl, apiKey, token }),
24649
- [backendUrl, apiKey, token]
24760
+ () => ({ backendUrl, appUrl, apiKey, token }),
24761
+ [backendUrl, appUrl, apiKey, token]
24650
24762
  );
24651
24763
  return /* @__PURE__ */ jsx(AssistantRuntimeProvider, { aui, runtime, children: /* @__PURE__ */ jsx(AthenaContext.Provider, { value: athenaConfig, children: /* @__PURE__ */ jsx(ThreadListRefreshContext.Provider, { value: handleRefresh, children: /* @__PURE__ */ jsx(TooltipProvider, { children }) }) }) });
24652
24764
  }
@@ -24660,6 +24772,8 @@ function AthenaProvider({
24660
24772
  frontendTools = {},
24661
24773
  apiUrl,
24662
24774
  backendUrl,
24775
+ appUrl,
24776
+ environment,
24663
24777
  workbench,
24664
24778
  knowledgeBase,
24665
24779
  systemPrompt,
@@ -24669,10 +24783,15 @@ function AthenaProvider({
24669
24783
  }) {
24670
24784
  const frontendToolNames = useMemo(() => Object.keys(frontendTools), [frontendTools]);
24671
24785
  const themeStyleVars = useMemo(() => theme ? themeToStyleVars(theme) : void 0, [theme]);
24786
+ const environmentUrls = useMemo(
24787
+ () => getAthenaEnvironmentUrls({ environment }),
24788
+ [environment]
24789
+ );
24672
24790
  const bridge = useParentBridge();
24673
24791
  const effectiveToken = tokenProp ?? bridge.token;
24674
- const effectiveApiUrl = apiUrl ?? bridge.apiUrl ?? DEFAULT_API_URL;
24675
- const effectiveBackendUrl = backendUrl ?? bridge.backendUrl ?? DEFAULT_BACKEND_URL;
24792
+ const effectiveApiUrl = apiUrl ?? bridge.apiUrl ?? environmentUrls.apiUrl ?? DEFAULT_API_URL;
24793
+ const effectiveBackendUrl = backendUrl ?? bridge.backendUrl ?? environmentUrls.backendUrl ?? DEFAULT_BACKEND_URL;
24794
+ const effectiveAppUrl = appUrl ?? bridge.appUrl ?? deriveAthenaAppUrl({ apiUrl: effectiveApiUrl, backendUrl: effectiveBackendUrl }) ?? environmentUrls.appUrl ?? DEFAULT_APP_URL;
24676
24795
  if (!bridge.ready) {
24677
24796
  return null;
24678
24797
  }
@@ -24683,6 +24802,7 @@ function AthenaProvider({
24683
24802
  {
24684
24803
  apiUrl: effectiveApiUrl,
24685
24804
  backendUrl: effectiveBackendUrl,
24805
+ appUrl: effectiveAppUrl,
24686
24806
  apiKey,
24687
24807
  token: effectiveToken,
24688
24808
  model,
@@ -24702,6 +24822,7 @@ function AthenaProvider({
24702
24822
  {
24703
24823
  apiUrl: effectiveApiUrl,
24704
24824
  backendUrl: effectiveBackendUrl,
24825
+ appUrl: effectiveAppUrl,
24705
24826
  apiKey,
24706
24827
  token: effectiveToken,
24707
24828
  model,
@@ -60499,9 +60620,12 @@ function useAttachments() {
60499
60620
  }
60500
60621
  return ctx;
60501
60622
  }
60502
- function buildAttachmentMarkdown(attachments) {
60623
+ function buildAttachmentMarkdownWithAppUrl({
60624
+ attachments,
60625
+ appUrl = DEFAULT_APP_URL
60626
+ }) {
60503
60627
  if (attachments.length === 0) return "";
60504
- return attachments.map((a) => `[@${a.title}](https://app.athenaintel.com/dashboard/spaces?asset_id=${a.id})`).join("\n");
60628
+ return attachments.map((attachment) => `[@${attachment.title}](${createAthenaSpacesUrl({ appUrl, assetIds: attachment.id })})`).join("\n");
60505
60629
  }
60506
60630
  const QuoteCtx = createContext(null);
60507
60631
  function QuoteProvider({ children }) {
@@ -60567,7 +60691,10 @@ function buildComposedMessage(opts) {
60567
60691
  var _a2;
60568
60692
  const parts = [];
60569
60693
  if (opts.attachments && opts.attachments.length > 0) {
60570
- const attachmentMd = buildAttachmentMarkdown(opts.attachments);
60694
+ const attachmentMd = buildAttachmentMarkdownWithAppUrl({
60695
+ attachments: opts.attachments,
60696
+ appUrl: opts.appUrl
60697
+ });
60571
60698
  if (attachmentMd) parts.push(attachmentMd);
60572
60699
  }
60573
60700
  if (opts.quote) {
@@ -60588,6 +60715,7 @@ const TiptapComposer = ({ tools = [] }) => {
60588
60715
  const mentionStore = useMentionSuggestions(tools);
60589
60716
  const { attachments, clearAttachments, isUploading } = useAttachments();
60590
60717
  const { quote, clearQuote } = useQuote();
60718
+ const { appUrl } = useAthenaConfig();
60591
60719
  const attachmentsRef = useRef(attachments);
60592
60720
  attachmentsRef.current = attachments;
60593
60721
  const quoteRef = useRef(quote);
@@ -60608,7 +60736,8 @@ const TiptapComposer = ({ tools = [] }) => {
60608
60736
  const fullMessage = buildComposedMessage({
60609
60737
  attachments: currentAttachments,
60610
60738
  quote: currentQuote,
60611
- userText: markdown
60739
+ userText: markdown,
60740
+ appUrl
60612
60741
  });
60613
60742
  if (fullMessage) {
60614
60743
  aui.thread().append({
@@ -63958,6 +64087,7 @@ const ComposerAction = () => /* @__PURE__ */ jsxs("div", { className: "aui-compo
63958
64087
  ] });
63959
64088
  const ComposerSendWithQuote = () => {
63960
64089
  const aui = useAui();
64090
+ const { appUrl } = useAthenaConfig();
63961
64091
  const { quote, clearQuote } = useQuote();
63962
64092
  const { attachments, clearAttachments, isUploading } = useAttachments();
63963
64093
  const editorRef = useComposerEditorRef();
@@ -63971,7 +64101,8 @@ const ComposerSendWithQuote = () => {
63971
64101
  const fullMessage = buildComposedMessage({
63972
64102
  attachments,
63973
64103
  quote,
63974
- userText
64104
+ userText,
64105
+ appUrl
63975
64106
  });
63976
64107
  if (!fullMessage) return;
63977
64108
  aui.thread().append({
@@ -64055,6 +64186,7 @@ const AssistantMessage = ({ toolUIs }) => /* @__PURE__ */ jsxs(
64055
64186
  );
64056
64187
  const AssistantActionBar = () => {
64057
64188
  const threadId = useAthenaThreadId();
64189
+ const { appUrl } = useAthenaConfig();
64058
64190
  return /* @__PURE__ */ jsxs(
64059
64191
  ActionBarPrimitiveRoot,
64060
64192
  {
@@ -64084,10 +64216,7 @@ const AssistantActionBar = () => {
64084
64216
  {
64085
64217
  className: "aui-action-bar-more-item flex cursor-pointer select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground",
64086
64218
  onClick: () => {
64087
- window.open(
64088
- `https://app.athenaintel.com/dashboard/spaces?session_id=${threadId}`,
64089
- "_blank"
64090
- );
64219
+ window.open(createAthenaSpacesUrl({ appUrl, sessionId: threadId }), "_blank");
64091
64220
  },
64092
64221
  children: [
64093
64222
  /* @__PURE__ */ jsx(ExternalLink, { className: "size-4" }),
@@ -64575,6 +64704,7 @@ export {
64575
64704
  CreatePresentationToolUI,
64576
64705
  CreateSheetToolUI,
64577
64706
  DEFAULT_API_URL,
64707
+ DEFAULT_APP_URL,
64578
64708
  DEFAULT_BACKEND_URL,
64579
64709
  EmailSearchToolUI,
64580
64710
  ExpandableSection,