@athenaintel/react 0.9.17 → 0.9.18

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
@@ -58896,17 +58896,39 @@ const useAssetPanelStore = create()(
58896
58896
  const existing = s.tabs.find((t) => t.id === assetId);
58897
58897
  if (existing) {
58898
58898
  const tabs = meta ? s.tabs.map(
58899
- (t) => t.id === assetId ? { ...t, name: meta.name ?? t.name, type: meta.type ?? t.type } : t
58899
+ (t) => t.id === assetId ? {
58900
+ ...t,
58901
+ name: meta.name ?? t.name,
58902
+ type: meta.type ?? t.type,
58903
+ embedSearchParams: meta.embedSearchParams ?? t.embedSearchParams
58904
+ } : t
58900
58905
  ) : s.tabs;
58901
58906
  return { isOpen: true, tabs, activeTabId: assetId };
58902
58907
  }
58903
58908
  const newTab = {
58904
58909
  id: assetId,
58905
58910
  name: (meta == null ? void 0 : meta.name) ?? null,
58906
- type: (meta == null ? void 0 : meta.type) ?? "unknown"
58911
+ type: (meta == null ? void 0 : meta.type) ?? "unknown",
58912
+ embedSearchParams: (meta == null ? void 0 : meta.embedSearchParams) ?? null
58907
58913
  };
58908
58914
  return { isOpen: true, tabs: [...s.tabs, newTab], activeTabId: assetId };
58909
58915
  }),
58916
+ updateTabMeta: (assetId, meta) => set2((s) => {
58917
+ const existing = s.tabs.find((t) => t.id === assetId);
58918
+ if (!existing) {
58919
+ return {};
58920
+ }
58921
+ return {
58922
+ tabs: s.tabs.map(
58923
+ (t) => t.id === assetId ? {
58924
+ ...t,
58925
+ name: meta.name ?? t.name,
58926
+ type: meta.type ?? t.type,
58927
+ embedSearchParams: meta.embedSearchParams ?? t.embedSearchParams
58928
+ } : t
58929
+ )
58930
+ };
58931
+ }),
58910
58932
  closeTab: (assetId) => set2((s) => {
58911
58933
  var _a2;
58912
58934
  const tabs = s.tabs.filter((t) => t.id !== assetId);
@@ -58964,13 +58986,43 @@ const ASSET_TYPE_ALIASES = {
58964
58986
  super_document: "document"
58965
58987
  };
58966
58988
  const isAthenaSpacesPath = (url) => url.pathname.replace(/\/+$/, "") === "/dashboard/spaces";
58967
- const normalizeAssetType = (value) => {
58989
+ const normalizeAssetType$1 = (value) => {
58968
58990
  if (!value) {
58969
58991
  return null;
58970
58992
  }
58971
58993
  const normalizedValue = value.trim().replace(/^athena\//, "").toLowerCase().replace(/-/g, "_");
58972
58994
  return ASSET_TYPE_ALIASES[normalizedValue] ?? null;
58973
58995
  };
58996
+ const isLikelyAssetId = (value) => !!value && /^(asset|thread|project|collection)_[a-z0-9-]+$/i.test(value.trim());
58997
+ const sanitizeDisplayName = (value) => {
58998
+ if (!value) {
58999
+ return null;
59000
+ }
59001
+ const trimmedValue = value.trim();
59002
+ if (!trimmedValue) {
59003
+ return null;
59004
+ }
59005
+ if (trimmedValue.startsWith('"') && trimmedValue.endsWith('"') || trimmedValue.startsWith("'") && trimmedValue.endsWith("'")) {
59006
+ return trimmedValue.slice(1, -1).trim() || null;
59007
+ }
59008
+ return trimmedValue;
59009
+ };
59010
+ const getCitationDisplayName = ({
59011
+ assetName,
59012
+ linkText
59013
+ }) => {
59014
+ const sanitizedAssetName = sanitizeDisplayName(assetName);
59015
+ const sanitizedLinkText = sanitizeDisplayName(linkText);
59016
+ const genericLinkTextPattern = /^(this|that|the)\s+asset$/i;
59017
+ if (sanitizedAssetName && !isLikelyAssetId(sanitizedAssetName)) {
59018
+ return sanitizedAssetName;
59019
+ }
59020
+ if (sanitizedLinkText && !genericLinkTextPattern.test(sanitizedLinkText)) {
59021
+ return sanitizedLinkText;
59022
+ }
59023
+ return sanitizedAssetName ?? sanitizedLinkText;
59024
+ };
59025
+ const getEmbedSearchParams = (url) => Object.fromEntries(url.searchParams.entries());
58974
59026
  const getOrigin = (value) => {
58975
59027
  if (!value) {
58976
59028
  return null;
@@ -59052,7 +59104,11 @@ const parseAthenaCitationLink = ({
59052
59104
  url,
59053
59105
  assetId,
59054
59106
  assetIds,
59055
- assetType: normalizeAssetType(url.searchParams.get("asset_type") ?? url.searchParams.get("type"))
59107
+ assetType: normalizeAssetType$1(
59108
+ url.searchParams.get("asset_type") ?? url.searchParams.get("assetType") ?? url.searchParams.get("type")
59109
+ ),
59110
+ assetName: sanitizeDisplayName(url.searchParams.get("name")),
59111
+ embedSearchParams: getEmbedSearchParams(url)
59056
59112
  };
59057
59113
  };
59058
59114
  const isAthenaCitationUrl = ({
@@ -59100,12 +59156,19 @@ const useAthenaLinkClickHandler = () => {
59100
59156
  const citationMetadata = citationLink ? {
59101
59157
  assetId: citationLink.assetId,
59102
59158
  assetIds: citationLink.assetIds,
59103
- assetType: citationLink.assetType
59159
+ assetType: citationLink.assetType,
59160
+ assetName: citationLink.assetName,
59161
+ embedSearchParams: citationLink.embedSearchParams
59104
59162
  } : null;
59105
59163
  const openInAssetPanel = citationLink ? () => {
59164
+ const displayName = getCitationDisplayName({
59165
+ assetName: citationLink.assetName,
59166
+ linkText: trimmedLinkText
59167
+ });
59106
59168
  openAsset(citationLink.assetId, {
59107
- name: trimmedLinkText ?? void 0,
59108
- type: citationLink.assetType ?? void 0
59169
+ name: displayName ?? void 0,
59170
+ type: citationLink.assetType ?? void 0,
59171
+ embedSearchParams: citationLink.embedSearchParams
59109
59172
  });
59110
59173
  } : void 0;
59111
59174
  const context2 = {
@@ -63545,6 +63608,12 @@ function extractAssetId(result) {
63545
63608
  if (typeof id === "string" && id.startsWith("asset_")) return id;
63546
63609
  return null;
63547
63610
  }
63611
+ function extractAssetTitle(result) {
63612
+ const data = normalizeResult(result);
63613
+ if (!data) return null;
63614
+ const title = data.assetTitle ?? data.asset_title ?? data.title ?? data.name;
63615
+ return typeof title === "string" && title.trim().length > 0 ? title.trim() : null;
63616
+ }
63548
63617
  function resetAssetAutoOpen() {
63549
63618
  useAssetPanelStore.getState().resetAutoOpen();
63550
63619
  }
@@ -64264,6 +64333,7 @@ const OpenAssetToolUIImpl = ({
64264
64333
  const typedArgs = args;
64265
64334
  const argsAssetId = (typedArgs == null ? void 0 : typedArgs.asset_id) ?? (typedArgs == null ? void 0 : typedArgs.assetId) ?? "";
64266
64335
  const resultAssetId = extractAssetId(result);
64336
+ const resultAssetTitle = extractAssetTitle(result);
64267
64337
  const assetId = resultAssetId ?? (argsAssetId.startsWith("asset_") ? argsAssetId : null);
64268
64338
  const isRunning = (status == null ? void 0 : status.type) === "running";
64269
64339
  const isComplete = (status == null ? void 0 : status.type) === "complete" || !status;
@@ -64275,10 +64345,10 @@ const OpenAssetToolUIImpl = ({
64275
64345
  if (isComplete && !isCancelled && assetId && !wasCompleteAtMount.current) {
64276
64346
  const store = useAssetPanelStore.getState();
64277
64347
  if (store.markAutoOpened(assetId)) {
64278
- store.openAsset(assetId);
64348
+ store.openAsset(assetId, { name: resultAssetTitle ?? void 0 });
64279
64349
  }
64280
64350
  }
64281
- }, [isComplete, isCancelled, assetId]);
64351
+ }, [isComplete, isCancelled, assetId, resultAssetTitle]);
64282
64352
  return /* @__PURE__ */ jsxRuntime.jsx(
64283
64353
  ToolCard,
64284
64354
  {
@@ -64294,7 +64364,7 @@ const OpenAssetToolUIImpl = ({
64294
64364
  "button",
64295
64365
  {
64296
64366
  type: "button",
64297
- onClick: () => openAsset(assetId),
64367
+ onClick: () => openAsset(assetId, { name: resultAssetTitle ?? void 0 }),
64298
64368
  className: "flex items-center gap-1.5 rounded-md border border-border/60 px-3 py-1.5 text-xs font-medium text-muted-foreground transition-colors hover:bg-muted/50 hover:text-foreground",
64299
64369
  children: [
64300
64370
  /* @__PURE__ */ jsxRuntime.jsx(ExternalLink, { className: "size-3" }),
@@ -65219,14 +65289,67 @@ const AthenaUserMessage = ({
65219
65289
  children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "aui-user-message-content wrap-break-word rounded-2xl bg-muted px-4 py-2.5 text-foreground", children: /* @__PURE__ */ jsxRuntime.jsx(MessagePrimitiveParts, { components: { Text: TextComponent } }) })
65220
65290
  }
65221
65291
  );
65292
+ const EMBED_ASSET_TYPE_ALIASES = {
65293
+ document: "document",
65294
+ image: "document",
65295
+ notebook: "notebook",
65296
+ pdf: "document",
65297
+ powerpoint_deck: "presentation",
65298
+ presentation: "presentation",
65299
+ puck_presentation: "presentation",
65300
+ sheet: "spreadsheet",
65301
+ spreadsheet: "spreadsheet",
65302
+ super_document: "document"
65303
+ };
65222
65304
  const embedCache = /* @__PURE__ */ new Map();
65305
+ const normalizeAssetType = (value) => {
65306
+ if (!value) {
65307
+ return null;
65308
+ }
65309
+ const normalizedValue = value.trim().replace(/^athena\//, "").toLowerCase().replace(/-/g, "_");
65310
+ return EMBED_ASSET_TYPE_ALIASES[normalizedValue] ?? null;
65311
+ };
65312
+ const getEmbedSearchParamsCacheKey = (embedSearchParams) => {
65313
+ if (!embedSearchParams || Object.keys(embedSearchParams).length === 0) {
65314
+ return "{}";
65315
+ }
65316
+ const sortedEntries = Object.entries(embedSearchParams).sort(
65317
+ ([left], [right]) => left.localeCompare(right)
65318
+ );
65319
+ return JSON.stringify(Object.fromEntries(sortedEntries));
65320
+ };
65321
+ const appendEmbedSearchParams = ({
65322
+ embedUrl,
65323
+ embedSearchParams
65324
+ }) => {
65325
+ if (!embedSearchParams || Object.keys(embedSearchParams).length === 0) {
65326
+ return embedUrl;
65327
+ }
65328
+ const url = new URL(embedUrl);
65329
+ for (const [key, value] of Object.entries(embedSearchParams)) {
65330
+ if (!value) {
65331
+ continue;
65332
+ }
65333
+ url.searchParams.set(key, value);
65334
+ }
65335
+ return url.toString();
65336
+ };
65223
65337
  function useAssetEmbed(assetId, options = {
65224
65338
  backendUrl: ""
65225
65339
  }) {
65226
- const { readOnly = false, expiresInSeconds = 60 * 60 * 24 * 30, backendUrl, apiKey, token } = options;
65340
+ const {
65341
+ readOnly = false,
65342
+ expiresInSeconds = 60 * 60 * 24 * 30,
65343
+ backendUrl,
65344
+ apiKey,
65345
+ token,
65346
+ embedSearchParams
65347
+ } = options;
65227
65348
  const [embedUrl, setEmbedUrl] = React.useState(null);
65228
65349
  const [isLoading, setIsLoading] = React.useState(false);
65229
65350
  const [error2, setError] = React.useState(null);
65351
+ const [assetTitle, setAssetTitle] = React.useState(null);
65352
+ const [assetType, setAssetType] = React.useState(null);
65230
65353
  const abortRef = React.useRef(null);
65231
65354
  React.useEffect(() => {
65232
65355
  var _a2;
@@ -65234,14 +65357,18 @@ function useAssetEmbed(assetId, options = {
65234
65357
  setEmbedUrl(null);
65235
65358
  setIsLoading(false);
65236
65359
  setError(null);
65360
+ setAssetTitle(null);
65361
+ setAssetType(null);
65237
65362
  return;
65238
65363
  }
65239
- const cacheKey = `${assetId}:${readOnly}:${token ?? apiKey ?? "anon"}`;
65364
+ const cacheKey = `${assetId}:${readOnly}:${token ?? apiKey ?? "anon"}:${getEmbedSearchParamsCacheKey(embedSearchParams)}`;
65240
65365
  const cached = embedCache.get(cacheKey);
65241
65366
  if (cached && cached.expiresAt > Date.now() / 1e3) {
65242
65367
  setEmbedUrl(cached.url);
65243
65368
  setIsLoading(false);
65244
65369
  setError(null);
65370
+ setAssetTitle(cached.assetTitle);
65371
+ setAssetType(cached.assetType);
65245
65372
  return;
65246
65373
  }
65247
65374
  const apiBaseUrl = backendUrl.replace(/\/api\/assistant-ui\/?$/, "");
@@ -65249,11 +65376,14 @@ function useAssetEmbed(assetId, options = {
65249
65376
  (_a2 = abortRef.current) == null ? void 0 : _a2.abort();
65250
65377
  const controller = new AbortController();
65251
65378
  abortRef.current = controller;
65379
+ setEmbedUrl(null);
65252
65380
  setIsLoading(true);
65253
65381
  setError(null);
65382
+ setAssetTitle(null);
65383
+ setAssetType(null);
65254
65384
  const headers = { "Content-Type": "application/json" };
65255
65385
  if (token) {
65256
- headers["Authorization"] = `Bearer ${token}`;
65386
+ headers.Authorization = `Bearer ${token}`;
65257
65387
  } else if (apiKey) {
65258
65388
  headers["X-API-KEY"] = apiKey;
65259
65389
  }
@@ -65273,17 +65403,31 @@ function useAssetEmbed(assetId, options = {
65273
65403
  }
65274
65404
  return res.json();
65275
65405
  }).then((data) => {
65276
- embedCache.set(`${assetId}:${readOnly}:${token ?? apiKey ?? "anon"}`, { url: data.embed_url, expiresAt: data.expires_at });
65277
- setEmbedUrl(data.embed_url);
65406
+ const resolvedAssetType = normalizeAssetType(data.athena_converted_type) ?? normalizeAssetType(data.athena_original_type);
65407
+ const resolvedEmbedUrl = appendEmbedSearchParams({
65408
+ embedUrl: data.embed_url,
65409
+ embedSearchParams
65410
+ });
65411
+ embedCache.set(cacheKey, {
65412
+ url: resolvedEmbedUrl,
65413
+ expiresAt: data.expires_at,
65414
+ assetTitle: data.title ?? null,
65415
+ assetType: resolvedAssetType
65416
+ });
65417
+ setEmbedUrl(resolvedEmbedUrl);
65418
+ setAssetTitle(data.title ?? null);
65419
+ setAssetType(resolvedAssetType);
65278
65420
  setIsLoading(false);
65279
65421
  }).catch((err) => {
65280
- if (err.name === "AbortError") return;
65422
+ if (err.name === "AbortError") {
65423
+ return;
65424
+ }
65281
65425
  setError(err.message);
65282
65426
  setIsLoading(false);
65283
65427
  });
65284
65428
  return () => controller.abort();
65285
- }, [assetId, readOnly, expiresInSeconds, backendUrl, apiKey, token]);
65286
- return { embedUrl, isLoading, error: error2 };
65429
+ }, [assetId, readOnly, expiresInSeconds, backendUrl, apiKey, token, embedSearchParams]);
65430
+ return { embedUrl, isLoading, error: error2, assetTitle, assetType };
65287
65431
  }
65288
65432
  const ASSET_TYPE_CONFIG = {
65289
65433
  presentation: { icon: Presentation, label: "Presentation" },
@@ -65293,13 +65437,28 @@ const ASSET_TYPE_CONFIG = {
65293
65437
  unknown: { icon: File$1, label: "Asset" }
65294
65438
  };
65295
65439
  const AssetIframe = React.memo(
65296
- ({ tabId, tabName }) => {
65440
+ ({ tabId, tabName, tabType, embedSearchParams }) => {
65297
65441
  const { backendUrl, apiKey, token } = useAthenaConfig();
65298
- const { embedUrl, isLoading, error: error2 } = useAssetEmbed(tabId, {
65442
+ const { embedUrl, isLoading, error: error2, assetTitle, assetType } = useAssetEmbed(tabId, {
65299
65443
  backendUrl,
65300
65444
  apiKey,
65301
- token
65445
+ token,
65446
+ embedSearchParams
65302
65447
  });
65448
+ React.useEffect(() => {
65449
+ if (!assetTitle && !assetType) {
65450
+ return;
65451
+ }
65452
+ const nextName = assetTitle ?? tabName;
65453
+ const nextType = assetType ?? tabType;
65454
+ if (nextName === tabName && nextType === tabType) {
65455
+ return;
65456
+ }
65457
+ useAssetPanelStore.getState().updateTabMeta(tabId, {
65458
+ name: nextName ?? void 0,
65459
+ type: nextType
65460
+ });
65461
+ }, [assetTitle, assetType, tabId, tabName, tabType]);
65303
65462
  if (isLoading) {
65304
65463
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-full items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center", children: [
65305
65464
  /* @__PURE__ */ jsxRuntime.jsx(LoaderCircle, { className: "mx-auto size-6 animate-spin text-muted-foreground" }),
@@ -65361,7 +65520,7 @@ const PanelContent = ({
65361
65520
  return /* @__PURE__ */ jsxRuntime.jsx(
65362
65521
  "div",
65363
65522
  {
65364
- className: `flex-1 overflow-hidden ${isTiled ? `${gridClass} gap-px bg-border/60` : ""}`,
65523
+ className: cn("flex-1 overflow-hidden", isTiled && gridClass, isTiled && "gap-px bg-border/60"),
65365
65524
  children: tabs.map((tab) => {
65366
65525
  const isActive2 = tab.id === activeTabId;
65367
65526
  const config2 = ASSET_TYPE_CONFIG[tab.type];
@@ -65384,7 +65543,15 @@ const PanelContent = ({
65384
65543
  }
65385
65544
  )
65386
65545
  ] }),
65387
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(AssetIframe, { tabId: tab.id, tabName: tab.name }) })
65546
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(
65547
+ AssetIframe,
65548
+ {
65549
+ tabId: tab.id,
65550
+ tabName: tab.name,
65551
+ tabType: tab.type,
65552
+ embedSearchParams: tab.embedSearchParams
65553
+ }
65554
+ ) })
65388
65555
  ]
65389
65556
  },
65390
65557
  tab.id
@@ -65394,7 +65561,15 @@ const PanelContent = ({
65394
65561
  "div",
65395
65562
  {
65396
65563
  className: isActive2 ? "h-full w-full" : "hidden",
65397
- children: /* @__PURE__ */ jsxRuntime.jsx(AssetIframe, { tabId: tab.id, tabName: tab.name })
65564
+ children: /* @__PURE__ */ jsxRuntime.jsx(
65565
+ AssetIframe,
65566
+ {
65567
+ tabId: tab.id,
65568
+ tabName: tab.name,
65569
+ tabType: tab.type,
65570
+ embedSearchParams: tab.embedSearchParams
65571
+ }
65572
+ )
65398
65573
  },
65399
65574
  tab.id
65400
65575
  );
@@ -65412,7 +65587,10 @@ const TabBar = () => {
65412
65587
  return /* @__PURE__ */ jsxRuntime.jsxs(
65413
65588
  "div",
65414
65589
  {
65415
- className: `group flex max-w-[180px] shrink-0 cursor-pointer items-center gap-1.5 border-r border-border/40 px-3 py-1.5 text-xs ${isActive2 ? "border-b-2 border-b-primary bg-background text-foreground" : "text-muted-foreground hover:bg-background/50 hover:text-foreground"}`,
65590
+ className: cn(
65591
+ "group flex max-w-[180px] shrink-0 cursor-pointer items-center gap-1.5 border-r border-border/40 px-3 py-1.5 text-xs",
65592
+ isActive2 ? "border-b-2 border-b-primary bg-background text-foreground" : "text-muted-foreground hover:bg-background/50 hover:text-foreground"
65593
+ ),
65416
65594
  onClick: () => setActiveTab(tab.id),
65417
65595
  children: [
65418
65596
  /* @__PURE__ */ jsxRuntime.jsx(TypeIcon, { className: "size-3 shrink-0" }),
@@ -65454,7 +65632,10 @@ const PanelHeader = ({ fullscreen }) => {
65454
65632
  "button",
65455
65633
  {
65456
65634
  onClick: () => setViewMode(isTiled ? "tabs" : "tiled"),
65457
- className: `flex size-7 items-center justify-center rounded-lg transition-colors ${isTiled ? "bg-primary/10 text-primary" : "text-muted-foreground hover:bg-accent hover:text-foreground"}`,
65635
+ className: cn(
65636
+ "flex size-7 items-center justify-center rounded-lg transition-colors",
65637
+ isTiled ? "bg-primary/10 text-primary" : "text-muted-foreground hover:bg-accent hover:text-foreground"
65638
+ ),
65458
65639
  title: isTiled ? "Switch to tabs" : "Tile all assets",
65459
65640
  children: isTiled ? /* @__PURE__ */ jsxRuntime.jsx(Layers, { className: "size-3.5" }) : /* @__PURE__ */ jsxRuntime.jsx(LayoutGrid, { className: "size-3.5" })
65460
65641
  }