dsh-vscode-workbench 0.1.10 → 0.1.12
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.en.md +28 -6
- package/README.md +28 -6
- package/lib/client.js +293 -104
- package/lib/client.js.map +1 -1
- package/lib/index.js +93 -41
- package/lib/index.js.map +1 -1
- package/lib/types/client/Workbench.d.ts +3 -0
- package/lib/types/client/terminal.d.ts +1 -0
- package/lib/types/client/websocket.d.ts +15 -0
- package/lib/types/terminal.d.ts +5 -0
- package/package.json +29 -27
- package/src/client/DshConversationPanel.tsx +2 -0
- package/src/client/TerminalPanel.tsx +12 -5
- package/src/client/Workbench.tsx +140 -15
- package/src/client/styles.ts +9 -4
- package/src/client/terminal.ts +15 -4
- package/src/client/websocket.ts +50 -0
- package/src/host.ts +47 -14
- package/src/terminal.ts +27 -2
package/lib/index.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { createRequire } from "node:module";
|
|
2
|
-
import { access, lstat, mkdir, open, readFile, readdir, realpath, rename, rm, stat
|
|
2
|
+
import { access, lstat, mkdir, open, readFile, readdir, realpath, rename, rm, stat } from "node:fs/promises";
|
|
3
3
|
import { basename, dirname, extname, isAbsolute, join, normalize, relative, resolve, sep } from "node:path";
|
|
4
4
|
import chokidar from "chokidar";
|
|
5
5
|
import { WebSocket, WebSocketServer } from "ws";
|
|
6
6
|
import { createHash, randomUUID } from "node:crypto";
|
|
7
7
|
import { spawn } from "node:child_process";
|
|
8
|
-
import { constants, realpathSync } from "node:fs";
|
|
8
|
+
import { chmodSync, constants, realpathSync, statSync } from "node:fs";
|
|
9
9
|
import * as pty from "node-pty";
|
|
10
10
|
//#region src/wire.ts
|
|
11
11
|
var WorkbenchError = class extends Error {
|
|
@@ -84,7 +84,7 @@ function authorize(req, res, connection) {
|
|
|
84
84
|
}
|
|
85
85
|
//#endregion
|
|
86
86
|
//#region src/host.ts
|
|
87
|
-
const require = createRequire(import.meta.url);
|
|
87
|
+
const require$1 = createRequire(import.meta.url);
|
|
88
88
|
const TEXT_LIMIT = 5242880;
|
|
89
89
|
const PROCESS_TIMEOUT = 3e4;
|
|
90
90
|
function cwdFor(ctx, sessionId) {
|
|
@@ -173,21 +173,44 @@ async function readDocument(cwd, path) {
|
|
|
173
173
|
await handle.close();
|
|
174
174
|
}
|
|
175
175
|
}
|
|
176
|
+
const pendingSaves = /* @__PURE__ */ new Map();
|
|
176
177
|
async function saveDocument(cwd, path, content, expected) {
|
|
177
|
-
const
|
|
178
|
-
|
|
179
|
-
const
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
178
|
+
const resolved = await workspacePath(cwd, path);
|
|
179
|
+
const absolute = await realpath(resolved.absolute);
|
|
180
|
+
const previous = pendingSaves.get(absolute) ?? Promise.resolve();
|
|
181
|
+
let release;
|
|
182
|
+
const pending = new Promise((resolve) => {
|
|
183
|
+
release = resolve;
|
|
183
184
|
});
|
|
185
|
+
pendingSaves.set(absolute, pending);
|
|
186
|
+
await previous;
|
|
187
|
+
let temp;
|
|
184
188
|
try {
|
|
189
|
+
const checkRevision = async () => {
|
|
190
|
+
const checked = await workspacePath(cwd, path);
|
|
191
|
+
if (await realpath(checked.absolute) !== absolute || (await readDocument(cwd, path)).revision !== expected) throw new WorkbenchError("revision-conflict", "file changed on disk; reload before saving", 409);
|
|
192
|
+
};
|
|
193
|
+
await checkRevision();
|
|
194
|
+
const info = await stat(absolute);
|
|
195
|
+
temp = join(dirname(absolute), `.${randomUUID()}.dsh-vscode.tmp`);
|
|
196
|
+
const handle = await open(temp, "wx", info.mode & 511);
|
|
197
|
+
try {
|
|
198
|
+
await handle.writeFile(content, { encoding: "utf8" });
|
|
199
|
+
await handle.chmod(info.mode & 511);
|
|
200
|
+
} finally {
|
|
201
|
+
await handle.close();
|
|
202
|
+
}
|
|
203
|
+
await checkRevision();
|
|
185
204
|
await rename(temp, absolute);
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
205
|
+
return await readDocument(cwd, path);
|
|
206
|
+
} finally {
|
|
207
|
+
try {
|
|
208
|
+
if (temp !== void 0) await rm(temp, { force: true });
|
|
209
|
+
} finally {
|
|
210
|
+
release();
|
|
211
|
+
if (pendingSaves.get(absolute) === pending) pendingSaves.delete(absolute);
|
|
212
|
+
}
|
|
189
213
|
}
|
|
190
|
-
return readDocument(cwd, path);
|
|
191
214
|
}
|
|
192
215
|
async function createEntry(cwd, path, kind) {
|
|
193
216
|
const { absolute } = await workspacePath(cwd, path, true);
|
|
@@ -222,8 +245,8 @@ async function renameEntry(cwd, path, nextPath) {
|
|
|
222
245
|
await rename(source.absolute, target.absolute);
|
|
223
246
|
}
|
|
224
247
|
async function deleteEntry(cwd, path) {
|
|
225
|
-
|
|
226
|
-
|
|
248
|
+
const { root, absolute } = await workspacePath(cwd, path);
|
|
249
|
+
if (absolute === root) throw new WorkbenchError("root-delete", "cannot delete workspace root", 403);
|
|
227
250
|
await rm(absolute, {
|
|
228
251
|
recursive: true,
|
|
229
252
|
force: false
|
|
@@ -257,7 +280,7 @@ async function workspacePreviewFile(cwd, path) {
|
|
|
257
280
|
/** Resolve the PDF.js worker shipped with this plugin's runtime dependency. */
|
|
258
281
|
function pdfWorkerAsset() {
|
|
259
282
|
return {
|
|
260
|
-
path: require.resolve("pdfjs-dist/legacy/build/pdf.worker.min.mjs"),
|
|
283
|
+
path: require$1.resolve("pdfjs-dist/legacy/build/pdf.worker.min.mjs"),
|
|
261
284
|
type: "text/javascript; charset=utf-8"
|
|
262
285
|
};
|
|
263
286
|
}
|
|
@@ -318,7 +341,7 @@ async function searchWorkspace(cwd, request, signal) {
|
|
|
318
341
|
limited: false
|
|
319
342
|
};
|
|
320
343
|
const root = await canonicalRoot(cwd);
|
|
321
|
-
const rg = require("@vscode/ripgrep").rgPath;
|
|
344
|
+
const rg = require$1("@vscode/ripgrep").rgPath;
|
|
322
345
|
const args = [
|
|
323
346
|
"--json",
|
|
324
347
|
"--line-number",
|
|
@@ -443,29 +466,36 @@ async function gitStatus(cwd) {
|
|
|
443
466
|
let ahead = 0;
|
|
444
467
|
let behind = 0;
|
|
445
468
|
const changes = [];
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
const
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
const xy = parts[1] ?? "..";
|
|
461
|
-
const path = parts.slice(record.startsWith("2 ") ? 9 : 8).join(" ");
|
|
462
|
-
changes.push({
|
|
463
|
-
path,
|
|
464
|
-
index: xy[0] ?? ".",
|
|
465
|
-
worktree: xy[1] ?? ".",
|
|
466
|
-
staged: xy[0] !== ".",
|
|
467
|
-
untracked: false
|
|
469
|
+
const records = result.stdout.split("\0");
|
|
470
|
+
for (let index = 0; index < records.length; index++) {
|
|
471
|
+
const record = records[index];
|
|
472
|
+
if (record.startsWith("# branch.head ")) branch = record.slice(14);
|
|
473
|
+
else if (record.startsWith("# branch.ab ")) {
|
|
474
|
+
const match = /\+(\d+) -(\d+)/.exec(record);
|
|
475
|
+
ahead = Number(match?.[1] ?? 0);
|
|
476
|
+
behind = Number(match?.[2] ?? 0);
|
|
477
|
+
} else if (record.startsWith("? ")) changes.push({
|
|
478
|
+
path: record.slice(2),
|
|
479
|
+
index: "?",
|
|
480
|
+
worktree: "?",
|
|
481
|
+
staged: false,
|
|
482
|
+
untracked: true
|
|
468
483
|
});
|
|
484
|
+
else if (record.startsWith("1 ") || record.startsWith("2 ") || record.startsWith("u ")) {
|
|
485
|
+
const renamed = record.startsWith("2 ");
|
|
486
|
+
const parts = record.split(" ");
|
|
487
|
+
const xy = parts[1] ?? "..";
|
|
488
|
+
const path = parts.slice(renamed ? 9 : record.startsWith("u ") ? 10 : 8).join(" ");
|
|
489
|
+
const originalPath = renamed ? records[++index] : void 0;
|
|
490
|
+
changes.push({
|
|
491
|
+
path,
|
|
492
|
+
...originalPath === void 0 ? {} : { originalPath },
|
|
493
|
+
index: xy[0] ?? ".",
|
|
494
|
+
worktree: xy[1] ?? ".",
|
|
495
|
+
staged: xy[0] !== ".",
|
|
496
|
+
untracked: false
|
|
497
|
+
});
|
|
498
|
+
}
|
|
469
499
|
}
|
|
470
500
|
return {
|
|
471
501
|
repository,
|
|
@@ -685,14 +715,14 @@ async function gitAction(cwd, action, path, value) {
|
|
|
685
715
|
}
|
|
686
716
|
/** Resolve the official VS Code Codicon font shipped by @vscode/codicons. */
|
|
687
717
|
function codiconAsset() {
|
|
688
|
-
const packageRoot = dirname(require.resolve("@vscode/codicons/package.json"));
|
|
718
|
+
const packageRoot = dirname(require$1.resolve("@vscode/codicons/package.json"));
|
|
689
719
|
return {
|
|
690
720
|
path: resolve(packageRoot, "dist", "codicon.ttf"),
|
|
691
721
|
type: "font/ttf"
|
|
692
722
|
};
|
|
693
723
|
}
|
|
694
724
|
function monacoAsset(raw) {
|
|
695
|
-
const packageRoot = dirname(require.resolve("monaco-editor/package.json"));
|
|
725
|
+
const packageRoot = dirname(require$1.resolve("monaco-editor/package.json"));
|
|
696
726
|
const path = resolve(packageRoot, "min", raw);
|
|
697
727
|
if (!inside(resolve(packageRoot, "min"), path)) throw new WorkbenchError("asset-invalid", "invalid Monaco asset path", 403);
|
|
698
728
|
return {
|
|
@@ -702,6 +732,7 @@ function monacoAsset(raw) {
|
|
|
702
732
|
}
|
|
703
733
|
//#endregion
|
|
704
734
|
//#region src/terminal.ts
|
|
735
|
+
const require = createRequire(import.meta.url);
|
|
705
736
|
const SENSITIVE = /(api[_-]?key|token|credential|secret|password|passwd|private[_-]?key|^dsh_.*(?:key|token|secret))/i;
|
|
706
737
|
const MAX_TERMINALS = 8;
|
|
707
738
|
const REPLAY_BYTES = 2097152;
|
|
@@ -720,9 +751,30 @@ function defaultTerminalShell(platform = process.platform, env = process.env) {
|
|
|
720
751
|
args: ["-l"]
|
|
721
752
|
};
|
|
722
753
|
}
|
|
754
|
+
/** Add execute bits when a registry package extracted a native helper without them. */
|
|
755
|
+
function ensureExecutable(path) {
|
|
756
|
+
if (process.platform === "win32") return true;
|
|
757
|
+
try {
|
|
758
|
+
const mode = statSync(path).mode;
|
|
759
|
+
if ((mode & 73) === 0) chmodSync(path, mode | 73);
|
|
760
|
+
return true;
|
|
761
|
+
} catch {
|
|
762
|
+
return false;
|
|
763
|
+
}
|
|
764
|
+
}
|
|
765
|
+
/** Repair node-pty's macOS/Linux helper, whose npm package currently loses its execute bit. */
|
|
766
|
+
function repairNodePtyHelper() {
|
|
767
|
+
if (process.platform === "win32") return;
|
|
768
|
+
const packageDirectory = dirname(require.resolve("node-pty/package.json"));
|
|
769
|
+
ensureExecutable(join(packageDirectory, "build", "Release", "spawn-helper"));
|
|
770
|
+
ensureExecutable(join(packageDirectory, "prebuilds", `${process.platform}-${process.arch}`, "spawn-helper"));
|
|
771
|
+
}
|
|
723
772
|
/** Own interactive terminals by their canonical workspace directory. */
|
|
724
773
|
var TerminalManager = class {
|
|
725
774
|
workspaces = /* @__PURE__ */ new Map();
|
|
775
|
+
constructor() {
|
|
776
|
+
repairNodePtyHelper();
|
|
777
|
+
}
|
|
726
778
|
workspace(cwd) {
|
|
727
779
|
return realpathSync(cwd);
|
|
728
780
|
}
|
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/wire.ts","../src/host.ts","../src/terminal.ts","../src/index.ts"],"sourcesContent":["import type { IncomingMessage, ServerResponse } from 'node:http'\nimport type { WorkbenchConnection } from './context.ts'\n\nexport class WorkbenchError extends Error {\n constructor(public code: string, message: string, public status = 400) { super(message) }\n}\n\nexport async function readBody(req: IncomingMessage): Promise<Record<string, unknown>> {\n const chunks: Buffer[] = []\n let size = 0\n for await (const chunk of req) {\n const value = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)\n size += value.length\n if (size > 2 * 1024 * 1024) throw new WorkbenchError('too-large', 'request body is too large', 413)\n chunks.push(value)\n }\n try {\n const value: unknown = JSON.parse(Buffer.concat(chunks).toString('utf8') || '{}')\n if (value === null || typeof value !== 'object' || Array.isArray(value)) throw new Error('object expected')\n return value as Record<string, unknown>\n } catch { throw new WorkbenchError('bad-json', 'request body must be a JSON object') }\n}\n\n/** Read a binary upload while enforcing a fixed request limit. */\nexport async function readBinaryBody(req: IncomingMessage, limit = 100 * 1024 * 1024): Promise<Buffer> {\n const chunks: Buffer[] = []\n let size = 0\n for await (const chunk of req) {\n const value = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)\n size += value.length\n if (size > limit) throw new WorkbenchError('too-large', 'uploaded file is too large', 413)\n chunks.push(value)\n }\n return Buffer.concat(chunks)\n}\n\nexport function stringField(body: Record<string, unknown>, key: string): string {\n const value = body[key]\n if (typeof value !== 'string') throw new WorkbenchError('bad-request', `${key} must be a string`)\n return value\n}\n\nexport function send(res: ServerResponse, status: number, value: unknown): void {\n res.writeHead(status, { 'content-type': 'application/json; charset=utf-8', 'cache-control': 'no-store' })\n res.end(JSON.stringify(value))\n}\n\nexport function sendError(res: ServerResponse, error: unknown): void {\n const known = error instanceof WorkbenchError ? error : new WorkbenchError('internal', error instanceof Error ? error.message : String(error), 500)\n send(res, known.status, { ok: false, error: { code: known.code, message: known.message } })\n}\n\n/** Reuse Harness authentication and its deployment-aware Host/Origin fence. */\nexport function authorize(req: IncomingMessage, res: ServerResponse, connection: WorkbenchConnection): boolean {\n const rejection = connection.requestRejection(req)\n if (rejection === undefined) return true\n const code = rejection === 401 ? 'unauthorized' : 'forbidden'\n send(res, rejection, { ok: false, error: { code, message: code } })\n return false\n}\n","import { createHash, randomUUID } from 'node:crypto'\nimport { spawn } from 'node:child_process'\nimport { createRequire } from 'node:module'\nimport { dirname, extname, isAbsolute, join, normalize, relative, resolve, sep } from 'node:path'\nimport { access, lstat, mkdir, open, readFile, readdir, realpath, rename, rm, stat, writeFile } from 'node:fs/promises'\nimport { constants } from 'node:fs'\nimport type { HostContext } from './context.ts'\nimport type { FileDocument, FileEntry, GitChange, GitCommit, GitCommitFile, GitDiff, GitStatus, SearchMatch, SearchRequest } from './types.ts'\nimport { WorkbenchError } from './wire.ts'\n\nconst require = createRequire(import.meta.url)\nconst TEXT_LIMIT = 5 * 1024 * 1024\nconst PROCESS_TIMEOUT = 30_000\n\nexport function cwdFor(ctx: HostContext, sessionId: string): string {\n const session = ctx.sessions.get(sessionId)\n if (session === undefined) throw new WorkbenchError('session-not-found', 'session not found', 404)\n const cwd = ctx.workingDirectory.get(session)\n if (!isAbsolute(cwd)) throw new WorkbenchError('cwd-invalid', 'session working directory is not absolute')\n return normalize(cwd)\n}\n\nfunction inside(root: string, target: string): boolean {\n const rel = relative(root, target)\n return rel === '' || (!rel.startsWith(`..${sep}`) && rel !== '..' && !isAbsolute(rel))\n}\n\nasync function canonicalRoot(cwd: string): Promise<string> {\n return realpath(cwd).catch(() => { throw new WorkbenchError('cwd-missing', 'session working directory does not exist', 404) })\n}\n\n/** Resolve a caller-relative path and reject traversal and symlink escape. */\nexport async function workspacePath(cwd: string, raw: string, create = false): Promise<{ root: string; absolute: string }> {\n if (isAbsolute(raw)) throw new WorkbenchError('path-invalid', 'absolute paths are not accepted')\n const root = await canonicalRoot(cwd)\n const absolute = resolve(root, raw === '' ? '.' : raw)\n if (!inside(root, absolute)) throw new WorkbenchError('path-outside', 'path is outside the workspace', 403)\n if (create) {\n const parent = await realpath(dirname(absolute)).catch(() => { throw new WorkbenchError('parent-missing', 'parent directory does not exist', 404) })\n if (!inside(root, parent)) throw new WorkbenchError('path-outside', 'path follows a symlink outside the workspace', 403)\n } else {\n const actual = await realpath(absolute).catch(() => { throw new WorkbenchError('not-found', 'path does not exist', 404) })\n if (!inside(root, actual)) throw new WorkbenchError('path-outside', 'path follows a symlink outside the workspace', 403)\n }\n return { root, absolute }\n}\n\nfunction relativePath(root: string, absolute: string): string { return relative(root, absolute).split(sep).join('/') }\nfunction revision(content: Buffer, mtimeMs: number): string {\n return createHash('sha256').update(content).update(String(mtimeMs)).digest('hex')\n}\n\nexport async function listFiles(cwd: string, path: string): Promise<FileEntry[]> {\n const { root, absolute } = await workspacePath(cwd, path)\n const values = await readdir(absolute, { withFileTypes: true })\n const rows = await Promise.all(values.filter(item => item.name !== '.git').map(async item => {\n const full = join(absolute, item.name)\n if (!item.isSymbolicLink()) return { name: item.name, path: relativePath(root, full), kind: item.isDirectory() ? 'directory' as const : 'file' as const }\n const actual = await realpath(full).catch(() => undefined)\n if (actual === undefined || !inside(root, actual)) return undefined\n const info = await stat(full)\n const kind = info.isDirectory() ? 'directory' as const : 'file' as const\n return { name: item.name, path: relativePath(root, full), kind, size: info.size, mtimeMs: info.mtimeMs }\n }))\n return rows.filter(row => row !== undefined).sort((a, b) => a.kind === b.kind ? a.name.localeCompare(b.name) : a.kind === 'directory' ? -1 : 1)\n}\n\nexport async function readDocument(cwd: string, path: string): Promise<FileDocument> {\n const { root, absolute } = await workspacePath(cwd, path)\n const info = await stat(absolute)\n if (!info.isFile()) throw new WorkbenchError('not-file', 'path is not a file')\n const tooLarge = info.size > TEXT_LIMIT\n const handle = await open(absolute, 'r')\n try {\n const head = Buffer.alloc(Math.min(info.size, tooLarge ? 4096 : TEXT_LIMIT))\n const { bytesRead } = await handle.read(head, 0, head.length, 0)\n const bytes = head.subarray(0, bytesRead)\n const binary = bytes.includes(0)\n return {\n path: relativePath(root, absolute), content: binary || tooLarge ? '' : bytes.toString('utf8'),\n revision: revision(bytes, info.mtimeMs), size: info.size, binary, tooLarge,\n }\n } finally { await handle.close() }\n}\n\nexport async function saveDocument(cwd: string, path: string, content: string, expected: string): Promise<FileDocument> {\n const { absolute } = await workspacePath(cwd, path)\n const current = await readDocument(cwd, path)\n if (current.revision !== expected) throw new WorkbenchError('revision-conflict', 'file changed on disk; reload before saving', 409)\n const temp = join(dirname(absolute), `.${randomUUID()}.dsh-vscode.tmp`)\n await writeFile(temp, content, { encoding: 'utf8', flag: 'wx' })\n try { await rename(temp, absolute) } catch (error) { await rm(temp, { force: true }); throw error }\n return readDocument(cwd, path)\n}\n\nexport async function createEntry(cwd: string, path: string, kind: 'file' | 'directory'): Promise<void> {\n const { absolute } = await workspacePath(cwd, path, true)\n if (kind === 'directory') await mkdir(absolute)\n else { const handle = await open(absolute, 'wx'); await handle.close() }\n}\n\n/** Write an uploaded file into an existing workspace directory without overwriting files. */\nexport async function uploadFile(cwd: string, directory: string, name: string, content: Buffer): Promise<FileEntry> {\n if (name === '' || name === '.' || name === '..' || name.includes('/') || name.includes('\\\\')) throw new WorkbenchError('filename-invalid', 'uploaded file name is invalid')\n const targetPath = directory === '' ? name : `${directory}/${name}`\n const { root, absolute } = await workspacePath(cwd, targetPath, true)\n const handle = await open(absolute, 'wx')\n try { await handle.writeFile(content) } finally { await handle.close() }\n const info = await lstat(absolute)\n return { name, path: relativePath(root, absolute), kind: 'file', size: info.size, mtimeMs: info.mtimeMs }\n}\n\nexport async function renameEntry(cwd: string, path: string, nextPath: string): Promise<void> {\n const source = await workspacePath(cwd, path)\n const target = await workspacePath(cwd, nextPath, true)\n await access(target.absolute, constants.F_OK).then(\n () => { throw new WorkbenchError('target-exists', 'destination already exists', 409) }, () => undefined,\n )\n await rename(source.absolute, target.absolute)\n}\n\nexport async function deleteEntry(cwd: string, path: string): Promise<void> {\n if (path === '') throw new WorkbenchError('root-delete', 'cannot delete workspace root', 403)\n const { absolute } = await workspacePath(cwd, path)\n await rm(absolute, { recursive: true, force: false })\n}\n\nconst IMAGE_TYPES:Record<string,string>={'.avif':'image/avif','.bmp':'image/bmp','.gif':'image/gif','.ico':'image/x-icon','.jpeg':'image/jpeg','.jpg':'image/jpeg','.png':'image/png','.svg':'image/svg+xml','.webp':'image/webp'}\nconst PREVIEW_TYPES:Record<string,string>={...IMAGE_TYPES,'.pdf':'application/pdf','.doc':'application/msword','.docx':'application/vnd.openxmlformats-officedocument.wordprocessingml.document','.odt':'application/vnd.oasis.opendocument.text'}\n/** Resolve an image inside the workspace for protected browser preview. */\nexport async function workspaceImage(cwd:string,path:string):Promise<{path:string;type:string}>{const resolved=await workspacePath(cwd,path);const type=IMAGE_TYPES[extname(resolved.absolute).toLowerCase()];if(type===undefined)throw new WorkbenchError('unsupported-media','file is not a supported image',415);return {path:resolved.absolute,type}}\n/** Resolve a supported preview file inside the workspace. */\nexport async function workspacePreviewFile(cwd:string,path:string):Promise<{path:string;type:string}>{const resolved=await workspacePath(cwd,path);const type=PREVIEW_TYPES[extname(resolved.absolute).toLowerCase()];if(type===undefined)throw new WorkbenchError('unsupported-media','file is not a supported preview format',415);return {path:resolved.absolute,type}}\n\n/** Resolve the PDF.js worker shipped with this plugin's runtime dependency. */\nexport function pdfWorkerAsset(): { path: string; type: string } {\n return { path: require.resolve('pdfjs-dist/legacy/build/pdf.worker.min.mjs'), type: 'text/javascript; charset=utf-8' }\n}\n\ninterface ProcessResult { stdout: string; stderr: string; code: number }\nexport function run(command: string, args: string[], cwd: string, timeout = PROCESS_TIMEOUT, signal?: AbortSignal): Promise<ProcessResult> {\n return new Promise((resolvePromise, reject) => {\n const child = spawn(command, args, { cwd, shell: false, windowsHide: true })\n let stdout = ''; let stderr = ''; let settled = false\n const timer = setTimeout(() => { child.kill(); if (!settled) reject(new WorkbenchError('timeout', `${command} timed out`, 504)) }, timeout)\n const abort = () => { child.kill(); if (!settled) { settled = true; clearTimeout(timer); reject(new WorkbenchError('cancelled', `${command} cancelled`, 499)) } }\n signal?.addEventListener('abort', abort, { once: true })\n child.stdout.on('data', chunk => { stdout += String(chunk) })\n child.stderr.on('data', chunk => { stderr += String(chunk) })\n child.on('error', error => { clearTimeout(timer); signal?.removeEventListener('abort', abort); if (!settled) { settled = true; reject(error) } })\n child.on('close', code => { clearTimeout(timer); signal?.removeEventListener('abort', abort); if (!settled) { settled = true; resolvePromise({ stdout, stderr, code: code ?? 1 }) } })\n })\n}\n\nexport async function searchWorkspace(cwd: string, request: SearchRequest, signal?: AbortSignal): Promise<{ matches: SearchMatch[]; limited: boolean }> {\n if (request.query === '') return { matches: [], limited: false }\n const root = await canonicalRoot(cwd)\n const rg = require('@vscode/ripgrep').rgPath as string\n const args = ['--json', '--line-number', '--column', '--hidden', '--glob', '!.git/**', '--max-count', '2000']\n if (!request.regex) args.push('--fixed-strings')\n if (!request.caseSensitive) args.push('--ignore-case')\n if (request.wholeWord) args.push('--word-regexp')\n if (request.include) args.push('--glob', request.include)\n if (request.exclude) args.push('--glob', `!${request.exclude}`)\n args.push('--', request.query, '.')\n const result = await run(rg, args, root, PROCESS_TIMEOUT, signal)\n if (result.code > 1) throw new WorkbenchError('search-failed', result.stderr || 'ripgrep failed', 500)\n const matches: SearchMatch[] = []\n for (const line of result.stdout.split('\\n')) {\n if (line === '') continue\n const event = JSON.parse(line) as { type: string; data?: { path?: { text?: string }; lines?: { text?: string }; line_number?: number; submatches?: Array<{ start: number; end: number; match?: { text?: string } }> } }\n if (event.type !== 'match' || event.data?.path?.text === undefined || event.data.lines?.text === undefined) continue\n for (const hit of event.data.submatches ?? []) {\n matches.push({ path: event.data.path.text.replace(/^\\.\\//, ''), line: event.data.line_number ?? 1, column: hit.start + 1, preview: event.data.lines.text.trimEnd(), match: hit.match?.text ?? '' })\n if (matches.length >= 2000) return { matches, limited: true }\n }\n }\n return { matches, limited: false }\n}\n\nasync function gitRoot(cwd: string): Promise<string> {\n const result = await run('git', ['rev-parse', '--show-toplevel'], cwd)\n if (result.code !== 0) throw new WorkbenchError('not-repository', 'current workspace is not inside a Git repository', 404)\n return result.stdout.trim()\n}\n\nfunction validateCommitHash(value?: string): string {\n if (!/^[0-9a-f]{7,64}$/i.test(value ?? '')) throw new WorkbenchError('bad-request', 'commit hash is invalid')\n return value!\n}\n\nfunction validateGitPath(repository: string, path?: string): string {\n if (path === undefined || path === '' || isAbsolute(path) || !inside(repository, resolve(repository, path))) throw new WorkbenchError('bad-request', 'repository-relative path is required')\n return path\n}\n\nasync function gitObject(repository: string, spec: string): Promise<string> {\n const result = await run('git', ['show', '--no-textconv', spec], repository)\n return result.code === 0 ? result.stdout : ''\n}\n\nasync function commitFiles(repository: string, hash: string): Promise<GitCommitFile[]> {\n const parent=await run('git',['rev-parse','--verify',`${hash}^1`],repository)\n const result = parent.code===0\n ? await run('git',['diff','--name-status','-z','-M',parent.stdout.trim(),hash,'--'],repository)\n : await run('git', ['diff-tree', '--root', '--no-commit-id', '--name-status', '-r', '-z', '-M', hash], repository)\n if (result.code !== 0) throw new WorkbenchError('git-failed', result.stderr || result.stdout, 409)\n const tokens = result.stdout.split('\\0').filter(Boolean); const files: GitCommitFile[] = []\n for (let index = 0; index < tokens.length;) {\n const status = tokens[index++] ?? ''; const code = status[0] ?? ''\n if (code === 'R' || code === 'C') { const previousPath=tokens[index++]??'';const path=tokens[index++]??'';files.push({path,previousPath,status:code}) }\n else { const path=tokens[index++]??'';files.push({path,status:code}) }\n }\n return files\n}\n\nexport async function gitStatus(cwd: string): Promise<GitStatus> {\n const repository = await gitRoot(cwd)\n const result = await run('git', ['status', '--porcelain=v2', '-z', '--branch', '--untracked-files=all'], repository)\n if (result.code !== 0) throw new WorkbenchError('git-failed', result.stderr, 500)\n let branch = 'HEAD'; let ahead = 0; let behind = 0\n const changes: GitChange[] = []\n for (const record of result.stdout.split('\\0')) {\n if (record.startsWith('# branch.head ')) branch = record.slice(14)\n else if (record.startsWith('# branch.ab ')) {\n const match = /\\+(\\d+) -(\\d+)/.exec(record); ahead = Number(match?.[1] ?? 0); behind = Number(match?.[2] ?? 0)\n } else if (record.startsWith('? ')) changes.push({ path: record.slice(2), index: '?', worktree: '?', staged: false, untracked: true })\n else if (record.startsWith('1 ') || record.startsWith('2 ')) {\n const parts = record.split(' '); const xy = parts[1] ?? '..'; const path = parts.slice(record.startsWith('2 ') ? 9 : 8).join(' ')\n changes.push({ path, index: xy[0] ?? '.', worktree: xy[1] ?? '.', staged: xy[0] !== '.', untracked: false })\n }\n }\n return { repository, branch, ahead, behind, changes }\n}\n\nexport async function gitAction(cwd: string, action: string, path?: string, value?: string): Promise<unknown> {\n const repository = await gitRoot(cwd)\n let args: string[]\n switch (action) {\n case 'stage': args = ['add', '--', path ?? '']; break\n case 'stage.all': args = ['add', '-A']; break\n case 'unstage': args = ['restore', '--staged', '--', path ?? '']; break\n case 'unstage.all': args = ['restore', '--staged', '--', '.']; break\n case 'discard': {\n args = value === 'untracked' ? ['clean', '-f', '--', path ?? ''] : ['restore', '--worktree', '--', path ?? '']\n break\n }\n case 'discard.all': {\n const head = await run('git', ['rev-parse', '--verify', 'HEAD'], repository)\n if (head.code === 0) {\n const restore = await run('git', ['restore', '--source=HEAD', '--staged', '--worktree', '--', '.'], repository)\n if (restore.code !== 0) throw new WorkbenchError('git-failed', restore.stderr || restore.stdout, 409)\n }\n const clean = await run('git', ['clean', '-fd'], repository)\n if (clean.code !== 0) throw new WorkbenchError('git-failed', clean.stderr || clean.stdout, 409)\n return gitStatus(cwd)\n }\n case 'commit': args = ['commit', '-m', value ?? '']; break\n case 'branch.create': args = ['switch', '-c', value ?? '']; break\n case 'branch.switch': args = ['switch', value ?? '']; break\n case 'branches': {\n const result = await run('git', ['for-each-ref', '--format=%(refname:short)', 'refs/heads'], repository)\n if (result.code !== 0) throw new WorkbenchError('git-failed', result.stderr, 500)\n return result.stdout.split('\\n').filter(Boolean)\n }\n case 'log': {\n const head = await run('git', ['rev-parse', '--verify', 'HEAD'], repository)\n if (head.code !== 0) return []\n const result = await run('git', ['log', '--topo-order', '--date=iso-strict', '--decorate=short', '--pretty=format:%H%x1f%P%x1f%an%x1f%aI%x1f%s%x1f%D%x00', '-n', '100'], repository)\n if (result.code !== 0) throw new WorkbenchError('git-failed', result.stderr || result.stdout, 500)\n return result.stdout.split('\\0').filter(Boolean).map((record): GitCommit => {\n const [rawHash = '', parents = '', author = '', date = '', subject = '', refs = ''] = record.split('\\x1f');const hash=rawHash.trim()\n return { hash, parents: parents.split(' ').filter(Boolean), author, date, subject, refs: refs.split(',').map(item => item.trim()).filter(Boolean) }\n })\n }\n case 'commit.show': {\n const hash = validateCommitHash(value)\n const result = await run('git', ['show', '--no-ext-diff', '--find-renames', '--format=fuller', '--stat', '--patch', '--no-color', hash], repository)\n if (result.code !== 0) throw new WorkbenchError('git-failed', result.stderr || result.stdout, 409)\n return { diff: result.stdout, original: '', modified: result.stdout } satisfies GitDiff\n }\n case 'commit.files': return commitFiles(repository, validateCommitHash(value))\n case 'commit.file.diff': {\n const hash=validateCommitHash(value);const target=validateGitPath(repository,path);const files=await commitFiles(repository,hash);const file=files.find(item=>item.path===target)\n if (file===undefined) throw new WorkbenchError('not-found','file is not part of the commit',404)\n const parent=await run('git',['rev-parse','--verify',`${hash}^1`],repository)\n const shown=parent.code===0\n ? await run('git',['diff','--no-ext-diff','--find-renames','--patch','--no-color',parent.stdout.trim(),hash,'--',file.previousPath??target,target],repository)\n : await run('git',['show','--no-ext-diff','--find-renames','--format=','--patch','--no-color',hash,'--',file.previousPath??target,target],repository)\n if(shown.code!==0)throw new WorkbenchError('git-failed',shown.stderr||shown.stdout,409)\n const original=file.status==='A'||parent.code!==0?'':await gitObject(repository,`${parent.stdout.trim()}:${file.previousPath??target}`)\n const modified=file.status==='D'?'':await gitObject(repository,`${hash}:${target}`)\n return {diff:shown.stdout,original,modified} satisfies GitDiff\n }\n case 'diff': {\n const untracked = value === 'untracked'\n const staged = value === 'staged'\n args = untracked\n ? ['diff', '--no-index', '--', process.platform === 'win32' ? 'NUL' : '/dev/null', path ?? '']\n : ['diff', ...(staged ? ['--cached'] : []), '--', path ?? '']\n break\n }\n default: throw new WorkbenchError('bad-action', `unknown Git action ${action}`)\n }\n if (args.some(arg => arg === '') && action !== 'commit') throw new WorkbenchError('bad-request', 'path or value is required')\n const result = await run('git', args, repository)\n const expectedUntrackedDifference = action === 'diff' && value === 'untracked' && result.code === 1\n if (result.code !== 0 && !expectedUntrackedDifference) throw new WorkbenchError('git-failed', result.stderr || result.stdout, 409)\n if(action!=='diff')return gitStatus(cwd)\n const target=validateGitPath(repository,path)\n const original=value==='untracked'?'':await gitObject(repository,`${value==='staged'?'HEAD:':':'}${target}`)\n const modified=value==='staged'?await gitObject(repository,`:${target}`):await readFile(resolve(repository,target),'utf8').catch(()=> '')\n return {diff:result.stdout,original,modified} satisfies GitDiff\n}\n\n/** Resolve the official VS Code Codicon font shipped by @vscode/codicons. */\nexport function codiconAsset(): { path: string; type: string } {\n const packageRoot = dirname(require.resolve('@vscode/codicons/package.json'))\n return { path: resolve(packageRoot, 'dist', 'codicon.ttf'), type: 'font/ttf' }\n}\n\nexport function monacoAsset(raw: string): { path: string; type: string } {\n const packageRoot = dirname(require.resolve('monaco-editor/package.json'))\n const path = resolve(packageRoot, 'min', raw)\n const root = resolve(packageRoot, 'min')\n if (!inside(root, path)) throw new WorkbenchError('asset-invalid', 'invalid Monaco asset path', 403)\n const type = extname(path) === '.css' ? 'text/css' : extname(path) === '.js' ? 'text/javascript' : extname(path) === '.ttf' ? 'font/ttf' : 'application/octet-stream'\n return { path, type }\n}\n","import { randomUUID } from 'node:crypto'\nimport { realpathSync } from 'node:fs'\nimport { basename } from 'node:path'\nimport type { IncomingMessage } from 'node:http'\nimport type { Duplex } from 'node:stream'\nimport * as pty from 'node-pty'\nimport type { IPty } from 'node-pty'\nimport { WebSocket, WebSocketServer } from 'ws'\nimport type { HostContext } from './context.ts'\nimport { cwdFor } from './host.ts'\nimport { authorize, readBody, send, sendError } from './wire.ts'\n\nexport interface TerminalInfo { id: string; title: string; cwd: string; running: boolean; exitCode?: number; sequence: number }\nexport interface TerminalOutput { sequence: number; data: string }\n\ninterface TerminalHandle { info: TerminalInfo; process: IPty; replay: string; listeners: Set<(output: TerminalOutput) => void> }\nconst SENSITIVE = /(api[_-]?key|token|credential|secret|password|passwd|private[_-]?key|^dsh_.*(?:key|token|secret))/i\nconst MAX_TERMINALS = 8\nconst REPLAY_BYTES = 2 * 1024 * 1024\n\n/** Remove credentials while retaining ordinary interactive-shell variables. */\nexport function sanitizedTerminalEnv(env: NodeJS.ProcessEnv): Record<string, string> {\n return Object.fromEntries(Object.entries(env).filter(([key, value]) => value !== undefined && !SENSITIVE.test(key)) as Array<[string, string]>)\n}\n\n/** Select the user's interactive shell with platform-specific fallbacks. */\nexport function defaultTerminalShell(platform = process.platform, env = process.env): { shell: string; args: string[] } {\n if (platform === 'win32') return { shell: env.COMSPEC?.toLowerCase().includes('powershell') ? env.COMSPEC : 'powershell.exe', args: ['-NoLogo'] }\n return { shell: env.SHELL || (platform === 'darwin' ? '/bin/zsh' : '/bin/bash'), args: ['-l'] }\n}\n\n/** Own interactive terminals by their canonical workspace directory. */\nexport class TerminalManager {\n private readonly workspaces = new Map<string, Map<string, TerminalHandle>>()\n\n private workspace(cwd: string): string { return realpathSync(cwd) }\n\n list(cwd: string): TerminalInfo[] { return [...(this.workspaces.get(this.workspace(cwd))?.values() ?? [])].map(handle => ({ ...handle.info })) }\n\n create(cwd: string, title?: string): TerminalInfo {\n const key = this.workspace(cwd)\n const terminals = this.workspaces.get(key) ?? new Map<string, TerminalHandle>()\n this.workspaces.set(key, terminals)\n if (terminals.size >= MAX_TERMINALS) throw new Error(`terminal limit reached (${MAX_TERMINALS})`)\n const { shell, args } = defaultTerminalShell()\n const child = pty.spawn(shell, args, { name: 'xterm-256color', cols: 80, rows: 24, cwd: key, env: sanitizedTerminalEnv(process.env) })\n const info: TerminalInfo = { id: randomUUID(), title: title || basename(shell), cwd: key, running: true, sequence: 0 }\n const handle: TerminalHandle = { info, process: child, replay: '', listeners: new Set() }\n terminals.set(info.id, handle)\n child.onData(data => {\n info.sequence++\n handle.replay += data\n if (Buffer.byteLength(handle.replay) > REPLAY_BYTES) handle.replay = handle.replay.slice(-REPLAY_BYTES)\n for (const listener of handle.listeners) listener({ sequence: info.sequence, data })\n })\n child.onExit(({ exitCode }) => {\n info.running = false\n info.exitCode = exitCode\n info.sequence++\n const data = `\\r\\n[process exited with code ${exitCode}]\\r\\n`\n for (const listener of handle.listeners) listener({ sequence: info.sequence, data })\n })\n return { ...info }\n }\n\n get(cwd: string, id: string): TerminalHandle | undefined { return this.workspaces.get(this.workspace(cwd))?.get(id) }\n\n close(cwd: string, id: string): void {\n const key = this.workspace(cwd)\n const terminals = this.workspaces.get(key)\n const handle = terminals?.get(id)\n if (handle === undefined || terminals === undefined) return\n terminals.delete(id)\n try { handle.process.kill() } catch { /* The shell may already have exited. */ }\n if (terminals.size === 0) this.workspaces.delete(key)\n }\n\n rename(cwd: string, id: string, title: string): TerminalInfo {\n const handle = this.get(cwd, id)\n if (handle === undefined) throw new Error('terminal not found')\n handle.info.title = title\n return { ...handle.info }\n }\n\n dispose(): void { for (const [cwd, terminals] of this.workspaces) for (const id of terminals.keys()) this.close(cwd, id) }\n}\n\nfunction terminalRequestAllowed(req: IncomingMessage): boolean {\n const host = req.headers.host\n if (host === undefined || req.headers['sec-fetch-site'] === 'cross-site') return false\n let hostname: string\n try { hostname = new URL(`http://${host}`).hostname } catch { return false }\n if (hostname !== 'localhost' && hostname !== '[::1]' && !hostname.startsWith('127.')) return false\n const origin = req.headers.origin\n try { return origin === undefined || new URL(origin).host === host } catch { return false }\n}\n\n/** Register the private local terminal API and WebSocket transport. */\nexport function installTerminal(ctx: HostContext): void {\n const manager = new TerminalManager()\n ctx.effect(() => ctx.webServer.register({ kind: 'prefix', path: '/dsh-vscode-terminal/api', handler: async (req, res) => {\n if (!authorize(req, res, ctx.connection)) return\n if (!terminalRequestAllowed(req)) return send(res, 403, { ok: false, error: { message: 'forbidden' } })\n if (req.method !== 'POST') return send(res, 405, { ok: false, error: { message: 'POST required' } })\n try {\n const body = await readBody(req)\n const sessionId = typeof body.sessionId === 'string' ? body.sessionId : ''\n if (sessionId === '') throw new Error('sessionId required')\n const cwd = cwdFor(ctx, sessionId)\n const method = new URL(req.url ?? '/', 'http://dsh.local').pathname.slice('/dsh-vscode-terminal/api/'.length)\n let value: unknown\n if (method === 'list') value = manager.list(cwd)\n else if (method === 'create') value = manager.create(cwd, typeof body.title === 'string' ? body.title : undefined)\n else if (method === 'close') { manager.close(cwd, typeof body.id === 'string' ? body.id : ''); value = manager.list(cwd) }\n else if (method === 'rename') value = manager.rename(cwd, typeof body.id === 'string' ? body.id : '', typeof body.title === 'string' ? body.title : '')\n else throw new Error('unknown terminal method')\n send(res, 200, { ok: true, value })\n } catch (error) { sendError(res, error) }\n } }), 'dsh-vscode-workbench: terminal API')\n\n const webSocket = new WebSocketServer({ noServer: true })\n ctx.effect(() => ctx.webServer.registerUpgrade({ path: '/dsh-vscode-terminal/ws', handler(req, socket, head) {\n if (ctx.connection.requestRejection(req) !== undefined || !terminalRequestAllowed(req)) { socket.destroy(); return }\n webSocket.handleUpgrade(req as IncomingMessage, socket as Duplex, head, connection => {\n const url = new URL(req.url ?? '/', 'http://dsh.local')\n const sessionId = url.searchParams.get('sessionId')\n const id = url.searchParams.get('id')\n if (sessionId === null || id === null) { connection.close(1008, 'sessionId and id required'); return }\n let handle: TerminalHandle | undefined\n try { handle = manager.get(cwdFor(ctx, sessionId), id) }\n catch { connection.close(1008, 'session workspace unavailable'); return }\n if (handle === undefined) { connection.close(1008, 'terminal not found'); return }\n if (handle.replay !== '') connection.send(JSON.stringify({ type: 'replay', sequence: handle.info.sequence, data: handle.replay }))\n const listener = (output: TerminalOutput) => { if (connection.readyState === WebSocket.OPEN) connection.send(JSON.stringify({ type: 'output', ...output })) }\n handle.listeners.add(listener)\n connection.on('message', raw => {\n const text = raw.toString()\n try {\n const message: unknown = JSON.parse(text)\n if (message !== null && typeof message === 'object' && 'type' in message && message.type === 'input' && 'data' in message && typeof message.data === 'string') handle.process.write(message.data)\n else if (message !== null && typeof message === 'object' && 'type' in message && message.type === 'resize' && 'cols' in message && 'rows' in message && typeof message.cols === 'number' && typeof message.rows === 'number') handle.process.resize(Math.max(2, Math.floor(message.cols)), Math.max(2, Math.floor(message.rows)))\n } catch { handle.process.write(text) }\n })\n connection.on('close', () => handle.listeners.delete(listener))\n })\n } }), 'dsh-vscode-workbench: terminal WebSocket')\n ctx.effect(() => () => { webSocket.close(); manager.dispose() }, 'dsh-vscode-workbench: terminal teardown')\n}\n","/** DSH host plugin for the VS Code workbench. */\nimport { readFile } from 'node:fs/promises'\nimport type { IncomingMessage } from 'node:http'\nimport { isAbsolute, relative, sep } from 'node:path'\nimport type { Duplex } from 'node:stream'\nimport chokidar from 'chokidar'\nimport { WebSocket, WebSocketServer } from 'ws'\nimport type { HostContext } from './context.ts'\nimport { codiconAsset, createEntry, cwdFor, deleteEntry, gitAction, gitStatus, listFiles, monacoAsset, pdfWorkerAsset, readDocument, renameEntry, saveDocument, searchWorkspace, uploadFile, workspacePreviewFile } from './host.ts'\nimport { installTerminal } from './terminal.ts'\nimport type { SearchRequest } from './types.ts'\nimport { readBinaryBody, readBody, send, sendError, stringField, authorize, WorkbenchError } from './wire.ts'\n\nexport { WorkbenchError } from './wire.ts'\nexport * from './types.ts'\nexport const name = 'dsh-vscode-workbench'\nexport const inject = ['webServer', 'sessions', 'connection', 'workingDirectory']\n\nasync function dispatch(ctx: HostContext, method: string, body: Record<string, unknown>, signal?: AbortSignal): Promise<unknown> {\n const sessionId = stringField(body, 'sessionId'); const cwd = cwdFor(ctx, sessionId)\n switch (method) {\n case 'workspace': return { cwd, name: cwd.split(/[\\\\/]/).at(-1) || cwd }\n case 'fs.list': return listFiles(cwd, stringField(body, 'path'))\n case 'fs.read': return readDocument(cwd, stringField(body, 'path'))\n case 'fs.save': return saveDocument(cwd, stringField(body, 'path'), stringField(body, 'content'), stringField(body, 'revision'))\n case 'fs.create': return createEntry(cwd, stringField(body, 'path'), body.kind === 'directory' ? 'directory' : 'file').then(() => ({ ok: true }))\n case 'fs.rename': return renameEntry(cwd, stringField(body, 'path'), stringField(body, 'nextPath')).then(() => ({ ok: true }))\n case 'fs.delete': return deleteEntry(cwd, stringField(body, 'path')).then(() => ({ ok: true }))\n case 'search': return searchWorkspace(cwd, body as unknown as SearchRequest, signal)\n case 'git.status': return gitStatus(cwd)\n case 'git.action': return gitAction(cwd, stringField(body, 'action'), typeof body.path === 'string' ? body.path : undefined, typeof body.value === 'string' ? body.value : undefined)\n default: throw new WorkbenchError('not-found', `unknown workbench API method ${method}`, 404)\n }\n}\n\nexport function apply(ctx: HostContext): void {\n installTerminal(ctx)\n ctx.effect(() => ctx.webServer.register({\n kind: 'exact', path: '/dsh-vscode/codicons/codicon.ttf', handler: async (req, res) => {\n if (!authorize(req, res, ctx.connection)) return\n try {\n const asset = codiconAsset()\n res.writeHead(200, { 'content-type': asset.type, 'cache-control': 'public, max-age=31536000, immutable' })\n res.end(await readFile(asset.path))\n } catch (error) { sendError(res, error) }\n },\n }), 'dsh-vscode-workbench: Codicon font')\n\n ctx.effect(() => ctx.webServer.register({\n kind: 'exact', path: '/dsh-vscode/pdfjs/worker.mjs', handler: async (req, res) => {\n if (!authorize(req, res, ctx.connection)) return\n try {\n const asset = pdfWorkerAsset()\n res.writeHead(200, { 'content-type': asset.type, 'cache-control': 'public, max-age=31536000, immutable' })\n res.end(await readFile(asset.path))\n } catch (error) { sendError(res, error) }\n },\n }), 'dsh-vscode-workbench: PDF.js worker')\n\n ctx.effect(() => ctx.webServer.register({\n kind: 'prefix', path: '/dsh-vscode/api', handler: async (req, res) => {\n if (!authorize(req, res, ctx.connection)) return\n if (req.method !== 'POST') return send(res, 405, { ok: false, error: { code: 'method', message: 'POST required' } })\n try {\n const controller = new AbortController()\n req.once('aborted', () => controller.abort())\n const path = new URL(req.url ?? '/', 'http://dsh.local').pathname\n const method = path.slice('/dsh-vscode/api/'.length)\n send(res, 200, { ok: true, value: await dispatch(ctx, method, await readBody(req), controller.signal) })\n } catch (error) { sendError(res, error) }\n },\n }), 'dsh-vscode-workbench: API')\n\n ctx.effect(() => ctx.webServer.register({\n kind: 'exact', path: '/dsh-vscode/upload', handler: async (req, res) => {\n if (!authorize(req, res, ctx.connection)) return\n if (req.method !== 'POST') return send(res, 405, { ok: false, error: { code: 'method', message: 'POST required' } })\n try {\n const url = new URL(req.url ?? '/', 'http://dsh.local')\n const sessionId = url.searchParams.get('sessionId'); const directory = url.searchParams.get('directory'); const name = url.searchParams.get('name')\n if (sessionId === null || directory === null || name === null) throw new WorkbenchError('bad-request', 'sessionId, directory and name are required')\n send(res, 201, { ok: true, value: await uploadFile(cwdFor(ctx, sessionId), directory, name, await readBinaryBody(req)) })\n } catch (error) { sendError(res, error) }\n },\n }), 'dsh-vscode-workbench: file upload')\n\n ctx.effect(() => ctx.webServer.register({\n kind:'prefix',path:'/dsh-vscode/file',handler:async(req,res)=>{if(!authorize(req,res,ctx.connection))return;try{const url=new URL(req.url??'/','http://dsh.local');const sessionId=url.searchParams.get('sessionId');const path=url.searchParams.get('path');if(sessionId===null||path===null)throw new WorkbenchError('bad-request','sessionId and path are required');const asset=await workspacePreviewFile(cwdFor(ctx,sessionId),path);res.writeHead(200,{'content-type':asset.type,'x-content-type-options':'nosniff','cache-control':'no-store'});res.end(await readFile(asset.path))}catch(error){sendError(res,error)}}\n }), 'dsh-vscode-workbench: file preview')\n\n ctx.effect(() => ctx.webServer.register({\n kind: 'prefix', path: '/dsh-vscode/monaco', handler: async (req, res) => {\n if (!authorize(req, res, ctx.connection)) return\n try {\n const raw = decodeURIComponent(new URL(req.url ?? '/', 'http://dsh.local').pathname.slice('/dsh-vscode/monaco/'.length))\n const asset = monacoAsset(raw)\n res.writeHead(200, { 'content-type': asset.type, 'cache-control': 'public, max-age=31536000, immutable' })\n res.end(await readFile(asset.path))\n } catch (error) { sendError(res, error) }\n },\n }), 'dsh-vscode-workbench: Monaco assets')\n\n const wss = new WebSocketServer({ noServer: true })\n ctx.effect(() => ctx.webServer.registerUpgrade({\n path: '/dsh-vscode/ws/files', handler(req, socket, head) {\n if (ctx.connection.requestRejection(req) !== undefined) { socket.destroy(); return }\n wss.handleUpgrade(req as IncomingMessage, socket as Duplex, head, (ws) => {\n const sessionId = new URL(req.url ?? '/', 'http://dsh.local').searchParams.get('sessionId')\n if (sessionId === null) { ws.close(1008, 'sessionId required'); return }\n let workspace: string\n try { workspace = cwdFor(ctx, sessionId) }\n catch { ws.close(1008, 'session workspace unavailable'); return }\n const watcher = chokidar.watch(workspace, { ignoreInitial: true, ignored: /(^|[/\\\\])(\\.git|node_modules|\\.next|\\.nuxt|\\.turbo|\\.vite|coverage)([/\\\\]|$)/, awaitWriteFinish: { stabilityThreshold: 100, pollInterval: 25 } })\n let paths = new Set<string>(); let timer: ReturnType<typeof setTimeout> | undefined\n watcher.on('all', (_event, path) => {\n const changed = isAbsolute(path) ? relative(workspace, path) : path\n paths.add(changed.split(sep).join('/')); clearTimeout(timer); timer = setTimeout(() => {\n if (ws.readyState === WebSocket.OPEN) ws.send(JSON.stringify({ type: 'files.changed', paths: [...paths] }))\n paths = new Set()\n }, 150)\n })\n ws.on('close', () => { clearTimeout(timer); void watcher.close() })\n })\n },\n }), 'dsh-vscode-workbench: file watcher')\n ctx.effect(() => () => { wss.close() }, 'dsh-vscode-workbench: watcher teardown')\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["require"],"sources":["../src/wire.ts","../src/host.ts","../src/terminal.ts","../src/index.ts"],"sourcesContent":["import type { IncomingMessage, ServerResponse } from 'node:http'\nimport type { WorkbenchConnection } from './context.ts'\n\nexport class WorkbenchError extends Error {\n constructor(public code: string, message: string, public status = 400) { super(message) }\n}\n\nexport async function readBody(req: IncomingMessage): Promise<Record<string, unknown>> {\n const chunks: Buffer[] = []\n let size = 0\n for await (const chunk of req) {\n const value = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)\n size += value.length\n if (size > 2 * 1024 * 1024) throw new WorkbenchError('too-large', 'request body is too large', 413)\n chunks.push(value)\n }\n try {\n const value: unknown = JSON.parse(Buffer.concat(chunks).toString('utf8') || '{}')\n if (value === null || typeof value !== 'object' || Array.isArray(value)) throw new Error('object expected')\n return value as Record<string, unknown>\n } catch { throw new WorkbenchError('bad-json', 'request body must be a JSON object') }\n}\n\n/** Read a binary upload while enforcing a fixed request limit. */\nexport async function readBinaryBody(req: IncomingMessage, limit = 100 * 1024 * 1024): Promise<Buffer> {\n const chunks: Buffer[] = []\n let size = 0\n for await (const chunk of req) {\n const value = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)\n size += value.length\n if (size > limit) throw new WorkbenchError('too-large', 'uploaded file is too large', 413)\n chunks.push(value)\n }\n return Buffer.concat(chunks)\n}\n\nexport function stringField(body: Record<string, unknown>, key: string): string {\n const value = body[key]\n if (typeof value !== 'string') throw new WorkbenchError('bad-request', `${key} must be a string`)\n return value\n}\n\nexport function send(res: ServerResponse, status: number, value: unknown): void {\n res.writeHead(status, { 'content-type': 'application/json; charset=utf-8', 'cache-control': 'no-store' })\n res.end(JSON.stringify(value))\n}\n\nexport function sendError(res: ServerResponse, error: unknown): void {\n const known = error instanceof WorkbenchError ? error : new WorkbenchError('internal', error instanceof Error ? error.message : String(error), 500)\n send(res, known.status, { ok: false, error: { code: known.code, message: known.message } })\n}\n\n/** Reuse Harness authentication and its deployment-aware Host/Origin fence. */\nexport function authorize(req: IncomingMessage, res: ServerResponse, connection: WorkbenchConnection): boolean {\n const rejection = connection.requestRejection(req)\n if (rejection === undefined) return true\n const code = rejection === 401 ? 'unauthorized' : 'forbidden'\n send(res, rejection, { ok: false, error: { code, message: code } })\n return false\n}\n","import { createHash, randomUUID } from 'node:crypto'\nimport { spawn } from 'node:child_process'\nimport { createRequire } from 'node:module'\nimport { dirname, extname, isAbsolute, join, normalize, relative, resolve, sep } from 'node:path'\nimport { access, lstat, mkdir, open, readFile, readdir, realpath, rename, rm, stat } from 'node:fs/promises'\nimport { constants } from 'node:fs'\nimport type { HostContext } from './context.ts'\nimport type { FileDocument, FileEntry, GitChange, GitCommit, GitCommitFile, GitDiff, GitStatus, SearchMatch, SearchRequest } from './types.ts'\nimport { WorkbenchError } from './wire.ts'\n\nconst require = createRequire(import.meta.url)\nconst TEXT_LIMIT = 5 * 1024 * 1024\nconst PROCESS_TIMEOUT = 30_000\n\nexport function cwdFor(ctx: HostContext, sessionId: string): string {\n const session = ctx.sessions.get(sessionId)\n if (session === undefined) throw new WorkbenchError('session-not-found', 'session not found', 404)\n const cwd = ctx.workingDirectory.get(session)\n if (!isAbsolute(cwd)) throw new WorkbenchError('cwd-invalid', 'session working directory is not absolute')\n return normalize(cwd)\n}\n\nfunction inside(root: string, target: string): boolean {\n const rel = relative(root, target)\n return rel === '' || (!rel.startsWith(`..${sep}`) && rel !== '..' && !isAbsolute(rel))\n}\n\nasync function canonicalRoot(cwd: string): Promise<string> {\n return realpath(cwd).catch(() => { throw new WorkbenchError('cwd-missing', 'session working directory does not exist', 404) })\n}\n\n/** Resolve a caller-relative path and reject traversal and symlink escape. */\nexport async function workspacePath(cwd: string, raw: string, create = false): Promise<{ root: string; absolute: string }> {\n if (isAbsolute(raw)) throw new WorkbenchError('path-invalid', 'absolute paths are not accepted')\n const root = await canonicalRoot(cwd)\n const absolute = resolve(root, raw === '' ? '.' : raw)\n if (!inside(root, absolute)) throw new WorkbenchError('path-outside', 'path is outside the workspace', 403)\n if (create) {\n const parent = await realpath(dirname(absolute)).catch(() => { throw new WorkbenchError('parent-missing', 'parent directory does not exist', 404) })\n if (!inside(root, parent)) throw new WorkbenchError('path-outside', 'path follows a symlink outside the workspace', 403)\n } else {\n const actual = await realpath(absolute).catch(() => { throw new WorkbenchError('not-found', 'path does not exist', 404) })\n if (!inside(root, actual)) throw new WorkbenchError('path-outside', 'path follows a symlink outside the workspace', 403)\n }\n return { root, absolute }\n}\n\nfunction relativePath(root: string, absolute: string): string { return relative(root, absolute).split(sep).join('/') }\nfunction revision(content: Buffer, mtimeMs: number): string {\n return createHash('sha256').update(content).update(String(mtimeMs)).digest('hex')\n}\n\nexport async function listFiles(cwd: string, path: string): Promise<FileEntry[]> {\n const { root, absolute } = await workspacePath(cwd, path)\n const values = await readdir(absolute, { withFileTypes: true })\n const rows = await Promise.all(values.filter(item => item.name !== '.git').map(async item => {\n const full = join(absolute, item.name)\n if (!item.isSymbolicLink()) return { name: item.name, path: relativePath(root, full), kind: item.isDirectory() ? 'directory' as const : 'file' as const }\n const actual = await realpath(full).catch(() => undefined)\n if (actual === undefined || !inside(root, actual)) return undefined\n const info = await stat(full)\n const kind = info.isDirectory() ? 'directory' as const : 'file' as const\n return { name: item.name, path: relativePath(root, full), kind, size: info.size, mtimeMs: info.mtimeMs }\n }))\n return rows.filter(row => row !== undefined).sort((a, b) => a.kind === b.kind ? a.name.localeCompare(b.name) : a.kind === 'directory' ? -1 : 1)\n}\n\nexport async function readDocument(cwd: string, path: string): Promise<FileDocument> {\n const { root, absolute } = await workspacePath(cwd, path)\n const info = await stat(absolute)\n if (!info.isFile()) throw new WorkbenchError('not-file', 'path is not a file')\n const tooLarge = info.size > TEXT_LIMIT\n const handle = await open(absolute, 'r')\n try {\n const head = Buffer.alloc(Math.min(info.size, tooLarge ? 4096 : TEXT_LIMIT))\n const { bytesRead } = await handle.read(head, 0, head.length, 0)\n const bytes = head.subarray(0, bytesRead)\n const binary = bytes.includes(0)\n return {\n path: relativePath(root, absolute), content: binary || tooLarge ? '' : bytes.toString('utf8'),\n revision: revision(bytes, info.mtimeMs), size: info.size, binary, tooLarge,\n }\n } finally { await handle.close() }\n}\n\nconst pendingSaves = new Map<string, Promise<void>>()\n\nexport async function saveDocument(cwd: string, path: string, content: string, expected: string): Promise<FileDocument> {\n const resolved = await workspacePath(cwd, path)\n const absolute = await realpath(resolved.absolute)\n const previous = pendingSaves.get(absolute) ?? Promise.resolve()\n let release!: () => void\n const pending = new Promise<void>(resolve => { release = resolve })\n pendingSaves.set(absolute, pending)\n await previous\n let temp: string | undefined\n try {\n const checkRevision = async () => {\n const checked = await workspacePath(cwd, path)\n if (await realpath(checked.absolute) !== absolute || (await readDocument(cwd, path)).revision !== expected) {\n throw new WorkbenchError('revision-conflict', 'file changed on disk; reload before saving', 409)\n }\n }\n await checkRevision()\n const info = await stat(absolute)\n temp = join(dirname(absolute), `.${randomUUID()}.dsh-vscode.tmp`)\n const handle = await open(temp, 'wx', info.mode & 0o777)\n try {\n await handle.writeFile(content, { encoding: 'utf8' })\n await handle.chmod(info.mode & 0o777)\n } finally { await handle.close() }\n await checkRevision()\n await rename(temp, absolute)\n return await readDocument(cwd, path)\n } finally {\n try { if (temp !== undefined) await rm(temp, { force: true }) }\n finally {\n release()\n if (pendingSaves.get(absolute) === pending) pendingSaves.delete(absolute)\n }\n }\n}\n\nexport async function createEntry(cwd: string, path: string, kind: 'file' | 'directory'): Promise<void> {\n const { absolute } = await workspacePath(cwd, path, true)\n if (kind === 'directory') await mkdir(absolute)\n else { const handle = await open(absolute, 'wx'); await handle.close() }\n}\n\n/** Write an uploaded file into an existing workspace directory without overwriting files. */\nexport async function uploadFile(cwd: string, directory: string, name: string, content: Buffer): Promise<FileEntry> {\n if (name === '' || name === '.' || name === '..' || name.includes('/') || name.includes('\\\\')) throw new WorkbenchError('filename-invalid', 'uploaded file name is invalid')\n const targetPath = directory === '' ? name : `${directory}/${name}`\n const { root, absolute } = await workspacePath(cwd, targetPath, true)\n const handle = await open(absolute, 'wx')\n try { await handle.writeFile(content) } finally { await handle.close() }\n const info = await lstat(absolute)\n return { name, path: relativePath(root, absolute), kind: 'file', size: info.size, mtimeMs: info.mtimeMs }\n}\n\nexport async function renameEntry(cwd: string, path: string, nextPath: string): Promise<void> {\n const source = await workspacePath(cwd, path)\n const target = await workspacePath(cwd, nextPath, true)\n await access(target.absolute, constants.F_OK).then(\n () => { throw new WorkbenchError('target-exists', 'destination already exists', 409) }, () => undefined,\n )\n await rename(source.absolute, target.absolute)\n}\n\nexport async function deleteEntry(cwd: string, path: string): Promise<void> {\n const { root, absolute } = await workspacePath(cwd, path)\n if (absolute === root) throw new WorkbenchError('root-delete', 'cannot delete workspace root', 403)\n await rm(absolute, { recursive: true, force: false })\n}\n\nconst IMAGE_TYPES:Record<string,string>={'.avif':'image/avif','.bmp':'image/bmp','.gif':'image/gif','.ico':'image/x-icon','.jpeg':'image/jpeg','.jpg':'image/jpeg','.png':'image/png','.svg':'image/svg+xml','.webp':'image/webp'}\nconst PREVIEW_TYPES:Record<string,string>={...IMAGE_TYPES,'.pdf':'application/pdf','.doc':'application/msword','.docx':'application/vnd.openxmlformats-officedocument.wordprocessingml.document','.odt':'application/vnd.oasis.opendocument.text'}\n/** Resolve an image inside the workspace for protected browser preview. */\nexport async function workspaceImage(cwd:string,path:string):Promise<{path:string;type:string}>{const resolved=await workspacePath(cwd,path);const type=IMAGE_TYPES[extname(resolved.absolute).toLowerCase()];if(type===undefined)throw new WorkbenchError('unsupported-media','file is not a supported image',415);return {path:resolved.absolute,type}}\n/** Resolve a supported preview file inside the workspace. */\nexport async function workspacePreviewFile(cwd:string,path:string):Promise<{path:string;type:string}>{const resolved=await workspacePath(cwd,path);const type=PREVIEW_TYPES[extname(resolved.absolute).toLowerCase()];if(type===undefined)throw new WorkbenchError('unsupported-media','file is not a supported preview format',415);return {path:resolved.absolute,type}}\n\n/** Resolve the PDF.js worker shipped with this plugin's runtime dependency. */\nexport function pdfWorkerAsset(): { path: string; type: string } {\n return { path: require.resolve('pdfjs-dist/legacy/build/pdf.worker.min.mjs'), type: 'text/javascript; charset=utf-8' }\n}\n\ninterface ProcessResult { stdout: string; stderr: string; code: number }\nexport function run(command: string, args: string[], cwd: string, timeout = PROCESS_TIMEOUT, signal?: AbortSignal): Promise<ProcessResult> {\n return new Promise((resolvePromise, reject) => {\n const child = spawn(command, args, { cwd, shell: false, windowsHide: true })\n let stdout = ''; let stderr = ''; let settled = false\n const timer = setTimeout(() => { child.kill(); if (!settled) reject(new WorkbenchError('timeout', `${command} timed out`, 504)) }, timeout)\n const abort = () => { child.kill(); if (!settled) { settled = true; clearTimeout(timer); reject(new WorkbenchError('cancelled', `${command} cancelled`, 499)) } }\n signal?.addEventListener('abort', abort, { once: true })\n child.stdout.on('data', chunk => { stdout += String(chunk) })\n child.stderr.on('data', chunk => { stderr += String(chunk) })\n child.on('error', error => { clearTimeout(timer); signal?.removeEventListener('abort', abort); if (!settled) { settled = true; reject(error) } })\n child.on('close', code => { clearTimeout(timer); signal?.removeEventListener('abort', abort); if (!settled) { settled = true; resolvePromise({ stdout, stderr, code: code ?? 1 }) } })\n })\n}\n\nexport async function searchWorkspace(cwd: string, request: SearchRequest, signal?: AbortSignal): Promise<{ matches: SearchMatch[]; limited: boolean }> {\n if (request.query === '') return { matches: [], limited: false }\n const root = await canonicalRoot(cwd)\n const rg = require('@vscode/ripgrep').rgPath as string\n const args = ['--json', '--line-number', '--column', '--hidden', '--glob', '!.git/**', '--max-count', '2000']\n if (!request.regex) args.push('--fixed-strings')\n if (!request.caseSensitive) args.push('--ignore-case')\n if (request.wholeWord) args.push('--word-regexp')\n if (request.include) args.push('--glob', request.include)\n if (request.exclude) args.push('--glob', `!${request.exclude}`)\n args.push('--', request.query, '.')\n const result = await run(rg, args, root, PROCESS_TIMEOUT, signal)\n if (result.code > 1) throw new WorkbenchError('search-failed', result.stderr || 'ripgrep failed', 500)\n const matches: SearchMatch[] = []\n for (const line of result.stdout.split('\\n')) {\n if (line === '') continue\n const event = JSON.parse(line) as { type: string; data?: { path?: { text?: string }; lines?: { text?: string }; line_number?: number; submatches?: Array<{ start: number; end: number; match?: { text?: string } }> } }\n if (event.type !== 'match' || event.data?.path?.text === undefined || event.data.lines?.text === undefined) continue\n for (const hit of event.data.submatches ?? []) {\n matches.push({ path: event.data.path.text.replace(/^\\.\\//, ''), line: event.data.line_number ?? 1, column: hit.start + 1, preview: event.data.lines.text.trimEnd(), match: hit.match?.text ?? '' })\n if (matches.length >= 2000) return { matches, limited: true }\n }\n }\n return { matches, limited: false }\n}\n\nasync function gitRoot(cwd: string): Promise<string> {\n const result = await run('git', ['rev-parse', '--show-toplevel'], cwd)\n if (result.code !== 0) throw new WorkbenchError('not-repository', 'current workspace is not inside a Git repository', 404)\n return result.stdout.trim()\n}\n\nfunction validateCommitHash(value?: string): string {\n if (!/^[0-9a-f]{7,64}$/i.test(value ?? '')) throw new WorkbenchError('bad-request', 'commit hash is invalid')\n return value!\n}\n\nfunction validateGitPath(repository: string, path?: string): string {\n if (path === undefined || path === '' || isAbsolute(path) || !inside(repository, resolve(repository, path))) throw new WorkbenchError('bad-request', 'repository-relative path is required')\n return path\n}\n\nasync function gitObject(repository: string, spec: string): Promise<string> {\n const result = await run('git', ['show', '--no-textconv', spec], repository)\n return result.code === 0 ? result.stdout : ''\n}\n\nasync function commitFiles(repository: string, hash: string): Promise<GitCommitFile[]> {\n const parent=await run('git',['rev-parse','--verify',`${hash}^1`],repository)\n const result = parent.code===0\n ? await run('git',['diff','--name-status','-z','-M',parent.stdout.trim(),hash,'--'],repository)\n : await run('git', ['diff-tree', '--root', '--no-commit-id', '--name-status', '-r', '-z', '-M', hash], repository)\n if (result.code !== 0) throw new WorkbenchError('git-failed', result.stderr || result.stdout, 409)\n const tokens = result.stdout.split('\\0').filter(Boolean); const files: GitCommitFile[] = []\n for (let index = 0; index < tokens.length;) {\n const status = tokens[index++] ?? ''; const code = status[0] ?? ''\n if (code === 'R' || code === 'C') { const previousPath=tokens[index++]??'';const path=tokens[index++]??'';files.push({path,previousPath,status:code}) }\n else { const path=tokens[index++]??'';files.push({path,status:code}) }\n }\n return files\n}\n\nexport async function gitStatus(cwd: string): Promise<GitStatus> {\n const repository = await gitRoot(cwd)\n const result = await run('git', ['status', '--porcelain=v2', '-z', '--branch', '--untracked-files=all'], repository)\n if (result.code !== 0) throw new WorkbenchError('git-failed', result.stderr, 500)\n let branch = 'HEAD'; let ahead = 0; let behind = 0\n const changes: GitChange[] = []\n const records = result.stdout.split('\\0')\n for (let index = 0; index < records.length; index++) {\n const record = records[index]!\n if (record.startsWith('# branch.head ')) branch = record.slice(14)\n else if (record.startsWith('# branch.ab ')) {\n const match = /\\+(\\d+) -(\\d+)/.exec(record); ahead = Number(match?.[1] ?? 0); behind = Number(match?.[2] ?? 0)\n } else if (record.startsWith('? ')) changes.push({ path: record.slice(2), index: '?', worktree: '?', staged: false, untracked: true })\n else if (record.startsWith('1 ') || record.startsWith('2 ') || record.startsWith('u ')) {\n const renamed = record.startsWith('2 ')\n const parts = record.split(' '); const xy = parts[1] ?? '..'\n const path = parts.slice(renamed ? 9 : record.startsWith('u ') ? 10 : 8).join(' ')\n const originalPath = renamed ? records[++index] : undefined\n changes.push({ path, ...(originalPath === undefined ? {} : { originalPath }), index: xy[0] ?? '.', worktree: xy[1] ?? '.', staged: xy[0] !== '.', untracked: false })\n }\n }\n return { repository, branch, ahead, behind, changes }\n}\n\nexport async function gitAction(cwd: string, action: string, path?: string, value?: string): Promise<unknown> {\n const repository = await gitRoot(cwd)\n let args: string[]\n switch (action) {\n case 'stage': args = ['add', '--', path ?? '']; break\n case 'stage.all': args = ['add', '-A']; break\n case 'unstage': args = ['restore', '--staged', '--', path ?? '']; break\n case 'unstage.all': args = ['restore', '--staged', '--', '.']; break\n case 'discard': {\n args = value === 'untracked' ? ['clean', '-f', '--', path ?? ''] : ['restore', '--worktree', '--', path ?? '']\n break\n }\n case 'discard.all': {\n const head = await run('git', ['rev-parse', '--verify', 'HEAD'], repository)\n if (head.code === 0) {\n const restore = await run('git', ['restore', '--source=HEAD', '--staged', '--worktree', '--', '.'], repository)\n if (restore.code !== 0) throw new WorkbenchError('git-failed', restore.stderr || restore.stdout, 409)\n }\n const clean = await run('git', ['clean', '-fd'], repository)\n if (clean.code !== 0) throw new WorkbenchError('git-failed', clean.stderr || clean.stdout, 409)\n return gitStatus(cwd)\n }\n case 'commit': args = ['commit', '-m', value ?? '']; break\n case 'branch.create': args = ['switch', '-c', value ?? '']; break\n case 'branch.switch': args = ['switch', value ?? '']; break\n case 'branches': {\n const result = await run('git', ['for-each-ref', '--format=%(refname:short)', 'refs/heads'], repository)\n if (result.code !== 0) throw new WorkbenchError('git-failed', result.stderr, 500)\n return result.stdout.split('\\n').filter(Boolean)\n }\n case 'log': {\n const head = await run('git', ['rev-parse', '--verify', 'HEAD'], repository)\n if (head.code !== 0) return []\n const result = await run('git', ['log', '--topo-order', '--date=iso-strict', '--decorate=short', '--pretty=format:%H%x1f%P%x1f%an%x1f%aI%x1f%s%x1f%D%x00', '-n', '100'], repository)\n if (result.code !== 0) throw new WorkbenchError('git-failed', result.stderr || result.stdout, 500)\n return result.stdout.split('\\0').filter(Boolean).map((record): GitCommit => {\n const [rawHash = '', parents = '', author = '', date = '', subject = '', refs = ''] = record.split('\\x1f');const hash=rawHash.trim()\n return { hash, parents: parents.split(' ').filter(Boolean), author, date, subject, refs: refs.split(',').map(item => item.trim()).filter(Boolean) }\n })\n }\n case 'commit.show': {\n const hash = validateCommitHash(value)\n const result = await run('git', ['show', '--no-ext-diff', '--find-renames', '--format=fuller', '--stat', '--patch', '--no-color', hash], repository)\n if (result.code !== 0) throw new WorkbenchError('git-failed', result.stderr || result.stdout, 409)\n return { diff: result.stdout, original: '', modified: result.stdout } satisfies GitDiff\n }\n case 'commit.files': return commitFiles(repository, validateCommitHash(value))\n case 'commit.file.diff': {\n const hash=validateCommitHash(value);const target=validateGitPath(repository,path);const files=await commitFiles(repository,hash);const file=files.find(item=>item.path===target)\n if (file===undefined) throw new WorkbenchError('not-found','file is not part of the commit',404)\n const parent=await run('git',['rev-parse','--verify',`${hash}^1`],repository)\n const shown=parent.code===0\n ? await run('git',['diff','--no-ext-diff','--find-renames','--patch','--no-color',parent.stdout.trim(),hash,'--',file.previousPath??target,target],repository)\n : await run('git',['show','--no-ext-diff','--find-renames','--format=','--patch','--no-color',hash,'--',file.previousPath??target,target],repository)\n if(shown.code!==0)throw new WorkbenchError('git-failed',shown.stderr||shown.stdout,409)\n const original=file.status==='A'||parent.code!==0?'':await gitObject(repository,`${parent.stdout.trim()}:${file.previousPath??target}`)\n const modified=file.status==='D'?'':await gitObject(repository,`${hash}:${target}`)\n return {diff:shown.stdout,original,modified} satisfies GitDiff\n }\n case 'diff': {\n const untracked = value === 'untracked'\n const staged = value === 'staged'\n args = untracked\n ? ['diff', '--no-index', '--', process.platform === 'win32' ? 'NUL' : '/dev/null', path ?? '']\n : ['diff', ...(staged ? ['--cached'] : []), '--', path ?? '']\n break\n }\n default: throw new WorkbenchError('bad-action', `unknown Git action ${action}`)\n }\n if (args.some(arg => arg === '') && action !== 'commit') throw new WorkbenchError('bad-request', 'path or value is required')\n const result = await run('git', args, repository)\n const expectedUntrackedDifference = action === 'diff' && value === 'untracked' && result.code === 1\n if (result.code !== 0 && !expectedUntrackedDifference) throw new WorkbenchError('git-failed', result.stderr || result.stdout, 409)\n if(action!=='diff')return gitStatus(cwd)\n const target=validateGitPath(repository,path)\n const original=value==='untracked'?'':await gitObject(repository,`${value==='staged'?'HEAD:':':'}${target}`)\n const modified=value==='staged'?await gitObject(repository,`:${target}`):await readFile(resolve(repository,target),'utf8').catch(()=> '')\n return {diff:result.stdout,original,modified} satisfies GitDiff\n}\n\n/** Resolve the official VS Code Codicon font shipped by @vscode/codicons. */\nexport function codiconAsset(): { path: string; type: string } {\n const packageRoot = dirname(require.resolve('@vscode/codicons/package.json'))\n return { path: resolve(packageRoot, 'dist', 'codicon.ttf'), type: 'font/ttf' }\n}\n\nexport function monacoAsset(raw: string): { path: string; type: string } {\n const packageRoot = dirname(require.resolve('monaco-editor/package.json'))\n const path = resolve(packageRoot, 'min', raw)\n const root = resolve(packageRoot, 'min')\n if (!inside(root, path)) throw new WorkbenchError('asset-invalid', 'invalid Monaco asset path', 403)\n const type = extname(path) === '.css' ? 'text/css' : extname(path) === '.js' ? 'text/javascript' : extname(path) === '.ttf' ? 'font/ttf' : 'application/octet-stream'\n return { path, type }\n}\n","import { randomUUID } from 'node:crypto'\nimport { chmodSync, realpathSync, statSync } from 'node:fs'\nimport { createRequire } from 'node:module'\nimport { basename, dirname, join } from 'node:path'\nimport type { IncomingMessage } from 'node:http'\nimport type { Duplex } from 'node:stream'\nimport * as pty from 'node-pty'\nimport type { IPty } from 'node-pty'\nimport { WebSocket, WebSocketServer } from 'ws'\nimport type { HostContext } from './context.ts'\nimport { cwdFor } from './host.ts'\nimport { authorize, readBody, send, sendError } from './wire.ts'\n\nconst require = createRequire(import.meta.url)\n\nexport interface TerminalInfo { id: string; title: string; cwd: string; running: boolean; exitCode?: number; sequence: number }\nexport interface TerminalOutput { sequence: number; data: string }\n\ninterface TerminalHandle { info: TerminalInfo; process: IPty; replay: string; listeners: Set<(output: TerminalOutput) => void> }\nconst SENSITIVE = /(api[_-]?key|token|credential|secret|password|passwd|private[_-]?key|^dsh_.*(?:key|token|secret))/i\nconst MAX_TERMINALS = 8\nconst REPLAY_BYTES = 2 * 1024 * 1024\n\n/** Remove credentials while retaining ordinary interactive-shell variables. */\nexport function sanitizedTerminalEnv(env: NodeJS.ProcessEnv): Record<string, string> {\n return Object.fromEntries(Object.entries(env).filter(([key, value]) => value !== undefined && !SENSITIVE.test(key)) as Array<[string, string]>)\n}\n\n/** Select the user's interactive shell with platform-specific fallbacks. */\nexport function defaultTerminalShell(platform = process.platform, env = process.env): { shell: string; args: string[] } {\n if (platform === 'win32') return { shell: env.COMSPEC?.toLowerCase().includes('powershell') ? env.COMSPEC : 'powershell.exe', args: ['-NoLogo'] }\n return { shell: env.SHELL || (platform === 'darwin' ? '/bin/zsh' : '/bin/bash'), args: ['-l'] }\n}\n\n/** Add execute bits when a registry package extracted a native helper without them. */\nexport function ensureExecutable(path: string): boolean {\n if (process.platform === 'win32') return true\n try {\n const mode = statSync(path).mode\n if ((mode & 0o111) === 0) chmodSync(path, mode | 0o111)\n return true\n } catch {\n return false\n }\n}\n\n/** Repair node-pty's macOS/Linux helper, whose npm package currently loses its execute bit. */\nexport function repairNodePtyHelper(): void {\n if (process.platform === 'win32') return\n const packageDirectory = dirname(require.resolve('node-pty/package.json'))\n ensureExecutable(join(packageDirectory, 'build', 'Release', 'spawn-helper'))\n ensureExecutable(join(packageDirectory, 'prebuilds', `${process.platform}-${process.arch}`, 'spawn-helper'))\n}\n\n/** Own interactive terminals by their canonical workspace directory. */\nexport class TerminalManager {\n private readonly workspaces = new Map<string, Map<string, TerminalHandle>>()\n\n constructor() { repairNodePtyHelper() }\n\n private workspace(cwd: string): string { return realpathSync(cwd) }\n\n list(cwd: string): TerminalInfo[] { return [...(this.workspaces.get(this.workspace(cwd))?.values() ?? [])].map(handle => ({ ...handle.info })) }\n\n create(cwd: string, title?: string): TerminalInfo {\n const key = this.workspace(cwd)\n const terminals = this.workspaces.get(key) ?? new Map<string, TerminalHandle>()\n this.workspaces.set(key, terminals)\n if (terminals.size >= MAX_TERMINALS) throw new Error(`terminal limit reached (${MAX_TERMINALS})`)\n const { shell, args } = defaultTerminalShell()\n const child = pty.spawn(shell, args, { name: 'xterm-256color', cols: 80, rows: 24, cwd: key, env: sanitizedTerminalEnv(process.env) })\n const info: TerminalInfo = { id: randomUUID(), title: title || basename(shell), cwd: key, running: true, sequence: 0 }\n const handle: TerminalHandle = { info, process: child, replay: '', listeners: new Set() }\n terminals.set(info.id, handle)\n child.onData(data => {\n info.sequence++\n handle.replay += data\n if (Buffer.byteLength(handle.replay) > REPLAY_BYTES) handle.replay = handle.replay.slice(-REPLAY_BYTES)\n for (const listener of handle.listeners) listener({ sequence: info.sequence, data })\n })\n child.onExit(({ exitCode }) => {\n info.running = false\n info.exitCode = exitCode\n info.sequence++\n const data = `\\r\\n[process exited with code ${exitCode}]\\r\\n`\n for (const listener of handle.listeners) listener({ sequence: info.sequence, data })\n })\n return { ...info }\n }\n\n get(cwd: string, id: string): TerminalHandle | undefined { return this.workspaces.get(this.workspace(cwd))?.get(id) }\n\n close(cwd: string, id: string): void {\n const key = this.workspace(cwd)\n const terminals = this.workspaces.get(key)\n const handle = terminals?.get(id)\n if (handle === undefined || terminals === undefined) return\n terminals.delete(id)\n try { handle.process.kill() } catch { /* The shell may already have exited. */ }\n if (terminals.size === 0) this.workspaces.delete(key)\n }\n\n rename(cwd: string, id: string, title: string): TerminalInfo {\n const handle = this.get(cwd, id)\n if (handle === undefined) throw new Error('terminal not found')\n handle.info.title = title\n return { ...handle.info }\n }\n\n dispose(): void { for (const [cwd, terminals] of this.workspaces) for (const id of terminals.keys()) this.close(cwd, id) }\n}\n\nfunction terminalRequestAllowed(req: IncomingMessage): boolean {\n const host = req.headers.host\n if (host === undefined || req.headers['sec-fetch-site'] === 'cross-site') return false\n let hostname: string\n try { hostname = new URL(`http://${host}`).hostname } catch { return false }\n if (hostname !== 'localhost' && hostname !== '[::1]' && !hostname.startsWith('127.')) return false\n const origin = req.headers.origin\n try { return origin === undefined || new URL(origin).host === host } catch { return false }\n}\n\n/** Register the private local terminal API and WebSocket transport. */\nexport function installTerminal(ctx: HostContext): void {\n const manager = new TerminalManager()\n ctx.effect(() => ctx.webServer.register({ kind: 'prefix', path: '/dsh-vscode-terminal/api', handler: async (req, res) => {\n if (!authorize(req, res, ctx.connection)) return\n if (!terminalRequestAllowed(req)) return send(res, 403, { ok: false, error: { message: 'forbidden' } })\n if (req.method !== 'POST') return send(res, 405, { ok: false, error: { message: 'POST required' } })\n try {\n const body = await readBody(req)\n const sessionId = typeof body.sessionId === 'string' ? body.sessionId : ''\n if (sessionId === '') throw new Error('sessionId required')\n const cwd = cwdFor(ctx, sessionId)\n const method = new URL(req.url ?? '/', 'http://dsh.local').pathname.slice('/dsh-vscode-terminal/api/'.length)\n let value: unknown\n if (method === 'list') value = manager.list(cwd)\n else if (method === 'create') value = manager.create(cwd, typeof body.title === 'string' ? body.title : undefined)\n else if (method === 'close') { manager.close(cwd, typeof body.id === 'string' ? body.id : ''); value = manager.list(cwd) }\n else if (method === 'rename') value = manager.rename(cwd, typeof body.id === 'string' ? body.id : '', typeof body.title === 'string' ? body.title : '')\n else throw new Error('unknown terminal method')\n send(res, 200, { ok: true, value })\n } catch (error) { sendError(res, error) }\n } }), 'dsh-vscode-workbench: terminal API')\n\n const webSocket = new WebSocketServer({ noServer: true })\n ctx.effect(() => ctx.webServer.registerUpgrade({ path: '/dsh-vscode-terminal/ws', handler(req, socket, head) {\n if (ctx.connection.requestRejection(req) !== undefined || !terminalRequestAllowed(req)) { socket.destroy(); return }\n webSocket.handleUpgrade(req as IncomingMessage, socket as Duplex, head, connection => {\n const url = new URL(req.url ?? '/', 'http://dsh.local')\n const sessionId = url.searchParams.get('sessionId')\n const id = url.searchParams.get('id')\n if (sessionId === null || id === null) { connection.close(1008, 'sessionId and id required'); return }\n let handle: TerminalHandle | undefined\n try { handle = manager.get(cwdFor(ctx, sessionId), id) }\n catch { connection.close(1008, 'session workspace unavailable'); return }\n if (handle === undefined) { connection.close(1008, 'terminal not found'); return }\n if (handle.replay !== '') connection.send(JSON.stringify({ type: 'replay', sequence: handle.info.sequence, data: handle.replay }))\n const listener = (output: TerminalOutput) => { if (connection.readyState === WebSocket.OPEN) connection.send(JSON.stringify({ type: 'output', ...output })) }\n handle.listeners.add(listener)\n connection.on('message', raw => {\n const text = raw.toString()\n try {\n const message: unknown = JSON.parse(text)\n if (message !== null && typeof message === 'object' && 'type' in message && message.type === 'input' && 'data' in message && typeof message.data === 'string') handle.process.write(message.data)\n else if (message !== null && typeof message === 'object' && 'type' in message && message.type === 'resize' && 'cols' in message && 'rows' in message && typeof message.cols === 'number' && typeof message.rows === 'number') handle.process.resize(Math.max(2, Math.floor(message.cols)), Math.max(2, Math.floor(message.rows)))\n } catch { handle.process.write(text) }\n })\n connection.on('close', () => handle.listeners.delete(listener))\n })\n } }), 'dsh-vscode-workbench: terminal WebSocket')\n ctx.effect(() => () => { webSocket.close(); manager.dispose() }, 'dsh-vscode-workbench: terminal teardown')\n}\n","/** DSH host plugin for the VS Code workbench. */\nimport { readFile } from 'node:fs/promises'\nimport type { IncomingMessage } from 'node:http'\nimport { isAbsolute, relative, sep } from 'node:path'\nimport type { Duplex } from 'node:stream'\nimport chokidar from 'chokidar'\nimport { WebSocket, WebSocketServer } from 'ws'\nimport type { HostContext } from './context.ts'\nimport { codiconAsset, createEntry, cwdFor, deleteEntry, gitAction, gitStatus, listFiles, monacoAsset, pdfWorkerAsset, readDocument, renameEntry, saveDocument, searchWorkspace, uploadFile, workspacePreviewFile } from './host.ts'\nimport { installTerminal } from './terminal.ts'\nimport type { SearchRequest } from './types.ts'\nimport { readBinaryBody, readBody, send, sendError, stringField, authorize, WorkbenchError } from './wire.ts'\n\nexport { WorkbenchError } from './wire.ts'\nexport * from './types.ts'\nexport const name = 'dsh-vscode-workbench'\nexport const inject = ['webServer', 'sessions', 'connection', 'workingDirectory']\n\nasync function dispatch(ctx: HostContext, method: string, body: Record<string, unknown>, signal?: AbortSignal): Promise<unknown> {\n const sessionId = stringField(body, 'sessionId'); const cwd = cwdFor(ctx, sessionId)\n switch (method) {\n case 'workspace': return { cwd, name: cwd.split(/[\\\\/]/).at(-1) || cwd }\n case 'fs.list': return listFiles(cwd, stringField(body, 'path'))\n case 'fs.read': return readDocument(cwd, stringField(body, 'path'))\n case 'fs.save': return saveDocument(cwd, stringField(body, 'path'), stringField(body, 'content'), stringField(body, 'revision'))\n case 'fs.create': return createEntry(cwd, stringField(body, 'path'), body.kind === 'directory' ? 'directory' : 'file').then(() => ({ ok: true }))\n case 'fs.rename': return renameEntry(cwd, stringField(body, 'path'), stringField(body, 'nextPath')).then(() => ({ ok: true }))\n case 'fs.delete': return deleteEntry(cwd, stringField(body, 'path')).then(() => ({ ok: true }))\n case 'search': return searchWorkspace(cwd, body as unknown as SearchRequest, signal)\n case 'git.status': return gitStatus(cwd)\n case 'git.action': return gitAction(cwd, stringField(body, 'action'), typeof body.path === 'string' ? body.path : undefined, typeof body.value === 'string' ? body.value : undefined)\n default: throw new WorkbenchError('not-found', `unknown workbench API method ${method}`, 404)\n }\n}\n\nexport function apply(ctx: HostContext): void {\n installTerminal(ctx)\n ctx.effect(() => ctx.webServer.register({\n kind: 'exact', path: '/dsh-vscode/codicons/codicon.ttf', handler: async (req, res) => {\n if (!authorize(req, res, ctx.connection)) return\n try {\n const asset = codiconAsset()\n res.writeHead(200, { 'content-type': asset.type, 'cache-control': 'public, max-age=31536000, immutable' })\n res.end(await readFile(asset.path))\n } catch (error) { sendError(res, error) }\n },\n }), 'dsh-vscode-workbench: Codicon font')\n\n ctx.effect(() => ctx.webServer.register({\n kind: 'exact', path: '/dsh-vscode/pdfjs/worker.mjs', handler: async (req, res) => {\n if (!authorize(req, res, ctx.connection)) return\n try {\n const asset = pdfWorkerAsset()\n res.writeHead(200, { 'content-type': asset.type, 'cache-control': 'public, max-age=31536000, immutable' })\n res.end(await readFile(asset.path))\n } catch (error) { sendError(res, error) }\n },\n }), 'dsh-vscode-workbench: PDF.js worker')\n\n ctx.effect(() => ctx.webServer.register({\n kind: 'prefix', path: '/dsh-vscode/api', handler: async (req, res) => {\n if (!authorize(req, res, ctx.connection)) return\n if (req.method !== 'POST') return send(res, 405, { ok: false, error: { code: 'method', message: 'POST required' } })\n try {\n const controller = new AbortController()\n req.once('aborted', () => controller.abort())\n const path = new URL(req.url ?? '/', 'http://dsh.local').pathname\n const method = path.slice('/dsh-vscode/api/'.length)\n send(res, 200, { ok: true, value: await dispatch(ctx, method, await readBody(req), controller.signal) })\n } catch (error) { sendError(res, error) }\n },\n }), 'dsh-vscode-workbench: API')\n\n ctx.effect(() => ctx.webServer.register({\n kind: 'exact', path: '/dsh-vscode/upload', handler: async (req, res) => {\n if (!authorize(req, res, ctx.connection)) return\n if (req.method !== 'POST') return send(res, 405, { ok: false, error: { code: 'method', message: 'POST required' } })\n try {\n const url = new URL(req.url ?? '/', 'http://dsh.local')\n const sessionId = url.searchParams.get('sessionId'); const directory = url.searchParams.get('directory'); const name = url.searchParams.get('name')\n if (sessionId === null || directory === null || name === null) throw new WorkbenchError('bad-request', 'sessionId, directory and name are required')\n send(res, 201, { ok: true, value: await uploadFile(cwdFor(ctx, sessionId), directory, name, await readBinaryBody(req)) })\n } catch (error) { sendError(res, error) }\n },\n }), 'dsh-vscode-workbench: file upload')\n\n ctx.effect(() => ctx.webServer.register({\n kind:'prefix',path:'/dsh-vscode/file',handler:async(req,res)=>{if(!authorize(req,res,ctx.connection))return;try{const url=new URL(req.url??'/','http://dsh.local');const sessionId=url.searchParams.get('sessionId');const path=url.searchParams.get('path');if(sessionId===null||path===null)throw new WorkbenchError('bad-request','sessionId and path are required');const asset=await workspacePreviewFile(cwdFor(ctx,sessionId),path);res.writeHead(200,{'content-type':asset.type,'x-content-type-options':'nosniff','cache-control':'no-store'});res.end(await readFile(asset.path))}catch(error){sendError(res,error)}}\n }), 'dsh-vscode-workbench: file preview')\n\n ctx.effect(() => ctx.webServer.register({\n kind: 'prefix', path: '/dsh-vscode/monaco', handler: async (req, res) => {\n if (!authorize(req, res, ctx.connection)) return\n try {\n const raw = decodeURIComponent(new URL(req.url ?? '/', 'http://dsh.local').pathname.slice('/dsh-vscode/monaco/'.length))\n const asset = monacoAsset(raw)\n res.writeHead(200, { 'content-type': asset.type, 'cache-control': 'public, max-age=31536000, immutable' })\n res.end(await readFile(asset.path))\n } catch (error) { sendError(res, error) }\n },\n }), 'dsh-vscode-workbench: Monaco assets')\n\n const wss = new WebSocketServer({ noServer: true })\n ctx.effect(() => ctx.webServer.registerUpgrade({\n path: '/dsh-vscode/ws/files', handler(req, socket, head) {\n if (ctx.connection.requestRejection(req) !== undefined) { socket.destroy(); return }\n wss.handleUpgrade(req as IncomingMessage, socket as Duplex, head, (ws) => {\n const sessionId = new URL(req.url ?? '/', 'http://dsh.local').searchParams.get('sessionId')\n if (sessionId === null) { ws.close(1008, 'sessionId required'); return }\n let workspace: string\n try { workspace = cwdFor(ctx, sessionId) }\n catch { ws.close(1008, 'session workspace unavailable'); return }\n const watcher = chokidar.watch(workspace, { ignoreInitial: true, ignored: /(^|[/\\\\])(\\.git|node_modules|\\.next|\\.nuxt|\\.turbo|\\.vite|coverage)([/\\\\]|$)/, awaitWriteFinish: { stabilityThreshold: 100, pollInterval: 25 } })\n let paths = new Set<string>(); let timer: ReturnType<typeof setTimeout> | undefined\n watcher.on('all', (_event, path) => {\n const changed = isAbsolute(path) ? relative(workspace, path) : path\n paths.add(changed.split(sep).join('/')); clearTimeout(timer); timer = setTimeout(() => {\n if (ws.readyState === WebSocket.OPEN) ws.send(JSON.stringify({ type: 'files.changed', paths: [...paths] }))\n paths = new Set()\n }, 150)\n })\n ws.on('close', () => { clearTimeout(timer); void watcher.close() })\n })\n },\n }), 'dsh-vscode-workbench: file watcher')\n ctx.effect(() => () => { wss.close() }, 'dsh-vscode-workbench: watcher teardown')\n}\n"],"mappings":"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"}
|
|
@@ -2,6 +2,7 @@ import type { FileDocument, GitCommit, GitDiff } from '../types.ts';
|
|
|
2
2
|
import type { VscodeWorkbench } from './service.ts';
|
|
3
3
|
import { type DocumentPreviewKind } from './documentPreview.tsx';
|
|
4
4
|
interface Tab extends FileDocument {
|
|
5
|
+
instance?: symbol;
|
|
5
6
|
dirty: boolean;
|
|
6
7
|
draft: string;
|
|
7
8
|
loaded?: boolean;
|
|
@@ -20,6 +21,8 @@ interface Tab extends FileDocument {
|
|
|
20
21
|
type ResizeDirection = 1 | -1;
|
|
21
22
|
/** Calculate a panel width from a horizontal pointer movement. */
|
|
22
23
|
export declare function resizedPanelWidth(startWidth: number, startX: number, nextX: number, direction: ResizeDirection, min: number, max: number): number;
|
|
24
|
+
/** Retry a workspace lookup that raced the Host publishing its session after startup. */
|
|
25
|
+
export declare function workspaceRetryDelay(error: unknown, attempt: number): number | undefined;
|
|
23
26
|
/** Restore tab headers without reading their file contents. */
|
|
24
27
|
export declare function restoreTabPaths(paths: string[]): Tab[];
|
|
25
28
|
/** Return whether file changes require reloading one visible directory. */
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/** Page facts needed to resolve a WebSocket URL. */
|
|
2
|
+
export interface WebSocketPageLocation {
|
|
3
|
+
readonly protocol: string;
|
|
4
|
+
readonly host: string;
|
|
5
|
+
}
|
|
6
|
+
/** Read the Host origin published by the DSH Desktop shell before application boot. */
|
|
7
|
+
export declare function transportStreamBaseUrl(globals?: typeof globalThis): string | undefined;
|
|
8
|
+
/**
|
|
9
|
+
* Resolve an absolute workbench route to a WebSocket URL.
|
|
10
|
+
*
|
|
11
|
+
* Network pages keep their own origin. Application-delivered pages such as
|
|
12
|
+
* `dsh-app://app/` have no WebSocket transport of their own, so they must use
|
|
13
|
+
* the local Host origin published by the desktop shell.
|
|
14
|
+
*/
|
|
15
|
+
export declare function websocketUrl(path: string, location?: WebSocketPageLocation, streamBaseUrl?: string | undefined): string | undefined;
|