@athenaintel/react 0.9.5 → 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/README.md CHANGED
@@ -26,6 +26,24 @@ function App() {
26
26
  }
27
27
  ```
28
28
 
29
+ ## Environment And URLs
30
+
31
+ ```tsx
32
+ <AthenaProvider environment="staging">
33
+ <AthenaChat />
34
+ </AthenaProvider>
35
+
36
+ <AthenaProvider
37
+ apiUrl="https://sync.example.com/api/chat"
38
+ backendUrl="https://api.example.com/api/assistant-ui"
39
+ appUrl="https://app.example.com"
40
+ >
41
+ <AthenaChat />
42
+ </AthenaProvider>
43
+ ```
44
+
45
+ If `appUrl` is omitted, the provider now resolves it from the parent bridge or from the matching Athena environment defaults. Known Athena staging/prod `apiUrl` and `backendUrl` values automatically fall back to the corresponding frontend origin.
46
+
29
47
  ## Theming
30
48
 
31
49
  ```tsx
package/dist/index.cjs CHANGED
@@ -16475,6 +16475,106 @@ const INTERNAL = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProp
16475
16475
  useSmoothStatus,
16476
16476
  useToolInvocations
16477
16477
  }, Symbol.toStringTag, { value: "Module" }));
16478
+ const ATHENA_ENVIRONMENT_URLS = {
16479
+ production: {
16480
+ apiUrl: "https://sync.athenaintel.com/api/chat",
16481
+ backendUrl: "https://api.athenaintel.com/api/assistant-ui",
16482
+ appUrl: "https://app.athenaintel.com"
16483
+ },
16484
+ staging: {
16485
+ apiUrl: "https://staging-sync.athenaintel.com/api/chat",
16486
+ backendUrl: "https://staging-api.athenaintel.com/api/assistant-ui",
16487
+ appUrl: "https://staging-app.athenaintel.com"
16488
+ }
16489
+ };
16490
+ const DEFAULT_ATHENA_ENVIRONMENT = "production";
16491
+ const DEFAULT_API_URL = ATHENA_ENVIRONMENT_URLS.production.apiUrl;
16492
+ const DEFAULT_BACKEND_URL = ATHENA_ENVIRONMENT_URLS.production.backendUrl;
16493
+ const DEFAULT_APP_URL = ATHENA_ENVIRONMENT_URLS.production.appUrl;
16494
+ const SPACES_PATHNAME = "/dashboard/spaces/";
16495
+ const normalizeBaseUrl = (url) => url.replace(/\/+$/, "");
16496
+ const getHostname = (value) => {
16497
+ if (!value) return null;
16498
+ try {
16499
+ return new URL(value).hostname;
16500
+ } catch {
16501
+ return null;
16502
+ }
16503
+ };
16504
+ const deriveWorkspaceAppUrl = ({
16505
+ sourceUrl,
16506
+ sourcePort
16507
+ }) => {
16508
+ var _a2;
16509
+ try {
16510
+ const parsedUrl = new URL(sourceUrl);
16511
+ const match2 = parsedUrl.hostname.match(
16512
+ new RegExp(`^(?<prefix>.+)--${sourcePort}\\.(?<domain>app\\.athenaintel\\.com|staging-app\\.athenaintel\\.com)$`)
16513
+ );
16514
+ if (!((_a2 = match2 == null ? void 0 : match2.groups) == null ? void 0 : _a2.prefix) || !match2.groups.domain) {
16515
+ return null;
16516
+ }
16517
+ return `${parsedUrl.protocol}//${match2.groups.prefix}--8082.${match2.groups.domain}`;
16518
+ } catch {
16519
+ return null;
16520
+ }
16521
+ };
16522
+ function getAthenaEnvironmentUrls({
16523
+ environment = DEFAULT_ATHENA_ENVIRONMENT
16524
+ } = {}) {
16525
+ return ATHENA_ENVIRONMENT_URLS[environment];
16526
+ }
16527
+ function deriveAthenaAppUrl({
16528
+ apiUrl,
16529
+ backendUrl
16530
+ }) {
16531
+ if (backendUrl) {
16532
+ const workspaceAppUrl = deriveWorkspaceAppUrl({
16533
+ sourceUrl: backendUrl,
16534
+ sourcePort: "8000"
16535
+ });
16536
+ if (workspaceAppUrl) return workspaceAppUrl;
16537
+ const backendHostname = getHostname(backendUrl);
16538
+ if (backendHostname === "api.athenaintel.com") {
16539
+ return ATHENA_ENVIRONMENT_URLS.production.appUrl;
16540
+ }
16541
+ if (backendHostname === "staging-api.athenaintel.com") {
16542
+ return ATHENA_ENVIRONMENT_URLS.staging.appUrl;
16543
+ }
16544
+ }
16545
+ if (apiUrl) {
16546
+ const workspaceAppUrl = deriveWorkspaceAppUrl({
16547
+ sourceUrl: apiUrl,
16548
+ sourcePort: "8787"
16549
+ });
16550
+ if (workspaceAppUrl) return workspaceAppUrl;
16551
+ const apiHostname = getHostname(apiUrl);
16552
+ if (apiHostname === "sync.athenaintel.com") {
16553
+ return ATHENA_ENVIRONMENT_URLS.production.appUrl;
16554
+ }
16555
+ if (apiHostname === "staging-sync.athenaintel.com") {
16556
+ return ATHENA_ENVIRONMENT_URLS.staging.appUrl;
16557
+ }
16558
+ }
16559
+ return null;
16560
+ }
16561
+ function createAthenaSpacesUrl({
16562
+ appUrl = DEFAULT_APP_URL,
16563
+ assetIds,
16564
+ sessionId
16565
+ }) {
16566
+ const url = new URL(SPACES_PATHNAME, `${normalizeBaseUrl(appUrl)}/`);
16567
+ if (assetIds) {
16568
+ const normalizedAssetIds = (Array.isArray(assetIds) ? assetIds : [assetIds]).map((assetId) => assetId.trim()).filter((assetId) => assetId.length > 0);
16569
+ if (normalizedAssetIds.length > 0) {
16570
+ url.searchParams.set("asset_ids", normalizedAssetIds.join(","));
16571
+ }
16572
+ }
16573
+ if (sessionId) {
16574
+ url.searchParams.set("session_id", sessionId);
16575
+ }
16576
+ return url.toString();
16577
+ }
16478
16578
  function isTrustedOrigin(origin) {
16479
16579
  try {
16480
16580
  const { hostname } = new URL(origin);
@@ -16490,6 +16590,7 @@ function useParentBridge() {
16490
16590
  token: null,
16491
16591
  apiUrl: null,
16492
16592
  backendUrl: null,
16593
+ appUrl: null,
16493
16594
  // If not in an iframe, we're ready immediately (standalone mode)
16494
16595
  ready: !isInIframe
16495
16596
  });
@@ -16505,7 +16606,8 @@ function useParentBridge() {
16505
16606
  setState((prev) => ({
16506
16607
  ...prev,
16507
16608
  apiUrl: typeof event.data.apiUrl === "string" ? event.data.apiUrl : prev.apiUrl,
16508
- backendUrl: typeof event.data.backendUrl === "string" ? event.data.backendUrl : prev.backendUrl
16609
+ backendUrl: typeof event.data.backendUrl === "string" ? event.data.backendUrl : prev.backendUrl,
16610
+ appUrl: typeof event.data.appUrl === "string" ? event.data.appUrl : prev.appUrl
16509
16611
  // Don't set ready here — wait for athena-auth (token) or the timeout.
16510
16612
  // Setting ready on config alone causes a race: the thread list fires
16511
16613
  // before the token arrives, falling back to X-API-KEY.
@@ -20737,8 +20839,6 @@ async function archiveThread(backendUrl, auth, threadId) {
20737
20839
  throw new Error(`[AthenaSDK] Failed to archive thread: ${res.status}`);
20738
20840
  }
20739
20841
  }
20740
- const DEFAULT_API_URL = "https://sync.athenaintel.com/api/chat";
20741
- const DEFAULT_BACKEND_URL = "https://api.athenaintel.com/api/assistant-ui";
20742
20842
  const DEFAULT_MODEL = "claude-opus-4-6-thinking-max-fast";
20743
20843
  const DEFAULT_AGENT = "athena_assist_agent";
20744
20844
  const ATHENA_TRACKING_ID_KEY = "_athena_tracking_id";
@@ -24547,6 +24647,7 @@ function AthenaStandalone({
24547
24647
  children,
24548
24648
  apiUrl,
24549
24649
  backendUrl,
24650
+ appUrl,
24550
24651
  apiKey,
24551
24652
  token,
24552
24653
  model,
@@ -24576,8 +24677,8 @@ function AthenaStandalone({
24576
24677
  threadId
24577
24678
  });
24578
24679
  const athenaConfig = React.useMemo(
24579
- () => ({ backendUrl, apiKey, token }),
24580
- [backendUrl, apiKey, token]
24680
+ () => ({ backendUrl, appUrl, apiKey, token }),
24681
+ [backendUrl, appUrl, apiKey, token]
24581
24682
  );
24582
24683
  return /* @__PURE__ */ jsxRuntime.jsx(AssistantRuntimeProvider, { aui, runtime, children: /* @__PURE__ */ jsxRuntime.jsx(AthenaContext.Provider, { value: athenaConfig, children: /* @__PURE__ */ jsxRuntime.jsx(TooltipProvider, { children }) }) });
24583
24684
  }
@@ -24602,6 +24703,7 @@ function AthenaWithThreadList({
24602
24703
  children,
24603
24704
  apiUrl,
24604
24705
  backendUrl,
24706
+ appUrl,
24605
24707
  apiKey,
24606
24708
  token,
24607
24709
  model,
@@ -24673,8 +24775,8 @@ function AthenaWithThreadList({
24673
24775
  const auiTools = React.useMemo(() => Tools({ toolkit: frontendTools }), [frontendTools]);
24674
24776
  const aui = useAui({ tools: auiTools });
24675
24777
  const athenaConfig = React.useMemo(
24676
- () => ({ backendUrl, apiKey, token }),
24677
- [backendUrl, apiKey, token]
24778
+ () => ({ backendUrl, appUrl, apiKey, token }),
24779
+ [backendUrl, appUrl, apiKey, token]
24678
24780
  );
24679
24781
  return /* @__PURE__ */ jsxRuntime.jsx(AssistantRuntimeProvider, { aui, runtime, children: /* @__PURE__ */ jsxRuntime.jsx(AthenaContext.Provider, { value: athenaConfig, children: /* @__PURE__ */ jsxRuntime.jsx(ThreadListRefreshContext.Provider, { value: handleRefresh, children: /* @__PURE__ */ jsxRuntime.jsx(TooltipProvider, { children }) }) }) });
24680
24782
  }
@@ -24688,6 +24790,8 @@ function AthenaProvider({
24688
24790
  frontendTools = {},
24689
24791
  apiUrl,
24690
24792
  backendUrl,
24793
+ appUrl,
24794
+ environment,
24691
24795
  workbench,
24692
24796
  knowledgeBase,
24693
24797
  systemPrompt,
@@ -24697,10 +24801,15 @@ function AthenaProvider({
24697
24801
  }) {
24698
24802
  const frontendToolNames = React.useMemo(() => Object.keys(frontendTools), [frontendTools]);
24699
24803
  const themeStyleVars = React.useMemo(() => theme ? themeToStyleVars(theme) : void 0, [theme]);
24804
+ const environmentUrls = React.useMemo(
24805
+ () => getAthenaEnvironmentUrls({ environment }),
24806
+ [environment]
24807
+ );
24700
24808
  const bridge = useParentBridge();
24701
24809
  const effectiveToken = tokenProp ?? bridge.token;
24702
- const effectiveApiUrl = apiUrl ?? bridge.apiUrl ?? DEFAULT_API_URL;
24703
- const effectiveBackendUrl = backendUrl ?? bridge.backendUrl ?? DEFAULT_BACKEND_URL;
24810
+ const effectiveApiUrl = apiUrl ?? bridge.apiUrl ?? environmentUrls.apiUrl ?? DEFAULT_API_URL;
24811
+ const effectiveBackendUrl = backendUrl ?? bridge.backendUrl ?? environmentUrls.backendUrl ?? DEFAULT_BACKEND_URL;
24812
+ const effectiveAppUrl = appUrl ?? bridge.appUrl ?? deriveAthenaAppUrl({ apiUrl: effectiveApiUrl, backendUrl: effectiveBackendUrl }) ?? environmentUrls.appUrl ?? DEFAULT_APP_URL;
24704
24813
  if (!bridge.ready) {
24705
24814
  return null;
24706
24815
  }
@@ -24711,6 +24820,7 @@ function AthenaProvider({
24711
24820
  {
24712
24821
  apiUrl: effectiveApiUrl,
24713
24822
  backendUrl: effectiveBackendUrl,
24823
+ appUrl: effectiveAppUrl,
24714
24824
  apiKey,
24715
24825
  token: effectiveToken,
24716
24826
  model,
@@ -24730,6 +24840,7 @@ function AthenaProvider({
24730
24840
  {
24731
24841
  apiUrl: effectiveApiUrl,
24732
24842
  backendUrl: effectiveBackendUrl,
24843
+ appUrl: effectiveAppUrl,
24733
24844
  apiKey,
24734
24845
  token: effectiveToken,
24735
24846
  model,
@@ -60527,9 +60638,12 @@ function useAttachments() {
60527
60638
  }
60528
60639
  return ctx;
60529
60640
  }
60530
- function buildAttachmentMarkdown(attachments) {
60641
+ function buildAttachmentMarkdownWithAppUrl({
60642
+ attachments,
60643
+ appUrl = DEFAULT_APP_URL
60644
+ }) {
60531
60645
  if (attachments.length === 0) return "";
60532
- return attachments.map((a) => `[@${a.title}](https://app.athenaintel.com/dashboard/spaces?asset_id=${a.id})`).join("\n");
60646
+ return attachments.map((attachment) => `[@${attachment.title}](${createAthenaSpacesUrl({ appUrl, assetIds: attachment.id })})`).join("\n");
60533
60647
  }
60534
60648
  const QuoteCtx = React.createContext(null);
60535
60649
  function QuoteProvider({ children }) {
@@ -60595,7 +60709,10 @@ function buildComposedMessage(opts) {
60595
60709
  var _a2;
60596
60710
  const parts = [];
60597
60711
  if (opts.attachments && opts.attachments.length > 0) {
60598
- const attachmentMd = buildAttachmentMarkdown(opts.attachments);
60712
+ const attachmentMd = buildAttachmentMarkdownWithAppUrl({
60713
+ attachments: opts.attachments,
60714
+ appUrl: opts.appUrl
60715
+ });
60599
60716
  if (attachmentMd) parts.push(attachmentMd);
60600
60717
  }
60601
60718
  if (opts.quote) {
@@ -60616,6 +60733,7 @@ const TiptapComposer = ({ tools = [] }) => {
60616
60733
  const mentionStore = useMentionSuggestions(tools);
60617
60734
  const { attachments, clearAttachments, isUploading } = useAttachments();
60618
60735
  const { quote, clearQuote } = useQuote();
60736
+ const { appUrl } = useAthenaConfig();
60619
60737
  const attachmentsRef = React.useRef(attachments);
60620
60738
  attachmentsRef.current = attachments;
60621
60739
  const quoteRef = React.useRef(quote);
@@ -60636,7 +60754,8 @@ const TiptapComposer = ({ tools = [] }) => {
60636
60754
  const fullMessage = buildComposedMessage({
60637
60755
  attachments: currentAttachments,
60638
60756
  quote: currentQuote,
60639
- userText: markdown
60757
+ userText: markdown,
60758
+ appUrl
60640
60759
  });
60641
60760
  if (fullMessage) {
60642
60761
  aui.thread().append({
@@ -63986,6 +64105,7 @@ const ComposerAction = () => /* @__PURE__ */ jsxRuntime.jsxs("div", { className:
63986
64105
  ] });
63987
64106
  const ComposerSendWithQuote = () => {
63988
64107
  const aui = useAui();
64108
+ const { appUrl } = useAthenaConfig();
63989
64109
  const { quote, clearQuote } = useQuote();
63990
64110
  const { attachments, clearAttachments, isUploading } = useAttachments();
63991
64111
  const editorRef = useComposerEditorRef();
@@ -63999,7 +64119,8 @@ const ComposerSendWithQuote = () => {
63999
64119
  const fullMessage = buildComposedMessage({
64000
64120
  attachments,
64001
64121
  quote,
64002
- userText
64122
+ userText,
64123
+ appUrl
64003
64124
  });
64004
64125
  if (!fullMessage) return;
64005
64126
  aui.thread().append({
@@ -64083,6 +64204,7 @@ const AssistantMessage = ({ toolUIs }) => /* @__PURE__ */ jsxRuntime.jsxs(
64083
64204
  );
64084
64205
  const AssistantActionBar = () => {
64085
64206
  const threadId = useAthenaThreadId();
64207
+ const { appUrl } = useAthenaConfig();
64086
64208
  return /* @__PURE__ */ jsxRuntime.jsxs(
64087
64209
  ActionBarPrimitiveRoot,
64088
64210
  {
@@ -64112,10 +64234,7 @@ const AssistantActionBar = () => {
64112
64234
  {
64113
64235
  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",
64114
64236
  onClick: () => {
64115
- window.open(
64116
- `https://app.athenaintel.com/dashboard/spaces?session_id=${threadId}`,
64117
- "_blank"
64118
- );
64237
+ window.open(createAthenaSpacesUrl({ appUrl, sessionId: threadId }), "_blank");
64119
64238
  },
64120
64239
  children: [
64121
64240
  /* @__PURE__ */ jsxRuntime.jsx(ExternalLink, { className: "size-4" }),
@@ -64602,6 +64721,7 @@ exports.CreateNotebookToolUI = CreateNotebookToolUI;
64602
64721
  exports.CreatePresentationToolUI = CreatePresentationToolUI;
64603
64722
  exports.CreateSheetToolUI = CreateSheetToolUI;
64604
64723
  exports.DEFAULT_API_URL = DEFAULT_API_URL;
64724
+ exports.DEFAULT_APP_URL = DEFAULT_APP_URL;
64605
64725
  exports.DEFAULT_BACKEND_URL = DEFAULT_BACKEND_URL;
64606
64726
  exports.EmailSearchToolUI = EmailSearchToolUI;
64607
64727
  exports.ExpandableSection = ExpandableSection;