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.
- package/README.md +27 -42
- package/lib/client-editor.js +449 -4278
- package/lib/client-registry.js +641 -1343
- package/lib/client-terminal.js +172 -262
- package/lib/client.js +645 -1347
- package/lib/index.js +24 -122
- package/lib/types/bundle-route.d.ts +1 -1
- package/lib/types/client/SideCardSection.d.ts +3 -3
- package/lib/types/client/TextEditor.d.ts +20 -10
- package/lib/types/client/add-plugin-modal.d.ts +0 -4
- package/lib/types/client/api.d.ts +8 -11
- package/lib/types/client/builtins/index.d.ts +10 -10
- package/lib/types/client/chunk-loader.d.ts +7 -8
- package/lib/types/client/locales.d.ts +0 -26
- package/lib/types/client/native-avoid.d.ts +2 -0
- package/lib/types/client/plugins-shared.d.ts +6 -6
- package/lib/types/client/service.d.ts +13 -83
- package/lib/types/context-types.d.ts +19 -10
- package/lib/types/index.d.ts +1 -1
- package/lib/types/prefs-shared.d.ts +1 -24
- package/package.json +26 -30
- package/src/bundle-route.ts +1 -1
- package/src/client/EditorHost.tsx +52 -122
- package/src/client/SandboxStatusBar.tsx +12 -9
- package/src/client/SideCardSection.module.css +2 -2
- package/src/client/SideCardSection.tsx +28 -81
- package/src/client/SideChatView.module.css +12 -12
- package/src/client/TextEditor.tsx +89 -266
- package/src/client/add-plugin-modal.tsx +16 -24
- package/src/client/api.ts +1 -25
- package/src/client/builtins/index.ts +10 -14
- package/src/client/chunk-loader.ts +7 -8
- package/src/client/index.tsx +12 -3
- package/src/client/locales-ar.ts +0 -6
- package/src/client/locales-de.ts +0 -6
- package/src/client/locales-fr.ts +0 -6
- package/src/client/locales-hi.ts +0 -6
- package/src/client/locales-id.ts +0 -6
- package/src/client/locales-it.ts +0 -6
- package/src/client/locales-ja.ts +0 -6
- package/src/client/locales-ko.ts +0 -6
- package/src/client/locales-nl.ts +0 -6
- package/src/client/locales-pl.ts +0 -6
- package/src/client/locales-pt.ts +0 -6
- package/src/client/locales-ru.ts +0 -6
- package/src/client/locales-sv.ts +0 -6
- package/src/client/locales-th.ts +0 -6
- package/src/client/locales-tr.ts +0 -6
- package/src/client/locales-vi.ts +0 -6
- package/src/client/locales-zh-HK.ts +0 -6
- package/src/client/locales-zh-MO.ts +0 -6
- package/src/client/locales-zh-TW.ts +0 -6
- package/src/client/locales.ts +0 -52
- package/src/client/native-avoid.ts +155 -0
- package/src/client/plugins-shared.ts +6 -6
- package/src/client/prefs.ts +0 -7
- package/src/client/service.ts +13 -150
- package/src/client/sidebar.module.css +1 -425
- package/src/config.ts +1 -4
- package/src/context-types.ts +12 -7
- package/src/index.ts +12 -78
- package/src/jobs-routes.ts +3 -2
- package/src/prefs-shared.ts +1 -27
- package/src/sidechat-routes.ts +13 -8
- package/src/subagent-live-route.ts +2 -1
- package/lib/client-mermaid.js +0 -200753
- package/lib/types/client/MarkdownHtml.d.ts +0 -32
- package/lib/types/client/PdfView.d.ts +0 -6
- package/lib/types/client/builtins/viewers.d.ts +0 -3
- package/lib/types/client/chunks/mermaid.d.ts +0 -10
- package/lib/types/client/editor-load.d.ts +0 -66
- package/lib/types/client/image-types.d.ts +0 -3
- package/lib/types/client/markdown-html.d.ts +0 -96
- package/lib/types/client/markdown-images.d.ts +0 -45
- package/lib/types/client/md-toc.d.ts +0 -4
- package/lib/types/client/mermaid-blocks.d.ts +0 -47
- package/lib/types/client/mermaid-sanitize.d.ts +0 -2
- package/lib/types/client/mermaid.d.ts +0 -12
- package/lib/types/client/pdf-types.d.ts +0 -2
- package/lib/types/client/plugins-viewers.d.ts +0 -3
- package/lib/types/html-route.d.ts +0 -59
- package/src/client/MarkdownHtml.tsx +0 -296
- package/src/client/PdfView.tsx +0 -110
- package/src/client/builtins/viewers.tsx +0 -125
- package/src/client/chunks/mermaid.tsx +0 -10
- package/src/client/editor-load.ts +0 -92
- package/src/client/image-types.ts +0 -8
- package/src/client/markdown-html.ts +0 -331
- package/src/client/markdown-images.ts +0 -137
- package/src/client/md-toc.tsx +0 -127
- package/src/client/mermaid-blocks.ts +0 -110
- package/src/client/mermaid-sanitize.ts +0 -93
- package/src/client/mermaid.tsx +0 -406
- package/src/client/pdf-types.ts +0 -4
- package/src/client/plugins-viewers.ts +0 -30
- 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
|
|
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
|
-
|
|
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
|
|
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
|
|
3484
|
-
const
|
|
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.
|
|
3546
|
-
const { agentPreset, setup } = await composeChildSetup(ctx, resolvePresetId(parentSession.header, parentSession.
|
|
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
|
-
|
|
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.
|
|
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
|
|
3672
|
-
const
|
|
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 (
|
|
3687
|
-
*
|
|
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
|
|
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"
|
|
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,
|
|
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
|
|
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
|
|
56
|
+
feature: TabDescriptor;
|
|
57
57
|
prefs: SidebarPrefs;
|
|
58
58
|
store: SidebarStore;
|
|
59
59
|
service: BetterSidebarService;
|
|
@@ -1,10 +1,20 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
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
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
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
|
|
14
|
-
*
|
|
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
|
|
3
|
-
* libraries (CodeMirror, xterm —
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
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'
|
|
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
|
};
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Shared vocabulary of the recommended plugin
|
|
3
|
-
* the GitHub topic URL. The
|
|
4
|
-
* `plugins-tabs.ts` (tab registrations) and
|
|
5
|
-
*
|
|
6
|
-
* (
|
|
7
|
-
*
|
|
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";
|