@athenaintel/react 0.10.27 → 0.10.28

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.js CHANGED
@@ -14116,7 +14116,7 @@ const useAssetPanelStore = create()(
14116
14116
  ...t,
14117
14117
  name: meta.name ?? t.name,
14118
14118
  type: meta.type ?? t.type,
14119
- slideNumber: meta.slideNumber ?? t.slideNumber
14119
+ slideNumber: "slideNumber" in meta ? meta.slideNumber : t.slideNumber
14120
14120
  } : t
14121
14121
  ) : s.tabs;
14122
14122
  return { isOpen: true, tabs, activeTabId: assetId };
@@ -50007,18 +50007,6 @@ function AssetToolCard({
50007
50007
  const assetId = extractAssetId$1(result);
50008
50008
  const title = extractTitle(argsText, result);
50009
50009
  const assetType = toolMetaToAssetType(toolName);
50010
- const wasCompleteAtMount = useRef(isComplete);
50011
- useEffect(() => {
50012
- if (isComplete && !isCancelled && assetId && !wasCompleteAtMount.current) {
50013
- const store = useAssetPanelStore.getState();
50014
- if (store.markAutoOpened(assetId)) {
50015
- store.openAsset(assetId, {
50016
- name: title ?? void 0,
50017
- type: assetType
50018
- });
50019
- }
50020
- }
50021
- }, [isComplete, isCancelled, assetId, title, assetType]);
50022
50010
  const success = isComplete && isResultSuccess(result);
50023
50011
  return /* @__PURE__ */ jsxs("div", { className: cn(
50024
50012
  "aui-tool-fallback-root my-3 w-full rounded-xl border border-border/60 bg-background py-2.5 shadow-sm",
@@ -50580,6 +50568,32 @@ function normalizeResult(result) {
50580
50568
  function truncate(text2, max2) {
50581
50569
  return text2.length > max2 ? `${text2.slice(0, max2)}...` : text2;
50582
50570
  }
50571
+ function isSdkToolDebugEnabled() {
50572
+ var _a2, _b;
50573
+ try {
50574
+ const hostname = (_a2 = globalThis.location) == null ? void 0 : _a2.hostname;
50575
+ if (hostname === "localhost" || hostname === "127.0.0.1" || hostname === "::1") {
50576
+ return true;
50577
+ }
50578
+ return ((_b = globalThis.localStorage) == null ? void 0 : _b.getItem("athena:sdk:debug")) === "1";
50579
+ } catch {
50580
+ return false;
50581
+ }
50582
+ }
50583
+ function stringifyDebugPayload(payload) {
50584
+ return JSON.stringify(payload, (_key, value) => {
50585
+ if (typeof value === "string" && value.length > 800) {
50586
+ return `${value.slice(0, 800)}... [truncated ${value.length - 800} chars]`;
50587
+ }
50588
+ return value;
50589
+ });
50590
+ }
50591
+ function logDebugPayload(label, payload) {
50592
+ if (!isSdkToolDebugEnabled()) {
50593
+ return;
50594
+ }
50595
+ console.info(`${label} ${stringifyDebugPayload(payload)}`);
50596
+ }
50583
50597
  function formatToolName(name) {
50584
50598
  return name.replace(/_/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
50585
50599
  }
@@ -50890,6 +50904,20 @@ function getNumberField(source, keys2) {
50890
50904
  }
50891
50905
  return null;
50892
50906
  }
50907
+ const PRESENTATION_CODE_SLIDE_NUMBER_KEYS = [
50908
+ "slideNumber",
50909
+ "slide_number",
50910
+ "targetSlideNumber",
50911
+ "target_slide_number",
50912
+ "targetSlide",
50913
+ "target_slide"
50914
+ ];
50915
+ const PRESENTATION_CODE_SLIDE_INDEX_KEYS = [
50916
+ "slideIndex",
50917
+ "slide_index",
50918
+ "targetSlideIndex",
50919
+ "target_slide_index"
50920
+ ];
50893
50921
  function getStudioAssetId({
50894
50922
  args,
50895
50923
  result
@@ -50897,41 +50925,42 @@ function getStudioAssetId({
50897
50925
  const id = getStringField(result, ["asset_id", "assetId", "id"]) ?? getStringField(args, ["asset_id", "assetId", "id"]);
50898
50926
  return (id == null ? void 0 : id.startsWith("asset_")) ? id : null;
50899
50927
  }
50900
- function getSlideNumber(args) {
50901
- const explicit = getNumberField(args, ["slideNumber", "slide_number"]);
50928
+ function getPresentationCodeDeckId(code2) {
50929
+ const match2 = code2.match(/\bdeck_id\s*=\s*["']([^"']+)["']/);
50930
+ const deckId = match2 == null ? void 0 : match2[1];
50931
+ return (deckId == null ? void 0 : deckId.startsWith("asset_")) ? deckId : null;
50932
+ }
50933
+ function getPresentationCodeSlideNumberFromFields(source) {
50934
+ const explicit = getNumberField(source, PRESENTATION_CODE_SLIDE_NUMBER_KEYS);
50902
50935
  if (explicit != null && Number.isInteger(explicit) && explicit >= 1) {
50903
50936
  return explicit;
50904
50937
  }
50905
- const zeroBasedIndex = getNumberField(args, ["index", "slideIndex", "slide_index"]);
50938
+ const zeroBasedIndex = getNumberField(source, PRESENTATION_CODE_SLIDE_INDEX_KEYS);
50906
50939
  if (zeroBasedIndex != null && Number.isInteger(zeroBasedIndex) && zeroBasedIndex >= 0) {
50907
50940
  return zeroBasedIndex + 1;
50908
50941
  }
50909
50942
  return void 0;
50910
50943
  }
50911
- const completedStudioToolEffects = /* @__PURE__ */ new Set();
50912
- const MAX_COMPLETED_STUDIO_TOOL_EFFECTS = 500;
50913
- function markStudioToolEffect(key) {
50914
- if (completedStudioToolEffects.has(key)) {
50915
- return false;
50916
- }
50917
- if (completedStudioToolEffects.size >= MAX_COMPLETED_STUDIO_TOOL_EFFECTS) {
50918
- const oldest = completedStudioToolEffects.values().next().value;
50919
- if (oldest) completedStudioToolEffects.delete(oldest);
50944
+ function getPresentationCodeSlideNumberFromText(text2) {
50945
+ const match2 = text2 == null ? void 0 : text2.match(/\bslide\s*(?:#|number\s*)?(\d+)\b/i);
50946
+ if (!match2) {
50947
+ return void 0;
50920
50948
  }
50921
- completedStudioToolEffects.add(key);
50922
- return true;
50949
+ const slideNumber = Number.parseInt(match2[1] ?? "", 10);
50950
+ return Number.isInteger(slideNumber) && slideNumber >= 1 ? slideNumber : void 0;
50923
50951
  }
50924
- function dispatchPresentationNavigate(assetId, slideNumber) {
50925
- const targetSlide = slideNumber;
50926
- if (typeof targetSlide !== "number" || !Number.isInteger(targetSlide) || targetSlide < 1) {
50927
- return;
50928
- }
50929
- window.dispatchEvent(
50930
- new CustomEvent("pptx-studio-navigate", {
50931
- detail: { assetId, slideNumber: targetSlide }
50932
- })
50952
+ function getPresentationCodeSlideNumber({
50953
+ args,
50954
+ result
50955
+ }) {
50956
+ return getPresentationCodeSlideNumberFromFields(args) ?? getPresentationCodeSlideNumberFromFields(result) ?? getPresentationCodeSlideNumberFromText(
50957
+ getStringField(args, ["summary", "title", "description"])
50933
50958
  );
50934
50959
  }
50960
+ function getAddSlideNumber(args) {
50961
+ const index2 = getNumberField(args, ["index"]);
50962
+ return index2 != null && Number.isInteger(index2) && index2 >= 0 ? index2 + 1 : void 0;
50963
+ }
50935
50964
  function CreateAssetToolUIImpl({
50936
50965
  icon: Icon2,
50937
50966
  assetType,
@@ -50952,18 +50981,6 @@ function CreateAssetToolUIImpl({
50952
50981
  const isCancelled = (status == null ? void 0 : status.type) === "incomplete" && status.reason === "cancelled";
50953
50982
  const errorMsg = (status == null ? void 0 : status.type) === "incomplete" ? status.error : null;
50954
50983
  const openAsset = useAssetPanelStore((s) => s.openAsset);
50955
- const wasCompleteAtMount = useRef(isComplete);
50956
- useEffect(() => {
50957
- if (isComplete && !isCancelled && assetId && !wasCompleteAtMount.current) {
50958
- const store = useAssetPanelStore.getState();
50959
- if (store.markAutoOpened(assetId)) {
50960
- store.openAsset(assetId, {
50961
- name: createdName || name || void 0,
50962
- type: assetType
50963
- });
50964
- }
50965
- }
50966
- }, [isComplete, isCancelled, assetId, createdName, name, assetType]);
50967
50984
  const handleOpen = () => {
50968
50985
  if (assetId) {
50969
50986
  openAsset(assetId, {
@@ -51041,10 +51058,23 @@ const CreatePresentationToolUI = memo(
51041
51058
  CreatePresentationToolUIImpl
51042
51059
  );
51043
51060
  CreatePresentationToolUI.displayName = "CreatePresentationToolUI";
51061
+ function openStudioAsset({
51062
+ assetId,
51063
+ assetType,
51064
+ slideNumber,
51065
+ preserveExistingSlide
51066
+ }) {
51067
+ const store = useAssetPanelStore.getState();
51068
+ const existing = store.tabs.find((tab) => tab.id === assetId);
51069
+ const shouldKeepCurrentSlide = preserveExistingSlide && existing;
51070
+ store.openAsset(assetId, {
51071
+ type: assetType,
51072
+ ...!shouldKeepCurrentSlide && slideNumber !== void 0 ? { slideNumber } : {}
51073
+ });
51074
+ }
51044
51075
  function StudioPtcToolUI({
51045
51076
  config: config2,
51046
51077
  toolName,
51047
- toolCallId,
51048
51078
  args,
51049
51079
  result,
51050
51080
  status
@@ -51059,42 +51089,57 @@ function StudioPtcToolUI({
51059
51089
  const isComplete = (status == null ? void 0 : status.type) === "complete" || !status;
51060
51090
  const isCancelled = (status == null ? void 0 : status.type) === "incomplete" && status.reason === "cancelled";
51061
51091
  const errorMsg = (status == null ? void 0 : status.type) === "incomplete" ? String(status.error ?? status.reason ?? "Tool failed") : null;
51062
- const openAsset = useAssetPanelStore((s) => s.openAsset);
51063
51092
  const handleOpen = useCallback(() => {
51064
51093
  if (!assetId) return;
51065
- openAsset(assetId, {
51066
- type: config2.assetType,
51067
- slideNumber
51068
- });
51069
- if (config2.assetType === "presentation") {
51070
- dispatchPresentationNavigate(assetId, slideNumber);
51094
+ if (toolName === "AddSlide") {
51095
+ logDebugPayload("[Athena SDK AddSlide] manual open", {
51096
+ args: typedArgs,
51097
+ parsedResult: data,
51098
+ rawResult: result,
51099
+ assetId,
51100
+ slideNumber
51101
+ });
51071
51102
  }
51072
- }, [assetId, config2.assetType, openAsset, slideNumber]);
51103
+ openStudioAsset({
51104
+ assetId,
51105
+ assetType: config2.assetType,
51106
+ slideNumber,
51107
+ preserveExistingSlide: config2.preserveExistingSlide
51108
+ });
51109
+ }, [
51110
+ assetId,
51111
+ config2.assetType,
51112
+ config2.preserveExistingSlide,
51113
+ data,
51114
+ result,
51115
+ slideNumber,
51116
+ toolName,
51117
+ typedArgs
51118
+ ]);
51073
51119
  useEffect(() => {
51074
- if (!config2.autoOpen || !isComplete || isCancelled || !assetId) {
51120
+ if (toolName !== "AddSlide") {
51075
51121
  return;
51076
51122
  }
51077
- const effectKey = toolCallId ?? `${toolName ?? "studio-tool"}:${assetId}:${slideNumber ?? "asset"}`;
51078
- if (!markStudioToolEffect(effectKey)) {
51079
- return;
51080
- }
51081
- const store = useAssetPanelStore.getState();
51082
- store.openAsset(assetId, {
51083
- type: config2.assetType,
51084
- slideNumber
51123
+ logDebugPayload("[Athena SDK AddSlide] tool state", {
51124
+ args: typedArgs,
51125
+ parsedResult: data,
51126
+ rawResult: result,
51127
+ status,
51128
+ assetId,
51129
+ slideNumber,
51130
+ isComplete,
51131
+ isCancelled
51085
51132
  });
51086
- if (config2.assetType === "presentation") {
51087
- dispatchPresentationNavigate(assetId, slideNumber);
51088
- }
51089
51133
  }, [
51090
51134
  assetId,
51091
- config2.assetType,
51092
- config2.autoOpen,
51135
+ data,
51093
51136
  isCancelled,
51094
51137
  isComplete,
51138
+ result,
51095
51139
  slideNumber,
51096
- toolCallId,
51097
- toolName
51140
+ status,
51141
+ toolName,
51142
+ typedArgs
51098
51143
  ]);
51099
51144
  return /* @__PURE__ */ jsx(
51100
51145
  ToolCard,
@@ -51152,8 +51197,7 @@ const StudioCreateWorkbookToolUI = createStudioPtcToolUI(
51152
51197
  },
51153
51198
  doneLabel: () => "Workbook created",
51154
51199
  getSubtitle: getNameSubtitle,
51155
- openLabel: () => "Open workbook",
51156
- autoOpen: true
51200
+ openLabel: () => "Open workbook"
51157
51201
  }
51158
51202
  );
51159
51203
  const StudioAddSheetToolUI = createStudioPtcToolUI(
@@ -51171,8 +51215,7 @@ const StudioAddSheetToolUI = createStudioPtcToolUI(
51171
51215
  return name ? `Sheet added: ${name}` : "Sheet added";
51172
51216
  },
51173
51217
  getSubtitle: (args) => getStringField(args, ["name", "sheetName", "sheet_name"]) ?? void 0,
51174
- openLabel: () => "Open workbook",
51175
- autoOpen: true
51218
+ openLabel: () => "Open workbook"
51176
51219
  }
51177
51220
  );
51178
51221
  const StudioOpenWorkbookToolUI = createStudioPtcToolUI(
@@ -51183,8 +51226,7 @@ const StudioOpenWorkbookToolUI = createStudioPtcToolUI(
51183
51226
  badge: "Sheet",
51184
51227
  runningLabel: () => "Opening workbook...",
51185
51228
  doneLabel: () => "Workbook opened",
51186
- openLabel: () => "Open workbook",
51187
- autoOpen: true
51229
+ openLabel: () => "Open workbook"
51188
51230
  }
51189
51231
  );
51190
51232
  const StudioCreatePresentationToolUI = createStudioPtcToolUI(
@@ -51200,8 +51242,7 @@ const StudioCreatePresentationToolUI = createStudioPtcToolUI(
51200
51242
  doneLabel: () => "Presentation created",
51201
51243
  getSubtitle: getNameSubtitle,
51202
51244
  getSlideNumber: () => 1,
51203
- openLabel: () => "Open presentation",
51204
- autoOpen: true
51245
+ openLabel: () => "Open presentation"
51205
51246
  }
51206
51247
  );
51207
51248
  const StudioOpenPresentationToolUI = createStudioPtcToolUI(
@@ -51215,7 +51256,7 @@ const StudioOpenPresentationToolUI = createStudioPtcToolUI(
51215
51256
  getSlideNumber: () => 1,
51216
51257
  getSubtitle: (_args, _result, slideNumber) => slideNumber ? `Slide ${slideNumber}` : void 0,
51217
51258
  openLabel: () => "Open presentation",
51218
- autoOpen: true
51259
+ preserveExistingSlide: true
51219
51260
  }
51220
51261
  );
51221
51262
  const StudioAddSlideToolUI = createStudioPtcToolUI(
@@ -51227,9 +51268,8 @@ const StudioAddSlideToolUI = createStudioPtcToolUI(
51227
51268
  runningLabel: () => "Adding slide...",
51228
51269
  doneLabel: (_args, slideNumber) => slideNumber ? `Slide ${slideNumber} added` : "Slide added",
51229
51270
  getSubtitle: getSlideSubtitle,
51230
- getSlideNumber,
51231
- openLabel: (slideNumber) => slideNumber ? `Open slide ${slideNumber}` : "Open presentation",
51232
- autoOpen: true
51271
+ getSlideNumber: (args) => getAddSlideNumber(args) ?? 1,
51272
+ openLabel: (slideNumber) => slideNumber ? `Open slide ${slideNumber}` : "Open presentation"
51233
51273
  }
51234
51274
  );
51235
51275
  const StudioCreateDocumentToolUI = createStudioPtcToolUI(
@@ -51244,8 +51284,7 @@ const StudioCreateDocumentToolUI = createStudioPtcToolUI(
51244
51284
  },
51245
51285
  doneLabel: () => "Document created",
51246
51286
  getSubtitle: getNameSubtitle,
51247
- openLabel: () => "Open document",
51248
- autoOpen: true
51287
+ openLabel: () => "Open document"
51249
51288
  }
51250
51289
  );
51251
51290
  const StudioCreateParagraphToolUI = createStudioPtcToolUI(
@@ -51257,8 +51296,7 @@ const StudioCreateParagraphToolUI = createStudioPtcToolUI(
51257
51296
  runningLabel: () => "Adding paragraph...",
51258
51297
  doneLabel: () => "Paragraph added",
51259
51298
  getSubtitle: getParagraphSubtitle,
51260
- openLabel: () => "Open document",
51261
- autoOpen: true
51299
+ openLabel: () => "Open document"
51262
51300
  }
51263
51301
  );
51264
51302
  const StudioOpenDocumentToolUI = createStudioPtcToolUI(
@@ -51269,8 +51307,7 @@ const StudioOpenDocumentToolUI = createStudioPtcToolUI(
51269
51307
  badge: "Doc",
51270
51308
  runningLabel: () => "Opening document...",
51271
51309
  doneLabel: () => "Document opened",
51272
- openLabel: () => "Open document",
51273
- autoOpen: true
51310
+ openLabel: () => "Open document"
51274
51311
  }
51275
51312
  );
51276
51313
  const CreateEmailDraftToolUIImpl = ({
@@ -51778,7 +51815,7 @@ const ExecutePresentationCodeToolUIImpl = ({
51778
51815
  const typedArgs = args;
51779
51816
  const code2 = (typedArgs == null ? void 0 : typedArgs.code) ?? "";
51780
51817
  const summary = (typedArgs == null ? void 0 : typedArgs.summary) ?? null;
51781
- const deckIdFromArgs = typeof (typedArgs == null ? void 0 : typedArgs.deck_id) === "string" ? typedArgs.deck_id : null;
51818
+ const deckIdFromArgs = getStringField(typedArgs, ["deck_id", "deckId", "asset_id", "assetId"]) ?? getPresentationCodeDeckId(code2);
51782
51819
  const isRunning = (status == null ? void 0 : status.type) === "running";
51783
51820
  const isComplete = (status == null ? void 0 : status.type) === "complete";
51784
51821
  const errorMsg = (status == null ? void 0 : status.type) === "incomplete" ? status.error : null;
@@ -51786,21 +51823,55 @@ const ExecutePresentationCodeToolUIImpl = ({
51786
51823
  () => isComplete ? parsePythonResult(result) : null,
51787
51824
  [result, isComplete]
51788
51825
  );
51826
+ const resultData = useMemo(() => normalizeResult(result), [result]);
51789
51827
  const outputText = parsed ? getExecutionTextOutput(parsed) : null;
51790
- const assetId = (parsed == null ? void 0 : parsed.assetId) ?? null;
51828
+ const targetSlideNumber = getPresentationCodeSlideNumber({
51829
+ args: typedArgs,
51830
+ result: resultData
51831
+ });
51791
51832
  const deckId = (parsed == null ? void 0 : parsed.deckId) ?? deckIdFromArgs;
51833
+ const assetId = (parsed == null ? void 0 : parsed.assetId) ?? ((deckId == null ? void 0 : deckId.startsWith("asset_")) ? deckId : null);
51792
51834
  const hasError = parsed && (parsed.error || parsed.exception);
51793
51835
  const openAsset = useAssetPanelStore((s) => s.openAsset);
51794
- const wasCompleteAtMount = useRef(isComplete);
51795
51836
  useEffect(() => {
51796
- if (!isComplete || !assetId || wasCompleteAtMount.current) {
51837
+ if (!isComplete) {
51797
51838
  return;
51798
51839
  }
51799
- const store = useAssetPanelStore.getState();
51800
- if (store.markAutoOpened(assetId)) {
51801
- store.openAsset(assetId, { type: "presentation" });
51840
+ logDebugPayload("[Athena SDK execute_presentation_code] tool state", {
51841
+ args: typedArgs,
51842
+ parsedResult: resultData,
51843
+ status,
51844
+ assetId,
51845
+ deckId,
51846
+ targetSlideNumber,
51847
+ outputText
51848
+ });
51849
+ }, [
51850
+ assetId,
51851
+ deckId,
51852
+ isComplete,
51853
+ outputText,
51854
+ resultData,
51855
+ status,
51856
+ targetSlideNumber,
51857
+ typedArgs
51858
+ ]);
51859
+ const openPresentation = useCallback(() => {
51860
+ if (!assetId) {
51861
+ return;
51802
51862
  }
51803
- }, [assetId, isComplete]);
51863
+ logDebugPayload("[Athena SDK execute_presentation_code] open deck", {
51864
+ args: typedArgs,
51865
+ parsedResult: resultData,
51866
+ assetId,
51867
+ deckId,
51868
+ targetSlideNumber
51869
+ });
51870
+ openAsset(assetId, {
51871
+ type: "presentation",
51872
+ ...targetSlideNumber !== void 0 ? { slideNumber: targetSlideNumber } : {}
51873
+ });
51874
+ }, [assetId, deckId, openAsset, resultData, targetSlideNumber, typedArgs]);
51804
51875
  return /* @__PURE__ */ jsxs(
51805
51876
  ToolCard,
51806
51877
  {
@@ -51823,11 +51894,11 @@ const ExecutePresentationCodeToolUIImpl = ({
51823
51894
  "button",
51824
51895
  {
51825
51896
  type: "button",
51826
- onClick: () => openAsset(assetId, { type: "presentation" }),
51897
+ onClick: openPresentation,
51827
51898
  className: "flex shrink-0 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",
51828
51899
  children: [
51829
51900
  /* @__PURE__ */ jsx(ExternalLink, { className: "size-3" }),
51830
- "Open deck"
51901
+ targetSlideNumber ? `Open slide ${targetSlideNumber}` : "Open deck"
51831
51902
  ]
51832
51903
  }
51833
51904
  )
@@ -51886,15 +51957,6 @@ const OpenAssetToolUIImpl = ({
51886
51957
  const isCancelled = (status == null ? void 0 : status.type) === "incomplete" && status.reason === "cancelled";
51887
51958
  const errorMsg = (status == null ? void 0 : status.type) === "incomplete" ? status.error : null;
51888
51959
  const openAsset = useAssetPanelStore((s) => s.openAsset);
51889
- const wasCompleteAtMount = useRef(isComplete);
51890
- useEffect(() => {
51891
- if (isComplete && !isCancelled && assetId && !wasCompleteAtMount.current) {
51892
- const store = useAssetPanelStore.getState();
51893
- if (store.markAutoOpened(assetId)) {
51894
- store.openAsset(assetId);
51895
- }
51896
- }
51897
- }, [isComplete, isCancelled, assetId]);
51898
51960
  return /* @__PURE__ */ jsx(
51899
51961
  ToolCard,
51900
51962
  {
@@ -52633,18 +52695,6 @@ const CaptureMomentToolUIImpl = ({
52633
52695
  const isComplete = (status == null ? void 0 : status.type) === "complete" || !status;
52634
52696
  const isCancelled = (status == null ? void 0 : status.type) === "incomplete" && status.reason === "cancelled";
52635
52697
  const openAsset = useAssetPanelStore((s) => s.openAsset);
52636
- const wasCompleteAtMount = useRef(isComplete);
52637
- useEffect(() => {
52638
- if (isComplete && !isCancelled && createdAssetId && !wasCompleteAtMount.current) {
52639
- const store = useAssetPanelStore.getState();
52640
- if (store.markAutoOpened(createdAssetId)) {
52641
- store.openAsset(createdAssetId, {
52642
- name: void 0,
52643
- type: "unknown"
52644
- });
52645
- }
52646
- }
52647
- }, [isComplete, isCancelled, createdAssetId, resultType]);
52648
52698
  const handleOpen = () => {
52649
52699
  if (createdAssetId) {
52650
52700
  openAsset(createdAssetId, {
@@ -52704,6 +52754,153 @@ const CaptureMomentToolUI = memo(
52704
52754
  CaptureMomentToolUIImpl
52705
52755
  );
52706
52756
  CaptureMomentToolUI.displayName = "CaptureMomentToolUI";
52757
+ function normalizeContentResult(result) {
52758
+ if (Array.isArray(result)) {
52759
+ return result;
52760
+ }
52761
+ if (typeof result === "string") {
52762
+ try {
52763
+ const parsed = JSON.parse(result);
52764
+ return normalizeContentResult(parsed);
52765
+ } catch {
52766
+ return [];
52767
+ }
52768
+ }
52769
+ if (result && typeof result === "object") {
52770
+ const obj = result;
52771
+ if (Array.isArray(obj.result)) {
52772
+ return obj.result;
52773
+ }
52774
+ if (typeof obj.result === "string") {
52775
+ return normalizeContentResult(obj.result);
52776
+ }
52777
+ if (Array.isArray(obj.content)) {
52778
+ return obj.content;
52779
+ }
52780
+ }
52781
+ return [];
52782
+ }
52783
+ function getSlideScreenshotResult(result) {
52784
+ let text2 = null;
52785
+ let imageUrl = null;
52786
+ let mediaType = null;
52787
+ let s3Key = null;
52788
+ for (const item of normalizeContentResult(result)) {
52789
+ if (!item || typeof item !== "object") {
52790
+ continue;
52791
+ }
52792
+ const part = item;
52793
+ if (!text2 && part.type === "text" && typeof part.text === "string") {
52794
+ text2 = part.text;
52795
+ continue;
52796
+ }
52797
+ if (part.type !== "image") {
52798
+ continue;
52799
+ }
52800
+ const source = part.source && typeof part.source === "object" ? part.source : {};
52801
+ if (!imageUrl) {
52802
+ imageUrl = getStringField(source, ["presigned_url", "url"]) ?? getStringField(part, ["url", "image_url"]);
52803
+ }
52804
+ if (!mediaType) {
52805
+ mediaType = getStringField(source, ["media_type", "mime_type"]) ?? getStringField(part, ["media_type", "mime_type"]);
52806
+ }
52807
+ if (!s3Key) {
52808
+ s3Key = getStringField(source, ["data", "s3_key"]);
52809
+ }
52810
+ }
52811
+ return { text: text2, imageUrl, mediaType, s3Key };
52812
+ }
52813
+ const CaptureSlideScreenshotToolUIImpl = ({
52814
+ toolName,
52815
+ args,
52816
+ result,
52817
+ status
52818
+ }) => {
52819
+ const typedArgs = args;
52820
+ const assetId = getStringField(typedArgs, ["asset_id", "assetId"]);
52821
+ const slideNumber = getNumberField(typedArgs, ["slide_number", "slideNumber"]) ?? void 0;
52822
+ const { text: text2, imageUrl, mediaType } = useMemo(
52823
+ () => getSlideScreenshotResult(result),
52824
+ [result]
52825
+ );
52826
+ const isRunning = (status == null ? void 0 : status.type) === "running";
52827
+ const isComplete = (status == null ? void 0 : status.type) === "complete" || !status;
52828
+ const isCancelled = (status == null ? void 0 : status.type) === "incomplete" && status.reason === "cancelled";
52829
+ const errorMsg = (status == null ? void 0 : status.type) === "incomplete" ? String(status.error ?? status.reason ?? "Capture failed") : null;
52830
+ const openAsset = useAssetPanelStore((s) => s.openAsset);
52831
+ const handleOpenSlide = useCallback(() => {
52832
+ if (!assetId) {
52833
+ return;
52834
+ }
52835
+ openAsset(assetId, {
52836
+ type: "presentation",
52837
+ ...slideNumber ? { slideNumber } : {}
52838
+ });
52839
+ }, [assetId, openAsset, slideNumber]);
52840
+ const subtitle = [
52841
+ slideNumber ? `Slide ${slideNumber}` : null,
52842
+ assetId ? truncate(assetId, 34) : null
52843
+ ].filter((value) => Boolean(value)).join(" · ");
52844
+ return /* @__PURE__ */ jsxs(
52845
+ ToolCard,
52846
+ {
52847
+ icon: Camera,
52848
+ status: (status == null ? void 0 : status.type) ?? "complete",
52849
+ title: isRunning ? "Capturing slide screenshot..." : errorMsg ? "Slide screenshot failed" : "Slide screenshot captured",
52850
+ subtitle: subtitle || void 0,
52851
+ badge: slideNumber ? `Slide ${slideNumber}` : mediaType ?? void 0,
52852
+ toolName,
52853
+ args: typedArgs,
52854
+ result,
52855
+ error: errorMsg,
52856
+ children: [
52857
+ isComplete && !isCancelled && imageUrl && /* @__PURE__ */ jsxs("div", { className: "border-t border-border/40 p-3", children: [
52858
+ /* @__PURE__ */ jsx("div", { className: "overflow-hidden rounded-lg border border-border/50 bg-muted/20", children: /* @__PURE__ */ jsx(
52859
+ "img",
52860
+ {
52861
+ src: imageUrl,
52862
+ alt: slideNumber ? `Slide ${slideNumber} screenshot` : "Slide screenshot",
52863
+ className: "aspect-video w-full object-contain",
52864
+ loading: "lazy"
52865
+ }
52866
+ ) }),
52867
+ text2 && /* @__PURE__ */ jsx("p", { className: "mt-2 text-[11px] leading-relaxed text-muted-foreground", children: truncate(text2, 160) })
52868
+ ] }),
52869
+ isComplete && !isCancelled && assetId && /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap gap-2 border-t border-border/40 px-4 py-2", children: [
52870
+ /* @__PURE__ */ jsxs(
52871
+ "button",
52872
+ {
52873
+ type: "button",
52874
+ onClick: handleOpenSlide,
52875
+ 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",
52876
+ children: [
52877
+ /* @__PURE__ */ jsx(ExternalLink, { className: "size-3" }),
52878
+ slideNumber ? `Open slide ${slideNumber}` : "Open presentation"
52879
+ ]
52880
+ }
52881
+ ),
52882
+ imageUrl && /* @__PURE__ */ jsxs(
52883
+ "a",
52884
+ {
52885
+ href: imageUrl,
52886
+ target: "_blank",
52887
+ rel: "noreferrer",
52888
+ 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",
52889
+ children: [
52890
+ /* @__PURE__ */ jsx(Image, { className: "size-3" }),
52891
+ "Open image"
52892
+ ]
52893
+ }
52894
+ )
52895
+ ] })
52896
+ ]
52897
+ }
52898
+ );
52899
+ };
52900
+ const CaptureSlideScreenshotToolUI = memo(
52901
+ CaptureSlideScreenshotToolUIImpl
52902
+ );
52903
+ CaptureSlideScreenshotToolUI.displayName = "CaptureSlideScreenshotToolUI";
52707
52904
  const TOOL_UI_REGISTRY = {
52708
52905
  search: WebSearchToolUI,
52709
52906
  browse: BrowseToolUI,
@@ -52731,6 +52928,7 @@ const TOOL_UI_REGISTRY = {
52731
52928
  open_asset_in_workspace: OpenAssetToolUI,
52732
52929
  // Media capture
52733
52930
  capture_moment: CaptureMomentToolUI,
52931
+ capture_slide_screenshot: CaptureSlideScreenshotToolUI,
52734
52932
  // Spreadsheet toolkit
52735
52933
  update_sheet_range: UpdateSheetRangeToolUI,
52736
52934
  // Database toolkit
@@ -53840,10 +54038,37 @@ const AthenaUserMessage = ({
53840
54038
  }
53841
54039
  );
53842
54040
  const embedCache = /* @__PURE__ */ new Map();
54041
+ function resolveAssetEmbedUrl({
54042
+ embedUrl,
54043
+ appUrl
54044
+ }) {
54045
+ if (!appUrl) {
54046
+ return embedUrl;
54047
+ }
54048
+ try {
54049
+ const resolvedEmbedUrl = new URL(embedUrl);
54050
+ const resolvedAppUrl = new URL(appUrl);
54051
+ if (!resolvedEmbedUrl.pathname.startsWith("/embed/")) {
54052
+ return embedUrl;
54053
+ }
54054
+ resolvedEmbedUrl.protocol = resolvedAppUrl.protocol;
54055
+ resolvedEmbedUrl.host = resolvedAppUrl.host;
54056
+ return resolvedEmbedUrl.toString();
54057
+ } catch {
54058
+ return embedUrl;
54059
+ }
54060
+ }
53843
54061
  function useAssetEmbed(assetId, options = {
53844
54062
  backendUrl: ""
53845
54063
  }) {
53846
- const { readOnly = false, expiresInSeconds = 60 * 60 * 24 * 30, backendUrl, apiKey, token } = options;
54064
+ const {
54065
+ readOnly = false,
54066
+ expiresInSeconds = 60 * 60 * 24 * 30,
54067
+ backendUrl,
54068
+ appUrl,
54069
+ apiKey,
54070
+ token
54071
+ } = options;
53847
54072
  const [embedUrl, setEmbedUrl] = useState(null);
53848
54073
  const [isLoading, setIsLoading] = useState(false);
53849
54074
  const [error2, setError] = useState(null);
@@ -53860,7 +54085,7 @@ function useAssetEmbed(assetId, options = {
53860
54085
  return;
53861
54086
  }
53862
54087
  const authContext = hasToken ? "token" : apiKey ?? "anon";
53863
- const cacheKey = `${assetId}:${readOnly}:${authContext}`;
54088
+ const cacheKey = `${assetId}:${readOnly}:${authContext}:${appUrl ?? ""}`;
53864
54089
  const cached2 = embedCache.get(cacheKey);
53865
54090
  if (cached2 && cached2.expiresAt > Date.now() / 1e3) {
53866
54091
  setEmbedUrl(cached2.url);
@@ -53898,8 +54123,12 @@ function useAssetEmbed(assetId, options = {
53898
54123
  }
53899
54124
  return res.json();
53900
54125
  }).then((data) => {
53901
- embedCache.set(cacheKey, { url: data.embed_url, expiresAt: data.expires_at });
53902
- setEmbedUrl(data.embed_url);
54126
+ const resolvedEmbedUrl = resolveAssetEmbedUrl({
54127
+ embedUrl: data.embed_url,
54128
+ appUrl
54129
+ });
54130
+ embedCache.set(cacheKey, { url: resolvedEmbedUrl, expiresAt: data.expires_at });
54131
+ setEmbedUrl(resolvedEmbedUrl);
53903
54132
  setIsLoading(false);
53904
54133
  }).catch((err) => {
53905
54134
  if (err.name === "AbortError") return;
@@ -53907,7 +54136,7 @@ function useAssetEmbed(assetId, options = {
53907
54136
  setIsLoading(false);
53908
54137
  });
53909
54138
  return () => controller.abort();
53910
- }, [assetId, readOnly, expiresInSeconds, backendUrl, apiKey, hasToken]);
54139
+ }, [assetId, readOnly, expiresInSeconds, backendUrl, appUrl, apiKey, hasToken]);
53911
54140
  return { embedUrl, isLoading, error: error2 };
53912
54141
  }
53913
54142
  const ABSOLUTE_URL_PATTERN = /^[a-zA-Z][a-zA-Z\d+\-.]*:/;
@@ -53930,6 +54159,21 @@ function buildAssetIframeSrc({
53930
54159
  return `${embedUrl}${separator}slide=${targetSlide}`;
53931
54160
  }
53932
54161
  }
54162
+ function buildPresentationNavigationMessage({
54163
+ assetId,
54164
+ assetType,
54165
+ slideNumber
54166
+ }) {
54167
+ if (assetType !== "presentation" || typeof slideNumber !== "number" || !Number.isInteger(slideNumber) || slideNumber < 1) {
54168
+ return null;
54169
+ }
54170
+ return {
54171
+ type: "NAVIGATE_TO_SLIDE",
54172
+ assetId,
54173
+ deckId: assetId,
54174
+ slideNumber
54175
+ };
54176
+ }
53933
54177
  const ASSET_TYPE_CONFIG = {
53934
54178
  presentation: { icon: Presentation, label: "Presentation" },
53935
54179
  spreadsheet: { icon: FileSpreadsheet, label: "Spreadsheet" },
@@ -53939,9 +54183,11 @@ const ASSET_TYPE_CONFIG = {
53939
54183
  };
53940
54184
  const AssetIframe = memo(
53941
54185
  ({ tab }) => {
53942
- const { backendUrl, apiKey, token } = useAthenaConfig();
54186
+ const iframeRef = useRef(null);
54187
+ const { backendUrl, appUrl, apiKey, token } = useAthenaConfig();
53943
54188
  const { embedUrl, isLoading, error: error2 } = useAssetEmbed(tab.id, {
53944
54189
  backendUrl,
54190
+ appUrl,
53945
54191
  apiKey,
53946
54192
  token
53947
54193
  });
@@ -53953,6 +54199,22 @@ const AssetIframe = memo(
53953
54199
  }) : null,
53954
54200
  [embedUrl, tab.slideNumber, tab.type]
53955
54201
  );
54202
+ const navigationMessage = useMemo(
54203
+ () => buildPresentationNavigationMessage({
54204
+ assetId: tab.id,
54205
+ assetType: tab.type,
54206
+ slideNumber: tab.slideNumber
54207
+ }),
54208
+ [tab.id, tab.slideNumber, tab.type]
54209
+ );
54210
+ const postNavigationMessage = useCallback(() => {
54211
+ var _a2, _b;
54212
+ if (!navigationMessage) return;
54213
+ (_b = (_a2 = iframeRef.current) == null ? void 0 : _a2.contentWindow) == null ? void 0 : _b.postMessage(navigationMessage, "*");
54214
+ }, [navigationMessage]);
54215
+ useEffect(() => {
54216
+ postNavigationMessage();
54217
+ }, [postNavigationMessage]);
53956
54218
  if (isLoading) {
53957
54219
  return /* @__PURE__ */ jsx("div", { className: "flex h-full items-center justify-center", children: /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
53958
54220
  /* @__PURE__ */ jsx(LoaderCircle, { className: "mx-auto size-6 animate-spin text-muted-foreground" }),
@@ -53970,16 +54232,19 @@ const AssetIframe = memo(
53970
54232
  return /* @__PURE__ */ jsx(
53971
54233
  "iframe",
53972
54234
  {
54235
+ ref: iframeRef,
53973
54236
  src: iframeSrc,
53974
54237
  width: "100%",
53975
54238
  height: "100%",
53976
54239
  frameBorder: "0",
53977
54240
  allow: "fullscreen",
53978
54241
  title: tab.name ?? `Asset ${tab.id}`,
53979
- className: "h-full w-full"
54242
+ className: "h-full w-full",
54243
+ onLoad: postNavigationMessage
53980
54244
  }
53981
54245
  );
53982
- }
54246
+ },
54247
+ (prev, next) => prev.tab.id === next.tab.id && prev.tab.name === next.tab.name && prev.tab.type === next.tab.type && prev.tab.slideNumber === next.tab.slideNumber
53983
54248
  );
53984
54249
  AssetIframe.displayName = "AssetIframe";
53985
54250
  const PanelContent = ({