coderaft 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE.md ADDED
@@ -0,0 +1,110 @@
1
+ # Third-Party Licenses
2
+
3
+ This package bundles the following third-party dependencies.
4
+
5
+ See [ThirdPartyNotices.txt](./ThirdPartyNotices.txt) for the full notices from bundled VS Code grammars, extensions, and assets.
6
+
7
+ ---
8
+
9
+ ## MIT License
10
+
11
+ The following packages are licensed under the **MIT License**:
12
+
13
+ | Package | Author/Copyright |
14
+ | -------------------------------- | ----------------------------------- |
15
+ | code-server | Coder Technologies Inc. |
16
+ | @microsoft/1ds-core-js | Microsoft Application Insights Team |
17
+ | @microsoft/1ds-post-js | Microsoft Application Insights Team |
18
+ | @parcel/watcher | Parcel |
19
+ | @vscode/deviceid | Microsoft Corporation |
20
+ | @vscode/iconv-lite-umd | Microsoft |
21
+ | @vscode/native-watchdog | Microsoft Corporation |
22
+ | @vscode/proxy-agent | Microsoft |
23
+ | @vscode/ripgrep | Rob Lourens |
24
+ | @vscode/spdlog | Microsoft |
25
+ | @vscode/tree-sitter-wasm | Visual Studio Code Team |
26
+ | @vscode/vscode-languagedetection | Tyler Leonhardt |
27
+ | @vscode/windows-process-tree | Microsoft Corporation |
28
+ | @vscode/windows-registry | Microsoft Corporation |
29
+ | @xterm/addon-clipboard | The xterm.js authors |
30
+ | @xterm/addon-image | The xterm.js authors |
31
+ | @xterm/addon-ligatures | The xterm.js authors |
32
+ | @xterm/addon-progress | The xterm.js authors |
33
+ | @xterm/addon-search | The xterm.js authors |
34
+ | @xterm/addon-serialize | The xterm.js authors |
35
+ | @xterm/addon-unicode11 | The xterm.js authors |
36
+ | @xterm/addon-webgl | The xterm.js authors |
37
+ | @xterm/headless | The xterm.js authors |
38
+ | @xterm/xterm | The xterm.js authors |
39
+ | cookie | Roman Shtylman |
40
+ | http-proxy-agent | Nathan Rajlich |
41
+ | https-proxy-agent | Nathan Rajlich |
42
+ | katex | KaTeX Contributors |
43
+ | minimist | James Halliday |
44
+ | node-pty | Microsoft Corporation |
45
+ | tas-client | Microsoft |
46
+ | vscode-oniguruma | Microsoft Corporation |
47
+ | vscode-regexpp | Toru Nagashima |
48
+ | vscode-textmate | Microsoft Corporation |
49
+ | ws | Einar Otto Stangvik |
50
+ | yauzl | Josh Wolfe |
51
+ | yazl | Josh Wolfe |
52
+
53
+ ```
54
+ MIT License
55
+
56
+ Permission is hereby granted, free of charge, to any person obtaining a copy
57
+ of this software and associated documentation files (the "Software"), to deal
58
+ in the Software without restriction, including without limitation the rights
59
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
60
+ copies of the Software, and to permit persons to whom the Software is
61
+ furnished to do so, subject to the following conditions:
62
+
63
+ The above copyright notice and this permission notice shall be included in all
64
+ copies or substantial portions of the Software.
65
+
66
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
67
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
68
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
69
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
70
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
71
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
72
+ SOFTWARE.
73
+ ```
74
+
75
+ ---
76
+
77
+ ## Apache License 2.0
78
+
79
+ The following packages are licensed under the **Apache License 2.0**:
80
+
81
+ | Package | Author/Copyright |
82
+ | ----------------------------- | ----------------------- |
83
+ | @anthropic-ai/sandbox-runtime | Anthropic PBC |
84
+ | kerberos | The MongoDB NodeJS Team |
85
+ | typescript | Microsoft Corp. |
86
+
87
+ ```
88
+ Licensed under the Apache License, Version 2.0 (the "License");
89
+ you may not use this file except in compliance with the License.
90
+ You may obtain a copy of the License at
91
+
92
+ http://www.apache.org/licenses/LICENSE-2.0
93
+
94
+ Unless required by applicable law or agreed to in writing, software
95
+ distributed under the License is distributed on an "AS IS" BASIS,
96
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
97
+ See the License for the specific language governing permissions and
98
+ limitations under the License.
99
+ ```
100
+
101
+ ---
102
+
103
+ ## LGPL-2.1+
104
+
105
+ | Package | Author/Copyright |
106
+ | --------- | ---------------- |
107
+ | jschardet | António Afonso |
108
+
109
+ Licensed under the GNU Lesser General Public License v2.1 or later.
110
+ See https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html
package/README.md ADDED
File without changes
package/code.mjs ADDED
@@ -0,0 +1,48 @@
1
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
2
+ import { join, resolve } from "node:path";
3
+ import { tmpdir } from "node:os";
4
+ import { fileURLToPath } from "node:url";
5
+
6
+ // Auto-updated by scripts/pack.ts
7
+ const codeArchiveHash = "2cc1d5a1fed987e5";
8
+
9
+ const archivePath = fileURLToPath(new URL("./code.tar.zst", import.meta.url));
10
+
11
+ const verbose = !!process.env.DEBUG;
12
+
13
+ const gray = (str) => `\x1b[90m${str}\x1b[0m`;
14
+ const log = (...args) => console.log(gray(`[code-server] ${args.join(" ")}`));
15
+ const vlog = verbose ? log : () => {};
16
+
17
+ export async function loadCode() {
18
+ if (process.env.CODE_MODULES_DIR) {
19
+ vlog(`Using CODE_MODULES_DIR: ${process.env.CODE_MODULES_DIR}`);
20
+ return { modulesDir: resolve(process.env.CODE_MODULES_DIR) };
21
+ }
22
+
23
+ const cacheDir = join(tmpdir(), "code-server", codeArchiveHash);
24
+ const modulesDir = join(cacheDir, "node_modules");
25
+ const markerPath = join(cacheDir, ".complete");
26
+
27
+ if (existsSync(markerPath) && readFileSync(markerPath, "utf8") === codeArchiveHash) {
28
+ vlog(`Cache hit: ${cacheDir}`);
29
+ return { modulesDir };
30
+ }
31
+
32
+ if (!existsSync(archivePath)) {
33
+ throw new Error(`Archive not found: ${archivePath}`);
34
+ }
35
+
36
+ mkdirSync(cacheDir, { recursive: true });
37
+
38
+ vlog(`Extracting... (${cacheDir})`);
39
+ const start = performance.now();
40
+
41
+ const { extractTarZst } = await import("./tar.mjs");
42
+ await extractTarZst(archivePath, cacheDir);
43
+
44
+ writeFileSync(markerPath, codeArchiveHash);
45
+ vlog(`Extracted in ${(performance.now() - start).toFixed(0)}ms`);
46
+
47
+ return { modulesDir };
48
+ }
package/code.tar.zst ADDED
Binary file
@@ -0,0 +1,218 @@
1
+ import { randomBytes, randomUUID } from "node:crypto";
2
+ import { createReadStream, readFileSync, readdirSync, unlinkSync } from "node:fs";
3
+ import { createServer } from "node:http";
4
+ import { homedir } from "node:os";
5
+ import { extname, join, normalize, sep } from "node:path";
6
+ import { stat } from "node:fs/promises";
7
+ import { loadCode } from "#code";
8
+ const STATIC_MIME = {
9
+ ".js": "text/javascript",
10
+ ".mjs": "text/javascript",
11
+ ".css": "text/css",
12
+ ".html": "text/html",
13
+ ".json": "application/json",
14
+ ".svg": "image/svg+xml",
15
+ ".png": "image/png",
16
+ ".jpg": "image/jpeg",
17
+ ".jpeg": "image/jpeg",
18
+ ".gif": "image/gif",
19
+ ".ico": "image/x-icon",
20
+ ".webp": "image/webp",
21
+ ".wasm": "application/wasm",
22
+ ".woff": "font/woff",
23
+ ".woff2": "font/woff2",
24
+ ".map": "application/json",
25
+ ".txt": "text/plain"
26
+ };
27
+ async function serveStatic(res, root, relPath) {
28
+ const abs = normalize(join(root, decodeURIComponent(relPath)));
29
+ if (abs !== root && !abs.startsWith(root + sep)) {
30
+ res.writeHead(400).end("Bad request.");
31
+ return true;
32
+ }
33
+ try {
34
+ const st = await stat(abs);
35
+ if (!st.isFile()) return false;
36
+ const headers = {
37
+ "Content-Type": STATIC_MIME[extname(abs).toLowerCase()] ?? "application/octet-stream",
38
+ "Content-Length": st.size,
39
+ "Cache-Control": "public, max-age=31536000, immutable"
40
+ };
41
+ if (abs.endsWith("/serviceWorker.js")) headers["Service-Worker-Allowed"] = "/";
42
+ res.writeHead(200, headers);
43
+ createReadStream(abs).pipe(res);
44
+ return true;
45
+ } catch {
46
+ return false;
47
+ }
48
+ }
49
+ const MANIFEST_BODY = JSON.stringify({
50
+ name: "code-server",
51
+ short_name: "code-server",
52
+ start_url: ".",
53
+ display: "fullscreen",
54
+ display_override: ["window-controls-overlay"],
55
+ description: "Run Code on a remote server.",
56
+ icons: [192, 512].flatMap((size) => [{
57
+ src: `./_static/src/browser/media/pwa-icon-${size}.png`,
58
+ type: "image/png",
59
+ sizes: `${size}x${size}`,
60
+ purpose: "any"
61
+ }, {
62
+ src: `./_static/src/browser/media/pwa-icon-maskable-${size}.png`,
63
+ type: "image/png",
64
+ sizes: `${size}x${size}`,
65
+ purpose: "maskable"
66
+ }])
67
+ });
68
+ const ROBOTS_TXT = "User-agent: *\nDisallow: /\n";
69
+ async function createCodeServer(opts = {}) {
70
+ const withoutToken = opts.vscode?.["without-connection-token"] === true;
71
+ const connectionToken = withoutToken ? "" : opts.connectionToken ?? randomUUID();
72
+ const defaultFolder = opts.defaultFolder ?? process.cwd();
73
+ const mintKey = randomBytes(32);
74
+ process.env.CODE_SERVER_PARENT_PID ??= String(process.pid);
75
+ cleanupStaleLocks(opts.vscode?.["user-data-dir"] ?? join(homedir(), ".vscode-server-oss", "data"));
76
+ const { modulesDir } = await loadCode();
77
+ const vsRootPath = join(modulesDir, "code-server", "lib", "vscode");
78
+ const _log = console.log;
79
+ console.log = (...args) => {
80
+ if (typeof args[0] === "string" && args[0].includes("[reconnection-grace-time]")) return;
81
+ if (args.length === 2 && typeof args[1] === "string" && !args[1].trim()) return;
82
+ _log(...args);
83
+ };
84
+ const vscodeServer = await (await (await import(join(vsRootPath, "out/server-main.js"))).loadCodeWithNls()).createServer(null, {
85
+ "default-folder": defaultFolder,
86
+ ...withoutToken ? {} : { "connection-token": connectionToken },
87
+ "reconnection-grace-time": "10800",
88
+ "disable-getting-started-override": true,
89
+ ...opts.vscode
90
+ });
91
+ console.log = _log;
92
+ return {
93
+ connectionToken,
94
+ handleRequest(req, res) {
95
+ const method = req.method ?? "GET";
96
+ const url = (req.url ?? "/").split("?")[0];
97
+ if (url === "/manifest.json") {
98
+ res.writeHead(200, {
99
+ "Content-Type": "application/manifest+json",
100
+ "Cache-Control": "no-cache"
101
+ });
102
+ res.end(MANIFEST_BODY);
103
+ return;
104
+ }
105
+ if (url === "/healthz") {
106
+ sendJson(res, 200, {
107
+ status: "alive",
108
+ lastHeartbeat: Date.now()
109
+ });
110
+ return;
111
+ }
112
+ if (url === "/update/check") {
113
+ const codeServerVersion = JSON.parse(readFileSync(join(modulesDir, "code-server", "package.json"), "utf8")).version;
114
+ sendJson(res, 200, {
115
+ checked: Date.now(),
116
+ latest: codeServerVersion,
117
+ current: codeServerVersion,
118
+ isLatest: true
119
+ });
120
+ return;
121
+ }
122
+ if (url === "/robots.txt") {
123
+ res.writeHead(200, {
124
+ "Content-Type": "text/plain; charset=utf-8",
125
+ "Content-Length": Buffer.byteLength(ROBOTS_TXT)
126
+ });
127
+ res.end(ROBOTS_TXT);
128
+ return;
129
+ }
130
+ if (url === "/mint-key" && method === "POST") {
131
+ res.writeHead(200, {
132
+ "Content-Type": "application/octet-stream",
133
+ "Content-Length": mintKey.length
134
+ });
135
+ res.end(mintKey);
136
+ return;
137
+ }
138
+ if (url === "/login" || url === "/logout") {
139
+ res.writeHead(302, { Location: "/" });
140
+ res.end();
141
+ return;
142
+ }
143
+ if (url.startsWith("/_static/")) {
144
+ serveStatic(res, join(modulesDir, "code-server"), url.slice(9)).then((served) => {
145
+ if (!served) vscodeServer.handleRequest(req, res);
146
+ });
147
+ return;
148
+ }
149
+ vscodeServer.handleRequest(req, res);
150
+ },
151
+ handleUpgrade(req, socket) {
152
+ vscodeServer.handleUpgrade(req, socket);
153
+ socket.resume();
154
+ },
155
+ async dispose() {
156
+ vscodeServer.dispose();
157
+ }
158
+ };
159
+ }
160
+ async function startCodeServer(opts = {}) {
161
+ const port = opts.port ?? (Number(process.env.PORT) || 8080);
162
+ const handler = await createCodeServer(opts);
163
+ const server = createServer((req, res) => {
164
+ handler.handleRequest(req, res);
165
+ });
166
+ server.on("upgrade", (req, socket) => {
167
+ handler.handleUpgrade(req, socket);
168
+ });
169
+ const listen = (p) => new Promise((resolve, reject) => {
170
+ server.once("error", reject);
171
+ const cb = () => {
172
+ server.removeListener("error", reject);
173
+ resolve();
174
+ };
175
+ if (opts.host) server.listen(p, opts.host, cb);
176
+ else server.listen(p, cb);
177
+ });
178
+ try {
179
+ await listen(port);
180
+ } catch (err) {
181
+ if (err?.code === "EADDRINUSE") await listen(0);
182
+ else throw err;
183
+ }
184
+ const actualPort = server.address().port;
185
+ return {
186
+ server,
187
+ port: actualPort,
188
+ url: handler.connectionToken ? `http://localhost:${actualPort}/?tkn=${handler.connectionToken}` : `http://localhost:${actualPort}/`,
189
+ connectionToken: handler.connectionToken,
190
+ async close() {
191
+ await handler.dispose();
192
+ server.closeAllConnections();
193
+ await new Promise((resolve, reject) => {
194
+ server.close((err) => err ? reject(err) : resolve());
195
+ });
196
+ }
197
+ };
198
+ }
199
+ function cleanupStaleLocks(userDataDir) {
200
+ const storageDir = join(userDataDir, "User", "workspaceStorage");
201
+ try {
202
+ for (const entry of readdirSync(storageDir)) {
203
+ const lockPath = join(storageDir, entry, "vscode.lock");
204
+ try {
205
+ unlinkSync(lockPath);
206
+ } catch {}
207
+ }
208
+ } catch {}
209
+ }
210
+ function sendJson(res, status, body) {
211
+ const payload = JSON.stringify(body);
212
+ res.writeHead(status, {
213
+ "Content-Type": "application/json; charset=utf-8",
214
+ "Content-Length": Buffer.byteLength(payload)
215
+ });
216
+ res.end(payload);
217
+ }
218
+ export { startCodeServer as n, createCodeServer as t };
package/dist/cli.d.mts ADDED
@@ -0,0 +1 @@
1
+ export { };
package/dist/cli.mjs ADDED
@@ -0,0 +1,242 @@
1
+ #!/usr/bin/env node
2
+ import { n as startCodeServer } from "./_chunks/server.mjs";
3
+ import { parseArgs } from "node:util";
4
+ const { values, positionals } = parseArgs({
5
+ allowPositionals: true,
6
+ options: {
7
+ port: {
8
+ type: "string",
9
+ short: "p"
10
+ },
11
+ host: {
12
+ type: "string",
13
+ short: "H"
14
+ },
15
+ "server-base-path": { type: "string" },
16
+ "socket-path": { type: "string" },
17
+ "print-startup-performance": { type: "boolean" },
18
+ "connection-token": { type: "string" },
19
+ "connection-token-file": { type: "string" },
20
+ "without-connection-token": { type: "boolean" },
21
+ auth: { type: "string" },
22
+ "github-auth": { type: "string" },
23
+ "default-folder": { type: "string" },
24
+ "default-workspace": { type: "string" },
25
+ locale: { type: "string" },
26
+ "server-data-dir": { type: "string" },
27
+ "user-data-dir": { type: "string" },
28
+ "extensions-dir": { type: "string" },
29
+ "extensions-download-dir": { type: "string" },
30
+ "builtin-extensions-dir": { type: "string" },
31
+ "agent-plugins-dir": { type: "string" },
32
+ log: { type: "string" },
33
+ "logs-path": { type: "string" },
34
+ "disable-websocket-compression": { type: "boolean" },
35
+ "use-host-proxy": { type: "boolean" },
36
+ "disable-file-downloads": { type: "boolean" },
37
+ "disable-file-uploads": { type: "boolean" },
38
+ "file-watcher-polling": { type: "string" },
39
+ "telemetry-level": { type: "string" },
40
+ "disable-telemetry": { type: "boolean" },
41
+ "disable-update-check": { type: "boolean" },
42
+ "disable-experiments": { type: "boolean" },
43
+ "enable-sync": { type: "boolean" },
44
+ "enable-proposed-api": {
45
+ type: "string",
46
+ multiple: true
47
+ },
48
+ "disable-workspace-trust": { type: "boolean" },
49
+ "disable-getting-started-override": { type: "boolean" },
50
+ "enable-remote-auto-shutdown": { type: "boolean" },
51
+ "remote-auto-shutdown-without-delay": { type: "boolean" },
52
+ "without-browser-env-var": { type: "boolean" },
53
+ "reconnection-grace-time": { type: "string" },
54
+ "agent-host-path": { type: "string" },
55
+ "agent-host-port": { type: "string" },
56
+ "inspect-ptyhost": { type: "string" },
57
+ "inspect-brk-ptyhost": { type: "string" },
58
+ "inspect-agenthost": { type: "string" },
59
+ "inspect-brk-agenthost": { type: "string" },
60
+ "enable-smoke-test-driver": { type: "boolean" },
61
+ "crash-reporter-directory": { type: "string" },
62
+ "crash-reporter-id": { type: "string" },
63
+ "force-disable-user-env": { type: "boolean" },
64
+ "force-user-env": { type: "boolean" },
65
+ open: {
66
+ type: "boolean",
67
+ short: "o"
68
+ },
69
+ help: {
70
+ type: "boolean",
71
+ short: "h"
72
+ }
73
+ },
74
+ strict: true
75
+ });
76
+ if (values.help) {
77
+ console.log(`
78
+ Usage: code-server [options]
79
+
80
+ Server:
81
+ -p, --port <port> Port to listen on (default: $PORT or 8080)
82
+ -H, --host <host> Host/interface to bind
83
+ --server-base-path <path> Base path for the web UI (default: /)
84
+ --socket-path <path> Path to a socket file to listen on
85
+ --print-startup-performance Print startup timing to stdout
86
+
87
+ Auth:
88
+ --connection-token <token> Connection token for auth (auto-generated)
89
+ --connection-token-file <path> Path to file containing connection token
90
+ --without-connection-token Disable connection token auth
91
+ --auth <type> Auth type
92
+ --github-auth <token> GitHub auth token
93
+
94
+ Defaults:
95
+ --default-folder <path> Default workspace folder
96
+ --default-workspace <path> Default workspace file
97
+ --locale <locale> The locale to use (e.g. en-US)
98
+
99
+ Data:
100
+ --server-data-dir <path> Server data directory
101
+ --user-data-dir <path> User data directory
102
+ --extensions-dir <path> Extensions directory
103
+ --extensions-download-dir <path> Extensions download directory
104
+ --builtin-extensions-dir <path> Built-in extensions directory
105
+ --agent-plugins-dir <path> Agent plugins directory
106
+
107
+ Logging:
108
+ --log <level> Log level (off, critical, error, warn, info, debug, trace)
109
+ --logs-path <path> Logs output directory
110
+
111
+ Network:
112
+ --disable-websocket-compression Disable WebSocket compression
113
+ --use-host-proxy Enable host proxy
114
+
115
+ Files:
116
+ --disable-file-downloads Disable file downloads
117
+ --disable-file-uploads Disable file uploads
118
+ --file-watcher-polling <ms> File watcher polling interval
119
+
120
+ Telemetry:
121
+ --telemetry-level <level> Telemetry level (off, crash, error, all)
122
+ --disable-telemetry Disable telemetry
123
+ --disable-update-check Disable update check
124
+ --disable-experiments Disable experiments
125
+
126
+ Features:
127
+ --enable-sync Enable settings sync
128
+ --enable-proposed-api <ext-id> Enable proposed API for extension (repeatable)
129
+ --disable-workspace-trust Disable workspace trust
130
+ --disable-getting-started-override Disable getting started override
131
+
132
+ Remote:
133
+ --enable-remote-auto-shutdown Enable remote auto shutdown
134
+ --remote-auto-shutdown-without-delay Auto shutdown without delay
135
+ --without-browser-env-var Disable browser env var
136
+ --reconnection-grace-time <sec> Reconnection grace time (default: 10800)
137
+
138
+ Agent Host:
139
+ --agent-host-path <path> Agent host WebSocket socket path
140
+ --agent-host-port <port> Agent host WebSocket port
141
+
142
+ Shell:
143
+ --force-disable-user-env Force disable user shell env resolution
144
+ --force-user-env Force user shell env resolution
145
+
146
+ Debugging:
147
+ --inspect-ptyhost <port> Inspect pty host
148
+ --inspect-brk-ptyhost <port> Inspect pty host (break on start)
149
+ --inspect-agenthost <port> Inspect agent host
150
+ --inspect-brk-agenthost <port> Inspect agent host (break on start)
151
+ --enable-smoke-test-driver Enable smoke test driver
152
+ --crash-reporter-directory <dir> Crash reporter directory
153
+ --crash-reporter-id <id> Crash reporter ID
154
+
155
+ -o, --open Open in browser on startup
156
+ -h, --help Show this help message
157
+ `);
158
+ process.exit(0);
159
+ }
160
+ const vscode = {};
161
+ for (const key of [
162
+ "server-base-path",
163
+ "socket-path",
164
+ "print-startup-performance",
165
+ "connection-token-file",
166
+ "without-connection-token",
167
+ "auth",
168
+ "github-auth",
169
+ "default-workspace",
170
+ "locale",
171
+ "server-data-dir",
172
+ "user-data-dir",
173
+ "extensions-dir",
174
+ "extensions-download-dir",
175
+ "builtin-extensions-dir",
176
+ "agent-plugins-dir",
177
+ "log",
178
+ "file-watcher-polling",
179
+ "disable-websocket-compression",
180
+ "use-host-proxy",
181
+ "disable-file-downloads",
182
+ "disable-file-uploads",
183
+ "telemetry-level",
184
+ "disable-telemetry",
185
+ "disable-update-check",
186
+ "disable-experiments",
187
+ "enable-sync",
188
+ "enable-proposed-api",
189
+ "disable-workspace-trust",
190
+ "disable-getting-started-override",
191
+ "enable-remote-auto-shutdown",
192
+ "remote-auto-shutdown-without-delay",
193
+ "without-browser-env-var",
194
+ "reconnection-grace-time",
195
+ "agent-host-path",
196
+ "agent-host-port",
197
+ "inspect-ptyhost",
198
+ "inspect-brk-ptyhost",
199
+ "inspect-agenthost",
200
+ "inspect-brk-agenthost",
201
+ "enable-smoke-test-driver",
202
+ "crash-reporter-directory",
203
+ "crash-reporter-id",
204
+ "force-disable-user-env",
205
+ "force-user-env"
206
+ ]) if (values[key] !== void 0) vscode[key] = values[key];
207
+ if (values["logs-path"]) vscode.logsPath = values["logs-path"];
208
+ const dir = positionals[0];
209
+ const autoPort0 = !values.port && values.open && !process.env.PORT;
210
+ if (autoPort0 || dir) vscode["disable-workspace-trust"] = true;
211
+ const handle = await startCodeServer({
212
+ port: values.port ? Number(values.port) : autoPort0 ? 0 : void 0,
213
+ host: values.host,
214
+ defaultFolder: dir || values["default-folder"],
215
+ connectionToken: values["connection-token"],
216
+ vscode
217
+ });
218
+ const c = {
219
+ cyan: "\x1B[36m",
220
+ bold: "\x1B[1m",
221
+ dim: "\x1B[2m",
222
+ reset: "\x1B[0m"
223
+ };
224
+ const mem = `${(process.memoryUsage.rss() / 1024 / 1024).toFixed(0)} MB`;
225
+ console.log(`\n ${c.bold}${c.cyan}➜${c.reset} ${c.bold}Ready${c.reset} ${c.dim}at${c.reset} ${c.cyan}${handle.url}${c.reset}\n ${c.bold}${c.cyan}➜${c.reset} ${c.bold}Memory${c.reset} ${c.dim}${mem}${c.reset}\n`);
226
+ if (values.open) {
227
+ const { exec } = await import("node:child_process");
228
+ const url = handle.url;
229
+ const platform = process.platform;
230
+ if (platform === "darwin") exec(`open -na "Google Chrome" --args --app="${url}" || open -na "Chromium" --args --app="${url}" || open "${url}"`);
231
+ else if (platform === "win32") exec(`start chrome --app="${url}" || start msedge --app="${url}" || start "" "${url}"`);
232
+ else exec(`google-chrome-stable --app="${url}" 2>/dev/null || google-chrome --app="${url}" 2>/dev/null || chromium --app="${url}" 2>/dev/null || xdg-open "${url}"`);
233
+ }
234
+ let shuttingDown = false;
235
+ const shutdown = () => {
236
+ if (shuttingDown) return;
237
+ shuttingDown = true;
238
+ handle.close().finally(() => process.exit(0));
239
+ };
240
+ process.on("SIGINT", shutdown);
241
+ process.on("SIGTERM", shutdown);
242
+ export {};
@@ -0,0 +1,112 @@
1
+ import { IncomingMessage, Server, ServerResponse } from "node:http";
2
+ import { Duplex } from "node:stream";
3
+ /**
4
+ * Options for `createServer()` from VS Code server
5
+ * (`code-server/lib/vscode/out/server-main.js`).
6
+ *
7
+ * Scope: only options that are actually consumed when the server is embedded
8
+ * via `createServer(null, opts)` — i.e. reached through `zF`/`jF`/`uM`/`AF`
9
+ * directly, or read from `environmentService.args` during request handling,
10
+ * workbench construction, or extension host setup.
11
+ *
12
+ * Options that only fire through the `spawnCli`/`YH` argv-parsing entry
13
+ * (license prompt, extension install/list/uninstall, host/port listen,
14
+ * `--folder-uri`, `--locate-shell-integration-path`, etc.) are intentionally
15
+ * omitted — passing them to `createServer()` has no effect.
16
+ */
17
+ interface VSCodeServerOptions {
18
+ /** The path under which the web UI and the code server is provided. Defaults to `'/'`. */
19
+ "server-base-path"?: string;
20
+ /** The path to a socket file for the server to listen to. Also toggles Windows management-connection socket transfer. */
21
+ "socket-path"?: string;
22
+ /** Print startup timing breakdown to stdout once the server is ready. */
23
+ "print-startup-performance"?: boolean;
24
+ /** A secret that must be included with all requests. */
25
+ "connection-token"?: string;
26
+ /** Path to a file that contains the connection token. */
27
+ "connection-token-file"?: string;
28
+ /** Run without a connection token. Only use this if the connection is secured by other means. */
29
+ "without-connection-token"?: boolean;
30
+ auth?: string;
31
+ "github-auth"?: string;
32
+ /** Specifies the directory that server data is kept in. */
33
+ "server-data-dir"?: string;
34
+ "user-data-dir"?: string;
35
+ "extensions-dir"?: string;
36
+ "extensions-download-dir"?: string;
37
+ "builtin-extensions-dir"?: string;
38
+ /** The path to the directory where agent plugins are located. */
39
+ "agent-plugins-dir"?: string;
40
+ /** The workspace folder to open when no input is specified in the browser URL. A relative or absolute path resolved against the current working directory. */
41
+ "default-folder"?: string;
42
+ /** The workspace to open when no input is specified in the browser URL. A relative or absolute path resolved against the current working directory. */
43
+ "default-workspace"?: string;
44
+ locale?: string;
45
+ log?: string;
46
+ logsPath?: string;
47
+ "disable-websocket-compression"?: boolean;
48
+ "use-host-proxy"?: boolean;
49
+ "disable-file-downloads"?: boolean;
50
+ "disable-file-uploads"?: boolean;
51
+ "file-watcher-polling"?: string;
52
+ /** Sets the initial telemetry level. Valid levels are: `'off'`, `'crash'`, `'error'` and `'all'`. */
53
+ "telemetry-level"?: string;
54
+ "disable-telemetry"?: boolean;
55
+ "disable-update-check"?: boolean;
56
+ "disable-experiments"?: boolean;
57
+ "enable-sync"?: boolean;
58
+ "enable-proposed-api"?: string[];
59
+ "disable-workspace-trust"?: boolean;
60
+ "disable-getting-started-override"?: boolean;
61
+ "link-protection-trusted-domains"?: string[];
62
+ "enable-remote-auto-shutdown"?: boolean;
63
+ "remote-auto-shutdown-without-delay"?: boolean;
64
+ "without-browser-env-var"?: boolean;
65
+ /** Override the reconnection grace time window in seconds. Defaults to `10800` (3 hours). */
66
+ "reconnection-grace-time"?: string;
67
+ /** The path to a socket file for the agent host WebSocket server to listen on. */
68
+ "agent-host-path"?: string;
69
+ /** The port the agent host WebSocket server should listen on. */
70
+ "agent-host-port"?: string;
71
+ "inspect-ptyhost"?: string;
72
+ "inspect-brk-ptyhost"?: string;
73
+ "inspect-agenthost"?: string;
74
+ "inspect-brk-agenthost"?: string;
75
+ "enable-smoke-test-driver"?: boolean;
76
+ "crash-reporter-directory"?: string;
77
+ "crash-reporter-id"?: string;
78
+ "force-disable-user-env"?: boolean;
79
+ "force-user-env"?: boolean;
80
+ }
81
+ interface CreateCodeServerOptions {
82
+ /** Workspace folder opened when no input is given in the URL. */
83
+ defaultFolder?: string;
84
+ /** Connection token (shared auth secret). Auto-generated if omitted. */
85
+ connectionToken?: string;
86
+ /** Extra options forwarded to VS Code's `createServer()`. */
87
+ vscode?: VSCodeServerOptions;
88
+ }
89
+ interface StartCodeServerOptions extends CreateCodeServerOptions {
90
+ /** TCP port to listen on. Defaults to `$PORT` or `8080`. */
91
+ port?: number;
92
+ /** Host/interface to bind. Defaults to Node's default (all interfaces). */
93
+ host?: string;
94
+ }
95
+ interface CodeServerHandler {
96
+ /** Node-style HTTP request handler (middleware). */
97
+ handleRequest(req: IncomingMessage, res: ServerResponse): void;
98
+ /** Handle WebSocket upgrade. */
99
+ handleUpgrade(req: IncomingMessage, socket: Duplex): void;
100
+ connectionToken: string;
101
+ dispose(): Promise<void>;
102
+ }
103
+ interface CodeServerHandle {
104
+ server: Server;
105
+ port: number;
106
+ url: string;
107
+ connectionToken: string;
108
+ close(): Promise<void>;
109
+ }
110
+ declare function createCodeServer(opts?: CreateCodeServerOptions): Promise<CodeServerHandler>;
111
+ declare function startCodeServer(opts?: StartCodeServerOptions): Promise<CodeServerHandle>;
112
+ export { type CodeServerHandle, type CodeServerHandler, type CreateCodeServerOptions, type StartCodeServerOptions, createCodeServer, startCodeServer };
package/dist/index.mjs ADDED
@@ -0,0 +1,2 @@
1
+ import { n as startCodeServer, t as createCodeServer } from "./_chunks/server.mjs";
2
+ export { createCodeServer, startCodeServer };
package/package.json ADDED
@@ -0,0 +1,69 @@
1
+ {
2
+ "name": "coderaft",
3
+ "version": "0.0.4",
4
+ "repository": "pithings/coderaft",
5
+ "bin": {
6
+ "coderaft": "./dist/cli.mjs"
7
+ },
8
+ "files": [
9
+ "dist",
10
+ "LICENSE.md",
11
+ "ThirdPartyNotices.txt",
12
+ "tar.mjs",
13
+ "code.mjs",
14
+ "code.tar.zst"
15
+ ],
16
+ "type": "module",
17
+ "imports": {
18
+ "#code": "./code.mjs"
19
+ },
20
+ "scripts": {
21
+ "build": "obuild"
22
+ },
23
+ "devDependencies": {
24
+ "@anthropic-ai/sandbox-runtime": "0.0.42",
25
+ "@github/copilot": "^1.0.11",
26
+ "@github/copilot-sdk": "^0.2.0",
27
+ "@microsoft/1ds-core-js": "^3.2.13",
28
+ "@microsoft/1ds-post-js": "^3.2.13",
29
+ "@parcel/watcher": "^2.5.6",
30
+ "@vscode/deviceid": "^0.1.1",
31
+ "@vscode/fs-copyfile": "^2.0.0",
32
+ "@vscode/iconv-lite-umd": "0.7.1",
33
+ "@vscode/native-watchdog": "^1.4.6",
34
+ "@vscode/proxy-agent": "^0.40.0",
35
+ "@vscode/ripgrep": "^1.17.1",
36
+ "@vscode/spdlog": "^0.15.8",
37
+ "@vscode/tree-sitter-wasm": "^0.3.0",
38
+ "@vscode/vscode-languagedetection": "1.0.23",
39
+ "@vscode/windows-process-tree": "^0.6.0",
40
+ "@vscode/windows-registry": "^1.2.0",
41
+ "@xterm/addon-clipboard": "^0.3.0-beta.191",
42
+ "@xterm/addon-image": "^0.10.0-beta.191",
43
+ "@xterm/addon-ligatures": "^0.11.0-beta.191",
44
+ "@xterm/addon-progress": "^0.3.0-beta.191",
45
+ "@xterm/addon-search": "^0.17.0-beta.191",
46
+ "@xterm/addon-serialize": "^0.15.0-beta.191",
47
+ "@xterm/addon-unicode11": "^0.10.0-beta.191",
48
+ "@xterm/addon-webgl": "^0.20.0-beta.190",
49
+ "@xterm/headless": "^6.1.0-beta.191",
50
+ "@xterm/xterm": "^6.1.0-beta.191",
51
+ "code-server": "^4.114.0",
52
+ "cookie": "^0.7.0",
53
+ "http-proxy-agent": "^7.0.0",
54
+ "https-proxy-agent": "^7.0.2",
55
+ "jschardet": "3.1.4",
56
+ "katex": "^0.16.22",
57
+ "kerberos": "2.1.1",
58
+ "minimist": "^1.2.8",
59
+ "node-pty": "^1.2.0-beta.12",
60
+ "tas-client": "0.3.1",
61
+ "typescript": "^6.0.2",
62
+ "vscode-oniguruma": "1.7.0",
63
+ "vscode-regexpp": "^3.1.0",
64
+ "vscode-textmate": "^9.3.2",
65
+ "ws": "^8.19.0",
66
+ "yauzl": "^3.0.0",
67
+ "yazl": "^2.4.3"
68
+ }
69
+ }
package/tar.mjs ADDED
@@ -0,0 +1,169 @@
1
+ // Streaming tar.zst extractor with pool-buffer strategy.
2
+ // Decompresses with Node's built-in zstd (libzstd) and parses tar entries
3
+ // incrementally as chunks arrive — no need to buffer the full archive.
4
+ // A single pre-allocated buffer (pool) grows to fit the largest tar entry,
5
+ // then compacts after each batch of entries, keeping memory ~3x lower than
6
+ // a full-buffer approach while matching or beating system tar in speed.
7
+ // Supports USTAR, GNU long names (type "L"), pax headers, and symlinks.
8
+
9
+ import { createReadStream, mkdirSync, openSync, writeSync, closeSync, symlinkSync } from "node:fs";
10
+ import { dirname, join } from "node:path";
11
+ import { createZstdDecompress } from "node:zlib";
12
+
13
+ const BLOCK = 512;
14
+ const HIGH_WATER = 4 * 1024 * 1024; // 4MB initial buffer
15
+
16
+ /**
17
+ * Extract a .tar.zst archive to a directory (streaming, low memory).
18
+ * @param {string} archivePath - path to .tar.zst file
19
+ * @param {string} destDir - destination directory
20
+ * @returns {Promise<void>}
21
+ */
22
+ export async function extractTarZst(archivePath, destDir) {
23
+ const stream = createReadStream(archivePath).pipe(createZstdDecompress());
24
+
25
+ // Pre-allocated buffer with read/write cursors to avoid repeated concat
26
+ let pool = Buffer.allocUnsafe(HIGH_WATER);
27
+ let start = 0; // read cursor
28
+ let end = 0; // write cursor
29
+
30
+ let gnuLongName = "";
31
+ let paxPath = "";
32
+ const createdDirs = new Set();
33
+
34
+ function ensureDir(dir) {
35
+ if (!createdDirs.has(dir)) {
36
+ mkdirSync(dir, { recursive: true });
37
+ createdDirs.add(dir);
38
+ }
39
+ }
40
+
41
+ function available() {
42
+ return end - start;
43
+ }
44
+
45
+ function compact() {
46
+ if (start === 0) return;
47
+ if (start === end) {
48
+ start = end = 0;
49
+ } else {
50
+ pool.copy(pool, 0, start, end);
51
+ end -= start;
52
+ start = 0;
53
+ }
54
+ }
55
+
56
+ function appendChunk(chunk) {
57
+ const needed = end + chunk.length;
58
+ if (needed > pool.length) {
59
+ // Grow: max of double or exactly what's needed
60
+ const newSize = Math.max(pool.length * 2, needed - start);
61
+ const newPool = Buffer.allocUnsafe(newSize);
62
+ pool.copy(newPool, 0, start, end);
63
+ end -= start;
64
+ start = 0;
65
+ pool = newPool;
66
+ } else if (end + chunk.length > pool.length) {
67
+ compact();
68
+ }
69
+ chunk.copy(pool, end);
70
+ end += chunk.length;
71
+ }
72
+
73
+ function processEntries() {
74
+ while (available() >= BLOCK) {
75
+ // Null block
76
+ if (pool[start] === 0 && pool[start + 1] === 0) {
77
+ start += BLOCK;
78
+ continue;
79
+ }
80
+
81
+ const size = parseOctal(pool, start + 124, 12);
82
+ const typeflag = String.fromCharCode(pool[start + 156]);
83
+ const dataBlocks = Math.ceil(size / BLOCK) * BLOCK;
84
+ const totalNeeded = BLOCK + dataBlocks;
85
+
86
+ if (available() < totalNeeded) break;
87
+
88
+ const headerStart = start;
89
+ const dataStart = start + BLOCK;
90
+
91
+ if (typeflag === "L") {
92
+ // eslint-disable-next-line no-control-regex
93
+ gnuLongName = pool.toString("utf8", dataStart, dataStart + size).replace(/\0+$/, "");
94
+ start += totalNeeded;
95
+ continue;
96
+ }
97
+
98
+ if (typeflag === "x") {
99
+ paxPath = parsePaxPath(pool.toString("utf8", dataStart, dataStart + size));
100
+ start += totalNeeded;
101
+ continue;
102
+ }
103
+
104
+ if (typeflag === "g") {
105
+ start += totalNeeded;
106
+ continue;
107
+ }
108
+
109
+ const name = gnuLongName || paxPath || readTarPath(pool, headerStart);
110
+ gnuLongName = "";
111
+ paxPath = "";
112
+
113
+ if (name) {
114
+ const fullPath = join(destDir, name);
115
+
116
+ if (typeflag === "5" || name.endsWith("/")) {
117
+ ensureDir(fullPath);
118
+ } else if (typeflag === "2") {
119
+ const linkname = readString(pool, headerStart + 157, 100);
120
+ ensureDir(dirname(fullPath));
121
+ symlinkSync(linkname, fullPath);
122
+ } else if (typeflag === "0" || typeflag === "\0") {
123
+ ensureDir(dirname(fullPath));
124
+ const fd = openSync(fullPath, "w", parseOctal(pool, headerStart + 100, 8) || 0o644);
125
+ writeSync(fd, pool, dataStart, size);
126
+ closeSync(fd);
127
+ }
128
+ }
129
+
130
+ start += totalNeeded;
131
+ }
132
+ }
133
+
134
+ for await (const chunk of stream) {
135
+ appendChunk(chunk);
136
+ processEntries();
137
+ compact();
138
+ }
139
+
140
+ // Process any remaining data
141
+ processEntries();
142
+ }
143
+
144
+ // --- tar header parsing ---
145
+
146
+ function readTarPath(buf, offset) {
147
+ const prefix = readString(buf, offset + 345, 155);
148
+ const name = readString(buf, offset, 100);
149
+ return prefix ? prefix + "/" + name : name;
150
+ }
151
+
152
+ function readString(buf, offset, length) {
153
+ const end = buf.indexOf(0, offset);
154
+ const slice = buf.subarray(offset, end >= 0 && end < offset + length ? end : offset + length);
155
+ return slice.toString("utf8");
156
+ }
157
+
158
+ function parseOctal(buf, offset, length) {
159
+ const str = readString(buf, offset, length).trim();
160
+ return str ? parseInt(str, 8) || 0 : 0;
161
+ }
162
+
163
+ function parsePaxPath(paxData) {
164
+ for (const line of paxData.split("\n")) {
165
+ const match = line.match(/^\d+ path=(.+)/);
166
+ if (match) return match[1];
167
+ }
168
+ return "";
169
+ }