@athenaintel/react 0.10.26 → 0.10.27

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
@@ -14152,14 +14152,20 @@ const useAssetPanelStore = create()(
14152
14152
  const existing = s.tabs.find((t) => t.id === assetId);
14153
14153
  if (existing) {
14154
14154
  const tabs = meta ? s.tabs.map(
14155
- (t) => t.id === assetId ? { ...t, name: meta.name ?? t.name, type: meta.type ?? t.type } : t
14155
+ (t) => t.id === assetId ? {
14156
+ ...t,
14157
+ name: meta.name ?? t.name,
14158
+ type: meta.type ?? t.type,
14159
+ slideNumber: meta.slideNumber ?? t.slideNumber
14160
+ } : t
14156
14161
  ) : s.tabs;
14157
14162
  return { isOpen: true, tabs, activeTabId: assetId };
14158
14163
  }
14159
14164
  const newTab = {
14160
14165
  id: assetId,
14161
14166
  name: (meta == null ? void 0 : meta.name) ?? null,
14162
- type: (meta == null ? void 0 : meta.type) ?? "unknown"
14167
+ type: (meta == null ? void 0 : meta.type) ?? "unknown",
14168
+ slideNumber: meta == null ? void 0 : meta.slideNumber
14163
14169
  };
14164
14170
  return { isOpen: true, tabs: [...s.tabs, newTab], activeTabId: assetId };
14165
14171
  }),
@@ -50904,6 +50910,68 @@ function extractAssetId(result) {
50904
50910
  function resetAssetAutoOpen() {
50905
50911
  useAssetPanelStore.getState().resetAutoOpen();
50906
50912
  }
50913
+ function getStringField(source, keys2) {
50914
+ if (!source) return null;
50915
+ for (const key of keys2) {
50916
+ const value = source[key];
50917
+ if (typeof value === "string" && value.trim()) {
50918
+ return value;
50919
+ }
50920
+ }
50921
+ return null;
50922
+ }
50923
+ function getNumberField(source, keys2) {
50924
+ if (!source) return null;
50925
+ for (const key of keys2) {
50926
+ const value = source[key];
50927
+ if (typeof value === "number" && Number.isFinite(value)) {
50928
+ return value;
50929
+ }
50930
+ }
50931
+ return null;
50932
+ }
50933
+ function getStudioAssetId({
50934
+ args,
50935
+ result
50936
+ }) {
50937
+ const id = getStringField(result, ["asset_id", "assetId", "id"]) ?? getStringField(args, ["asset_id", "assetId", "id"]);
50938
+ return (id == null ? void 0 : id.startsWith("asset_")) ? id : null;
50939
+ }
50940
+ function getSlideNumber(args) {
50941
+ const explicit = getNumberField(args, ["slideNumber", "slide_number"]);
50942
+ if (explicit != null && Number.isInteger(explicit) && explicit >= 1) {
50943
+ return explicit;
50944
+ }
50945
+ const zeroBasedIndex = getNumberField(args, ["index", "slideIndex", "slide_index"]);
50946
+ if (zeroBasedIndex != null && Number.isInteger(zeroBasedIndex) && zeroBasedIndex >= 0) {
50947
+ return zeroBasedIndex + 1;
50948
+ }
50949
+ return void 0;
50950
+ }
50951
+ const completedStudioToolEffects = /* @__PURE__ */ new Set();
50952
+ const MAX_COMPLETED_STUDIO_TOOL_EFFECTS = 500;
50953
+ function markStudioToolEffect(key) {
50954
+ if (completedStudioToolEffects.has(key)) {
50955
+ return false;
50956
+ }
50957
+ if (completedStudioToolEffects.size >= MAX_COMPLETED_STUDIO_TOOL_EFFECTS) {
50958
+ const oldest = completedStudioToolEffects.values().next().value;
50959
+ if (oldest) completedStudioToolEffects.delete(oldest);
50960
+ }
50961
+ completedStudioToolEffects.add(key);
50962
+ return true;
50963
+ }
50964
+ function dispatchPresentationNavigate(assetId, slideNumber) {
50965
+ const targetSlide = slideNumber;
50966
+ if (typeof targetSlide !== "number" || !Number.isInteger(targetSlide) || targetSlide < 1) {
50967
+ return;
50968
+ }
50969
+ window.dispatchEvent(
50970
+ new CustomEvent("pptx-studio-navigate", {
50971
+ detail: { assetId, slideNumber: targetSlide }
50972
+ })
50973
+ );
50974
+ }
50907
50975
  function CreateAssetToolUIImpl({
50908
50976
  icon: Icon2,
50909
50977
  assetType,
@@ -51013,6 +51081,238 @@ const CreatePresentationToolUI = React.memo(
51013
51081
  CreatePresentationToolUIImpl
51014
51082
  );
51015
51083
  CreatePresentationToolUI.displayName = "CreatePresentationToolUI";
51084
+ function StudioPtcToolUI({
51085
+ config: config2,
51086
+ toolName,
51087
+ toolCallId,
51088
+ args,
51089
+ result,
51090
+ status
51091
+ }) {
51092
+ var _a2, _b;
51093
+ const typedArgs = args;
51094
+ const data = React.useMemo(() => normalizeResult(result), [result]);
51095
+ const slideNumber = (_a2 = config2.getSlideNumber) == null ? void 0 : _a2.call(config2, typedArgs);
51096
+ const assetId = getStudioAssetId({ args: typedArgs, result: data });
51097
+ const subtitle = (_b = config2.getSubtitle) == null ? void 0 : _b.call(config2, typedArgs, data, slideNumber);
51098
+ const isRunning = (status == null ? void 0 : status.type) === "running";
51099
+ const isComplete = (status == null ? void 0 : status.type) === "complete" || !status;
51100
+ const isCancelled = (status == null ? void 0 : status.type) === "incomplete" && status.reason === "cancelled";
51101
+ const errorMsg = (status == null ? void 0 : status.type) === "incomplete" ? String(status.error ?? status.reason ?? "Tool failed") : null;
51102
+ const openAsset = useAssetPanelStore((s) => s.openAsset);
51103
+ const handleOpen = React.useCallback(() => {
51104
+ if (!assetId) return;
51105
+ openAsset(assetId, {
51106
+ type: config2.assetType,
51107
+ slideNumber
51108
+ });
51109
+ if (config2.assetType === "presentation") {
51110
+ dispatchPresentationNavigate(assetId, slideNumber);
51111
+ }
51112
+ }, [assetId, config2.assetType, openAsset, slideNumber]);
51113
+ React.useEffect(() => {
51114
+ if (!config2.autoOpen || !isComplete || isCancelled || !assetId) {
51115
+ return;
51116
+ }
51117
+ const effectKey = toolCallId ?? `${toolName ?? "studio-tool"}:${assetId}:${slideNumber ?? "asset"}`;
51118
+ if (!markStudioToolEffect(effectKey)) {
51119
+ return;
51120
+ }
51121
+ const store = useAssetPanelStore.getState();
51122
+ store.openAsset(assetId, {
51123
+ type: config2.assetType,
51124
+ slideNumber
51125
+ });
51126
+ if (config2.assetType === "presentation") {
51127
+ dispatchPresentationNavigate(assetId, slideNumber);
51128
+ }
51129
+ }, [
51130
+ assetId,
51131
+ config2.assetType,
51132
+ config2.autoOpen,
51133
+ isCancelled,
51134
+ isComplete,
51135
+ slideNumber,
51136
+ toolCallId,
51137
+ toolName
51138
+ ]);
51139
+ return /* @__PURE__ */ jsxRuntime.jsx(
51140
+ ToolCard,
51141
+ {
51142
+ icon: config2.icon,
51143
+ status: (status == null ? void 0 : status.type) ?? "complete",
51144
+ title: isRunning ? config2.runningLabel(typedArgs) : config2.doneLabel(typedArgs, slideNumber),
51145
+ subtitle,
51146
+ badge: config2.badge,
51147
+ toolName,
51148
+ args: typedArgs,
51149
+ result,
51150
+ error: errorMsg,
51151
+ children: assetId && isComplete && !isCancelled && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-t border-border/40 px-4 py-2", children: /* @__PURE__ */ jsxRuntime.jsxs(
51152
+ "button",
51153
+ {
51154
+ type: "button",
51155
+ onClick: handleOpen,
51156
+ 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",
51157
+ children: [
51158
+ /* @__PURE__ */ jsxRuntime.jsx(ExternalLink, { className: "size-3" }),
51159
+ config2.openLabel(slideNumber)
51160
+ ]
51161
+ }
51162
+ ) })
51163
+ }
51164
+ );
51165
+ }
51166
+ function createStudioPtcToolUI(displayName, config2) {
51167
+ const Component = (props) => /* @__PURE__ */ jsxRuntime.jsx(StudioPtcToolUI, { config: config2, ...props });
51168
+ const Memoized = React.memo(Component);
51169
+ Memoized.displayName = displayName;
51170
+ return Memoized;
51171
+ }
51172
+ const getNameSubtitle = (args, result) => getStringField(result, ["title", "name", "asset_name"]) ?? getStringField(args, ["title", "name"]) ?? void 0;
51173
+ const getParagraphSubtitle = (args) => {
51174
+ const text2 = getStringField(args, ["text"]);
51175
+ return text2 ? truncate(text2, 80) : void 0;
51176
+ };
51177
+ const getSlideSubtitle = (args, _result, slideNumber) => {
51178
+ const layout = getStringField(args, ["layoutName", "layout_name"]) ?? getStringField(args, ["layoutPath", "layout_path"]);
51179
+ const slideLabel = slideNumber ? `Slide ${slideNumber}` : null;
51180
+ if (slideLabel && layout) return `${slideLabel} - ${truncate(layout, 48)}`;
51181
+ return slideLabel ?? (layout ? truncate(layout, 64) : void 0);
51182
+ };
51183
+ const StudioCreateWorkbookToolUI = createStudioPtcToolUI(
51184
+ "StudioCreateWorkbookToolUI",
51185
+ {
51186
+ icon: ChartColumn,
51187
+ assetType: "spreadsheet",
51188
+ badge: "Sheet",
51189
+ runningLabel: (args) => {
51190
+ const title = getStringField(args, ["title", "name"]);
51191
+ return title ? `Creating workbook "${title}"...` : "Creating workbook...";
51192
+ },
51193
+ doneLabel: () => "Workbook created",
51194
+ getSubtitle: getNameSubtitle,
51195
+ openLabel: () => "Open workbook",
51196
+ autoOpen: true
51197
+ }
51198
+ );
51199
+ const StudioAddSheetToolUI = createStudioPtcToolUI(
51200
+ "StudioAddSheetToolUI",
51201
+ {
51202
+ icon: ChartColumn,
51203
+ assetType: "spreadsheet",
51204
+ badge: "Sheet",
51205
+ runningLabel: (args) => {
51206
+ const name = getStringField(args, ["name", "sheetName", "sheet_name"]);
51207
+ return name ? `Adding sheet "${name}"...` : "Adding sheet...";
51208
+ },
51209
+ doneLabel: (args) => {
51210
+ const name = getStringField(args, ["name", "sheetName", "sheet_name"]);
51211
+ return name ? `Sheet added: ${name}` : "Sheet added";
51212
+ },
51213
+ getSubtitle: (args) => getStringField(args, ["name", "sheetName", "sheet_name"]) ?? void 0,
51214
+ openLabel: () => "Open workbook",
51215
+ autoOpen: true
51216
+ }
51217
+ );
51218
+ const StudioOpenWorkbookToolUI = createStudioPtcToolUI(
51219
+ "StudioOpenWorkbookToolUI",
51220
+ {
51221
+ icon: ChartColumn,
51222
+ assetType: "spreadsheet",
51223
+ badge: "Sheet",
51224
+ runningLabel: () => "Opening workbook...",
51225
+ doneLabel: () => "Workbook opened",
51226
+ openLabel: () => "Open workbook",
51227
+ autoOpen: true
51228
+ }
51229
+ );
51230
+ const StudioCreatePresentationToolUI = createStudioPtcToolUI(
51231
+ "StudioCreatePresentationToolUI",
51232
+ {
51233
+ icon: Presentation,
51234
+ assetType: "presentation",
51235
+ badge: "Deck",
51236
+ runningLabel: (args) => {
51237
+ const title = getStringField(args, ["title", "name"]);
51238
+ return title ? `Creating presentation "${title}"...` : "Creating presentation...";
51239
+ },
51240
+ doneLabel: () => "Presentation created",
51241
+ getSubtitle: getNameSubtitle,
51242
+ getSlideNumber: () => 1,
51243
+ openLabel: () => "Open presentation",
51244
+ autoOpen: true
51245
+ }
51246
+ );
51247
+ const StudioOpenPresentationToolUI = createStudioPtcToolUI(
51248
+ "StudioOpenPresentationToolUI",
51249
+ {
51250
+ icon: Presentation,
51251
+ assetType: "presentation",
51252
+ badge: "Deck",
51253
+ runningLabel: () => "Opening presentation...",
51254
+ doneLabel: () => "Presentation opened",
51255
+ getSlideNumber: () => 1,
51256
+ getSubtitle: (_args, _result, slideNumber) => slideNumber ? `Slide ${slideNumber}` : void 0,
51257
+ openLabel: () => "Open presentation",
51258
+ autoOpen: true
51259
+ }
51260
+ );
51261
+ const StudioAddSlideToolUI = createStudioPtcToolUI(
51262
+ "StudioAddSlideToolUI",
51263
+ {
51264
+ icon: Presentation,
51265
+ assetType: "presentation",
51266
+ badge: "Deck",
51267
+ runningLabel: () => "Adding slide...",
51268
+ doneLabel: (_args, slideNumber) => slideNumber ? `Slide ${slideNumber} added` : "Slide added",
51269
+ getSubtitle: getSlideSubtitle,
51270
+ getSlideNumber,
51271
+ openLabel: (slideNumber) => slideNumber ? `Open slide ${slideNumber}` : "Open presentation",
51272
+ autoOpen: true
51273
+ }
51274
+ );
51275
+ const StudioCreateDocumentToolUI = createStudioPtcToolUI(
51276
+ "StudioCreateDocumentToolUI",
51277
+ {
51278
+ icon: FileText,
51279
+ assetType: "document",
51280
+ badge: "Doc",
51281
+ runningLabel: (args) => {
51282
+ const title = getStringField(args, ["title", "name"]);
51283
+ return title ? `Creating document "${title}"...` : "Creating document...";
51284
+ },
51285
+ doneLabel: () => "Document created",
51286
+ getSubtitle: getNameSubtitle,
51287
+ openLabel: () => "Open document",
51288
+ autoOpen: true
51289
+ }
51290
+ );
51291
+ const StudioCreateParagraphToolUI = createStudioPtcToolUI(
51292
+ "StudioCreateParagraphToolUI",
51293
+ {
51294
+ icon: FileText,
51295
+ assetType: "document",
51296
+ badge: "Doc",
51297
+ runningLabel: () => "Adding paragraph...",
51298
+ doneLabel: () => "Paragraph added",
51299
+ getSubtitle: getParagraphSubtitle,
51300
+ openLabel: () => "Open document",
51301
+ autoOpen: true
51302
+ }
51303
+ );
51304
+ const StudioOpenDocumentToolUI = createStudioPtcToolUI(
51305
+ "StudioOpenDocumentToolUI",
51306
+ {
51307
+ icon: FileText,
51308
+ assetType: "document",
51309
+ badge: "Doc",
51310
+ runningLabel: () => "Opening document...",
51311
+ doneLabel: () => "Document opened",
51312
+ openLabel: () => "Open document",
51313
+ autoOpen: true
51314
+ }
51315
+ );
51016
51316
  const CreateEmailDraftToolUIImpl = ({
51017
51317
  toolName,
51018
51318
  args,
@@ -52456,6 +52756,16 @@ const TOOL_UI_REGISTRY = {
52456
52756
  create_new_sheet: CreateSheetToolUI,
52457
52757
  create_powerpoint_deck: CreatePresentationToolUI,
52458
52758
  create_new_notebook: CreateNotebookToolUI,
52759
+ // Studio SDK nested PTC tools
52760
+ CreateWorkbook: StudioCreateWorkbookToolUI,
52761
+ AddSheet: StudioAddSheetToolUI,
52762
+ OpenWorkbook: StudioOpenWorkbookToolUI,
52763
+ CreatePresentation: StudioCreatePresentationToolUI,
52764
+ OpenPresentation: StudioOpenPresentationToolUI,
52765
+ AddSlide: StudioAddSlideToolUI,
52766
+ CreateDocument: StudioCreateDocumentToolUI,
52767
+ OpenDocument: StudioOpenDocumentToolUI,
52768
+ CreateParagraph: StudioCreateParagraphToolUI,
52459
52769
  execute_presentation_code: ExecutePresentationCodeToolUI,
52460
52770
  run_python_code: RunPythonCodeToolUI,
52461
52771
  open_asset_in_workspace: OpenAssetToolUI,
@@ -53640,6 +53950,26 @@ function useAssetEmbed(assetId, options = {
53640
53950
  }, [assetId, readOnly, expiresInSeconds, backendUrl, apiKey, hasToken]);
53641
53951
  return { embedUrl, isLoading, error: error2 };
53642
53952
  }
53953
+ const ABSOLUTE_URL_PATTERN = /^[a-zA-Z][a-zA-Z\d+\-.]*:/;
53954
+ function buildAssetIframeSrc({
53955
+ embedUrl,
53956
+ assetType,
53957
+ slideNumber
53958
+ }) {
53959
+ const targetSlide = slideNumber;
53960
+ if (assetType !== "presentation" || typeof targetSlide !== "number" || !Number.isInteger(targetSlide) || targetSlide < 1) {
53961
+ return embedUrl;
53962
+ }
53963
+ try {
53964
+ const isAbsolute = ABSOLUTE_URL_PATTERN.test(embedUrl);
53965
+ const url = new URL(embedUrl, "https://athena.local");
53966
+ url.searchParams.set("slide", String(targetSlide));
53967
+ return isAbsolute ? url.toString() : `${url.pathname}${url.search}${url.hash}`;
53968
+ } catch {
53969
+ const separator = embedUrl.includes("?") ? "&" : "?";
53970
+ return `${embedUrl}${separator}slide=${targetSlide}`;
53971
+ }
53972
+ }
53643
53973
  const ASSET_TYPE_CONFIG = {
53644
53974
  presentation: { icon: Presentation, label: "Presentation" },
53645
53975
  spreadsheet: { icon: FileSpreadsheet, label: "Spreadsheet" },
@@ -53648,13 +53978,21 @@ const ASSET_TYPE_CONFIG = {
53648
53978
  unknown: { icon: File$1, label: "Asset" }
53649
53979
  };
53650
53980
  const AssetIframe = React.memo(
53651
- ({ tabId, tabName }) => {
53981
+ ({ tab }) => {
53652
53982
  const { backendUrl, apiKey, token } = useAthenaConfig();
53653
- const { embedUrl, isLoading, error: error2 } = useAssetEmbed(tabId, {
53983
+ const { embedUrl, isLoading, error: error2 } = useAssetEmbed(tab.id, {
53654
53984
  backendUrl,
53655
53985
  apiKey,
53656
53986
  token
53657
53987
  });
53988
+ const iframeSrc = React.useMemo(
53989
+ () => embedUrl ? buildAssetIframeSrc({
53990
+ embedUrl,
53991
+ assetType: tab.type,
53992
+ slideNumber: tab.slideNumber
53993
+ }) : null,
53994
+ [embedUrl, tab.slideNumber, tab.type]
53995
+ );
53658
53996
  if (isLoading) {
53659
53997
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-full items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center", children: [
53660
53998
  /* @__PURE__ */ jsxRuntime.jsx(LoaderCircle, { className: "mx-auto size-6 animate-spin text-muted-foreground" }),
@@ -53668,16 +54006,16 @@ const AssetIframe = React.memo(
53668
54006
  /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-0.5 line-clamp-2 break-words text-[10px] text-muted-foreground", children: error2 })
53669
54007
  ] }) });
53670
54008
  }
53671
- if (!embedUrl) return null;
54009
+ if (!iframeSrc) return null;
53672
54010
  return /* @__PURE__ */ jsxRuntime.jsx(
53673
54011
  "iframe",
53674
54012
  {
53675
- src: embedUrl,
54013
+ src: iframeSrc,
53676
54014
  width: "100%",
53677
54015
  height: "100%",
53678
54016
  frameBorder: "0",
53679
54017
  allow: "fullscreen",
53680
- title: tabName ?? `Asset ${tabId}`,
54018
+ title: tab.name ?? `Asset ${tab.id}`,
53681
54019
  className: "h-full w-full"
53682
54020
  }
53683
54021
  );
@@ -53739,7 +54077,7 @@ const PanelContent = ({
53739
54077
  }
53740
54078
  )
53741
54079
  ] }),
53742
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(AssetIframe, { tabId: tab.id, tabName: tab.name }) })
54080
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(AssetIframe, { tab }) })
53743
54081
  ]
53744
54082
  },
53745
54083
  tab.id
@@ -53749,7 +54087,7 @@ const PanelContent = ({
53749
54087
  "div",
53750
54088
  {
53751
54089
  className: isActive2 ? "h-full w-full" : "hidden",
53752
- children: /* @__PURE__ */ jsxRuntime.jsx(AssetIframe, { tabId: tab.id, tabName: tab.name })
54090
+ children: /* @__PURE__ */ jsxRuntime.jsx(AssetIframe, { tab })
53753
54091
  },
53754
54092
  tab.id
53755
54093
  );