@corenel/sidecar 0.1.3 → 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.
- package/README.md +2 -2
- package/dist/cli.js +21 -9
- 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 `
|
|
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
|
-
- `
|
|
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.
|
|
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
|
}
|
|
@@ -349,7 +361,7 @@ var MAX_READ_BYTES = 16 * 1024 * 1024;
|
|
|
349
361
|
function nodeFsTools(roots) {
|
|
350
362
|
return [
|
|
351
363
|
{
|
|
352
|
-
name: "
|
|
364
|
+
name: "sidecar_fs_read_file",
|
|
353
365
|
description: "Read a UTF-8 text file from the sidecar machine, relative to a pre-approved root.",
|
|
354
366
|
parameters: {
|
|
355
367
|
type: "object",
|
|
@@ -368,7 +380,7 @@ function nodeFsTools(roots) {
|
|
|
368
380
|
}
|
|
369
381
|
},
|
|
370
382
|
{
|
|
371
|
-
name: "
|
|
383
|
+
name: "sidecar_fs_write_file",
|
|
372
384
|
description: "Write a UTF-8 text file on the sidecar machine, relative to a pre-approved root.",
|
|
373
385
|
parameters: {
|
|
374
386
|
type: "object",
|
|
@@ -390,7 +402,7 @@ function nodeFsTools(roots) {
|
|
|
390
402
|
}
|
|
391
403
|
},
|
|
392
404
|
{
|
|
393
|
-
name: "
|
|
405
|
+
name: "sidecar_fs_read_bytes",
|
|
394
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.",
|
|
395
407
|
parameters: {
|
|
396
408
|
type: "object",
|
|
@@ -409,7 +421,7 @@ function nodeFsTools(roots) {
|
|
|
409
421
|
}
|
|
410
422
|
},
|
|
411
423
|
{
|
|
412
|
-
name: "
|
|
424
|
+
name: "sidecar_fs_list_dir",
|
|
413
425
|
description: "List the entries of a directory on the sidecar machine, relative to a pre-approved root.",
|
|
414
426
|
parameters: {
|
|
415
427
|
type: "object",
|
|
@@ -430,7 +442,7 @@ var MAX_TIMEOUT_MS = 3e5;
|
|
|
430
442
|
var MAX_OUTPUT = 1e5;
|
|
431
443
|
function nodeShellTool(roots) {
|
|
432
444
|
return {
|
|
433
|
-
name: "
|
|
445
|
+
name: "sidecar_shell_exec",
|
|
434
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.",
|
|
435
447
|
parameters: {
|
|
436
448
|
type: "object",
|
|
@@ -497,7 +509,7 @@ import { randomBytes } from "node:crypto";
|
|
|
497
509
|
import { homedir } from "node:os";
|
|
498
510
|
import { join } from "node:path";
|
|
499
511
|
function corenelDir() {
|
|
500
|
-
return join(homedir(),
|
|
512
|
+
return join(homedir(), stateDirName());
|
|
501
513
|
}
|
|
502
514
|
function tokenPath() {
|
|
503
515
|
return join(corenelDir(), "daemon.token");
|
|
@@ -824,7 +836,7 @@ function parseArgs(argv) {
|
|
|
824
836
|
else if (a === "--tunnel-name") out.tunnelName = argv[++i];
|
|
825
837
|
else if (a === "--open") out.open = true;
|
|
826
838
|
else if (a === "--app-url") out.appUrl = argv[++i];
|
|
827
|
-
else if (a === "--sidecar" || a === "start") {
|
|
839
|
+
else if (a === "--sidecar" || a === "start" || a === "--") {
|
|
828
840
|
} else throw new Error(`unknown argument: ${a}
|
|
829
841
|
valid flags: ${KNOWN_FLAGS.join(" ")}`);
|
|
830
842
|
}
|
|
@@ -924,7 +936,7 @@ async function main() {
|
|
|
924
936
|
[
|
|
925
937
|
`corenel sidecar listening on ${scheme}://${handle.host}:${handle.port}`,
|
|
926
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)`,
|
|
927
|
-
` tools:
|
|
939
|
+
` tools: sidecar_fs_read/write/list${args.allowShell ? " + sidecar_shell_exec" : " (shell off; pass --allow-shell to enable)"}`,
|
|
928
940
|
` token: ${token} (also at ${tokenPath()})`,
|
|
929
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(" ")}`,
|
|
930
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)"}`,
|
package/package.json
CHANGED
|
@@ -1,41 +1,48 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@corenel/sidecar",
|
|
3
|
-
"version": "0.1.
|
|
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
|
-
|
|
9
|
-
"corenel
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
"
|
|
13
|
-
"
|
|
14
|
-
],
|
|
15
|
-
"
|
|
16
|
-
"
|
|
17
|
-
},
|
|
18
|
-
"
|
|
19
|
-
"
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
"
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
"
|
|
27
|
-
},
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
"
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
"
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
"
|
|
37
|
-
"
|
|
38
|
-
|
|
39
|
-
|
|
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
|
+
}
|