@openviking/react 0.1.4 → 0.1.6

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.
Files changed (139) hide show
  1. package/README.md +15 -11
  2. package/dist/28~0.js +15 -0
  3. package/dist/2~0.js +6 -3
  4. package/dist/37~0.js +27 -0
  5. package/dist/3c~0.js +17 -9
  6. package/dist/3~0.js +4 -2
  7. package/dist/ae~0.js +6 -2
  8. package/dist/a~0.js +79 -72
  9. package/dist/ck~0.js +4 -0
  10. package/dist/client/paths.d.ts +4 -0
  11. package/dist/client/provider.d.ts +10 -6
  12. package/dist/components/agent-connect/agent-connect-code-block.d.ts +14 -0
  13. package/dist/components/agent-connect/agent-connect-copy.d.ts +3 -0
  14. package/dist/components/agent-connect/agent-connect-design.d.ts +1 -1
  15. package/dist/components/agent-connect/agent-connect-installer.d.ts +1 -0
  16. package/dist/components/agent-connect/agent-connect-instructions-view.d.ts +4 -6
  17. package/dist/components/agent-connect/agent-connect-instructions.d.ts +13 -0
  18. package/dist/components/agent-connect/agent-connect-markdown.d.ts +8 -2
  19. package/dist/components/agent-connect/agent-connect-mask.d.ts +10 -0
  20. package/dist/components/agent-connect/agent-connect.d.ts +1 -1
  21. package/dist/components/agent-connect/locales/en-US.d.ts +3 -0
  22. package/dist/components/agent-connect/style.css +163 -5
  23. package/dist/components/agent-connect/types.d.ts +5 -3
  24. package/dist/components/agent-connect/use-agent-connect-copy.d.ts +6 -0
  25. package/dist/components/directory-tour/style.css +46 -2
  26. package/dist/components/directory-tour/types.d.ts +2 -1
  27. package/dist/components/experience-dashboard/dashboard-tabs.d.ts +11 -0
  28. package/dist/components/experience-dashboard/experience-dashboard.d.ts +2 -0
  29. package/dist/components/experience-dashboard/experience-impact.d.ts +11 -0
  30. package/dist/components/experience-dashboard/experience-list.d.ts +9 -0
  31. package/dist/components/experience-dashboard/experience-pagination.d.ts +8 -0
  32. package/dist/components/experience-dashboard/experience-tests.d.ts +6 -0
  33. package/dist/components/experience-dashboard/experience-trajectories.d.ts +6 -0
  34. package/dist/components/experience-dashboard/index.d.ts +2 -0
  35. package/dist/components/experience-dashboard/labels.d.ts +2 -0
  36. package/dist/components/experience-dashboard/style.css +699 -0
  37. package/dist/components/experience-dashboard/style.js +0 -0
  38. package/dist/components/experience-dashboard/types.d.ts +106 -0
  39. package/dist/components/experience-dashboard.js +1 -0
  40. package/dist/components/file-browser-entries/file-browser-entries.d.ts +1 -1
  41. package/dist/components/file-browser-entries/style.css +259 -13
  42. package/dist/components/file-browser-entries/types.d.ts +2 -2
  43. package/dist/components/file-preview/style.css +48 -4
  44. package/dist/components/file-preview/types.d.ts +2 -2
  45. package/dist/components/file-tree/style.css +63 -4
  46. package/dist/components/file-tree/types.d.ts +2 -2
  47. package/dist/components/scope-switcher/scope-switcher.d.ts +2 -2
  48. package/dist/components/scope-switcher/style.css +48 -4
  49. package/dist/components/scope-switcher/types.d.ts +5 -5
  50. package/dist/components/scope-switcher.js +1 -1
  51. package/dist/components/style.css +2451 -139
  52. package/dist/components/tui/style.css +122 -36
  53. package/dist/components/tui/tui.d.ts +1 -1
  54. package/dist/components/tui/types.d.ts +2 -2
  55. package/dist/components/viking-bot/ark-message-list-view.d.ts +4 -1
  56. package/dist/components/viking-bot/interaction/types.d.ts +2 -2
  57. package/dist/components/viking-bot/interaction/viking-bot-interaction.d.ts +1 -1
  58. package/dist/components/viking-bot/session-actions.d.ts +2 -2
  59. package/dist/components/viking-bot/style.css +159 -12
  60. package/dist/components/viking-bot/types.d.ts +7 -7
  61. package/dist/components/viking-bot/viking-bot.d.ts +1 -1
  62. package/dist/components/wiki-dashboard/index.d.ts +2 -0
  63. package/dist/components/wiki-dashboard/labels.d.ts +2 -0
  64. package/dist/components/wiki-dashboard/style.css +741 -0
  65. package/dist/components/wiki-dashboard/style.js +0 -0
  66. package/dist/components/wiki-dashboard/types.d.ts +92 -0
  67. package/dist/components/wiki-dashboard/wiki-action-button.d.ts +9 -0
  68. package/dist/components/wiki-dashboard/wiki-conflict-card.d.ts +15 -0
  69. package/dist/components/wiki-dashboard/wiki-dashboard.d.ts +2 -0
  70. package/dist/components/wiki-dashboard/wiki-file-icon.d.ts +3 -0
  71. package/dist/components/wiki-dashboard/wiki-severity-filter.d.ts +8 -0
  72. package/dist/components/wiki-dashboard.js +1 -0
  73. package/dist/c~0.js +169 -155
  74. package/dist/e~0.js +3 -1
  75. package/dist/fi~0.js +354 -0
  76. package/dist/fj~0.js +503 -0
  77. package/dist/f~0.js +661 -309
  78. package/dist/icons/index.d.ts +28 -0
  79. package/dist/icons.js +1 -1
  80. package/dist/index.d.ts +4 -0
  81. package/dist/index.js +3 -1
  82. package/dist/k~0.js +277 -1
  83. package/dist/lk~0.js +55 -13
  84. package/dist/l~0.js +1096 -187
  85. package/dist/modules/console/console.d.ts +1 -1
  86. package/dist/modules/console/index.d.ts +1 -2
  87. package/dist/modules/console/style.css +377 -56
  88. package/dist/modules/console/types.d.ts +2 -2
  89. package/dist/modules/console/use-console.d.ts +1 -1
  90. package/dist/modules/console.js +1 -1
  91. package/dist/modules/file-browser/dashboard-data.d.ts +9 -0
  92. package/dist/modules/file-browser/dashboard-indicator.d.ts +8 -0
  93. package/dist/modules/file-browser/dashboard-labels.d.ts +9 -0
  94. package/dist/modules/file-browser/dashboard-model.d.ts +14 -0
  95. package/dist/modules/file-browser/dashboard-resource.d.ts +12 -0
  96. package/dist/modules/file-browser/experience-dashboard-pane.d.ts +8 -0
  97. package/dist/modules/file-browser/experience-data.d.ts +31 -0
  98. package/dist/modules/file-browser/file-browser-labels.d.ts +1 -1
  99. package/dist/modules/file-browser/file-browser-tree-pane.d.ts +3 -2
  100. package/dist/modules/file-browser/file-browser.d.ts +1 -1
  101. package/dist/modules/file-browser/fs-directories.d.ts +8 -0
  102. package/dist/modules/file-browser/fs-lines.d.ts +36 -0
  103. package/dist/modules/file-browser/fs-memory-fields.d.ts +65 -0
  104. package/dist/modules/file-browser/fs-model.d.ts +12 -2
  105. package/dist/modules/file-browser/fs-read-file.d.ts +14 -0
  106. package/dist/modules/file-browser/fs-selection.d.ts +4 -0
  107. package/dist/modules/file-browser/index.d.ts +2 -2
  108. package/dist/modules/file-browser/style.css +1883 -25
  109. package/dist/modules/file-browser/types.d.ts +64 -2
  110. package/dist/modules/file-browser/use-browser-dashboards.d.ts +31 -0
  111. package/dist/modules/file-browser/use-dashboard-query.d.ts +9 -0
  112. package/dist/modules/file-browser/use-experience-dashboard.d.ts +27 -0
  113. package/dist/modules/file-browser/use-file-browser.d.ts +2 -45
  114. package/dist/modules/file-browser/use-fs-tree.d.ts +2 -0
  115. package/dist/modules/file-browser/use-wiki-dashboard.d.ts +17 -0
  116. package/dist/modules/file-browser/wiki-conflicts.d.ts +12 -0
  117. package/dist/modules/file-browser/wiki-dashboard-pane.d.ts +14 -0
  118. package/dist/modules/file-browser.js +1 -1
  119. package/dist/modules/scope-cascade/controller.d.ts +2 -2
  120. package/dist/modules/scope-cascade/index.d.ts +1 -2
  121. package/dist/modules/scope-cascade/scope-cascade.d.ts +2 -2
  122. package/dist/modules/scope-cascade/style.css +48 -4
  123. package/dist/modules/scope-cascade/types.d.ts +9 -4
  124. package/dist/modules/scope-cascade/use-scope-cascade.d.ts +2 -2
  125. package/dist/modules/scope-cascade.js +1 -1
  126. package/dist/modules/style.css +2459 -192
  127. package/dist/n~0.js +16 -130
  128. package/dist/rt~0.js +152 -0
  129. package/dist/r~0.js +17 -38
  130. package/dist/shared/components/popover/popover.d.ts +1 -1
  131. package/dist/shared/components/popover/types.d.ts +7 -1
  132. package/dist/shared/dashboard/dashboard-state.d.ts +12 -0
  133. package/dist/shared/locale-context.d.ts +8 -0
  134. package/dist/static/image/dashboard-background.png +0 -0
  135. package/dist/style.css +9445 -4822
  136. package/dist/u~0.js +324 -96
  137. package/dist/viking-bot-composer~0.js +4 -2
  138. package/dist/viking-bot-interaction~0.js +3 -1
  139. package/package.json +14 -2
package/dist/l~0.js CHANGED
@@ -1,13 +1,16 @@
1
1
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
- import { useCallback, useEffect, useId, useMemo, useRef, useState } from "react";
2
+ import { createElement, useCallback, useEffect, useId, useMemo, useRef, useState } from "react";
3
3
  import { FilePreview as file_preview_FilePreview } from "./3~0.js";
4
- import { Tooltip } from "./r~0.js";
5
- import { getFileTypeColor, resolveFileTypeIconKey, FolderIcon, getFileTypeIcon } from "./k~0.js";
4
+ import { Tooltip } from "./rt~0.js";
5
+ import { getFileTypeColor, getFileTypeIcon, WikiBookIcon, ExperienceBoardIcon, WikiConflictBoardIcon, FolderIcon, WikiBoardIcon, resolveFileTypeIconKey } from "./k~0.js";
6
6
  import { FileBrowserEntries } from "./2~0.js";
7
7
  import { FileTree as file_tree_FileTree } from "./n~0.js";
8
8
  import { resolveLocale } from "./nx~0.js";
9
9
  import { OV_PATHS } from "./ck~0.js";
10
- import { useOvClient } from "./ae~0.js";
10
+ import { isOvClientError, useOvSignal, useOvClient } from "./ae~0.js";
11
+ import { ExperienceDashboard } from "./f~0.js";
12
+ import { WikiDashboard } from "./fj~0.js";
13
+ import { useLocale, LocaleProvider } from "./28~0.js";
11
14
  function clampResizableWidth(width, min, max) {
12
15
  const rounded = Math.round(width);
13
16
  const lower = Math.max(min, rounded);
@@ -237,6 +240,26 @@ function resolveTreeMaxWidth(containerWidth) {
237
240
  if (!containerWidth) return TREE_MAX_WIDTH;
238
241
  return Math.max(TREE_MIN_WIDTH, Math.min(TREE_MAX_WIDTH, containerWidth - DETAIL_MIN_WIDTH - RESIZE_FOOTPRINT));
239
242
  }
243
+ const en = {
244
+ experienceTitle: 'Experience dashboard',
245
+ wikiTitle: 'Dashboard',
246
+ openExperience: 'Open experience dashboard',
247
+ openWiki: 'Open Wiki dashboard',
248
+ wikiConflicts: 'View pending Wiki conflicts',
249
+ failed: 'Could not load dashboard information'
250
+ };
251
+ const zh = {
252
+ experienceTitle: '经验看板',
253
+ wikiTitle: '看板',
254
+ openExperience: '打开经验看板',
255
+ openWiki: '打开 Wiki 看板',
256
+ wikiConflicts: '查看 Wiki 待确认冲突',
257
+ failed: '看板信息加载失败'
258
+ };
259
+ const dashboard_labels_dashboardLabels = (locale, labels)=>({
260
+ ...'zh-CN' === locale ? zh : en,
261
+ ...labels
262
+ });
240
263
  const file_browser_icons_SIZE = 16;
241
264
  const strokeProps = {
242
265
  width: file_browser_icons_SIZE,
@@ -303,6 +326,25 @@ function FileBrowserToolbar({ searchId, query, refreshing, canRefresh, placehold
303
326
  ]
304
327
  });
305
328
  }
329
+ function DashboardIndicator({ dashboard, locale, labels, onOpen }) {
330
+ const text = dashboard_labels_dashboardLabels(locale, labels);
331
+ const label = 'experience' === dashboard.kind ? text.openExperience : dashboard.pendingConflicts ? text.wikiConflicts : text.openWiki;
332
+ const Icon = 'experience' === dashboard.kind ? ExperienceBoardIcon : dashboard.pendingConflicts ? WikiConflictBoardIcon : WikiBoardIcon;
333
+ return /*#__PURE__*/ jsx("button", {
334
+ type: "button",
335
+ className: `ov-file-browser__dashboard${dashboard.pendingConflicts ? ' ov-file-browser__dashboard--pending' : ''}`,
336
+ "aria-label": label,
337
+ title: label,
338
+ onClick: (event)=>{
339
+ event.stopPropagation();
340
+ onOpen(dashboard.uri);
341
+ },
342
+ children: /*#__PURE__*/ jsx(Icon, {
343
+ width: 12,
344
+ height: 12
345
+ })
346
+ });
347
+ }
306
348
  function fileTypeIcon(name) {
307
349
  const Icon = getFileTypeIcon(name);
308
350
  const key = resolveFileTypeIconKey(name);
@@ -319,7 +361,7 @@ function directoryIcon() {
319
361
  className: "ov-file-tree__file-type-icon"
320
362
  });
321
363
  }
322
- function FileBrowserTreePane({ entries, locale, searchId, browser, treeLabels, searchPlaceholder, refreshLabel, searchLoading, searchEmpty, searchErrorLabel, retryLabel }) {
364
+ function FileBrowserTreePane({ entries, locale, dashboardLabels, searchId, browser, treeLabels, searchPlaceholder, refreshLabel, searchLoading, searchEmpty, searchErrorLabel, retryLabel }) {
323
365
  return /*#__PURE__*/ jsxs(Fragment, {
324
366
  children: [
325
367
  /*#__PURE__*/ jsx(FileBrowserEntries, {
@@ -337,44 +379,77 @@ function FileBrowserTreePane({ entries, locale, searchId, browser, treeLabels, s
337
379
  onQueryChange: browser.actions.setQuery,
338
380
  onRefresh: ()=>void browser.actions.refresh()
339
381
  }),
340
- /*#__PURE__*/ jsx("div", {
382
+ /*#__PURE__*/ jsxs("div", {
341
383
  className: "ov-file-browser__tree-scroll",
342
- children: /*#__PURE__*/ jsx(file_tree_FileTree, {
343
- locale: locale,
344
- rows: browser.rows,
345
- selectedId: browser.selectedId,
346
- isReady: browser.isReady,
347
- labels: treeLabels,
348
- emptyFallback: browser.searching ? browser.searchError ? /*#__PURE__*/ jsxs("div", {
384
+ children: [
385
+ browser.dashboardError ? /*#__PURE__*/ jsxs("div", {
349
386
  className: "ov-file-browser__hint ov-file-browser__hint--error",
387
+ "aria-live": "polite",
350
388
  children: [
351
- /*#__PURE__*/ jsx("p", {
352
- className: "ov-file-browser__failure-title",
353
- children: searchErrorLabel
354
- }),
355
- /*#__PURE__*/ jsx("p", {
356
- className: "ov-file-browser__failure-detail",
357
- children: browser.searchError.message
389
+ /*#__PURE__*/ jsxs("p", {
390
+ children: [
391
+ dashboard_labels_dashboardLabels(locale, dashboardLabels).failed,
392
+ ":",
393
+ ' ',
394
+ browser.dashboardError.message
395
+ ]
358
396
  }),
359
397
  /*#__PURE__*/ jsx("button", {
360
398
  type: "button",
361
- className: "ov-file-browser__retry",
362
399
  onClick: ()=>void browser.actions.refresh(),
363
400
  children: retryLabel
364
401
  })
365
402
  ]
366
- }) : /*#__PURE__*/ jsx("p", {
367
- className: "ov-file-browser__hint",
368
- children: browser.searchLoading ? searchLoading : searchEmpty
369
- }) : void 0,
370
- renderRowIcon: (row)=>fileTypeIcon(row.name),
371
- operations: {
372
- select: browser.actions.select,
373
- toggleExpand: browser.actions.toggleExpand,
374
- loadMore: browser.actions.loadMore,
375
- retry: browser.actions.retry
376
- }
377
- })
403
+ }) : null,
404
+ /*#__PURE__*/ jsx(file_tree_FileTree, {
405
+ locale: locale,
406
+ rows: browser.rows,
407
+ selectedId: browser.selectedId,
408
+ isReady: browser.isReady,
409
+ labels: treeLabels,
410
+ emptyFallback: browser.searching ? browser.searchError ? /*#__PURE__*/ jsxs("div", {
411
+ className: "ov-file-browser__hint ov-file-browser__hint--error",
412
+ children: [
413
+ /*#__PURE__*/ jsx("p", {
414
+ className: "ov-file-browser__failure-title",
415
+ children: searchErrorLabel
416
+ }),
417
+ /*#__PURE__*/ jsx("p", {
418
+ className: "ov-file-browser__failure-detail",
419
+ children: browser.searchError.message
420
+ }),
421
+ /*#__PURE__*/ jsx("button", {
422
+ type: "button",
423
+ className: "ov-file-browser__retry",
424
+ onClick: ()=>void browser.actions.refresh(),
425
+ children: retryLabel
426
+ })
427
+ ]
428
+ }) : /*#__PURE__*/ jsx("p", {
429
+ className: "ov-file-browser__hint",
430
+ children: browser.searchLoading ? searchLoading : searchEmpty
431
+ }) : void 0,
432
+ renderRowIcon: (row)=>browser.dashboards.get(row.uri)?.isRoot ? /*#__PURE__*/ jsx(WikiBookIcon, {
433
+ width: 14,
434
+ height: 14
435
+ }) : fileTypeIcon(row.name),
436
+ renderDashboard: (row)=>{
437
+ const dashboard = browser.dashboards.get(row.uri);
438
+ return dashboard ? /*#__PURE__*/ jsx(DashboardIndicator, {
439
+ dashboard: dashboard,
440
+ locale: locale,
441
+ labels: dashboardLabels,
442
+ onOpen: browser.actions.openDashboard
443
+ }) : null;
444
+ },
445
+ operations: {
446
+ select: browser.actions.select,
447
+ toggleExpand: browser.actions.toggleExpand,
448
+ loadMore: browser.actions.loadMore,
449
+ retry: browser.actions.retry
450
+ }
451
+ })
452
+ ]
378
453
  })
379
454
  ]
380
455
  });
@@ -475,6 +550,11 @@ function useContainerWidth() {
475
550
  width
476
551
  };
477
552
  }
553
+ function selectedRowId(uri, results) {
554
+ if (!uri || null === results) return uri;
555
+ const index = results.findIndex((entry)=>entry.uri === uri);
556
+ return index < 0 ? uri : `${uri}#${index}`;
557
+ }
478
558
  const emptyDir = ()=>({
479
559
  entries: [],
480
560
  hasMore: false,
@@ -502,6 +582,7 @@ function nameFromUri(uri) {
502
582
  function toEntryRow(entry, depth, expanded, index, busy) {
503
583
  const isDir = true === entry.isDir;
504
584
  return {
585
+ tags: entry.tags,
505
586
  kind: 'entry',
506
587
  id: void 0 === index ? entry.uri : `${entry.uri}#${index}`,
507
588
  depth,
@@ -512,7 +593,7 @@ function toEntryRow(entry, depth, expanded, index, busy) {
512
593
  busy: busy || void 0
513
594
  };
514
595
  }
515
- function toFileTab(entry, content, maxLines, icon, openParent) {
596
+ function toFileTab(entry, content, maxLines, icon, openParent, truncated = content.split('\n').length >= maxLines) {
516
597
  const name = nameFromUri(entry.uri);
517
598
  return {
518
599
  kind: 'file',
@@ -526,7 +607,7 @@ function toFileTab(entry, content, maxLines, icon, openParent) {
526
607
  content,
527
608
  fileName: name,
528
609
  path: entry.uri,
529
- truncated: content.split('\n').length >= maxLines
610
+ truncated
530
611
  }
531
612
  };
532
613
  }
@@ -611,6 +692,39 @@ function isAbort(error) {
611
692
  function toError(cause) {
612
693
  return cause instanceof Error ? cause : new Error(String(cause));
613
694
  }
695
+ async function readDirectory(client, uri, options) {
696
+ const read = (path)=>client.request({
697
+ method: 'GET',
698
+ path,
699
+ query: {
700
+ uri
701
+ },
702
+ options
703
+ }).then((value)=>({
704
+ ok: true,
705
+ text: 'string' == typeof value ? value : ''
706
+ })).catch((cause)=>({
707
+ ok: false,
708
+ cause
709
+ }));
710
+ const [abstractResult, overviewResult] = await Promise.all([
711
+ read(OV_PATHS.contentAbstract),
712
+ read(OV_PATHS.contentOverview)
713
+ ]);
714
+ const aborted = [
715
+ abstractResult,
716
+ overviewResult
717
+ ].find((result)=>!result.ok && isAbort(result.cause));
718
+ if (aborted && !aborted.ok) throw aborted.cause;
719
+ if (!abstractResult.ok && !overviewResult.ok) throw abstractResult.cause;
720
+ const reason = (result)=>result.ok ? void 0 : result.cause instanceof Error ? result.cause.message : String(result.cause);
721
+ return {
722
+ abstract: abstractResult.ok ? abstractResult.text : '',
723
+ overview: overviewResult.ok ? overviewResult.text : '',
724
+ abstractError: reason(abstractResult),
725
+ overviewError: reason(overviewResult)
726
+ };
727
+ }
614
728
  const BINARY_EXTENSIONS = new Set([
615
729
  'png',
616
730
  'jpg',
@@ -694,38 +808,152 @@ function toBinaryTab(uri, name, file, icon, openParent) {
694
808
  }
695
809
  };
696
810
  }
697
- async function readDirectory(client, uri, options) {
698
- const read = (path)=>client.request({
811
+ const LINE_BREAK_CODES = new Set([
812
+ 0x0a,
813
+ 0x0b,
814
+ 0x0c,
815
+ 0x0d,
816
+ 0x1c,
817
+ 0x1d,
818
+ 0x1e,
819
+ 0x85,
820
+ 0x2028,
821
+ 0x2029
822
+ ]);
823
+ function splitLines(text) {
824
+ if (!text) return [];
825
+ const lines = [];
826
+ let start = 0;
827
+ for(let index = 0; index < text.length; index++){
828
+ if (!LINE_BREAK_CODES.has(text.charCodeAt(index))) continue;
829
+ const paired = 0x0d === text.charCodeAt(index) && 0x0a === text.charCodeAt(index + 1);
830
+ const end = index + (paired ? 2 : 1);
831
+ lines.push(text.slice(start, end));
832
+ start = end;
833
+ index = end - 1;
834
+ }
835
+ if (start < text.length) lines.push(text.slice(start));
836
+ return lines;
837
+ }
838
+ function joinLines(lines) {
839
+ return lines.join('');
840
+ }
841
+ const PY_WHITESPACE_CODES = [
842
+ 0x09,
843
+ 0x0a,
844
+ 0x0b,
845
+ 0x0c,
846
+ 0x0d,
847
+ 0x1c,
848
+ 0x1d,
849
+ 0x1e,
850
+ 0x1f,
851
+ 0x20,
852
+ 0x85,
853
+ 0xa0,
854
+ 0x1680,
855
+ 0x2000,
856
+ 0x2001,
857
+ 0x2002,
858
+ 0x2003,
859
+ 0x2004,
860
+ 0x2005,
861
+ 0x2006,
862
+ 0x2007,
863
+ 0x2008,
864
+ 0x2009,
865
+ 0x200a,
866
+ 0x2028,
867
+ 0x2029,
868
+ 0x202f,
869
+ 0x205f,
870
+ 0x3000
871
+ ];
872
+ const PY_WHITESPACE = String.fromCharCode(...PY_WHITESPACE_CODES);
873
+ const PY_WORD = '\\p{L}\\p{N}_';
874
+ const MEMORY_FIELDS_COMMENT = new RegExp(`<!--[${PY_WHITESPACE}]*MEMORY_FIELDS(?![${PY_WORD}])[\\s\\S]*?[${PY_WHITESPACE}]*-->`, 'gu');
875
+ function isPythonBlank(text) {
876
+ for (const char of text)if (!PY_WHITESPACE.includes(char)) return false;
877
+ return true;
878
+ }
879
+ function trimPythonEnd(text) {
880
+ let end = text.length;
881
+ while(end > 0 && PY_WHITESPACE.includes(text[end - 1] ?? ''))end--;
882
+ return text.slice(0, end);
883
+ }
884
+ function uriParts(uri) {
885
+ const [beforeQuery = ''] = uri.split('?');
886
+ const path = beforeQuery.replace(/\/+$/, '');
887
+ if (!path.startsWith('viking://')) return [];
888
+ return path.slice(9).split('/').filter(Boolean);
889
+ }
890
+ function isMemoryUri(uri) {
891
+ const parts = uriParts(uri);
892
+ if (parts.length < 3) return false;
893
+ if ('user' !== parts[0] && '~' !== parts[0]) return false;
894
+ const scoped = '~' === parts[0] ? [
895
+ 'user',
896
+ '~',
897
+ ...parts.slice(1)
898
+ ] : parts;
899
+ if ('memories' === scoped[2]) return true;
900
+ return scoped.length >= 5 && 'peers' === scoped[2] && 'memories' === scoped[4];
901
+ }
902
+ function stripMemoryFieldsTrailer(text) {
903
+ let visible = text;
904
+ for(;;){
905
+ let start = -1;
906
+ MEMORY_FIELDS_COMMENT.lastIndex = 0;
907
+ let match;
908
+ while(null !== (match = MEMORY_FIELDS_COMMENT.exec(visible))){
909
+ const after = visible.slice(match.index + match[0].length);
910
+ if (isPythonBlank(after)) start = match.index;
911
+ }
912
+ if (start < 0) return visible;
913
+ visible = trimPythonEnd(visible.slice(0, start));
914
+ }
915
+ }
916
+ const MAX_LINES = 2000;
917
+ async function readFile(client, uri, options, openParent) {
918
+ const name = nameFromUri(uri);
919
+ const icon = fileTypeIcon(name);
920
+ if (isBinaryFile(name)) {
921
+ const blob = await client.request({
699
922
  method: 'GET',
700
- path,
923
+ path: OV_PATHS.contentDownload,
701
924
  query: {
702
925
  uri
703
926
  },
927
+ responseType: 'blob',
704
928
  options
705
- }).then((value)=>({
706
- ok: true,
707
- text: 'string' == typeof value ? value : ''
708
- })).catch((cause)=>({
709
- ok: false,
710
- cause
711
- }));
712
- const [abstractResult, overviewResult] = await Promise.all([
713
- read(OV_PATHS.contentAbstract),
714
- read(OV_PATHS.contentOverview)
715
- ]);
716
- const aborted = [
717
- abstractResult,
718
- overviewResult
719
- ].find((result)=>!result.ok && isAbort(result.cause));
720
- if (aborted && !aborted.ok) throw aborted.cause;
721
- if (!abstractResult.ok && !overviewResult.ok) throw abstractResult.cause;
722
- const reason = (result)=>result.ok ? void 0 : result.cause instanceof Error ? result.cause.message : String(result.cause);
723
- return {
724
- abstract: abstractResult.ok ? abstractResult.text : '',
725
- overview: overviewResult.ok ? overviewResult.text : '',
726
- abstractError: reason(abstractResult),
727
- overviewError: reason(overviewResult)
728
- };
929
+ });
930
+ const typed = new Blob([
931
+ blob
932
+ ], {
933
+ type: mimeTypeOf(name)
934
+ });
935
+ return toBinaryTab(uri, name, typed, icon, openParent);
936
+ }
937
+ const read = (limit)=>client.request({
938
+ method: 'GET',
939
+ path: OV_PATHS.contentRead,
940
+ query: {
941
+ uri,
942
+ limit
943
+ },
944
+ options
945
+ }).then((value)=>'string' == typeof value ? value : '');
946
+ const first = await read(MAX_LINES);
947
+ if (!isMemoryUri(uri)) return toFileTab({
948
+ uri
949
+ }, first, MAX_LINES, icon, openParent, splitLines(first).length >= MAX_LINES);
950
+ const full = splitLines(first).length < MAX_LINES ? first : await read(-1);
951
+ const lines = splitLines(stripMemoryFieldsTrailer(full));
952
+ const truncated = lines.length > MAX_LINES;
953
+ const visible = joinLines(truncated ? lines.slice(0, MAX_LINES) : lines);
954
+ return toFileTab({
955
+ uri
956
+ }, visible, MAX_LINES, icon, openParent, truncated);
729
957
  }
730
958
  async function resolveIsDirectory(client, uri, options) {
731
959
  try {
@@ -747,7 +975,6 @@ function abortError() {
747
975
  error.name = 'AbortError';
748
976
  return error;
749
977
  }
750
- const MAX_LINES = 2000;
751
978
  function useFsPreview({ client, uri, resourceType = 'file', labels = resolveSummaryLabels('en-US'), formatCharacterCount = resolveLabels(void 0, 'en-US').formatCharacterCount, openParent, generation = 0, requestOptions }) {
752
979
  const [directory, setDirectory] = useState(null);
753
980
  const [tabs, setTabs] = useState(null);
@@ -866,39 +1093,6 @@ function loadingTab(uri, isDirectory) {
866
1093
  }
867
1094
  };
868
1095
  }
869
- async function readFile(client, uri, options, openParent) {
870
- const name = nameFromUri(uri);
871
- const icon = fileTypeIcon(name);
872
- if (isBinaryFile(name)) {
873
- const blob = await client.request({
874
- method: 'GET',
875
- path: OV_PATHS.contentDownload,
876
- query: {
877
- uri
878
- },
879
- responseType: 'blob',
880
- options
881
- });
882
- const typed = new Blob([
883
- blob
884
- ], {
885
- type: mimeTypeOf(name)
886
- });
887
- return toBinaryTab(uri, name, typed, icon, openParent);
888
- }
889
- const content = await client.request({
890
- method: 'GET',
891
- path: OV_PATHS.contentRead,
892
- query: {
893
- uri,
894
- limit: MAX_LINES
895
- },
896
- options
897
- });
898
- return toFileTab({
899
- uri
900
- }, 'string' == typeof content ? content : '', MAX_LINES, icon, openParent);
901
- }
902
1096
  function mergeFindResult(result) {
903
1097
  const seen = new Set();
904
1098
  const entries = [];
@@ -970,6 +1164,659 @@ function useFsSearch({ client, query, targetUri, generation = 0, requestOptions
970
1164
  error
971
1165
  };
972
1166
  }
1167
+ const isHomeUri = (uri)=>'viking://~' === uri || uri.startsWith('viking://~/');
1168
+ async function readDashboardStat(client, uri, options) {
1169
+ const stat = await client.request({
1170
+ method: 'GET',
1171
+ path: OV_PATHS.fsStat,
1172
+ query: {
1173
+ uri
1174
+ },
1175
+ options
1176
+ });
1177
+ const canonical = stat?.uri ?? uri;
1178
+ if ('boolean' != typeof stat?.isDir || 'string' != typeof canonical || !canonical || isHomeUri(canonical)) throw new TypeError('Invalid canonical resource stat');
1179
+ return {
1180
+ uri: canonical,
1181
+ isDir: stat.isDir
1182
+ };
1183
+ }
1184
+ async function resolveDashboardUri(client, uri, options) {
1185
+ return isHomeUri(uri) ? (await readDashboardStat(client, uri, options)).uri : uri;
1186
+ }
1187
+ async function readDashboardHint(client, uri, options) {
1188
+ const result = await client.request({
1189
+ method: 'GET',
1190
+ path: OV_PATHS.fsAttrs,
1191
+ query: {
1192
+ uri
1193
+ },
1194
+ options
1195
+ });
1196
+ return {
1197
+ uri: await resolveDashboardUri(client, result?.uri ?? uri, options),
1198
+ tags: result?.attrs?.tags ?? []
1199
+ };
1200
+ }
1201
+ const EXPERIENCE_PAGE_SIZE = 20;
1202
+ const isExperienceDirectory = (uri)=>/^viking:\/\/(?:user\/[^/]+|~)\/memories\/experiences\/?$/.test(uri);
1203
+ const isExperienceFile = (uri)=>/^viking:\/\/(?:user\/[^/]+|~)\/memories\/experiences\/[^/]+\.md$/i.test(uri);
1204
+ function experienceDateRange(days, now = new Date()) {
1205
+ if (!days) return {};
1206
+ const start = new Date(now);
1207
+ start.setUTCDate(start.getUTCDate() - days + 1);
1208
+ return {
1209
+ start_date: start.toISOString().slice(0, 10),
1210
+ end_date: now.toISOString().slice(0, 10)
1211
+ };
1212
+ }
1213
+ async function readExperiences(client, uri, page, options) {
1214
+ uri = await resolveDashboardUri(client, uri, options);
1215
+ const result = await client.requestEnvelope({
1216
+ method: 'GET',
1217
+ path: OV_PATHS.fsLs,
1218
+ query: {
1219
+ uri,
1220
+ output: 'original',
1221
+ limit: EXPERIENCE_PAGE_SIZE,
1222
+ offset: page * EXPERIENCE_PAGE_SIZE,
1223
+ sort_by: 'mtime',
1224
+ sort_order: 'desc'
1225
+ },
1226
+ options
1227
+ });
1228
+ if (!Array.isArray(result.result)) throw new TypeError('Invalid Experience listing');
1229
+ const prefix = `${uri.replace(/\/+$/, '')}/`;
1230
+ return {
1231
+ items: result.result.filter((item)=>!item.isDir && item.uri.startsWith(prefix) && isExperienceFile(item.uri)),
1232
+ hasMore: result.hasMore
1233
+ };
1234
+ }
1235
+ async function readExperienceSources(client, uri, options) {
1236
+ uri = await resolveDashboardUri(client, uri, options);
1237
+ const result = await client.request({
1238
+ method: 'GET',
1239
+ path: OV_PATHS.fsAttrs,
1240
+ query: {
1241
+ uri
1242
+ },
1243
+ options
1244
+ });
1245
+ const links = result?.attrs?.memory?.links;
1246
+ if (void 0 !== links && !Array.isArray(links)) throw new TypeError('Invalid Experience links');
1247
+ const prefix = uri.slice(0, uri.indexOf('/memories/experiences/')) + '/memories/trajectories/';
1248
+ const seen = new Set();
1249
+ return (links ?? []).flatMap((link)=>{
1250
+ if ('derived_from' !== link.link_type || 'string' != typeof link.to_uri || !link.to_uri.startsWith(prefix) || seen.has(link.to_uri)) return [];
1251
+ seen.add(link.to_uri);
1252
+ return [
1253
+ {
1254
+ uri: link.to_uri,
1255
+ name: link.to_uri.split('/').pop() ?? link.to_uri,
1256
+ description: link.description ?? link.match_text
1257
+ }
1258
+ ];
1259
+ });
1260
+ }
1261
+ const dashboardKey = (uri)=>`dashboard:${uri}`;
1262
+ const within = (uri, root)=>uri === root || uri.startsWith(`${root.replace(/\/+$/, '')}/`);
1263
+ function resolveDashboard(uri, rows, targets) {
1264
+ if (isExperienceDirectory(uri) || isExperienceFile(uri)) return {
1265
+ kind: 'experience',
1266
+ uri
1267
+ };
1268
+ const entries = rows.filter((row)=>'entry' === row.kind);
1269
+ const row = entries.find((item)=>item.uri === uri);
1270
+ const hasWiki = entries.some((item)=>item.tags?.includes('compile_target=true') && within(uri, item.uri));
1271
+ const owner = targets.filter((item)=>within(uri, item.to)).sort((a, b)=>b.to.length - a.to.length)[0];
1272
+ if (!hasWiki && !owner) return;
1273
+ const tagged = row?.tags?.find((tag)=>tag.startsWith('has_conflict='));
1274
+ return {
1275
+ kind: 'wiki',
1276
+ uri,
1277
+ isRoot: Boolean(row?.tags?.includes('compile_target=true') || owner?.to === uri),
1278
+ pendingConflicts: tagged ? 'has_conflict=true' === tagged : owner?.to === uri && void 0 !== owner.conflicts_num ? owner.conflicts_num > 0 : void 0
1279
+ };
1280
+ }
1281
+ async function readCompileTargets(client, rootUri, options) {
1282
+ rootUri = await resolveDashboardUri(client, rootUri, options);
1283
+ const targets = [];
1284
+ let cursor;
1285
+ const seen = new Set();
1286
+ do {
1287
+ const result = await client.request({
1288
+ method: 'GET',
1289
+ path: OV_PATHS.compileConfigs,
1290
+ query: {
1291
+ limit: 100,
1292
+ cursor
1293
+ },
1294
+ options
1295
+ });
1296
+ if (!Array.isArray(result?.targets)) throw new TypeError('Invalid Compile target registry');
1297
+ targets.push(...result.targets.filter((item)=>'string' == typeof item.to && 'memory' !== item.compile_type && false !== item.initialized && (within(item.to, rootUri) || within(rootUri, item.to))));
1298
+ cursor = result.next_cursor ?? void 0;
1299
+ if (cursor && seen.has(cursor)) throw new TypeError('Compile target cursor did not advance');
1300
+ if (cursor) seen.add(cursor);
1301
+ }while (cursor)
1302
+ return targets;
1303
+ }
1304
+ function useDashboardQuery(load, requestOptions, enabled = true, refreshGeneration = 0) {
1305
+ const client = useOvClient();
1306
+ const inheritedSignal = useOvSignal();
1307
+ const { baseURL, apiKey, accountId, userId, resourceId, signal } = requestOptions ?? {};
1308
+ const [generation, setGeneration] = useState(0);
1309
+ const [state, setState] = useState({
1310
+ owner: [],
1311
+ error: null
1312
+ });
1313
+ const owner = useMemo(()=>[
1314
+ client,
1315
+ load,
1316
+ baseURL,
1317
+ apiKey,
1318
+ accountId,
1319
+ userId,
1320
+ resourceId,
1321
+ signal,
1322
+ inheritedSignal,
1323
+ generation,
1324
+ enabled,
1325
+ refreshGeneration
1326
+ ], [
1327
+ client,
1328
+ load,
1329
+ baseURL,
1330
+ apiKey,
1331
+ accountId,
1332
+ userId,
1333
+ resourceId,
1334
+ signal,
1335
+ inheritedSignal,
1336
+ generation,
1337
+ enabled,
1338
+ refreshGeneration
1339
+ ]);
1340
+ const current = owner.every((value, i)=>value === state.owner[i]);
1341
+ useEffect(()=>{
1342
+ if (!enabled) return;
1343
+ if (!client) return void setState({
1344
+ owner,
1345
+ error: new Error('OpenVikingProvider is required')
1346
+ });
1347
+ const controller = new AbortController();
1348
+ const signals = [
1349
+ controller.signal,
1350
+ signal,
1351
+ inheritedSignal
1352
+ ].filter((value)=>Boolean(value));
1353
+ const options = {
1354
+ baseURL,
1355
+ apiKey,
1356
+ accountId,
1357
+ userId,
1358
+ resourceId,
1359
+ signal: AbortSignal.any(signals)
1360
+ };
1361
+ load(client, options).then((data)=>{
1362
+ if (!options.signal.aborted) setState({
1363
+ owner,
1364
+ data,
1365
+ error: null
1366
+ });
1367
+ }, (cause)=>{
1368
+ if (!options.signal.aborted) setState({
1369
+ owner,
1370
+ error: cause instanceof Error ? cause : new Error(String(cause))
1371
+ });
1372
+ });
1373
+ return ()=>controller.abort();
1374
+ }, [
1375
+ client,
1376
+ load,
1377
+ baseURL,
1378
+ apiKey,
1379
+ accountId,
1380
+ userId,
1381
+ resourceId,
1382
+ signal,
1383
+ inheritedSignal,
1384
+ generation,
1385
+ enabled,
1386
+ owner
1387
+ ]);
1388
+ return {
1389
+ data: current ? state.data : void 0,
1390
+ loading: enabled && !current,
1391
+ error: current ? state.error : null,
1392
+ retry: ()=>setGeneration((value)=>value + 1)
1393
+ };
1394
+ }
1395
+ function useExperienceDashboard({ uri, requestOptions, enabled = true, refreshGeneration = 0 }) {
1396
+ const client = useOvClient();
1397
+ const signal = useOvSignal();
1398
+ const owner = useMemo(()=>[
1399
+ uri,
1400
+ client,
1401
+ signal,
1402
+ requestOptions?.baseURL,
1403
+ requestOptions?.apiKey,
1404
+ requestOptions?.accountId,
1405
+ requestOptions?.userId,
1406
+ requestOptions?.resourceId
1407
+ ], [
1408
+ uri,
1409
+ client,
1410
+ signal,
1411
+ requestOptions?.baseURL,
1412
+ requestOptions?.apiKey,
1413
+ requestOptions?.accountId,
1414
+ requestOptions?.userId,
1415
+ requestOptions?.resourceId
1416
+ ]);
1417
+ const [state, setState] = useState({
1418
+ owner,
1419
+ page: 0,
1420
+ days: 7,
1421
+ tab: 'impact'
1422
+ });
1423
+ const current = state.owner === owner ? state : {
1424
+ owner,
1425
+ page: 0,
1426
+ days: 7,
1427
+ tab: 'impact'
1428
+ };
1429
+ const { page, days, tab } = current;
1430
+ const setPage = (value)=>setState({
1431
+ ...current,
1432
+ page: Math.max(0, value)
1433
+ });
1434
+ const setDays = (value)=>setState({
1435
+ ...current,
1436
+ days: value,
1437
+ page: 0
1438
+ });
1439
+ const setTab = (value)=>setState({
1440
+ ...current,
1441
+ tab: value,
1442
+ page: 0
1443
+ });
1444
+ const directory = isExperienceDirectory(uri);
1445
+ const loadList = useCallback((client, options)=>readExperiences(client, uri, page, options), [
1446
+ uri,
1447
+ page
1448
+ ]);
1449
+ const loadSources = useCallback((client, options)=>readExperienceSources(client, uri, options), [
1450
+ uri
1451
+ ]);
1452
+ const loadTrajectories = useCallback(async (client, options)=>{
1453
+ const result = await client.request({
1454
+ method: 'GET',
1455
+ path: OV_PATHS.experienceTrajectories,
1456
+ query: {
1457
+ experience_uri: uri,
1458
+ offset: 20 * page,
1459
+ limit: 20,
1460
+ ...experienceDateRange(days)
1461
+ },
1462
+ options
1463
+ });
1464
+ if (!Array.isArray(result?.items) || !Number.isSafeInteger(result.total) || result.total < 0 || result.items.some((item)=>'string' != typeof item?.uri || 'string' != typeof item.name)) throw new TypeError('Invalid Experience trajectories');
1465
+ return result;
1466
+ }, [
1467
+ uri,
1468
+ page,
1469
+ days
1470
+ ]);
1471
+ const loadOutcomes = useCallback(async (client, options)=>{
1472
+ const result = await client.request({
1473
+ method: 'GET',
1474
+ path: OV_PATHS.experienceOutcomes,
1475
+ query: {
1476
+ experience_uri: uri,
1477
+ ...experienceDateRange(days)
1478
+ },
1479
+ options
1480
+ });
1481
+ if (!Array.isArray(result?.outcome_distribution) || result.outcome_distribution.some((entry)=>![
1482
+ 'success',
1483
+ 'partial',
1484
+ 'unfinished',
1485
+ 'failure',
1486
+ 'unknown'
1487
+ ].includes(entry?.outcome) || !Number.isSafeInteger(entry.count) || entry.count < 0)) throw new TypeError('Invalid Experience outcomes');
1488
+ return result.outcome_distribution;
1489
+ }, [
1490
+ uri,
1491
+ days
1492
+ ]);
1493
+ const list = useDashboardQuery(loadList, requestOptions, enabled && directory, refreshGeneration);
1494
+ const sources = useDashboardQuery(loadSources, requestOptions, enabled && !directory && 'source' === tab, refreshGeneration);
1495
+ const trajectories = useDashboardQuery(loadTrajectories, requestOptions, enabled && !directory && 'impact' === tab, refreshGeneration);
1496
+ const outcomes = useDashboardQuery(loadOutcomes, requestOptions, enabled && !directory && 'impact' === tab, refreshGeneration);
1497
+ return {
1498
+ list,
1499
+ sources,
1500
+ trajectories,
1501
+ outcomes,
1502
+ page,
1503
+ setPage,
1504
+ days,
1505
+ setDays,
1506
+ tab,
1507
+ setTab
1508
+ };
1509
+ }
1510
+ function ExperienceDashboardPane({ uri, locale, requestOptions, refreshGeneration, onOpenUri }) {
1511
+ const browser = useExperienceDashboard({
1512
+ uri,
1513
+ requestOptions,
1514
+ refreshGeneration
1515
+ });
1516
+ const directory = isExperienceDirectory(uri);
1517
+ const status = (query)=>({
1518
+ loading: query.loading,
1519
+ error: query.error,
1520
+ onRetry: query.retry
1521
+ });
1522
+ return /*#__PURE__*/ jsx(ExperienceDashboard, {
1523
+ uri: uri,
1524
+ kind: directory ? 'directory' : 'file',
1525
+ locale: locale,
1526
+ onOpenUri: onOpenUri,
1527
+ data: {
1528
+ experiences: browser.list.data?.items,
1529
+ outcomes: browser.outcomes.data,
1530
+ trajectories: browser.trajectories.data?.items,
1531
+ trajectoryTotal: browser.trajectories.data?.total,
1532
+ sources: browser.sources.data
1533
+ },
1534
+ tab: browser.tab,
1535
+ days: browser.days,
1536
+ page: browser.page,
1537
+ startIndex: 20 * browser.page,
1538
+ hasMore: Boolean(directory ? browser.list.data?.hasMore : 'impact' === browser.tab && browser.trajectories.data?.has_more),
1539
+ states: {
1540
+ list: status(browser.list),
1541
+ sources: status(browser.sources),
1542
+ outcomes: status(browser.outcomes),
1543
+ trajectories: status(browser.trajectories)
1544
+ },
1545
+ onTabChange: browser.setTab,
1546
+ onDaysChange: browser.setDays,
1547
+ onPageChange: browser.setPage
1548
+ });
1549
+ }
1550
+ const wiki_conflicts_prefix = '<!-- CONFLICTS_CONTENT';
1551
+ const manualResolutionBasis = '\u4eba\u5de5\u4fee\u590d';
1552
+ const timestamp = (value)=>'number' == typeof value && Number.isSafeInteger(value) && value >= 0 && Number.isFinite(new Date(1000 * value).getTime());
1553
+ const locateWikiConflict = (document, matchText)=>{
1554
+ const mask = (value)=>value.replace(/[^\r\n]/g, ' ');
1555
+ const body = document.replace(/^(?:\uFEFF)?---\r?\n[\s\S]*?\r?\n---(?:\r?\n|$)/, mask).replace(/<!--[\s\S]*?(?:-->|$)/g, mask);
1556
+ const start = matchText ? body.indexOf(matchText) : -1;
1557
+ if (start < 0) return {
1558
+ status: 'missing'
1559
+ };
1560
+ if (body.indexOf(matchText, start + 1) >= 0) return {
1561
+ status: 'ambiguous'
1562
+ };
1563
+ return {
1564
+ status: 'unique',
1565
+ start,
1566
+ end: start + matchText.length,
1567
+ line: document.slice(0, start).split('\n').length
1568
+ };
1569
+ };
1570
+ const parseWikiFileConflicts = (content)=>{
1571
+ const start = content.lastIndexOf(wiki_conflicts_prefix);
1572
+ if (start < 0) return {
1573
+ status: 'missing'
1574
+ };
1575
+ const footer = content.slice(start).trimEnd();
1576
+ if (!footer.endsWith('-->')) return {
1577
+ status: 'invalid'
1578
+ };
1579
+ const document = content.slice(0, start);
1580
+ const source = footer.slice(wiki_conflicts_prefix.length, -3).trim();
1581
+ let parsed;
1582
+ try {
1583
+ parsed = source ? JSON.parse(`[${source}]`) : [];
1584
+ } catch {
1585
+ return {
1586
+ status: 'invalid'
1587
+ };
1588
+ }
1589
+ if (!Array.isArray(parsed)) return {
1590
+ status: 'invalid'
1591
+ };
1592
+ const records = [];
1593
+ for (const [index, raw] of parsed.entries()){
1594
+ if (!raw || 'object' != typeof raw || Array.isArray(raw)) return {
1595
+ status: 'invalid'
1596
+ };
1597
+ const value = raw;
1598
+ if ('string' != typeof value.match_text || !value.match_text || 'string' != typeof value.problem_description || 'string' != typeof value.reason || ![
1599
+ 'high',
1600
+ 'medium',
1601
+ 'low'
1602
+ ].includes(value.severity) || ![
1603
+ 'unfixed',
1604
+ 'fixed'
1605
+ ].includes(value.state) || !timestamp(value.begin_time) || 'string' != typeof value.fix_plan || 'string' != typeof value.resolution_basis) return {
1606
+ status: 'invalid'
1607
+ };
1608
+ if ('fixed' === value.state ? !timestamp(value.fix_time) || value.fix_time < value.begin_time : null !== value.fix_time) return {
1609
+ status: 'invalid'
1610
+ };
1611
+ const matchText = value.match_text;
1612
+ const location = locateWikiConflict(document, matchText);
1613
+ records.push({
1614
+ id: JSON.stringify([
1615
+ index,
1616
+ value.begin_time,
1617
+ matchText
1618
+ ]),
1619
+ matchText,
1620
+ description: value.problem_description,
1621
+ reason: value.reason,
1622
+ severity: value.severity,
1623
+ state: value.state,
1624
+ beginTime: value.begin_time,
1625
+ fixTime: value.fix_time,
1626
+ fixPlan: value.fix_plan,
1627
+ resolutionBasis: value.resolution_basis,
1628
+ resolutionSource: 'fixed' === value.state && value.resolution_basis.trim() ? value.resolution_basis.trim() === manualResolutionBasis ? 'manual' : 'automatic' : void 0,
1629
+ location
1630
+ });
1631
+ }
1632
+ return {
1633
+ status: 'available',
1634
+ document,
1635
+ records
1636
+ };
1637
+ };
1638
+ async function readWikiDashboard(client, uri, options) {
1639
+ const stat = await readDashboardStat(client, uri, options);
1640
+ uri = stat.uri;
1641
+ if (!stat.isDir) {
1642
+ const result = await client.request({
1643
+ method: 'GET',
1644
+ path: OV_PATHS.contentRead,
1645
+ query: {
1646
+ uri,
1647
+ limit: -1
1648
+ },
1649
+ options
1650
+ });
1651
+ if ('string' != typeof result) throw new TypeError('Invalid Wiki content response');
1652
+ const parsed = parseWikiFileConflicts(result);
1653
+ if ('invalid' === parsed.status) throw new TypeError('Invalid CONFLICTS_CONTENT metadata');
1654
+ return {
1655
+ kind: 'file',
1656
+ data: {
1657
+ path: uri,
1658
+ conflicts: 'available' === parsed.status ? parsed.records : []
1659
+ }
1660
+ };
1661
+ }
1662
+ const page = await client.requestEnvelope({
1663
+ method: 'GET',
1664
+ path: OV_PATHS.fsLs,
1665
+ query: {
1666
+ uri,
1667
+ recursive: true,
1668
+ output: 'agent',
1669
+ tags: [
1670
+ 'has_conflict=true'
1671
+ ],
1672
+ limit: 100,
1673
+ sort_by: 'mtime',
1674
+ sort_order: 'desc'
1675
+ },
1676
+ options
1677
+ });
1678
+ if (!Array.isArray(page.result)) throw new TypeError('Invalid Wiki conflict listing');
1679
+ const prefix = `${uri.replace(/\/+$/, '')}/`;
1680
+ const files = page.result.filter((entry)=>!entry.isDir && entry.uri.startsWith(prefix)).map((entry)=>entry.uri);
1681
+ return {
1682
+ kind: 'directory',
1683
+ data: {
1684
+ files,
1685
+ conflictFileCount: files.length,
1686
+ limited: page.hasMore || files.length >= 100
1687
+ }
1688
+ };
1689
+ }
1690
+ function useWikiDashboard({ uri, requestOptions, enabled = true, refreshGeneration = 0 }) {
1691
+ const load = useCallback((client, options)=>readWikiDashboard(client, uri, options), [
1692
+ uri
1693
+ ]);
1694
+ return useDashboardQuery(load, requestOptions, enabled, refreshGeneration);
1695
+ }
1696
+ function WikiDashboardPane({ uri, kind, requestOptions, refreshGeneration, onOpenUri, onOpenDashboard, onEdit, onDiscuss, ...props }) {
1697
+ const query = useWikiDashboard({
1698
+ uri,
1699
+ requestOptions,
1700
+ refreshGeneration
1701
+ });
1702
+ const common = {
1703
+ ...props,
1704
+ loading: query.loading,
1705
+ error: query.error,
1706
+ onRetry: query.retry
1707
+ };
1708
+ if ((query.data?.kind ?? kind) === 'file') return /*#__PURE__*/ createElement(WikiDashboard, {
1709
+ ...common,
1710
+ key: uri,
1711
+ kind: "file",
1712
+ data: query.data?.kind === 'file' ? query.data.data : void 0,
1713
+ onOpenUri: onOpenUri && (()=>onOpenUri(uri)),
1714
+ onEdit: onEdit && ((conflict)=>onEdit(uri, conflict)),
1715
+ onDiscuss: onDiscuss && ((conflict)=>onDiscuss(uri, conflict))
1716
+ });
1717
+ return /*#__PURE__*/ createElement(WikiDashboard, {
1718
+ ...common,
1719
+ key: uri,
1720
+ kind: "directory",
1721
+ data: query.data?.kind === 'directory' ? query.data.data : void 0,
1722
+ onOpenUri: onOpenUri,
1723
+ onOpenDashboard: onOpenDashboard,
1724
+ onEdit: onEdit
1725
+ });
1726
+ }
1727
+ function useBrowserDashboards({ rows, metadataRows, uri, rootUri, generation, locale, requestOptions, onOpenUri, dashboardKinds, renderDashboard, dashboardLabels }) {
1728
+ const [opened, setOpened] = useState(null);
1729
+ const load = useCallback((client, options)=>readCompileTargets(client, rootUri, options), [
1730
+ rootUri
1731
+ ]);
1732
+ const wikiEnabled = void 0 === dashboardKinds || dashboardKinds.includes('wiki');
1733
+ const catalog = useDashboardQuery(load, requestOptions, wikiEnabled, generation);
1734
+ const loadHint = useCallback(async (client, options)=>uri ? readDashboardHint(client, uri, options) : void 0, [
1735
+ uri
1736
+ ]);
1737
+ const hint = useDashboardQuery(loadHint, requestOptions, wikiEnabled && Boolean(uri), generation);
1738
+ const canonicalUri = hint.data?.uri ?? uri;
1739
+ const knownRows = canonicalUri && hint.data?.tags.includes('compile_target=true') ? [
1740
+ ...metadataRows,
1741
+ {
1742
+ kind: 'entry',
1743
+ uri: canonicalUri,
1744
+ id: canonicalUri,
1745
+ name: canonicalUri,
1746
+ depth: 0,
1747
+ type: 'directory',
1748
+ tags: hint.data.tags
1749
+ }
1750
+ ] : metadataRows;
1751
+ const unsupported = isOvClientError(catalog.error) && 404 === catalog.error.statusCode;
1752
+ const targets = catalog.data ?? [];
1753
+ const resolve = (target)=>{
1754
+ const match = resolveDashboard(target === uri ? canonicalUri ?? target : target, knownRows, targets);
1755
+ return match ? {
1756
+ ...match,
1757
+ uri: target
1758
+ } : void 0;
1759
+ };
1760
+ const dashboards = new Map(rows.filter((row)=>'entry' === row.kind).flatMap((row)=>{
1761
+ const dashboard = resolve(row.uri);
1762
+ return dashboard && (void 0 === dashboardKinds || dashboardKinds.includes(dashboard.kind)) ? [
1763
+ [
1764
+ row.uri,
1765
+ dashboard
1766
+ ]
1767
+ ] : [];
1768
+ }));
1769
+ const resolved = uri ? resolve(uri) : void 0;
1770
+ const current = resolved && (void 0 === dashboardKinds || dashboardKinds.includes(resolved.kind)) ? resolved : void 0;
1771
+ const open = useCallback((target)=>{
1772
+ setOpened(target);
1773
+ onOpenUri(target);
1774
+ }, [
1775
+ onOpenUri
1776
+ ]);
1777
+ const close = useCallback(()=>setOpened(null), []);
1778
+ const text = dashboard_labels_dashboardLabels(locale, dashboardLabels);
1779
+ const title = current?.kind === 'experience' ? text.experienceTitle : text.wikiTitle;
1780
+ const tab = current && uri ? {
1781
+ key: dashboardKey(uri),
1782
+ title,
1783
+ icon: createElement('experience' === current.kind ? ExperienceBoardIcon : WikiBoardIcon, {
1784
+ width: 14,
1785
+ height: 14
1786
+ }),
1787
+ kind: 'content',
1788
+ content: renderDashboard?.(current) ?? ('experience' === current.kind ? createElement(ExperienceDashboardPane, {
1789
+ uri,
1790
+ locale,
1791
+ requestOptions,
1792
+ refreshGeneration: generation,
1793
+ onOpenUri: (target)=>{
1794
+ setOpened(null);
1795
+ onOpenUri(target);
1796
+ }
1797
+ }) : createElement(WikiDashboardPane, {
1798
+ uri,
1799
+ kind: knownRows.some((row)=>'entry' === row.kind && row.uri === canonicalUri && 'file' === row.type) ? 'file' : 'directory',
1800
+ locale,
1801
+ requestOptions,
1802
+ refreshGeneration: generation,
1803
+ onOpenUri: (target)=>{
1804
+ setOpened(null);
1805
+ onOpenUri(target);
1806
+ },
1807
+ onOpenDashboard: open
1808
+ }))
1809
+ } : void 0;
1810
+ return {
1811
+ dashboards,
1812
+ tab,
1813
+ isOpen: null !== uri && opened === uri && Boolean(current),
1814
+ open,
1815
+ close,
1816
+ error: unsupported ? null : catalog.error,
1817
+ retry: catalog.retry
1818
+ };
1819
+ }
973
1820
  function knownDirectories(rootUri, dirs) {
974
1821
  const known = new Set([
975
1822
  rootUri
@@ -993,6 +1840,21 @@ function useKnownFile(dirs) {
993
1840
  files
994
1841
  ]);
995
1842
  }
1843
+ function useTreeMetadata(rootUri, dirs) {
1844
+ const directoryUris = useMemo(()=>knownDirectories(rootUri, dirs), [
1845
+ rootUri,
1846
+ dirs
1847
+ ]);
1848
+ const isKnownFile = useKnownFile(dirs);
1849
+ const metadataRows = useMemo(()=>Object.values(dirs).flatMap((dir)=>dir.entries.map((entry)=>toEntryRow(entry, 0, false))), [
1850
+ dirs
1851
+ ]);
1852
+ return {
1853
+ directoryUris,
1854
+ isKnownFile,
1855
+ metadataRows
1856
+ };
1857
+ }
996
1858
  const ids = new WeakMap();
997
1859
  let nextId = 1;
998
1860
  function idOf(value) {
@@ -1063,6 +1925,7 @@ async function loadPage(client, uri, offset, signal, requestOptions) {
1063
1925
  query: {
1064
1926
  uri,
1065
1927
  output: 'agent',
1928
+ include_tags: true,
1066
1929
  node_limit: PAGE_SIZE,
1067
1930
  offset
1068
1931
  },
@@ -1188,6 +2051,14 @@ function useFsTree({ client, rootUri, defaultExpandedUri, requestOptions }) {
1188
2051
  setExpanded((prev)=>new Set(prev).add(uri));
1189
2052
  if (!dirsRef.current[uri]) await fetchPage(uri, 0);
1190
2053
  },
2054
+ openPath: async (uri)=>{
2055
+ const current = scope.current();
2056
+ for (const parent of expandChain(rootUri, uri)){
2057
+ if (current.controller.signal.aborted || scope.current().key !== current.key) return;
2058
+ setExpanded((prev)=>new Set(prev).add(parent));
2059
+ if (!dirsRef.current[parent]) await fetchPage(parent, 0);
2060
+ }
2061
+ },
1191
2062
  toggleExpand: async (row)=>{
1192
2063
  const isOpen = expandedRef.current.has(row.uri);
1193
2064
  setExpanded((prev)=>{
@@ -1225,21 +2096,17 @@ function useFsTree({ client, rootUri, defaultExpandedUri, requestOptions }) {
1225
2096
  dirs,
1226
2097
  expanded
1227
2098
  ]);
1228
- const directoryUris = useMemo(()=>knownDirectories(rootUri, dirs), [
1229
- rootUri,
1230
- dirs
1231
- ]);
1232
- const isKnownFile = useKnownFile(dirs);
2099
+ const metadata = useTreeMetadata(rootUri, dirs);
1233
2100
  return {
1234
2101
  rows,
2102
+ ...metadata,
1235
2103
  isReady,
1236
2104
  error,
1237
- directoryUris,
1238
- isKnownFile,
1239
2105
  ...state
1240
2106
  };
1241
2107
  }
1242
- function useFileBrowser({ rootUri, locale = 'en-US', controlled = false, summaryLabels, formatCharacterCount, defaultExpandedUri, currentUri, requestOptions, onUriChange }) {
2108
+ function useFileBrowser({ rootUri, locale: localeProp, dashboardKinds, renderDashboard, dashboardLabels, controlled = false, summaryLabels, formatCharacterCount, defaultExpandedUri, currentUri, requestOptions, onUriChange }) {
2109
+ const locale = useLocale(localeProp);
1243
2110
  const client = useOvClient();
1244
2111
  const [query, setQuery] = useState('');
1245
2112
  const [pendingUri, setPendingUri] = useState(currentUri);
@@ -1287,17 +2154,36 @@ function useFileBrowser({ rootUri, locale = 'en-US', controlled = false, summary
1287
2154
  search.results,
1288
2155
  tree.rows
1289
2156
  ]);
1290
- const selectedId = useMemo(()=>{
1291
- if (!activeUri || null === search.results) return activeUri;
1292
- const index = search.results.findIndex((entry)=>entry.uri === activeUri);
1293
- return index < 0 ? activeUri : `${activeUri}#${index}`;
1294
- }, [
1295
- activeUri,
1296
- search.results
2157
+ const openPath = tree.openPath;
2158
+ const openResource = useMemo(()=>async (uri)=>{
2159
+ setPendingUri(uri);
2160
+ notifyUriChange.current(uri);
2161
+ const directory = tree.directoryUris.has(uri) ? uri : uri.slice(0, uri.lastIndexOf('/'));
2162
+ await openPath(directory);
2163
+ }, [
2164
+ openPath,
2165
+ tree.directoryUris
1297
2166
  ]);
2167
+ const boards = useBrowserDashboards({
2168
+ rows,
2169
+ metadataRows: tree.metadataRows,
2170
+ uri: activeUri,
2171
+ rootUri,
2172
+ generation: refreshGeneration,
2173
+ locale,
2174
+ requestOptions,
2175
+ onOpenUri: openResource,
2176
+ dashboardKinds,
2177
+ renderDashboard,
2178
+ dashboardLabels
2179
+ });
2180
+ const selectedId = selectedRowId(activeUri, search.results);
1298
2181
  const { open, toggleExpand, loadMore, retry, refresh } = tree;
2182
+ const { open: openDashboard, close: closeDashboard } = boards;
2183
+ const setActiveKey = preview.setActiveKey;
1299
2184
  const actions = useMemo(()=>({
1300
2185
  select: async (row)=>{
2186
+ closeDashboard();
1301
2187
  setPendingUri(row.uri);
1302
2188
  notifyUriChange.current(row.uri);
1303
2189
  if ('directory' === row.type) await open(row.uri);
@@ -1320,15 +2206,25 @@ function useFileBrowser({ rootUri, locale = 'en-US', controlled = false, summary
1320
2206
  setRefreshing(false);
1321
2207
  }
1322
2208
  },
1323
- setPreviewKey: preview.setActiveKey,
2209
+ openDashboard: openDashboard,
2210
+ setPreviewKey: (key)=>{
2211
+ if (activeUri && key === dashboardKey(activeUri)) openDashboard(activeUri);
2212
+ else {
2213
+ closeDashboard();
2214
+ setActiveKey(key);
2215
+ }
2216
+ },
1324
2217
  setQuery
1325
2218
  }), [
1326
- preview.setActiveKey,
2219
+ setActiveKey,
1327
2220
  open,
1328
2221
  toggleExpand,
1329
2222
  loadMore,
1330
2223
  retry,
1331
- refresh
2224
+ refresh,
2225
+ openDashboard,
2226
+ closeDashboard,
2227
+ activeUri
1332
2228
  ]);
1333
2229
  return {
1334
2230
  rows,
@@ -1339,8 +2235,13 @@ function useFileBrowser({ rootUri, locale = 'en-US', controlled = false, summary
1339
2235
  treeError: tree.error,
1340
2236
  previewError: preview.error,
1341
2237
  searchError: search.error,
1342
- previewTabs: preview.tabs,
1343
- previewKey: preview.activeKey,
2238
+ dashboards: boards.dashboards,
2239
+ dashboardError: boards.error,
2240
+ previewTabs: boards.tab ? [
2241
+ ...preview.tabs ?? [],
2242
+ boards.tab
2243
+ ] : preview.tabs,
2244
+ previewKey: boards.isOpen && activeUri ? dashboardKey(activeUri) : preview.activeKey,
1344
2245
  previewFooter: preview.footer,
1345
2246
  query,
1346
2247
  searching: null !== search.results,
@@ -1349,7 +2250,8 @@ function useFileBrowser({ rootUri, locale = 'en-US', controlled = false, summary
1349
2250
  actions
1350
2251
  };
1351
2252
  }
1352
- function FileBrowser({ uri, defaultUri, rootUri = 'viking://', defaultExpandedUri, locale, agentConnect, onUriChange, onImportResources, renderImportResources, labels, requestOptions, className, style, ...rest }) {
2253
+ function FileBrowser({ uri, defaultUri, rootUri = 'viking://', defaultExpandedUri, locale: localeProp, agentConnect, dashboardKinds, renderDashboard, onUriChange, onImportResources, renderImportResources, labels, requestOptions, className, style, ...rest }) {
2254
+ const locale = useLocale(localeProp);
1353
2255
  const [internalUri, setInternalUri] = useState(()=>defaultUri ?? null);
1354
2256
  const [preferredTreeWidth, setPreferredTreeWidth] = useState(352);
1355
2257
  const searchId = useId();
@@ -1382,6 +2284,9 @@ function FileBrowser({ uri, defaultUri, rootUri = 'viking://', defaultExpandedUr
1382
2284
  const browser = useFileBrowser({
1383
2285
  rootUri,
1384
2286
  locale,
2287
+ dashboardKinds,
2288
+ renderDashboard,
2289
+ dashboardLabels: labels?.dashboard,
1385
2290
  controlled: isControlled,
1386
2291
  summaryLabels,
1387
2292
  formatCharacterCount: text.formatCharacterCount,
@@ -1390,77 +2295,81 @@ function FileBrowser({ uri, defaultUri, rootUri = 'viking://', defaultExpandedUr
1390
2295
  requestOptions,
1391
2296
  onUriChange: changeUri
1392
2297
  });
1393
- return /*#__PURE__*/ jsxs("div", {
1394
- ...rest,
1395
- ref: layoutRef,
1396
- className: [
1397
- 'ov-file-browser',
1398
- className
1399
- ].filter(Boolean).join(' '),
1400
- style: {
1401
- ...style,
1402
- '--ov-file-browser-tree-width': `${treeWidth}px`
1403
- },
1404
- children: [
1405
- /*#__PURE__*/ jsx("div", {
1406
- className: "ov-file-browser__tree",
1407
- children: /*#__PURE__*/ jsx(FileBrowserTreePane, {
1408
- entries: {
1409
- agentConnect,
1410
- onImportResources,
1411
- renderImportResources,
1412
- labels: labels?.entries
1413
- },
1414
- searchId: searchId,
1415
- browser: browser,
1416
- treeLabels: text.tree,
2298
+ return /*#__PURE__*/ jsx(LocaleProvider, {
2299
+ locale: locale,
2300
+ children: /*#__PURE__*/ jsxs("div", {
2301
+ ...rest,
2302
+ ref: layoutRef,
2303
+ className: [
2304
+ 'ov-file-browser',
2305
+ className
2306
+ ].filter(Boolean).join(' '),
2307
+ style: {
2308
+ ...style,
2309
+ '--ov-file-browser-tree-width': `${treeWidth}px`
2310
+ },
2311
+ children: [
2312
+ /*#__PURE__*/ jsx("div", {
2313
+ className: "ov-file-browser__tree",
2314
+ children: /*#__PURE__*/ jsx(FileBrowserTreePane, {
2315
+ entries: {
2316
+ agentConnect,
2317
+ onImportResources,
2318
+ renderImportResources,
2319
+ labels: labels?.entries
2320
+ },
2321
+ searchId: searchId,
2322
+ browser: browser,
2323
+ treeLabels: text.tree,
2324
+ locale: locale,
2325
+ dashboardLabels: labels?.dashboard,
2326
+ searchPlaceholder: text.searchPlaceholder,
2327
+ refreshLabel: text.refresh,
2328
+ searchLoading: text.searchLoading,
2329
+ searchEmpty: text.searchEmpty,
2330
+ searchErrorLabel: text.searchFailed,
2331
+ retryLabel: text.retry
2332
+ })
2333
+ }),
2334
+ /*#__PURE__*/ jsx(ResizableHandle, {
2335
+ label: text.resizeTree,
2336
+ min: 200,
2337
+ max: treeMaxWidth,
2338
+ value: treeWidth,
2339
+ onResize: setPreferredTreeWidth,
2340
+ className: "ov-file-browser__resizer"
2341
+ }),
2342
+ browser.previewTabs && browser.previewTabs.length > 0 ? /*#__PURE__*/ jsx(FileBrowserDetail, {
2343
+ tabs: browser.previewTabs,
2344
+ activeKey: browser.previewKey,
1417
2345
  locale: locale,
1418
- searchPlaceholder: text.searchPlaceholder,
1419
- refreshLabel: text.refresh,
1420
- searchLoading: text.searchLoading,
1421
- searchEmpty: text.searchEmpty,
1422
- searchErrorLabel: text.searchFailed,
1423
- retryLabel: text.retry
1424
- })
1425
- }),
1426
- /*#__PURE__*/ jsx(ResizableHandle, {
1427
- label: text.resizeTree,
1428
- min: 200,
1429
- max: treeMaxWidth,
1430
- value: treeWidth,
1431
- onResize: setPreferredTreeWidth,
1432
- className: "ov-file-browser__resizer"
1433
- }),
1434
- browser.previewTabs && browser.previewTabs.length > 0 ? /*#__PURE__*/ jsx(FileBrowserDetail, {
1435
- tabs: browser.previewTabs,
1436
- activeKey: browser.previewKey,
1437
- locale: locale,
1438
- labels: previewLabels,
1439
- footer: browser.previewFooter,
1440
- viewLabels: {
1441
- preview: text.previewMode,
1442
- source: text.sourceMode,
1443
- copyPath: text.copyPath,
1444
- copyContent: text.copyContent,
1445
- download: text.download,
1446
- viewSwitch: text.viewSwitch
1447
- },
1448
- onActiveKeyChange: browser.actions.setPreviewKey
1449
- }) : browser.currentUri && browser.previewError ? /*#__PURE__*/ jsx("div", {
1450
- className: "ov-file-browser__detail",
1451
- children: /*#__PURE__*/ jsx(FileBrowserFailure, {
1452
- message: text.error,
1453
- detail: browser.previewError.message,
1454
- retryLabel: text.retry,
1455
- onRetry: ()=>void browser.actions.refresh()
1456
- })
1457
- }) : /*#__PURE__*/ jsx("div", {
1458
- className: "ov-file-browser__detail",
1459
- children: /*#__PURE__*/ jsx(FileBrowserEmpty, {
1460
- label: text.empty
2346
+ labels: previewLabels,
2347
+ footer: browser.previewFooter,
2348
+ viewLabels: {
2349
+ preview: text.previewMode,
2350
+ source: text.sourceMode,
2351
+ copyPath: text.copyPath,
2352
+ copyContent: text.copyContent,
2353
+ download: text.download,
2354
+ viewSwitch: text.viewSwitch
2355
+ },
2356
+ onActiveKeyChange: browser.actions.setPreviewKey
2357
+ }) : browser.currentUri && browser.previewError ? /*#__PURE__*/ jsx("div", {
2358
+ className: "ov-file-browser__detail",
2359
+ children: /*#__PURE__*/ jsx(FileBrowserFailure, {
2360
+ message: text.error,
2361
+ detail: browser.previewError.message,
2362
+ retryLabel: text.retry,
2363
+ onRetry: ()=>void browser.actions.refresh()
2364
+ })
2365
+ }) : /*#__PURE__*/ jsx("div", {
2366
+ className: "ov-file-browser__detail",
2367
+ children: /*#__PURE__*/ jsx(FileBrowserEmpty, {
2368
+ label: text.empty
2369
+ })
1461
2370
  })
1462
- })
1463
- ]
2371
+ ]
2372
+ })
1464
2373
  });
1465
2374
  }
1466
- export { FileBrowser, useFileBrowser };
2375
+ export { FileBrowser };