@athenaintel/react 0.9.6 → 0.9.8

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
@@ -17,7 +17,7 @@ import '@athenaintel/react/styles.css';
17
17
  function App() {
18
18
  return (
19
19
  <AthenaProvider
20
- apiKey="your-api-key"
20
+ config={{ apiKey: 'your-api-key' }}
21
21
  tools={[Toolkits.DOCUMENT, Toolkits.WEB_SEARCH]}
22
22
  >
23
23
  <AthenaChat />
@@ -26,23 +26,27 @@ function App() {
26
26
  }
27
27
  ```
28
28
 
29
- ## Environment And URLs
29
+ ## Provider Config
30
30
 
31
31
  ```tsx
32
- <AthenaProvider environment="staging">
32
+ <AthenaProvider config={{ environment: 'staging' }}>
33
33
  <AthenaChat />
34
34
  </AthenaProvider>
35
35
 
36
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"
37
+ config={{
38
+ apiUrl: 'https://sync.example.com/api/chat',
39
+ backendUrl: 'https://api.example.com',
40
+ appUrl: 'https://app.example.com',
41
+ }}
40
42
  >
41
43
  <AthenaChat />
42
44
  </AthenaProvider>
43
45
  ```
44
46
 
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.
47
+ `config` accepts `apiKey`, `token`, `apiUrl`, `backendUrl`, `appUrl`, and `environment`. Top-level `apiKey`, `token`, `apiUrl`, `backendUrl`, `appUrl`, and `environment` props remain supported as compatibility aliases, but `config` is now the preferred API.
48
+
49
+ If `config.appUrl` is omitted, the provider resolves it from the parent bridge or from the matching Athena environment defaults. Known Athena staging and production `apiUrl` and `backendUrl` values automatically fall back to the corresponding frontend origin.
46
50
 
47
51
  ## Theming
48
52
 
@@ -64,6 +68,26 @@ Preset themes: `light`, `dark`, `midnight`, `warm`, `purple`, `green`.
64
68
  - **`<ThreadList>`** — Conversation history sidebar
65
69
  - **`Toolkits`** — Constants for all available backend toolkits
66
70
 
71
+ ## Composer Hooks
72
+
73
+ Use `useAppendToComposer()` when you want to prefill a draft without sending it.
74
+
75
+ Use `useSendMessage()` for workflow buttons, sidebar shortcuts, and other UI that lives outside `<AthenaChat>` but still needs to submit a prompt.
76
+
77
+ ```tsx
78
+ import { useSendMessage } from '@athenaintel/react';
79
+
80
+ function WorkflowButton() {
81
+ const sendMessage = useSendMessage();
82
+
83
+ return (
84
+ <button onClick={() => void sendMessage('Run the quarterly workflow')}>
85
+ Run workflow
86
+ </button>
87
+ );
88
+ }
89
+ ```
90
+
67
91
  ## License
68
92
 
69
93
  Proprietary. For licensed enterprise customers only.
package/dist/index.cjs CHANGED
@@ -16491,8 +16491,16 @@ const DEFAULT_ATHENA_ENVIRONMENT = "production";
16491
16491
  const DEFAULT_API_URL = ATHENA_ENVIRONMENT_URLS.production.apiUrl;
16492
16492
  const DEFAULT_BACKEND_URL = ATHENA_ENVIRONMENT_URLS.production.backendUrl;
16493
16493
  const DEFAULT_APP_URL = ATHENA_ENVIRONMENT_URLS.production.appUrl;
16494
- const SPACES_PATHNAME = "/dashboard/spaces/";
16494
+ const MARATHON_APP_PORT = "8082";
16495
+ const SPACES_PATHNAME = "dashboard/spaces/";
16495
16496
  const normalizeBaseUrl = (url) => url.replace(/\/+$/, "");
16497
+ const createUrlWithFallback = (url, fallbackUrl) => {
16498
+ try {
16499
+ return new URL(`${normalizeBaseUrl(url)}/`);
16500
+ } catch {
16501
+ return new URL(`${normalizeBaseUrl(fallbackUrl)}/`);
16502
+ }
16503
+ };
16496
16504
  const getHostname = (value) => {
16497
16505
  if (!value) return null;
16498
16506
  try {
@@ -16514,7 +16522,7 @@ const deriveWorkspaceAppUrl = ({
16514
16522
  if (!((_a2 = match2 == null ? void 0 : match2.groups) == null ? void 0 : _a2.prefix) || !match2.groups.domain) {
16515
16523
  return null;
16516
16524
  }
16517
- return `${parsedUrl.protocol}//${match2.groups.prefix}--8082.${match2.groups.domain}`;
16525
+ return `${parsedUrl.protocol}//${match2.groups.prefix}--${MARATHON_APP_PORT}.${match2.groups.domain}`;
16518
16526
  } catch {
16519
16527
  return null;
16520
16528
  }
@@ -16563,7 +16571,7 @@ function createAthenaSpacesUrl({
16563
16571
  assetIds,
16564
16572
  sessionId
16565
16573
  }) {
16566
- const url = new URL(SPACES_PATHNAME, `${normalizeBaseUrl(appUrl)}/`);
16574
+ const url = new URL(SPACES_PATHNAME, createUrlWithFallback(appUrl, DEFAULT_APP_URL));
16567
16575
  if (assetIds) {
16568
16576
  const normalizedAssetIds = (Array.isArray(assetIds) ? assetIds : [assetIds]).map((assetId) => assetId.trim()).filter((assetId) => assetId.length > 0);
16569
16577
  if (normalizedAssetIds.length > 0) {
@@ -20625,7 +20633,9 @@ const toolMessageSchema = objectType({
20625
20633
  type: literalType("tool"),
20626
20634
  content: toolMessageContentSchema,
20627
20635
  tool_call_id: stringType(),
20628
- name: stringType().nullable(),
20636
+ // Some backend/tool result flows omit the tool name entirely.
20637
+ // The converter already treats toolName as optional, so accept that shape.
20638
+ name: nullableToOptionalString,
20629
20639
  artifact: anyType().optional(),
20630
20640
  status: enumType(["success", "error"]),
20631
20641
  additional_kwargs: recordType(stringType(), unknownType()).optional()
@@ -20777,7 +20787,7 @@ function getAuthHeaders(auth) {
20777
20787
  }
20778
20788
  return {};
20779
20789
  }
20780
- function getAgoraBaseUrl(backendUrl) {
20790
+ function getAthenaApiBaseUrl(backendUrl) {
20781
20791
  const stripped = backendUrl.replace(/\/api\/assistant-ui\/?$/, "");
20782
20792
  if (stripped === backendUrl) {
20783
20793
  return backendUrl.replace(/\/$/, "");
@@ -20785,14 +20795,16 @@ function getAgoraBaseUrl(backendUrl) {
20785
20795
  return stripped;
20786
20796
  }
20787
20797
  async function listThreads(backendUrl, auth, opts = {}) {
20788
- const base2 = getAgoraBaseUrl(backendUrl);
20798
+ const base2 = getAthenaApiBaseUrl(backendUrl);
20789
20799
  const res = await fetch(`${base2}/api/conversations/threads/list`, {
20790
20800
  method: "POST",
20791
20801
  headers: { "Content-Type": "application/json", ...getAuthHeaders(auth) },
20792
20802
  body: JSON.stringify({
20793
20803
  limit: opts.limit ?? 50,
20794
20804
  offset: opts.offset ?? 0,
20795
- exclude_triggered: opts.exclude_triggered ?? true
20805
+ // Default to the full recent-conversations set unless a caller
20806
+ // explicitly asks to hide triggered/background sessions.
20807
+ exclude_triggered: opts.exclude_triggered ?? false
20796
20808
  })
20797
20809
  });
20798
20810
  if (!res.ok) {
@@ -20814,7 +20826,7 @@ function deserializeMessage(msg) {
20814
20826
  return msg;
20815
20827
  }
20816
20828
  async function getThreadState(backendUrl, auth, threadId) {
20817
- const base2 = getAgoraBaseUrl(backendUrl);
20829
+ const base2 = getAthenaApiBaseUrl(backendUrl);
20818
20830
  const res = await fetch(`${base2}/api/unstable/threads/${threadId}`, {
20819
20831
  method: "GET",
20820
20832
  headers: { ...getAuthHeaders(auth) }
@@ -20829,7 +20841,7 @@ async function getThreadState(backendUrl, auth, threadId) {
20829
20841
  return data;
20830
20842
  }
20831
20843
  async function archiveThread(backendUrl, auth, threadId) {
20832
- const base2 = getAgoraBaseUrl(backendUrl);
20844
+ const base2 = getAthenaApiBaseUrl(backendUrl);
20833
20845
  const res = await fetch(`${base2}/api/conversations/threads/archive`, {
20834
20846
  method: "POST",
20835
20847
  headers: { "Content-Type": "application/json", ...getAuthHeaders(auth) },
@@ -24643,6 +24655,15 @@ const themes = {
24643
24655
  radius: "0.625rem"
24644
24656
  }
24645
24657
  };
24658
+ const resolveTokenOverride = ({
24659
+ config: config2,
24660
+ token
24661
+ }) => {
24662
+ if ((config2 == null ? void 0 : config2.token) !== void 0) {
24663
+ return config2.token;
24664
+ }
24665
+ return token;
24666
+ };
24646
24667
  function AthenaStandalone({
24647
24668
  children,
24648
24669
  apiUrl,
@@ -24782,6 +24803,7 @@ function AthenaWithThreadList({
24782
24803
  }
24783
24804
  function AthenaProvider({
24784
24805
  children,
24806
+ config: config2,
24785
24807
  apiKey,
24786
24808
  token: tokenProp,
24787
24809
  agent: agent2,
@@ -24801,15 +24823,21 @@ function AthenaProvider({
24801
24823
  }) {
24802
24824
  const frontendToolNames = React.useMemo(() => Object.keys(frontendTools), [frontendTools]);
24803
24825
  const themeStyleVars = React.useMemo(() => theme ? themeToStyleVars(theme) : void 0, [theme]);
24826
+ const configuredEnvironment = (config2 == null ? void 0 : config2.environment) ?? environment;
24804
24827
  const environmentUrls = React.useMemo(
24805
- () => getAthenaEnvironmentUrls({ environment }),
24806
- [environment]
24828
+ () => getAthenaEnvironmentUrls({ environment: configuredEnvironment }),
24829
+ [configuredEnvironment]
24807
24830
  );
24831
+ const configuredApiKey = (config2 == null ? void 0 : config2.apiKey) ?? apiKey;
24832
+ const configuredToken = resolveTokenOverride({ config: config2, token: tokenProp });
24833
+ const configuredApiUrl = (config2 == null ? void 0 : config2.apiUrl) ?? apiUrl;
24834
+ const configuredBackendUrl = (config2 == null ? void 0 : config2.backendUrl) ?? backendUrl;
24835
+ const configuredAppUrl = (config2 == null ? void 0 : config2.appUrl) ?? appUrl;
24808
24836
  const bridge = useParentBridge();
24809
- const effectiveToken = tokenProp ?? bridge.token;
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;
24837
+ const effectiveToken = configuredToken !== void 0 ? configuredToken : bridge.token;
24838
+ const effectiveApiUrl = configuredApiUrl ?? bridge.apiUrl ?? environmentUrls.apiUrl;
24839
+ const effectiveBackendUrl = configuredBackendUrl ?? bridge.backendUrl ?? environmentUrls.backendUrl;
24840
+ const effectiveAppUrl = configuredAppUrl ?? bridge.appUrl ?? deriveAthenaAppUrl({ apiUrl: effectiveApiUrl, backendUrl: effectiveBackendUrl }) ?? environmentUrls.appUrl;
24813
24841
  if (!bridge.ready) {
24814
24842
  return null;
24815
24843
  }
@@ -24821,7 +24849,7 @@ function AthenaProvider({
24821
24849
  apiUrl: effectiveApiUrl,
24822
24850
  backendUrl: effectiveBackendUrl,
24823
24851
  appUrl: effectiveAppUrl,
24824
- apiKey,
24852
+ apiKey: configuredApiKey,
24825
24853
  token: effectiveToken,
24826
24854
  model,
24827
24855
  agent: agent2,
@@ -24841,7 +24869,7 @@ function AthenaProvider({
24841
24869
  apiUrl: effectiveApiUrl,
24842
24870
  backendUrl: effectiveBackendUrl,
24843
24871
  appUrl: effectiveAppUrl,
24844
- apiKey,
24872
+ apiKey: configuredApiKey,
24845
24873
  token: effectiveToken,
24846
24874
  model,
24847
24875
  agent: agent2,
@@ -60770,7 +60798,7 @@ const TiptapComposer = ({ tools = [] }) => {
60770
60798
  composerRuntime.send();
60771
60799
  }
60772
60800
  editor2.commands.clearContent();
60773
- }, [aui, composerRuntime, clearAttachments, clearQuote]);
60801
+ }, [aui, composerRuntime, clearAttachments, clearQuote, appUrl]);
60774
60802
  const handleSubmitRef = React.useRef(handleSubmit);
60775
60803
  handleSubmitRef.current = handleSubmit;
60776
60804
  const editor = useEditor({
@@ -63680,9 +63708,6 @@ function useFileUpload() {
63680
63708
  formData.append("files", file, file.name);
63681
63709
  }
63682
63710
  const baseUrl = backendUrl.replace(/\/api\/assistant-ui\/?$/, "");
63683
- if (baseUrl === backendUrl) {
63684
- console.warn("[AthenaSDK] useFileUpload: backendUrl does not end with /api/assistant-ui — upload URL may be incorrect:", `${baseUrl}/api/upload/`);
63685
- }
63686
63711
  const uploadUrl = `${baseUrl}/api/upload/`;
63687
63712
  const headers = {};
63688
63713
  if (token) {
@@ -63945,6 +63970,23 @@ const ComposerDropZone = ({
63945
63970
  }
63946
63971
  );
63947
63972
  };
63973
+ function useSendMessage() {
63974
+ const aui = useAui();
63975
+ return React.useCallback(
63976
+ async (text2, options) => {
63977
+ if (!text2.trim()) return;
63978
+ const composer = aui.composer();
63979
+ const currentText = composer.getState().text;
63980
+ const shouldReplace = (options == null ? void 0 : options.replace) ?? true;
63981
+ composer.setText(
63982
+ shouldReplace || !currentText ? text2 : `${currentText}
63983
+ ${text2}`
63984
+ );
63985
+ await composer.send();
63986
+ },
63987
+ [aui]
63988
+ );
63989
+ }
63948
63990
  const EMPTY_MENTION_TOOLS = [];
63949
63991
  function QuotePostMessageBridge() {
63950
63992
  useQuoteFromPostMessage();
@@ -63976,14 +64018,11 @@ const SuggestionCard = ({
63976
64018
  suggestion,
63977
64019
  index: index2
63978
64020
  }) => {
63979
- const aui = useAui();
63980
64021
  const Icon2 = suggestion.icon;
64022
+ const sendMessage = useSendMessage();
63981
64023
  const handleClick2 = React.useCallback(() => {
63982
- aui.thread().append({
63983
- role: "user",
63984
- content: [{ type: "text", text: suggestion.prompt }]
63985
- });
63986
- }, [aui, suggestion.prompt]);
64024
+ void sendMessage(suggestion.prompt);
64025
+ }, [sendMessage, suggestion.prompt]);
63987
64026
  return /* @__PURE__ */ jsxRuntime.jsxs(
63988
64027
  "button",
63989
64028
  {
@@ -64130,7 +64169,7 @@ const ComposerSendWithQuote = () => {
64130
64169
  editor == null ? void 0 : editor.clear();
64131
64170
  clearQuote();
64132
64171
  clearAttachments();
64133
- }, [aui, quote, attachments, isUploading, clearQuote, clearAttachments, editorRef]);
64172
+ }, [aui, quote, attachments, isUploading, clearQuote, clearAttachments, editorRef, appUrl]);
64134
64173
  if (hasExtras) {
64135
64174
  return /* @__PURE__ */ jsxRuntime.jsx(
64136
64175
  TooltipIconButton,
@@ -64283,8 +64322,8 @@ function useAssetEmbed(assetId, options = {
64283
64322
  setError(null);
64284
64323
  return;
64285
64324
  }
64286
- const agoraBase = backendUrl.replace(/\/api\/assistant-ui\/?$/, "");
64287
- const endpoint = `${agoraBase}/api/embed/generate-token`;
64325
+ const apiBaseUrl = backendUrl.replace(/\/api\/assistant-ui\/?$/, "");
64326
+ const endpoint = `${apiBaseUrl}/api/embed/generate-token`;
64288
64327
  (_a2 = abortRef.current) == null ? void 0 : _a2.abort();
64289
64328
  const controller = new AbortController();
64290
64329
  abortRef.current = controller;
@@ -64772,4 +64811,5 @@ exports.useParentAuth = useParentAuth;
64772
64811
  exports.useParentBridge = useParentBridge;
64773
64812
  exports.useQuote = useQuote;
64774
64813
  exports.useRefreshThreadList = useRefreshThreadList;
64814
+ exports.useSendMessage = useSendMessage;
64775
64815
  //# sourceMappingURL=index.cjs.map