@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.cjs CHANGED
@@ -16483,24 +16483,60 @@ function isTrustedOrigin(origin) {
16483
16483
  return false;
16484
16484
  }
16485
16485
  }
16486
- function useParentAuth() {
16487
- const [authToken, setAuthToken] = React.useState(null);
16486
+ const BRIDGE_TIMEOUT_MS = 2e3;
16487
+ function useParentBridge() {
16488
+ const isInIframe = typeof window !== "undefined" && window.parent !== window;
16489
+ const [state, setState] = React.useState({
16490
+ token: null,
16491
+ apiUrl: null,
16492
+ backendUrl: null,
16493
+ // If not in an iframe, we're ready immediately (standalone mode)
16494
+ ready: !isInIframe
16495
+ });
16488
16496
  const readySignalSent = React.useRef(false);
16497
+ const configReceived = React.useRef(false);
16489
16498
  React.useEffect(() => {
16499
+ if (!isInIframe) return;
16490
16500
  const handler = (event) => {
16491
16501
  if (!isTrustedOrigin(event.origin)) return;
16492
- if (event.data && typeof event.data === "object" && event.data.type === "athena-auth" && typeof event.data.token === "string") {
16493
- setAuthToken(event.data.token);
16502
+ if (!event.data || typeof event.data !== "object") return;
16503
+ if (event.data.type === "athena-config") {
16504
+ configReceived.current = true;
16505
+ setState((prev) => ({
16506
+ ...prev,
16507
+ apiUrl: typeof event.data.apiUrl === "string" ? event.data.apiUrl : prev.apiUrl,
16508
+ backendUrl: typeof event.data.backendUrl === "string" ? event.data.backendUrl : prev.backendUrl,
16509
+ ready: true
16510
+ }));
16511
+ }
16512
+ if (event.data.type === "athena-auth" && typeof event.data.token === "string") {
16513
+ setState((prev) => ({
16514
+ ...prev,
16515
+ token: event.data.token,
16516
+ // If we got a token, we're ready even without config
16517
+ ready: true
16518
+ }));
16494
16519
  }
16495
16520
  };
16496
16521
  window.addEventListener("message", handler);
16497
- if (!readySignalSent.current && window.parent !== window) {
16522
+ if (!readySignalSent.current) {
16498
16523
  window.parent.postMessage({ type: "athena-auth-ready" }, "*");
16499
16524
  readySignalSent.current = true;
16500
16525
  }
16501
- return () => window.removeEventListener("message", handler);
16502
- }, []);
16503
- return authToken;
16526
+ const timer = setTimeout(() => {
16527
+ if (!configReceived.current) {
16528
+ setState((prev) => ({ ...prev, ready: true }));
16529
+ }
16530
+ }, BRIDGE_TIMEOUT_MS);
16531
+ return () => {
16532
+ window.removeEventListener("message", handler);
16533
+ clearTimeout(timer);
16534
+ };
16535
+ }, [isInIframe]);
16536
+ return state;
16537
+ }
16538
+ function useParentAuth() {
16539
+ return useParentBridge().token;
16504
16540
  }
16505
16541
  const { fromThreadMessageLike, getAutoStatus } = INTERNAL;
16506
16542
  const joinExternalMessages = (messages) => {
@@ -24491,70 +24527,6 @@ const themes = {
24491
24527
  radius: "0.625rem"
24492
24528
  }
24493
24529
  };
24494
- const QuoteCtx = React.createContext(null);
24495
- function QuoteProvider({ children }) {
24496
- const [quote, setQuote] = React.useState(null);
24497
- const clearQuote = React.useCallback(() => setQuote(null), []);
24498
- const value = React.useMemo(() => ({ quote, setQuote, clearQuote }), [quote, setQuote, clearQuote]);
24499
- return /* @__PURE__ */ jsxRuntime.jsx(QuoteCtx.Provider, { value, children });
24500
- }
24501
- function useQuote() {
24502
- const ctx = React.useContext(QuoteCtx);
24503
- if (!ctx) {
24504
- throw new Error("[AthenaSDK] useQuote must be used within <QuoteProvider>");
24505
- }
24506
- return ctx;
24507
- }
24508
- function useQuoteFromPostMessage() {
24509
- const { setQuote } = useQuote();
24510
- React.useEffect(() => {
24511
- const handleKeydown = (e) => {
24512
- var _a2;
24513
- if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === "l") {
24514
- const sel = window.getSelection();
24515
- const selection = (_a2 = sel == null ? void 0 : sel.toString()) == null ? void 0 : _a2.trim();
24516
- if (selection && selection.length > 0) {
24517
- e.preventDefault();
24518
- let messageId;
24519
- let role;
24520
- let node = sel == null ? void 0 : sel.anchorNode;
24521
- while (node && node !== document.body) {
24522
- if (node instanceof HTMLElement) {
24523
- const dataRole = node.getAttribute("data-role");
24524
- if (dataRole === "assistant" || dataRole === "user") {
24525
- role = dataRole;
24526
- messageId = node.getAttribute("data-message-id") ?? void 0;
24527
- break;
24528
- }
24529
- }
24530
- node = node.parentElement;
24531
- }
24532
- setQuote({ text: selection, sourceRole: role, sourceMessageId: messageId });
24533
- }
24534
- }
24535
- };
24536
- const handleMessage = (event) => {
24537
- const data = event.data;
24538
- if (data && typeof data === "object" && data.type === "athena-add-to-composer" && typeof data.text === "string" && data.text.trim().length > 0) {
24539
- setQuote({
24540
- text: data.text,
24541
- sourceTitle: data.sourceTitle,
24542
- sourceAssetId: data.sourceAssetId
24543
- });
24544
- }
24545
- };
24546
- document.addEventListener("keydown", handleKeydown, true);
24547
- window.addEventListener("message", handleMessage);
24548
- return () => {
24549
- document.removeEventListener("keydown", handleKeydown, true);
24550
- window.removeEventListener("message", handleMessage);
24551
- };
24552
- }, [setQuote]);
24553
- }
24554
- function QuotePostMessageBridge() {
24555
- useQuoteFromPostMessage();
24556
- return null;
24557
- }
24558
24530
  function AthenaStandalone({
24559
24531
  children,
24560
24532
  apiUrl,
@@ -24591,10 +24563,7 @@ function AthenaStandalone({
24591
24563
  () => ({ backendUrl, apiKey, token }),
24592
24564
  [backendUrl, apiKey, token]
24593
24565
  );
24594
- return /* @__PURE__ */ jsxRuntime.jsx(AssistantRuntimeProvider, { aui, runtime, children: /* @__PURE__ */ jsxRuntime.jsx(AthenaContext.Provider, { value: athenaConfig, children: /* @__PURE__ */ jsxRuntime.jsxs(QuoteProvider, { children: [
24595
- /* @__PURE__ */ jsxRuntime.jsx(QuotePostMessageBridge, {}),
24596
- /* @__PURE__ */ jsxRuntime.jsx(TooltipProvider, { children })
24597
- ] }) }) });
24566
+ return /* @__PURE__ */ jsxRuntime.jsx(AssistantRuntimeProvider, { aui, runtime, children: /* @__PURE__ */ jsxRuntime.jsx(AthenaContext.Provider, { value: athenaConfig, children: /* @__PURE__ */ jsxRuntime.jsx(TooltipProvider, { children }) }) });
24598
24567
  }
24599
24568
  function useAthenaRuntimeHook(config2) {
24600
24569
  const remoteId = useAthenaThreadId();
@@ -24673,10 +24642,7 @@ function AthenaWithThreadList({
24673
24642
  () => ({ backendUrl, apiKey, token }),
24674
24643
  [backendUrl, apiKey, token]
24675
24644
  );
24676
- return /* @__PURE__ */ jsxRuntime.jsx(AssistantRuntimeProvider, { aui, runtime, children: /* @__PURE__ */ jsxRuntime.jsx(AthenaContext.Provider, { value: athenaConfig, children: /* @__PURE__ */ jsxRuntime.jsxs(QuoteProvider, { children: [
24677
- /* @__PURE__ */ jsxRuntime.jsx(QuotePostMessageBridge, {}),
24678
- /* @__PURE__ */ jsxRuntime.jsx(TooltipProvider, { children })
24679
- ] }) }) });
24645
+ return /* @__PURE__ */ jsxRuntime.jsx(AssistantRuntimeProvider, { aui, runtime, children: /* @__PURE__ */ jsxRuntime.jsx(AthenaContext.Provider, { value: athenaConfig, children: /* @__PURE__ */ jsxRuntime.jsx(TooltipProvider, { children }) }) });
24680
24646
  }
24681
24647
  function AthenaProvider({
24682
24648
  children,
@@ -24697,15 +24663,19 @@ function AthenaProvider({
24697
24663
  }) {
24698
24664
  const frontendToolNames = React.useMemo(() => Object.keys(frontendTools), [frontendTools]);
24699
24665
  const themeStyleVars = React.useMemo(() => theme ? themeToStyleVars(theme) : void 0, [theme]);
24700
- const parentAuthToken = useParentAuth();
24701
- const effectiveToken = tokenProp ?? parentAuthToken;
24702
- const effectiveBackendUrl = backendUrl ?? DEFAULT_BACKEND_URL;
24666
+ const bridge = useParentBridge();
24667
+ const effectiveToken = tokenProp ?? bridge.token;
24668
+ const effectiveApiUrl = apiUrl ?? bridge.apiUrl ?? DEFAULT_API_URL;
24669
+ const effectiveBackendUrl = backendUrl ?? bridge.backendUrl ?? DEFAULT_BACKEND_URL;
24670
+ if (!bridge.ready) {
24671
+ return null;
24672
+ }
24703
24673
  let inner;
24704
24674
  if (enableThreadList) {
24705
24675
  inner = /* @__PURE__ */ jsxRuntime.jsx(
24706
24676
  AthenaWithThreadList,
24707
24677
  {
24708
- apiUrl,
24678
+ apiUrl: effectiveApiUrl,
24709
24679
  backendUrl: effectiveBackendUrl,
24710
24680
  apiKey,
24711
24681
  token: effectiveToken,
@@ -24724,7 +24694,7 @@ function AthenaProvider({
24724
24694
  inner = /* @__PURE__ */ jsxRuntime.jsx(
24725
24695
  AthenaStandalone,
24726
24696
  {
24727
- apiUrl,
24697
+ apiUrl: effectiveApiUrl,
24728
24698
  backendUrl: effectiveBackendUrl,
24729
24699
  apiKey,
24730
24700
  token: effectiveToken,
@@ -60512,7 +60482,7 @@ function AttachmentProvider({ children }) {
60512
60482
  const clearAttachments = React.useCallback(() => setAttachments([]), []);
60513
60483
  const value = React.useMemo(
60514
60484
  () => ({ attachments, addAttachments, removeAttachment, clearAttachments, isUploading, setIsUploading }),
60515
- [attachments, addAttachments, removeAttachment, clearAttachments, isUploading]
60485
+ [attachments, addAttachments, removeAttachment, clearAttachments, isUploading, setIsUploading]
60516
60486
  );
60517
60487
  return /* @__PURE__ */ jsxRuntime.jsx(AttachmentCtx.Provider, { value, children });
60518
60488
  }
@@ -60527,6 +60497,66 @@ function buildAttachmentMarkdown(attachments) {
60527
60497
  if (attachments.length === 0) return "";
60528
60498
  return attachments.map((a) => `[@${a.title}](https://app.athenaintel.com/dashboard/spaces?asset_id=${a.id})`).join("\n");
60529
60499
  }
60500
+ const QuoteCtx = React.createContext(null);
60501
+ function QuoteProvider({ children }) {
60502
+ const [quote, setQuote] = React.useState(null);
60503
+ const clearQuote = React.useCallback(() => setQuote(null), []);
60504
+ const value = React.useMemo(() => ({ quote, setQuote, clearQuote }), [quote, setQuote, clearQuote]);
60505
+ return /* @__PURE__ */ jsxRuntime.jsx(QuoteCtx.Provider, { value, children });
60506
+ }
60507
+ function useQuote() {
60508
+ const ctx = React.useContext(QuoteCtx);
60509
+ if (!ctx) {
60510
+ throw new Error("[AthenaSDK] useQuote must be used within <QuoteProvider>");
60511
+ }
60512
+ return ctx;
60513
+ }
60514
+ function useQuoteFromPostMessage() {
60515
+ const { setQuote } = useQuote();
60516
+ React.useEffect(() => {
60517
+ const handleKeydown = (e) => {
60518
+ var _a2;
60519
+ if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === "l") {
60520
+ const sel = window.getSelection();
60521
+ const selection = (_a2 = sel == null ? void 0 : sel.toString()) == null ? void 0 : _a2.trim();
60522
+ if (selection && selection.length > 0) {
60523
+ e.preventDefault();
60524
+ let messageId;
60525
+ let role;
60526
+ let node = sel == null ? void 0 : sel.anchorNode;
60527
+ while (node && node !== document.body) {
60528
+ if (node instanceof HTMLElement) {
60529
+ const dataRole = node.getAttribute("data-role");
60530
+ if (dataRole === "assistant" || dataRole === "user") {
60531
+ role = dataRole;
60532
+ messageId = node.getAttribute("data-message-id") ?? void 0;
60533
+ break;
60534
+ }
60535
+ }
60536
+ node = node.parentElement;
60537
+ }
60538
+ setQuote({ text: selection, sourceRole: role, sourceMessageId: messageId });
60539
+ }
60540
+ }
60541
+ };
60542
+ const handleMessage = (event) => {
60543
+ const data = event.data;
60544
+ if (data && typeof data === "object" && data.type === "athena-add-to-composer" && typeof data.text === "string" && data.text.trim().length > 0) {
60545
+ setQuote({
60546
+ text: data.text,
60547
+ sourceTitle: data.sourceTitle,
60548
+ sourceAssetId: data.sourceAssetId
60549
+ });
60550
+ }
60551
+ };
60552
+ document.addEventListener("keydown", handleKeydown, true);
60553
+ window.addEventListener("message", handleMessage);
60554
+ return () => {
60555
+ document.removeEventListener("keydown", handleKeydown, true);
60556
+ window.removeEventListener("message", handleMessage);
60557
+ };
60558
+ }, [setQuote]);
60559
+ }
60530
60560
  function buildComposedMessage(opts) {
60531
60561
  var _a2;
60532
60562
  const parts = [];
@@ -60579,15 +60609,17 @@ const TiptapComposer = ({ tools = [] }) => {
60579
60609
  role: "user",
60580
60610
  content: [{ type: "text", text: fullMessage }]
60581
60611
  });
60612
+ clearAttachments();
60613
+ clearQuote();
60582
60614
  }
60583
- clearAttachments();
60584
- clearQuote();
60585
60615
  } else {
60586
60616
  composerRuntime.setText(markdown);
60587
60617
  composerRuntime.send();
60588
60618
  }
60589
60619
  editor2.commands.clearContent();
60590
60620
  }, [aui, composerRuntime, clearAttachments, clearQuote]);
60621
+ const handleSubmitRef = React.useRef(handleSubmit);
60622
+ handleSubmitRef.current = handleSubmit;
60591
60623
  const editor = useEditor({
60592
60624
  immediatelyRender: true,
60593
60625
  extensions: [
@@ -60618,7 +60650,7 @@ const TiptapComposer = ({ tools = [] }) => {
60618
60650
  store: mentionStore
60619
60651
  }),
60620
60652
  ComposerKeybinds.configure({
60621
- onSubmit: () => handleSubmit()
60653
+ onSubmit: () => handleSubmitRef.current()
60622
60654
  })
60623
60655
  ],
60624
60656
  editorProps: {
@@ -63598,8 +63630,8 @@ const ComposerDropZone = ({
63598
63630
  onUpload
63599
63631
  }) => {
63600
63632
  const [isDragOver, setIsDragOver] = React.useState(false);
63601
- const { upload, isUploading } = useFileUpload();
63602
- const { addAttachments, setIsUploading } = useAttachments();
63633
+ const { upload } = useFileUpload();
63634
+ const { addAttachments, setIsUploading, isUploading } = useAttachments();
63603
63635
  const handleDragOver = React.useCallback((e) => {
63604
63636
  e.preventDefault();
63605
63637
  e.stopPropagation();
@@ -63652,6 +63684,10 @@ const ComposerDropZone = ({
63652
63684
  );
63653
63685
  };
63654
63686
  const EMPTY_MENTION_TOOLS = [];
63687
+ function QuotePostMessageBridge() {
63688
+ useQuoteFromPostMessage();
63689
+ return null;
63690
+ }
63655
63691
  const DEFAULT_SUGGESTIONS = [
63656
63692
  {
63657
63693
  icon: Search,
@@ -63750,12 +63786,15 @@ const AthenaChat = ({
63750
63786
  ),
63751
63787
  /* @__PURE__ */ jsxRuntime.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: [
63752
63788
  /* @__PURE__ */ jsxRuntime.jsx(ThreadScrollToBottom, {}),
63753
- /* @__PURE__ */ jsxRuntime.jsx(AttachmentProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(ComposerEditorProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(ComposerDropZone, { children: /* @__PURE__ */ jsxRuntime.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: [
63754
- /* @__PURE__ */ jsxRuntime.jsx(ComposerQuotePreview, {}),
63755
- /* @__PURE__ */ jsxRuntime.jsx(ComposerAttachmentPreview, {}),
63756
- /* @__PURE__ */ jsxRuntime.jsx(TiptapComposer, { tools }),
63757
- /* @__PURE__ */ jsxRuntime.jsx(ComposerAction, {})
63758
- ] }) }) }) })
63789
+ /* @__PURE__ */ jsxRuntime.jsx(AttachmentProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(ComposerEditorProvider, { children: /* @__PURE__ */ jsxRuntime.jsxs(QuoteProvider, { children: [
63790
+ /* @__PURE__ */ jsxRuntime.jsx(QuotePostMessageBridge, {}),
63791
+ /* @__PURE__ */ jsxRuntime.jsx(ComposerDropZone, { children: /* @__PURE__ */ jsxRuntime.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: [
63792
+ /* @__PURE__ */ jsxRuntime.jsx(ComposerQuotePreview, {}),
63793
+ /* @__PURE__ */ jsxRuntime.jsx(ComposerAttachmentPreview, {}),
63794
+ /* @__PURE__ */ jsxRuntime.jsx(TiptapComposer, { tools }),
63795
+ /* @__PURE__ */ jsxRuntime.jsx(ComposerAction, {})
63796
+ ] }) })
63797
+ ] }) }) })
63759
63798
  ] })
63760
63799
  ]
63761
63800
  }
@@ -63812,6 +63851,7 @@ const ComposerSendWithQuote = () => {
63812
63851
  var _a2;
63813
63852
  if (isUploading) return;
63814
63853
  const editor = editorRef.current;
63854
+ if (!editor && !quote && attachments.length === 0) return;
63815
63855
  const userText = ((_a2 = editor == null ? void 0 : editor.getMarkdown()) == null ? void 0 : _a2.trim()) ?? "";
63816
63856
  const fullMessage = buildComposedMessage({
63817
63857
  attachments,
@@ -64405,6 +64445,7 @@ exports.CreateEmailDraftToolUI = CreateEmailDraftToolUI;
64405
64445
  exports.CreateNotebookToolUI = CreateNotebookToolUI;
64406
64446
  exports.CreatePresentationToolUI = CreatePresentationToolUI;
64407
64447
  exports.CreateSheetToolUI = CreateSheetToolUI;
64448
+ exports.DEFAULT_API_URL = DEFAULT_API_URL;
64408
64449
  exports.DEFAULT_BACKEND_URL = DEFAULT_BACKEND_URL;
64409
64450
  exports.EmailSearchToolUI = EmailSearchToolUI;
64410
64451
  exports.ExpandableSection = ExpandableSection;
@@ -64452,5 +64493,6 @@ exports.useComposerAttachment = useComposerAttachment;
64452
64493
  exports.useFileUpload = useFileUpload;
64453
64494
  exports.useMentionSuggestions = useMentionSuggestions;
64454
64495
  exports.useParentAuth = useParentAuth;
64496
+ exports.useParentBridge = useParentBridge;
64455
64497
  exports.useQuote = useQuote;
64456
64498
  //# sourceMappingURL=index.cjs.map