dsh-coding-sidebar 1.0.2 → 1.0.4

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 (96) hide show
  1. package/README.md +27 -42
  2. package/lib/client-editor.js +449 -4278
  3. package/lib/client-registry.js +641 -1343
  4. package/lib/client-terminal.js +172 -262
  5. package/lib/client.js +645 -1347
  6. package/lib/index.js +24 -122
  7. package/lib/types/bundle-route.d.ts +1 -1
  8. package/lib/types/client/SideCardSection.d.ts +3 -3
  9. package/lib/types/client/TextEditor.d.ts +20 -10
  10. package/lib/types/client/add-plugin-modal.d.ts +0 -4
  11. package/lib/types/client/api.d.ts +8 -11
  12. package/lib/types/client/builtins/index.d.ts +10 -10
  13. package/lib/types/client/chunk-loader.d.ts +7 -8
  14. package/lib/types/client/locales.d.ts +0 -26
  15. package/lib/types/client/native-avoid.d.ts +2 -0
  16. package/lib/types/client/plugins-shared.d.ts +6 -6
  17. package/lib/types/client/service.d.ts +13 -83
  18. package/lib/types/context-types.d.ts +19 -10
  19. package/lib/types/index.d.ts +1 -1
  20. package/lib/types/prefs-shared.d.ts +1 -24
  21. package/package.json +26 -30
  22. package/src/bundle-route.ts +1 -1
  23. package/src/client/EditorHost.tsx +52 -122
  24. package/src/client/SandboxStatusBar.tsx +12 -9
  25. package/src/client/SideCardSection.module.css +2 -2
  26. package/src/client/SideCardSection.tsx +28 -81
  27. package/src/client/SideChatView.module.css +12 -12
  28. package/src/client/TextEditor.tsx +89 -266
  29. package/src/client/add-plugin-modal.tsx +16 -24
  30. package/src/client/api.ts +1 -25
  31. package/src/client/builtins/index.ts +10 -14
  32. package/src/client/chunk-loader.ts +7 -8
  33. package/src/client/index.tsx +12 -3
  34. package/src/client/locales-ar.ts +0 -6
  35. package/src/client/locales-de.ts +0 -6
  36. package/src/client/locales-fr.ts +0 -6
  37. package/src/client/locales-hi.ts +0 -6
  38. package/src/client/locales-id.ts +0 -6
  39. package/src/client/locales-it.ts +0 -6
  40. package/src/client/locales-ja.ts +0 -6
  41. package/src/client/locales-ko.ts +0 -6
  42. package/src/client/locales-nl.ts +0 -6
  43. package/src/client/locales-pl.ts +0 -6
  44. package/src/client/locales-pt.ts +0 -6
  45. package/src/client/locales-ru.ts +0 -6
  46. package/src/client/locales-sv.ts +0 -6
  47. package/src/client/locales-th.ts +0 -6
  48. package/src/client/locales-tr.ts +0 -6
  49. package/src/client/locales-vi.ts +0 -6
  50. package/src/client/locales-zh-HK.ts +0 -6
  51. package/src/client/locales-zh-MO.ts +0 -6
  52. package/src/client/locales-zh-TW.ts +0 -6
  53. package/src/client/locales.ts +0 -52
  54. package/src/client/native-avoid.ts +155 -0
  55. package/src/client/plugins-shared.ts +6 -6
  56. package/src/client/prefs.ts +0 -7
  57. package/src/client/service.ts +13 -150
  58. package/src/client/sidebar.module.css +1 -425
  59. package/src/config.ts +1 -4
  60. package/src/context-types.ts +12 -7
  61. package/src/index.ts +12 -78
  62. package/src/jobs-routes.ts +3 -2
  63. package/src/prefs-shared.ts +1 -27
  64. package/src/sidechat-routes.ts +13 -8
  65. package/src/subagent-live-route.ts +2 -1
  66. package/lib/client-mermaid.js +0 -200753
  67. package/lib/types/client/MarkdownHtml.d.ts +0 -32
  68. package/lib/types/client/PdfView.d.ts +0 -6
  69. package/lib/types/client/builtins/viewers.d.ts +0 -3
  70. package/lib/types/client/chunks/mermaid.d.ts +0 -10
  71. package/lib/types/client/editor-load.d.ts +0 -66
  72. package/lib/types/client/image-types.d.ts +0 -3
  73. package/lib/types/client/markdown-html.d.ts +0 -96
  74. package/lib/types/client/markdown-images.d.ts +0 -45
  75. package/lib/types/client/md-toc.d.ts +0 -4
  76. package/lib/types/client/mermaid-blocks.d.ts +0 -47
  77. package/lib/types/client/mermaid-sanitize.d.ts +0 -2
  78. package/lib/types/client/mermaid.d.ts +0 -12
  79. package/lib/types/client/pdf-types.d.ts +0 -2
  80. package/lib/types/client/plugins-viewers.d.ts +0 -3
  81. package/lib/types/html-route.d.ts +0 -59
  82. package/src/client/MarkdownHtml.tsx +0 -296
  83. package/src/client/PdfView.tsx +0 -110
  84. package/src/client/builtins/viewers.tsx +0 -125
  85. package/src/client/chunks/mermaid.tsx +0 -10
  86. package/src/client/editor-load.ts +0 -92
  87. package/src/client/image-types.ts +0 -8
  88. package/src/client/markdown-html.ts +0 -331
  89. package/src/client/markdown-images.ts +0 -137
  90. package/src/client/md-toc.tsx +0 -127
  91. package/src/client/mermaid-blocks.ts +0 -110
  92. package/src/client/mermaid-sanitize.ts +0 -93
  93. package/src/client/mermaid.tsx +0 -406
  94. package/src/client/pdf-types.ts +0 -4
  95. package/src/client/plugins-viewers.ts +0 -30
  96. package/src/html-route.ts +0 -106
package/lib/index.js CHANGED
@@ -42,15 +42,12 @@ const SIDEBAR_PREFS_DEFAULTS = {
42
42
  customCss: "",
43
43
  titleBarCompat: false,
44
44
  titleBarStripPx: 40,
45
- htmlViewerNoSandbox: false,
46
- htmlViewerDefaultUnsafe: false,
47
45
  browserNoSandbox: false,
48
46
  browserInterceptLinks: true,
49
47
  browserInterceptHttp: true,
50
48
  browserInterceptHttps: false,
51
49
  browserAllowedLoopback: "",
52
50
  tabsEnabled: {},
53
- viewersEnabled: {},
54
51
  pluginSettings: {}
55
52
  };
56
53
  //#endregion
@@ -114,15 +111,12 @@ const PrefsSchema = z.object({
114
111
  customCss: z.string(),
115
112
  titleBarCompat: z.boolean().default(false),
116
113
  titleBarStripPx: z.number().step(1).min(0).max(120).default(40),
117
- htmlViewerNoSandbox: z.boolean().default(false),
118
- htmlViewerDefaultUnsafe: z.boolean().default(false),
119
114
  browserNoSandbox: z.boolean().default(false),
120
115
  browserInterceptLinks: z.boolean().default(true),
121
116
  browserInterceptHttp: z.boolean().default(true),
122
117
  browserInterceptHttps: z.boolean().default(false),
123
118
  browserAllowedLoopback: z.string().default(""),
124
119
  tabsEnabled: z.dict(z.boolean()).default({}),
125
- viewersEnabled: z.dict(z.boolean()).default({}),
126
120
  pluginSettings: z.dict(z.dict(z.any())).default({})
127
121
  });
128
122
  //#endregion
@@ -541,60 +535,6 @@ async function searchFiles(root, query, opts = {}) {
541
535
  truncated
542
536
  };
543
537
  }
544
- /**
545
- * Decode a route pathname into the session + absolute file path. Rejects
546
- * a wrong prefix (404), an empty path, malformed percent encoding, and a
547
- * missing sessionId or file path (400). The caller still must bound the
548
- * decoded path with the workspace real-path guard — a decoded `..`
549
- * segment resolves outside the cwd and is refused there.
550
- */
551
- function decodeHtmlUrl(pathname) {
552
- if (!pathname.startsWith("/sidebar/html/")) return {
553
- ok: false,
554
- status: 404,
555
- message: "not an html route"
556
- };
557
- const rest = pathname.slice(14);
558
- if (rest === "") return {
559
- ok: false,
560
- status: 400,
561
- message: "invalid html route path"
562
- };
563
- let segments;
564
- try {
565
- segments = rest.split("/").map((segment) => decodeURIComponent(segment));
566
- } catch {
567
- return {
568
- ok: false,
569
- status: 400,
570
- message: "malformed URL encoding"
571
- };
572
- }
573
- const [sessionId, ...pathSegments] = segments;
574
- if (sessionId === void 0 || sessionId === "") return {
575
- ok: false,
576
- status: 400,
577
- message: "sessionId and file path are required"
578
- };
579
- const unc = pathSegments[0] === "";
580
- const tail = unc ? pathSegments.slice(1) : pathSegments;
581
- if (tail.length === 0 || tail.some((segment) => segment === "")) return {
582
- ok: false,
583
- status: 400,
584
- message: "sessionId and file path are required"
585
- };
586
- let path;
587
- if (unc) path = `//${tail.join("/")}`;
588
- else if (/^[A-Za-z]:$/.test(tail[0] ?? "")) path = tail.join("/");
589
- else path = `/${tail.join("/")}`;
590
- return {
591
- ok: true,
592
- ref: {
593
- sessionId,
594
- path
595
- }
596
- };
597
- }
598
538
  //#endregion
599
539
  //#region src/browser-probe.ts
600
540
  /**
@@ -692,11 +632,7 @@ function isTrustedApiRequest(request, trustedHosts) {
692
632
  * only allowlisted chunk names are servable (no path traversal).
693
633
  */
694
634
  /** The chunk names the client may request (mirror of src/client/chunk-loader.ts). */
695
- const CHUNK_NAMES = [
696
- "terminal",
697
- "editor",
698
- "mermaid"
699
- ];
635
+ const CHUNK_NAMES = ["terminal", "editor"];
700
636
  /** Directory of this host-half module (lib/ — the chunk scripts live next to it). */
701
637
  const LIB_DIR = dirname(fileURLToPath(import.meta.url));
702
638
  /** sha1 content hash shortened to 12 hex chars (same shape as the client-modules rev). */
@@ -2962,7 +2898,7 @@ const MIRROR_MAX_ENTRIES = 200;
2962
2898
  * The live job_output mirror: subscribes to the session append feed and
2963
2899
  * caches the job_output traces the session store's own log can lag behind
2964
2900
  * (after a host restart the store session stays frozen at its rehydration
2965
- * boundary, so `session.events` misses everything appended since — the very
2901
+ * boundary, so a stale snapshot misses everything appended since — the very
2966
2902
  * reads the pane exists to show). Zero DSH writes: the api-proxy pushes the
2967
2903
  * same feed to browsers.
2968
2904
  */
@@ -3025,7 +2961,8 @@ function buildJobsApi(ctx, outputLimit) {
3025
2961
  const sessionId = requireString(payload, "sessionId");
3026
2962
  const id = requireString(payload, "id");
3027
2963
  const bySeq = /* @__PURE__ */ new Map();
3028
- for (const event of ctx.sessions.get(sessionId)?.events ?? []) {
2964
+ const store = ctx.sessions.get(sessionId);
2965
+ for (const event of (store?.snapshotEvents !== void 0 ? store.snapshotEvents() : []) ?? []) {
3029
2966
  const trace = traceOf(event);
3030
2967
  if (trace !== void 0) bySeq.set(trace.seq, trace);
3031
2968
  }
@@ -3420,7 +3357,8 @@ function buildSubagentLiveApi(ctx) {
3420
3357
  if (entry.kind !== "child" || entry.activity !== "running") continue;
3421
3358
  if (entry.label?.startsWith("Side: ") ?? false) continue;
3422
3359
  try {
3423
- const activity = lastActivity(ctx.sessions.get(entry.id)?.events ?? [], 12);
3360
+ const stored = ctx.sessions.get(entry.id);
3361
+ const activity = lastActivity(stored?.snapshotEvents !== void 0 ? stored.snapshotEvents() : [], 12);
3424
3362
  if (activity.text !== void 0 || activity.tool !== void 0) live[entry.id] = activity;
3425
3363
  } catch {}
3426
3364
  }
@@ -3480,8 +3418,10 @@ async function composeChildSetup(ctx, presetId) {
3480
3418
  async function composePersistedSetup(ctx, childId) {
3481
3419
  const persistence = ctx.get("sessionPersistence");
3482
3420
  if (persistence === void 0) return () => Promise.resolve();
3483
- const inspected = await persistence.inspect(childId);
3484
- const presetId = resolvePresetId(inspected.meta, inspected.events);
3421
+ const handle = await persistence.open(childId, "read");
3422
+ const { events } = await handle.read();
3423
+ const presetId = resolvePresetId(handle.header, events);
3424
+ await handle.close();
3485
3425
  const presets = ctx.get("agentPresets");
3486
3426
  if (presets === void 0 || presetId === void 0) return () => Promise.resolve();
3487
3427
  const resolved = await presets.resolve(presetId);
@@ -3542,8 +3482,8 @@ function buildSidechatApi(ctx) {
3542
3482
  const parent = liveThreadAgent(ctx, sessionId);
3543
3483
  if (parent === void 0) throw new SidebarError("sidechat-error", `parent session "${sessionId}" is not running`, 409);
3544
3484
  const parentSession = parent.session;
3545
- const inheritance = buildSidechatInheritance(parentSession.events);
3546
- const { agentPreset, setup } = await composeChildSetup(ctx, resolvePresetId(parentSession.header, parentSession.events));
3485
+ const inheritance = buildSidechatInheritance(parentSession.snapshotEvents());
3486
+ const { agentPreset, setup } = await composeChildSetup(ctx, resolvePresetId(parentSession.header, parentSession.snapshotEvents()));
3547
3487
  const childId = `session-${randomUUID()}`;
3548
3488
  const label = question === "" ? SIDE_NEW_THREAD_TITLE : sideLabel(question);
3549
3489
  const descriptor = snapshotSubagentDescriptor({
@@ -3565,7 +3505,7 @@ function buildSidechatApi(ctx) {
3565
3505
  meta: {
3566
3506
  ...parentSession.header.cwd === void 0 ? {} : { cwd: parentSession.header.cwd },
3567
3507
  parentSession: parentSession.id,
3568
- seedLength: seed.length,
3508
+ isSeeded: seed.length > 0,
3569
3509
  origin: "subagent",
3570
3510
  delegationDepth: (parentSession.header.delegationDepth ?? 0) + 1,
3571
3511
  ...agentPreset === void 0 ? {} : { agentPreset }
@@ -3622,7 +3562,7 @@ function buildSidechatApi(ctx) {
3622
3562
  throw new SidebarError("sidechat-error", `thread resume failed: ${error instanceof Error ? error.message : String(error)}`, 500);
3623
3563
  }
3624
3564
  }
3625
- if (boundaryDelivered(agent.session.events)) admitFollowup(agent, textPrompt(text));
3565
+ if (boundaryDelivered(agent.session.snapshotEvents())) admitFollowup(agent, textPrompt(text));
3626
3566
  else {
3627
3567
  const parts = [SIDE_BOUNDARY_PROMPT];
3628
3568
  const snapshot = pendingSnapshots.get(childId);
@@ -3668,8 +3608,10 @@ function buildSidechatApi(ctx) {
3668
3608
  }
3669
3609
  const persistence = ctx.get("sessionPersistence");
3670
3610
  if (persistence !== void 0) try {
3671
- const inspected = await persistence.inspect(childId);
3672
- const preset = resolvePresetId(inspected.meta, inspected.events);
3611
+ const handle = await persistence.open(childId, "read");
3612
+ const { events } = await handle.read();
3613
+ const preset = resolvePresetId(handle.header, events);
3614
+ await handle.close();
3673
3615
  return {
3674
3616
  live: false,
3675
3617
  ...preset === void 0 ? {} : { preset }
@@ -3683,8 +3625,8 @@ function buildSidechatApi(ctx) {
3683
3625
  //#region src/index.ts
3684
3626
  /**
3685
3627
  * dsh-coding-sidebar host half: the /sidebar JSON API (explorer listing, file
3686
- * read/write, git), the /sidebar/file media route (images), the /sidebar/html
3687
- * preview route, the /sidebar/bundle lazy-chunk route (client code splits),
3628
+ * read/write, git), the /sidebar/file media route (file bytes / downloads),
3629
+ * the /sidebar/bundle lazy-chunk route (client code splits),
3688
3630
  * and the terminal WebSocket upgrade. Every route passes the same
3689
3631
  * browser-trust fence as the /api gateway — Host-header loopback or the
3690
3632
  * web runtime's `trustedHosts` (LAN IP literals sampled at boot plus
@@ -3715,10 +3657,7 @@ const MEDIA_TYPES = {
3715
3657
  ".svg": "image/svg+xml",
3716
3658
  ".bmp": "image/bmp",
3717
3659
  ".ico": "image/x-icon",
3718
- ".avif": "image/avif",
3719
- ".pdf": "application/pdf",
3720
- ".html": "text/html",
3721
- ".htm": "text/html"
3660
+ ".avif": "image/avif"
3722
3661
  };
3723
3662
  /** Content type served by /sidebar/file (binary-safe fallback for unknowns). */
3724
3663
  function mediaTypeForPath(path) {
@@ -3749,7 +3688,9 @@ async function sessionCwdOf(ctx, sessionId, clientCwd) {
3749
3688
  }
3750
3689
  const persistence = ctx.get("sessionPersistence");
3751
3690
  if (persistence !== void 0) {
3752
- const metaCwd = (await persistence.inspect(sessionId)).meta.cwd;
3691
+ const handle = await persistence.open(sessionId, "read");
3692
+ const metaCwd = handle.header.cwd;
3693
+ await handle.close();
3753
3694
  if (metaCwd !== void 0 && metaCwd !== "") try {
3754
3695
  return requireAbsolute(metaCwd);
3755
3696
  } catch {
@@ -4294,45 +4235,6 @@ function apply(ctx, config) {
4294
4235
  }
4295
4236
  }
4296
4237
  }), "dsh-coding-sidebar: /sidebar/file media route");
4297
- ctx.effect(() => ctx.webServer.register({
4298
- kind: "prefix",
4299
- path: "/sidebar/html",
4300
- handler: async (req, res) => {
4301
- if (!fence(req)) {
4302
- res.writeHead(403);
4303
- res.end("forbidden");
4304
- return;
4305
- }
4306
- if (req.method !== "GET") {
4307
- res.writeHead(405);
4308
- res.end();
4309
- return;
4310
- }
4311
- try {
4312
- const decoded = decodeHtmlUrl(new URL(req.url ?? "/", "http://dsh.internal").pathname);
4313
- if (!decoded.ok) {
4314
- writeError(res, new SidebarError("bad-request", decoded.message, decoded.status));
4315
- return;
4316
- }
4317
- const { sessionId, path } = decoded.ref;
4318
- const absolute = await ensureWorkspacePath(await sessionCwdOf(ctx, sessionId), path);
4319
- const info = await stat(absolute);
4320
- if (!info.isFile() || info.size > resolved.mediaLimit) throw new SidebarError("fs-error", "not a file or too large", 400);
4321
- const type = mediaTypeForPath(absolute);
4322
- const body = await readFile(absolute);
4323
- res.writeHead(200, {
4324
- "content-type": type === "text/html" ? "text/html; charset=utf-8" : type,
4325
- "cache-control": "no-cache",
4326
- "x-content-type-options": "nosniff",
4327
- "referrer-policy": "no-referrer",
4328
- "content-security-policy": "sandbox allow-scripts allow-popups allow-downloads allow-modals; object-src 'none'"
4329
- });
4330
- res.end(body);
4331
- } catch (error) {
4332
- writeError(res, error);
4333
- }
4334
- }
4335
- }), "dsh-coding-sidebar: /sidebar/html preview route");
4336
4238
  const wss = new WebSocketServer({ noServer: true });
4337
4239
  ctx.effect(() => ctx.webServer.registerUpgrade({
4338
4240
  path: "/sidebar/ws/terminal",
@@ -1,6 +1,6 @@
1
1
  import type { Context, SidebarHttpRequest, SidebarHttpResponse } from './context-types.ts';
2
2
  /** The chunk names the client may request (mirror of src/client/chunk-loader.ts). */
3
- export declare const CHUNK_NAMES: readonly ["terminal", "editor", "mermaid"];
3
+ export declare const CHUNK_NAMES: readonly ["terminal", "editor"];
4
4
  export type ChunkName = (typeof CHUNK_NAMES)[number];
5
5
  /**
6
6
  * Build the /sidebar/bundle route handler. `fence` is the shared browser-
@@ -1,7 +1,7 @@
1
1
  import type { PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots';
2
2
  import { type SidebarPrefs } from '../prefs-shared.ts';
3
3
  import type { SidebarStore } from './state.ts';
4
- import type { BetterSidebarService, FileViewerDescriptor, SidebarSettingToggle, TabDescriptor } from './service.ts';
4
+ import type { BetterSidebarService, SidebarSettingToggle, TabDescriptor } from './service.ts';
5
5
  /** Injected business face: the shared store (prefs cache) + the sidebar service (registries). */
6
6
  export interface SideCardSectionInjected {
7
7
  store: SidebarStore;
@@ -43,7 +43,7 @@ export declare function FeatureSettingsRows(props: {
43
43
  valueSource?: (key: string) => unknown;
44
44
  }): import("react").JSX.Element;
45
45
  /**
46
- * The secondary settings popup body of one feature (tab or viewer):
46
+ * The secondary settings popup body of one registered tab:
47
47
  * - the host-prefs `toggles` rows, then the plugin-owned `pluginToggles`
48
48
  * rows (their values live in `pluginSettings[feature.id]`, projected onto
49
49
  * the prefs face so the shared row renderer reads them);
@@ -53,7 +53,7 @@ export declare function FeatureSettingsRows(props: {
53
53
  * open-behavior picker) and still ship a custom configuration area.
54
54
  */
55
55
  export declare function SettingsBody(props: {
56
- feature: TabDescriptor | FileViewerDescriptor;
56
+ feature: TabDescriptor;
57
57
  prefs: SidebarPrefs;
58
58
  store: SidebarStore;
59
59
  service: BetterSidebarService;
@@ -1,10 +1,20 @@
1
- import type { FileViewerProps } from './service.ts';
2
- /**
3
- * The sandbox tokens of the HTML preview iframe. NO allow-same-origin (the
4
- * preview must stay in an opaque origin — with the route's own origin it
5
- * could read session data) and NO allow-top-navigation (a previewed page
6
- * must not hijack the GUI). The user can disable the sandbox per-feature
7
- * in the side card settings (warned); the toggle below reflects it.
8
- */
9
- export declare const HTML_IFRAME_SANDBOX = "allow-scripts allow-popups allow-downloads allow-modals";
10
- export declare function TextEditor(props: FileViewerProps): import("react").JSX.Element;
1
+ import type { EditorToolbarControls, EditorToolbarState } from './service.ts';
2
+ import type { Context } from '../context-types.ts';
3
+ import type { SessionScope } from './api.ts';
4
+ import type { SidebarStore } from './state.ts';
5
+ /** Props of the sidebar text editor (the editor tab's content). */
6
+ export interface TextEditorProps {
7
+ ctx: Context;
8
+ store?: SidebarStore;
9
+ scope: SessionScope;
10
+ path: string;
11
+ /** fs.read text content (undefined while loading / for non-editable reads). */
12
+ content?: string;
13
+ truncated?: boolean;
14
+ /** 'host' skips the own toolbar row — the editor host's merged-mode header
15
+ * renders it instead, fed through the two callbacks below. */
16
+ toolbar?: 'self' | 'host';
17
+ onToolbarState?: (state: EditorToolbarState) => void;
18
+ onToolbarControls?: (controls: EditorToolbarControls | null) => void;
19
+ }
20
+ export declare function TextEditor(props: TextEditorProps): import("react").JSX.Element;
@@ -1,15 +1,11 @@
1
1
  import type { BetterSidebarService } from './service.ts';
2
- /** Which extension point the modal is adding a plugin for. */
3
- export type PluginKind = 'tab' | 'viewer';
4
2
  /** The modal body: the GitHub topic button + the recommended plugin list
5
3
  * with per-entry jump/copy buttons (extracted for direct testing). */
6
4
  export declare function PluginListBody(props: {
7
5
  service: BetterSidebarService;
8
- kind: PluginKind;
9
6
  }): import("react").JSX.Element;
10
7
  /** The modal itself (mounted only while open — see the module comment). */
11
8
  export declare function AddPluginModal(props: {
12
9
  service: BetterSidebarService;
13
10
  onClose: () => void;
14
- kind: PluginKind;
15
11
  }): import("react").JSX.Element;
@@ -1,3 +1,11 @@
1
+ /**
2
+ * Typed fetch wrapper over the /sidebar JSON API. Every call posts to
3
+ * `/sidebar/api/<method>` with the sessionId and — when known — the session's
4
+ * cwd from the client's own list summary. The host prefers its attached
5
+ * session header and uses the summary cwd only while the session is still
6
+ * hydrating at page load (a detached session would otherwise fail the
7
+ * request). Failures surface as {@link SidebarApiError} with the wire code.
8
+ */
1
9
  import type { LastActivity } from '../subagent-activity.ts';
2
10
  import type { SidechatThreadInfo } from '../sidechat-core.ts';
3
11
  import type { BrowserProbeResult } from './browser.ts';
@@ -259,17 +267,6 @@ export declare const api: {
259
267
  started: boolean;
260
268
  }>;
261
269
  };
262
- /** Absolute URL of the media route for one path (images only). */
263
- export declare function mediaUrl(scope: SessionScope, path: string): string;
264
270
  /** Absolute URL of the download route: serves raw bytes (binary-safe) with
265
271
  * `Content-Disposition: attachment`, so the browser saves the file. */
266
272
  export declare function downloadUrl(scope: SessionScope, path: string): string;
267
- /**
268
- * Absolute URL of the HTML preview route (see html-route.ts): the path is
269
- * fully encoded so the previewed page's relative assets resolve back into
270
- * the same route with the session scope intact. The UNC marker is
271
- * platform-neutral — the host's requireAbsolute resolves the decoded
272
- * forward-slash `//server/share/...` form on both win32 and POSIX — so no
273
- * client-side platform signal is needed.
274
- */
275
- export declare function htmlUrl(scope: SessionScope, path: string): string;
@@ -1,18 +1,18 @@
1
1
  /**
2
- * Built-in registration: the plugin registers its own tab pages and file
3
- * previewers through the same {@link BetterSidebarService} external plugins
4
- * use — eating its own dogfood. The descriptors live next to their feature
5
- * modules (tabs.tsx / viewers.tsx); this module only aggregates them and
6
- * owns the disposer lifecycle (cordis auto-invokes it on fiber disposal,
7
- * HMR-safe).
2
+ * Built-in registration: the plugin registers its own tab pages through the
3
+ * same {@link BetterSidebarService} external plugins use — eating its own
4
+ * dogfood. The descriptors live next to their feature modules (tabs.tsx);
5
+ * this module only aggregates them and owns the disposer lifecycle (cordis
6
+ * auto-invokes it on fiber disposal, HMR-safe).
7
+ *
8
+ * (v1.0.4: the built-in file viewers were retired with the file-viewer
9
+ * registry — file preview is the host's job now.)
8
10
  */
9
11
  import type { Context } from '../../context-types.ts';
10
12
  import type { BetterSidebarService } from '../service.ts';
11
13
  import { type BuiltinTabOptions } from './tabs.tsx';
12
14
  /**
13
- * Register all built-in tabs and viewers with the service. Returns a
14
- * disposer that unregisters everything (cordis auto-invokes it on fiber
15
- * disposal). The `ctx` is threaded into tab descriptors that need it
16
- * (EditorHost reads `ctx.betterSidebar` for file-viewer matching).
15
+ * Register all built-in tabs with the service. Returns a disposer that
16
+ * unregisters everything (cordis auto-invokes it on fiber disposal).
17
17
  */
18
18
  export declare function registerBuiltins(ctx: Context, service: BetterSidebarService, options?: BuiltinTabOptions): () => void;
@@ -1,11 +1,10 @@
1
1
  /**
2
- * Lazy chunk loader for the client bundle. The heavy preview/terminal
3
- * libraries (CodeMirror, xterm — the editor/terminal stacks, several MB)
4
- * live in separate build-time bundles (`lib/client-<name>.js`) fetched only
5
- * on first use of the feature that needs them, so startup downloads/parses
6
- * only the ~1MB core bundle. (The office stack Univer / docx-preview /
7
- * pptx-renderer is no longer bundled here: Office previews moved to the
8
- * recommended office plugin, see plugins-viewers.ts.)
2
+ * Lazy chunk loader for the client bundle. The heavy editor/terminal
3
+ * libraries (CodeMirror, xterm — several MB) live in separate build-time
4
+ * bundles (`lib/client-<name>.js`) fetched only on first use of the feature
5
+ * that needs them, so startup downloads/parses only the ~1MB core bundle.
6
+ * (v1.0.4: the mermaid chunk was retired with the file-viewer line; the
7
+ * office stack moved to the ecosystem even earlier.)
9
8
  *
10
9
  * How a chunk script works (see tsdown.config.ts chunkBundle):
11
10
  *
@@ -49,7 +48,7 @@
49
48
  * client.js); an edit that does land while a core HMR happens is caught by
50
49
  * the ETag comparison on the next activation.
51
50
  */
52
- export type ChunkName = 'terminal' | 'editor' | 'mermaid';
51
+ export type ChunkName = 'terminal' | 'editor';
53
52
  /** The module exports a chunk factory provides (namespace-ish record). */
54
53
  export type ChunkExports = Record<string, unknown>;
55
54
  /**
@@ -94,14 +94,6 @@ export declare const zh: {
94
94
  terminalDepsFailed: string;
95
95
  terminalDepsHint: string;
96
96
  terminalDepsProfile: string;
97
- preview: string;
98
- toc: string;
99
- edit: string;
100
- mermaidError: string;
101
- mermaidZoomIn: string;
102
- mermaidZoomOut: string;
103
- mermaidZoomReset: string;
104
- mermaidZoomHint: string;
105
97
  refresh: string;
106
98
  refreshUnsavedConfirm: string;
107
99
  save: string;
@@ -244,16 +236,8 @@ export declare const zh: {
244
236
  settingsShellArgsDesc: string;
245
237
  settingsShellArgsPlaceholder: string;
246
238
  settingsTabsTitle: string;
247
- settingsViewersTitle: string;
248
239
  settingsGeneralTitle: string;
249
240
  settingsPopup: string;
250
- settingsViewerCatchAll: string;
251
- viewerImage: string;
252
- viewerPdf: string;
253
- viewerMarkdown: string;
254
- viewerCode: string;
255
- viewerBinary: string;
256
- viewerHtml: string;
257
241
  browser: string;
258
242
  browserPlaceholder: string;
259
243
  browserGo: string;
@@ -264,14 +248,9 @@ export declare const zh: {
264
248
  browserBlockedLoopback: string;
265
249
  browserInvalid: string;
266
250
  browserNoSandboxWarning: string;
267
- htmlNoSandboxWarning: string;
268
251
  sandboxStatusOn: string;
269
252
  sandboxUnlock: string;
270
253
  sandboxRestore: string;
271
- settingsHtmlDefaultUnsafeTitle: string;
272
- settingsHtmlDefaultUnsafeDesc: string;
273
- settingsHtmlSandboxTitle: string;
274
- settingsHtmlSandboxDesc: string;
275
254
  settingsBrowserSandboxTitle: string;
276
255
  settingsBrowserSandboxDesc: string;
277
256
  settingsBrowserLinksTitle: string;
@@ -352,10 +331,7 @@ export declare const zh: {
352
331
  jobKillError: string;
353
332
  addPluginsTabCard: string;
354
333
  addPluginsTabCardDesc: string;
355
- addPluginsViewerCard: string;
356
- addPluginsViewerCardDesc: string;
357
334
  addPluginsTabDesc: string;
358
- addPluginsViewerDesc: string;
359
335
  addPluginsBrowseMore: string;
360
336
  addPluginsSearch: string;
361
337
  addPluginsNoMatch: string;
@@ -363,7 +339,6 @@ export declare const zh: {
363
339
  addPluginsEmpty: string;
364
340
  openPlugin: string;
365
341
  copyInstall: string;
366
- pluginOfficeDesc: string;
367
342
  pluginFlowglassDesc: string;
368
343
  pluginGitForgeDesc: string;
369
344
  pluginGitRemotesDesc: string;
@@ -371,7 +346,6 @@ export declare const zh: {
371
346
  pluginSidebarQaDesc: string;
372
347
  pluginSshTunnelDesc: string;
373
348
  pluginTurnReviewDesc: string;
374
- pluginVideoPreviewDesc: string;
375
349
  pluginDocsPanelDesc: string;
376
350
  pluginEgoBrowserDesc: string;
377
351
  };
@@ -0,0 +1,2 @@
1
+ import type { SidebarStore } from './state.ts';
2
+ export declare function installNativeSidebarAvoidance(store: SidebarStore): () => void;
@@ -1,10 +1,10 @@
1
1
  /**
2
- * Shared vocabulary of the recommended plugin catalogs: the entry shape and
3
- * the GitHub topic URL. The two catalogs live in sibling modules —
4
- * `plugins-tabs.ts` (tab registrations) and `plugins-viewers.ts` (file
5
- * previewer registrations) and are shown in the two "add plugin" modals
6
- * (Side card settings → the dashed cards at the end of the 侧边栏内容 /
7
- * 文件预览 grids).
2
+ * Shared vocabulary of the recommended plugin catalog: the entry shape and
3
+ * the GitHub topic URL. The catalog lives in the sibling module
4
+ * `plugins-tabs.ts` (tab registrations) and is shown in the "add plugin"
5
+ * modal (Side card settings the dashed card at the end of the 侧边栏内容
6
+ * grid). (v1.0.4: the file-previewer catalog was retired with the
7
+ * file-viewer registry.)
8
8
  */
9
9
  /** The GitHub topic page listing every repo tagged `dsh-coding-sidebar`. */
10
10
  export declare const PLUGIN_TOPIC_URL = "https://github.com/topics/dsh-coding-sidebar";