dsh-coding-sidebar 1.0.3 → 1.0.5

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 (94) hide show
  1. package/README.md +27 -42
  2. package/lib/client-editor.js +315 -4179
  3. package/lib/client-registry.js +913 -1303
  4. package/lib/client-terminal.js +189 -261
  5. package/lib/client.js +911 -1301
  6. package/lib/index.js +13 -110
  7. package/lib/types/bundle-route.d.ts +1 -1
  8. package/lib/types/client/LiveView.d.ts +1 -0
  9. package/lib/types/client/SideCardSection.d.ts +3 -3
  10. package/lib/types/client/TextEditor.d.ts +20 -10
  11. package/lib/types/client/add-plugin-modal.d.ts +0 -4
  12. package/lib/types/client/api.d.ts +16 -11
  13. package/lib/types/client/builtins/index.d.ts +10 -10
  14. package/lib/types/client/chunk-loader.d.ts +7 -8
  15. package/lib/types/client/locales.d.ts +6 -26
  16. package/lib/types/client/native-avoid.d.ts +2 -0
  17. package/lib/types/client/plugins-shared.d.ts +6 -6
  18. package/lib/types/client/service.d.ts +13 -83
  19. package/lib/types/index.d.ts +1 -1
  20. package/lib/types/prefs-shared.d.ts +1 -24
  21. package/lib/types/wire.d.ts +1 -1
  22. package/package.json +26 -29
  23. package/src/bundle-route.ts +1 -1
  24. package/src/client/BrowserView.tsx +18 -2
  25. package/src/client/EditorHost.tsx +52 -122
  26. package/src/client/LiveView.tsx +229 -0
  27. package/src/client/SandboxStatusBar.tsx +12 -9
  28. package/src/client/SideCardSection.tsx +28 -81
  29. package/src/client/TextEditor.tsx +89 -266
  30. package/src/client/add-plugin-modal.tsx +16 -24
  31. package/src/client/api.ts +4 -25
  32. package/src/client/builtins/index.ts +10 -14
  33. package/src/client/chunk-loader.ts +7 -8
  34. package/src/client/index.tsx +12 -3
  35. package/src/client/locales-ar.ts +0 -6
  36. package/src/client/locales-de.ts +0 -6
  37. package/src/client/locales-fr.ts +0 -6
  38. package/src/client/locales-hi.ts +0 -6
  39. package/src/client/locales-id.ts +0 -6
  40. package/src/client/locales-it.ts +0 -6
  41. package/src/client/locales-ja.ts +0 -6
  42. package/src/client/locales-ko.ts +0 -6
  43. package/src/client/locales-nl.ts +0 -6
  44. package/src/client/locales-pl.ts +0 -6
  45. package/src/client/locales-pt.ts +0 -6
  46. package/src/client/locales-ru.ts +0 -6
  47. package/src/client/locales-sv.ts +0 -6
  48. package/src/client/locales-th.ts +0 -6
  49. package/src/client/locales-tr.ts +0 -6
  50. package/src/client/locales-vi.ts +0 -6
  51. package/src/client/locales-zh-HK.ts +0 -6
  52. package/src/client/locales-zh-MO.ts +0 -6
  53. package/src/client/locales-zh-TW.ts +0 -6
  54. package/src/client/locales.ts +12 -52
  55. package/src/client/native-avoid.ts +155 -0
  56. package/src/client/plugins-shared.ts +6 -6
  57. package/src/client/prefs.ts +0 -7
  58. package/src/client/service.ts +13 -150
  59. package/src/client/sidebar.module.css +28 -420
  60. package/src/config.ts +1 -4
  61. package/src/index.ts +17 -74
  62. package/src/prefs-shared.ts +1 -27
  63. package/src/wire.ts +1 -0
  64. package/lib/client-mermaid.js +0 -200776
  65. package/lib/types/client/MarkdownHtml.d.ts +0 -32
  66. package/lib/types/client/PdfView.d.ts +0 -6
  67. package/lib/types/client/builtins/viewers.d.ts +0 -3
  68. package/lib/types/client/chunks/mermaid.d.ts +0 -10
  69. package/lib/types/client/editor-load.d.ts +0 -66
  70. package/lib/types/client/image-types.d.ts +0 -3
  71. package/lib/types/client/markdown-html.d.ts +0 -96
  72. package/lib/types/client/markdown-images.d.ts +0 -45
  73. package/lib/types/client/md-toc.d.ts +0 -4
  74. package/lib/types/client/mermaid-blocks.d.ts +0 -47
  75. package/lib/types/client/mermaid-sanitize.d.ts +0 -2
  76. package/lib/types/client/mermaid.d.ts +0 -12
  77. package/lib/types/client/pdf-types.d.ts +0 -2
  78. package/lib/types/client/plugins-viewers.d.ts +0 -3
  79. package/lib/types/html-route.d.ts +0 -59
  80. package/src/client/MarkdownHtml.tsx +0 -296
  81. package/src/client/PdfView.tsx +0 -110
  82. package/src/client/builtins/viewers.tsx +0 -125
  83. package/src/client/chunks/mermaid.tsx +0 -10
  84. package/src/client/editor-load.ts +0 -92
  85. package/src/client/image-types.ts +0 -8
  86. package/src/client/markdown-html.ts +0 -331
  87. package/src/client/markdown-images.ts +0 -137
  88. package/src/client/md-toc.tsx +0 -127
  89. package/src/client/mermaid-blocks.ts +0 -110
  90. package/src/client/mermaid-sanitize.ts +0 -93
  91. package/src/client/mermaid.tsx +0 -406
  92. package/src/client/pdf-types.ts +0 -4
  93. package/src/client/plugins-viewers.ts +0 -30
  94. package/src/html-route.ts +0 -106
@@ -58,15 +58,12 @@ window.__ModuleLoader__.load({
58
58
  customCss: "",
59
59
  titleBarCompat: false,
60
60
  titleBarStripPx: 40,
61
- htmlViewerNoSandbox: false,
62
- htmlViewerDefaultUnsafe: false,
63
61
  browserNoSandbox: false,
64
62
  browserInterceptLinks: true,
65
63
  browserInterceptHttp: true,
66
64
  browserInterceptHttps: false,
67
65
  browserAllowedLoopback: "",
68
66
  tabsEnabled: {},
69
- viewersEnabled: {},
70
67
  pluginSettings: {}
71
68
  };
72
69
  /** Clamp one width percent into the contract range (shared by schema and client reads). */
@@ -1302,14 +1299,139 @@ window.__ModuleLoader__.load({
1302
1299
  return new SidebarStore();
1303
1300
  }
1304
1301
  //#endregion
1305
- //#region src/client/service.ts
1306
- /** Extract the lowercase extension without leading dot from a path. */
1307
- function extOfPath(path) {
1308
- const at = path.lastIndexOf(".");
1309
- if (at === -1) return "";
1310
- const base = path.slice(at + 1).toLowerCase();
1311
- return base.includes("/") || base.includes("\\") ? "" : base;
1302
+ //#region src/client/native-avoid.ts
1303
+ /**
1304
+ * Native-sidebar avoidance: when the DSH shell's own sidebar expands to its
1305
+ * wide form, an expanded sidebar panel would crowd the page into several
1306
+ * columns — so the panel yields (collapses; the fact that WE collapsed it
1307
+ * is remembered) and restores when the native sidebar returns to its rail.
1308
+ *
1309
+ * Detection: the host exposes no programmable open/close event — the
1310
+ * `settings.trigger` slot's `{ wide }` owner prop is pushed only to the
1311
+ * slot's occupant, and that slot is single-masked (occupying it would take
1312
+ * over the settings button). But the shell stamps every slot outlet with
1313
+ * `data-slot="<key>"` (the conversation package's own CSS targets
1314
+ * `[data-slot=conversation\.session]`), and the native sidebar hosts the
1315
+ * `sidebar.*` slots — its documented collapsed form is a 56px icon rail,
1316
+ * the expanded form a full column. So: watch the first
1317
+ * `[data-slot^="sidebar."]` element with a ResizeObserver; width > 80px
1318
+ * means expanded. No anchor (older host, attribute renamed) → the feature
1319
+ * stays inert.
1320
+ *
1321
+ * The yield rides the regular `panelOpen` state (same contract as every
1322
+ * other collapse: the toggle button, content-open auto-expansion and the
1323
+ * per-session persistence all keep working). A panel transition we did not
1324
+ * apply — the user reopening the panel, or a content open expanding it —
1325
+ * hands ownership back (no restore on native close); a session switch
1326
+ * re-runs the rule against the newly active session.
1327
+ */
1328
+ /** The documented rail is 56px; anything wider is an expanded sidebar. */
1329
+ const RAIL_MAX_WIDTH = 80;
1330
+ /** The native sidebar's slot outlets (sidebar.settings and siblings). */
1331
+ const ANCHOR_SELECTOR = "[data-slot^=\"sidebar.\"]";
1332
+ function installNativeSidebarAvoidance(store) {
1333
+ if (typeof ResizeObserver === "undefined" || typeof MutationObserver === "undefined" || typeof document === "undefined" || document.body === null) return () => {};
1334
+ let disposed = false;
1335
+ /** null until the anchor is found and measured (unknown = never act). */
1336
+ let nativeWide = null;
1337
+ /** The currently open panel was collapsed by US (restore on native close). */
1338
+ let yielded = false;
1339
+ /** Guards the store subscription: the in-flight reduce is ours. */
1340
+ let applying = false;
1341
+ let lastSeenOpen = null;
1342
+ let lastSessionId;
1343
+ const snapshotOpen = () => store.getSnapshot().state?.panelOpen === true;
1344
+ /** Apply the avoidance rule for the current native-sidebar state. */
1345
+ const reevaluate = () => {
1346
+ if (disposed || nativeWide === null) return;
1347
+ if (nativeWide && !yielded && snapshotOpen()) {
1348
+ yielded = true;
1349
+ applying = true;
1350
+ store.reduce(togglePanel);
1351
+ } else if (!nativeWide && yielded) {
1352
+ yielded = false;
1353
+ if (snapshotOpen()) return;
1354
+ applying = true;
1355
+ store.reduce(togglePanel);
1356
+ }
1357
+ };
1358
+ lastSeenOpen = snapshotOpen();
1359
+ lastSessionId = store.getSnapshot().sessionId;
1360
+ const unsubscribe = store.subscribe(() => {
1361
+ if (disposed) return;
1362
+ const snapshot = store.getSnapshot();
1363
+ const open = snapshotOpen();
1364
+ if (applying) {
1365
+ applying = false;
1366
+ lastSeenOpen = open;
1367
+ lastSessionId = snapshot.sessionId;
1368
+ return;
1369
+ }
1370
+ if (snapshot.sessionId !== lastSessionId) {
1371
+ lastSessionId = snapshot.sessionId;
1372
+ lastSeenOpen = open;
1373
+ reevaluate();
1374
+ return;
1375
+ }
1376
+ if (open !== lastSeenOpen) {
1377
+ lastSeenOpen = open;
1378
+ if (yielded && open) yielded = false;
1379
+ }
1380
+ });
1381
+ let resizeObserver = null;
1382
+ let finder = null;
1383
+ const applyWidth = (width) => {
1384
+ const wide = width > RAIL_MAX_WIDTH;
1385
+ if (wide !== nativeWide) {
1386
+ nativeWide = wide;
1387
+ reevaluate();
1388
+ }
1389
+ };
1390
+ const watch = (element) => {
1391
+ resizeObserver = new ResizeObserver(() => {
1392
+ if (!element.isConnected) {
1393
+ resizeObserver?.disconnect();
1394
+ resizeObserver = null;
1395
+ nativeWide = null;
1396
+ startSearch();
1397
+ return;
1398
+ }
1399
+ applyWidth(element.getBoundingClientRect().width);
1400
+ });
1401
+ resizeObserver.observe(element);
1402
+ applyWidth(element.getBoundingClientRect().width);
1403
+ };
1404
+ const startSearch = () => {
1405
+ const found = document.querySelector(ANCHOR_SELECTOR);
1406
+ if (found !== null) {
1407
+ watch(found);
1408
+ return;
1409
+ }
1410
+ finder = new MutationObserver(() => {
1411
+ const element = document.querySelector(ANCHOR_SELECTOR);
1412
+ if (element !== null) {
1413
+ finder?.disconnect();
1414
+ finder = null;
1415
+ watch(element);
1416
+ }
1417
+ });
1418
+ finder.observe(document.body, {
1419
+ childList: true,
1420
+ subtree: true
1421
+ });
1422
+ };
1423
+ startSearch();
1424
+ return () => {
1425
+ disposed = true;
1426
+ unsubscribe();
1427
+ resizeObserver?.disconnect();
1428
+ resizeObserver = null;
1429
+ finder?.disconnect();
1430
+ finder = null;
1431
+ };
1312
1432
  }
1433
+ //#endregion
1434
+ //#region src/client/service.ts
1313
1435
  /** The file name of a path (both separators). */
1314
1436
  function baseNameOf(path) {
1315
1437
  const at = Math.max(path.lastIndexOf("/"), path.lastIndexOf("\\"));
@@ -1340,7 +1462,7 @@ window.__ModuleLoader__.load({
1340
1462
  if (claimed) return tab;
1341
1463
  }
1342
1464
  }
1343
- const SIDEBAR_SERVICE_VERSION = "1.0.3";
1465
+ const SIDEBAR_SERVICE_VERSION = "1.0.5";
1344
1466
  /**
1345
1467
  * Monotonic capability list consumers use to gate new API usage (features
1346
1468
  * are never removed). Each string names a v0.12.0+ capability:
@@ -1381,12 +1503,11 @@ window.__ModuleLoader__.load({
1381
1503
  }
1382
1504
  /**
1383
1505
  * Create one BetterSidebar service bound to a store. The service owns the
1384
- * tab/viewer registries (Map + listener set) and proxies openTab/closeTab
1506
+ * tab registry (Map + listener set) and proxies openTab/closeTab
1385
1507
  * to the store's reducer. One instance per client plugin activation.
1386
1508
  */
1387
1509
  function createBetterSidebarService(store) {
1388
1510
  const tabs = /* @__PURE__ */ new Map();
1389
- const viewers = /* @__PURE__ */ new Map();
1390
1511
  const listeners = /* @__PURE__ */ new Set();
1391
1512
  const notify = () => {
1392
1513
  for (const fn of [...listeners]) fn();
@@ -1408,36 +1529,9 @@ window.__ModuleLoader__.load({
1408
1529
  }
1409
1530
  };
1410
1531
  };
1411
- const registerFileViewer = (descriptor) => {
1412
- if (viewers.has(descriptor.id)) throw new Error(`[dsh-coding-sidebar] file viewer "${descriptor.id}" already registered`);
1413
- viewers.set(descriptor.id, descriptor);
1414
- notify();
1415
- return () => {
1416
- if (viewers.get(descriptor.id) === descriptor) {
1417
- viewers.delete(descriptor.id);
1418
- notify();
1419
- }
1420
- };
1421
- };
1422
1532
  const getTabs = () => Array.from(tabs.values());
1423
- const getFileViewers = () => Array.from(viewers.values());
1424
1533
  const getTab = (id) => tabs.get(id);
1425
1534
  const isTabEnabled = (id) => store.getPrefs().tabsEnabled[id] !== false;
1426
- const isViewerEnabled = (id) => store.getPrefs().viewersEnabled[id] !== false;
1427
- const matchFileViewer = (path, head) => {
1428
- const ext = extOfPath(path);
1429
- for (const v of Array.from(viewers.values()).sort((a, b) => (b.priority ?? 0) - (a.priority ?? 0))) {
1430
- if (!isViewerEnabled(v.id)) continue;
1431
- if (head !== void 0 && v.detect !== void 0) {
1432
- if (v.detect(path, head)) return v;
1433
- if (v.exts.length === 0) continue;
1434
- } else if (v.exts.length === 0) {
1435
- if (v.detect === void 0) return v;
1436
- continue;
1437
- }
1438
- if (v.exts.includes(ext)) return v;
1439
- }
1440
- };
1441
1535
  const openTab = (seed, scope) => {
1442
1536
  if (!isTabEnabled(seed.type)) {
1443
1537
  console.warn(`[dsh-coding-sidebar] tab type "${seed.type}" is disabled in the side card settings`);
@@ -1571,13 +1665,9 @@ window.__ModuleLoader__.load({
1571
1665
  };
1572
1666
  return {
1573
1667
  registerTab,
1574
- registerFileViewer,
1575
1668
  getTabs,
1576
- getFileViewers,
1577
1669
  getTab,
1578
1670
  isTabEnabled,
1579
- isViewerEnabled,
1580
- matchFileViewer,
1581
1671
  openTab,
1582
1672
  closeTab: closeTab$1,
1583
1673
  subscribe,
@@ -1917,13 +2007,7 @@ window.__ModuleLoader__.load({
1917
2007
  terminalDepsHint: "DSH 環境のターミナルまたは cmd で以下のコマンドを実行して修復し、再試行してください(node-pty は DSH コアと同じバージョンを維持):",
1918
2008
  terminalDepsProfile: "(検出された profile:{profile})",
1919
2009
  preview: "プレビュー",
1920
- toc: "目次",
1921
2010
  edit: "編集",
1922
- mermaidError: "Mermaid レンダリング失敗",
1923
- mermaidZoomIn: "拡大",
1924
- mermaidZoomOut: "縮小",
1925
- mermaidZoomReset: "リセット",
1926
- mermaidZoomHint: "スクロールで拡大 ・ ドラッグで移動 ・ Esc で閉じる",
1927
2011
  refresh: "更新",
1928
2012
  showInFolder: "フォルダーで表示",
1929
2013
  refreshUnsavedConfirm: "ディスク上のファイルが変更されました。更新すると未保存の編集が失われます。続行しますか?",
@@ -2276,13 +2360,7 @@ window.__ModuleLoader__.load({
2276
2360
  terminalDepsHint: "Führen Sie den folgenden Befehl in einem Terminal oder in cmd auf dem DSH-System aus, um dies zu beheben, und klicken Sie dann auf „Erneut versuchen“ (node-pty bleibt mit der DSH-Core-Version synchron):",
2277
2361
  terminalDepsProfile: " (erkanntes Profil: {profile})",
2278
2362
  preview: "Vorschau",
2279
- toc: "Inhaltsverzeichnis",
2280
2363
  edit: "Bearbeiten",
2281
- mermaidError: "Mermaid-Rendering fehlgeschlagen",
2282
- mermaidZoomIn: "Vergrößern",
2283
- mermaidZoomOut: "Verkleinern",
2284
- mermaidZoomReset: "Zurücksetzen",
2285
- mermaidZoomHint: "Scrollen zum Zoomen · Ziehen zum Verschieben · Esc zum Schließen",
2286
2364
  refresh: "Aktualisieren",
2287
2365
  showInFolder: "Im Ordner anzeigen",
2288
2366
  refreshUnsavedConfirm: "Die Datei wurde geändert. Beim Aktualisieren gehen ungespeicherte Änderungen verloren. Fortfahren?",
@@ -2641,13 +2719,7 @@ window.__ModuleLoader__.load({
2641
2719
  terminalDepsHint: "Exécutez la commande suivante dans un terminal ou cmd de l’environnement DSH pour réparer, puis cliquez sur Réessayer (node-pty reste à la même version que le cœur DSH) :",
2642
2720
  terminalDepsProfile: " (profil détecté : {profile})",
2643
2721
  preview: "Aperçu",
2644
- toc: "Sommaire",
2645
2722
  edit: "Modifier",
2646
- mermaidError: "Échec du rendu Mermaid",
2647
- mermaidZoomIn: "Agrandir",
2648
- mermaidZoomOut: "Réduire",
2649
- mermaidZoomReset: "Réinitialiser",
2650
- mermaidZoomHint: "Molette pour zoomer · glisser pour déplacer · Échap pour fermer",
2651
2723
  refresh: "Actualiser",
2652
2724
  showInFolder: "Afficher dans le dossier",
2653
2725
  refreshUnsavedConfirm: "Le fichier a changé sur le disque. Actualiser supprimera les modifications non enregistrées. Continuer ?",
@@ -2997,13 +3069,7 @@ window.__ModuleLoader__.load({
2997
3069
  terminalDepsHint: "Execute o comando abaixo em um terminal ou cmd na máquina do DSH para reparar e tente novamente (node-pty permanece em sincronia com a versão do núcleo do DSH):",
2998
3070
  terminalDepsProfile: " (perfil detectado: {profile})",
2999
3071
  preview: "Pré-visualizar",
3000
- toc: "Sumário",
3001
3072
  edit: "Editar",
3002
- mermaidError: "Falha ao renderizar o Mermaid",
3003
- mermaidZoomIn: "Ampliar",
3004
- mermaidZoomOut: "Reduzir",
3005
- mermaidZoomReset: "Redefinir",
3006
- mermaidZoomHint: "Rolar para ampliar · arrastar para mover · Esc para fechar",
3007
3073
  refresh: "Atualizar",
3008
3074
  showInFolder: "Mostrar na pasta",
3009
3075
  refreshUnsavedConfirm: "O arquivo mudou no disco. Atualizar descartará edições não salvas. Continuar?",
@@ -3361,13 +3427,7 @@ window.__ModuleLoader__.load({
3361
3427
  terminalDepsHint: "DSH가 설치된 환경의 터미널 또는 cmd에서 아래 명령을 실행하여 복구한 후 다시 시도를 클릭하세요(node-pty는 DSH 코어와 동일한 버전을 유지합니다):",
3362
3428
  terminalDepsProfile: " (profile 감지됨: {profile})",
3363
3429
  preview: "미리보기",
3364
- toc: "목차",
3365
3430
  edit: "편집",
3366
- mermaidError: "Mermaid 렌더링 실패",
3367
- mermaidZoomIn: "확대",
3368
- mermaidZoomOut: "축소",
3369
- mermaidZoomReset: "초기화",
3370
- mermaidZoomHint: "휠로 확대/축소 · 드래그로 이동 · Esc로 닫기",
3371
3431
  refresh: "새로고침",
3372
3432
  showInFolder: "폴더에서 표시",
3373
3433
  refreshUnsavedConfirm: "디스크의 파일이 변경되었습니다. 새로고침하면 저장되지 않은 편집 내용이 손실됩니다. 계속하시겠습니까?",
@@ -3734,13 +3794,7 @@ window.__ModuleLoader__.load({
3734
3794
  terminalDepsHint: "شغّل الأمر التالي في طرفية أو cmd على جهاز DSH للإصلاح، ثم أعد المحاولة (يبقى node-pty متزامناً مع إصدار نواة DSH):",
3735
3795
  terminalDepsProfile: " (الملف الشخصي المكتشف: {profile})",
3736
3796
  preview: "معاينة",
3737
- toc: "الفهرس",
3738
3797
  edit: "تحرير",
3739
- mermaidError: "فشل رسم Mermaid",
3740
- mermaidZoomIn: "تكبير",
3741
- mermaidZoomOut: "تصغير",
3742
- mermaidZoomReset: "إعادة تعيين",
3743
- mermaidZoomHint: "العجلة للتقريب · السحب للتحريك · Esc للإغلاق",
3744
3798
  refresh: "تحديث",
3745
3799
  showInFolder: "إظهار في المجلد",
3746
3800
  refreshUnsavedConfirm: "تغيّر الملف على القرص. سيؤدي التحديث إلى فقدان التعديلات غير المحفوظة. متابعة؟",
@@ -4106,13 +4160,7 @@ window.__ModuleLoader__.load({
4106
4160
  terminalDepsHint: "DSH मशीन पर एक टर्मिनल या cmd में नीचे दिया गया कमांड चलाएँ, फिर पुनः प्रयास करें (node-pty DSH कोर संस्करण के साथ सिंक रहता है):",
4107
4161
  terminalDepsProfile: " (पहचाना गया प्रोफ़ाइल: {profile})",
4108
4162
  preview: "पूर्वावलोकन",
4109
- toc: "विषय-सूची",
4110
4163
  edit: "संपादित करें",
4111
- mermaidError: "Mermaid रेंडर विफल",
4112
- mermaidZoomIn: "ज़ूम इन",
4113
- mermaidZoomOut: "ज़ूम आउट",
4114
- mermaidZoomReset: "रीसेट",
4115
- mermaidZoomHint: "स्क्रॉल से ज़ूम · खींचें पैन करने · Esc से बंद",
4116
4164
  refresh: "ताज़ा करें",
4117
4165
  showInFolder: "फ़ोल्डर में दिखाएँ",
4118
4166
  refreshUnsavedConfirm: "डिस्क पर फ़ाइल बदल गई है। रीफ़्रेश करने पर असहेज किए गए संपादन खो जाएँगे। जारी रखें?",
@@ -4476,13 +4524,7 @@ window.__ModuleLoader__.load({
4476
4524
  terminalDepsHint: "Jalankan perintah di bawah ini di terminal atau cmd pada mesin DSH untuk memperbaikinya, lalu coba lagi (node-pty tetap sinkron dengan versi inti DSH):",
4477
4525
  terminalDepsProfile: " (profil terdeteksi: {profile})",
4478
4526
  preview: "Pratinjau",
4479
- toc: "Daftar Isi",
4480
4527
  edit: "Edit",
4481
- mermaidError: "Render Mermaid gagal",
4482
- mermaidZoomIn: "Perbesar",
4483
- mermaidZoomOut: "Perkecil",
4484
- mermaidZoomReset: "Reset",
4485
- mermaidZoomHint: "Gulir untuk zoom · seret untuk geser · Esc untuk tutup",
4486
4528
  refresh: "Segarkan",
4487
4529
  showInFolder: "Tampilkan di folder",
4488
4530
  refreshUnsavedConfirm: "File berubah di disk. Menyegarkan akan membuang edit yang belum disimpan. Lanjutkan?",
@@ -4848,13 +4890,7 @@ window.__ModuleLoader__.load({
4848
4890
  terminalDepsHint: "Onarmak için DSH makinesindeki bir terminalde veya cmd’de aşağıdaki komutu çalıştırın, sonra yeniden deneyin (node-pty, DSH çekirdek sürümüyle senkron kalır):",
4849
4891
  terminalDepsProfile: " (algılanan profil: {profile})",
4850
4892
  preview: "Önizleme",
4851
- toc: "İçindekiler",
4852
4893
  edit: "Düzenle",
4853
- mermaidError: "Mermaid oluşturma başarısız",
4854
- mermaidZoomIn: "Yakınlaştır",
4855
- mermaidZoomOut: "Uzaklaştır",
4856
- mermaidZoomReset: "Sıfırla",
4857
- mermaidZoomHint: "Yakınlaştırmak için kaydır · taşımak için sürükle · kapatmak için Esc",
4858
4894
  refresh: "Yenile",
4859
4895
  showInFolder: "Klasörde göster",
4860
4896
  refreshUnsavedConfirm: "Dosya diskte değişti. Yenileme kaydedilmemiş düzenlemeleri atar. Devam edilsin mi?",
@@ -5220,13 +5256,7 @@ window.__ModuleLoader__.load({
5220
5256
  terminalDepsHint: "Chạy lệnh sau trong terminal hoặc cmd trên máy DSH để sửa, rồi nhấn thử lại (node-pty đồng bộ phiên bản với lõi DSH):",
5221
5257
  terminalDepsProfile: " (phát hiện profile: {profile})",
5222
5258
  preview: "Xem trước",
5223
- toc: "Mục lục",
5224
5259
  edit: "Chỉnh sửa",
5225
- mermaidError: "Render Mermaid thất bại",
5226
- mermaidZoomIn: "Phóng to",
5227
- mermaidZoomOut: "Thu nhỏ",
5228
- mermaidZoomReset: "Đặt lại",
5229
- mermaidZoomHint: "Cuộn để zoom · kéo để di chuyển · Esc để đóng",
5230
5260
  refresh: "Làm mới",
5231
5261
  showInFolder: "Hiển thị trong thư mục",
5232
5262
  refreshUnsavedConfirm: "Tệp đã thay đổi trên đĩa. Làm mới sẽ loại bỏ các chỉnh sửa chưa lưu. Tiếp tục?",
@@ -5592,13 +5622,7 @@ window.__ModuleLoader__.load({
5592
5622
  terminalDepsHint: "เรียกใช้คำสั่งด้านล่างในเทอร์มินัลหรือ cmd บนเครื่อง DSH เพื่อซ่อมแซม แล้วกดลองอีกครั้ง (node-pty ต้องซิงค์กับเวอร์ชันหลักของ DSH):",
5593
5623
  terminalDepsProfile: " (ตรวจพบ profile: {profile})",
5594
5624
  preview: "พรีวิว",
5595
- toc: "สารบัญ",
5596
5625
  edit: "แก้ไข",
5597
- mermaidError: "เรนเดอร์ Mermaid ล้มเหลว",
5598
- mermaidZoomIn: "ซูมเข้า",
5599
- mermaidZoomOut: "ซูมออก",
5600
- mermaidZoomReset: "รีเซ็ต",
5601
- mermaidZoomHint: "เลื่อนเพื่อซูม · ลากเพื่อแพน · Esc เพื่อปิด",
5602
5626
  refresh: "รีเฟรช",
5603
5627
  showInFolder: "แสดงในโฟลเดอร์",
5604
5628
  refreshUnsavedConfirm: "ไฟล์เปลี่ยนบนดิสก์ การรีเฟรชจะทิ้งการแก้ไขที่ยังไม่ได้บันทึก ดำเนินการต่อหรือไม่",
@@ -5960,13 +5984,7 @@ window.__ModuleLoader__.load({
5960
5984
  terminalDepsHint: "Выполните приведённую ниже команду в терминале или cmd на машине DSH, затем нажмите «Повторить» (node-pty остаётся синхронизированным с версией ядра DSH):",
5961
5985
  terminalDepsProfile: " (обнаружен profile: {profile})",
5962
5986
  preview: "Предпросмотр",
5963
- toc: "Оглавление",
5964
5987
  edit: "Изменить",
5965
- mermaidError: "Сбой рендеринга Mermaid",
5966
- mermaidZoomIn: "Приблизить",
5967
- mermaidZoomOut: "Отдалить",
5968
- mermaidZoomReset: "Сбросить",
5969
- mermaidZoomHint: "Колесо — масштаб · перетаскивание — панорама · Esc — закрыть",
5970
5988
  refresh: "Обновить",
5971
5989
  showInFolder: "Показать в папке",
5972
5990
  refreshUnsavedConfirm: "Файл изменился на диске. Обновление отбросит несохранённые изменения. Продолжить?",
@@ -6323,13 +6341,7 @@ window.__ModuleLoader__.load({
6323
6341
  terminalDepsHint: "Esegua il comando seguente in un terminale o cmd sul computer DSH per ripristinarlo, poi riprovi (node-pty resta sincronizzato con la versione del core DSH):",
6324
6342
  terminalDepsProfile: " (rilevato profilo: {profile})",
6325
6343
  preview: "Anteprima",
6326
- toc: "Indice",
6327
6344
  edit: "Modifica",
6328
- mermaidError: "Rendering Mermaid non riuscito",
6329
- mermaidZoomIn: "Ingrandisci",
6330
- mermaidZoomOut: "Riduci",
6331
- mermaidZoomReset: "Ripristina",
6332
- mermaidZoomHint: "Scorra per zoom · trascini per panoramica · Esc per chiudere",
6333
6345
  refresh: "Aggiorna",
6334
6346
  showInFolder: "Mostra nella cartella",
6335
6347
  refreshUnsavedConfirm: "Il file è cambiato su disco. Aggiornare scarterà le modifiche non salvate. Continuare?",
@@ -6694,13 +6706,7 @@ window.__ModuleLoader__.load({
6694
6706
  terminalDepsHint: "Voer het onderstaande commando uit in een terminal of cmd op de DSH-machine om het te herstellen en probeer het opnieuw (node-pty blijft in sync met de DSH-coreversie):",
6695
6707
  terminalDepsProfile: " (gedetecteerde profile: {profile})",
6696
6708
  preview: "Voorbeeld",
6697
- toc: "Inhoudsopgave",
6698
6709
  edit: "Bewerken",
6699
- mermaidError: "Mermaid-renderen mislukt",
6700
- mermaidZoomIn: "Inzoomen",
6701
- mermaidZoomOut: "Uitzoomen",
6702
- mermaidZoomReset: "Resetten",
6703
- mermaidZoomHint: "Scrollen om te zoomen · slepen om te pannen · Esc om te sluiten",
6704
6710
  refresh: "Vernieuwen",
6705
6711
  showInFolder: "In map tonen",
6706
6712
  refreshUnsavedConfirm: "Het bestand is op schijf gewijzigd. Vernieuwen gooit niet-opgeslagen wijzigingen weg. Doorgaan?",
@@ -7050,13 +7056,7 @@ window.__ModuleLoader__.load({
7050
7056
  terminalDepsHint: "Kör kommandot nedan i en terminal eller cmd på DSH-maskinen för att reparera det, försök sedan igen (node-pty hålls synkad med DSH-kärnversionen):",
7051
7057
  terminalDepsProfile: " (upptäckt profil: {profile})",
7052
7058
  preview: "Förhandsgranska",
7053
- toc: "Innehållsförteckning",
7054
7059
  edit: "Redigera",
7055
- mermaidError: "Mermaid-rendering misslyckades",
7056
- mermaidZoomIn: "Zooma in",
7057
- mermaidZoomOut: "Zooma ut",
7058
- mermaidZoomReset: "Återställ",
7059
- mermaidZoomHint: "Rulla för att zooma · dra för att panorera · Esc för att stänga",
7060
7060
  refresh: "Uppdatera",
7061
7061
  showInFolder: "Visa i mapp",
7062
7062
  refreshUnsavedConfirm: "Filen ändrades på disken. Uppdatering kastar osparade ändringar. Fortsätta?",
@@ -7424,13 +7424,7 @@ window.__ModuleLoader__.load({
7424
7424
  terminalDepsHint: "Uruchom poniższe polecenie w terminalu lub cmd na maszynie DSH, aby to naprawić, a następnie ponów (node-pty pozostaje w synchronizacji z wersją rdzenia DSH):",
7425
7425
  terminalDepsProfile: " (wykryty profil: {profile})",
7426
7426
  preview: "Podgląd",
7427
- toc: "Spis treści",
7428
7427
  edit: "Edytuj",
7429
- mermaidError: "Renderowanie Mermaid nie powiodło się",
7430
- mermaidZoomIn: "Powiększ",
7431
- mermaidZoomOut: "Pomniejsz",
7432
- mermaidZoomReset: "Resetuj",
7433
- mermaidZoomHint: "Kółko: powiększenie · przeciąganie: panowanie · Esc: zamknięcie",
7434
7428
  refresh: "Odśwież",
7435
7429
  showInFolder: "Pokaż w folderze",
7436
7430
  refreshUnsavedConfirm: "Plik zmienił się na dysku. Odświeżenie odrzuci niezapisane zmiany. Kontynuować?",
@@ -7811,13 +7805,7 @@ window.__ModuleLoader__.load({
7811
7805
  terminalDepsHint: "在 DSH 所在環境的終端或 cmd 中執行以下命令修復,然後點重試(node-pty 與 DSH 核心保持同一版本):",
7812
7806
  terminalDepsProfile: "(偵測到 profile:{profile})",
7813
7807
  preview: "預覽",
7814
- toc: "目錄",
7815
7808
  edit: "編輯",
7816
- mermaidError: "Mermaid 渲染失敗",
7817
- mermaidZoomIn: "放大",
7818
- mermaidZoomOut: "縮小",
7819
- mermaidZoomReset: "重設",
7820
- mermaidZoomHint: "滾輪縮放 · 拖曳平移 · Esc 關閉",
7821
7809
  refresh: "重新整理",
7822
7810
  showInFolder: "在文件夾中顯示",
7823
7811
  refreshUnsavedConfirm: "檔案已在磁碟上變更。重新整理會丟失尚未儲存的編輯。繼續?",
@@ -8198,13 +8186,7 @@ window.__ModuleLoader__.load({
8198
8186
  terminalDepsHint: "在 DSH 所在環境的終端或 cmd 中執行以下命令修復,然後點重試(node-pty 與 DSH 核心保持同一版本):",
8199
8187
  terminalDepsProfile: "(偵測到 profile:{profile})",
8200
8188
  preview: "預覽",
8201
- toc: "目錄",
8202
8189
  edit: "編輯",
8203
- mermaidError: "Mermaid 渲染失敗",
8204
- mermaidZoomIn: "放大",
8205
- mermaidZoomOut: "縮小",
8206
- mermaidZoomReset: "重設",
8207
- mermaidZoomHint: "滾輪縮放 · 拖曳平移 · Esc 關閉",
8208
8190
  refresh: "重新整理",
8209
8191
  showInFolder: "在資料夾中顯示",
8210
8192
  refreshUnsavedConfirm: "檔案已在磁碟上變更。重新整理會丟失尚未儲存的編輯。繼續?",
@@ -8585,13 +8567,7 @@ window.__ModuleLoader__.load({
8585
8567
  terminalDepsHint: "在 DSH 所在環境的終端或 cmd 中執行以下命令修復,然後點重試(node-pty 與 DSH 核心保持同一版本):",
8586
8568
  terminalDepsProfile: "(偵測到 profile:{profile})",
8587
8569
  preview: "預覽",
8588
- toc: "目錄",
8589
8570
  edit: "編輯",
8590
- mermaidError: "Mermaid 渲染失敗",
8591
- mermaidZoomIn: "放大",
8592
- mermaidZoomOut: "縮小",
8593
- mermaidZoomReset: "重設",
8594
- mermaidZoomHint: "滾輪縮放 · 拖曳平移 · Esc 關閉",
8595
8571
  refresh: "重新整理",
8596
8572
  showInFolder: "在文件夾中顯示",
8597
8573
  refreshUnsavedConfirm: "檔案已在磁碟上變更。重新整理會丟失尚未儲存的編輯。繼續?",
@@ -8963,14 +8939,6 @@ window.__ModuleLoader__.load({
8963
8939
  terminalDepsFailed: "终端依赖 node-pty 加载失败",
8964
8940
  terminalDepsHint: "在 DSH 所在环境的终端或 cmd 中执行以下命令修复,然后点重试(node-pty 与 DSH 核心保持同一版本):",
8965
8941
  terminalDepsProfile: "(检测到 profile:{profile})",
8966
- preview: "预览",
8967
- toc: "目录",
8968
- edit: "编辑",
8969
- mermaidError: "Mermaid 渲染失败",
8970
- mermaidZoomIn: "放大",
8971
- mermaidZoomOut: "缩小",
8972
- mermaidZoomReset: "重置",
8973
- mermaidZoomHint: "滚轮缩放 · 拖拽平移 · Esc 关闭",
8974
8942
  refresh: "刷新",
8975
8943
  refreshUnsavedConfirm: "文件已在磁盘更新,刷新将丢弃未保存编辑。继续吗?",
8976
8944
  save: "保存",
@@ -9113,34 +9081,27 @@ window.__ModuleLoader__.load({
9113
9081
  settingsShellArgsDesc: "显式 shell 启动参数,空格分隔;非空时完全替换默认参数(与 yaml 的 shellArgs 契约一致)",
9114
9082
  settingsShellArgsPlaceholder: "如 -l(留空用默认参数)",
9115
9083
  settingsTabsTitle: "侧边栏内容",
9116
- settingsViewersTitle: "文件预览",
9117
9084
  settingsGeneralTitle: "常规",
9118
9085
  settingsPopup: "功能设置",
9119
- settingsViewerCatchAll: "兜底:任意文件",
9120
- viewerImage: "图片",
9121
- viewerPdf: "PDF",
9122
- viewerMarkdown: "Markdown",
9123
- viewerCode: "代码",
9124
- viewerBinary: "二进制下载",
9125
- viewerHtml: "HTML",
9126
9086
  browser: "浏览器",
9127
9087
  browserPlaceholder: "输入网址,例如 example.com",
9128
9088
  browserGo: "前往",
9129
9089
  browserBack: "后退",
9130
9090
  browserForward: "前进",
9131
9091
  browserStart: "输入网址开始浏览(沙箱模式)",
9092
+ browserLive: "Agent 实况",
9093
+ browserLiveFree: "自由浏览",
9094
+ browserLiveConnecting: "连接 agent 浏览器宿主…",
9095
+ browserLiveDown: "宿主不可达:确认 KCoder 已启动(端口 9223)",
9096
+ browserLiveTargetNone: "暂无打开的页面——agent 发起浏览后此处实时显示",
9097
+ browserLiveFollowLatest: "跟随最新页面",
9132
9098
  browserBlockedScheme: "已阻止:仅支持 http/https 链接",
9133
9099
  browserBlockedLoopback: "已阻止:不允许在浏览器中访问本机或内部地址",
9134
9100
  browserInvalid: "无效的网址",
9135
9101
  browserNoSandboxWarning: "沙箱已关闭:当前页面与界面同源,拥有完整会话权限(可在设置中恢复)",
9136
- htmlNoSandboxWarning: "沙箱已关闭:此 HTML 与界面同源,可读取会话文件与内部接口(可在设置中恢复)",
9137
9102
  sandboxStatusOn: "沙箱模式:已启用 · 页面无法访问界面数据与本地文件,登录态与第三方 Cookie 可能不可用",
9138
9103
  sandboxUnlock: "临时解锁(不安全)",
9139
9104
  sandboxRestore: "恢复沙箱",
9140
- settingsHtmlDefaultUnsafeTitle: "HTML 预览默认以非沙箱模式打开(不安全)",
9141
- settingsHtmlDefaultUnsafeDesc: "开启后,每次打开 HTML 文件时预览默认处于非沙箱状态(与界面同源,可读取会话文件与内部接口);可在状态行临时恢复沙箱",
9142
- settingsHtmlSandboxTitle: "关闭 HTML 预览沙箱(不安全)",
9143
- settingsHtmlSandboxDesc: "关闭后,预览的 HTML 将与界面同源运行,可读取会话文件、本地存储并调用内部接口。仅对完全可信的文件开启",
9144
9105
  settingsBrowserSandboxTitle: "关闭浏览器沙箱(不安全)",
9145
9106
  settingsBrowserSandboxDesc: "关闭后,访问的任何网站都将与界面同源运行,可读取会话数据并冒充你的登录状态。仅对完全可信的站点开启",
9146
9107
  settingsBrowserLinksTitle: "聊天区外链在侧边栏打开",
@@ -9221,10 +9182,7 @@ window.__ModuleLoader__.load({
9221
9182
  jobKillError: "终止失败",
9222
9183
  addPluginsTabCard: "添加 Tab 插件",
9223
9184
  addPluginsTabCardDesc: "注册新的侧边栏页面",
9224
- addPluginsViewerCard: "添加预览插件",
9225
- addPluginsViewerCardDesc: "注册新的文件类型预览",
9226
9185
  addPluginsTabDesc: "侧边栏页面(Tab)可以由插件扩展。插件通过 ctx.betterSidebar 服务注册;点击「安装」复制安装命令,粘贴到 DSH 所在环境的终端执行。",
9227
- addPluginsViewerDesc: "文件预览器可以由插件扩展。插件通过 ctx.betterSidebar 服务注册;点击「安装」复制安装命令,粘贴到 DSH 所在环境的终端执行。",
9228
9186
  addPluginsBrowseMore: "在 GitHub 上浏览更多插件(topic: dsh-coding-sidebar)",
9229
9187
  addPluginsSearch: "搜索插件名称 / 描述…",
9230
9188
  addPluginsNoMatch: "没有匹配的插件",
@@ -9232,7 +9190,6 @@ window.__ModuleLoader__.load({
9232
9190
  addPluginsEmpty: "暂未收录插件,欢迎在 GitHub topic 下发布你的插件",
9233
9191
  openPlugin: "跳转",
9234
9192
  copyInstall: "复制安装命令",
9235
- pluginOfficeDesc: "为 dsh-coding-sidebar 编辑器提供 Office 三件套预览(.docx / .xlsx / .pptx),把重型 Office 渲染库拆出主包、按需安装",
9236
9193
  pluginFlowglassDesc: "实时会话流程图:三列泳道展示用户、助手与工具调用,支持并行分组、子代理支线、逐层钻取和实时状态;安装 dsh-coding-sidebar 后注册原生「流镜」Tab,未安装时保留独立抽屉",
9237
9194
  pluginGitForgeDesc: "dsh-coding-sidebar「Git 凭据」Tab:GitHub/Gitea 等 Forge 账号库 + 按项目授权 + push 策略硬拦;token 仅存本地 secrets,不进模型上下文;提供只读 GitForge 工具与 agent HTTPS credential helper",
9238
9195
  pluginGitRemotesDesc: "dsh-coding-sidebar Git 远程 Tab:看分支/上游/ahead-behind,fetch(可 prune)、ff-only pull、确认后才 push。不替换内置 Git 的暂存/提交,也不提供 force-push 或模型自动推送",
@@ -9240,7 +9197,6 @@ window.__ModuleLoader__.load({
9240
9197
  pluginSidebarQaDesc: "基于 dsh-coding-sidebar 的划选提问tab分页: 对话划选 → 右侧面板提问 → 同工作区独立追问会话(❓追问·主题):快速无思考模型压缩主对话上下文后与引文一起注入,不打断主对话;追问可嵌套、可继续、可归档",
9241
9198
  pluginSshTunnelDesc: "dsh-coding-sidebar「SSH 隧道」Tab:多机主机清单 + 按项目授权 + 密钥本地保管;模型工具 SSHManager(exec/SFTP/会话策略);中央交互终端与双栏 SFTP",
9242
9199
  pluginTurnReviewDesc: "对「刚刚这一回合」的 diff 做 Approve / Request changes 的人闸门:只审上一回合,不 fork 会话;文件按主会话/子代理/未归因分组,按文件勾选打回 + 可选评语,点文件先看回合开始快照 vs 现在的 diff。不是 /rewind",
9243
- pluginVideoPreviewDesc: "在 dsh-coding-sidebar 编辑器内联预览视频文件(.mp4/.webm/.mov/.mkv/.avi 等),自带支持 HTTP Range(206)的 /video 宿主路由,可拖动进度条、不受 20MB mediaLimit 限制",
9244
9200
  pluginDocsPanelDesc: "DSH 侧边栏里的「全局文档」:全局 Markdown 笔记,任何工作区随时可读——列表点选阅读、悬浮大纲跳转、Chrome / VS Code 外部打开、代码复制,目录可配置(默认 ~/.dsh/docs)",
9245
9201
  pluginEgoBrowserDesc: "把 CitroLabs/ego-lite 接进 DeepSeek Harness 的 agent 浏览器:32 个 ego_* 工具驱动真实 Chromium,侧边栏原生「ego 浏览器」Tab 实时观察 agent 逛的每个页面,可直接点击/拖拽/输入接管;装 dsh-coding-sidebar 时自动注册 Tab,没装则退回浮动浮窗"
9246
9202
  };
@@ -9318,14 +9274,6 @@ window.__ModuleLoader__.load({
9318
9274
  terminalDepsFailed: "Terminal dependency node-pty failed to load",
9319
9275
  terminalDepsHint: "Run the command below in a terminal or cmd on the DSH machine to repair it, then retry (node-pty stays in sync with the DSH core version):",
9320
9276
  terminalDepsProfile: " (detected profile: {profile})",
9321
- preview: "Preview",
9322
- toc: "Table of contents",
9323
- edit: "Edit",
9324
- mermaidError: "Mermaid render failed",
9325
- mermaidZoomIn: "Zoom in",
9326
- mermaidZoomOut: "Zoom out",
9327
- mermaidZoomReset: "Reset",
9328
- mermaidZoomHint: "Scroll to zoom · drag to pan · Esc to close",
9329
9277
  refresh: "Refresh",
9330
9278
  refreshUnsavedConfirm: "The file changed on disk. Refreshing will discard unsaved edits. Continue?",
9331
9279
  save: "Save",
@@ -9468,34 +9416,27 @@ window.__ModuleLoader__.load({
9468
9416
  settingsFontSizeDesc: "Terminal font size in px (9–32, default 13)",
9469
9417
  settingsFontSizeSuffix: "px",
9470
9418
  settingsTabsTitle: "Sidebar content",
9471
- settingsViewersTitle: "File viewers",
9472
9419
  settingsGeneralTitle: "General",
9473
9420
  settingsPopup: "Feature settings",
9474
- settingsViewerCatchAll: "Catch-all: any file",
9475
- viewerImage: "Image",
9476
- viewerPdf: "PDF",
9477
- viewerMarkdown: "Markdown",
9478
- viewerCode: "Code",
9479
- viewerBinary: "Binary download",
9480
- viewerHtml: "HTML",
9481
9421
  browser: "Browser",
9482
9422
  browserPlaceholder: "Enter a URL, e.g. example.com",
9483
9423
  browserGo: "Go",
9484
9424
  browserBack: "Back",
9485
9425
  browserForward: "Forward",
9486
9426
  browserStart: "Enter a URL to start browsing (sandbox mode)",
9427
+ browserLive: "Agent live",
9428
+ browserLiveFree: "Free browse",
9429
+ browserLiveConnecting: "connecting to the agent browser host…",
9430
+ browserLiveDown: "host unreachable: make sure KCoder is running (port 9223)",
9431
+ browserLiveTargetNone: "No open pages yet — they appear here live once the agent browses",
9432
+ browserLiveFollowLatest: "Follow latest",
9487
9433
  browserBlockedScheme: "Blocked: only http/https URLs are allowed",
9488
9434
  browserBlockedLoopback: "Blocked: local and internal addresses cannot be browsed here",
9489
9435
  browserInvalid: "Invalid URL",
9490
9436
  browserNoSandboxWarning: "Sandbox off: the current page runs with full GUI privileges (re-enable in settings)",
9491
- htmlNoSandboxWarning: "Sandbox off: this HTML runs with full GUI privileges (re-enable in settings)",
9492
9437
  sandboxStatusOn: "Sandbox mode: on · pages cannot access the GUI's data or local files; logins and third-party cookies may not work",
9493
9438
  sandboxUnlock: "Temporarily disable (unsafe)",
9494
9439
  sandboxRestore: "Restore sandbox",
9495
- settingsHtmlDefaultUnsafeTitle: "Open HTML previews unsandboxed by default (unsafe)",
9496
- settingsHtmlDefaultUnsafeDesc: "When on, every newly opened HTML preview starts in the unsandboxed state (same origin as the GUI — it can read session files and internal APIs); the status row still offers a one-tap restore",
9497
- settingsHtmlSandboxTitle: "Disable HTML preview sandbox (unsafe)",
9498
- settingsHtmlSandboxDesc: "With the sandbox off, previewed HTML runs with the same origin as the GUI: it can read session files, local storage and call internal APIs. Only enable for fully trusted files",
9499
9440
  settingsBrowserSandboxTitle: "Disable browser sandbox (unsafe)",
9500
9441
  settingsBrowserSandboxDesc: "With the sandbox off, any visited site runs with the same origin as the GUI: it can read session data and act as your logged-in session. Only enable for fully trusted sites",
9501
9442
  settingsBrowserLinksTitle: "Open chat external links in the sidebar",
@@ -9576,10 +9517,7 @@ window.__ModuleLoader__.load({
9576
9517
  jobKillError: "Kill failed",
9577
9518
  addPluginsTabCard: "Add tab plugins",
9578
9519
  addPluginsTabCardDesc: "Register a new sidebar page",
9579
- addPluginsViewerCard: "Add preview plugins",
9580
- addPluginsViewerCardDesc: "Register a file-type preview",
9581
9520
  addPluginsTabDesc: "Sidebar pages (tabs) can be extended by plugins. Plugins register through the ctx.betterSidebar service; clicking Install copies the install command — paste it into a terminal where your DSH profile lives and run it.",
9582
- addPluginsViewerDesc: "File previewers can be extended by plugins. Plugins register through the ctx.betterSidebar service; clicking Install copies the install command — paste it into a terminal where your DSH profile lives and run it.",
9583
9521
  addPluginsBrowseMore: "Browse more plugins on GitHub (topic: dsh-coding-sidebar)",
9584
9522
  addPluginsSearch: "Search by plugin name or description…",
9585
9523
  addPluginsNoMatch: "No plugins match",
@@ -9587,7 +9525,6 @@ window.__ModuleLoader__.load({
9587
9525
  addPluginsEmpty: "No plugins curated yet — publish yours under the GitHub topic",
9588
9526
  openPlugin: "Open",
9589
9527
  copyInstall: "Copy install command",
9590
- pluginOfficeDesc: "Office-suite preview (.docx / .xlsx / .pptx) for the dsh-coding-sidebar editor, keeping the heavy Office render libraries out of the core bundle",
9591
9528
  pluginFlowglassDesc: "Live session flowgraph with three lanes for user, assistant, and tool calls, plus parallel groups, sub-agent branches, drill-down, and live status; registers a native Flowglass tab when dsh-coding-sidebar is installed and keeps its standalone drawer as a fallback",
9592
9529
  pluginGitForgeDesc: "Git Forge tab: GitHub/Gitea (and other forge) account library + per-project grants + hard push policy; tokens stay in local secrets (never in model context); read-only GitForge tool and agent HTTPS credential helper",
9593
9530
  pluginGitRemotesDesc: "Git Remotes tab: branch/upstream/ahead-behind, fetch (optional prune), ff-only pull, and push only after an in-tab confirm. Does not replace the built-in Git stage/commit tab, and does not offer force-push or a model auto-push tool",
@@ -9595,7 +9532,6 @@ window.__ModuleLoader__.load({
9595
9532
  pluginSidebarQaDesc: "Select-and-ask: Select conversation text → ask in the right-side panel → a dedicated follow-up session (❓追问) in the same workspace; a fast no-thinking model compresses the main context and injects it with the quote, without interrupting the main conversation. Follow-ups nest, continue, and archive",
9596
9533
  pluginSshTunnelDesc: "SSH Tunnel tab: multi-host inventory + per-project grants + local secrets; SSHManager tool (exec/SFTP/session strategies); center interactive terminal and dual-pane SFTP",
9597
9534
  pluginTurnReviewDesc: "A human gate on the just-finished turn: Approve / Request changes per path with an optional comment; paths grouped by main session / subagent / unattributed; inline snapshot-vs-now diff before you decide. No fork, no /rewind",
9598
- pluginVideoPreviewDesc: "Inline video preview (.mp4/.webm/.mov/.mkv/.avi etc.) for the dsh-coding-sidebar editor, backed by a dedicated /video host route with HTTP Range (206) support — scrubbing works and files are not capped by the 20MB mediaLimit",
9599
9535
  pluginDocsPanelDesc: "Global docs in the DSH sidebar: read your own Markdown notes from any workspace — a file list, an outline, open in Chrome / VS Code, and copy buttons; the docs directory is configurable (default ~/.dsh/docs)",
9600
9536
  pluginEgoBrowserDesc: "The agent browser for DeepSeek Harness: 32 ego_* tools drive a real Chromium, with a native sidebar \"ego browser\" tab giving a live view of every page the agent visits — you can click, drag, and type to take over. Registers the tab automatically when dsh-coding-sidebar is present, otherwise falls back to a floating bubble"
9601
9537
  };
@@ -9956,7 +9892,7 @@ window.__ModuleLoader__.load({
9956
9892
  }
9957
9893
  //#endregion
9958
9894
  //#region \0dsh-css:/Users/libing/kk_Projects/dsh-coding-sidebar/src/client/sidebar.module.css.mjs
9959
- const css$4 = "[data-dsh-panel-host]{z-index:25;pointer-events:none;position:fixed;inset:0;overflow:hidden}[data-dsh-panel-host][data-dsh-panel-host-degraded]{position:absolute;top:0;left:0}.S5HVoW_toggleCluster{top:calc(3px + env(safe-area-inset-top));z-index:45;pointer-events:auto;flex-direction:row;gap:4px;display:flex;position:absolute;right:10px}.S5HVoW_panel:not(.S5HVoW_panelHidden) .S5HVoW_tabBar{padding-right:72px}.S5HVoW_toggleButton{width:28px;height:28px;color:var(--dsw-alias-label-secondary);cursor:pointer;transition:background var(--ds-transition-duration-slow) var(--ds-ease-in-out), color var(--ds-transition-duration-slow) var(--ds-ease-in-out);background:0 0;border:none;border-radius:50%;justify-content:center;align-items:center;display:flex}.S5HVoW_toggleButton:hover:not(:disabled):not([aria-disabled=true]){background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.S5HVoW_toggleButton:disabled,.S5HVoW_toggleButton[aria-disabled=true]{opacity:.4;cursor:default}.S5HVoW_panel{box-sizing:border-box;z-index:40;pointer-events:auto;background:var(--dsw-alias-bg-layer-1);border-left:1px solid var(--dsw-alias-border-l2);padding-bottom:env(safe-area-inset-bottom);transition:transform var(--ds-transition-duration-slow) var(--ds-ease-in-out), width var(--ds-transition-duration-slow) var(--ds-ease-in-out);flex-direction:column;display:flex;position:absolute;top:0;bottom:0;right:0}.S5HVoW_panelHidden{pointer-events:none;visibility:hidden;transition:transform var(--ds-transition-duration-slow) var(--ds-ease-in-out), width var(--ds-transition-duration-slow) var(--ds-ease-in-out), visibility 0s linear var(--ds-transition-duration-slow);transform:translate(102%)}.S5HVoW_panel[data-dragging]{transition:none}.S5HVoW_panelResize{cursor:col-resize;z-index:2;touch-action:none;width:8px;position:absolute;top:0;bottom:0;left:-4px}.S5HVoW_panelResizeActive{background:var(--dsw-alias-interactive-bg-hover-accent)}.S5HVoW_panelBody{flex:1;min-width:0;min-height:0;display:flex}.S5HVoW_panel{contain:layout style}body[data-dsh-sidebar-dragging] .S5HVoW_panel{will-change:transform}.S5HVoW_floatWindow{z-index:42;pointer-events:auto;background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l2);box-shadow:var(--dsw-shadow-lv3);contain:layout style;border-radius:8px;flex-direction:column;display:flex;position:absolute;overflow:hidden}.S5HVoW_floatWindowDragging{will-change:left, top, width, height}.S5HVoW_floatHeader{height:34px;font:var(--dsw-font-xxs-12);color:var(--dsw-alias-label-secondary);background:var(--dsw-alias-bg-layer-1);border-bottom:1px solid var(--dsw-alias-border-l1);cursor:grab;user-select:none;flex:none;align-items:center;gap:4px;padding:0 4px 0 10px;display:flex}.S5HVoW_floatWindowDragging .S5HVoW_floatHeader{cursor:grabbing}.S5HVoW_floatTitle{text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;overflow:hidden}.S5HVoW_floatClose{width:18px;height:18px;color:var(--dsw-alias-label-tertiary);cursor:pointer;background:0 0;border:none;border-radius:4px;flex:none;justify-content:center;align-items:center;padding:0;display:inline-flex}.S5HVoW_floatClose:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.S5HVoW_floatContent{flex-direction:column;flex:1;min-width:0;min-height:0;display:flex;overflow:hidden}.S5HVoW_floatResize{z-index:2;cursor:nwse-resize;touch-action:none;width:14px;height:14px;position:absolute;bottom:0;right:0}.S5HVoW_floatResize:hover{background:var(--dsw-alias-interactive-bg-hover-accent)}.S5HVoW_pane[data-dsh-float-dock-over]{outline:2px dashed var(--dsw-alias-interactive-bg-hover-accent);outline-offset:-2px}.S5HVoW_floatDropHint{z-index:46;pointer-events:none;border:2px dashed var(--dsw-alias-interactive-bg-hover-accent);background:color-mix(in srgb, var(--dsw-alias-interactive-bg-hover-accent) 12%, transparent);border-radius:8px;justify-content:center;align-items:center;display:flex;position:absolute}.S5HVoW_floatDropHintLabel{font:var(--dsw-font-xxs-12);color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l2);border-radius:999px;padding:4px 12px}.S5HVoW_toggleCluster,.S5HVoW_toggleButton,.S5HVoW_tabBar,.S5HVoW_floatHeader{-webkit-app-region:no-drag}body[data-dsh-title-bar-compat] .S5HVoW_toggleCluster{top:calc(var(--dsh-title-bar-strip,40px) + 3px)}body[data-dsh-title-bar-compat] .S5HVoW_panel{padding-top:var(--dsh-title-bar-strip,40px)}.S5HVoW_iconButton{width:28px;height:28px;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;border-radius:50%;flex:none;justify-content:center;align-items:center;padding:0;display:inline-flex}.S5HVoW_iconButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.S5HVoW_iconButton:disabled{opacity:.4;cursor:default}.S5HVoW_workbench,.S5HVoW_split{flex:1;min-width:0;min-height:0;display:flex}.S5HVoW_splitRow{flex-direction:row}.S5HVoW_splitCol{flex-direction:column}.S5HVoW_splitChild{display:flex;position:relative;overflow:hidden}.S5HVoW_divider{z-index:3;touch-action:none;flex:none;position:relative}.S5HVoW_dividerRow:after,.S5HVoW_dividerCol:after{content:\"\";background:var(--dsw-alias-border-l2);transition:background var(--ds-transition-duration-slow) var(--ds-ease-in-out);position:absolute}.S5HVoW_dividerRow{cursor:col-resize;width:7px;margin:0 -2px}.S5HVoW_dividerRow:after{width:1px;top:0;bottom:0;left:50%;transform:translate(-50%)}.S5HVoW_dividerCol{cursor:row-resize;height:7px;margin:-2px 0}.S5HVoW_dividerCol:after{height:1px;top:50%;left:0;right:0;transform:translateY(-50%)}.S5HVoW_divider:hover:after,.S5HVoW_dividerActive:after{background:var(--dsw-alias-interactive-bg-hover-accent)}.S5HVoW_pane{background:var(--dsw-alias-bg-base);flex-direction:column;flex:1;min-width:0;min-height:0;display:flex;position:relative}.S5HVoW_paneDrop{outline:1px solid var(--dsw-alias-interactive-bg-hover-accent);outline-offset:-1px}.S5HVoW_dropOverlay{z-index:6;pointer-events:none;background:var(--dsw-alias-interactive-bg-hover-accent);opacity:.5;position:absolute}.S5HVoW_dropLeft{width:25%;top:0;bottom:0;left:0}.S5HVoW_dropRight{width:25%;top:0;bottom:0;right:0}.S5HVoW_dropUp{height:25%;top:0;left:0;right:0}.S5HVoW_dropDown{height:25%;bottom:0;left:0;right:0}.S5HVoW_dropCenter{outline:2px dashed var(--dsw-alias-interactive-bg-hover-accent);outline-offset:-2px;background:0 0;inset:25%}.S5HVoW_paneContent{flex-direction:column;flex:1;min-height:0;display:flex;overflow:hidden}.S5HVoW_paneTab{flex-direction:column;flex:1;min-height:0;display:flex}.S5HVoW_paneTabHidden{display:none}.S5HVoW_paneEmptyCards{flex:1;grid-template-columns:repeat(auto-fill,minmax(140px,1fr));align-content:start;gap:8px;min-height:0;padding:12px;display:grid;overflow:hidden}.S5HVoW_paneCard{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1);min-width:0;color:var(--dsw-alias-label-secondary);font:var(--dsw-font-xxs-strong-12);cursor:pointer;text-align:center;border-radius:8px;flex-direction:column;justify-content:center;align-items:center;gap:6px;padding:12px 8px;display:flex}.S5HVoW_paneCard:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-border-l2)}.S5HVoW_paneCard:disabled{opacity:.45;cursor:default}.S5HVoW_tabBar{border-bottom:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1);flex:none;align-items:stretch;height:34px;display:flex}.S5HVoW_tabBarDrop{outline:1px dashed var(--dsw-alias-interactive-bg-hover-accent);outline-offset:-1px}.S5HVoW_tabList{scrollbar-width:none;flex:1;min-width:0;display:flex;overflow-x:auto}.S5HVoW_tabList::-webkit-scrollbar{display:none}.S5HVoW_tab{min-width:64px;max-width:160px;font:var(--dsw-font-xxs-12);color:var(--dsw-alias-label-secondary);border-right:1px solid var(--dsw-alias-border-l1);cursor:pointer;user-select:none;background:0 0;flex:none;align-items:center;gap:4px;padding:0 4px 0 10px;display:flex}.S5HVoW_tab:hover{background:var(--dsw-alias-interactive-bg-hover)}.S5HVoW_tabActive{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-interactive-bg-active)}.S5HVoW_tabTitle{text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;overflow:hidden}.S5HVoW_tabBadge{min-width:16px;height:15px;font:var(--dsw-font-xxxs-strong-11);background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-brand-primary);border-radius:8px;flex:none;justify-content:center;align-items:center;padding:0 4px;display:inline-flex}.S5HVoW_tabClose{width:18px;height:18px;color:var(--dsw-alias-label-tertiary);cursor:pointer;background:0 0;border:none;border-radius:4px;flex:none;justify-content:center;align-items:center;padding:0;display:inline-flex}.S5HVoW_tabClose:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.S5HVoW_tabBarPlus{background:var(--dsw-alias-bg-layer-1);width:22px;height:22px;color:var(--dsw-alias-label-tertiary);cursor:pointer;border:none;border-radius:5px;flex:none;justify-content:center;align-self:center;align-items:center;margin:0 6px;padding:0;display:inline-flex;position:sticky;right:0}.S5HVoW_tabBarPlus:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.S5HVoW_pinnedTab{color:var(--dsw-alias-label-tertiary);font-style:italic}.S5HVoW_pinnedTab:hover{color:var(--dsw-alias-label-secondary)}.S5HVoW_explorer{flex-direction:column;flex:1;min-height:0;display:flex}.S5HVoW_explorerHeader{flex:none;justify-content:space-between;align-items:center;gap:8px;height:36px;padding:0 8px 0 12px;display:flex}.S5HVoW_explorerRoot{font:var(--dsw-font-s-14);color:var(--dsw-alias-label-secondary);text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.S5HVoW_explorerBody{flex:1;min-height:0;padding:4px 8px 8px;overflow:hidden auto}.S5HVoW_explorerRow{box-sizing:border-box;width:100%;max-width:100%;height:34px;font:var(--dsw-font-s-14);color:var(--dsw-alias-label-primary);text-align:left;cursor:pointer;white-space:nowrap;animation:S5HVoW_dsh-row-in .15s var(--ds-ease-in-out);background:0 0;border:none;border-radius:8px;align-items:center;gap:6px;padding:0 8px;display:flex}.S5HVoW_explorerRow:hover{background:var(--dsw-alias-interactive-bg-hover)}.S5HVoW_explorerRowRevealed{background:color-mix(in srgb, var(--dsw-alias-interactive-bg-hover-accent) 18%, transparent);box-shadow:inset 2px 0 0 var(--dsw-alias-interactive-bg-hover-accent)}.S5HVoW_explorerDir{font:var(--dsw-font-s-strong-14)}.S5HVoW_explorerHidden{opacity:.45}.S5HVoW_explorerSymlink{color:var(--dsw-alias-label-tertiary);flex:none}.S5HVoW_explorerBroken .S5HVoW_explorerName{color:var(--dsw-alias-state-error-primary)}.S5HVoW_explorerName{text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}.S5HVoW_explorerRef{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-2);height:20px;color:var(--dsw-alias-label-tertiary);font:var(--dsw-font-xxxs-strong-11);cursor:pointer;border-radius:999px;flex:none;align-items:center;padding:0 8px;display:none}.S5HVoW_explorerRef:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.S5HVoW_explorerRow:hover .S5HVoW_explorerRef,.S5HVoW_explorerRow:focus-within .S5HVoW_explorerRef{display:inline-flex}.S5HVoW_explorerCopied{font:var(--dsw-font-xxxs-11);color:var(--dsw-alias-label-tertiary);flex:none}.S5HVoW_explorerError{font:var(--dsw-font-xxs-12);color:var(--dsw-alias-state-error-primary);cursor:default}@keyframes S5HVoW_dsh-row-in{0%{opacity:0}}.S5HVoW_explorerEmpty{font:var(--dsw-font-xxs-12);color:var(--dsw-alias-label-tertiary);text-align:center;padding:16px}.S5HVoW_explorerRowDropTarget{background:var(--dsw-alias-interactive-bg-hover);outline:1px dashed var(--dsw-alias-interactive-bg-hover-accent);outline-offset:-1px}.S5HVoW_uploadDropZone{z-index:1001;pointer-events:none;border:2px dashed var(--dsw-alias-interactive-bg-hover-accent);box-shadow:0 0 0 200vmax var(--dsw-alias-bg-mask-drop);animation:S5HVoW_dsh-row-in .15s var(--ds-ease-in-out);border-radius:10px;justify-content:center;align-items:flex-start;padding:12px;display:flex;position:fixed}.S5HVoW_uploadDropHero{flex-direction:column;align-items:center;gap:10px;max-width:100%;padding-top:8px;display:flex}.S5HVoW_uploadDropZonePill{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-2);max-width:100%;box-shadow:var(--dsw-shadow-lv2);color:var(--dsw-alias-label-primary);font:var(--dsw-font-xxs-strong-12);border-radius:999px;align-items:center;gap:6px;padding:6px 12px;display:flex}.S5HVoW_uploadDropZoneText{white-space:nowrap;text-overflow:ellipsis;overflow:hidden}.S5HVoW_uploadDropChatHint{z-index:1002;pointer-events:none;animation:S5HVoW_dsh-row-in .15s var(--ds-ease-in-out);justify-content:center;align-items:center;padding:24px;display:flex;position:fixed;top:0;bottom:0;left:0}.S5HVoW_uploadDropChatCard{text-align:center;max-width:100%;color:var(--dsw-alias-label-primary);font:var(--dsw-font-s-strong-14);flex-direction:column;align-items:center;gap:12px;display:flex}.S5HVoW_uploadOverlay{z-index:30;background:var(--dsw-alias-bg-mask-1);backdrop-filter:var(--dsw-mask-blur);animation:S5HVoW_dsh-row-in .15s var(--ds-ease-in-out);justify-content:center;align-items:center;display:flex;position:absolute;inset:0}.S5HVoW_uploadOverlayCard{border:1px solid var(--dsw-alias-border-inverted);background:var(--dsw-alias-bg-layer-2);min-width:280px;max-width:min(420px,100% - 48px);box-shadow:var(--dsw-shadow-lv3);border-radius:24px;flex-direction:column;gap:12px;padding:20px 24px;display:flex}.S5HVoW_uploadOverlayTitle{font:var(--dsw-font-s-strong-14);color:var(--dsw-alias-label-primary);align-items:center;gap:8px;display:flex}.S5HVoW_uploadOverlayTitle>svg{flex:none}.S5HVoW_uploadOverlayTitle>span{white-space:nowrap;text-overflow:ellipsis;min-width:0;overflow:hidden}.S5HVoW_uploadOverlayProgress{background:var(--dsw-alias-border-l2);border-radius:3px;height:6px;overflow:hidden}.S5HVoW_uploadOverlayProgressFill{background:var(--dsw-alias-interactive-bg-hover-accent);height:100%;transition:width .15s var(--ds-ease-in-out);border-radius:3px}.S5HVoW_uploadOverlayStatus{min-height:1em;font:var(--dsw-font-xxs-12);font-variant-numeric:tabular-nums;color:var(--dsw-alias-label-tertiary);white-space:nowrap;text-overflow:ellipsis;overflow:hidden}.S5HVoW_uploadOverlayCancel{border:1px solid var(--dsw-alias-border-l2);height:28px;color:var(--dsw-alias-label-primary);font:var(--dsw-font-xxs-strong-12);cursor:pointer;background:0 0;border-radius:8px;align-self:flex-end;padding:0 14px}.S5HVoW_uploadOverlayCancel:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover);border-color:var(--dsw-alias-border-l2)}.S5HVoW_uploadOverlayCancel:disabled{opacity:.4;cursor:default}.S5HVoW_editor{flex-direction:column;flex:1;min-height:0;display:flex}.S5HVoW_editorHeader{border-bottom:1px solid var(--dsw-alias-border-l1);flex:none;align-items:center;gap:6px;padding:6px 8px;display:flex}.S5HVoW_editorTitle{min-width:0;font:var(--dsw-font-xxs-strong-12);color:var(--dsw-alias-label-secondary);text-overflow:ellipsis;white-space:nowrap;flex:1;overflow:hidden}.S5HVoW_editorPathInput{box-sizing:border-box;border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1);min-width:0;height:28px;color:var(--dsw-alias-label-primary);font:var(--dsw-font-xxs-12);border-radius:6px;flex:1;padding:0 10px}.S5HVoW_editorPathInput:focus{border-color:var(--dsw-alias-border-l2);outline:none}.S5HVoW_editorTreeToggleActive{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-interactive-bg-active)}.S5HVoW_editorBody{flex:1;min-height:0;display:flex}.S5HVoW_editorMain{flex-direction:column;flex:1;min-width:0;min-height:0;display:flex}.S5HVoW_editorTreeDock{border-left:1px solid var(--dsw-alias-border-l1);flex:none;min-height:0;display:flex;position:relative}.S5HVoW_editorTreeResize{cursor:col-resize;touch-action:none;z-index:3;width:6px;position:absolute;top:0;bottom:0;left:0}.S5HVoW_editorTreeResize:hover{background:var(--dsw-alias-border-l2)}.S5HVoW_editorTreePanel{flex-direction:column;flex:1;min-width:0;min-height:0;display:flex;position:relative}.S5HVoW_editorTreePanelFull{flex:1}.S5HVoW_editorTreeSearch{border-bottom:1px solid var(--dsw-alias-border-l1);flex:none;align-items:center;gap:6px;padding:6px 8px;display:flex}.S5HVoW_editorSearchInput{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1);min-width:0;height:26px;color:var(--dsw-alias-label-primary);font:var(--dsw-font-xxs-12);border-radius:6px;flex:1;padding:0 10px}.S5HVoW_editorSearchInput:focus{border-color:var(--dsw-alias-border-l2);outline:none}.S5HVoW_editorSearchHint{font:var(--dsw-font-xxs-12);color:var(--dsw-alias-label-tertiary);padding:8px 12px}.S5HVoW_editorSearchResult{width:100%;color:var(--dsw-alias-label-primary);font:var(--dsw-font-xxs-12);text-align:left;cursor:pointer;text-overflow:ellipsis;white-space:nowrap;background:0 0;border:none;border-radius:6px;padding:4px 8px;display:block;overflow:hidden}.S5HVoW_editorSearchResult:hover{background:var(--dsw-alias-interactive-bg-hover)}.S5HVoW_editorStatus{font:var(--dsw-font-xxxs-11);color:var(--dsw-alias-label-tertiary)}.S5HVoW_editorStatusError{color:var(--dsw-alias-state-error-primary)}.S5HVoW_dirtyDot{background:var(--dsw-alias-state-warn-primary);border-radius:50%;flex:none;width:7px;height:7px}.S5HVoW_editorPlaceholder{font:var(--dsw-font-xxs-12);color:var(--dsw-alias-label-tertiary);text-align:center;flex:1;justify-content:center;align-items:center;padding:16px;display:flex}.S5HVoW_orphanedType{opacity:.7;overflow-wrap:anywhere;margin-top:8px;font-size:12px;display:block}.S5HVoW_editorBinary{text-align:center;flex-direction:column;flex:1;justify-content:center;align-items:center;gap:12px;padding:24px 16px;display:flex}.S5HVoW_editorBinaryNotice{font:var(--dsw-font-xxs-12);color:var(--dsw-alias-label-tertiary)}.S5HVoW_editorDownloadLink{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary);font:var(--dsw-font-xxs-strong-12);cursor:pointer;transition:background var(--ds-transition-duration-slow) var(--ds-ease-in-out), border-color var(--ds-transition-duration-slow) var(--ds-ease-in-out);border-radius:6px;align-items:center;gap:6px;padding:6px 14px;text-decoration:none;display:inline-flex}.S5HVoW_editorDownloadLink:hover{background:var(--dsw-alias-interactive-bg-hover);border-color:var(--dsw-alias-border-l2)}.S5HVoW_editorError{font:var(--dsw-font-xxs-12);color:var(--dsw-alias-state-error-primary);padding:12px 16px}.S5HVoW_editorBanner{font:var(--dsw-font-xxxs-11);color:var(--dsw-alias-state-warn-label);background:var(--dsw-alias-state-warn-tertiary);flex:none;padding:4px 8px}.S5HVoW_sandboxStatus{font:var(--dsw-font-xxxs-11);flex:none;align-items:center;gap:8px;padding:4px 10px;display:flex}.S5HVoW_sandboxStatusOn{color:var(--dsw-alias-label-secondary);background:var(--dsw-alias-bg-layer-1);border-bottom:1px solid var(--dsw-alias-border-l1)}.S5HVoW_sandboxStatusOff{color:var(--dsw-alias-state-error-primary);background:color-mix(in srgb, var(--dsw-alias-state-error-primary) 10%, transparent);border-bottom:1px solid color-mix(in srgb, var(--dsw-alias-state-error-primary) 45%, transparent)}.S5HVoW_sandboxDot{background:var(--dsw-alias-state-success-primary);border-radius:50%;flex:none;width:6px;height:6px}.S5HVoW_sandboxStatusOff .S5HVoW_sandboxDot{background:var(--dsw-alias-state-error-primary)}.S5HVoW_sandboxStatusText{text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;overflow:hidden}.S5HVoW_sandboxAction{border:1px solid var(--dsw-alias-border-l2);font:inherit;color:inherit;cursor:pointer;background:0 0;border-radius:6px;flex:none;padding:2px 8px}.S5HVoW_sandboxAction:hover{background:var(--dsw-alias-interactive-bg-hover)}.S5HVoW_editorHtml{background:var(--dsw-alias-bg-base);border:none;flex:1;width:100%;min-height:0}.S5HVoW_browser{flex-direction:column;flex:1;min-height:0;display:flex}.S5HVoW_browserBar{border-bottom:1px solid var(--dsw-alias-border-l1);flex:none;align-items:center;gap:4px;padding:6px 8px;display:flex}.S5HVoW_browserInput{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1);min-width:0;height:28px;color:var(--dsw-alias-label-primary);font:var(--dsw-font-xxs-12);border-radius:6px;flex:1;padding:0 10px}.S5HVoW_browserInput:focus{border-color:var(--dsw-alias-border-l2);outline:none}.S5HVoW_browserMessage{font:var(--dsw-font-xxxs-11);color:var(--dsw-alias-state-warn-label);background:var(--dsw-alias-state-warn-tertiary);flex:none;padding:4px 12px}.S5HVoW_browserFrame{background:var(--dsw-alias-bg-base);border:none;flex:1;width:100%;min-height:0}.S5HVoW_browserStart{text-align:center;min-height:0;font:var(--dsw-font-xs-13);color:var(--dsw-alias-label-tertiary);flex:1;justify-content:center;align-items:center;padding:20px;display:flex}.S5HVoW_browserBlocked{text-align:center;min-height:0;color:var(--dsw-alias-state-warn-primary);flex-direction:column;flex:1;justify-content:center;align-items:center;gap:6px;padding:24px;display:flex}.S5HVoW_browserBlockedTitle{font:var(--dsw-font-xxs-strong-12);color:var(--dsw-alias-label-primary)}.S5HVoW_browserBlockedDesc{max-width:280px;font:var(--dsw-font-xxxs-11);color:var(--dsw-alias-label-secondary)}.S5HVoW_browserBlockedActions{gap:8px;margin-top:6px;display:flex}.S5HVoW_browserBlockedButton{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-primary);font:var(--dsw-font-xxxs-11);cursor:pointer;border-radius:6px;padding:4px 12px}.S5HVoW_browserBlockedButton:hover{background:var(--dsw-alias-interactive-bg-hover)}.S5HVoW_editorCm{background:0 0;flex:1;min-height:0;overflow:hidden}.S5HVoW_editorCmHidden{display:none}.S5HVoW_editorCm .cm-editor{height:100%}.S5HVoW_editorCm .cm-scroller{padding:12px 16px}.S5HVoW_editorCm .cm-editor.cm-focused{outline:none}.S5HVoW_editorModeToggle{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1);border-radius:6px;flex:none;align-items:center;gap:2px;padding:2px;display:inline-flex}.S5HVoW_editorModeButton{color:var(--dsw-alias-label-tertiary);font:var(--dsw-font-xxxs-11);cursor:pointer;background:0 0;border:none;border-radius:4px;padding:2px 8px}.S5HVoW_editorModeButton:hover{color:var(--dsw-alias-label-primary)}.S5HVoW_editorModeActive{background:var(--dsw-alias-bg-base);color:var(--dsw-alias-label-primary)}.S5HVoW_editorImageWrap{flex:1;justify-content:center;align-items:center;min-height:0;padding:12px;display:flex;overflow:auto}.S5HVoW_editorImage{object-fit:contain;max-width:100%;max-height:100%}.S5HVoW_editorMd{min-height:0;font:var(--dsw-font-xs-13);flex:1;padding:12px 16px;overflow-y:auto}.S5HVoW_mermaidWrap{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1);border-radius:6px;margin:6px 0;overflow:hidden}.S5HVoW_mermaidHeader{border-bottom:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-2);justify-content:space-between;align-items:center;gap:6px;padding:4px 8px;display:flex}.S5HVoW_mermaidInfo{font:var(--dsw-font-xxxs-strong-11);color:var(--dsw-alias-label-tertiary)}.S5HVoW_mermaidCopy{height:20px;color:var(--dsw-alias-label-secondary);font:var(--dsw-font-xxxs-11);cursor:pointer;background:0 0;border:none;border-radius:4px;align-items:center;gap:4px;padding:0 6px;display:inline-flex}.S5HVoW_mermaidCopy:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.S5HVoW_mermaidBody{cursor:zoom-in;justify-content:center;padding:10px;display:flex;overflow:auto}.S5HVoW_mermaidBody svg{max-width:100%;height:auto}.S5HVoW_mermaidError{border-bottom:1px solid var(--dsw-alias-border-l1);color:var(--dsw-alias-state-error-primary);font:var(--dsw-font-xxxs-11);padding:6px 10px}.S5HVoW_mermaidCode{font:var(--dsw-font-xxxs-11);margin:0;padding:8px 10px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;overflow:auto}.S5HVoW_mermaidMarkdown .md-code-block[data-mermaid-processed]{display:contents}.S5HVoW_mermaidModal{z-index:1000;background:var(--dsw-alias-bg-mask-1);backdrop-filter:blur(2px);flex-direction:column;justify-content:center;align-items:center;display:flex;position:fixed;inset:0}.S5HVoW_mermaidModalToolbar{z-index:10;gap:8px;display:flex;position:absolute;top:16px;right:16px}.S5HVoW_mermaidModalButton{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-2);width:36px;height:36px;color:var(--dsw-alias-label-primary);font:var(--dsw-font-xs-strong-13);cursor:pointer;border-radius:8px;justify-content:center;align-items:center;display:inline-flex}.S5HVoW_mermaidModalButton:hover{background:var(--dsw-alias-interactive-bg-hover)}.S5HVoW_mermaidModalStage{justify-content:center;align-items:center;width:90vw;height:80vh;display:flex;position:relative;overflow:hidden}.S5HVoW_mermaidModalStage svg{cursor:grab;transform-origin:50%;user-select:none;-webkit-user-drag:none;background:var(--dsw-alias-bg-layer-1);border-radius:12px;max-width:none;max-height:none;padding:16px}.S5HVoW_mermaidModalStage svg:active{cursor:grabbing}.S5HVoW_mermaidModalHint{color:var(--dsw-alias-label-tertiary);font:var(--dsw-font-xxxs-11);pointer-events:none;position:absolute;bottom:16px;left:50%;transform:translate(-50%)}.S5HVoW_selectionPopup{z-index:60;border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-2);height:28px;color:var(--dsw-alias-label-primary);font:var(--dsw-font-xxxs-strong-11);white-space:nowrap;cursor:pointer;border-radius:6px;align-items:center;padding:0 10px;display:inline-flex;position:fixed;transform:translate(-50%,calc(-100% - 8px))}.S5HVoW_selectionPopup:hover{background:var(--dsw-alias-interactive-bg-hover)}.S5HVoW_editorPdf{background:var(--dsw-alias-bg-base);flex-direction:column;flex:1;min-height:0;display:flex}.S5HVoW_editorPdfToolbar{border-bottom:1px solid var(--dsw-alias-border-l1);flex:none;justify-content:flex-end;padding:6px 8px;display:flex}.S5HVoW_editorPdfStage{flex:1;min-height:0;display:flex;position:relative}.S5HVoW_editorPdfFrame{background:var(--dsw-alias-bg-base);border:none;flex:1;width:100%;min-height:0}.S5HVoW_editorPdfFrameBlocked{pointer-events:none}.S5HVoW_editorPdfDragShield{z-index:4;pointer-events:none;background:0 0;position:absolute;inset:0}.S5HVoW_editorPdfDragShieldActive{pointer-events:auto}body[data-dsh-tab-dragging] .S5HVoW_editorPdfFrame{pointer-events:none!important}body[data-dsh-tab-dragging] .S5HVoW_editorPdfDragShield{pointer-events:auto!important}.S5HVoW_terminalWrap{background:var(--dsw-alias-bg-base);flex-direction:column;flex:1;min-height:0;display:flex;position:relative}.S5HVoW_terminal{flex:1;min-height:0;padding:6px 4px 6px 8px}.S5HVoW_terminal .xterm{height:100%}.S5HVoW_terminalBanner{font:var(--dsw-font-xxxs-11);color:var(--dsw-alias-state-warn-label);background:var(--dsw-alias-state-warn-tertiary);flex-wrap:wrap;flex:none;align-items:center;gap:8px;padding:3px 10px;display:flex}.S5HVoW_terminalBannerUrl{word-break:break-all;opacity:.85;flex-basis:100%;font-family:ui-monospace,SFMono-Regular,Menlo,monospace}.S5HVoW_boundaryError{z-index:50;background:var(--dsw-alias-bg-layer-1);border-left:1px solid var(--dsw-alias-border-l2);font:var(--dsw-font-xxs-12);color:var(--dsw-alias-state-error-primary);flex-direction:column;align-items:flex-start;gap:8px;padding:16px;display:flex;position:fixed;top:0;bottom:0;right:0;overflow:auto}.S5HVoW_terminalRetry{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-secondary);font:var(--dsw-font-xxxs-strong-11);cursor:pointer;border-radius:999px;flex:none;padding:1px 8px}.S5HVoW_terminalRetry:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.S5HVoW_terminalDepsBanner{font:var(--dsw-font-xxs-12);color:var(--dsw-alias-state-warn-label);background:var(--dsw-alias-state-warn-tertiary);flex-direction:column;flex:none;gap:6px;padding:10px;display:flex}.S5HVoW_terminalDepsTitle{font:var(--dsw-font-xxs-strong-12);color:var(--dsw-alias-state-warn-primary)}.S5HVoW_terminalDepsHint{opacity:.9}.S5HVoW_terminalDepsCommandRow{align-items:flex-start;gap:8px;display:flex}.S5HVoW_terminalRepairCommand{white-space:pre-wrap;word-break:break-all;user-select:text;min-width:0;color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l2);border-radius:4px;flex:1;max-height:160px;margin:0;padding:6px 8px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:11px;line-height:1.5;overflow:auto}.S5HVoW_terminalDepsNote{opacity:.85}.S5HVoW_terminalDepsActions{align-items:center;gap:8px;display:flex}.S5HVoW_tabBoundaryError{min-height:0;font:var(--dsw-font-xxs-12);color:var(--dsw-alias-state-error-primary);flex-direction:column;flex:1;align-items:flex-start;gap:8px;padding:12px 16px;display:flex;overflow:auto}.S5HVoW_git{flex-direction:column;flex:1;min-width:0;min-height:0;display:flex;overflow:hidden auto}.S5HVoW_gitHeader{flex:none;align-items:center;gap:8px;height:36px;padding:0 8px 0 12px;display:flex}.S5HVoW_gitWorktreeRow{flex:none;align-items:center;gap:8px;padding:6px 8px 0 12px;display:flex}.S5HVoW_gitWorktreeLabel{color:var(--dsw-alias-label-tertiary);font:var(--dsw-font-xxxs-11);flex:none}.S5HVoW_gitBranchSelect{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-base);min-width:0;height:26px;color:var(--dsw-alias-label-primary);font:var(--dsw-font-xxs-12);border-radius:6px;flex:1;padding:0 6px}.S5HVoW_gitSection{border-top:1px solid var(--dsw-alias-border-l1)}.S5HVoW_gitSectionHeader{font:var(--dsw-font-xxxs-strong-11);color:var(--dsw-alias-label-tertiary);text-transform:uppercase;justify-content:space-between;align-items:center;padding:6px 12px 4px;display:flex}.S5HVoW_gitLink{font:var(--dsw-font-xxxs-11);color:var(--dsw-alias-brand-primary);cursor:pointer;background:0 0;border:none;padding:0}.S5HVoW_gitLink:hover:not(:disabled){text-decoration:underline}.S5HVoW_gitLink:disabled{opacity:.4;cursor:default}.S5HVoW_gitRow{min-height:34px;animation:S5HVoW_dsh-row-in .15s var(--ds-ease-in-out);border-radius:8px;align-items:center;gap:6px;margin:0 6px;padding:0 8px;display:flex}.S5HVoW_gitRow:hover{background:var(--dsw-alias-interactive-bg-hover)}.S5HVoW_gitRowSelected{background:var(--dsw-alias-interactive-bg-active)}.S5HVoW_gitRowMain{cursor:pointer;text-align:left;background:0 0;border:none;flex:1;align-items:center;gap:8px;min-width:0;padding:3px 0;display:flex}.S5HVoW_gitBadge{width:20px;height:16px;font:var(--dsw-font-xxxs-strong-11);background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-secondary);border-radius:4px;flex:none;justify-content:center;align-items:center;display:inline-flex}.S5HVoW_gitName{text-overflow:ellipsis;white-space:nowrap;min-width:0;font:var(--dsw-font-s-14);color:var(--dsw-alias-label-primary);flex:1;overflow:hidden}.S5HVoW_gitEmpty{font:var(--dsw-font-xxs-12);color:var(--dsw-alias-label-tertiary);padding:4px 12px 8px}.S5HVoW_gitPlaceholder{font:var(--dsw-font-xxs-12);color:var(--dsw-alias-label-tertiary);text-align:center;padding:16px}.S5HVoW_gitError{font:var(--dsw-font-xxs-12);color:var(--dsw-alias-state-error-primary);white-space:pre-wrap;padding:8px 12px}.S5HVoW_gitDiff{border-top:1px solid var(--dsw-alias-border-l1);padding:8px}.S5HVoW_gitDiffTab{flex-direction:column;flex:1;min-width:0;min-height:0;display:flex;overflow:hidden auto}.S5HVoW_gitDiffTabHeader{border-bottom:1px solid var(--dsw-alias-border-l1);flex:none;align-items:center;gap:8px;height:36px;padding:0 8px 0 12px;display:flex}.S5HVoW_gitDiffTabTitle{text-overflow:ellipsis;white-space:nowrap;min-width:0;font:var(--dsw-font-xxs-strong-12);color:var(--dsw-alias-label-primary);flex:1;overflow:hidden}.S5HVoW_gitDiffFile{width:100%;color:inherit;text-align:left;cursor:pointer;background:0 0;border:0;align-items:baseline;gap:6px;padding:8px 2px 2px;display:flex}.S5HVoW_gitDiffFile:disabled{cursor:default}.S5HVoW_gitDiffFile:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}.S5HVoW_gitDiffFileChevron{color:var(--dsw-alias-label-tertiary);flex:none;transform:rotate(0)}.S5HVoW_gitDiffFileChevronExpanded{transform:rotate(90deg)}.S5HVoW_gitDiffFilePath{font:var(--dsw-font-xxs-strong-12);color:var(--dsw-alias-label-primary);text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.S5HVoW_gitDiffFileOld{font:var(--dsw-font-xxxs-11);color:var(--dsw-alias-label-tertiary);text-overflow:ellipsis;white-space:nowrap;flex:none;max-width:40%;overflow:hidden}.S5HVoW_gitDiffFileTag{border:1px solid var(--dsw-alias-border-l2);font:var(--dsw-font-xxxs-strong-11);color:var(--dsw-alias-label-secondary);border-radius:999px;flex:none;padding:0 6px}.S5HVoW_gitDiffHunk{font:var(--dsw-font-markdown-code-block-small);color:var(--dsw-alias-label-tertiary);gap:8px;padding:3px 2px;display:flex}.S5HVoW_gitDiffHunkHeader{color:var(--dsw-alias-label-secondary);flex:none}.S5HVoW_gitDiffHunkSection{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.S5HVoW_gitDiffLine{font:var(--dsw-font-markdown-code-block-small);white-space:pre-wrap;overflow-wrap:anywhere;align-items:stretch;min-width:0;line-height:20px;display:flex}.S5HVoW_gitDiffNum{text-align:right;width:36px;color:var(--dsw-alias-label-tertiary);user-select:none;flex:none;padding-right:8px}.S5HVoW_gitDiffCode{flex:1;min-width:0;overflow:visible}.S5HVoW_gitDiffCtx{color:var(--dsw-alias-label-primary)}.S5HVoW_gitDiffDel{color:var(--dsw-alias-state-error-primary);background:color-mix(in srgb, var(--dsw-alias-state-error-primary) 12%, transparent)}.S5HVoW_gitDiffAdd{color:var(--dsw-alias-state-success-primary);background:color-mix(in srgb, var(--dsw-alias-state-success-primary) 12%, transparent)}.S5HVoW_gitDiffMeta{padding-left:2px}.S5HVoW_gitDiffMetaText{font:var(--dsw-font-xxxs-11);color:var(--dsw-alias-label-tertiary);font-style:italic}.S5HVoW_gitDiffExpand{width:100%;font:var(--dsw-font-xxs-12);color:var(--dsw-alias-brand-primary);cursor:pointer;text-align:center;background:0 0;border:none;margin:4px 0;display:block}.S5HVoW_gitDiffExpand:hover{background:var(--dsw-alias-interactive-bg-hover)}.S5HVoW_gitConfirmDesc{font:var(--dsw-font-s-14);color:var(--dsw-alias-label-primary);white-space:pre-wrap;margin:0}.S5HVoW_gitCommit{border-top:1px solid var(--dsw-alias-border-l1);align-items:center;gap:6px;padding:8px 12px;display:flex}.S5HVoW_gitCommitInput{flex:1;min-width:0}.S5HVoW_gitCommitButton{background:var(--dsw-alias-button-primary-fill);height:26px;color:var(--dsw-alias-label-primary-inverted);font:var(--dsw-font-xxs-strong-12);cursor:pointer;border:none;border-radius:6px;flex:none;padding:0 12px}.S5HVoW_gitCommitButton:hover:not(:disabled){background:var(--dsw-alias-button-primary-hover)}.S5HVoW_gitCommitButton:disabled{opacity:.45;cursor:default}.S5HVoW_gitLogRow{cursor:pointer;border-radius:8px;flex-direction:column;gap:2px;padding:5px 12px;display:flex}.S5HVoW_gitLogRow:hover{background:var(--dsw-alias-interactive-bg-hover)}.S5HVoW_gitLogLine1{align-items:baseline;gap:8px;min-width:0;display:flex}.S5HVoW_gitLogHash{font:var(--dsw-font-markdown-code-block-small);color:var(--dsw-alias-label-tertiary);flex:none}.S5HVoW_gitLogLine2{flex-wrap:wrap;align-items:center;gap:6px;min-width:0;display:flex}.S5HVoW_gitLogRef{border:1px solid var(--dsw-alias-border-l2);font:var(--dsw-font-xxxs-strong-11);color:var(--dsw-alias-brand-primary);white-space:nowrap;border-radius:999px;flex:none;padding:0 5px}.S5HVoW_gitLogSubject{text-overflow:ellipsis;white-space:nowrap;min-width:0;font:var(--dsw-font-s-14);color:var(--dsw-alias-label-primary);flex:1;overflow:hidden}.S5HVoW_gitLogMeta{font:var(--dsw-font-xxxs-11);color:var(--dsw-alias-label-tertiary)}.S5HVoW_gitLogMore{border:1px solid var(--dsw-alias-border-l2);width:calc(100% - 24px);font:var(--dsw-font-xxs-12);color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border-radius:6px;margin:4px 12px 8px;padding:6px 0;display:block}.S5HVoW_gitLogMore:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.S5HVoW_gitLogMore:disabled{opacity:.5;cursor:default}.S5HVoW_producedRow{flex-wrap:wrap;align-items:center;gap:8px;padding:4px 0;display:flex}.S5HVoW_producedLabel{font:var(--dsw-font-xxs-12);color:var(--dsw-alias-label-tertiary)}.S5HVoW_producedChip{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-2);max-width:200px;color:var(--dsw-alias-label-secondary);font:var(--dsw-font-xxs-12);cursor:pointer;border-radius:999px;align-items:center;gap:4px;padding:2px 8px;display:inline-flex;overflow:hidden}.S5HVoW_producedChip:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.S5HVoW_producedChip span{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.S5HVoW_producedMore{font:var(--dsw-font-xxs-12);color:var(--dsw-alias-label-tertiary)}.S5HVoW_toggleButton:focus-visible,.S5HVoW_iconButton:focus-visible,.S5HVoW_tab:focus-visible,.S5HVoW_tabClose:focus-visible,.S5HVoW_tabBarPlus:focus-visible,.S5HVoW_paneCard:focus-visible,.S5HVoW_explorerRow:focus-visible,.S5HVoW_explorerRef:focus-visible,.S5HVoW_gitRowMain:focus-visible,.S5HVoW_gitLink:focus-visible,.S5HVoW_gitCommitButton:focus-visible,.S5HVoW_gitLogRow:focus-visible,.S5HVoW_gitLogMore:focus-visible,.S5HVoW_gitDiffFile:focus-visible,.S5HVoW_gitDiffExpand:focus-visible,.S5HVoW_terminalRetry:focus-visible,.S5HVoW_editorModeButton:focus-visible,.S5HVoW_editorDownloadLink:focus-visible,.S5HVoW_editorPptxButton:focus-visible,.S5HVoW_editorDocxZoomRange:focus-visible{outline:2px solid var(--dsw-alias-interactive-bg-hover-accent);outline-offset:-1px}@media (prefers-reduced-motion:reduce){.S5HVoW_panel,.S5HVoW_panelHidden,.S5HVoW_toggleCluster,.S5HVoW_toggleButton,.S5HVoW_tab,.S5HVoW_tabBarPlus,.S5HVoW_paneCard,.S5HVoW_explorerRow,.S5HVoW_gitRow,.S5HVoW_divider,.S5HVoW_dividerRow:after,.S5HVoW_dividerCol:after{transition:none;animation:none}}@media (width<=767px){.S5HVoW_panel:not(.S5HVoW_panelHidden) .S5HVoW_tabBar{padding-right:40px}.S5HVoW_tab{min-width:48px;max-width:128px}}.S5HVoW_openWithLabel{align-items:center;gap:8px;width:100%;min-width:0;display:flex}.S5HVoW_openWithName{text-overflow:ellipsis;white-space:nowrap;flex:auto;min-width:0;overflow:hidden}.S5HVoW_openWithChevron{color:var(--dsw-alias-label-tertiary);flex:none}.S5HVoW_openWithPin{width:20px;height:20px;color:var(--dsw-alias-label-tertiary);cursor:pointer;border-radius:6px;flex:none;justify-content:center;align-items:center;display:inline-flex}.S5HVoW_openWithPin:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.S5HVoW_openWithPinActive{color:var(--dsw-alias-state-business-primary)}.S5HVoW_editorHtmlBlock{margin:8px 0}.S5HVoW_editorHtmlBlock img,.S5HVoW_editorHtmlBlock video{max-width:100%}.S5HVoW_editorHtmlBlock details{margin:4px 0;padding:4px 0}.S5HVoW_editorHtmlBlock summary{cursor:pointer}.S5HVoW_tocBar{z-index:3;pointer-events:none;justify-content:flex-end;height:0;display:flex;position:sticky;top:0}.S5HVoW_tocButton{pointer-events:auto;border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1);width:26px;height:26px;color:var(--dsw-alias-label-secondary);cursor:pointer;border-radius:6px;justify-content:center;align-items:center;margin:4px 2px 0 0;padding:0;display:inline-flex}.S5HVoW_tocButton:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.S5HVoW_tocPanel{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-2);width:min(300px,82%);max-height:60vh;box-shadow:var(--dsw-shadow-lv2);pointer-events:auto;border-radius:8px;flex-direction:column;padding:4px;display:flex;position:absolute;top:32px;right:2px;overflow-y:auto}.S5HVoW_tocItem{min-width:0;color:var(--dsw-alias-label-secondary);font:var(--dsw-font-xxs-12);text-align:left;cursor:pointer;background:0 0;border:none;border-radius:6px;align-items:baseline;gap:8px;padding:4px 8px;display:flex}.S5HVoW_tocItem:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.S5HVoW_tocItem[data-level=\"2\"]{padding-left:18px}.S5HVoW_tocItem[data-level=\"3\"]{padding-left:28px}.S5HVoW_tocItem[data-level=\"4\"]{padding-left:38px}.S5HVoW_tocItem[data-level=\"5\"]{padding-left:48px}.S5HVoW_tocItem[data-level=\"6\"]{padding-left:58px}.S5HVoW_tocItemLevel{font:var(--dsw-font-xxxs-11);color:var(--dsw-alias-label-tertiary);flex:none}.S5HVoW_tocItemText{text-overflow:ellipsis;white-space:nowrap;flex:auto;min-width:0;overflow:hidden}@keyframes S5HVoW_dsh-toc-flash{0%,60%{background:var(--dsw-alias-interactive-bg-hover)}to{background:0 0}}.S5HVoW_tocFlash{border-radius:4px;animation:1.2s ease-out S5HVoW_dsh-toc-flash}";
9895
+ const css$4 = "[data-dsh-panel-host]{z-index:25;pointer-events:none;position:fixed;inset:0;overflow:hidden}[data-dsh-panel-host][data-dsh-panel-host-degraded]{position:absolute;top:0;left:0}.S5HVoW_toggleCluster{top:calc(3px + env(safe-area-inset-top));z-index:45;pointer-events:auto;flex-direction:row;gap:4px;display:flex;position:absolute;right:10px}.S5HVoW_panel:not(.S5HVoW_panelHidden) .S5HVoW_tabBar{padding-right:72px}.S5HVoW_toggleButton{width:28px;height:28px;color:var(--dsw-alias-label-secondary);cursor:pointer;transition:background var(--ds-transition-duration-slow) var(--ds-ease-in-out), color var(--ds-transition-duration-slow) var(--ds-ease-in-out);background:0 0;border:none;border-radius:50%;justify-content:center;align-items:center;display:flex}.S5HVoW_toggleButton:hover:not(:disabled):not([aria-disabled=true]){background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.S5HVoW_toggleButton:disabled,.S5HVoW_toggleButton[aria-disabled=true]{opacity:.4;cursor:default}.S5HVoW_panel{box-sizing:border-box;z-index:40;pointer-events:auto;background:var(--dsw-alias-bg-layer-1);border-left:1px solid var(--dsw-alias-border-l2);padding-bottom:env(safe-area-inset-bottom);transition:transform var(--ds-transition-duration-slow) var(--ds-ease-in-out), width var(--ds-transition-duration-slow) var(--ds-ease-in-out);flex-direction:column;display:flex;position:absolute;top:0;bottom:0;right:0}.S5HVoW_panelHidden{pointer-events:none;visibility:hidden;transition:transform var(--ds-transition-duration-slow) var(--ds-ease-in-out), width var(--ds-transition-duration-slow) var(--ds-ease-in-out), visibility 0s linear var(--ds-transition-duration-slow);transform:translate(102%)}.S5HVoW_panel[data-dragging]{transition:none}.S5HVoW_panelResize{cursor:col-resize;z-index:2;touch-action:none;width:8px;position:absolute;top:0;bottom:0;left:-4px}.S5HVoW_panelResizeActive{background:var(--dsw-alias-interactive-bg-hover-accent)}.S5HVoW_panelBody{flex:1;min-width:0;min-height:0;display:flex}.S5HVoW_panel{contain:layout style}body[data-dsh-sidebar-dragging] .S5HVoW_panel{will-change:transform}.S5HVoW_floatWindow{z-index:42;pointer-events:auto;background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l2);box-shadow:var(--dsw-shadow-lv3);contain:layout style;border-radius:8px;flex-direction:column;display:flex;position:absolute;overflow:hidden}.S5HVoW_floatWindowDragging{will-change:left, top, width, height}.S5HVoW_floatHeader{height:34px;font:var(--dsw-font-xxs-12);color:var(--dsw-alias-label-secondary);background:var(--dsw-alias-bg-layer-1);border-bottom:1px solid var(--dsw-alias-border-l1);cursor:grab;user-select:none;flex:none;align-items:center;gap:4px;padding:0 4px 0 10px;display:flex}.S5HVoW_floatWindowDragging .S5HVoW_floatHeader{cursor:grabbing}.S5HVoW_floatTitle{text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;overflow:hidden}.S5HVoW_floatClose{width:18px;height:18px;color:var(--dsw-alias-label-tertiary);cursor:pointer;background:0 0;border:none;border-radius:4px;flex:none;justify-content:center;align-items:center;padding:0;display:inline-flex}.S5HVoW_floatClose:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.S5HVoW_floatContent{flex-direction:column;flex:1;min-width:0;min-height:0;display:flex;overflow:hidden}.S5HVoW_floatResize{z-index:2;cursor:nwse-resize;touch-action:none;width:14px;height:14px;position:absolute;bottom:0;right:0}.S5HVoW_floatResize:hover{background:var(--dsw-alias-interactive-bg-hover-accent)}.S5HVoW_pane[data-dsh-float-dock-over]{outline:2px dashed var(--dsw-alias-interactive-bg-hover-accent);outline-offset:-2px}.S5HVoW_floatDropHint{z-index:46;pointer-events:none;border:2px dashed var(--dsw-alias-interactive-bg-hover-accent);background:color-mix(in srgb, var(--dsw-alias-interactive-bg-hover-accent) 12%, transparent);border-radius:8px;justify-content:center;align-items:center;display:flex;position:absolute}.S5HVoW_floatDropHintLabel{font:var(--dsw-font-xxs-12);color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l2);border-radius:999px;padding:4px 12px}.S5HVoW_toggleCluster,.S5HVoW_toggleButton,.S5HVoW_tabBar,.S5HVoW_floatHeader{-webkit-app-region:no-drag}body[data-dsh-title-bar-compat] .S5HVoW_toggleCluster{top:calc(var(--dsh-title-bar-strip,40px) + 3px)}body[data-dsh-title-bar-compat] .S5HVoW_panel{padding-top:var(--dsh-title-bar-strip,40px)}.S5HVoW_iconButton{width:28px;height:28px;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;border-radius:50%;flex:none;justify-content:center;align-items:center;padding:0;display:inline-flex}.S5HVoW_iconButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.S5HVoW_iconButton:disabled{opacity:.4;cursor:default}.S5HVoW_workbench,.S5HVoW_split{flex:1;min-width:0;min-height:0;display:flex}.S5HVoW_splitRow{flex-direction:row}.S5HVoW_splitCol{flex-direction:column}.S5HVoW_splitChild{display:flex;position:relative;overflow:hidden}.S5HVoW_divider{z-index:3;touch-action:none;flex:none;position:relative}.S5HVoW_dividerRow:after,.S5HVoW_dividerCol:after{content:\"\";background:var(--dsw-alias-border-l2);transition:background var(--ds-transition-duration-slow) var(--ds-ease-in-out);position:absolute}.S5HVoW_dividerRow{cursor:col-resize;width:7px;margin:0 -2px}.S5HVoW_dividerRow:after{width:1px;top:0;bottom:0;left:50%;transform:translate(-50%)}.S5HVoW_dividerCol{cursor:row-resize;height:7px;margin:-2px 0}.S5HVoW_dividerCol:after{height:1px;top:50%;left:0;right:0;transform:translateY(-50%)}.S5HVoW_divider:hover:after,.S5HVoW_dividerActive:after{background:var(--dsw-alias-interactive-bg-hover-accent)}.S5HVoW_pane{background:var(--dsw-alias-bg-base);flex-direction:column;flex:1;min-width:0;min-height:0;display:flex;position:relative}.S5HVoW_paneDrop{outline:1px solid var(--dsw-alias-interactive-bg-hover-accent);outline-offset:-1px}.S5HVoW_dropOverlay{z-index:6;pointer-events:none;background:var(--dsw-alias-interactive-bg-hover-accent);opacity:.5;position:absolute}.S5HVoW_dropLeft{width:25%;top:0;bottom:0;left:0}.S5HVoW_dropRight{width:25%;top:0;bottom:0;right:0}.S5HVoW_dropUp{height:25%;top:0;left:0;right:0}.S5HVoW_dropDown{height:25%;bottom:0;left:0;right:0}.S5HVoW_dropCenter{outline:2px dashed var(--dsw-alias-interactive-bg-hover-accent);outline-offset:-2px;background:0 0;inset:25%}.S5HVoW_paneContent{flex-direction:column;flex:1;min-height:0;display:flex;overflow:hidden}.S5HVoW_paneTab{flex-direction:column;flex:1;min-height:0;display:flex}.S5HVoW_paneTabHidden{display:none}.S5HVoW_paneEmptyCards{flex:1;grid-template-columns:repeat(auto-fill,minmax(140px,1fr));align-content:start;gap:8px;min-height:0;padding:12px;display:grid;overflow:hidden}.S5HVoW_paneCard{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1);min-width:0;color:var(--dsw-alias-label-secondary);font:var(--dsw-font-xxs-strong-12);cursor:pointer;text-align:center;border-radius:8px;flex-direction:column;justify-content:center;align-items:center;gap:6px;padding:12px 8px;display:flex}.S5HVoW_paneCard:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-border-l2)}.S5HVoW_paneCard:disabled{opacity:.45;cursor:default}.S5HVoW_tabBar{border-bottom:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1);flex:none;align-items:stretch;height:34px;display:flex}.S5HVoW_tabBarDrop{outline:1px dashed var(--dsw-alias-interactive-bg-hover-accent);outline-offset:-1px}.S5HVoW_tabList{scrollbar-width:none;flex:1;min-width:0;display:flex;overflow-x:auto}.S5HVoW_tabList::-webkit-scrollbar{display:none}.S5HVoW_tab{min-width:64px;max-width:160px;font:var(--dsw-font-xxs-12);color:var(--dsw-alias-label-secondary);border-right:1px solid var(--dsw-alias-border-l1);cursor:pointer;user-select:none;background:0 0;flex:none;align-items:center;gap:4px;padding:0 4px 0 10px;display:flex}.S5HVoW_tab:hover{background:var(--dsw-alias-interactive-bg-hover)}.S5HVoW_tabActive{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-interactive-bg-active)}.S5HVoW_tabTitle{text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;overflow:hidden}.S5HVoW_tabBadge{min-width:16px;height:15px;font:var(--dsw-font-xxxs-strong-11);background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-brand-primary);border-radius:8px;flex:none;justify-content:center;align-items:center;padding:0 4px;display:inline-flex}.S5HVoW_tabClose{width:18px;height:18px;color:var(--dsw-alias-label-tertiary);cursor:pointer;background:0 0;border:none;border-radius:4px;flex:none;justify-content:center;align-items:center;padding:0;display:inline-flex}.S5HVoW_tabClose:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.S5HVoW_tabBarPlus{background:var(--dsw-alias-bg-layer-1);width:22px;height:22px;color:var(--dsw-alias-label-tertiary);cursor:pointer;border:none;border-radius:5px;flex:none;justify-content:center;align-self:center;align-items:center;margin:0 6px;padding:0;display:inline-flex;position:sticky;right:0}.S5HVoW_tabBarPlus:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.S5HVoW_pinnedTab{color:var(--dsw-alias-label-tertiary);font-style:italic}.S5HVoW_pinnedTab:hover{color:var(--dsw-alias-label-secondary)}.S5HVoW_explorer{flex-direction:column;flex:1;min-height:0;display:flex}.S5HVoW_explorerHeader{flex:none;justify-content:space-between;align-items:center;gap:8px;height:36px;padding:0 8px 0 12px;display:flex}.S5HVoW_explorerRoot{font:var(--dsw-font-s-14);color:var(--dsw-alias-label-secondary);text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.S5HVoW_explorerBody{flex:1;min-height:0;padding:4px 8px 8px;overflow:hidden auto}.S5HVoW_explorerRow{box-sizing:border-box;width:100%;max-width:100%;height:34px;font:var(--dsw-font-s-14);color:var(--dsw-alias-label-primary);text-align:left;cursor:pointer;white-space:nowrap;animation:S5HVoW_dsh-row-in .15s var(--ds-ease-in-out);background:0 0;border:none;border-radius:8px;align-items:center;gap:6px;padding:0 8px;display:flex}.S5HVoW_explorerRow:hover{background:var(--dsw-alias-interactive-bg-hover)}.S5HVoW_explorerRowRevealed{background:color-mix(in srgb, var(--dsw-alias-interactive-bg-hover-accent) 18%, transparent);box-shadow:inset 2px 0 0 var(--dsw-alias-interactive-bg-hover-accent)}.S5HVoW_explorerDir{font:var(--dsw-font-s-strong-14)}.S5HVoW_explorerHidden{opacity:.45}.S5HVoW_explorerSymlink{color:var(--dsw-alias-label-tertiary);flex:none}.S5HVoW_explorerBroken .S5HVoW_explorerName{color:var(--dsw-alias-state-error-primary)}.S5HVoW_explorerName{text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}.S5HVoW_explorerRef{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-2);height:20px;color:var(--dsw-alias-label-tertiary);font:var(--dsw-font-xxxs-strong-11);cursor:pointer;border-radius:999px;flex:none;align-items:center;padding:0 8px;display:none}.S5HVoW_explorerRef:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.S5HVoW_explorerRow:hover .S5HVoW_explorerRef,.S5HVoW_explorerRow:focus-within .S5HVoW_explorerRef{display:inline-flex}.S5HVoW_explorerCopied{font:var(--dsw-font-xxxs-11);color:var(--dsw-alias-label-tertiary);flex:none}.S5HVoW_explorerError{font:var(--dsw-font-xxs-12);color:var(--dsw-alias-state-error-primary);cursor:default}@keyframes S5HVoW_dsh-row-in{0%{opacity:0}}.S5HVoW_explorerEmpty{font:var(--dsw-font-xxs-12);color:var(--dsw-alias-label-tertiary);text-align:center;padding:16px}.S5HVoW_explorerRowDropTarget{background:var(--dsw-alias-interactive-bg-hover);outline:1px dashed var(--dsw-alias-interactive-bg-hover-accent);outline-offset:-1px}.S5HVoW_uploadDropZone{z-index:1001;pointer-events:none;border:2px dashed var(--dsw-alias-interactive-bg-hover-accent);box-shadow:0 0 0 200vmax var(--dsw-alias-bg-mask-drop);animation:S5HVoW_dsh-row-in .15s var(--ds-ease-in-out);border-radius:10px;justify-content:center;align-items:flex-start;padding:12px;display:flex;position:fixed}.S5HVoW_uploadDropHero{flex-direction:column;align-items:center;gap:10px;max-width:100%;padding-top:8px;display:flex}.S5HVoW_uploadDropZonePill{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-2);max-width:100%;box-shadow:var(--dsw-shadow-lv2);color:var(--dsw-alias-label-primary);font:var(--dsw-font-xxs-strong-12);border-radius:999px;align-items:center;gap:6px;padding:6px 12px;display:flex}.S5HVoW_uploadDropZoneText{white-space:nowrap;text-overflow:ellipsis;overflow:hidden}.S5HVoW_uploadDropChatHint{z-index:1002;pointer-events:none;animation:S5HVoW_dsh-row-in .15s var(--ds-ease-in-out);justify-content:center;align-items:center;padding:24px;display:flex;position:fixed;top:0;bottom:0;left:0}.S5HVoW_uploadDropChatCard{text-align:center;max-width:100%;color:var(--dsw-alias-label-primary);font:var(--dsw-font-s-strong-14);flex-direction:column;align-items:center;gap:12px;display:flex}.S5HVoW_uploadOverlay{z-index:30;background:var(--dsw-alias-bg-mask-1);backdrop-filter:var(--dsw-mask-blur);animation:S5HVoW_dsh-row-in .15s var(--ds-ease-in-out);justify-content:center;align-items:center;display:flex;position:absolute;inset:0}.S5HVoW_uploadOverlayCard{border:1px solid var(--dsw-alias-border-inverted);background:var(--dsw-alias-bg-layer-2);min-width:280px;max-width:min(420px,100% - 48px);box-shadow:var(--dsw-shadow-lv3);border-radius:24px;flex-direction:column;gap:12px;padding:20px 24px;display:flex}.S5HVoW_uploadOverlayTitle{font:var(--dsw-font-s-strong-14);color:var(--dsw-alias-label-primary);align-items:center;gap:8px;display:flex}.S5HVoW_uploadOverlayTitle>svg{flex:none}.S5HVoW_uploadOverlayTitle>span{white-space:nowrap;text-overflow:ellipsis;min-width:0;overflow:hidden}.S5HVoW_uploadOverlayProgress{background:var(--dsw-alias-border-l2);border-radius:3px;height:6px;overflow:hidden}.S5HVoW_uploadOverlayProgressFill{background:var(--dsw-alias-interactive-bg-hover-accent);height:100%;transition:width .15s var(--ds-ease-in-out);border-radius:3px}.S5HVoW_uploadOverlayStatus{min-height:1em;font:var(--dsw-font-xxs-12);font-variant-numeric:tabular-nums;color:var(--dsw-alias-label-tertiary);white-space:nowrap;text-overflow:ellipsis;overflow:hidden}.S5HVoW_uploadOverlayCancel{border:1px solid var(--dsw-alias-border-l2);height:28px;color:var(--dsw-alias-label-primary);font:var(--dsw-font-xxs-strong-12);cursor:pointer;background:0 0;border-radius:8px;align-self:flex-end;padding:0 14px}.S5HVoW_uploadOverlayCancel:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover);border-color:var(--dsw-alias-border-l2)}.S5HVoW_uploadOverlayCancel:disabled{opacity:.4;cursor:default}.S5HVoW_editor{flex-direction:column;flex:1;min-height:0;display:flex}.S5HVoW_editorHeader{border-bottom:1px solid var(--dsw-alias-border-l1);flex:none;align-items:center;gap:6px;padding:6px 8px;display:flex}.S5HVoW_editorTitle{min-width:0;font:var(--dsw-font-xxs-strong-12);color:var(--dsw-alias-label-secondary);text-overflow:ellipsis;white-space:nowrap;flex:1;overflow:hidden}.S5HVoW_editorPathInput{box-sizing:border-box;border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1);min-width:0;height:28px;color:var(--dsw-alias-label-primary);font:var(--dsw-font-xxs-12);border-radius:6px;flex:1;padding:0 10px}.S5HVoW_editorPathInput:focus{border-color:var(--dsw-alias-border-l2);outline:none}.S5HVoW_editorTreeToggleActive{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-interactive-bg-active)}.S5HVoW_editorBody{flex:1;min-height:0;display:flex}.S5HVoW_editorMain{flex-direction:column;flex:1;min-width:0;min-height:0;display:flex}.S5HVoW_editorTreeDock{border-left:1px solid var(--dsw-alias-border-l1);flex:none;min-height:0;display:flex;position:relative}.S5HVoW_editorTreeResize{cursor:col-resize;touch-action:none;z-index:3;width:6px;position:absolute;top:0;bottom:0;left:0}.S5HVoW_editorTreeResize:hover{background:var(--dsw-alias-border-l2)}.S5HVoW_editorTreePanel{flex-direction:column;flex:1;min-width:0;min-height:0;display:flex;position:relative}.S5HVoW_editorTreePanelFull{flex:1}.S5HVoW_editorTreeSearch{border-bottom:1px solid var(--dsw-alias-border-l1);flex:none;align-items:center;gap:6px;padding:6px 8px;display:flex}.S5HVoW_editorSearchInput{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1);min-width:0;height:26px;color:var(--dsw-alias-label-primary);font:var(--dsw-font-xxs-12);border-radius:6px;flex:1;padding:0 10px}.S5HVoW_editorSearchInput:focus{border-color:var(--dsw-alias-border-l2);outline:none}.S5HVoW_editorSearchHint{font:var(--dsw-font-xxs-12);color:var(--dsw-alias-label-tertiary);padding:8px 12px}.S5HVoW_editorSearchResult{width:100%;color:var(--dsw-alias-label-primary);font:var(--dsw-font-xxs-12);text-align:left;cursor:pointer;text-overflow:ellipsis;white-space:nowrap;background:0 0;border:none;border-radius:6px;padding:4px 8px;display:block;overflow:hidden}.S5HVoW_editorSearchResult:hover{background:var(--dsw-alias-interactive-bg-hover)}.S5HVoW_editorStatus{font:var(--dsw-font-xxxs-11);color:var(--dsw-alias-label-tertiary)}.S5HVoW_editorStatusError{color:var(--dsw-alias-state-error-primary)}.S5HVoW_dirtyDot{background:var(--dsw-alias-state-warn-primary);border-radius:50%;flex:none;width:7px;height:7px}.S5HVoW_editorPlaceholder{font:var(--dsw-font-xxs-12);color:var(--dsw-alias-label-tertiary);text-align:center;flex:1;justify-content:center;align-items:center;padding:16px;display:flex}.S5HVoW_orphanedType{opacity:.7;overflow-wrap:anywhere;margin-top:8px;font-size:12px;display:block}.S5HVoW_editorBinary{text-align:center;flex-direction:column;flex:1;justify-content:center;align-items:center;gap:12px;padding:24px 16px;display:flex}.S5HVoW_editorBinaryNotice{font:var(--dsw-font-xxs-12);color:var(--dsw-alias-label-tertiary)}.S5HVoW_editorDownloadLink{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary);font:var(--dsw-font-xxs-strong-12);cursor:pointer;transition:background var(--ds-transition-duration-slow) var(--ds-ease-in-out), border-color var(--ds-transition-duration-slow) var(--ds-ease-in-out);border-radius:6px;align-items:center;gap:6px;padding:6px 14px;text-decoration:none;display:inline-flex}.S5HVoW_editorDownloadLink:hover{background:var(--dsw-alias-interactive-bg-hover);border-color:var(--dsw-alias-border-l2)}.S5HVoW_editorError{font:var(--dsw-font-xxs-12);color:var(--dsw-alias-state-error-primary);padding:12px 16px}.S5HVoW_editorBanner{font:var(--dsw-font-xxxs-11);color:var(--dsw-alias-state-warn-label);background:var(--dsw-alias-state-warn-tertiary);flex:none;padding:4px 8px}.S5HVoW_sandboxStatus{font:var(--dsw-font-xxxs-11);flex:none;align-items:center;gap:8px;padding:4px 10px;display:flex}.S5HVoW_sandboxStatusOn{color:var(--dsw-alias-label-secondary);background:var(--dsw-alias-bg-layer-1);border-bottom:1px solid var(--dsw-alias-border-l1)}.S5HVoW_sandboxStatusOff{color:var(--dsw-alias-state-error-primary);background:color-mix(in srgb, var(--dsw-alias-state-error-primary) 10%, transparent);border-bottom:1px solid color-mix(in srgb, var(--dsw-alias-state-error-primary) 45%, transparent)}.S5HVoW_sandboxDot{background:var(--dsw-alias-state-success-primary);border-radius:50%;flex:none;width:6px;height:6px}.S5HVoW_sandboxStatusOff .S5HVoW_sandboxDot{background:var(--dsw-alias-state-error-primary)}.S5HVoW_sandboxStatusText{text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;overflow:hidden}.S5HVoW_sandboxAction{border:1px solid var(--dsw-alias-border-l2);font:inherit;color:inherit;cursor:pointer;background:0 0;border-radius:6px;flex:none;padding:2px 8px}.S5HVoW_sandboxAction:hover{background:var(--dsw-alias-interactive-bg-hover)}.S5HVoW_browser{flex-direction:column;flex:1;min-height:0;display:flex}.S5HVoW_browserBar{border-bottom:1px solid var(--dsw-alias-border-l1);flex:none;align-items:center;gap:4px;padding:6px 8px;display:flex}.S5HVoW_browserInput{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1);min-width:0;height:28px;color:var(--dsw-alias-label-primary);font:var(--dsw-font-xxs-12);border-radius:6px;flex:1;padding:0 10px}.S5HVoW_browserInput:focus{border-color:var(--dsw-alias-border-l2);outline:none}.S5HVoW_browserMessage{font:var(--dsw-font-xxxs-11);color:var(--dsw-alias-state-warn-label);background:var(--dsw-alias-state-warn-tertiary);flex:none;padding:4px 12px}.S5HVoW_browserFrame{background:var(--dsw-alias-bg-base);border:none;flex:1;width:100%;min-height:0}.S5HVoW_browserStart{text-align:center;min-height:0;font:var(--dsw-font-xs-13);color:var(--dsw-alias-label-tertiary);flex:1;justify-content:center;align-items:center;padding:20px;display:flex}.S5HVoW_browserBlocked{text-align:center;min-height:0;color:var(--dsw-alias-state-warn-primary);flex-direction:column;flex:1;justify-content:center;align-items:center;gap:6px;padding:24px;display:flex}.S5HVoW_browserBlockedTitle{font:var(--dsw-font-xxs-strong-12);color:var(--dsw-alias-label-primary)}.S5HVoW_browserBlockedDesc{max-width:280px;font:var(--dsw-font-xxxs-11);color:var(--dsw-alias-label-secondary)}.S5HVoW_browserBlockedActions{gap:8px;margin-top:6px;display:flex}.S5HVoW_browserBlockedButton{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-primary);font:var(--dsw-font-xxxs-11);cursor:pointer;border-radius:6px;padding:4px 12px}.S5HVoW_browserBlockedButton:hover{background:var(--dsw-alias-interactive-bg-hover)}.S5HVoW_editorCm{background:0 0;flex:1;min-height:0;overflow:hidden}.S5HVoW_editorCm .cm-editor{height:100%}.S5HVoW_editorCm .cm-scroller{padding:12px 16px}.S5HVoW_editorCm .cm-editor.cm-focused{outline:none}.S5HVoW_selectionPopup{z-index:60;border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-2);height:28px;color:var(--dsw-alias-label-primary);font:var(--dsw-font-xxxs-strong-11);white-space:nowrap;cursor:pointer;border-radius:6px;align-items:center;padding:0 10px;display:inline-flex;position:fixed;transform:translate(-50%,calc(-100% - 8px))}.S5HVoW_selectionPopup:hover{background:var(--dsw-alias-interactive-bg-hover)}.S5HVoW_terminalWrap{background:var(--dsw-alias-bg-base);flex-direction:column;flex:1;min-height:0;display:flex;position:relative}.S5HVoW_terminal{flex:1;min-height:0;padding:6px 4px 6px 8px}.S5HVoW_terminal .xterm{height:100%}.S5HVoW_terminalBanner{font:var(--dsw-font-xxxs-11);color:var(--dsw-alias-state-warn-label);background:var(--dsw-alias-state-warn-tertiary);flex-wrap:wrap;flex:none;align-items:center;gap:8px;padding:3px 10px;display:flex}.S5HVoW_terminalBannerUrl{word-break:break-all;opacity:.85;flex-basis:100%;font-family:ui-monospace,SFMono-Regular,Menlo,monospace}.S5HVoW_boundaryError{z-index:50;background:var(--dsw-alias-bg-layer-1);border-left:1px solid var(--dsw-alias-border-l2);font:var(--dsw-font-xxs-12);color:var(--dsw-alias-state-error-primary);flex-direction:column;align-items:flex-start;gap:8px;padding:16px;display:flex;position:fixed;top:0;bottom:0;right:0;overflow:auto}.S5HVoW_terminalRetry{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-secondary);font:var(--dsw-font-xxxs-strong-11);cursor:pointer;border-radius:999px;flex:none;padding:1px 8px}.S5HVoW_terminalRetry:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.S5HVoW_terminalDepsBanner{font:var(--dsw-font-xxs-12);color:var(--dsw-alias-state-warn-label);background:var(--dsw-alias-state-warn-tertiary);flex-direction:column;flex:none;gap:6px;padding:10px;display:flex}.S5HVoW_terminalDepsTitle{font:var(--dsw-font-xxs-strong-12);color:var(--dsw-alias-state-warn-primary)}.S5HVoW_terminalDepsHint{opacity:.9}.S5HVoW_terminalDepsCommandRow{align-items:flex-start;gap:8px;display:flex}.S5HVoW_terminalRepairCommand{white-space:pre-wrap;word-break:break-all;user-select:text;min-width:0;color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l2);border-radius:4px;flex:1;max-height:160px;margin:0;padding:6px 8px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:11px;line-height:1.5;overflow:auto}.S5HVoW_terminalDepsNote{opacity:.85}.S5HVoW_terminalDepsActions{align-items:center;gap:8px;display:flex}.S5HVoW_tabBoundaryError{min-height:0;font:var(--dsw-font-xxs-12);color:var(--dsw-alias-state-error-primary);flex-direction:column;flex:1;align-items:flex-start;gap:8px;padding:12px 16px;display:flex;overflow:auto}.S5HVoW_git{flex-direction:column;flex:1;min-width:0;min-height:0;display:flex;overflow:hidden auto}.S5HVoW_gitHeader{flex:none;align-items:center;gap:8px;height:36px;padding:0 8px 0 12px;display:flex}.S5HVoW_gitWorktreeRow{flex:none;align-items:center;gap:8px;padding:6px 8px 0 12px;display:flex}.S5HVoW_gitWorktreeLabel{color:var(--dsw-alias-label-tertiary);font:var(--dsw-font-xxxs-11);flex:none}.S5HVoW_gitBranchSelect{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-base);min-width:0;height:26px;color:var(--dsw-alias-label-primary);font:var(--dsw-font-xxs-12);border-radius:6px;flex:1;padding:0 6px}.S5HVoW_gitSection{border-top:1px solid var(--dsw-alias-border-l1)}.S5HVoW_gitSectionHeader{font:var(--dsw-font-xxxs-strong-11);color:var(--dsw-alias-label-tertiary);text-transform:uppercase;justify-content:space-between;align-items:center;padding:6px 12px 4px;display:flex}.S5HVoW_gitLink{font:var(--dsw-font-xxxs-11);color:var(--dsw-alias-brand-primary);cursor:pointer;background:0 0;border:none;padding:0}.S5HVoW_gitLink:hover:not(:disabled){text-decoration:underline}.S5HVoW_gitLink:disabled{opacity:.4;cursor:default}.S5HVoW_gitRow{min-height:34px;animation:S5HVoW_dsh-row-in .15s var(--ds-ease-in-out);border-radius:8px;align-items:center;gap:6px;margin:0 6px;padding:0 8px;display:flex}.S5HVoW_gitRow:hover{background:var(--dsw-alias-interactive-bg-hover)}.S5HVoW_gitRowSelected{background:var(--dsw-alias-interactive-bg-active)}.S5HVoW_gitRowMain{cursor:pointer;text-align:left;background:0 0;border:none;flex:1;align-items:center;gap:8px;min-width:0;padding:3px 0;display:flex}.S5HVoW_gitBadge{width:20px;height:16px;font:var(--dsw-font-xxxs-strong-11);background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-secondary);border-radius:4px;flex:none;justify-content:center;align-items:center;display:inline-flex}.S5HVoW_gitName{text-overflow:ellipsis;white-space:nowrap;min-width:0;font:var(--dsw-font-s-14);color:var(--dsw-alias-label-primary);flex:1;overflow:hidden}.S5HVoW_gitEmpty{font:var(--dsw-font-xxs-12);color:var(--dsw-alias-label-tertiary);padding:4px 12px 8px}.S5HVoW_gitPlaceholder{font:var(--dsw-font-xxs-12);color:var(--dsw-alias-label-tertiary);text-align:center;padding:16px}.S5HVoW_gitError{font:var(--dsw-font-xxs-12);color:var(--dsw-alias-state-error-primary);white-space:pre-wrap;padding:8px 12px}.S5HVoW_gitDiff{border-top:1px solid var(--dsw-alias-border-l1);padding:8px}.S5HVoW_gitDiffTab{flex-direction:column;flex:1;min-width:0;min-height:0;display:flex;overflow:hidden auto}.S5HVoW_gitDiffTabHeader{border-bottom:1px solid var(--dsw-alias-border-l1);flex:none;align-items:center;gap:8px;height:36px;padding:0 8px 0 12px;display:flex}.S5HVoW_gitDiffTabTitle{text-overflow:ellipsis;white-space:nowrap;min-width:0;font:var(--dsw-font-xxs-strong-12);color:var(--dsw-alias-label-primary);flex:1;overflow:hidden}.S5HVoW_gitDiffFile{width:100%;color:inherit;text-align:left;cursor:pointer;background:0 0;border:0;align-items:baseline;gap:6px;padding:8px 2px 2px;display:flex}.S5HVoW_gitDiffFile:disabled{cursor:default}.S5HVoW_gitDiffFile:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}.S5HVoW_gitDiffFileChevron{color:var(--dsw-alias-label-tertiary);flex:none;transform:rotate(0)}.S5HVoW_gitDiffFileChevronExpanded{transform:rotate(90deg)}.S5HVoW_gitDiffFilePath{font:var(--dsw-font-xxs-strong-12);color:var(--dsw-alias-label-primary);text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.S5HVoW_gitDiffFileOld{font:var(--dsw-font-xxxs-11);color:var(--dsw-alias-label-tertiary);text-overflow:ellipsis;white-space:nowrap;flex:none;max-width:40%;overflow:hidden}.S5HVoW_gitDiffFileTag{border:1px solid var(--dsw-alias-border-l2);font:var(--dsw-font-xxxs-strong-11);color:var(--dsw-alias-label-secondary);border-radius:999px;flex:none;padding:0 6px}.S5HVoW_gitDiffHunk{font:var(--dsw-font-markdown-code-block-small);color:var(--dsw-alias-label-tertiary);gap:8px;padding:3px 2px;display:flex}.S5HVoW_gitDiffHunkHeader{color:var(--dsw-alias-label-secondary);flex:none}.S5HVoW_gitDiffHunkSection{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.S5HVoW_gitDiffLine{font:var(--dsw-font-markdown-code-block-small);white-space:pre-wrap;overflow-wrap:anywhere;align-items:stretch;min-width:0;line-height:20px;display:flex}.S5HVoW_gitDiffNum{text-align:right;width:36px;color:var(--dsw-alias-label-tertiary);user-select:none;flex:none;padding-right:8px}.S5HVoW_gitDiffCode{flex:1;min-width:0;overflow:visible}.S5HVoW_gitDiffCtx{color:var(--dsw-alias-label-primary)}.S5HVoW_gitDiffDel{color:var(--dsw-alias-state-error-primary);background:color-mix(in srgb, var(--dsw-alias-state-error-primary) 12%, transparent)}.S5HVoW_gitDiffAdd{color:var(--dsw-alias-state-success-primary);background:color-mix(in srgb, var(--dsw-alias-state-success-primary) 12%, transparent)}.S5HVoW_gitDiffMeta{padding-left:2px}.S5HVoW_gitDiffMetaText{font:var(--dsw-font-xxxs-11);color:var(--dsw-alias-label-tertiary);font-style:italic}.S5HVoW_gitDiffExpand{width:100%;font:var(--dsw-font-xxs-12);color:var(--dsw-alias-brand-primary);cursor:pointer;text-align:center;background:0 0;border:none;margin:4px 0;display:block}.S5HVoW_gitDiffExpand:hover{background:var(--dsw-alias-interactive-bg-hover)}.S5HVoW_gitConfirmDesc{font:var(--dsw-font-s-14);color:var(--dsw-alias-label-primary);white-space:pre-wrap;margin:0}.S5HVoW_gitCommit{border-top:1px solid var(--dsw-alias-border-l1);align-items:center;gap:6px;padding:8px 12px;display:flex}.S5HVoW_gitCommitInput{flex:1;min-width:0}.S5HVoW_gitCommitButton{background:var(--dsw-alias-button-primary-fill);height:26px;color:var(--dsw-alias-label-primary-inverted);font:var(--dsw-font-xxs-strong-12);cursor:pointer;border:none;border-radius:6px;flex:none;padding:0 12px}.S5HVoW_gitCommitButton:hover:not(:disabled){background:var(--dsw-alias-button-primary-hover)}.S5HVoW_gitCommitButton:disabled{opacity:.45;cursor:default}.S5HVoW_gitLogRow{cursor:pointer;border-radius:8px;flex-direction:column;gap:2px;padding:5px 12px;display:flex}.S5HVoW_gitLogRow:hover{background:var(--dsw-alias-interactive-bg-hover)}.S5HVoW_gitLogLine1{align-items:baseline;gap:8px;min-width:0;display:flex}.S5HVoW_gitLogHash{font:var(--dsw-font-markdown-code-block-small);color:var(--dsw-alias-label-tertiary);flex:none}.S5HVoW_gitLogLine2{flex-wrap:wrap;align-items:center;gap:6px;min-width:0;display:flex}.S5HVoW_gitLogRef{border:1px solid var(--dsw-alias-border-l2);font:var(--dsw-font-xxxs-strong-11);color:var(--dsw-alias-brand-primary);white-space:nowrap;border-radius:999px;flex:none;padding:0 5px}.S5HVoW_gitLogSubject{text-overflow:ellipsis;white-space:nowrap;min-width:0;font:var(--dsw-font-s-14);color:var(--dsw-alias-label-primary);flex:1;overflow:hidden}.S5HVoW_gitLogMeta{font:var(--dsw-font-xxxs-11);color:var(--dsw-alias-label-tertiary)}.S5HVoW_gitLogMore{border:1px solid var(--dsw-alias-border-l2);width:calc(100% - 24px);font:var(--dsw-font-xxs-12);color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border-radius:6px;margin:4px 12px 8px;padding:6px 0;display:block}.S5HVoW_gitLogMore:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.S5HVoW_gitLogMore:disabled{opacity:.5;cursor:default}.S5HVoW_producedRow{flex-wrap:wrap;align-items:center;gap:8px;padding:4px 0;display:flex}.S5HVoW_producedLabel{font:var(--dsw-font-xxs-12);color:var(--dsw-alias-label-tertiary)}.S5HVoW_producedChip{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-2);max-width:200px;color:var(--dsw-alias-label-secondary);font:var(--dsw-font-xxs-12);cursor:pointer;border-radius:999px;align-items:center;gap:4px;padding:2px 8px;display:inline-flex;overflow:hidden}.S5HVoW_producedChip:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.S5HVoW_producedChip span{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.S5HVoW_producedMore{font:var(--dsw-font-xxs-12);color:var(--dsw-alias-label-tertiary)}.S5HVoW_toggleButton:focus-visible,.S5HVoW_iconButton:focus-visible,.S5HVoW_tab:focus-visible,.S5HVoW_tabClose:focus-visible,.S5HVoW_tabBarPlus:focus-visible,.S5HVoW_paneCard:focus-visible,.S5HVoW_explorerRow:focus-visible,.S5HVoW_explorerRef:focus-visible,.S5HVoW_gitRowMain:focus-visible,.S5HVoW_gitLink:focus-visible,.S5HVoW_gitCommitButton:focus-visible,.S5HVoW_gitLogRow:focus-visible,.S5HVoW_gitLogMore:focus-visible,.S5HVoW_gitDiffFile:focus-visible,.S5HVoW_gitDiffExpand:focus-visible,.S5HVoW_terminalRetry:focus-visible,.S5HVoW_editorDownloadLink:focus-visible{outline:2px solid var(--dsw-alias-interactive-bg-hover-accent);outline-offset:-1px}@media (prefers-reduced-motion:reduce){.S5HVoW_panel,.S5HVoW_panelHidden,.S5HVoW_toggleCluster,.S5HVoW_toggleButton,.S5HVoW_tab,.S5HVoW_tabBarPlus,.S5HVoW_paneCard,.S5HVoW_explorerRow,.S5HVoW_gitRow,.S5HVoW_divider,.S5HVoW_dividerRow:after,.S5HVoW_dividerCol:after{transition:none;animation:none}}@media (width<=767px){.S5HVoW_panel:not(.S5HVoW_panelHidden) .S5HVoW_tabBar{padding-right:40px}.S5HVoW_tab{min-width:48px;max-width:128px}}.S5HVoW_openWithLabel{align-items:center;gap:8px;width:100%;min-width:0;display:flex}.S5HVoW_openWithName{text-overflow:ellipsis;white-space:nowrap;flex:auto;min-width:0;overflow:hidden}.S5HVoW_openWithChevron{color:var(--dsw-alias-label-tertiary);flex:none}.S5HVoW_openWithPin{width:20px;height:20px;color:var(--dsw-alias-label-tertiary);cursor:pointer;border-radius:6px;flex:none;justify-content:center;align-items:center;display:inline-flex}.S5HVoW_openWithPin:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.S5HVoW_openWithPinActive{color:var(--dsw-alias-state-business-primary)}@keyframes S5HVoW_dsh-toc-flash{0%,60%{background:var(--dsw-alias-interactive-bg-hover)}to{background:0 0}}.S5HVoW_browserLive{flex-direction:column;gap:6px;padding:8px 10px;display:flex;position:absolute;inset:0;overflow:hidden}.S5HVoW_browserLiveStatus{opacity:.75;align-items:center;gap:8px;font-size:12px;display:flex}.S5HVoW_browserLiveCanvas{object-fit:contain;border:1px solid var(--dsw-alias-border-l,#80808040);cursor:crosshair;background:#fff;border-radius:8px;flex:1;width:100%;min-height:0}.S5HVoW_browserLiveTarget{max-width:260px;font-size:12px}";
9960
9896
  const tagId$4 = "dsh-external/dsh-coding-sidebar/sidebar.module.css";
9961
9897
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$4) + "]") === null) {
9962
9898
  const tag = document.createElement("style");
@@ -9966,241 +9902,207 @@ window.__ModuleLoader__.load({
9966
9902
  document.head.appendChild(tag);
9967
9903
  }
9968
9904
  var sidebar_module_css_default = {
9969
- "paneEmptyCards": "S5HVoW_paneEmptyCards",
9970
- "panelResize": "S5HVoW_panelResize",
9971
- "producedMore": "S5HVoW_producedMore",
9972
- "divider": "S5HVoW_divider",
9973
- "editorTreeDock": "S5HVoW_editorTreeDock",
9974
- "editorPdfToolbar": "S5HVoW_editorPdfToolbar",
9975
- "tabClose": "S5HVoW_tabClose",
9976
- "panelHidden": "S5HVoW_panelHidden",
9977
- "paneContent": "S5HVoW_paneContent",
9978
- "explorerHidden": "S5HVoW_explorerHidden",
9979
- "editorHtmlBlock": "S5HVoW_editorHtmlBlock",
9980
- "editorPdf": "S5HVoW_editorPdf",
9981
- "editorPdfFrameBlocked": "S5HVoW_editorPdfFrameBlocked",
9982
- "gitDiffLine": "S5HVoW_gitDiffLine",
9983
- "producedRow": "S5HVoW_producedRow",
9984
- "explorerRowDropTarget": "S5HVoW_explorerRowDropTarget",
9985
- "editorBinary": "S5HVoW_editorBinary",
9986
- "floatHeader": "S5HVoW_floatHeader",
9987
- "editorPdfFrame": "S5HVoW_editorPdfFrame",
9988
- "gitDiffCode": "S5HVoW_gitDiffCode",
9989
- "floatDropHint": "S5HVoW_floatDropHint",
9990
- "dirtyDot": "S5HVoW_dirtyDot",
9991
- "editor": "S5HVoW_editor",
9992
- "gitLogLine2": "S5HVoW_gitLogLine2",
9993
- "tab": "S5HVoW_tab",
9994
- "uploadDropHero": "S5HVoW_uploadDropHero",
9995
- "mermaidModalStage": "S5HVoW_mermaidModalStage",
9996
- "gitLogRef": "S5HVoW_gitLogRef",
9997
- "editorHtml": "S5HVoW_editorHtml",
9998
- "gitBranchSelect": "S5HVoW_gitBranchSelect",
9999
- "tocButton": "S5HVoW_tocButton",
10000
- "floatTitle": "S5HVoW_floatTitle",
10001
- "iconButton": "S5HVoW_iconButton",
9905
+ "toggleButton": "S5HVoW_toggleButton",
10002
9906
  "tabBarDrop": "S5HVoW_tabBarDrop",
10003
- "paneTab": "S5HVoW_paneTab",
10004
- "uploadOverlayProgressFill": "S5HVoW_uploadOverlayProgressFill",
10005
- "gitRowSelected": "S5HVoW_gitRowSelected",
10006
- "tabTitle": "S5HVoW_tabTitle",
10007
- "gitHeader": "S5HVoW_gitHeader",
10008
- "splitCol": "S5HVoW_splitCol",
10009
- "gitDiffMetaText": "S5HVoW_gitDiffMetaText",
10010
- "gitLogRow": "S5HVoW_gitLogRow",
9907
+ "dropOverlay": "S5HVoW_dropOverlay",
9908
+ "sandboxDot": "S5HVoW_sandboxDot",
10011
9909
  "gitDiffFileOld": "S5HVoW_gitDiffFileOld",
10012
- "openWithChevron": "S5HVoW_openWithChevron",
10013
- "mermaidMarkdown": "S5HVoW_mermaidMarkdown",
10014
9910
  "gitLogHash": "S5HVoW_gitLogHash",
10015
- "pane": "S5HVoW_pane",
9911
+ "floatHeader": "S5HVoW_floatHeader",
9912
+ "uploadDropZoneText": "S5HVoW_uploadDropZoneText",
9913
+ "uploadDropChatHint": "S5HVoW_uploadDropChatHint",
9914
+ "gitLogLine2": "S5HVoW_gitLogLine2",
9915
+ "dividerActive": "S5HVoW_dividerActive",
9916
+ "terminalWrap": "S5HVoW_terminalWrap",
9917
+ "explorer": "S5HVoW_explorer",
9918
+ "uploadOverlayProgress": "S5HVoW_uploadOverlayProgress",
9919
+ "uploadDropZone": "S5HVoW_uploadDropZone",
10016
9920
  "browserBlockedActions": "S5HVoW_browserBlockedActions",
9921
+ "floatResize": "S5HVoW_floatResize",
9922
+ "panelBody": "S5HVoW_panelBody",
9923
+ "floatDropHintLabel": "S5HVoW_floatDropHintLabel",
9924
+ "explorerHeader": "S5HVoW_explorerHeader",
9925
+ "gitLink": "S5HVoW_gitLink",
9926
+ "gitDiff": "S5HVoW_gitDiff",
9927
+ "explorerName": "S5HVoW_explorerName",
9928
+ "tabBarPlus": "S5HVoW_tabBarPlus",
9929
+ "editorTreeSearch": "S5HVoW_editorTreeSearch",
9930
+ "terminalDepsBanner": "S5HVoW_terminalDepsBanner",
9931
+ "gitHeader": "S5HVoW_gitHeader",
9932
+ "tabActive": "S5HVoW_tabActive",
9933
+ "gitDiffFilePath": "S5HVoW_gitDiffFilePath",
9934
+ "dropDown": "S5HVoW_dropDown",
9935
+ "uploadOverlay": "S5HVoW_uploadOverlay",
9936
+ "openWithLabel": "S5HVoW_openWithLabel",
9937
+ "browserBar": "S5HVoW_browserBar",
9938
+ "gitConfirmDesc": "S5HVoW_gitConfirmDesc",
9939
+ "explorerRowDropTarget": "S5HVoW_explorerRowDropTarget",
9940
+ "editorPathInput": "S5HVoW_editorPathInput",
9941
+ "editorPlaceholder": "S5HVoW_editorPlaceholder",
10017
9942
  "terminal": "S5HVoW_terminal",
10018
- "editorBinaryNotice": "S5HVoW_editorBinaryNotice",
10019
- "paneDrop": "S5HVoW_paneDrop",
10020
- "toggleCluster": "S5HVoW_toggleCluster",
10021
- "mermaidCode": "S5HVoW_mermaidCode",
9943
+ "terminalRepairCommand": "S5HVoW_terminalRepairCommand",
9944
+ "browserLive": "S5HVoW_browserLive",
9945
+ "gitDiffNum": "S5HVoW_gitDiffNum",
9946
+ "iconButton": "S5HVoW_iconButton",
9947
+ "editorHeader": "S5HVoW_editorHeader",
10022
9948
  "uploadOverlayCard": "S5HVoW_uploadOverlayCard",
10023
- "gitCommitButton": "S5HVoW_gitCommitButton",
10024
- "editorDocxZoomRange": "S5HVoW_editorDocxZoomRange",
10025
- "terminalDepsCommandRow": "S5HVoW_terminalDepsCommandRow",
10026
- "gitLogMore": "S5HVoW_gitLogMore",
10027
- "floatWindowDragging": "S5HVoW_floatWindowDragging",
10028
- "editorTreePanelFull": "S5HVoW_editorTreePanelFull",
10029
- "editorPlaceholder": "S5HVoW_editorPlaceholder",
9949
+ "uploadDropHero": "S5HVoW_uploadDropHero",
9950
+ "paneTab": "S5HVoW_paneTab",
9951
+ "dividerRow": "S5HVoW_dividerRow",
9952
+ "editorBanner": "S5HVoW_editorBanner",
9953
+ "editorBody": "S5HVoW_editorBody",
9954
+ "terminalBanner": "S5HVoW_terminalBanner",
9955
+ "floatContent": "S5HVoW_floatContent",
9956
+ "paneCard": "S5HVoW_paneCard",
9957
+ "uploadDropChatCard": "S5HVoW_uploadDropChatCard",
10030
9958
  "editorDownloadLink": "S5HVoW_editorDownloadLink",
9959
+ "gitWorktreeRow": "S5HVoW_gitWorktreeRow",
9960
+ "gitDiffFileChevron": "S5HVoW_gitDiffFileChevron",
9961
+ "editorMain": "S5HVoW_editorMain",
9962
+ "gitDiffLine": "S5HVoW_gitDiffLine",
9963
+ "browserMessage": "S5HVoW_browserMessage",
9964
+ "gitRowMain": "S5HVoW_gitRowMain",
9965
+ "explorerEmpty": "S5HVoW_explorerEmpty",
9966
+ "terminalDepsCommandRow": "S5HVoW_terminalDepsCommandRow",
9967
+ "gitDiffCode": "S5HVoW_gitDiffCode",
9968
+ "gitDiffCtx": "S5HVoW_gitDiffCtx",
9969
+ "editorTreeDock": "S5HVoW_editorTreeDock",
9970
+ "editorSearchInput": "S5HVoW_editorSearchInput",
9971
+ "editorStatus": "S5HVoW_editorStatus",
9972
+ "producedChip": "S5HVoW_producedChip",
9973
+ "browserInput": "S5HVoW_browserInput",
9974
+ "panelResize": "S5HVoW_panelResize",
9975
+ "floatDropHint": "S5HVoW_floatDropHint",
9976
+ "editorStatusError": "S5HVoW_editorStatusError",
9977
+ "panel": "S5HVoW_panel",
9978
+ "gitDiffMeta": "S5HVoW_gitDiffMeta",
9979
+ "gitDiffMetaText": "S5HVoW_gitDiffMetaText",
9980
+ "terminalRetry": "S5HVoW_terminalRetry",
9981
+ "uploadOverlayTitle": "S5HVoW_uploadOverlayTitle",
9982
+ "gitDiffFileTag": "S5HVoW_gitDiffFileTag",
10031
9983
  "gitCommitInput": "S5HVoW_gitCommitInput",
10032
- "gitLogSubject": "S5HVoW_gitLogSubject",
10033
- "explorerRef": "S5HVoW_explorerRef",
10034
- "floatClose": "S5HVoW_floatClose",
10035
- "explorerError": "S5HVoW_explorerError",
10036
- "mermaidModal": "S5HVoW_mermaidModal",
10037
- "gitPlaceholder": "S5HVoW_gitPlaceholder",
10038
- "browserBlocked": "S5HVoW_browserBlocked",
10039
- "editorTreePanel": "S5HVoW_editorTreePanel",
9984
+ "gitDiffHunkSection": "S5HVoW_gitDiffHunkSection",
10040
9985
  "uploadOverlayStatus": "S5HVoW_uploadOverlayStatus",
10041
- "splitRow": "S5HVoW_splitRow",
10042
- "gitDiffFileChevronExpanded": "S5HVoW_gitDiffFileChevronExpanded",
10043
- "editorSearchResult": "S5HVoW_editorSearchResult",
10044
- "gitRow": "S5HVoW_gitRow",
10045
- "gitEmpty": "S5HVoW_gitEmpty",
10046
- "terminalRetry": "S5HVoW_terminalRetry",
10047
- "gitDiffNum": "S5HVoW_gitDiffNum",
10048
- "floatDropHintLabel": "S5HVoW_floatDropHintLabel",
10049
- "gitLink": "S5HVoW_gitLink",
10050
- "uploadOverlayCancel": "S5HVoW_uploadOverlayCancel",
10051
- "dropOverlay": "S5HVoW_dropOverlay",
10052
- "editorPdfDragShield": "S5HVoW_editorPdfDragShield",
10053
- "dropUp": "S5HVoW_dropUp",
10054
- "editorPptxButton": "S5HVoW_editorPptxButton",
10055
- "browser": "S5HVoW_browser",
10056
- "sandboxStatus": "S5HVoW_sandboxStatus",
10057
- "sandboxStatusText": "S5HVoW_sandboxStatusText",
10058
- "openWithName": "S5HVoW_openWithName",
10059
- "terminalBannerUrl": "S5HVoW_terminalBannerUrl",
9986
+ "gitLogLine1": "S5HVoW_gitLogLine1",
10060
9987
  "pinnedTab": "S5HVoW_pinnedTab",
10061
- "uploadOverlayProgress": "S5HVoW_uploadOverlayProgress",
10062
- "browserFrame": "S5HVoW_browserFrame",
10063
- "uploadOverlayTitle": "S5HVoW_uploadOverlayTitle",
9988
+ "divider": "S5HVoW_divider",
9989
+ "dsh-toc-flash": "S5HVoW_dsh-toc-flash",
9990
+ "paneEmptyCards": "S5HVoW_paneEmptyCards",
9991
+ "orphanedType": "S5HVoW_orphanedType",
9992
+ "browserLiveTarget": "S5HVoW_browserLiveTarget",
9993
+ "dropUp": "S5HVoW_dropUp",
9994
+ "panelResizeActive": "S5HVoW_panelResizeActive",
9995
+ "gitLogMore": "S5HVoW_gitLogMore",
9996
+ "panelHidden": "S5HVoW_panelHidden",
9997
+ "terminalDepsActions": "S5HVoW_terminalDepsActions",
9998
+ "gitLogSubject": "S5HVoW_gitLogSubject",
9999
+ "openWithPin": "S5HVoW_openWithPin",
10064
10000
  "explorerCopied": "S5HVoW_explorerCopied",
10001
+ "explorerDir": "S5HVoW_explorerDir",
10002
+ "gitDiffAdd": "S5HVoW_gitDiffAdd",
10065
10003
  "sandboxStatusOff": "S5HVoW_sandboxStatusOff",
10066
- "toggleButton": "S5HVoW_toggleButton",
10067
- "gitCommit": "S5HVoW_gitCommit",
10004
+ "sandboxStatusText": "S5HVoW_sandboxStatusText",
10005
+ "producedRow": "S5HVoW_producedRow",
10006
+ "openWithChevron": "S5HVoW_openWithChevron",
10007
+ "editorBinaryNotice": "S5HVoW_editorBinaryNotice",
10068
10008
  "gitDiffHunk": "S5HVoW_gitDiffHunk",
10069
- "editorTreeSearch": "S5HVoW_editorTreeSearch",
10070
- "workbench": "S5HVoW_workbench",
10071
- "panelBody": "S5HVoW_panelBody",
10072
- "tocFlash": "S5HVoW_tocFlash",
10073
- "openWithLabel": "S5HVoW_openWithLabel",
10074
- "explorerSymlink": "S5HVoW_explorerSymlink",
10075
- "dsh-row-in": "S5HVoW_dsh-row-in",
10009
+ "gitLogRow": "S5HVoW_gitLogRow",
10010
+ "browserBlocked": "S5HVoW_browserBlocked",
10011
+ "producedLabel": "S5HVoW_producedLabel",
10012
+ "git": "S5HVoW_git",
10013
+ "floatWindow": "S5HVoW_floatWindow",
10076
10014
  "explorerRowRevealed": "S5HVoW_explorerRowRevealed",
10077
- "editorSearchInput": "S5HVoW_editorSearchInput",
10078
- "mermaidInfo": "S5HVoW_mermaidInfo",
10079
- "gitDiffFileTag": "S5HVoW_gitDiffFileTag",
10080
- "explorerDir": "S5HVoW_explorerDir",
10081
- "browserInput": "S5HVoW_browserInput",
10082
- "editorMd": "S5HVoW_editorMd",
10083
- "sandboxStatusOn": "S5HVoW_sandboxStatusOn",
10084
- "mermaidWrap": "S5HVoW_mermaidWrap",
10085
- "editorImage": "S5HVoW_editorImage",
10086
- "sandboxDot": "S5HVoW_sandboxDot",
10087
- "editorStatusError": "S5HVoW_editorStatusError",
10088
- "gitLogMeta": "S5HVoW_gitLogMeta",
10089
- "dropLeft": "S5HVoW_dropLeft",
10090
- "browserBlockedTitle": "S5HVoW_browserBlockedTitle",
10091
- "tocPanel": "S5HVoW_tocPanel",
10092
- "editorCmHidden": "S5HVoW_editorCmHidden",
10093
- "selectionPopup": "S5HVoW_selectionPopup",
10094
- "gitDiffHunkSection": "S5HVoW_gitDiffHunkSection",
10095
- "gitDiffCtx": "S5HVoW_gitDiffCtx",
10096
- "editorImageWrap": "S5HVoW_editorImageWrap",
10097
- "explorerRow": "S5HVoW_explorerRow",
10098
- "editorModeActive": "S5HVoW_editorModeActive",
10099
- "gitDiffFile": "S5HVoW_gitDiffFile",
10100
- "editorStatus": "S5HVoW_editorStatus",
10101
- "explorerHeader": "S5HVoW_explorerHeader",
10102
- "uploadDropZoneText": "S5HVoW_uploadDropZoneText",
10103
- "tabList": "S5HVoW_tabList",
10104
- "explorerEmpty": "S5HVoW_explorerEmpty",
10105
- "gitSection": "S5HVoW_gitSection",
10106
- "tabBarPlus": "S5HVoW_tabBarPlus",
10107
- "explorerBody": "S5HVoW_explorerBody",
10108
- "gitDiffExpand": "S5HVoW_gitDiffExpand",
10109
- "dividerRow": "S5HVoW_dividerRow",
10110
- "editorPdfStage": "S5HVoW_editorPdfStage",
10111
- "producedChip": "S5HVoW_producedChip",
10112
- "editorError": "S5HVoW_editorError",
10113
- "terminalDepsNote": "S5HVoW_terminalDepsNote",
10114
- "floatResize": "S5HVoW_floatResize",
10115
- "uploadDropZonePill": "S5HVoW_uploadDropZonePill",
10116
- "browserBlockedDesc": "S5HVoW_browserBlockedDesc",
10117
- "mermaidModalButton": "S5HVoW_mermaidModalButton",
10118
- "floatContent": "S5HVoW_floatContent",
10119
10015
  "splitChild": "S5HVoW_splitChild",
10120
- "terminalDepsActions": "S5HVoW_terminalDepsActions",
10121
- "dividerActive": "S5HVoW_dividerActive",
10122
- "uploadDropZone": "S5HVoW_uploadDropZone",
10123
- "gitSectionHeader": "S5HVoW_gitSectionHeader",
10124
- "editorBanner": "S5HVoW_editorBanner",
10125
- "browserBar": "S5HVoW_browserBar",
10126
- "gitBadge": "S5HVoW_gitBadge",
10127
- "terminalDepsHint": "S5HVoW_terminalDepsHint",
10128
- "openWithPin": "S5HVoW_openWithPin",
10129
- "tabBoundaryError": "S5HVoW_tabBoundaryError",
10130
- "uploadOverlay": "S5HVoW_uploadOverlay",
10131
- "editorPdfDragShieldActive": "S5HVoW_editorPdfDragShieldActive",
10132
- "tabBar": "S5HVoW_tabBar",
10133
- "sandboxAction": "S5HVoW_sandboxAction",
10134
- "mermaidCopy": "S5HVoW_mermaidCopy",
10135
- "tabBadge": "S5HVoW_tabBadge",
10136
- "browserStart": "S5HVoW_browserStart",
10137
- "git": "S5HVoW_git",
10138
- "gitLogLine1": "S5HVoW_gitLogLine1",
10139
- "editorMain": "S5HVoW_editorMain",
10140
- "editorTreeToggleActive": "S5HVoW_editorTreeToggleActive",
10141
- "producedLabel": "S5HVoW_producedLabel",
10142
- "mermaidBody": "S5HVoW_mermaidBody",
10143
- "editorHeader": "S5HVoW_editorHeader",
10144
- "paneCard": "S5HVoW_paneCard",
10145
- "openWithPinActive": "S5HVoW_openWithPinActive",
10146
- "panelResizeActive": "S5HVoW_panelResizeActive",
10147
- "dropDown": "S5HVoW_dropDown",
10148
- "boundaryError": "S5HVoW_boundaryError",
10149
- "tocBar": "S5HVoW_tocBar",
10150
- "explorerName": "S5HVoW_explorerName",
10151
- "gitName": "S5HVoW_gitName",
10152
- "explorerRoot": "S5HVoW_explorerRoot",
10016
+ "terminalDepsNote": "S5HVoW_terminalDepsNote",
10017
+ "browserFrame": "S5HVoW_browserFrame",
10018
+ "gitPlaceholder": "S5HVoW_gitPlaceholder",
10019
+ "gitSection": "S5HVoW_gitSection",
10020
+ "gitDiffTabTitle": "S5HVoW_gitDiffTabTitle",
10153
10021
  "dividerCol": "S5HVoW_dividerCol",
10154
- "editorCm": "S5HVoW_editorCm",
10155
- "tocItemText": "S5HVoW_tocItemText",
10156
- "gitDiffTabHeader": "S5HVoW_gitDiffTabHeader",
10157
- "terminalDepsTitle": "S5HVoW_terminalDepsTitle",
10158
- "editorModeButton": "S5HVoW_editorModeButton",
10159
- "panel": "S5HVoW_panel",
10160
- "explorerBroken": "S5HVoW_explorerBroken",
10161
- "editorTreeResize": "S5HVoW_editorTreeResize",
10162
- "gitDiffFileChevron": "S5HVoW_gitDiffFileChevron",
10163
- "gitConfirmDesc": "S5HVoW_gitConfirmDesc",
10164
- "editorBody": "S5HVoW_editorBody",
10165
- "gitWorktreeLabel": "S5HVoW_gitWorktreeLabel",
10022
+ "tabClose": "S5HVoW_tabClose",
10023
+ "gitEmpty": "S5HVoW_gitEmpty",
10166
10024
  "editorTitle": "S5HVoW_editorTitle",
10025
+ "gitLogRef": "S5HVoW_gitLogRef",
10026
+ "editorTreeToggleActive": "S5HVoW_editorTreeToggleActive",
10167
10027
  "editorSearchHint": "S5HVoW_editorSearchHint",
10168
- "tocItem": "S5HVoW_tocItem",
10169
- "dsh-toc-flash": "S5HVoW_dsh-toc-flash",
10170
- "terminalWrap": "S5HVoW_terminalWrap",
10171
- "orphanedType": "S5HVoW_orphanedType",
10172
- "mermaidModalToolbar": "S5HVoW_mermaidModalToolbar",
10173
- "terminalDepsBanner": "S5HVoW_terminalDepsBanner",
10174
- "editorPathInput": "S5HVoW_editorPathInput",
10175
- "paneTabHidden": "S5HVoW_paneTabHidden",
10028
+ "producedMore": "S5HVoW_producedMore",
10029
+ "gitRowSelected": "S5HVoW_gitRowSelected",
10030
+ "browserLiveStatus": "S5HVoW_browserLiveStatus",
10031
+ "splitCol": "S5HVoW_splitCol",
10032
+ "uploadDropZonePill": "S5HVoW_uploadDropZonePill",
10033
+ "terminalDepsTitle": "S5HVoW_terminalDepsTitle",
10034
+ "explorerHidden": "S5HVoW_explorerHidden",
10035
+ "workbench": "S5HVoW_workbench",
10036
+ "paneContent": "S5HVoW_paneContent",
10037
+ "explorerError": "S5HVoW_explorerError",
10038
+ "editorTreeResize": "S5HVoW_editorTreeResize",
10039
+ "gitName": "S5HVoW_gitName",
10040
+ "editorError": "S5HVoW_editorError",
10176
10041
  "gitDiffHunkHeader": "S5HVoW_gitDiffHunkHeader",
10177
- "tabActive": "S5HVoW_tabActive",
10178
- "split": "S5HVoW_split",
10179
- "floatWindow": "S5HVoW_floatWindow",
10042
+ "explorerSymlink": "S5HVoW_explorerSymlink",
10180
10043
  "browserBlockedButton": "S5HVoW_browserBlockedButton",
10181
- "editorModeToggle": "S5HVoW_editorModeToggle",
10182
- "mermaidHeader": "S5HVoW_mermaidHeader",
10183
- "mermaidError": "S5HVoW_mermaidError",
10184
- "terminalRepairCommand": "S5HVoW_terminalRepairCommand",
10185
- "gitError": "S5HVoW_gitError",
10186
- "gitDiffFilePath": "S5HVoW_gitDiffFilePath",
10187
- "tocItemLevel": "S5HVoW_tocItemLevel",
10188
- "terminalBanner": "S5HVoW_terminalBanner",
10189
- "uploadDropChatCard": "S5HVoW_uploadDropChatCard",
10190
- "gitDiffTab": "S5HVoW_gitDiffTab",
10191
- "uploadDropChatHint": "S5HVoW_uploadDropChatHint",
10044
+ "sandboxAction": "S5HVoW_sandboxAction",
10045
+ "editorBinary": "S5HVoW_editorBinary",
10046
+ "browserBlockedTitle": "S5HVoW_browserBlockedTitle",
10047
+ "gitSectionHeader": "S5HVoW_gitSectionHeader",
10048
+ "pane": "S5HVoW_pane",
10049
+ "explorerBody": "S5HVoW_explorerBody",
10050
+ "explorerRow": "S5HVoW_explorerRow",
10051
+ "editorTreePanel": "S5HVoW_editorTreePanel",
10052
+ "gitBadge": "S5HVoW_gitBadge",
10053
+ "gitDiffDel": "S5HVoW_gitDiffDel",
10054
+ "splitRow": "S5HVoW_splitRow",
10055
+ "gitWorktreeLabel": "S5HVoW_gitWorktreeLabel",
10056
+ "toggleCluster": "S5HVoW_toggleCluster",
10057
+ "explorerRef": "S5HVoW_explorerRef",
10058
+ "dsh-row-in": "S5HVoW_dsh-row-in",
10059
+ "editor": "S5HVoW_editor",
10060
+ "browserLiveCanvas": "S5HVoW_browserLiveCanvas",
10061
+ "selectionPopup": "S5HVoW_selectionPopup",
10192
10062
  "dropRight": "S5HVoW_dropRight",
10193
- "gitRowMain": "S5HVoW_gitRowMain",
10063
+ "explorerBroken": "S5HVoW_explorerBroken",
10064
+ "boundaryError": "S5HVoW_boundaryError",
10065
+ "paneTabHidden": "S5HVoW_paneTabHidden",
10066
+ "floatClose": "S5HVoW_floatClose",
10067
+ "browserStart": "S5HVoW_browserStart",
10068
+ "gitBranchSelect": "S5HVoW_gitBranchSelect",
10069
+ "gitDiffExpand": "S5HVoW_gitDiffExpand",
10070
+ "floatWindowDragging": "S5HVoW_floatWindowDragging",
10071
+ "gitCommitButton": "S5HVoW_gitCommitButton",
10072
+ "editorSearchResult": "S5HVoW_editorSearchResult",
10073
+ "browserBlockedDesc": "S5HVoW_browserBlockedDesc",
10074
+ "gitLogMeta": "S5HVoW_gitLogMeta",
10075
+ "openWithPinActive": "S5HVoW_openWithPinActive",
10076
+ "terminalDepsHint": "S5HVoW_terminalDepsHint",
10194
10077
  "dropCenter": "S5HVoW_dropCenter",
10195
- "gitDiffDel": "S5HVoW_gitDiffDel",
10196
- "gitDiff": "S5HVoW_gitDiff",
10197
- "gitDiffAdd": "S5HVoW_gitDiffAdd",
10198
- "mermaidModalHint": "S5HVoW_mermaidModalHint",
10199
- "gitDiffMeta": "S5HVoW_gitDiffMeta",
10200
- "gitDiffTabTitle": "S5HVoW_gitDiffTabTitle",
10201
- "explorer": "S5HVoW_explorer",
10202
- "browserMessage": "S5HVoW_browserMessage",
10203
- "gitWorktreeRow": "S5HVoW_gitWorktreeRow"
10078
+ "dirtyDot": "S5HVoW_dirtyDot",
10079
+ "sandboxStatusOn": "S5HVoW_sandboxStatusOn",
10080
+ "terminalBannerUrl": "S5HVoW_terminalBannerUrl",
10081
+ "dropLeft": "S5HVoW_dropLeft",
10082
+ "uploadOverlayCancel": "S5HVoW_uploadOverlayCancel",
10083
+ "browser": "S5HVoW_browser",
10084
+ "tabList": "S5HVoW_tabList",
10085
+ "split": "S5HVoW_split",
10086
+ "tabBoundaryError": "S5HVoW_tabBoundaryError",
10087
+ "tab": "S5HVoW_tab",
10088
+ "editorTreePanelFull": "S5HVoW_editorTreePanelFull",
10089
+ "explorerRoot": "S5HVoW_explorerRoot",
10090
+ "gitDiffFile": "S5HVoW_gitDiffFile",
10091
+ "gitDiffTab": "S5HVoW_gitDiffTab",
10092
+ "gitDiffTabHeader": "S5HVoW_gitDiffTabHeader",
10093
+ "gitCommit": "S5HVoW_gitCommit",
10094
+ "gitRow": "S5HVoW_gitRow",
10095
+ "openWithName": "S5HVoW_openWithName",
10096
+ "gitError": "S5HVoW_gitError",
10097
+ "uploadOverlayProgressFill": "S5HVoW_uploadOverlayProgressFill",
10098
+ "tabBadge": "S5HVoW_tabBadge",
10099
+ "editorCm": "S5HVoW_editorCm",
10100
+ "floatTitle": "S5HVoW_floatTitle",
10101
+ "tabBar": "S5HVoW_tabBar",
10102
+ "paneDrop": "S5HVoW_paneDrop",
10103
+ "tabTitle": "S5HVoW_tabTitle",
10104
+ "sandboxStatus": "S5HVoW_sandboxStatus",
10105
+ "gitDiffFileChevronExpanded": "S5HVoW_gitDiffFileChevronExpanded"
10204
10106
  };
10205
10107
  //#endregion
10206
10108
  //#region src/client/intercept.tsx
@@ -10547,29 +10449,23 @@ window.__ModuleLoader__.load({
10547
10449
  /** Probe a URL's response headers (the sidebar browser's embeddability
10548
10450
  * check; see the host's browser.probe route). */
10549
10451
  browserProbe: (url, signal) => call("browser.probe", { url }, signal),
10452
+ /** Agent 浏览器宿主的 page target 列表(host 代理 CDP /json/list)。 */
10453
+ cdpTargets: (signal) => call("cdp.targets", {}, signal),
10550
10454
  /** External open for the file tree's "open with" menu: reveal a path in
10551
10455
  * the OS file manager, or hand a custom-scheme URL (vscode://, cursor://,
10552
10456
  * zed://, custom editors) to its registered handler. The host launches
10553
10457
  * the platform opener (argv, no shell). */
10554
10458
  openExternal: (payload) => call("open.external", payload)
10555
10459
  };
10556
- /** Absolute URL of the media route for one path (images only). */
10557
- function mediaUrl(scope, path) {
10558
- return fileUrl(scope, path, false);
10559
- }
10560
10460
  /** Absolute URL of the download route: serves raw bytes (binary-safe) with
10561
10461
  * `Content-Disposition: attachment`, so the browser saves the file. */
10562
10462
  function downloadUrl(scope, path) {
10563
- return fileUrl(scope, path, true);
10564
- }
10565
- /** Shared URL builder for the /sidebar/file route (media vs download). */
10566
- function fileUrl(scope, path, download) {
10567
10463
  const params = new URLSearchParams({
10568
10464
  sessionId: scope.sessionId,
10569
- path
10465
+ path,
10466
+ download: "1"
10570
10467
  });
10571
10468
  if (scope.cwd !== void 0 && scope.cwd !== "") params.set("cwd", scope.cwd);
10572
- if (download) params.set("download", "1");
10573
10469
  return `/sidebar/file?${params.toString()}`;
10574
10470
  }
10575
10471
  //#endregion
@@ -10590,67 +10486,6 @@ window.__ModuleLoader__.load({
10590
10486
  });
10591
10487
  }
10592
10488
  //#endregion
10593
- //#region src/client/editor-load.ts
10594
- /** Decode the host's base64 head bytes into the sniffing buffer. */
10595
- function decodeHead(headBase64) {
10596
- const binary = atob(headBase64);
10597
- const bytes = new Uint8Array(binary.length);
10598
- for (let i = 0; i < binary.length; i += 1) bytes[i] = binary.charCodeAt(i);
10599
- return bytes;
10600
- }
10601
- /**
10602
- * Dispatch one matched viewer's fetchStrategy. A missing viewer or a
10603
- * `binary-download` strategy both mean "no client-side renderer" → the
10604
- * download UI. `mediaUrlOf` builds the media URL for `mediaUrl`/`none`
10605
- * strategies (pure, but scope-bound — injected by the host).
10606
- */
10607
- function planFirstMatch(viewer, mediaUrlOf) {
10608
- if (viewer === void 0 || viewer.fetchStrategy === "binary-download") return { kind: "binary" };
10609
- switch (viewer.fetchStrategy) {
10610
- case "mediaUrl":
10611
- case "none": return {
10612
- kind: "render",
10613
- viewer,
10614
- mediaUrl: mediaUrlOf()
10615
- };
10616
- case "custom": return {
10617
- kind: "customLoad",
10618
- viewer
10619
- };
10620
- case "fsRead": return {
10621
- kind: "fetchFsRead",
10622
- viewer
10623
- };
10624
- }
10625
- }
10626
- /**
10627
- * Decide what an fsRead result means for the editor.
10628
- * - Text: the first match stands (content is valid for any fsRead viewer).
10629
- * - Binary: the host head bytes enable a re-match — a `detect` viewer (e.g.
10630
- * a plugin sniffing a binary format) may claim the file. `custom` viewers
10631
- * load their own bytes; `mediaUrl`/`none` viewers render the media route;
10632
- * an fsRead viewer or nothing cannot render binary → download UI.
10633
- */
10634
- function planFsReadOutcome(viewer, result, rematch, mediaUrlOf) {
10635
- if (!result.binary) return {
10636
- kind: "render",
10637
- viewer,
10638
- content: result.content,
10639
- truncated: result.truncated
10640
- };
10641
- const claimed = result.head === void 0 ? void 0 : rematch(decodeHead(result.head));
10642
- if (claimed !== void 0 && claimed.fetchStrategy === "custom") return {
10643
- kind: "customLoad",
10644
- viewer: claimed
10645
- };
10646
- if (claimed !== void 0 && (claimed.fetchStrategy === "mediaUrl" || claimed.fetchStrategy === "none")) return {
10647
- kind: "render",
10648
- viewer: claimed,
10649
- mediaUrl: mediaUrlOf()
10650
- };
10651
- return { kind: "binary" };
10652
- }
10653
- //#endregion
10654
10489
  //#region node_modules/.pnpm/react-icons@5.7.0_react@18.3.1/node_modules/react-icons/lib/iconContext.mjs
10655
10490
  var DefaultContext = {
10656
10491
  color: void 0,
@@ -10796,6 +10631,24 @@ window.__ModuleLoader__.load({
10796
10631
  }
10797
10632
  //#endregion
10798
10633
  //#region node_modules/.pnpm/react-icons@5.7.0_react@18.3.1/node_modules/react-icons/vsc/index.mjs
10634
+ function VscRemoteExplorer(props) {
10635
+ return GenIcon({
10636
+ "tag": "svg",
10637
+ "attr": {
10638
+ "viewBox": "0 0 24 25",
10639
+ "fill": "currentColor"
10640
+ },
10641
+ "child": [{
10642
+ "tag": "path",
10643
+ "attr": {
10644
+ "fillRule": "evenodd",
10645
+ "clipRule": "evenodd",
10646
+ "d": "M9.32 20.0677C9.469 20.5907 9.667 21.0917 9.911 21.5677H3.759C3.345 21.5677 3.009 21.2317 3.009 20.8177C3.009 20.4037 3.345 20.0677 3.759 20.0677H6.008V18.5517H3C1.343 18.5517 0 17.2087 0 15.5517V5.06775C0 3.41075 1.343 2.06775 3 2.06775H16.5C18.157 2.06775 19.5 3.41075 19.5 5.06775V9.88775C19.016 9.74975 18.516 9.65275 18 9.60575V5.06775C18 4.23975 17.328 3.56775 16.5 3.56775H3C2.172 3.56775 1.5 4.23975 1.5 5.06775V15.5517C1.5 16.3797 2.172 17.0517 3 17.0517H9.039C9.016 17.3047 9 17.5587 9 17.8177C9 18.0657 9.016 18.3097 9.037 18.5517H7.507V20.0677H9.32ZM24 17.8177C24 21.5457 20.978 24.5677 17.25 24.5677C13.522 24.5677 10.5 21.5457 10.5 17.8177C10.5 14.0897 13.522 11.0677 17.25 11.0677C20.978 11.0677 24 14.0897 24 17.8177ZM17.251 19.3177C17.251 19.2187 17.231 19.1217 17.194 19.0307C17.156 18.9397 17.101 18.8567 17.031 18.7867L14.781 16.5367C14.64 16.3957 14.449 16.3167 14.25 16.3167C14.051 16.3167 13.86 16.3957 13.719 16.5367C13.578 16.6777 13.499 16.8687 13.499 17.0677C13.499 17.2667 13.578 17.4577 13.719 17.5987L15.44 19.3177L13.719 21.0367C13.578 21.1777 13.499 21.3687 13.499 21.5677C13.499 21.7667 13.578 21.9577 13.719 22.0987C13.86 22.2397 14.051 22.3187 14.25 22.3187C14.449 22.3187 14.64 22.2397 14.781 22.0987L17.031 19.8487C17.101 19.7787 17.156 19.6967 17.194 19.6057C17.232 19.5147 17.251 19.4167 17.251 19.3177ZM19.06 16.3177L20.78 14.5987C20.921 14.4577 21 14.2667 21 14.0677C21 13.8687 20.921 13.6777 20.78 13.5367C20.639 13.3957 20.448 13.3167 20.249 13.3167C20.05 13.3167 19.859 13.3957 19.718 13.5367L17.468 15.7867C17.398 15.8567 17.343 15.9387 17.305 16.0307C17.267 16.1217 17.248 16.2197 17.248 16.3177C17.248 16.4157 17.268 16.5137 17.305 16.6057C17.343 16.6967 17.398 16.7797 17.468 16.8487L19.718 19.0987C19.859 19.2397 20.05 19.3187 20.249 19.3187C20.448 19.3187 20.639 19.2397 20.78 19.0987C20.921 18.9577 21 18.7667 21 18.5677C21 18.3687 20.921 18.1777 20.78 18.0367L19.06 16.3177Z"
10647
+ },
10648
+ "child": []
10649
+ }]
10650
+ })(props);
10651
+ }
10799
10652
  function VscPinned(props) {
10800
10653
  return GenIcon({
10801
10654
  "tag": "svg",
@@ -11042,137 +10895,6 @@ window.__ModuleLoader__.load({
11042
10895
  strokeLinejoin: "round"
11043
10896
  })
11044
10897
  });
11045
- /** Image viewer glyph: a picture frame with a sun and a mountain. */
11046
- const IconImageOutline16 = ({ size = 16, className }) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("svg", {
11047
- width: size,
11048
- height: size,
11049
- className,
11050
- viewBox: "0 0 16 16",
11051
- fill: "none",
11052
- xmlns: "http://www.w3.org/2000/svg",
11053
- children: [
11054
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("rect", {
11055
- x: "1.5",
11056
- y: "2.5",
11057
- width: "13",
11058
- height: "11",
11059
- rx: "2",
11060
- stroke: "currentColor",
11061
- strokeWidth: "1.5"
11062
- }),
11063
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("circle", {
11064
- cx: "5.5",
11065
- cy: "6",
11066
- r: "1.2",
11067
- stroke: "currentColor",
11068
- strokeWidth: "1.5"
11069
- }),
11070
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
11071
- d: "m3.5 12 3-3 2.25 2.25L11.5 8.5 13 10.5",
11072
- stroke: "currentColor",
11073
- strokeWidth: "1.5",
11074
- strokeLinecap: "round",
11075
- strokeLinejoin: "round"
11076
- })
11077
- ]
11078
- });
11079
- /** PDF viewer glyph: a document frame with the "PDF" label. */
11080
- const IconPdfOutline16 = ({ size = 16, className }) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("svg", {
11081
- width: size,
11082
- height: size,
11083
- className,
11084
- viewBox: "0 0 16 16",
11085
- fill: "none",
11086
- xmlns: "http://www.w3.org/2000/svg",
11087
- children: [
11088
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
11089
- d: "M3.5 1.5h6.5L13.5 5v9.5h-10z",
11090
- stroke: "currentColor",
11091
- strokeWidth: "1.5",
11092
- strokeLinejoin: "round"
11093
- }),
11094
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
11095
- d: "M9.5 1.5V5h4",
11096
- stroke: "currentColor",
11097
- strokeWidth: "1.5",
11098
- strokeLinejoin: "round"
11099
- }),
11100
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
11101
- d: "M5 13.5v-3h1.4c.75 0 1.1.32 1.1.85 0 .54-.35.85-1.1.85H5.3",
11102
- stroke: "currentColor",
11103
- strokeWidth: "1.25",
11104
- strokeLinecap: "round",
11105
- strokeLinejoin: "round"
11106
- }),
11107
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
11108
- d: "M8.3 13.5v-3h1.05c.8 0 1.35.5 1.35 1.5s-.55 1.5-1.35 1.5z",
11109
- stroke: "currentColor",
11110
- strokeWidth: "1.25",
11111
- strokeLinecap: "round",
11112
- strokeLinejoin: "round"
11113
- }),
11114
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
11115
- d: "M11.6 13.5v-3h1.3",
11116
- stroke: "currentColor",
11117
- strokeWidth: "1.25",
11118
- strokeLinecap: "round"
11119
- })
11120
- ]
11121
- });
11122
- /** Markdown viewer glyph: the classic "M with a down arrow" badge. */
11123
- const IconMarkdownOutline16 = ({ size = 16, className }) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("svg", {
11124
- width: size,
11125
- height: size,
11126
- className,
11127
- viewBox: "0 0 16 16",
11128
- fill: "none",
11129
- xmlns: "http://www.w3.org/2000/svg",
11130
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("rect", {
11131
- x: "1.5",
11132
- y: "2.5",
11133
- width: "13",
11134
- height: "11",
11135
- rx: "2",
11136
- stroke: "currentColor",
11137
- strokeWidth: "1.5"
11138
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
11139
- d: "M4 10.5V5.5l2 2.5 2-2.5v5M9.5 10.5v-5l2 2.5 2-2.5v5",
11140
- stroke: "currentColor",
11141
- strokeWidth: "1.5",
11142
- strokeLinecap: "round",
11143
- strokeLinejoin: "round"
11144
- })]
11145
- });
11146
- /** HTML viewer glyph: a document frame with a "‹/›" tag pair. */
11147
- const IconHtmlOutline16 = ({ size = 16, className }) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("svg", {
11148
- width: size,
11149
- height: size,
11150
- className,
11151
- viewBox: "0 0 16 16",
11152
- fill: "none",
11153
- xmlns: "http://www.w3.org/2000/svg",
11154
- children: [
11155
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
11156
- d: "M3.5 1.5h6.5L13.5 5v9.5h-10z",
11157
- stroke: "currentColor",
11158
- strokeWidth: "1.5",
11159
- strokeLinejoin: "round"
11160
- }),
11161
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
11162
- d: "M9.5 1.5V5h4",
11163
- stroke: "currentColor",
11164
- strokeWidth: "1.5",
11165
- strokeLinejoin: "round"
11166
- }),
11167
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
11168
- d: "M5.6 13.2 4.2 10l1.4-3.2M7.4 6.8 8.8 10l-1.4 3.2",
11169
- stroke: "currentColor",
11170
- strokeWidth: "1.25",
11171
- strokeLinecap: "round",
11172
- strokeLinejoin: "round"
11173
- })
11174
- ]
11175
- });
11176
10898
  /** Browser tab glyph: a globe with meridians. */
11177
10899
  const IconGlobeOutline16 = ({ size = 16, className }) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("svg", {
11178
10900
  width: size,
@@ -12296,15 +12018,12 @@ window.__ModuleLoader__.load({
12296
12018
  customCss: typeof record.customCss === "string" ? record.customCss : SIDEBAR_PREFS_DEFAULTS.customCss,
12297
12019
  titleBarCompat: typeof record.titleBarCompat === "boolean" ? record.titleBarCompat : SIDEBAR_PREFS_DEFAULTS.titleBarCompat,
12298
12020
  titleBarStripPx: typeof record.titleBarStripPx === "number" && Number.isFinite(record.titleBarStripPx) ? clampTitleBarStrip(record.titleBarStripPx) : SIDEBAR_PREFS_DEFAULTS.titleBarStripPx,
12299
- htmlViewerNoSandbox: typeof record.htmlViewerNoSandbox === "boolean" ? record.htmlViewerNoSandbox : SIDEBAR_PREFS_DEFAULTS.htmlViewerNoSandbox,
12300
- htmlViewerDefaultUnsafe: typeof record.htmlViewerDefaultUnsafe === "boolean" ? record.htmlViewerDefaultUnsafe : SIDEBAR_PREFS_DEFAULTS.htmlViewerDefaultUnsafe,
12301
12021
  browserNoSandbox: typeof record.browserNoSandbox === "boolean" ? record.browserNoSandbox : SIDEBAR_PREFS_DEFAULTS.browserNoSandbox,
12302
12022
  browserInterceptLinks: typeof record.browserInterceptLinks === "boolean" ? record.browserInterceptLinks : SIDEBAR_PREFS_DEFAULTS.browserInterceptLinks,
12303
12023
  browserInterceptHttp: typeof record.browserInterceptHttp === "boolean" ? record.browserInterceptHttp : SIDEBAR_PREFS_DEFAULTS.browserInterceptHttp,
12304
12024
  browserInterceptHttps: typeof record.browserInterceptHttps === "boolean" ? record.browserInterceptHttps : SIDEBAR_PREFS_DEFAULTS.browserInterceptHttps,
12305
12025
  browserAllowedLoopback: typeof record.browserAllowedLoopback === "string" ? record.browserAllowedLoopback : SIDEBAR_PREFS_DEFAULTS.browserAllowedLoopback,
12306
12026
  tabsEnabled: booleanMapOf(record.tabsEnabled),
12307
- viewersEnabled: booleanMapOf(record.viewersEnabled),
12308
12027
  pluginSettings: pluginSettingsMapOf(record.pluginSettings)
12309
12028
  };
12310
12029
  }
@@ -12728,14 +12447,98 @@ window.__ModuleLoader__.load({
12728
12447
  });
12729
12448
  }
12730
12449
  //#endregion
12450
+ //#region src/client/lazy-chunk.tsx
12451
+ /**
12452
+ * Lazy chunk view wrapper: mounts a component that lives in a lazy chunk,
12453
+ * showing a loading placeholder while the chunk script loads and an error +
12454
+ * retry affordance on failure. Used by the built-in tab/viewer descriptors.
12455
+ *
12456
+ * Contract note: {@link lazyChunkComponent} returns a plain render-prop
12457
+ * function — the descriptor contract is `component: (props) => ReactNode`,
12458
+ * and the repo renders descriptors BOTH ways: Sidebar calls
12459
+ * `descriptor.component(props)` directly, EditorHost renders it via
12460
+ * `createElement`. The wrapper function body therefore contains no hooks;
12461
+ * all state lives in the inner {@link LazyChunkView} component.
12462
+ */
12463
+ function LazyChunkView({ chunk, pick, props }) {
12464
+ const [attempt, setAttempt] = (0, react.useState)(0);
12465
+ const [state, setState] = (0, react.useState)({ status: "loading" });
12466
+ (0, react.useEffect)(() => {
12467
+ let cancelled = false;
12468
+ setState({ status: "loading" });
12469
+ loadChunk(chunk).then((mod) => {
12470
+ if (cancelled) return;
12471
+ const Comp = pick(mod);
12472
+ if (Comp === void 0) {
12473
+ setState({
12474
+ status: "error",
12475
+ message: `[dsh-coding-sidebar] chunk "${chunk}" is missing its component`
12476
+ });
12477
+ return;
12478
+ }
12479
+ setState({
12480
+ status: "ready",
12481
+ Comp
12482
+ });
12483
+ }).catch((error) => {
12484
+ if (cancelled) return;
12485
+ setState({
12486
+ status: "error",
12487
+ message: error instanceof Error ? error.message : String(error)
12488
+ });
12489
+ });
12490
+ return () => {
12491
+ cancelled = true;
12492
+ };
12493
+ }, [
12494
+ chunk,
12495
+ pick,
12496
+ attempt
12497
+ ]);
12498
+ if (state.status === "loading") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
12499
+ className: sidebar_module_css_default.editorPlaceholder,
12500
+ children: t("loading")
12501
+ });
12502
+ if (state.status === "error") return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
12503
+ className: sidebar_module_css_default.editorError,
12504
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: state.message }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
12505
+ type: "button",
12506
+ className: sidebar_module_css_default.terminalRetry,
12507
+ onClick: () => {
12508
+ setAttempt((current) => current + 1);
12509
+ },
12510
+ children: t("terminalRetry")
12511
+ })]
12512
+ });
12513
+ return (0, react.createElement)(state.Comp, props);
12514
+ }
12515
+ /**
12516
+ * Build a descriptor-compatible lazy wrapper for a chunk-resident component.
12517
+ * The returned function is the descriptor `component` itself: it returns an
12518
+ * element and never calls hooks, so both invocation styles (plain function
12519
+ * call and createElement/JSX render) work. `pick` must be a module-level
12520
+ * function (stable identity) — an inline lambda would re-trigger the load
12521
+ * effect on every render.
12522
+ * @param chunk - the chunk name (see chunk-loader.ts).
12523
+ * @param pick - select the component from the chunk's exports.
12524
+ */
12525
+ function lazyChunkComponent(chunk, pick) {
12526
+ return (props) => (0, react.createElement)(LazyChunkView, {
12527
+ chunk,
12528
+ pick,
12529
+ props
12530
+ });
12531
+ }
12532
+ //#endregion
12731
12533
  //#region src/client/EditorHost.tsx
12732
12534
  /**
12733
- * The editor tab host: the single FILES WINDOW. It resolves a file's
12734
- * previewer through the sidebar registry (`matchFileViewer`), fetches bytes
12735
- * per the matched viewer's fetch strategy, and renders its component — or
12736
- * the shared download pane when nothing can render the file. A tab without
12737
- * a path (the seeded "Files" home) renders an empty-state hint instead of
12738
- * the viewer loading flow; that path-less window IS the file explorer.
12535
+ * The editor tab host: the single FILES WINDOW. It fetches a file's text
12536
+ * through the host fs.read — text renders in the (chunk-lazy) sidebar text
12537
+ * editor, a binary file renders the shared download pane. (v1.0.4: the
12538
+ * file-viewer registry/matching was retired file preview is the host's
12539
+ * job now, the sidebar edits text only.) A tab without a path (the seeded
12540
+ * "Files" home) renders an empty-state hint instead of the loading flow;
12541
+ * that path-less window IS the file explorer.
12739
12542
  *
12740
12543
  * The chrome depends on the `editorExplorer` mode (read reactively so
12741
12544
  * toggling it re-renders without a reload):
@@ -12749,10 +12552,15 @@ window.__ModuleLoader__.load({
12749
12552
  * The tree's context menu offers the explicit escapes in both modes: open
12750
12553
  * in a new tab (per-path dedupe) or to the side (a fresh tab in a fresh
12751
12554
  * rightward split of the current pane).
12752
- *
12753
- * The strategy dispatch is pure (planFirstMatch / planFsReadOutcome in
12754
- * editor-load.ts); this component only wires it to the host APIs.
12755
12555
  */
12556
+ /**
12557
+ * Lazy wrapper over the chunk-resident text editor: CodeMirror and the
12558
+ * language packs are fetched only when a file tab first renders (see
12559
+ * chunk-loader.ts). The `pick` function is module-level (stable identity —
12560
+ * the wrapper effect depends on it); the cast bridges the chunk exports
12561
+ * record to the prop shape.
12562
+ */
12563
+ const LazyTextEditor = lazyChunkComponent("editor", (mod) => mod.TextEditor);
12756
12564
  /** The docked tree panel's width bounds (drag-resize clamps into them). */
12757
12565
  const TREE_WIDTH_DEFAULT = 240;
12758
12566
  const TREE_WIDTH_MIN = 160;
@@ -12790,7 +12598,6 @@ window.__ModuleLoader__.load({
12790
12598
  function EditorHost(props) {
12791
12599
  const { ctx, store, scope, tab, expanded, revealed, onToggleDir, onReferenceFile } = props;
12792
12600
  const path = tab.path ?? "";
12793
- const title = tab.title;
12794
12601
  const isDir = metaOf(tab).dir === true;
12795
12602
  const [load, setLoad] = (0, react.useState)({ status: "loading" });
12796
12603
  const [reloadSeq, setReloadSeq] = (0, react.useState)(0);
@@ -12929,81 +12736,36 @@ window.__ModuleLoader__.load({
12929
12736
  setToolbar(null);
12930
12737
  if (showEmpty || isDir) return;
12931
12738
  let cancelled = false;
12932
- const controller = new AbortController();
12933
12739
  setLoad({ status: "loading" });
12934
- const mediaUrlOf = () => mediaUrl(scope, path);
12935
- const apply = (action) => {
12740
+ api.fsRead(scope, path).then((result) => {
12936
12741
  if (cancelled) return;
12937
- switch (action.kind) {
12938
- case "binary":
12939
- setLoad({ status: "binary" });
12940
- return;
12941
- case "render":
12942
- setLoad({
12943
- status: "ready",
12944
- viewer: action.viewer,
12945
- content: action.content,
12946
- truncated: action.truncated,
12947
- mediaUrl: action.mediaUrl,
12948
- customData: action.customData
12949
- });
12950
- return;
12951
- case "customLoad":
12952
- action.viewer.load?.(path, scope, controller.signal).then((data) => {
12953
- if (cancelled) return;
12954
- setLoad({
12955
- status: "ready",
12956
- viewer: action.viewer,
12957
- customData: data
12958
- });
12959
- }).catch((error) => {
12960
- if (cancelled) return;
12961
- setLoad({
12962
- status: "error",
12963
- message: error instanceof Error ? error.message : String(error)
12964
- });
12965
- });
12966
- return;
12967
- case "fetchFsRead":
12968
- api.fsRead(scope, path).then((result) => {
12969
- if (cancelled) return;
12970
- const outcome = planFsReadOutcome(action.viewer, {
12971
- binary: result.kind === "binary",
12972
- content: result.kind === "text" ? result.content : "",
12973
- truncated: result.truncated,
12974
- head: result.kind === "binary" ? result.head : void 0
12975
- }, (head) => ctx.get("betterSidebar")?.matchFileViewer(path, head), mediaUrlOf);
12976
- apply(outcome);
12977
- }).catch((error) => {
12978
- if (cancelled) return;
12979
- setLoad({
12980
- status: "error",
12981
- message: error instanceof Error ? error.message : String(error)
12982
- });
12983
- });
12984
- return;
12742
+ if (result.kind === "binary") {
12743
+ setLoad({ status: "binary" });
12744
+ return;
12985
12745
  }
12986
- };
12987
- apply(planFirstMatch(ctx.get("betterSidebar")?.matchFileViewer(path), mediaUrlOf));
12746
+ setLoad({
12747
+ status: "ready",
12748
+ content: result.content,
12749
+ truncated: result.truncated
12750
+ });
12751
+ }).catch((error) => {
12752
+ if (cancelled) return;
12753
+ setLoad({
12754
+ status: "error",
12755
+ message: error instanceof Error ? error.message : String(error)
12756
+ });
12757
+ });
12988
12758
  return () => {
12989
12759
  cancelled = true;
12990
- controller.abort();
12991
12760
  };
12992
12761
  }, [
12993
12762
  scope.sessionId,
12994
12763
  scope.cwd,
12995
12764
  path,
12996
- ctx,
12997
12765
  showEmpty,
12998
12766
  isDir,
12999
12767
  reloadSeq
13000
12768
  ]);
13001
- const prevSaveState = (0, react.useRef)(void 0);
13002
- (0, react.useEffect)(() => {
13003
- const current = toolbar?.saveState;
13004
- if (prevSaveState.current !== "saved" && current === "saved" && toolbar?.mode === "preview") setReloadSeq((sequence) => sequence + 1);
13005
- prevSaveState.current = current;
13006
- }, [toolbar?.saveState, toolbar?.mode]);
13007
12769
  const treeOpen = treeOpenOf(tab);
13008
12770
  /** Persist the panel flag on the tab (survives reloads with the layout). */
13009
12771
  const toggleTree = () => {
@@ -13040,25 +12802,6 @@ window.__ModuleLoader__.load({
13040
12802
  cwd: scope.cwd,
13041
12803
  onOpen: openFile
13042
12804
  }, path),
13043
- toolbar?.modes === true && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
13044
- className: sidebar_module_css_default.editorModeToggle,
13045
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
13046
- type: "button",
13047
- className: clsx(sidebar_module_css_default.editorModeButton, toolbar.mode === "preview" && sidebar_module_css_default.editorModeActive),
13048
- onClick: () => {
13049
- if (toolbar.mode === "edit" && toolbar.dirty !== true && toolbar.saveState !== "failed") setReloadSeq((sequence) => sequence + 1);
13050
- controlsRef.current?.setMode("preview");
13051
- },
13052
- children: t("preview")
13053
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
13054
- type: "button",
13055
- className: clsx(sidebar_module_css_default.editorModeButton, toolbar.mode === "edit" && sidebar_module_css_default.editorModeActive),
13056
- onClick: () => {
13057
- controlsRef.current?.setMode("edit");
13058
- },
13059
- children: t("edit")
13060
- })]
13061
- }),
13062
12805
  toolbar?.dirty === true && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
13063
12806
  className: sidebar_module_css_default.dirtyDot,
13064
12807
  title: t("unsaved")
@@ -13116,17 +12859,13 @@ window.__ModuleLoader__.load({
13116
12859
  scope,
13117
12860
  path
13118
12861
  }),
13119
- !showEmpty && load.status === "ready" && (0, react.createElement)(load.viewer.component, {
12862
+ !showEmpty && load.status === "ready" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LazyTextEditor, {
13120
12863
  ctx,
13121
12864
  store,
13122
12865
  scope,
13123
12866
  path,
13124
- title,
13125
- viewerId: load.viewer.id,
13126
12867
  content: load.content,
13127
12868
  truncated: load.truncated,
13128
- mediaUrl: load.mediaUrl,
13129
- customData: load.customData,
13130
12869
  toolbar: "host",
13131
12870
  onToolbarState,
13132
12871
  onToolbarControls
@@ -13217,75 +12956,75 @@ window.__ModuleLoader__.load({
13217
12956
  document.head.appendChild(tag);
13218
12957
  }
13219
12958
  var SideCardSection_module_css_default = {
13220
- "pluginEntries": "AC9POW_pluginEntries",
13221
- "selectOptionIcon": "AC9POW_selectOptionIcon",
13222
- "openWithEditorRow": "AC9POW_openWithEditorRow",
12959
+ "typedInputNumber": "AC9POW_typedInputNumber",
12960
+ "cssTextArea": "AC9POW_cssTextArea",
12961
+ "pluginGroupHeading": "AC9POW_pluginGroupHeading",
12962
+ "switchTrack": "AC9POW_switchTrack",
12963
+ "rowText": "AC9POW_rowText",
12964
+ "desc": "AC9POW_desc",
12965
+ "percentInput": "AC9POW_percentInput",
12966
+ "openWithFamily": "AC9POW_openWithFamily",
12967
+ "suffix": "AC9POW_suffix",
13223
12968
  "openWithEditorInput": "AC9POW_openWithEditorInput",
13224
- "intro": "AC9POW_intro",
12969
+ "pluginName": "AC9POW_pluginName",
12970
+ "cardSwitchThumb": "AC9POW_cardSwitchThumb",
12971
+ "openWithHint": "AC9POW_openWithHint",
12972
+ "cardSettings": "AC9POW_cardSettings",
13225
12973
  "pluginInstall": "AC9POW_pluginInstall",
12974
+ "cardIconChip": "AC9POW_cardIconChip",
12975
+ "selectAnchor": "AC9POW_selectAnchor",
12976
+ "pluginModal": "AC9POW_pluginModal",
13226
12977
  "pluginEntryHead": "AC9POW_pluginEntryHead",
12978
+ "cardTitle": "AC9POW_cardTitle",
12979
+ "popupRows": "AC9POW_popupRows",
12980
+ "cardTop": "AC9POW_cardTop",
12981
+ "popupRow": "AC9POW_popupRow",
12982
+ "group": "AC9POW_group",
12983
+ "row": "AC9POW_row",
12984
+ "pluginJumpBtn": "AC9POW_pluginJumpBtn",
12985
+ "grid": "AC9POW_grid",
12986
+ "versionBadgeTag": "AC9POW_versionBadgeTag",
12987
+ "pluginEntryActions": "AC9POW_pluginEntryActions",
12988
+ "selectOption": "AC9POW_selectOption",
12989
+ "cardDesc": "AC9POW_cardDesc",
12990
+ "pluginDesc": "AC9POW_pluginDesc",
12991
+ "section": "AC9POW_section",
13227
12992
  "openWithEditorTemplate": "AC9POW_openWithEditorTemplate",
13228
12993
  "versionBadge": "AC9POW_versionBadge",
13229
- "cardDesc": "AC9POW_cardDesc",
13230
- "percentInput": "AC9POW_percentInput",
13231
- "pluginGroup": "AC9POW_pluginGroup",
13232
12994
  "switch": "AC9POW_switch",
13233
- "openWithRemove": "AC9POW_openWithRemove",
13234
- "pluginModal": "AC9POW_pluginModal",
13235
- "rowText": "AC9POW_rowText",
13236
- "switchInput": "AC9POW_switchInput",
13237
- "cardIconChip": "AC9POW_cardIconChip",
13238
- "versionBadgeTag": "AC9POW_versionBadgeTag",
12995
+ "pluginList": "AC9POW_pluginList",
12996
+ "versionBadgeName": "AC9POW_versionBadgeName",
12997
+ "openWithEditorRow": "AC9POW_openWithEditorRow",
12998
+ "selectAnchorText": "AC9POW_selectAnchorText",
13239
12999
  "pluginCopyBtn": "AC9POW_pluginCopyBtn",
13000
+ "card": "AC9POW_card",
13240
13001
  "selectOptionText": "AC9POW_selectOptionText",
13241
- "pluginTopicBtn": "AC9POW_pluginTopicBtn",
13242
- "popupRow": "AC9POW_popupRow",
13243
- "pluginSearch": "AC9POW_pluginSearch",
13244
- "typedInputNumber": "AC9POW_typedInputNumber",
13245
- "rowGear": "AC9POW_rowGear",
13246
- "pluginJumpBtn": "AC9POW_pluginJumpBtn",
13247
- "switchThumb": "AC9POW_switchThumb",
13248
- "section": "AC9POW_section",
13249
- "suffix": "AC9POW_suffix",
13250
- "grid": "AC9POW_grid",
13251
- "pluginDesc": "AC9POW_pluginDesc",
13252
- "cardSwitchThumb": "AC9POW_cardSwitchThumb",
13253
- "cardSettings": "AC9POW_cardSettings",
13254
- "openWithFamily": "AC9POW_openWithFamily",
13255
- "row": "AC9POW_row",
13256
- "cardMain": "AC9POW_cardMain",
13257
- "groupHeading": "AC9POW_groupHeading",
13002
+ "intro": "AC9POW_intro",
13258
13003
  "popupDialog": "AC9POW_popupDialog",
13259
- "count": "AC9POW_count",
13260
- "openWithHint": "AC9POW_openWithHint",
13261
- "cardTitle": "AC9POW_cardTitle",
13262
- "selectAnchorText": "AC9POW_selectAnchorText",
13263
- "selectOption": "AC9POW_selectOption",
13264
13004
  "typedInput": "AC9POW_typedInput",
13265
- "error": "AC9POW_error",
13266
- "cardOn": "AC9POW_cardOn",
13267
- "pluginEmpty": "AC9POW_pluginEmpty",
13268
- "popupRows": "AC9POW_popupRows",
13269
- "control": "AC9POW_control",
13270
- "card": "AC9POW_card",
13271
- "cssTextArea": "AC9POW_cssTextArea",
13272
- "done": "AC9POW_done",
13273
- "pluginGroupHeading": "AC9POW_pluginGroupHeading",
13274
- "desc": "AC9POW_desc",
13275
- "selectAnchorIcon": "AC9POW_selectAnchorIcon",
13276
13005
  "pluginEntry": "AC9POW_pluginEntry",
13277
- "pluginList": "AC9POW_pluginList",
13278
- "versionBadgeName": "AC9POW_versionBadgeName",
13006
+ "pluginEntries": "AC9POW_pluginEntries",
13279
13007
  "title": "AC9POW_title",
13280
- "group": "AC9POW_group",
13281
- "pluginName": "AC9POW_pluginName",
13282
- "switchTrack": "AC9POW_switchTrack",
13283
- "cardSwitch": "AC9POW_cardSwitch",
13008
+ "pluginGroup": "AC9POW_pluginGroup",
13009
+ "openWithRemove": "AC9POW_openWithRemove",
13010
+ "cardOn": "AC9POW_cardOn",
13011
+ "switchThumb": "AC9POW_switchThumb",
13012
+ "control": "AC9POW_control",
13013
+ "pluginSearch": "AC9POW_pluginSearch",
13014
+ "rowGear": "AC9POW_rowGear",
13015
+ "switchInput": "AC9POW_switchInput",
13016
+ "selectOptionIcon": "AC9POW_selectOptionIcon",
13017
+ "groupHeading": "AC9POW_groupHeading",
13284
13018
  "cardSwitchTrack": "AC9POW_cardSwitchTrack",
13019
+ "selectAnchorIcon": "AC9POW_selectAnchorIcon",
13020
+ "done": "AC9POW_done",
13021
+ "pluginTopicBtn": "AC9POW_pluginTopicBtn",
13285
13022
  "addCard": "AC9POW_addCard",
13286
- "selectAnchor": "AC9POW_selectAnchor",
13287
- "pluginEntryActions": "AC9POW_pluginEntryActions",
13288
- "cardTop": "AC9POW_cardTop"
13023
+ "cardMain": "AC9POW_cardMain",
13024
+ "cardSwitch": "AC9POW_cardSwitch",
13025
+ "error": "AC9POW_error",
13026
+ "pluginEmpty": "AC9POW_pluginEmpty",
13027
+ "count": "AC9POW_count"
13289
13028
  };
13290
13029
  //#endregion
13291
13030
  //#region src/client/open-with-settings.tsx
@@ -13437,89 +13176,6 @@ window.__ModuleLoader__.load({
13437
13176
  });
13438
13177
  }
13439
13178
  //#endregion
13440
- //#region src/client/lazy-chunk.tsx
13441
- /**
13442
- * Lazy chunk view wrapper: mounts a component that lives in a lazy chunk,
13443
- * showing a loading placeholder while the chunk script loads and an error +
13444
- * retry affordance on failure. Used by the built-in tab/viewer descriptors.
13445
- *
13446
- * Contract note: {@link lazyChunkComponent} returns a plain render-prop
13447
- * function — the descriptor contract is `component: (props) => ReactNode`,
13448
- * and the repo renders descriptors BOTH ways: Sidebar calls
13449
- * `descriptor.component(props)` directly, EditorHost renders it via
13450
- * `createElement`. The wrapper function body therefore contains no hooks;
13451
- * all state lives in the inner {@link LazyChunkView} component.
13452
- */
13453
- function LazyChunkView({ chunk, pick, props }) {
13454
- const [attempt, setAttempt] = (0, react.useState)(0);
13455
- const [state, setState] = (0, react.useState)({ status: "loading" });
13456
- (0, react.useEffect)(() => {
13457
- let cancelled = false;
13458
- setState({ status: "loading" });
13459
- loadChunk(chunk).then((mod) => {
13460
- if (cancelled) return;
13461
- const Comp = pick(mod);
13462
- if (Comp === void 0) {
13463
- setState({
13464
- status: "error",
13465
- message: `[dsh-coding-sidebar] chunk "${chunk}" is missing its component`
13466
- });
13467
- return;
13468
- }
13469
- setState({
13470
- status: "ready",
13471
- Comp
13472
- });
13473
- }).catch((error) => {
13474
- if (cancelled) return;
13475
- setState({
13476
- status: "error",
13477
- message: error instanceof Error ? error.message : String(error)
13478
- });
13479
- });
13480
- return () => {
13481
- cancelled = true;
13482
- };
13483
- }, [
13484
- chunk,
13485
- pick,
13486
- attempt
13487
- ]);
13488
- if (state.status === "loading") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
13489
- className: sidebar_module_css_default.editorPlaceholder,
13490
- children: t("loading")
13491
- });
13492
- if (state.status === "error") return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
13493
- className: sidebar_module_css_default.editorError,
13494
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: state.message }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
13495
- type: "button",
13496
- className: sidebar_module_css_default.terminalRetry,
13497
- onClick: () => {
13498
- setAttempt((current) => current + 1);
13499
- },
13500
- children: t("terminalRetry")
13501
- })]
13502
- });
13503
- return (0, react.createElement)(state.Comp, props);
13504
- }
13505
- /**
13506
- * Build a descriptor-compatible lazy wrapper for a chunk-resident component.
13507
- * The returned function is the descriptor `component` itself: it returns an
13508
- * element and never calls hooks, so both invocation styles (plain function
13509
- * call and createElement/JSX render) work. `pick` must be a module-level
13510
- * function (stable identity) — an inline lambda would re-trigger the load
13511
- * effect on every render.
13512
- * @param chunk - the chunk name (see chunk-loader.ts).
13513
- * @param pick - select the component from the chunk's exports.
13514
- */
13515
- function lazyChunkComponent(chunk, pick) {
13516
- return (props) => (0, react.createElement)(LazyChunkView, {
13517
- chunk,
13518
- pick,
13519
- props
13520
- });
13521
- }
13522
- //#endregion
13523
13179
  //#region src/client/GitView.tsx
13524
13180
  /**
13525
13181
  * The source-control panel: status list (staged vs unstaged), stage/unstage,
@@ -15086,58 +14742,58 @@ Mode: this is a continuable side conversation. Your answers stay in this side th
15086
14742
  document.head.appendChild(tag);
15087
14743
  }
15088
14744
  var SubagentView_module_css_default = {
15089
- "jobsPanePre": "F2T6aa_jobsPanePre",
15090
- "jobsPaneError": "F2T6aa_jobsPaneError",
15091
- "subagentLiveArgs": "F2T6aa_subagentLiveArgs",
15092
- "subagentContent": "F2T6aa_subagentContent",
15093
- "jobsSecondary": "F2T6aa_jobsSecondary",
15094
- "jobsRowSelected": "F2T6aa_jobsRowSelected",
14745
+ "jobsPaneDot": "F2T6aa_jobsPaneDot",
14746
+ "subagentLiveText": "F2T6aa_subagentLiveText",
14747
+ "jobsContent": "F2T6aa_jobsContent",
15095
14748
  "jobsPaneHeader": "F2T6aa_jobsPaneHeader",
15096
- "jobsPaneHint": "F2T6aa_jobsPaneHint",
15097
14749
  "jobsKind": "F2T6aa_jobsKind",
14750
+ "jobsCount": "F2T6aa_jobsCount",
14751
+ "subagentLiveArgs": "F2T6aa_subagentLiveArgs",
14752
+ "subagentLive": "F2T6aa_subagentLive",
14753
+ "jobsList": "F2T6aa_jobsList",
14754
+ "subagentContent": "F2T6aa_subagentContent",
14755
+ "jobs": "F2T6aa_jobs",
15098
14756
  "jobsRowSettled": "F2T6aa_jobsRowSettled",
14757
+ "historyToggle": "F2T6aa_historyToggle",
14758
+ "subagent": "F2T6aa_subagent",
15099
14759
  "subagentEmptyHint": "F2T6aa_subagentEmptyHint",
15100
- "jobsContent": "F2T6aa_jobsContent",
14760
+ "jobsLabelLine": "F2T6aa_jobsLabelLine",
15101
14761
  "jobsLabel": "F2T6aa_jobsLabel",
15102
- "subagentLiveText": "F2T6aa_subagentLiveText",
15103
- "jobsPaneDot": "F2T6aa_jobsPaneDot",
15104
- "jobsPaneClose": "F2T6aa_jobsPaneClose",
15105
14762
  "jobsKill": "F2T6aa_jobsKill",
15106
- "subagentError": "F2T6aa_subagentError",
15107
- "subagent": "F2T6aa_subagent",
15108
- "subagentRowDisabled": "F2T6aa_subagentRowDisabled",
15109
- "jobsKillArmed": "F2T6aa_jobsKillArmed",
15110
- "subagentDot": "F2T6aa_subagentDot",
15111
- "subagentSecondary": "F2T6aa_subagentSecondary",
15112
- "jobs": "F2T6aa_jobs",
15113
- "subagentTitle": "F2T6aa_subagentTitle",
15114
- "subagentRowLoading": "F2T6aa_subagentRowLoading",
15115
- "subagentLabel": "F2T6aa_subagentLabel",
15116
- "subagentRow": "F2T6aa_subagentRow",
14763
+ "jobsKillError": "F2T6aa_jobsKillError",
15117
14764
  "subagentCount": "F2T6aa_subagentCount",
15118
- "subagentEmpty": "F2T6aa_subagentEmpty",
15119
- "jobsCount": "F2T6aa_jobsCount",
15120
- "jobsList": "F2T6aa_jobsList",
14765
+ "jobsPaneClose": "F2T6aa_jobsPaneClose",
14766
+ "jobsPanePre": "F2T6aa_jobsPanePre",
14767
+ "jobsPaneHint": "F2T6aa_jobsPaneHint",
14768
+ "jobsDot": "F2T6aa_jobsDot",
14769
+ "subagentDot": "F2T6aa_subagentDot",
14770
+ "jobsPaneLabel": "F2T6aa_jobsPaneLabel",
14771
+ "jobsTitle": "F2T6aa_jobsTitle",
15121
14772
  "jobsRow": "F2T6aa_jobsRow",
15122
- "jobsRowMain": "F2T6aa_jobsRowMain",
15123
- "subagentRowActive": "F2T6aa_subagentRowActive",
15124
- "jobsKillError": "F2T6aa_jobsKillError",
14773
+ "jobsRowSelected": "F2T6aa_jobsRowSelected",
15125
14774
  "jobsPane": "F2T6aa_jobsPane",
15126
- "jobsPaneStatus": "F2T6aa_jobsPaneStatus",
15127
- "jobsPaneLabel": "F2T6aa_jobsPaneLabel",
15128
- "subagentNode": "F2T6aa_subagentNode",
14775
+ "subagentChildren": "F2T6aa_subagentChildren",
15129
14776
  "jobsHeader": "F2T6aa_jobsHeader",
15130
- "subagentLive": "F2T6aa_subagentLive",
15131
- "subagentRefresh": "F2T6aa_subagentRefresh",
15132
- "jobsLabelLine": "F2T6aa_jobsLabelLine",
14777
+ "subagentLiveTool": "F2T6aa_subagentLiveTool",
14778
+ "jobsKillArmed": "F2T6aa_jobsKillArmed",
15133
14779
  "subagentHeader": "F2T6aa_subagentHeader",
15134
- "historyToggle": "F2T6aa_historyToggle",
15135
14780
  "subagentErrorRetry": "F2T6aa_subagentErrorRetry",
15136
- "jobsTitle": "F2T6aa_jobsTitle",
15137
- "subagentChildren": "F2T6aa_subagentChildren",
15138
- "subagentBody": "F2T6aa_subagentBody",
15139
- "subagentLiveTool": "F2T6aa_subagentLiveTool",
15140
- "jobsDot": "F2T6aa_jobsDot"
14781
+ "subagentRowLoading": "F2T6aa_subagentRowLoading",
14782
+ "subagentNode": "F2T6aa_subagentNode",
14783
+ "jobsRowMain": "F2T6aa_jobsRowMain",
14784
+ "subagentError": "F2T6aa_subagentError",
14785
+ "jobsPaneError": "F2T6aa_jobsPaneError",
14786
+ "jobsSecondary": "F2T6aa_jobsSecondary",
14787
+ "subagentRowActive": "F2T6aa_subagentRowActive",
14788
+ "subagentLabel": "F2T6aa_subagentLabel",
14789
+ "subagentRow": "F2T6aa_subagentRow",
14790
+ "subagentTitle": "F2T6aa_subagentTitle",
14791
+ "subagentEmpty": "F2T6aa_subagentEmpty",
14792
+ "subagentSecondary": "F2T6aa_subagentSecondary",
14793
+ "subagentRefresh": "F2T6aa_subagentRefresh",
14794
+ "jobsPaneStatus": "F2T6aa_jobsPaneStatus",
14795
+ "subagentRowDisabled": "F2T6aa_subagentRowDisabled",
14796
+ "subagentBody": "F2T6aa_subagentBody"
15141
14797
  };
15142
14798
  //#endregion
15143
14799
  //#region src/client/SubagentView.tsx
@@ -16244,45 +15900,45 @@ Mode: this is a continuable side conversation. Your answers stay in this side th
16244
15900
  document.head.appendChild(tag);
16245
15901
  }
16246
15902
  var SideChatView_module_css_default = {
16247
- "sidechatAssistant": "_64UoUa_sidechatAssistant",
16248
- "sidechatUser": "_64UoUa_sidechatUser",
16249
- "sidechatHeaderDot": "_64UoUa_sidechatHeaderDot",
15903
+ "sidechatRowMeta": "_64UoUa_sidechatRowMeta",
15904
+ "sidechatHeroDesc": "_64UoUa_sidechatHeroDesc",
15905
+ "sidechatRowBody": "_64UoUa_sidechatRowBody",
15906
+ "sidechatComposer": "_64UoUa_sidechatComposer",
15907
+ "sidechatDetailHeader": "_64UoUa_sidechatDetailHeader",
16250
15908
  "sidechatRowSummary": "_64UoUa_sidechatRowSummary",
16251
- "sidechatBtnIn": "_64UoUa_sidechatBtnIn",
16252
- "sidechatRow": "_64UoUa_sidechatRow",
16253
- "sidechatRowMono": "_64UoUa_sidechatRowMono",
16254
- "sidechatComposerBar": "_64UoUa_sidechatComposerBar",
16255
- "sidechatSweep": "_64UoUa_sidechatSweep",
16256
- "sidechatStatusText": "_64UoUa_sidechatStatusText",
16257
- "sidechatIconBtn": "_64UoUa_sidechatIconBtn",
16258
- "sidechatHeroTitle": "_64UoUa_sidechatHeroTitle",
16259
- "sidechatRowIn": "_64UoUa_sidechatRowIn",
16260
- "sidechatRowProse": "_64UoUa_sidechatRowProse",
16261
15909
  "sidechatAgentBadge": "_64UoUa_sidechatAgentBadge",
16262
- "sidechatPrimaryBtn": "_64UoUa_sidechatPrimaryBtn",
16263
- "sidechatRowMeta": "_64UoUa_sidechatRowMeta",
15910
+ "sidechatRowIn": "_64UoUa_sidechatRowIn",
15911
+ "sidechatRowLine": "_64UoUa_sidechatRowLine",
15912
+ "sidechatShimmerText": "_64UoUa_sidechatShimmerText",
16264
15913
  "sidechatSendBtn": "_64UoUa_sidechatSendBtn",
16265
- "sidechatDetailHeader": "_64UoUa_sidechatDetailHeader",
15914
+ "sidechatRowFailed": "_64UoUa_sidechatRowFailed",
15915
+ "sidechat": "_64UoUa_sidechat",
15916
+ "sidechatError": "_64UoUa_sidechatError",
15917
+ "sidechatUser": "_64UoUa_sidechatUser",
15918
+ "sidechatHint": "_64UoUa_sidechatHint",
15919
+ "sidechatRow": "_64UoUa_sidechatRow",
15920
+ "sidechatHeaderSpacer": "_64UoUa_sidechatHeaderSpacer",
15921
+ "sidechatHeroTitle": "_64UoUa_sidechatHeroTitle",
15922
+ "sidechatStatus": "_64UoUa_sidechatStatus",
16266
15923
  "sidechatHero": "_64UoUa_sidechatHero",
16267
15924
  "sidechatFadeIn": "_64UoUa_sidechatFadeIn",
16268
- "sidechatRowBody": "_64UoUa_sidechatRowBody",
16269
- "sidechatComposer": "_64UoUa_sidechatComposer",
16270
- "sidechatHeroDesc": "_64UoUa_sidechatHeroDesc",
15925
+ "sidechatPrimaryBtn": "_64UoUa_sidechatPrimaryBtn",
15926
+ "sidechatHeaderDot": "_64UoUa_sidechatHeaderDot",
15927
+ "sidechatSweep": "_64UoUa_sidechatSweep",
15928
+ "sidechatIconBtn": "_64UoUa_sidechatIconBtn",
15929
+ "sidechatRowStatic": "_64UoUa_sidechatRowStatic",
15930
+ "sidechatComposerMeta": "_64UoUa_sidechatComposerMeta",
16271
15931
  "sidechatScroll": "_64UoUa_sidechatScroll",
16272
- "sidechatHint": "_64UoUa_sidechatHint",
16273
- "sidechatError": "_64UoUa_sidechatError",
16274
- "sidechat": "_64UoUa_sidechat",
16275
- "sidechatRowLabel": "_64UoUa_sidechatRowLabel",
16276
- "sidechatRowFailed": "_64UoUa_sidechatRowFailed",
16277
- "sidechatRowCode": "_64UoUa_sidechatRowCode",
16278
15932
  "sidechatComposerInput": "_64UoUa_sidechatComposerInput",
16279
- "sidechatComposerMeta": "_64UoUa_sidechatComposerMeta",
16280
- "sidechatRowStatic": "_64UoUa_sidechatRowStatic",
16281
- "sidechatHeaderSpacer": "_64UoUa_sidechatHeaderSpacer",
16282
15933
  "sidechatRowChevron": "_64UoUa_sidechatRowChevron",
16283
- "sidechatShimmerText": "_64UoUa_sidechatShimmerText",
16284
- "sidechatStatus": "_64UoUa_sidechatStatus",
16285
- "sidechatRowLine": "_64UoUa_sidechatRowLine"
15934
+ "sidechatRowProse": "_64UoUa_sidechatRowProse",
15935
+ "sidechatRowMono": "_64UoUa_sidechatRowMono",
15936
+ "sidechatStatusText": "_64UoUa_sidechatStatusText",
15937
+ "sidechatAssistant": "_64UoUa_sidechatAssistant",
15938
+ "sidechatRowCode": "_64UoUa_sidechatRowCode",
15939
+ "sidechatRowLabel": "_64UoUa_sidechatRowLabel",
15940
+ "sidechatComposerBar": "_64UoUa_sidechatComposerBar",
15941
+ "sidechatBtnIn": "_64UoUa_sidechatBtnIn"
16286
15942
  };
16287
15943
  //#endregion
16288
15944
  //#region src/client/SideChatView.tsx
@@ -16975,17 +16631,20 @@ Mode: this is a continuable side conversation. Your answers stay in this side th
16975
16631
  //#endregion
16976
16632
  //#region src/client/SandboxStatusBar.tsx
16977
16633
  /**
16978
- * The live sandbox status row of the two built-in web surfaces (HTML
16979
- * preview and the browser tab): a green "sandbox on" state with a one-tap
16980
- * TEMPORARY unlock, or a RED "sandbox off" state (global setting or the
16981
- * temporary unlock) with a restore action.
16634
+ * The live sandbox status row of the built-in browser tab: a green
16635
+ * "sandbox on" state with a one-tap TEMPORARY unlock, or a RED "sandbox
16636
+ * off" state (global setting or the temporary unlock) with a restore
16637
+ * action.
16982
16638
  *
16983
16639
  * The temporary unlock is component state only — it never writes the
16984
- * global side card setting (`htmlViewerNoSandbox` / `browserNoSandbox`);
16985
- * it lasts until the surface unmounts (tab switch / file switch) or the
16986
- * user restores the sandbox from the row. When the global setting already
16987
- * drops the sandbox, no unlock/restore action is offered (changing the
16988
- * global setting is the settings page's job) — the red warning stands.
16640
+ * global side card setting (`browserNoSandbox`); it lasts until the
16641
+ * surface unmounts (tab switch) or the user restores the sandbox from the
16642
+ * row. When the global setting already drops the sandbox, no
16643
+ * unlock/restore action is offered (changing the global setting is the
16644
+ * settings page's job) — the red warning stands.
16645
+ *
16646
+ * (v1.0.4: the HTML preview surface was retired with the file-viewer line;
16647
+ * this row now serves the browser tab only.)
16989
16648
  */
16990
16649
  function SandboxStatusBar(props) {
16991
16650
  const { sandboxed, local, dangerCopy, onUnlock, onRestore } = props;
@@ -17028,6 +16687,268 @@ Mode: this is a continuable side conversation. Your answers stay in this side th
17028
16687
  });
17029
16688
  }
17030
16689
  //#endregion
16690
+ //#region src/client/LiveView.tsx
16691
+ /**
16692
+ * Agent 浏览器实况(CDP screencast + 输入回传,2026-09-12 方案 2)。
16693
+ *
16694
+ * 数据面:KCoder 桌面端 browser-host 维护一个无头 Chromium(固定 CDP
16695
+ * 转发地址 127.0.0.1:9223,与 playwright MCP `--cdp-endpoint` 共用)。
16696
+ * 本组件作为第二个 CDP 客户端:
16697
+ * - target 列表经宿主代理 `/sidebar/api`(CDP HTTP 无 CORS 头);
16698
+ * - screencast/输入走 renderer 直连 `ws://127.0.0.1:9223/devtools/page/<id>`
16699
+ * (WebSocket 不受 CORS 约束,宿主未设 CSP)。
16700
+ *
16701
+ * 连接模型:`attachedId`(用户显式选择)优先,否则自动跟随「最新创建的
16702
+ * page target」;连接按 effectiveId 建立与重建,列表仅在内容变化时更新
16703
+ * state(JSON 比对),避免轮询引起重连抖动。
16704
+ *
16705
+ * 交互:screencast 帧绘到 canvas;指针/滚轮按 canvas→viewport 比例回传
16706
+ * (Input.dispatchMouseEvent);可打印字符经 Input.insertText,控制键走
16707
+ * rawKeyDown/keyUp。视口统一 1280×800(Emulation.setDeviceMetricsOverride),
16708
+ * canvas 等比缩放显示。
16709
+ */
16710
+ /** 与 KCoder desktop/main/browser-host.ts 的 BROWSER_HOST_PORT 一致。 */
16711
+ const CDP_WS = "ws://127.0.0.1:9223";
16712
+ /** 实况视口(CDP 侧强制,帧与输入坐标以此为基准)。 */
16713
+ const VIEW_W = 1280;
16714
+ const VIEW_H = 800;
16715
+ function LiveView() {
16716
+ const canvasRef = (0, react.useRef)(null);
16717
+ const wsRef = (0, react.useRef)(null);
16718
+ const [status, setStatus] = (0, react.useState)("connecting");
16719
+ const [targets, setTargets] = (0, react.useState)([]);
16720
+ const [hostDown, setHostDown] = (0, react.useState)(false);
16721
+ /** 用户显式钉住的 target(null = 自动跟随最新)。 */
16722
+ const [pinnedId, setPinnedId] = (0, react.useState)(null);
16723
+ /** 连接代数:手动重连/换 target 时 +1。 */
16724
+ const [epoch, setEpoch] = (0, react.useState)(0);
16725
+ (0, react.useEffect)(() => {
16726
+ let alive = true;
16727
+ const poll = async () => {
16728
+ try {
16729
+ const { targets: list } = await api.cdpTargets();
16730
+ if (!alive) return;
16731
+ setHostDown(false);
16732
+ setTargets((prev) => JSON.stringify(prev) === JSON.stringify(list) ? prev : list);
16733
+ } catch {
16734
+ if (alive) setHostDown(true);
16735
+ }
16736
+ };
16737
+ poll();
16738
+ const timer = setInterval(() => {
16739
+ poll();
16740
+ }, 3e3);
16741
+ return () => {
16742
+ alive = false;
16743
+ clearInterval(timer);
16744
+ };
16745
+ }, []);
16746
+ /** 实际附加的 target:id 钉住且存活 → 它;否则自动跟随最新页。 */
16747
+ const effectiveId = (0, react.useMemo)(() => {
16748
+ if (pinnedId !== null && targets.some((tg) => tg.id === pinnedId)) return pinnedId;
16749
+ return targets.length > 0 ? targets[targets.length - 1].id : null;
16750
+ }, [pinnedId, targets]);
16751
+ (0, react.useEffect)(() => {
16752
+ if (effectiveId === null) {
16753
+ setStatus("idle");
16754
+ return;
16755
+ }
16756
+ let cancelled = false;
16757
+ let socket = null;
16758
+ let msgId = 0;
16759
+ setStatus("connecting");
16760
+ socket = new WebSocket(`${CDP_WS}/devtools/page/${effectiveId}`);
16761
+ wsRef.current = socket;
16762
+ const send = (method, params) => {
16763
+ if (socket !== null && socket.readyState === WebSocket.OPEN) socket.send(JSON.stringify({
16764
+ id: ++msgId,
16765
+ method,
16766
+ params: params ?? {}
16767
+ }));
16768
+ };
16769
+ const draw = (data) => {
16770
+ const el = canvasRef.current;
16771
+ if (el === null || cancelled) return;
16772
+ const img = new Image();
16773
+ img.onload = () => {
16774
+ if (cancelled) return;
16775
+ el.width = img.naturalWidth;
16776
+ el.height = img.naturalHeight;
16777
+ el.getContext("2d")?.drawImage(img, 0, 0);
16778
+ };
16779
+ img.src = `data:image/jpeg;base64,${data}`;
16780
+ };
16781
+ socket.onopen = () => {
16782
+ if (cancelled) return;
16783
+ setStatus("live");
16784
+ send("Page.enable");
16785
+ send("Runtime.enable");
16786
+ send("Emulation.setDeviceMetricsOverride", {
16787
+ width: VIEW_W,
16788
+ height: VIEW_H,
16789
+ deviceScaleFactor: 1,
16790
+ mobile: false
16791
+ });
16792
+ send("Page.startScreencast", {
16793
+ format: "jpeg",
16794
+ quality: 62,
16795
+ maxWidth: VIEW_W,
16796
+ maxHeight: VIEW_H,
16797
+ everyNthFrame: 1
16798
+ });
16799
+ };
16800
+ socket.onmessage = (event) => {
16801
+ const msg = JSON.parse(event.data);
16802
+ if (msg.method === "Page.screencastFrame") {
16803
+ const p = msg.params ?? {};
16804
+ if (typeof p.data === "string") draw(p.data);
16805
+ if (typeof p.screencastFrameId === "string") send("Page.screencastFrameAck", { screencastFrameId: p.screencastFrameId });
16806
+ }
16807
+ };
16808
+ socket.onclose = () => {
16809
+ if (!cancelled) setStatus("connecting");
16810
+ };
16811
+ socket.onerror = () => {
16812
+ if (!cancelled) setStatus("down");
16813
+ };
16814
+ return () => {
16815
+ cancelled = true;
16816
+ socket?.close();
16817
+ wsRef.current = null;
16818
+ };
16819
+ }, [effectiveId]);
16820
+ const sendInput = (method, params) => {
16821
+ wsRef.current?.send(JSON.stringify({
16822
+ id: Math.floor(Math.random() * 1e9),
16823
+ method,
16824
+ params
16825
+ }));
16826
+ };
16827
+ const scaleOf = (el) => {
16828
+ const shown = el.getBoundingClientRect().width;
16829
+ return shown > 0 ? VIEW_W / shown : 1;
16830
+ };
16831
+ const posOf = (e) => {
16832
+ const rect = e.currentTarget.getBoundingClientRect();
16833
+ const k = scaleOf(e.currentTarget);
16834
+ return {
16835
+ x: (e.clientX - rect.left) * k,
16836
+ y: (e.clientY - rect.top) * k
16837
+ };
16838
+ };
16839
+ const onPointerDown = (e) => {
16840
+ const p = posOf(e);
16841
+ sendInput("Input.dispatchMouseEvent", {
16842
+ type: "mousePressed",
16843
+ x: p.x,
16844
+ y: p.y,
16845
+ button: "left",
16846
+ clickCount: 1
16847
+ });
16848
+ };
16849
+ const onPointerUp = (e) => {
16850
+ const p = posOf(e);
16851
+ sendInput("Input.dispatchMouseEvent", {
16852
+ type: "mouseReleased",
16853
+ x: p.x,
16854
+ y: p.y,
16855
+ button: "left",
16856
+ clickCount: 1
16857
+ });
16858
+ };
16859
+ const onPointerMove = (e) => {
16860
+ if (e.buttons === 0) return;
16861
+ const p = posOf(e);
16862
+ sendInput("Input.dispatchMouseEvent", {
16863
+ type: "mouseMoved",
16864
+ x: p.x,
16865
+ y: p.y,
16866
+ button: "left"
16867
+ });
16868
+ };
16869
+ const onWheel = (e) => {
16870
+ const p = posOf(e);
16871
+ sendInput("Input.dispatchMouseEvent", {
16872
+ type: "mouseWheel",
16873
+ x: p.x,
16874
+ y: p.y,
16875
+ deltaX: e.deltaX,
16876
+ deltaY: e.deltaY
16877
+ });
16878
+ };
16879
+ const onKeyDown = (e) => {
16880
+ const code = {
16881
+ Enter: 13,
16882
+ Backspace: 8,
16883
+ Tab: 9,
16884
+ Escape: 27,
16885
+ ArrowUp: 38,
16886
+ ArrowDown: 40,
16887
+ ArrowLeft: 37,
16888
+ ArrowRight: 39
16889
+ }[e.key];
16890
+ if (code !== void 0) {
16891
+ sendInput("Input.dispatchKeyEvent", {
16892
+ type: "rawKeyDown",
16893
+ windowsVirtualKeyCode: code,
16894
+ key: e.key
16895
+ });
16896
+ sendInput("Input.dispatchKeyEvent", {
16897
+ type: "keyUp",
16898
+ windowsVirtualKeyCode: code,
16899
+ key: e.key
16900
+ });
16901
+ return;
16902
+ }
16903
+ if (e.key.length === 1) sendInput("Input.insertText", { text: e.key });
16904
+ };
16905
+ const statusText = hostDown || status === "down" ? t("browserLiveDown") : status === "live" ? targets.find((tg) => tg.id === effectiveId)?.url ?? t("browserLiveTargetNone") : effectiveId === null ? t("browserLiveTargetNone") : t("browserLiveConnecting");
16906
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
16907
+ className: "browserLive",
16908
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
16909
+ className: "browserLiveStatus",
16910
+ children: [
16911
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
16912
+ type: "button",
16913
+ onClick: () => {
16914
+ setEpoch((e) => e + 1);
16915
+ },
16916
+ children: t("refresh")
16917
+ }),
16918
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
16919
+ className: "browserLiveTarget",
16920
+ value: effectiveId ?? "",
16921
+ onChange: (e) => {
16922
+ setPinnedId(e.target.value === "" ? null : e.target.value);
16923
+ },
16924
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
16925
+ value: "",
16926
+ children: t("browserLiveFollowLatest")
16927
+ }), targets.map((tg) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
16928
+ value: tg.id,
16929
+ children: tg.title || tg.url
16930
+ }, tg.id))]
16931
+ }),
16932
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: statusText })
16933
+ ]
16934
+ }), effectiveId !== null && status !== "idle" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("canvas", {
16935
+ ref: canvasRef,
16936
+ className: "browserLiveCanvas",
16937
+ width: VIEW_W,
16938
+ height: VIEW_H,
16939
+ tabIndex: 0,
16940
+ onPointerDown,
16941
+ onPointerUp,
16942
+ onPointerMove,
16943
+ onWheel,
16944
+ onKeyDown
16945
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
16946
+ className: "browserStart",
16947
+ children: hostDown ? t("browserLiveDown") : t("browserLiveTargetNone")
16948
+ })]
16949
+ });
16950
+ }
16951
+ //#endregion
17031
16952
  //#region src/client/BrowserView.tsx
17032
16953
  /**
17033
16954
  * The built-in browser tab: an address bar plus a sandboxed iframe.
@@ -17106,6 +17027,9 @@ Mode: this is a continuable side conversation. Your answers stay in this side th
17106
17027
  const [embedBlocked, setEmbedBlocked] = (0, react.useState)(null);
17107
17028
  /** The user asked to load the refused site anyway (keeps the plain iframe). */
17108
17029
  const [forceEmbed, setForceEmbed] = (0, react.useState)(false);
17030
+ /** Agent 实况模式(CDP screencast):开启后本 tab 只显示 agent 无头
17031
+ * 浏览器的实况画面,地址栏/iframe 暂停。会话态开关,不持久化。 */
17032
+ const [live, setLive] = (0, react.useState)(false);
17109
17033
  (0, react.useEffect)(() => {
17110
17034
  if (url === void 0) return;
17111
17035
  let cancelled = false;
@@ -17215,6 +17139,17 @@ Mode: this is a continuable side conversation. Your answers stay in this side th
17215
17139
  },
17216
17140
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconLinkOutline14, {})
17217
17141
  }),
17142
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
17143
+ type: "button",
17144
+ className: sidebar_module_css_default.iconButton,
17145
+ "aria-label": t("browserLive"),
17146
+ title: t("browserLive"),
17147
+ "aria-pressed": live,
17148
+ onClick: () => {
17149
+ setLive((value) => !value);
17150
+ },
17151
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(VscRemoteExplorer, { size: 15 })
17152
+ }),
17218
17153
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
17219
17154
  type: "button",
17220
17155
  className: sidebar_module_css_default.iconButton,
@@ -17243,7 +17178,7 @@ Mode: this is a continuable side conversation. Your answers stay in this side th
17243
17178
  setLocalUnlock(false);
17244
17179
  }
17245
17180
  }),
17246
- url === void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
17181
+ live ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LiveView, {}) : url === void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
17247
17182
  className: sidebar_module_css_default.browserStart,
17248
17183
  children: t("browserStart")
17249
17184
  }) : embedBlocked !== null && !forceEmbed ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(BrowserEmbedBlocked, {
@@ -17575,252 +17510,14 @@ Mode: this is a continuable side conversation. Your answers stay in this side th
17575
17510
  ];
17576
17511
  }
17577
17512
  //#endregion
17578
- //#region src/client/PdfView.tsx
17579
- /** Browser-native PDF preview with an always-available download fallback. */
17580
- function PdfView(props) {
17581
- const { scope, path, title } = props;
17582
- const [load, setLoad] = (0, react.useState)({ status: "loading" });
17583
- const [interactionBlocked, setInteractionBlocked] = (0, react.useState)(false);
17584
- const frameRef = (0, react.useRef)(null);
17585
- const shieldRef = (0, react.useRef)(null);
17586
- (0, react.useEffect)(() => {
17587
- const controller = new AbortController();
17588
- let objectUrl;
17589
- setLoad({ status: "loading" });
17590
- (async () => {
17591
- try {
17592
- const response = await fetch(mediaUrl(scope, path), { signal: controller.signal });
17593
- if (!response.ok) throw new Error(`HTTP ${response.status}`);
17594
- const bytes = await response.arrayBuffer();
17595
- if (controller.signal.aborted) return;
17596
- objectUrl = URL.createObjectURL(new Blob([bytes], { type: "application/pdf" }));
17597
- setLoad({
17598
- status: "ready",
17599
- url: objectUrl
17600
- });
17601
- } catch (error) {
17602
- if (controller.signal.aborted) return;
17603
- setLoad({
17604
- status: "error",
17605
- message: error instanceof Error ? error.message : String(error)
17606
- });
17607
- }
17608
- })();
17609
- return () => {
17610
- controller.abort();
17611
- if (objectUrl !== void 0) URL.revokeObjectURL(objectUrl);
17612
- };
17613
- }, [
17614
- scope.sessionId,
17615
- scope.cwd,
17616
- path
17617
- ]);
17618
- (0, react.useEffect)(() => {
17619
- const block = () => {
17620
- setInteractionBlocked(true);
17621
- if (frameRef.current !== null) frameRef.current.style.pointerEvents = "none";
17622
- if (shieldRef.current !== null) shieldRef.current.style.pointerEvents = "auto";
17623
- };
17624
- const unblock = () => {
17625
- setInteractionBlocked(false);
17626
- if (frameRef.current !== null) frameRef.current.style.pointerEvents = "";
17627
- if (shieldRef.current !== null) shieldRef.current.style.pointerEvents = "none";
17628
- };
17629
- const blockForResize = (event) => {
17630
- const target = event.target;
17631
- if (target instanceof Element && target.closest(`.${sidebar_module_css_default.panelResize}, .${sidebar_module_css_default.divider}`) !== null) block();
17632
- };
17633
- document.addEventListener("dragstart", block, true);
17634
- document.addEventListener("dragend", unblock, true);
17635
- document.addEventListener("drop", unblock, true);
17636
- window.addEventListener("pointerdown", blockForResize, true);
17637
- window.addEventListener("pointerup", unblock, true);
17638
- window.addEventListener("pointercancel", unblock, true);
17639
- window.addEventListener("blur", unblock);
17640
- return () => {
17641
- document.removeEventListener("dragstart", block, true);
17642
- document.removeEventListener("dragend", unblock, true);
17643
- document.removeEventListener("drop", unblock, true);
17644
- window.removeEventListener("pointerdown", blockForResize, true);
17645
- window.removeEventListener("pointerup", unblock, true);
17646
- window.removeEventListener("pointercancel", unblock, true);
17647
- window.removeEventListener("blur", unblock);
17648
- };
17649
- }, []);
17650
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
17651
- className: sidebar_module_css_default.editorPdf,
17652
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
17653
- className: sidebar_module_css_default.editorPdfToolbar,
17654
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
17655
- className: sidebar_module_css_default.editorDownloadLink,
17656
- href: downloadUrl(scope, path),
17657
- download: true,
17658
- children: t("downloadToView")
17659
- })
17660
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
17661
- className: sidebar_module_css_default.editorPdfStage,
17662
- children: [
17663
- load.status === "loading" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
17664
- className: sidebar_module_css_default.editorPlaceholder,
17665
- children: t("loading")
17666
- }),
17667
- load.status === "error" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
17668
- className: sidebar_module_css_default.editorError,
17669
- children: load.message
17670
- }),
17671
- load.status === "ready" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("iframe", {
17672
- ref: frameRef,
17673
- className: clsx(sidebar_module_css_default.editorPdfFrame, interactionBlocked && sidebar_module_css_default.editorPdfFrameBlocked),
17674
- src: load.url,
17675
- title
17676
- }),
17677
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
17678
- ref: shieldRef,
17679
- className: clsx(sidebar_module_css_default.editorPdfDragShield, interactionBlocked && sidebar_module_css_default.editorPdfDragShieldActive),
17680
- "aria-hidden": "true"
17681
- })
17682
- ]
17683
- })]
17684
- });
17685
- }
17686
- //#endregion
17687
- //#region src/client/builtins/viewers.tsx
17688
- /**
17689
- * The 6 built-in file viewer descriptors: every preview surface is a
17690
- * registered viewer (image / pdf / markdown / html / code /
17691
- * binary-download), exactly like external plugins register theirs. Office
17692
- * previews (.docx / .xlsx / .pptx) are NOT built in anymore — they moved to
17693
- * the recommended office plugin (see plugins-viewers.ts), which registers
17694
- * the same ids through this service.
17695
- *
17696
- * The `binary-download` viewer sniffs NUL bytes via `detect` for unknown
17697
- * binaries and serves legacy doc/xls/ppt by extension; `code` is the
17698
- * catch-all (`exts: []`, lowest priority) that claims any file no other
17699
- * viewer did.
17700
- *
17701
- * The heavy viewers (the CodeMirror-backed markdown/html/code) render
17702
- * through {@link lazyChunkComponent} wrappers — their libraries are fetched
17703
- * only when such a file is first opened (see chunk-loader.ts). The
17704
- * descriptor metadata (id/exts/priority/detect) is identical either way,
17705
- * so matching semantics and external-plugin overrides are unaffected; the
17706
- * `component` wrapper keeps the descriptor contract `(props) => ReactNode`.
17707
- *
17708
- * Every viewer carries the declarative settings-surface fields — `title`
17709
- * and `icon` — so the Side card settings page can render the enable/disable
17710
- * inventory without hardcoding (eating our own dogfood).
17711
- */
17712
- /**
17713
- * Lazy wrapper over the chunk-resident viewer component. The `pick`
17714
- * function is module-level (stable identity — the wrapper effect depends
17715
- * on it); the cast bridges the chunk exports record to the descriptor prop
17716
- * shape (the view reads only its own subset of FileViewerProps).
17717
- */
17718
- const LazyTextEditor = lazyChunkComponent("editor", (mod) => mod.TextEditor);
17719
- /** The 6 built-in file viewer descriptors. */
17720
- function builtinViewers() {
17721
- return [
17722
- {
17723
- id: "image",
17724
- title: () => t("viewerImage"),
17725
- icon: (size) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconImageOutline16, { size }),
17726
- exts: [
17727
- "png",
17728
- "jpg",
17729
- "jpeg",
17730
- "gif",
17731
- "webp",
17732
- "svg",
17733
- "bmp",
17734
- "ico",
17735
- "avif"
17736
- ],
17737
- fetchStrategy: "mediaUrl",
17738
- component: ({ mediaUrl: url, title }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
17739
- className: sidebar_module_css_default.editorImageWrap,
17740
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
17741
- className: sidebar_module_css_default.editorImage,
17742
- src: url,
17743
- alt: title
17744
- })
17745
- })
17746
- },
17747
- {
17748
- id: "pdf",
17749
- title: () => t("viewerPdf"),
17750
- icon: (size) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconPdfOutline16, { size }),
17751
- exts: ["pdf"],
17752
- fetchStrategy: "mediaUrl",
17753
- component: ({ scope, path, title }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PdfView, {
17754
- scope,
17755
- path,
17756
- title
17757
- })
17758
- },
17759
- {
17760
- id: "markdown",
17761
- title: () => t("viewerMarkdown"),
17762
- icon: (size) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconMarkdownOutline16, { size }),
17763
- exts: ["md", "markdown"],
17764
- fetchStrategy: "fsRead",
17765
- component: (props) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LazyTextEditor, { ...props })
17766
- },
17767
- {
17768
- id: "html",
17769
- title: () => t("viewerHtml"),
17770
- icon: (size) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconHtmlOutline16, { size }),
17771
- exts: ["html", "htm"],
17772
- fetchStrategy: "fsRead",
17773
- settings: { toggles: [{
17774
- key: "htmlViewerNoSandbox",
17775
- title: () => t("settingsHtmlSandboxTitle"),
17776
- desc: () => t("settingsHtmlSandboxDesc")
17777
- }, {
17778
- key: "htmlViewerDefaultUnsafe",
17779
- title: () => t("settingsHtmlDefaultUnsafeTitle"),
17780
- desc: () => t("settingsHtmlDefaultUnsafeDesc")
17781
- }] },
17782
- component: (props) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LazyTextEditor, { ...props })
17783
- },
17784
- {
17785
- id: "code",
17786
- title: () => t("viewerCode"),
17787
- icon: (size) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconCodeOutline16, { size }),
17788
- exts: [],
17789
- priority: -100,
17790
- fetchStrategy: "fsRead",
17791
- component: (props) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LazyTextEditor, { ...props })
17792
- },
17793
- {
17794
- id: "binary-download",
17795
- title: () => t("viewerBinary"),
17796
- icon: (size) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconDownloadOutline16, { size }),
17797
- exts: [
17798
- "doc",
17799
- "xls",
17800
- "ppt"
17801
- ],
17802
- priority: -50,
17803
- fetchStrategy: "binary-download",
17804
- detect: (_path, head) => head.includes(0),
17805
- component: ({ scope, path }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(BinaryDownload, {
17806
- scope,
17807
- path
17808
- })
17809
- }
17810
- ];
17811
- }
17812
- //#endregion
17813
17513
  //#region src/client/builtins/index.ts
17814
17514
  /**
17815
- * Register all built-in tabs and viewers with the service. Returns a
17816
- * disposer that unregisters everything (cordis auto-invokes it on fiber
17817
- * disposal). The `ctx` is threaded into tab descriptors that need it
17818
- * (EditorHost reads `ctx.betterSidebar` for file-viewer matching).
17515
+ * Register all built-in tabs with the service. Returns a disposer that
17516
+ * unregisters everything (cordis auto-invokes it on fiber disposal).
17819
17517
  */
17820
17518
  function registerBuiltins(ctx, service, options = {}) {
17821
17519
  const disposers = [];
17822
17520
  for (const tab of builtinTabs(ctx, options)) disposers.push(service.registerTab(tab));
17823
- for (const viewer of builtinViewers()) disposers.push(service.registerFileViewer(viewer));
17824
17521
  return () => {
17825
17522
  for (const d of disposers) try {
17826
17523
  d();
@@ -20343,12 +20040,12 @@ Mode: this is a continuable side conversation. Your answers stay in this side th
20343
20040
  //#endregion
20344
20041
  //#region src/client/plugins-shared.ts
20345
20042
  /**
20346
- * Shared vocabulary of the recommended plugin catalogs: the entry shape and
20347
- * the GitHub topic URL. The two catalogs live in sibling modules —
20348
- * `plugins-tabs.ts` (tab registrations) and `plugins-viewers.ts` (file
20349
- * previewer registrations) and are shown in the two "add plugin" modals
20350
- * (Side card settings → the dashed cards at the end of the 侧边栏内容 /
20351
- * 文件预览 grids).
20043
+ * Shared vocabulary of the recommended plugin catalog: the entry shape and
20044
+ * the GitHub topic URL. The catalog lives in the sibling module
20045
+ * `plugins-tabs.ts` (tab registrations) and is shown in the "add plugin"
20046
+ * modal (Side card settings the dashed card at the end of the 侧边栏内容
20047
+ * grid). (v1.0.4: the file-previewer catalog was retired with the
20048
+ * file-viewer registry.)
20352
20049
  */
20353
20050
  /** The GitHub topic page listing every repo tagged `dsh-coding-sidebar`. */
20354
20051
  const PLUGIN_TOPIC_URL = "https://github.com/topics/dsh-coding-sidebar";
@@ -20431,40 +20128,16 @@ Mode: this is a continuable side conversation. Your answers stay in this side th
20431
20128
  }
20432
20129
  ];
20433
20130
  //#endregion
20434
- //#region src/client/plugins-viewers.ts
20435
- /**
20436
- * The built-in catalog of FILE-PREVIEWER plugins (file-type previewers),
20437
- * shown in the "add preview plugin" modal (Side card settings → 文件预览
20438
- * grid → the dashed card). Adding an entry: append one object here (unique
20439
- * `id` = npm package name, `url` = GitHub repo, `description` =
20440
- * i18n-friendly, `install` = the full shell command pre-filled into the
20441
- * install terminal — it starts with `cd ~/.dsh` so the install runs with
20442
- * the DSH home as the working directory). Data integrity is guarded by
20443
- * `tests/plugin-list.spec.ts`.
20444
- */
20445
- /** File-previewer plugins (alphabetical order). */
20446
- const builtinViewerPlugins = [{
20447
- id: "@huanlin/dsh-plugin-better-sidebar-plugin-office",
20448
- name: "Office 预览插件",
20449
- url: "https://github.com/HuanLinOTO/dsh-plugin-better-sidebar-plugin-office",
20450
- description: () => t("pluginOfficeDesc"),
20451
- install: "cd ~/.dsh && dsh plugin --profile web add @huanlin/dsh-plugin-better-sidebar-plugin-office"
20452
- }, {
20453
- id: "dsh-video-preview",
20454
- name: "视频预览插件",
20455
- url: "https://github.com/zemul/dsh-video-preview",
20456
- description: () => t("pluginVideoPreviewDesc"),
20457
- install: "cd ~/.dsh && dsh plugin --profile web add dsh-video-preview"
20458
- }];
20459
- //#endregion
20460
20131
  //#region src/client/add-plugin-modal.tsx
20461
20132
  /**
20462
- * The "add plugin" modals (Side card settings → the dashed cards at the
20463
- * end of the 侧边栏内容 / 文件预览 grids): declare that the sidebar's
20464
- * extension points tab pages and file previewers — are open to plugins
20465
- * (registered through `ctx.betterSidebar`), point at the GitHub topic page
20466
- * for discovery, and show the repo's recommended plugin catalog of the
20467
- * matching kind (name / url / description / install script).
20133
+ * The "add plugin" modal (Side card settings → the dashed card at the end
20134
+ * of the 侧边栏内容 grid): declares that the sidebar's tab extension point
20135
+ * is open to plugins (registered through `ctx.betterSidebar`), points at
20136
+ * the GitHub topic page for discovery, and shows the repo's recommended
20137
+ * plugin catalog (name / url / description / install script).
20138
+ *
20139
+ * (v1.0.4: the file-viewer extension point was retired with the file-viewer
20140
+ * registry — this modal now catalogs tab plugins only.)
20468
20141
  *
20469
20142
  * Per entry there are two actions:
20470
20143
  * - 「跳转」opens the plugin's repo in a REAL new browser tab (window.open
@@ -20479,20 +20152,15 @@ Mode: this is a continuable side conversation. Your answers stay in this side th
20479
20152
  * Modal must never be renderToString'd (same rule as the settingsFor popup
20480
20153
  * in SideCardSection); the modal itself mounts only while open.
20481
20154
  */
20482
- /** The catalog of one kind (kept in two repo files: plugins-tabs.ts /
20483
- * plugins-viewers.ts). */
20484
- function catalogOf(kind) {
20485
- return kind === "tab" ? builtinTabPlugins : builtinViewerPlugins;
20486
- }
20487
20155
  /** How long the "已复制" feedback stays on the copy button. */
20488
20156
  const COPIED_FEEDBACK_MS = 1500;
20489
20157
  /** The modal body: the GitHub topic button + the recommended plugin list
20490
20158
  * with per-entry jump/copy buttons (extracted for direct testing). */
20491
20159
  function PluginListBody(props) {
20492
- const { service, kind } = props;
20160
+ const { service } = props;
20493
20161
  const [copiedId, setCopiedId] = (0, react.useState)(null);
20494
20162
  const [query, setQuery] = (0, react.useState)("");
20495
- const catalog = catalogOf(kind);
20163
+ const catalog = builtinTabPlugins;
20496
20164
  const needle = query.trim().toLowerCase();
20497
20165
  const matches = (entry) => {
20498
20166
  if (needle === "") return true;
@@ -20619,12 +20287,12 @@ Mode: this is a continuable side conversation. Your answers stay in this side th
20619
20287
  }
20620
20288
  /** The modal itself (mounted only while open — see the module comment). */
20621
20289
  function AddPluginModal(props) {
20622
- const { service, onClose, kind } = props;
20290
+ const { service, onClose } = props;
20623
20291
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Modal, {
20624
20292
  open: true,
20625
20293
  onClose,
20626
- title: kind === "tab" ? t("addPluginsTabCard") : t("addPluginsViewerCard"),
20627
- description: kind === "tab" ? t("addPluginsTabDesc") : t("addPluginsViewerDesc"),
20294
+ title: t("addPluginsTabCard"),
20295
+ description: t("addPluginsTabDesc"),
20628
20296
  closeLabel: t("close"),
20629
20297
  className: SideCardSection_module_css_default.pluginModal,
20630
20298
  footer: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
@@ -20633,10 +20301,7 @@ Mode: this is a continuable side conversation. Your answers stay in this side th
20633
20301
  onClick: onClose,
20634
20302
  children: t("settingsDone")
20635
20303
  }),
20636
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PluginListBody, {
20637
- service,
20638
- kind
20639
- })
20304
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PluginListBody, { service })
20640
20305
  });
20641
20306
  }
20642
20307
  //#endregion
@@ -20655,8 +20320,9 @@ Mode: this is a continuable side conversation. Your answers stay in this side th
20655
20320
  * external plugins alike), laid out in a responsive grid that wraps
20656
20321
  * several cards per row — icon chip + title + type id, clicked to toggle
20657
20322
  * the switch persisted in `prefs.tabsEnabled[id]`.
20658
- * - 文件预览: one SMALL CARD per REGISTERED file viewer — icon chip + title
20659
- * + the extensions it covers, clicked to toggle `prefs.viewersEnabled[id]`.
20323
+ *
20324
+ * (v1.0.4: the 文件预览 viewer inventory was retired with the file-viewer
20325
+ * registry — file preview is the host's job now.)
20660
20326
  *
20661
20327
  * Every group lives in a container card (the DSH PluginCard recipe: l2
20662
20328
  * hairline, 16px radius, layer-3 fill) with a heading and an inventory count
@@ -20713,18 +20379,14 @@ Mode: this is a continuable side conversation. Your answers stay in this side th
20713
20379
  const preset = getShellPreset(prefs.titleBarPresetId);
20714
20380
  return preset !== void 0 ? `preset:${preset.id}` : "auto";
20715
20381
  }
20716
- /** Viewer inventory order: priority desc (the catch-all `code` comes last). */
20717
- function viewerOrder(a, b) {
20718
- return (b.priority ?? 0) - (a.priority ?? 0);
20719
- }
20720
20382
  /** Whether a feature declares any secondary settings (gear button shows). */
20721
20383
  function hasSettings(feature) {
20722
20384
  const settings = feature.settings;
20723
20385
  return settings !== void 0 && ((settings.toggles?.length ?? 0) > 0 || (settings.pluginToggles?.length ?? 0) > 0 || settings.render !== void 0);
20724
20386
  }
20725
- /** A feature's display name (viewers fall back to their id). */
20387
+ /** A feature's display name. */
20726
20388
  function featureNameOf(feature) {
20727
- return textOf("title" in feature ? feature.title : void 0) || feature.id;
20389
+ return textOf(feature.title) || feature.id;
20728
20390
  }
20729
20391
  /**
20730
20392
  * Merge one plugin-owned setting into a pluginSettings map (pure, v0.12.0+).
@@ -21034,7 +20696,7 @@ Mode: this is a continuable side conversation. Your answers stay in this side th
21034
20696
  });
21035
20697
  }
21036
20698
  /**
21037
- * The secondary settings popup body of one feature (tab or viewer):
20699
+ * The secondary settings popup body of one registered tab:
21038
20700
  * - the host-prefs `toggles` rows, then the plugin-owned `pluginToggles`
21039
20701
  * rows (their values live in `pluginSettings[feature.id]`, projected onto
21040
20702
  * the prefs face so the shared row renderer reads them);
@@ -21090,16 +20752,14 @@ Mode: this is a continuable side conversation. Your answers stay in this side th
21090
20752
  const [settingsFor, setSettingsFor] = (0, react.useState)(null);
21091
20753
  const [stripSettingsOpen, setStripSettingsOpen] = (0, react.useState)(false);
21092
20754
  const detectedEnv = (0, react.useMemo)(() => parseDesktopEnv(), []);
21093
- const [addPluginsOpen, setAddPluginsOpen] = (0, react.useState)(null);
20755
+ const [addPluginsOpen, setAddPluginsOpen] = (0, react.useState)(false);
21094
20756
  const optimisticRef = (0, react.useRef)(prefs);
21095
20757
  (0, react.useEffect)(() => {
21096
20758
  optimisticRef.current = prefs;
21097
20759
  }, [prefs]);
21098
20760
  const [tabs, setTabs] = (0, react.useState)(() => [...service.getTabs()].sort(tabOrder));
21099
- const [viewers, setViewers] = (0, react.useState)(() => [...service.getFileViewers()].sort(viewerOrder));
21100
20761
  (0, react.useEffect)(() => service.subscribe(() => {
21101
20762
  setTabs([...service.getTabs()].sort(tabOrder));
21102
- setViewers([...service.getFileViewers()].sort(viewerOrder));
21103
20763
  }), [service]);
21104
20764
  const revisionRef = (0, react.useRef)(void 0);
21105
20765
  const dirtyRef = (0, react.useRef)(false);
@@ -21168,13 +20828,6 @@ Mode: this is a continuable side conversation. Your answers stay in this side th
21168
20828
  [id]: next
21169
20829
  } });
21170
20830
  };
21171
- /** Flip one per-viewer enable switch (merge into the viewersEnabled map). */
21172
- const onToggleViewer = (id, next) => {
21173
- applyPref({ viewersEnabled: {
21174
- ...optimisticRef.current.viewersEnabled,
21175
- [id]: next
21176
- } });
21177
- };
21178
20831
  /** Flip one declaratively-declared toggle (a SidebarPrefs boolean field). */
21179
20832
  const onToggleSetting = (toggle, next) => {
21180
20833
  applyPref({ [toggle.key]: next });
@@ -21520,7 +21173,7 @@ Mode: this is a continuable side conversation. Your answers stay in this side th
21520
21173
  type: "button",
21521
21174
  className: clsx(SideCardSection_module_css_default.card, SideCardSection_module_css_default.addCard),
21522
21175
  onClick: () => {
21523
- setAddPluginsOpen("tab");
21176
+ setAddPluginsOpen(true);
21524
21177
  },
21525
21178
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
21526
21179
  className: SideCardSection_module_css_default.cardTop,
@@ -21538,49 +21191,6 @@ Mode: this is a continuable side conversation. Your answers stay in this side th
21538
21191
  })]
21539
21192
  })]
21540
21193
  }),
21541
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
21542
- className: SideCardSection_module_css_default.group,
21543
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
21544
- className: SideCardSection_module_css_default.groupHeading,
21545
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("settingsViewersTitle") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
21546
- className: SideCardSection_module_css_default.count,
21547
- children: viewers.length
21548
- })]
21549
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
21550
- className: SideCardSection_module_css_default.grid,
21551
- children: [viewers.map((viewer) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react.Fragment, { children: renderCard({
21552
- title: textOf(viewer.title) || viewer.id,
21553
- desc: viewer.exts.length === 0 ? t("settingsViewerCatchAll") : viewer.exts.join(" · "),
21554
- icon: iconOf(viewer.icon, 16),
21555
- enabled: prefs.viewersEnabled[viewer.id] !== false,
21556
- onToggle: (next) => {
21557
- onToggleViewer(viewer.id, next);
21558
- },
21559
- onOpenSettings: prefs.viewersEnabled[viewer.id] !== false && hasSettings(viewer) ? () => {
21560
- setSettingsFor(viewer);
21561
- } : void 0
21562
- }) }, viewer.id)), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
21563
- type: "button",
21564
- className: clsx(SideCardSection_module_css_default.card, SideCardSection_module_css_default.addCard),
21565
- onClick: () => {
21566
- setAddPluginsOpen("viewer");
21567
- },
21568
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
21569
- className: SideCardSection_module_css_default.cardTop,
21570
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
21571
- className: SideCardSection_module_css_default.cardIconChip,
21572
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPlusOutline16, { size: 16 })
21573
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
21574
- className: SideCardSection_module_css_default.cardTitle,
21575
- children: t("addPluginsViewerCard")
21576
- })]
21577
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
21578
- className: SideCardSection_module_css_default.cardDesc,
21579
- children: t("addPluginsViewerCardDesc")
21580
- })]
21581
- })]
21582
- })]
21583
- }),
21584
21194
  settingsFor !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Modal, {
21585
21195
  open: true,
21586
21196
  onClose: () => {
@@ -21661,12 +21271,11 @@ Mode: this is a continuable side conversation. Your answers stay in this side th
21661
21271
  }, prefs.customCss)]
21662
21272
  })
21663
21273
  }),
21664
- addPluginsOpen !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AddPluginModal, {
21274
+ addPluginsOpen && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AddPluginModal, {
21665
21275
  service,
21666
21276
  onClose: () => {
21667
- setAddPluginsOpen(null);
21668
- },
21669
- kind: addPluginsOpen
21277
+ setAddPluginsOpen(false);
21278
+ }
21670
21279
  }),
21671
21280
  error !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
21672
21281
  className: SideCardSection_module_css_default.error,
@@ -21780,6 +21389,7 @@ Mode: this is a continuable side conversation. Your answers stay in this side th
21780
21389
  const sidebarStore = createSidebarStore();
21781
21390
  const service = createBetterSidebarService(sidebarStore);
21782
21391
  ctx.provide("betterSidebar", service);
21392
+ ctx.effect(() => installNativeSidebarAvoidance(sidebarStore), "dsh-coding-sidebar: native-sidebar avoidance");
21783
21393
  const fallbackTitle = t("terminal");
21784
21394
  let terminalTitle = fallbackTitle;
21785
21395
  api.shellGet().then(({ name }) => {
@@ -21789,7 +21399,7 @@ Mode: this is a continuable side conversation. Your answers stay in this side th
21789
21399
  const tabs = allLeaves(snapshot.state.splits).flatMap((leaf) => leaf.tabs);
21790
21400
  for (const tab of tabs) if (tab.type === "terminal" && !isAgentTabId(tab.id) && tab.title === fallbackTitle) service.updateTab(tab.id, { title: name });
21791
21401
  }).catch(() => {});
21792
- ctx.effect(() => registerBuiltins(ctx, service, { terminalTitle: () => terminalTitle }), "dsh-coding-sidebar: register built-in tabs and viewers");
21402
+ ctx.effect(() => registerBuiltins(ctx, service, { terminalTitle: () => terminalTitle }), "dsh-coding-sidebar: register built-in tabs");
21793
21403
  const fail = (phase, error) => {
21794
21404
  console.error(`[dsh-coding-sidebar] ${phase} error:`, error);
21795
21405
  try {