@athenaintel/react 0.7.2 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -96,7 +96,7 @@ export declare interface AthenaLayoutProps {
96
96
  minPercent?: number;
97
97
  }
98
98
 
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;
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;
100
100
 
101
101
  export declare interface AthenaProviderProps {
102
102
  children: ReactNode;
@@ -306,6 +306,8 @@ export declare const CreatePresentationToolUI: ToolCallMessagePartComponent;
306
306
 
307
307
  export declare const CreateSheetToolUI: ToolCallMessagePartComponent;
308
308
 
309
+ export declare const DEFAULT_API_URL = "https://sync.athenaintel.com/api/chat";
310
+
309
311
  export declare const DEFAULT_BACKEND_URL = "https://api.athenaintel.com/api/assistant-ui";
310
312
 
311
313
  export declare const EmailSearchToolUI: ToolCallMessagePartComponent;
@@ -387,6 +389,17 @@ export declare function normalizeResult(result: unknown): Record<string, unknown
387
389
 
388
390
  export declare const OpenAssetToolUI: ToolCallMessagePartComponent;
389
391
 
392
+ export declare interface ParentBridgeState {
393
+ /** PropelAuth access token from the parent window. */
394
+ token: string | null;
395
+ /** Sync server chat URL provided by the Marathon wrapper. */
396
+ apiUrl: string | null;
397
+ /** Agora backend URL provided by the Marathon wrapper. */
398
+ backendUrl: string | null;
399
+ /** True once config has been received from the parent (or timeout fired). */
400
+ ready: boolean;
401
+ }
402
+
390
403
  declare interface QuoteContextValue {
391
404
  quote: QuoteData | null;
392
405
  setQuote: (quote: QuoteData | null) => void;
@@ -859,19 +872,28 @@ export declare interface UseFileUploadReturn {
859
872
  export declare function useMentionSuggestions(tools: MentionTool[]): MentionSuggestionsStore;
860
873
 
861
874
  /**
862
- * Listens for auth tokens sent from a parent window via PostMessage.
875
+ * Legacy hook — returns just the auth token from the parent bridge.
876
+ * Prefer useParentBridge() for new code.
877
+ */
878
+ export declare function useParentAuth(): string | null;
879
+
880
+ /**
881
+ * Listens for auth tokens AND environment config sent from a parent window
882
+ * via PostMessage.
883
+ *
884
+ * When the app runs inside a Marathon wrapper, the wrapper sends:
885
+ * 1. { type: 'athena-config', apiUrl, backendUrl } — correct API URLs for the environment
886
+ * 2. { type: 'athena-auth', token } — relayed from the Olympus token-bridge iframe
863
887
  *
864
- * When the app runs inside an Olympus iframe, the parent sends
865
- * the user's PropelAuth access token so the chat authenticates as the
866
- * actual viewer — not the hardcoded API key owner.
888
+ * When running inside an Olympus inline preview, only athena-auth is sent.
889
+ * When running standalone (no parent), returns defaults immediately.
867
890
  *
868
891
  * Protocol:
892
+ * Parent -> iframe: { type: 'athena-config', apiUrl: string, backendUrl: string }
869
893
  * Parent -> iframe: { type: 'athena-auth', token: '<propel-access-token>' }
870
894
  * iframe -> Parent: { type: 'athena-auth-ready' }
871
- *
872
- * Falls back to null when running standalone (no parent window).
873
895
  */
874
- export declare function useParentAuth(): string | null;
896
+ export declare function useParentBridge(): ParentBridgeState;
875
897
 
876
898
  export declare function useQuote(): QuoteContextValue;
877
899
 
package/dist/index.js CHANGED
@@ -16465,24 +16465,60 @@ function isTrustedOrigin(origin) {
16465
16465
  return false;
16466
16466
  }
16467
16467
  }
16468
- function useParentAuth() {
16469
- const [authToken, setAuthToken] = useState(null);
16468
+ const BRIDGE_TIMEOUT_MS = 2e3;
16469
+ function useParentBridge() {
16470
+ const isInIframe = typeof window !== "undefined" && window.parent !== window;
16471
+ const [state, setState] = useState({
16472
+ token: null,
16473
+ apiUrl: null,
16474
+ backendUrl: null,
16475
+ // If not in an iframe, we're ready immediately (standalone mode)
16476
+ ready: !isInIframe
16477
+ });
16470
16478
  const readySignalSent = useRef(false);
16479
+ const configReceived = useRef(false);
16471
16480
  useEffect(() => {
16481
+ if (!isInIframe) return;
16472
16482
  const handler = (event) => {
16473
16483
  if (!isTrustedOrigin(event.origin)) return;
16474
- if (event.data && typeof event.data === "object" && event.data.type === "athena-auth" && typeof event.data.token === "string") {
16475
- setAuthToken(event.data.token);
16484
+ if (!event.data || typeof event.data !== "object") return;
16485
+ if (event.data.type === "athena-config") {
16486
+ configReceived.current = true;
16487
+ setState((prev) => ({
16488
+ ...prev,
16489
+ apiUrl: typeof event.data.apiUrl === "string" ? event.data.apiUrl : prev.apiUrl,
16490
+ backendUrl: typeof event.data.backendUrl === "string" ? event.data.backendUrl : prev.backendUrl,
16491
+ ready: true
16492
+ }));
16493
+ }
16494
+ if (event.data.type === "athena-auth" && typeof event.data.token === "string") {
16495
+ setState((prev) => ({
16496
+ ...prev,
16497
+ token: event.data.token,
16498
+ // If we got a token, we're ready even without config
16499
+ ready: true
16500
+ }));
16476
16501
  }
16477
16502
  };
16478
16503
  window.addEventListener("message", handler);
16479
- if (!readySignalSent.current && window.parent !== window) {
16504
+ if (!readySignalSent.current) {
16480
16505
  window.parent.postMessage({ type: "athena-auth-ready" }, "*");
16481
16506
  readySignalSent.current = true;
16482
16507
  }
16483
- return () => window.removeEventListener("message", handler);
16484
- }, []);
16485
- return authToken;
16508
+ const timer = setTimeout(() => {
16509
+ if (!configReceived.current) {
16510
+ setState((prev) => ({ ...prev, ready: true }));
16511
+ }
16512
+ }, BRIDGE_TIMEOUT_MS);
16513
+ return () => {
16514
+ window.removeEventListener("message", handler);
16515
+ clearTimeout(timer);
16516
+ };
16517
+ }, [isInIframe]);
16518
+ return state;
16519
+ }
16520
+ function useParentAuth() {
16521
+ return useParentBridge().token;
16486
16522
  }
16487
16523
  const { fromThreadMessageLike, getAutoStatus } = INTERNAL;
16488
16524
  const joinExternalMessages = (messages) => {
@@ -24473,70 +24509,6 @@ const themes = {
24473
24509
  radius: "0.625rem"
24474
24510
  }
24475
24511
  };
24476
- const QuoteCtx = createContext(null);
24477
- function QuoteProvider({ children }) {
24478
- const [quote, setQuote] = useState(null);
24479
- const clearQuote = useCallback(() => setQuote(null), []);
24480
- const value = useMemo(() => ({ quote, setQuote, clearQuote }), [quote, setQuote, clearQuote]);
24481
- return /* @__PURE__ */ jsx(QuoteCtx.Provider, { value, children });
24482
- }
24483
- function useQuote() {
24484
- const ctx = useContext(QuoteCtx);
24485
- if (!ctx) {
24486
- throw new Error("[AthenaSDK] useQuote must be used within <QuoteProvider>");
24487
- }
24488
- return ctx;
24489
- }
24490
- function useQuoteFromPostMessage() {
24491
- const { setQuote } = useQuote();
24492
- useEffect(() => {
24493
- const handleKeydown = (e) => {
24494
- var _a2;
24495
- if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === "l") {
24496
- const sel = window.getSelection();
24497
- const selection = (_a2 = sel == null ? void 0 : sel.toString()) == null ? void 0 : _a2.trim();
24498
- if (selection && selection.length > 0) {
24499
- e.preventDefault();
24500
- let messageId;
24501
- let role;
24502
- let node = sel == null ? void 0 : sel.anchorNode;
24503
- while (node && node !== document.body) {
24504
- if (node instanceof HTMLElement) {
24505
- const dataRole = node.getAttribute("data-role");
24506
- if (dataRole === "assistant" || dataRole === "user") {
24507
- role = dataRole;
24508
- messageId = node.getAttribute("data-message-id") ?? void 0;
24509
- break;
24510
- }
24511
- }
24512
- node = node.parentElement;
24513
- }
24514
- setQuote({ text: selection, sourceRole: role, sourceMessageId: messageId });
24515
- }
24516
- }
24517
- };
24518
- const handleMessage = (event) => {
24519
- const data = event.data;
24520
- if (data && typeof data === "object" && data.type === "athena-add-to-composer" && typeof data.text === "string" && data.text.trim().length > 0) {
24521
- setQuote({
24522
- text: data.text,
24523
- sourceTitle: data.sourceTitle,
24524
- sourceAssetId: data.sourceAssetId
24525
- });
24526
- }
24527
- };
24528
- document.addEventListener("keydown", handleKeydown, true);
24529
- window.addEventListener("message", handleMessage);
24530
- return () => {
24531
- document.removeEventListener("keydown", handleKeydown, true);
24532
- window.removeEventListener("message", handleMessage);
24533
- };
24534
- }, [setQuote]);
24535
- }
24536
- function QuotePostMessageBridge() {
24537
- useQuoteFromPostMessage();
24538
- return null;
24539
- }
24540
24512
  function AthenaStandalone({
24541
24513
  children,
24542
24514
  apiUrl,
@@ -24573,10 +24545,7 @@ function AthenaStandalone({
24573
24545
  () => ({ backendUrl, apiKey, token }),
24574
24546
  [backendUrl, apiKey, token]
24575
24547
  );
24576
- return /* @__PURE__ */ jsx(AssistantRuntimeProvider, { aui, runtime, children: /* @__PURE__ */ jsx(AthenaContext.Provider, { value: athenaConfig, children: /* @__PURE__ */ jsxs(QuoteProvider, { children: [
24577
- /* @__PURE__ */ jsx(QuotePostMessageBridge, {}),
24578
- /* @__PURE__ */ jsx(TooltipProvider, { children })
24579
- ] }) }) });
24548
+ return /* @__PURE__ */ jsx(AssistantRuntimeProvider, { aui, runtime, children: /* @__PURE__ */ jsx(AthenaContext.Provider, { value: athenaConfig, children: /* @__PURE__ */ jsx(TooltipProvider, { children }) }) });
24580
24549
  }
24581
24550
  function useAthenaRuntimeHook(config2) {
24582
24551
  const remoteId = useAthenaThreadId();
@@ -24655,10 +24624,7 @@ function AthenaWithThreadList({
24655
24624
  () => ({ backendUrl, apiKey, token }),
24656
24625
  [backendUrl, apiKey, token]
24657
24626
  );
24658
- return /* @__PURE__ */ jsx(AssistantRuntimeProvider, { aui, runtime, children: /* @__PURE__ */ jsx(AthenaContext.Provider, { value: athenaConfig, children: /* @__PURE__ */ jsxs(QuoteProvider, { children: [
24659
- /* @__PURE__ */ jsx(QuotePostMessageBridge, {}),
24660
- /* @__PURE__ */ jsx(TooltipProvider, { children })
24661
- ] }) }) });
24627
+ return /* @__PURE__ */ jsx(AssistantRuntimeProvider, { aui, runtime, children: /* @__PURE__ */ jsx(AthenaContext.Provider, { value: athenaConfig, children: /* @__PURE__ */ jsx(TooltipProvider, { children }) }) });
24662
24628
  }
24663
24629
  function AthenaProvider({
24664
24630
  children,
@@ -24679,15 +24645,19 @@ function AthenaProvider({
24679
24645
  }) {
24680
24646
  const frontendToolNames = useMemo(() => Object.keys(frontendTools), [frontendTools]);
24681
24647
  const themeStyleVars = useMemo(() => theme ? themeToStyleVars(theme) : void 0, [theme]);
24682
- const parentAuthToken = useParentAuth();
24683
- const effectiveToken = tokenProp ?? parentAuthToken;
24684
- const effectiveBackendUrl = backendUrl ?? DEFAULT_BACKEND_URL;
24648
+ const bridge = useParentBridge();
24649
+ const effectiveToken = tokenProp ?? bridge.token;
24650
+ const effectiveApiUrl = apiUrl ?? bridge.apiUrl ?? DEFAULT_API_URL;
24651
+ const effectiveBackendUrl = backendUrl ?? bridge.backendUrl ?? DEFAULT_BACKEND_URL;
24652
+ if (!bridge.ready) {
24653
+ return null;
24654
+ }
24685
24655
  let inner;
24686
24656
  if (enableThreadList) {
24687
24657
  inner = /* @__PURE__ */ jsx(
24688
24658
  AthenaWithThreadList,
24689
24659
  {
24690
- apiUrl,
24660
+ apiUrl: effectiveApiUrl,
24691
24661
  backendUrl: effectiveBackendUrl,
24692
24662
  apiKey,
24693
24663
  token: effectiveToken,
@@ -24706,7 +24676,7 @@ function AthenaProvider({
24706
24676
  inner = /* @__PURE__ */ jsx(
24707
24677
  AthenaStandalone,
24708
24678
  {
24709
- apiUrl,
24679
+ apiUrl: effectiveApiUrl,
24710
24680
  backendUrl: effectiveBackendUrl,
24711
24681
  apiKey,
24712
24682
  token: effectiveToken,
@@ -60494,7 +60464,7 @@ function AttachmentProvider({ children }) {
60494
60464
  const clearAttachments = useCallback(() => setAttachments([]), []);
60495
60465
  const value = useMemo(
60496
60466
  () => ({ attachments, addAttachments, removeAttachment, clearAttachments, isUploading, setIsUploading }),
60497
- [attachments, addAttachments, removeAttachment, clearAttachments, isUploading]
60467
+ [attachments, addAttachments, removeAttachment, clearAttachments, isUploading, setIsUploading]
60498
60468
  );
60499
60469
  return /* @__PURE__ */ jsx(AttachmentCtx.Provider, { value, children });
60500
60470
  }
@@ -60509,6 +60479,66 @@ function buildAttachmentMarkdown(attachments) {
60509
60479
  if (attachments.length === 0) return "";
60510
60480
  return attachments.map((a) => `[@${a.title}](https://app.athenaintel.com/dashboard/spaces?asset_id=${a.id})`).join("\n");
60511
60481
  }
60482
+ const QuoteCtx = createContext(null);
60483
+ function QuoteProvider({ children }) {
60484
+ const [quote, setQuote] = useState(null);
60485
+ const clearQuote = useCallback(() => setQuote(null), []);
60486
+ const value = useMemo(() => ({ quote, setQuote, clearQuote }), [quote, setQuote, clearQuote]);
60487
+ return /* @__PURE__ */ jsx(QuoteCtx.Provider, { value, children });
60488
+ }
60489
+ function useQuote() {
60490
+ const ctx = useContext(QuoteCtx);
60491
+ if (!ctx) {
60492
+ throw new Error("[AthenaSDK] useQuote must be used within <QuoteProvider>");
60493
+ }
60494
+ return ctx;
60495
+ }
60496
+ function useQuoteFromPostMessage() {
60497
+ const { setQuote } = useQuote();
60498
+ useEffect(() => {
60499
+ const handleKeydown = (e) => {
60500
+ var _a2;
60501
+ if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === "l") {
60502
+ const sel = window.getSelection();
60503
+ const selection = (_a2 = sel == null ? void 0 : sel.toString()) == null ? void 0 : _a2.trim();
60504
+ if (selection && selection.length > 0) {
60505
+ e.preventDefault();
60506
+ let messageId;
60507
+ let role;
60508
+ let node = sel == null ? void 0 : sel.anchorNode;
60509
+ while (node && node !== document.body) {
60510
+ if (node instanceof HTMLElement) {
60511
+ const dataRole = node.getAttribute("data-role");
60512
+ if (dataRole === "assistant" || dataRole === "user") {
60513
+ role = dataRole;
60514
+ messageId = node.getAttribute("data-message-id") ?? void 0;
60515
+ break;
60516
+ }
60517
+ }
60518
+ node = node.parentElement;
60519
+ }
60520
+ setQuote({ text: selection, sourceRole: role, sourceMessageId: messageId });
60521
+ }
60522
+ }
60523
+ };
60524
+ const handleMessage = (event) => {
60525
+ const data = event.data;
60526
+ if (data && typeof data === "object" && data.type === "athena-add-to-composer" && typeof data.text === "string" && data.text.trim().length > 0) {
60527
+ setQuote({
60528
+ text: data.text,
60529
+ sourceTitle: data.sourceTitle,
60530
+ sourceAssetId: data.sourceAssetId
60531
+ });
60532
+ }
60533
+ };
60534
+ document.addEventListener("keydown", handleKeydown, true);
60535
+ window.addEventListener("message", handleMessage);
60536
+ return () => {
60537
+ document.removeEventListener("keydown", handleKeydown, true);
60538
+ window.removeEventListener("message", handleMessage);
60539
+ };
60540
+ }, [setQuote]);
60541
+ }
60512
60542
  function buildComposedMessage(opts) {
60513
60543
  var _a2;
60514
60544
  const parts = [];
@@ -60561,15 +60591,17 @@ const TiptapComposer = ({ tools = [] }) => {
60561
60591
  role: "user",
60562
60592
  content: [{ type: "text", text: fullMessage }]
60563
60593
  });
60594
+ clearAttachments();
60595
+ clearQuote();
60564
60596
  }
60565
- clearAttachments();
60566
- clearQuote();
60567
60597
  } else {
60568
60598
  composerRuntime.setText(markdown);
60569
60599
  composerRuntime.send();
60570
60600
  }
60571
60601
  editor2.commands.clearContent();
60572
60602
  }, [aui, composerRuntime, clearAttachments, clearQuote]);
60603
+ const handleSubmitRef = useRef(handleSubmit);
60604
+ handleSubmitRef.current = handleSubmit;
60573
60605
  const editor = useEditor({
60574
60606
  immediatelyRender: true,
60575
60607
  extensions: [
@@ -60600,7 +60632,7 @@ const TiptapComposer = ({ tools = [] }) => {
60600
60632
  store: mentionStore
60601
60633
  }),
60602
60634
  ComposerKeybinds.configure({
60603
- onSubmit: () => handleSubmit()
60635
+ onSubmit: () => handleSubmitRef.current()
60604
60636
  })
60605
60637
  ],
60606
60638
  editorProps: {
@@ -63580,8 +63612,8 @@ const ComposerDropZone = ({
63580
63612
  onUpload
63581
63613
  }) => {
63582
63614
  const [isDragOver, setIsDragOver] = useState(false);
63583
- const { upload, isUploading } = useFileUpload();
63584
- const { addAttachments, setIsUploading } = useAttachments();
63615
+ const { upload } = useFileUpload();
63616
+ const { addAttachments, setIsUploading, isUploading } = useAttachments();
63585
63617
  const handleDragOver = useCallback((e) => {
63586
63618
  e.preventDefault();
63587
63619
  e.stopPropagation();
@@ -63634,6 +63666,10 @@ const ComposerDropZone = ({
63634
63666
  );
63635
63667
  };
63636
63668
  const EMPTY_MENTION_TOOLS = [];
63669
+ function QuotePostMessageBridge() {
63670
+ useQuoteFromPostMessage();
63671
+ return null;
63672
+ }
63637
63673
  const DEFAULT_SUGGESTIONS = [
63638
63674
  {
63639
63675
  icon: Search,
@@ -63732,12 +63768,15 @@ const AthenaChat = ({
63732
63768
  ),
63733
63769
  /* @__PURE__ */ jsxs(ThreadPrimitiveViewportFooter, { className: "aui-thread-viewport-footer sticky bottom-0 mx-auto mt-auto flex w-full max-w-(--thread-max-width) flex-col gap-4 overflow-visible rounded-t-3xl bg-background pb-4 md:pb-6", children: [
63734
63770
  /* @__PURE__ */ jsx(ThreadScrollToBottom, {}),
63735
- /* @__PURE__ */ jsx(AttachmentProvider, { children: /* @__PURE__ */ jsx(ComposerEditorProvider, { children: /* @__PURE__ */ jsx(ComposerDropZone, { children: /* @__PURE__ */ jsxs(ComposerPrimitiveRoot, { className: "aui-composer-root relative flex w-full flex-col rounded-2xl border border-input bg-background px-1 outline-none transition-shadow focus-within:border-ring focus-within:ring-2 focus-within:ring-ring/20", children: [
63736
- /* @__PURE__ */ jsx(ComposerQuotePreview, {}),
63737
- /* @__PURE__ */ jsx(ComposerAttachmentPreview, {}),
63738
- /* @__PURE__ */ jsx(TiptapComposer, { tools }),
63739
- /* @__PURE__ */ jsx(ComposerAction, {})
63740
- ] }) }) }) })
63771
+ /* @__PURE__ */ jsx(AttachmentProvider, { children: /* @__PURE__ */ jsx(ComposerEditorProvider, { children: /* @__PURE__ */ jsxs(QuoteProvider, { children: [
63772
+ /* @__PURE__ */ jsx(QuotePostMessageBridge, {}),
63773
+ /* @__PURE__ */ jsx(ComposerDropZone, { children: /* @__PURE__ */ jsxs(ComposerPrimitiveRoot, { className: "aui-composer-root relative flex w-full flex-col rounded-2xl border border-input bg-background px-1 pt-2 outline-none transition-shadow focus-within:border-ring focus-within:ring-2 focus-within:ring-ring/20", children: [
63774
+ /* @__PURE__ */ jsx(ComposerQuotePreview, {}),
63775
+ /* @__PURE__ */ jsx(ComposerAttachmentPreview, {}),
63776
+ /* @__PURE__ */ jsx(TiptapComposer, { tools }),
63777
+ /* @__PURE__ */ jsx(ComposerAction, {})
63778
+ ] }) })
63779
+ ] }) }) })
63741
63780
  ] })
63742
63781
  ]
63743
63782
  }
@@ -63794,6 +63833,7 @@ const ComposerSendWithQuote = () => {
63794
63833
  var _a2;
63795
63834
  if (isUploading) return;
63796
63835
  const editor = editorRef.current;
63836
+ if (!editor && !quote && attachments.length === 0) return;
63797
63837
  const userText = ((_a2 = editor == null ? void 0 : editor.getMarkdown()) == null ? void 0 : _a2.trim()) ?? "";
63798
63838
  const fullMessage = buildComposedMessage({
63799
63839
  attachments,
@@ -64388,6 +64428,7 @@ export {
64388
64428
  CreateNotebookToolUI,
64389
64429
  CreatePresentationToolUI,
64390
64430
  CreateSheetToolUI,
64431
+ DEFAULT_API_URL,
64391
64432
  DEFAULT_BACKEND_URL,
64392
64433
  EmailSearchToolUI,
64393
64434
  ExpandableSection,
@@ -64435,6 +64476,7 @@ export {
64435
64476
  useFileUpload,
64436
64477
  useMentionSuggestions,
64437
64478
  useParentAuth,
64479
+ useParentBridge,
64438
64480
  useQuote
64439
64481
  };
64440
64482
  //# sourceMappingURL=index.js.map