@corenel/sidecar 0.1.2 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +2 -2
  2. package/dist/cli.js +42 -9
  3. package/package.json +48 -41
package/README.md CHANGED
@@ -25,7 +25,7 @@ match the site you're connecting from (the app fills it in for you).
25
25
  | `--allow-origin <url>` | _(none)_ | Browser origin allowed to connect. Required for a web page. Repeatable. |
26
26
  | `--port <n>` | `4858` | Port to listen on. |
27
27
  | `--root <dir>` | cwd | Root the file tools are confined to. |
28
- | `--allow-shell` | off | Enable the `shell_exec` tool (RCE on your machine — opt-in). |
28
+ | `--allow-shell` | off | Enable the `sidecar_shell_exec` tool (RCE on your machine — opt-in). |
29
29
  | `--host <addr>` | `127.0.0.1` | Bind address. Non-loopback is reachable off-box; keep the token secret. |
30
30
  | `--tls-cert <f>` `--tls-key <f>` | _(none)_ | Serve `wss://` (needed for a remote sidecar from an https page). |
31
31
 
@@ -35,6 +35,6 @@ match the site you're connecting from (the app fills it in for you).
35
35
  allowed Origin.
36
36
  - The HTTP proxy (for local LLMs) only reaches **loopback** hosts — it can't be used as
37
37
  an SSRF pivot to internal services.
38
- - `shell_exec` is off unless you pass `--allow-shell`.
38
+ - `sidecar_shell_exec` is off unless you pass `--allow-shell`.
39
39
 
40
40
  Licensed under Elastic-2.0.
package/dist/cli.js CHANGED
@@ -10,6 +10,13 @@ import { spawn as spawn4 } from "node:child_process";
10
10
  import { WebSocketServer } from "ws";
11
11
  import { createServer as createHttpsServer } from "node:https";
12
12
 
13
+ // ../protocol/stateDir.ts
14
+ var DEFAULT_STATE_DIR = ".corenel";
15
+ var dirName = DEFAULT_STATE_DIR;
16
+ function stateDirName() {
17
+ return dirName;
18
+ }
19
+
13
20
  // ../protocol/sidecar.ts
14
21
  var SIDECAR_PROTOCOL = 1;
15
22
  function isLoopbackHost(host) {
@@ -39,6 +46,10 @@ var SidecarServer = class {
39
46
  authed = false;
40
47
  hostSeq = 0;
41
48
  hostPending = /* @__PURE__ */ new Map();
49
+ /** The connected host's dot-dir name, from `hello.stateDir` (informational —
50
+ * doesn't change any sidecar behavior yet; reserved for future workspace-state
51
+ * features that need to know the host's dir name). */
52
+ hostStateDir = ".corenel";
42
53
  constructor(opts) {
43
54
  this.opts = opts;
44
55
  this.ch = opts.channel;
@@ -88,7 +99,8 @@ var SidecarServer = class {
88
99
  return;
89
100
  }
90
101
  this.authed = true;
91
- this.opts.log?.(`paired \u2014 ${this.tools.size} ${this.tools.size === 1 ? "tool" : "tools"} advertised`);
102
+ this.hostStateDir = m.stateDir ?? ".corenel";
103
+ this.opts.log?.(`paired \u2014 ${this.tools.size} ${this.tools.size === 1 ? "tool" : "tools"} advertised (host dir: ${this.hostStateDir})`);
92
104
  const tools = [...this.tools.values()].map(({ run: _run, ...decl }) => decl);
93
105
  this.ch.send({ t: "welcome", tools, features: ["http-proxy"], ...this.opts.info ? { info: this.opts.info } : {} });
94
106
  }
@@ -279,6 +291,7 @@ function startSidecar(opts) {
279
291
  wss2.on("connection", onConnection);
280
292
  return new Promise((resolveHandle, reject) => {
281
293
  httpsServer.on("error", reject);
294
+ wss2.on("error", reject);
282
295
  httpsServer.listen(opts.port, host, () => {
283
296
  const addr = httpsServer.address();
284
297
  const boundPort = typeof addr === "object" && addr ? addr.port : opts.port;
@@ -348,7 +361,7 @@ var MAX_READ_BYTES = 16 * 1024 * 1024;
348
361
  function nodeFsTools(roots) {
349
362
  return [
350
363
  {
351
- name: "fs_read_file",
364
+ name: "sidecar_fs_read_file",
352
365
  description: "Read a UTF-8 text file from the sidecar machine, relative to a pre-approved root.",
353
366
  parameters: {
354
367
  type: "object",
@@ -367,7 +380,7 @@ function nodeFsTools(roots) {
367
380
  }
368
381
  },
369
382
  {
370
- name: "fs_write_file",
383
+ name: "sidecar_fs_write_file",
371
384
  description: "Write a UTF-8 text file on the sidecar machine, relative to a pre-approved root.",
372
385
  parameters: {
373
386
  type: "object",
@@ -389,7 +402,7 @@ function nodeFsTools(roots) {
389
402
  }
390
403
  },
391
404
  {
392
- name: "fs_read_bytes",
405
+ name: "sidecar_fs_read_bytes",
393
406
  description: "Read a file from the sidecar machine as base64 (for previewing media/binary the text read would mangle), relative to a pre-approved root.",
394
407
  parameters: {
395
408
  type: "object",
@@ -408,7 +421,7 @@ function nodeFsTools(roots) {
408
421
  }
409
422
  },
410
423
  {
411
- name: "fs_list_dir",
424
+ name: "sidecar_fs_list_dir",
412
425
  description: "List the entries of a directory on the sidecar machine, relative to a pre-approved root.",
413
426
  parameters: {
414
427
  type: "object",
@@ -429,7 +442,7 @@ var MAX_TIMEOUT_MS = 3e5;
429
442
  var MAX_OUTPUT = 1e5;
430
443
  function nodeShellTool(roots) {
431
444
  return {
432
- name: "shell_exec",
445
+ name: "sidecar_shell_exec",
433
446
  description: "Run a shell command on the sidecar machine (commands a browser cannot spawn). Runs in a pre-approved root by default; returns the exit status plus combined stdout/stderr.",
434
447
  parameters: {
435
448
  type: "object",
@@ -496,7 +509,7 @@ import { randomBytes } from "node:crypto";
496
509
  import { homedir } from "node:os";
497
510
  import { join } from "node:path";
498
511
  function corenelDir() {
499
- return join(homedir(), ".corenel");
512
+ return join(homedir(), stateDirName());
500
513
  }
501
514
  function tokenPath() {
502
515
  return join(corenelDir(), "daemon.token");
@@ -823,9 +836,27 @@ function parseArgs(argv) {
823
836
  else if (a === "--tunnel-name") out.tunnelName = argv[++i];
824
837
  else if (a === "--open") out.open = true;
825
838
  else if (a === "--app-url") out.appUrl = argv[++i];
839
+ else if (a === "--sidecar" || a === "start" || a === "--") {
840
+ } else throw new Error(`unknown argument: ${a}
841
+ valid flags: ${KNOWN_FLAGS.join(" ")}`);
826
842
  }
827
843
  return out;
828
844
  }
845
+ var KNOWN_FLAGS = [
846
+ "--port",
847
+ "--host",
848
+ "--root",
849
+ "--allow-origin",
850
+ "--allow-shell",
851
+ "--allow-lan",
852
+ "--tls-cert",
853
+ "--tls-key",
854
+ "--self-signed",
855
+ "--tunnel",
856
+ "--tunnel-name",
857
+ "--open",
858
+ "--app-url"
859
+ ];
829
860
  var isIp2 = (s) => /^\d{1,3}(?:\.\d{1,3}){3}$/.test(s);
830
861
  function openBrowser(url) {
831
862
  const p = process.platform;
@@ -905,7 +936,7 @@ async function main() {
905
936
  [
906
937
  `corenel sidecar listening on ${scheme}://${handle.host}:${handle.port}`,
907
938
  args.roots.length === 1 ? ` root: ${args.roots[0]}` : ` roots: ${args.roots.join("\n ")} (${args.roots.length} approved; pick the active one in the app)`,
908
- ` tools: fs_read/write/list${args.allowShell ? " + shell_exec" : " (shell off; pass --allow-shell to enable)"}`,
939
+ ` tools: sidecar_fs_read/write/list${args.allowShell ? " + sidecar_shell_exec" : " (shell off; pass --allow-shell to enable)"}`,
909
940
  ` token: ${token} (also at ${tokenPath()})`,
910
941
  tunnelWss ? ` connect at: ${tunnelWss} (public ${args.tunnel} tunnel${args.tunnelName ? ", stable" : ""} \u2014 pair from any device with this URL + the token)` : ` connect at: ${connectUrls.join(" ")}`,
911
942
  ` origins: ${allowedOrigins.join(", ")}${args.allowLan ? " + any private-LAN origin (--allow-lan)" : args.allowOrigins.length ? "" : " (canonical defaults; pass --allow-origin to add dev/self-hosted)"}`,
@@ -932,7 +963,9 @@ async function main() {
932
963
  process.on("SIGTERM", shutdown);
933
964
  }
934
965
  main().catch((e) => {
935
- process.stderr.write(`corenel-sidecar: ${e instanceof Error ? e.message : String(e)}
966
+ const code = e?.code;
967
+ const msg = code === "EADDRINUSE" ? `port already in use \u2014 another sidecar may be running. Stop it, or pass --port <n>.` : e instanceof Error ? e.message : String(e);
968
+ process.stderr.write(`corenel-sidecar: ${msg}
936
969
  `);
937
970
  process.exit(1);
938
971
  });
package/package.json CHANGED
@@ -1,41 +1,48 @@
1
- {
2
- "name": "@corenel/sidecar",
3
- "version": "0.1.2",
4
- "type": "module",
5
- "license": "Elastic-2.0",
6
- "description": "Prompd sidecar — a local capability server. Run it next to Prompd (prompd.app) so the browser app can reach your machine: local LLMs (Ollama/LM Studio/vLLM) without CORS, your filesystem, and (opt-in) shell.",
7
- "keywords": ["prompd", "corenel", "sidecar", "ollama", "local-llm", "cors"],
8
- "bin": {
9
- "corenel-sidecar": "dist/cli.js"
10
- },
11
- "files": [
12
- "dist",
13
- "README.md"
14
- ],
15
- "engines": {
16
- "node": ">=18"
17
- },
18
- "publishConfig": {
19
- "access": "public"
20
- },
21
- "scripts": {
22
- "build": "node build.mjs",
23
- "prepublishOnly": "node build.mjs",
24
- "start": "tsx src/cli.ts",
25
- "typecheck": "tsc --noEmit",
26
- "verify": "tsx src/verify.ts"
27
- },
28
- "dependencies": {
29
- "selfsigned": "^2.4.1",
30
- "ws": "^8.18.0"
31
- },
32
- "devDependencies": {
33
- "@corenel/protocol": "workspace:*",
34
- "@corenel/harness": "workspace:*",
35
- "@types/node": "^24.13.1",
36
- "@types/ws": "^8.5.13",
37
- "esbuild": "^0.21.5",
38
- "tsx": "^4.19.2",
39
- "typescript": "^5.9.3"
40
- }
41
- }
1
+ {
2
+ "name": "@corenel/sidecar",
3
+ "version": "0.1.4",
4
+ "type": "module",
5
+ "license": "Elastic-2.0",
6
+ "description": "Prompd sidecar — a local capability server. Run it next to Prompd (prompd.app) so the browser app can reach your machine: local LLMs (Ollama/LM Studio/vLLM) without CORS, your filesystem, and (opt-in) shell.",
7
+ "keywords": [
8
+ "prompd",
9
+ "corenel",
10
+ "sidecar",
11
+ "ollama",
12
+ "local-llm",
13
+ "cors"
14
+ ],
15
+ "bin": {
16
+ "corenel-sidecar": "dist/cli.js"
17
+ },
18
+ "files": [
19
+ "dist",
20
+ "README.md"
21
+ ],
22
+ "engines": {
23
+ "node": ">=18"
24
+ },
25
+ "publishConfig": {
26
+ "access": "public"
27
+ },
28
+ "scripts": {
29
+ "build": "node build.mjs",
30
+ "prepublishOnly": "node build.mjs",
31
+ "start": "tsx src/cli.ts",
32
+ "typecheck": "tsc --noEmit",
33
+ "verify": "tsx src/verify.ts"
34
+ },
35
+ "dependencies": {
36
+ "selfsigned": "^2.4.1",
37
+ "ws": "^8.18.0"
38
+ },
39
+ "devDependencies": {
40
+ "@corenel/protocol": "workspace:*",
41
+ "@corenel/harness": "workspace:*",
42
+ "@types/node": "^24.13.1",
43
+ "@types/ws": "^8.5.13",
44
+ "esbuild": "^0.21.5",
45
+ "tsx": "^4.19.2",
46
+ "typescript": "^5.9.3"
47
+ }
48
+ }