@invergent/agent-chat-react 1.5.1 → 1.5.3

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
@@ -22,8 +22,10 @@ var Ansi = require('ansi-to-react');
22
22
  var tokenlens = require('tokenlens');
23
23
  var cmdk = require('cmdk');
24
24
  var nanoid = require('nanoid');
25
+ require('pdfjs-dist/web/pdf_viewer.css');
25
26
  var dateFns = require('date-fns');
26
27
 
28
+ var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
27
29
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
28
30
 
29
31
  var Ansi__default = /*#__PURE__*/_interopDefault(Ansi);
@@ -6465,17 +6467,24 @@ function getLanguageHint(path) {
6465
6467
  return map[ext] ?? "plaintext";
6466
6468
  }
6467
6469
  var SKELETON_WIDTHS = [70, 85, 55, 90, 60, 78, 45, 82, 65, 72];
6470
+ var PDF_WORKER_SRC = new URL(
6471
+ "pdfjs-dist/legacy/build/pdf.worker.mjs",
6472
+ (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href))
6473
+ ).toString();
6468
6474
  function FileViewer({
6469
6475
  file,
6470
6476
  loading,
6471
6477
  error,
6478
+ downloadUrl,
6479
+ onDelete,
6472
6480
  onClose
6473
6481
  }) {
6474
6482
  const visible = loading || file !== null || error !== null;
6475
6483
  if (!visible) return null;
6476
6484
  const fileName2 = file?.path.split("/").pop() ?? "File";
6477
6485
  const lang = file ? getLanguageHint(file.path) : "";
6478
- const isImage = file?.encoding === "base64";
6486
+ const isPdf = file?.mime_type === "application/pdf" || file?.path.toLowerCase().endsWith(".pdf") || false;
6487
+ const isImage = file?.encoding === "base64" && !isPdf;
6479
6488
  const HeaderIcon = isImage ? lucideReact.ImageIcon : lucideReact.FileTextIcon;
6480
6489
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-h-0 flex-1 flex-col border-t border-line", children: [
6481
6490
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex shrink-0 items-center gap-2 border-b border-line px-3 py-2", children: [
@@ -6490,6 +6499,28 @@ function FileViewer({
6490
6499
  ] })
6491
6500
  ] })
6492
6501
  ] }),
6502
+ downloadUrl && /* @__PURE__ */ jsxRuntime.jsx(
6503
+ "a",
6504
+ {
6505
+ href: downloadUrl,
6506
+ download: fileName2,
6507
+ className: "shrink-0 rounded p-0.5 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground",
6508
+ "aria-label": `Download ${fileName2}`,
6509
+ title: "Download",
6510
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.DownloadIcon, { className: "size-3.5" })
6511
+ }
6512
+ ),
6513
+ onDelete && /* @__PURE__ */ jsxRuntime.jsx(
6514
+ "button",
6515
+ {
6516
+ type: "button",
6517
+ onClick: onDelete,
6518
+ className: "shrink-0 rounded p-0.5 text-muted-foreground transition-colors hover:bg-destructive/10 hover:text-destructive",
6519
+ "aria-label": `Delete ${fileName2}`,
6520
+ title: "Delete",
6521
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.TrashIcon, { className: "size-3.5" })
6522
+ }
6523
+ ),
6493
6524
  /* @__PURE__ */ jsxRuntime.jsx(
6494
6525
  "button",
6495
6526
  {
@@ -6516,6 +6547,8 @@ function FileViewer({
6516
6547
  /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertCircleIcon, { className: "mt-0.5 size-3.5 shrink-0" }),
6517
6548
  /* @__PURE__ */ jsxRuntime.jsx("span", { children: error })
6518
6549
  ] }),
6550
+ file && isPdf && file.encoding !== "base64" && /* @__PURE__ */ jsxRuntime.jsx(FileViewerError, { message: "PDF preview requires base64 file content." }),
6551
+ file && isPdf && file.encoding === "base64" && /* @__PURE__ */ jsxRuntime.jsx(PdfPreview, { file, fileName: fileName2 }),
6519
6552
  file && isImage && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center p-4", children: /* @__PURE__ */ jsxRuntime.jsx(
6520
6553
  "img",
6521
6554
  {
@@ -6524,66 +6557,290 @@ function FileViewer({
6524
6557
  className: "max-h-[60vh] max-w-full rounded object-contain"
6525
6558
  }
6526
6559
  ) }),
6527
- file && !isImage && /* @__PURE__ */ jsxRuntime.jsx("pre", { className: "wrap-break-word whitespace-pre-wrap p-3 text-[11px] leading-relaxed text-foreground", children: /* @__PURE__ */ jsxRuntime.jsx("code", { "data-language": lang, children: file.content }) })
6560
+ file && !isImage && !isPdf && /* @__PURE__ */ jsxRuntime.jsx("pre", { className: "wrap-break-word whitespace-pre-wrap p-3 text-[11px] leading-relaxed text-foreground", children: /* @__PURE__ */ jsxRuntime.jsx("code", { "data-language": lang, children: file.content }) })
6528
6561
  ] })
6529
6562
  ] });
6530
6563
  }
6531
- var TEXT_EXTENSIONS = /* @__PURE__ */ new Set([
6532
- ".py",
6533
- ".js",
6534
- ".ts",
6535
- ".tsx",
6536
- ".jsx",
6537
- ".json",
6538
- ".md",
6539
- ".yaml",
6540
- ".yml",
6541
- ".toml",
6542
- ".sql",
6543
- ".sh",
6544
- ".css",
6545
- ".html",
6546
- ".txt",
6547
- ".csv",
6548
- ".rst",
6549
- ".cfg",
6550
- ".ini",
6551
- ".env",
6552
- ".rs",
6553
- ".go",
6554
- ".java",
6555
- ".rb",
6556
- ".php",
6557
- ".c",
6558
- ".cpp",
6559
- ".h",
6560
- ".lock",
6561
- ".gitignore",
6562
- ".dockerignore",
6563
- ".editorconfig"
6564
- ]);
6565
- var IMAGE_EXTENSIONS = /* @__PURE__ */ new Set([
6566
- ".png",
6567
- ".jpg",
6568
- ".jpeg",
6569
- ".gif",
6570
- ".webp",
6571
- ".svg",
6572
- ".bmp",
6573
- ".ico",
6574
- ".avif",
6575
- ".tiff",
6576
- ".tif"
6577
- ]);
6564
+ function FileViewerError({ message }) {
6565
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-2 p-3 text-xs text-destructive", children: [
6566
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertCircleIcon, { className: "mt-0.5 size-3.5 shrink-0" }),
6567
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: message })
6568
+ ] });
6569
+ }
6570
+ function PdfPreview({
6571
+ file,
6572
+ fileName: fileName2
6573
+ }) {
6574
+ const containerRef = react.useRef(null);
6575
+ const viewerRef = react.useRef(null);
6576
+ const pdfViewerRef = react.useRef(null);
6577
+ const eventBusRef = react.useRef(null);
6578
+ const findControllerRef = react.useRef(null);
6579
+ const [error, setError] = react.useState(null);
6580
+ const [pageNumber, setPageNumber] = react.useState(1);
6581
+ const [pagesCount, setPagesCount] = react.useState(0);
6582
+ const [scale, setScale] = react.useState(1);
6583
+ const [query, setQuery] = react.useState("");
6584
+ react.useEffect(() => {
6585
+ let cancelled = false;
6586
+ let loadingTask = null;
6587
+ let pdfDocument = null;
6588
+ const renderPdf = async () => {
6589
+ setError(null);
6590
+ const container = containerRef.current;
6591
+ const viewerElement = viewerRef.current;
6592
+ if (!container || !viewerElement) return;
6593
+ const pdfBytes = decodeBase64(file.content);
6594
+ const pdfjs = await import('pdfjs-dist/legacy/build/pdf.mjs');
6595
+ pdfjs.GlobalWorkerOptions.workerSrc = PDF_WORKER_SRC;
6596
+ globalThis.pdfjsLib = pdfjs;
6597
+ const pdfViewerModule = await import('pdfjs-dist/web/pdf_viewer.mjs');
6598
+ loadingTask = pdfjs.getDocument({ data: pdfBytes });
6599
+ const pdf = await loadingTask.promise;
6600
+ pdfDocument = pdf;
6601
+ if (cancelled) return;
6602
+ const eventBus = new pdfViewerModule.EventBus();
6603
+ const linkService = new pdfViewerModule.PDFLinkService({ eventBus });
6604
+ const findController = new pdfViewerModule.PDFFindController({
6605
+ eventBus,
6606
+ linkService
6607
+ });
6608
+ const pdfViewer = new pdfViewerModule.PDFViewer({
6609
+ container,
6610
+ viewer: viewerElement,
6611
+ eventBus,
6612
+ linkService,
6613
+ findController,
6614
+ removePageBorders: true
6615
+ });
6616
+ linkService.setViewer(pdfViewer);
6617
+ linkService.setDocument(pdf);
6618
+ findController.setDocument(pdf);
6619
+ const onPagesInit = () => {
6620
+ pdfViewer.currentScaleValue = "page-width";
6621
+ setScale(pdfViewer.currentScale || 1);
6622
+ setPagesCount(pdfViewer.pagesCount);
6623
+ setPageNumber(pdfViewer.currentPageNumber);
6624
+ };
6625
+ const onPageChanging = (event) => {
6626
+ if (typeof event.pageNumber === "number") {
6627
+ setPageNumber(event.pageNumber);
6628
+ }
6629
+ };
6630
+ const onScaleChanging = (event) => {
6631
+ if (typeof event.scale === "number") {
6632
+ setScale(event.scale);
6633
+ }
6634
+ };
6635
+ eventBus.on("pagesinit", onPagesInit);
6636
+ eventBus.on("pagechanging", onPageChanging);
6637
+ eventBus.on("scalechanging", onScaleChanging);
6638
+ pdfViewerRef.current = pdfViewer;
6639
+ eventBusRef.current = eventBus;
6640
+ findControllerRef.current = findController;
6641
+ setPagesCount(pdf.numPages);
6642
+ pdfViewer.setDocument(pdf);
6643
+ };
6644
+ void renderPdf().catch((nextError) => {
6645
+ if (cancelled) return;
6646
+ if (nextError instanceof Error && nextError.name === "RenderingCancelledException") {
6647
+ return;
6648
+ }
6649
+ setError(formatPdfPreviewError(nextError));
6650
+ });
6651
+ return () => {
6652
+ cancelled = true;
6653
+ loadingTask?.destroy();
6654
+ pdfDocument?.destroy();
6655
+ pdfViewerRef.current?.cleanup();
6656
+ pdfViewerRef.current = null;
6657
+ eventBusRef.current = null;
6658
+ findControllerRef.current = null;
6659
+ };
6660
+ }, [file.content]);
6661
+ const setViewerPage = (nextPage) => {
6662
+ const viewer = pdfViewerRef.current;
6663
+ if (!viewer) return;
6664
+ const clampedPage = Math.min(
6665
+ Math.max(1, nextPage),
6666
+ Math.max(1, viewer.pagesCount)
6667
+ );
6668
+ viewer.currentPageNumber = clampedPage;
6669
+ setPageNumber(clampedPage);
6670
+ };
6671
+ const setViewerScale = (nextScale) => {
6672
+ const viewer = pdfViewerRef.current;
6673
+ if (!viewer) return;
6674
+ const clampedScale = Math.min(3, Math.max(0.5, nextScale));
6675
+ viewer.currentScale = clampedScale;
6676
+ setScale(clampedScale);
6677
+ };
6678
+ const runFind = (findPrevious = false) => {
6679
+ const eventBus = eventBusRef.current;
6680
+ if (!eventBus || !query.trim()) return;
6681
+ eventBus.dispatch("find", {
6682
+ source: eventBus,
6683
+ type: "again",
6684
+ query,
6685
+ phraseSearch: true,
6686
+ caseSensitive: false,
6687
+ entireWord: false,
6688
+ highlightAll: true,
6689
+ findPrevious,
6690
+ matchDiacritics: true
6691
+ });
6692
+ };
6693
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-h-full flex-col", children: [
6694
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex shrink-0 flex-wrap items-center gap-1.5 border-b border-line px-2 py-1.5", children: [
6695
+ /* @__PURE__ */ jsxRuntime.jsx(
6696
+ Button,
6697
+ {
6698
+ type: "button",
6699
+ variant: "ghost",
6700
+ size: "icon-xs",
6701
+ onClick: () => setViewerPage(pageNumber - 1),
6702
+ disabled: pageNumber <= 1,
6703
+ "aria-label": "Previous PDF page",
6704
+ title: "Previous page",
6705
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronLeftIcon, { className: "size-3.5" })
6706
+ }
6707
+ ),
6708
+ /* @__PURE__ */ jsxRuntime.jsx(
6709
+ Input,
6710
+ {
6711
+ type: "number",
6712
+ min: 1,
6713
+ max: pagesCount || 1,
6714
+ value: pageNumber,
6715
+ onChange: (event) => setViewerPage(Number(event.target.value)),
6716
+ "aria-label": "PDF page number",
6717
+ className: "h-7 w-12 border-input px-1 text-center text-xs"
6718
+ }
6719
+ ),
6720
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs text-muted-foreground", children: [
6721
+ "/ ",
6722
+ pagesCount || "-"
6723
+ ] }),
6724
+ /* @__PURE__ */ jsxRuntime.jsx(
6725
+ Button,
6726
+ {
6727
+ type: "button",
6728
+ variant: "ghost",
6729
+ size: "icon-xs",
6730
+ onClick: () => setViewerPage(pageNumber + 1),
6731
+ disabled: pagesCount > 0 && pageNumber >= pagesCount,
6732
+ "aria-label": "Next PDF page",
6733
+ title: "Next page",
6734
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRightIcon, { className: "size-3.5" })
6735
+ }
6736
+ ),
6737
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mx-1 h-5 w-px bg-line" }),
6738
+ /* @__PURE__ */ jsxRuntime.jsx(
6739
+ Button,
6740
+ {
6741
+ type: "button",
6742
+ variant: "ghost",
6743
+ size: "icon-xs",
6744
+ onClick: () => setViewerScale(scale - 0.1),
6745
+ disabled: scale <= 0.5,
6746
+ "aria-label": "Zoom out PDF",
6747
+ title: "Zoom out",
6748
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.MinusIcon, { className: "size-3.5" })
6749
+ }
6750
+ ),
6751
+ /* @__PURE__ */ jsxRuntime.jsxs(
6752
+ "button",
6753
+ {
6754
+ type: "button",
6755
+ className: "h-7 min-w-12 px-1 text-xs text-muted-foreground hover:text-foreground",
6756
+ onClick: () => {
6757
+ const viewer = pdfViewerRef.current;
6758
+ if (!viewer) return;
6759
+ viewer.currentScaleValue = "page-width";
6760
+ setScale(viewer.currentScale || 1);
6761
+ },
6762
+ "aria-label": "Fit PDF to width",
6763
+ title: "Fit width",
6764
+ children: [
6765
+ Math.round(scale * 100),
6766
+ "%"
6767
+ ]
6768
+ }
6769
+ ),
6770
+ /* @__PURE__ */ jsxRuntime.jsx(
6771
+ Button,
6772
+ {
6773
+ type: "button",
6774
+ variant: "ghost",
6775
+ size: "icon-xs",
6776
+ onClick: () => setViewerScale(scale + 0.1),
6777
+ disabled: scale >= 3,
6778
+ "aria-label": "Zoom in PDF",
6779
+ title: "Zoom in",
6780
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.PlusIcon, { className: "size-3.5" })
6781
+ }
6782
+ ),
6783
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mx-1 h-5 w-px bg-line" }),
6784
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.SearchIcon, { className: "size-3.5 text-muted-foreground" }),
6785
+ /* @__PURE__ */ jsxRuntime.jsx(
6786
+ Input,
6787
+ {
6788
+ type: "search",
6789
+ value: query,
6790
+ onChange: (event) => setQuery(event.target.value),
6791
+ onKeyDown: (event) => {
6792
+ if (event.key === "Enter") runFind(event.shiftKey);
6793
+ },
6794
+ placeholder: "Find",
6795
+ "aria-label": "Find in PDF",
6796
+ className: "h-7 w-28 border-input px-1 text-xs"
6797
+ }
6798
+ ),
6799
+ /* @__PURE__ */ jsxRuntime.jsx(
6800
+ Button,
6801
+ {
6802
+ type: "button",
6803
+ variant: "ghost",
6804
+ size: "xs",
6805
+ onClick: () => runFind(false),
6806
+ disabled: !query.trim(),
6807
+ children: "Find"
6808
+ }
6809
+ )
6810
+ ] }),
6811
+ error && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex w-full items-start gap-2 p-3 text-xs text-destructive", children: [
6812
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertCircleIcon, { className: "mt-0.5 size-3.5 shrink-0" }),
6813
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: error })
6814
+ ] }),
6815
+ !error && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative h-[70vh] min-h-[420px] flex-1 bg-muted/20", children: /* @__PURE__ */ jsxRuntime.jsx(
6816
+ "div",
6817
+ {
6818
+ ref: containerRef,
6819
+ "aria-label": `PDF viewer for ${fileName2}`,
6820
+ className: "absolute inset-0 overflow-auto",
6821
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", { ref: viewerRef, className: "pdfViewer" })
6822
+ }
6823
+ ) })
6824
+ ] });
6825
+ }
6826
+ function decodeBase64(content) {
6827
+ const binary = globalThis.atob(content);
6828
+ const bytes = new Uint8Array(binary.length);
6829
+ for (let index = 0; index < binary.length; index += 1) {
6830
+ bytes[index] = binary.charCodeAt(index);
6831
+ }
6832
+ return bytes;
6833
+ }
6834
+ function formatPdfPreviewError(error) {
6835
+ if (error instanceof Error && (error.name === "InvalidCharacterError" || error.message === "Invalid character")) {
6836
+ return "PDF preview data is not valid base64.";
6837
+ }
6838
+ return error instanceof Error ? error.message : "Failed to render PDF preview.";
6839
+ }
6578
6840
  var SKELETON_WIDTHS2 = [75, 60, 90, 65, 80, 70, 85, 55];
6579
6841
  var DEFAULT_WIDTH = 500;
6580
6842
  var MIN_WIDTH = 300;
6581
6843
  var MAX_WIDTH = 900;
6582
- function isViewable(name) {
6583
- const dot = name.lastIndexOf(".");
6584
- const ext = dot >= 0 ? name.slice(dot).toLowerCase() : "";
6585
- return TEXT_EXTENSIONS.has(ext) || IMAGE_EXTENSIONS.has(ext);
6586
- }
6587
6844
  function collectExpandedPaths(entries, depth = 0) {
6588
6845
  const paths = [];
6589
6846
  for (const entry of entries) {
@@ -6608,8 +6865,8 @@ function findEntry(entries, path) {
6608
6865
  }
6609
6866
  function RenderEntries({
6610
6867
  entries,
6611
- onFileSelect,
6612
- onDelete
6868
+ onDelete,
6869
+ downloadUrlFor
6613
6870
  }) {
6614
6871
  return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: entries.map((entry) => {
6615
6872
  if (entry.kind === "dir") {
@@ -6617,27 +6874,26 @@ function RenderEntries({
6617
6874
  RenderEntries,
6618
6875
  {
6619
6876
  entries: entry.children,
6620
- onFileSelect,
6621
- onDelete
6877
+ onDelete,
6878
+ downloadUrlFor
6622
6879
  }
6623
6880
  ) }, entry.path);
6624
6881
  }
6625
- const viewable = isViewable(entry.name);
6882
+ const fileName2 = entry.name;
6626
6883
  return /* @__PURE__ */ jsxRuntime.jsxs(FileTreeFile, { name: entry.name, path: entry.path, children: [
6627
6884
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "size-4 shrink-0" }),
6628
6885
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 flex-1 truncate", children: entry.name }),
6629
6886
  entry.size != null && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-1 shrink-0 text-xs text-muted-foreground/60", children: formatFileSize(entry.size) }),
6630
6887
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ml-1 flex shrink-0 items-center gap-0 opacity-0 transition-opacity group-hover:opacity-100", children: [
6631
- viewable && /* @__PURE__ */ jsxRuntime.jsx(
6632
- "button",
6888
+ /* @__PURE__ */ jsxRuntime.jsx(
6889
+ "a",
6633
6890
  {
6634
- type: "button",
6891
+ href: downloadUrlFor(entry.path),
6892
+ download: fileName2,
6635
6893
  className: "rounded p-0.5 text-muted-foreground hover:bg-muted hover:text-foreground",
6636
- onClick: (event) => {
6637
- event.stopPropagation();
6638
- onFileSelect(entry.path);
6639
- },
6640
- title: "View",
6894
+ onClick: (event) => event.stopPropagation(),
6895
+ title: "Download",
6896
+ "aria-label": `Download ${fileName2}`,
6641
6897
  children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.DownloadIcon, { className: "size-3" })
6642
6898
  }
6643
6899
  ),
@@ -6651,6 +6907,7 @@ function RenderEntries({
6651
6907
  onDelete(entry.path);
6652
6908
  },
6653
6909
  title: "Delete",
6910
+ "aria-label": `Delete ${fileName2}`,
6654
6911
  children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.TrashIcon, { className: "size-3" })
6655
6912
  }
6656
6913
  )
@@ -6968,8 +7225,8 @@ function WorkspacePanel({
6968
7225
  RenderEntries,
6969
7226
  {
6970
7227
  entries,
6971
- onFileSelect: handleSelect,
6972
- onDelete: setDeleteTarget
7228
+ onDelete: setDeleteTarget,
7229
+ downloadUrlFor: (path) => sessionId ? adapter.getWorkspaceDownloadUrl({ sessionId, path }) : "#"
6973
7230
  }
6974
7231
  )
6975
7232
  }
@@ -6981,7 +7238,13 @@ function WorkspacePanel({
6981
7238
  file,
6982
7239
  loading: fileLoading,
6983
7240
  error: fileError,
7241
+ downloadUrl: file && sessionId ? adapter.getWorkspaceDownloadUrl({
7242
+ sessionId,
7243
+ path: file.path
7244
+ }) : null,
7245
+ onDelete: file ? () => setDeleteTarget(file.path) : null,
6984
7246
  onClose: () => {
7247
+ onSelectedPathChange(null);
6985
7248
  setFile(null);
6986
7249
  setFileError(null);
6987
7250
  }