neo-mcp-daemon 1.0.1

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 ADDED
@@ -0,0 +1,64 @@
1
+ # test-neo-mcp-daemon
2
+
3
+ Local execution daemon for [Neo](https://heyneo.so) — written in TypeScript/Node.js, no Python required.
4
+
5
+ The daemon polls the Neo backend for commands (write files, run subprocesses, list files) and executes them on your machine. It is started automatically by the Neo MCP server when you submit a task.
6
+
7
+ ## Requirements
8
+
9
+ - Node.js 18+
10
+ - A Neo API key (`sk-v1-...`)
11
+
12
+ ## Usage
13
+
14
+ ### Automatic (recommended)
15
+
16
+ The Neo MCP server starts the daemon automatically when you submit your first task. No manual steps needed.
17
+
18
+ ### Manual start
19
+
20
+ ```bash
21
+ NEO_SECRET_KEY=sk-v1-... npx test-neo-mcp-daemon
22
+ ```
23
+
24
+ By default the daemon uses your home directory as the workspace. You can pass a path:
25
+
26
+ ```bash
27
+ NEO_SECRET_KEY=sk-v1-... npx test-neo-mcp-daemon /path/to/project
28
+ ```
29
+
30
+ ### Docker
31
+
32
+ ```bash
33
+ docker run --rm \
34
+ -e NEO_SECRET_KEY=sk-v1-... \
35
+ -v "$HOME":/root \
36
+ -v "$HOME/.neo":/root/.neo \
37
+ test-neo-mcp-daemon
38
+ ```
39
+
40
+ ## Environment variables
41
+
42
+ | Variable | Default | Description |
43
+ |---|---|---|
44
+ | `NEO_SECRET_KEY` | — | **Required.** Your Neo API key (`sk-v1-...`) |
45
+ | `NEO_ENV` | `prod` | Set to `staging` to use the staging backend |
46
+ | `NEO_API_URL` | auto | Explicit backend URL override (takes priority over `NEO_ENV`) |
47
+ | `NEO_DEPLOYMENT_ID` | auto | Override the deployment UUID (derived from API key by default) |
48
+
49
+ ## How it works
50
+
51
+ 1. Derives a stable deployment UUID from your API key (SHA-256 → UUID v5) — same key always maps to the same UUID, no config files needed
52
+ 2. Registers with the Neo backend under that UUID
53
+ 3. Polls `GET /v2/poll/{deployment_id}` for commands
54
+ 4. Dispatches commands locally: `write_code`, `run_subprocess`, `get_file`, `list_files`, `get_job_status`, `terminate_job`, `create_session`
55
+ 5. POSTs results back to `POST /v2/poll/response`
56
+
57
+ ## Path safety
58
+
59
+ The daemon only allows file operations within:
60
+ - Your home directory (`~`)
61
+ - The system temp directory (`/tmp` on Linux/macOS, `%TEMP%` on Windows)
62
+ - The workspace directory passed on the command line
63
+
64
+ All other absolute paths are blocked.
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ require('../dist/index.js');
package/dist/auth.d.ts ADDED
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Derive a stable deployment UUID from an API key.
3
+ *
4
+ * Algorithm matches Python daemon exactly:
5
+ * SHA-256(key)[:16] formatted as UUID with RFC 4122 version=5, variant=1.
6
+ * Same key → same UUID on every call, across Python and Node daemons.
7
+ */
8
+ export declare function deriveDeploymentId(secretKey: string): string;
9
+ /** Return the NEO_SECRET_KEY API key used for all requests. */
10
+ export declare function getAuthToken(): string;
11
+ //# sourceMappingURL=auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAgB5D;AAED,+DAA+D;AAC/D,wBAAgB,YAAY,IAAI,MAAM,CAErC"}
package/dist/auth.js ADDED
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.deriveDeploymentId = deriveDeploymentId;
4
+ exports.getAuthToken = getAuthToken;
5
+ const crypto_1 = require("crypto");
6
+ /**
7
+ * Derive a stable deployment UUID from an API key.
8
+ *
9
+ * Algorithm matches Python daemon exactly:
10
+ * SHA-256(key)[:16] formatted as UUID with RFC 4122 version=5, variant=1.
11
+ * Same key → same UUID on every call, across Python and Node daemons.
12
+ */
13
+ function deriveDeploymentId(secretKey) {
14
+ const hash = (0, crypto_1.createHash)('sha256').update(secretKey).digest();
15
+ const bytes = Buffer.from(hash.subarray(0, 16));
16
+ // Apply RFC 4122 version 5 and variant bits — mirrors Python's uuid.UUID(bytes=..., version=5)
17
+ bytes[6] = (bytes[6] & 0x0f) | 0x50; // version 5 (0101xxxx)
18
+ bytes[8] = (bytes[8] & 0x3f) | 0x80; // variant 1 (10xxxxxx)
19
+ const hex = bytes.toString('hex');
20
+ return [
21
+ hex.slice(0, 8),
22
+ hex.slice(8, 12),
23
+ hex.slice(12, 16),
24
+ hex.slice(16, 20),
25
+ hex.slice(20, 32),
26
+ ].join('-');
27
+ }
28
+ /** Return the NEO_SECRET_KEY API key used for all requests. */
29
+ function getAuthToken() {
30
+ return process.env['NEO_SECRET_KEY'] ?? '';
31
+ }
32
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":";;AASA,gDAgBC;AAGD,oCAEC;AA9BD,mCAAoC;AAEpC;;;;;;GAMG;AACH,SAAgB,kBAAkB,CAAC,SAAiB;IAClD,MAAM,IAAI,GAAG,IAAA,mBAAU,EAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,MAAM,EAAE,CAAC;IAC7D,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;IAEhD,+FAA+F;IAC/F,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC,uBAAuB;IAC5D,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC,uBAAuB;IAE5D,MAAM,GAAG,GAAG,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAClC,OAAO;QACL,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;QACf,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC;QAChB,GAAG,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC;QACjB,GAAG,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC;QACjB,GAAG,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC;KAClB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACd,CAAC;AAED,+DAA+D;AAC/D,SAAgB,YAAY;IAC1B,OAAO,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,IAAI,EAAE,CAAC;AAC7C,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Environment configuration.
3
+ * NEO_ENV=staging → https://alpha.heyneo.so
4
+ * NEO_ENV=prod → https://master.heyneo.so (default)
5
+ * NEO_API_URL → explicit override (takes priority)
6
+ */
7
+ export declare const NEO_API_URL: string;
8
+ export declare const NEO_ENV: string;
9
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,eAAO,MAAM,WAAW,QAA4C,CAAC;AACrE,eAAO,MAAM,OAAO,QAAO,CAAC"}
package/dist/config.js ADDED
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ /**
3
+ * Environment configuration.
4
+ * NEO_ENV=staging → https://alpha.heyneo.so
5
+ * NEO_ENV=prod → https://master.heyneo.so (default)
6
+ * NEO_API_URL → explicit override (takes priority)
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.NEO_ENV = exports.NEO_API_URL = void 0;
10
+ const _env = (process.env['NEO_ENV'] ?? 'prod').toLowerCase();
11
+ const _defaultUrl = _env === 'staging' ? 'https://alpha.heyneo.so' : 'https://master.heyneo.so';
12
+ exports.NEO_API_URL = process.env['NEO_API_URL'] ?? _defaultUrl;
13
+ exports.NEO_ENV = _env;
14
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;AAEH,MAAM,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,MAAM,CAAC,CAAC,WAAW,EAAE,CAAC;AAC9D,MAAM,WAAW,GAAG,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,yBAAyB,CAAC,CAAC,CAAC,0BAA0B,CAAC;AAEnF,QAAA,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,IAAI,WAAW,CAAC;AACxD,QAAA,OAAO,GAAG,IAAI,CAAC"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Neo npm daemon — main poll loop.
3
+ *
4
+ * Polls GET /v2/poll/{deployment_id} for commands and dispatches them via executor.ts.
5
+ * Sends results back via POST /v2/poll/response.
6
+ *
7
+ * Auth: NEO_SECRET_KEY API key used as Bearer token for all requests.
8
+ * Same wire protocol as the Python daemon.
9
+ */
10
+ export declare function runDaemon(opts?: {
11
+ workspace?: string;
12
+ deploymentId?: string;
13
+ signal?: AbortSignal;
14
+ }): Promise<void>;
15
+ //# sourceMappingURL=daemon.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"daemon.d.ts","sourceRoot":"","sources":["../src/daemon.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AA+GH,wBAAsB,SAAS,CAAC,IAAI,GAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,WAAW,CAAA;CAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAoF7H"}
package/dist/daemon.js ADDED
@@ -0,0 +1,177 @@
1
+ "use strict";
2
+ /**
3
+ * Neo npm daemon — main poll loop.
4
+ *
5
+ * Polls GET /v2/poll/{deployment_id} for commands and dispatches them via executor.ts.
6
+ * Sends results back via POST /v2/poll/response.
7
+ *
8
+ * Auth: NEO_SECRET_KEY API key used as Bearer token for all requests.
9
+ * Same wire protocol as the Python daemon.
10
+ */
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.runDaemon = runDaemon;
13
+ const fs_1 = require("fs");
14
+ const path_1 = require("path");
15
+ const auth_js_1 = require("./auth.js");
16
+ const config_js_1 = require("./config.js");
17
+ const executor_js_1 = require("./executor.js");
18
+ const paths_js_1 = require("./paths.js");
19
+ // ---------------------------------------------------------------------------
20
+ // Deployment ID
21
+ // ---------------------------------------------------------------------------
22
+ function getOrCreateDeploymentId() {
23
+ if (process.env['NEO_DEPLOYMENT_ID'])
24
+ return process.env['NEO_DEPLOYMENT_ID'];
25
+ const sk = process.env['NEO_SECRET_KEY'];
26
+ if (sk)
27
+ return (0, auth_js_1.deriveDeploymentId)(sk);
28
+ (0, fs_1.mkdirSync)(paths_js_1.DAEMON_DIR, { recursive: true });
29
+ try {
30
+ const { readFileSync } = require('fs');
31
+ const uid = readFileSync(paths_js_1.STANDALONE_UUID_FILE, 'utf8').trim();
32
+ if (uid)
33
+ return uid;
34
+ }
35
+ catch { /* not found */ }
36
+ const { randomUUID } = require('crypto');
37
+ const uid = randomUUID();
38
+ (0, fs_1.writeFileSync)(paths_js_1.STANDALONE_UUID_FILE, uid);
39
+ return uid;
40
+ }
41
+ // ---------------------------------------------------------------------------
42
+ // Sandbox log — so Python server.py _discover_sandbox_id() finds this daemon
43
+ // ---------------------------------------------------------------------------
44
+ function writeSandboxLog(deploymentId) {
45
+ (0, fs_1.mkdirSync)(paths_js_1.DAEMON_DIR, { recursive: true });
46
+ (0, fs_1.appendFileSync)(paths_js_1.DAEMON_LOG, JSON.stringify({ sandboxId: deploymentId, source: 'npm-daemon' }) + '\n');
47
+ }
48
+ // ---------------------------------------------------------------------------
49
+ // Thread workspace persistence
50
+ // ---------------------------------------------------------------------------
51
+ function loadThreadWorkspaces() {
52
+ try {
53
+ const { readFileSync } = require('fs');
54
+ return JSON.parse(readFileSync(paths_js_1.WORKSPACES_FILE, 'utf8'));
55
+ }
56
+ catch {
57
+ return {};
58
+ }
59
+ }
60
+ function saveThreadWorkspaces(workspaces) {
61
+ (0, fs_1.mkdirSync)(paths_js_1.DAEMON_DIR, { recursive: true });
62
+ (0, fs_1.writeFileSync)(paths_js_1.WORKSPACES_FILE, JSON.stringify(workspaces, null, 2));
63
+ }
64
+ // ---------------------------------------------------------------------------
65
+ // HTTP helpers
66
+ // ---------------------------------------------------------------------------
67
+ async function pollBackend(depId, token) {
68
+ try {
69
+ const controller = new AbortController();
70
+ const timeout = setTimeout(() => controller.abort(), 15_000);
71
+ const res = await fetch(`${config_js_1.NEO_API_URL}/v2/poll/${depId}?max_messages=10&wait_time=5`, { headers: { 'Authorization': `Bearer ${token}` }, signal: controller.signal });
72
+ clearTimeout(timeout);
73
+ if (res.status === 401) {
74
+ console.error('ERROR: Auth rejected (401). Check that NEO_SECRET_KEY is set correctly.');
75
+ return { commands: [], token };
76
+ }
77
+ if (res.status === 404 || !res.ok)
78
+ return { commands: [], token };
79
+ const data = await res.json();
80
+ const commands = Array.isArray(data) ? data : (data.messages ?? []);
81
+ return { commands, token };
82
+ }
83
+ catch {
84
+ return { commands: [], token };
85
+ }
86
+ }
87
+ async function sendResponse(depId, token, response) {
88
+ try {
89
+ const controller = new AbortController();
90
+ const timeout = setTimeout(() => controller.abort(), 30_000);
91
+ await fetch(`${config_js_1.NEO_API_URL}/v2/poll/response`, {
92
+ method: 'POST',
93
+ headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' },
94
+ body: JSON.stringify({ ...response, sandbox_id: response['sandbox_id'] ?? depId }),
95
+ signal: controller.signal,
96
+ });
97
+ clearTimeout(timeout);
98
+ }
99
+ catch { /* best-effort */ }
100
+ }
101
+ // ---------------------------------------------------------------------------
102
+ // Main daemon loop
103
+ // ---------------------------------------------------------------------------
104
+ async function runDaemon(opts = {}) {
105
+ const ws = (0, path_1.resolve)(opts.workspace ?? process.cwd());
106
+ const depId = opts.deploymentId ?? getOrCreateDeploymentId();
107
+ let token = (0, auth_js_1.getAuthToken)();
108
+ if (!token) {
109
+ console.error('ERROR: NEO_SECRET_KEY is not set.\n' +
110
+ 'Set your API key: export NEO_SECRET_KEY=sk-v1-...');
111
+ process.exit(1);
112
+ }
113
+ // Write sandbox log so server.py discovers this daemon
114
+ writeSandboxLog(depId);
115
+ // Write PID files: per-deployment (for is_running() checks) + global npm PID
116
+ (0, fs_1.mkdirSync)(paths_js_1.DAEMON_DIR, { recursive: true });
117
+ const pid = String(process.pid);
118
+ (0, fs_1.writeFileSync)((0, paths_js_1.pidFileForDeployment)(depId), pid);
119
+ (0, fs_1.writeFileSync)(paths_js_1.NPM_PID_FILE, pid);
120
+ const threadWorkspaces = loadThreadWorkspaces();
121
+ console.log('Neo npm daemon ready');
122
+ console.log(` deployment_id : ${depId}`);
123
+ console.log(` workspace : ${ws}`);
124
+ console.log(` backend : ${config_js_1.NEO_API_URL}`);
125
+ console.log(` pid : ${process.pid}`);
126
+ console.log('Polling for commands...\n');
127
+ // Cleanup on exit
128
+ const ac = new AbortController();
129
+ function shutdown() {
130
+ console.log('\nDaemon shutting down.');
131
+ for (const f of [(0, paths_js_1.pidFileForDeployment)(depId), paths_js_1.NPM_PID_FILE]) {
132
+ try {
133
+ require('fs').unlinkSync(f);
134
+ }
135
+ catch { /* already gone */ }
136
+ }
137
+ ac.abort();
138
+ }
139
+ // Callers (tests) can pass an AbortSignal to stop the loop without process.exit
140
+ opts.signal?.addEventListener('abort', shutdown);
141
+ process.on('SIGTERM', () => { shutdown(); process.exit(0); });
142
+ process.on('SIGINT', () => { shutdown(); process.exit(0); });
143
+ let backoff = 1_000; // ms
144
+ while (!ac.signal.aborted) {
145
+ const { commands, token: updatedToken } = await pollBackend(depId, token);
146
+ token = updatedToken;
147
+ if (commands.length > 0) {
148
+ backoff = 1_000;
149
+ for (const cmd of commands) {
150
+ const tid = cmd.thread_id;
151
+ const effectiveWs = (tid && threadWorkspaces[tid]) ? threadWorkspaces[tid] : ws;
152
+ const result = await (0, executor_js_1.dispatch)(cmd, effectiveWs);
153
+ const response = { ...result };
154
+ if (tid) {
155
+ response['thread_id'] = tid;
156
+ if (!threadWorkspaces[tid]) {
157
+ threadWorkspaces[tid] = effectiveWs;
158
+ saveThreadWorkspaces(threadWorkspaces);
159
+ }
160
+ }
161
+ if (cmd.response_queue_name) {
162
+ response['response_queue_name'] = cmd.response_queue_name;
163
+ }
164
+ await sendResponse(depId, token, response);
165
+ }
166
+ }
167
+ else {
168
+ // Interruptible sleep — exits immediately when signal fires
169
+ await new Promise(r => {
170
+ const t = setTimeout(r, backoff);
171
+ ac.signal.addEventListener('abort', () => { clearTimeout(t); r(); }, { once: true });
172
+ });
173
+ backoff = Math.min(backoff * 1.5, 10_000);
174
+ }
175
+ }
176
+ }
177
+ //# sourceMappingURL=daemon.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"daemon.js","sourceRoot":"","sources":["../src/daemon.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Action handlers — mirrors Python daemon's DaemonActionHandlers exactly.
3
+ * Supported actions: create_session, write_code, get_file, run_subprocess,
4
+ * get_job_status, terminate_job, list_files
5
+ */
6
+ export interface Command {
7
+ action: string;
8
+ request_id: string;
9
+ thread_id?: string;
10
+ response_queue_name?: string;
11
+ session_id?: string;
12
+ payload?: Record<string, unknown>;
13
+ filename?: string;
14
+ code?: string;
15
+ workdir?: string;
16
+ file_path?: string;
17
+ command?: string;
18
+ job_id?: string;
19
+ directory?: string;
20
+ max_depth?: number;
21
+ include_hidden?: boolean;
22
+ }
23
+ export interface ActionResult {
24
+ request_id: string;
25
+ status: string;
26
+ data?: Record<string, unknown>;
27
+ error?: string;
28
+ }
29
+ export declare function safeResolve(workspace: string, pathStr: string): string | null;
30
+ export declare function dispatch(cmd: Command, workspace: string): Promise<ActionResult>;
31
+ //# sourceMappingURL=executor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"executor.d.ts","sourceRoot":"","sources":["../src/executor.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAkBH,MAAM,WAAW,OAAO;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAE7B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAmBD,wBAAgB,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAW7E;AAyKD,wBAAsB,QAAQ,CAAC,GAAG,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAkBrF"}
@@ -0,0 +1,220 @@
1
+ "use strict";
2
+ /**
3
+ * Action handlers — mirrors Python daemon's DaemonActionHandlers exactly.
4
+ * Supported actions: create_session, write_code, get_file, run_subprocess,
5
+ * get_job_status, terminate_job, list_files
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.safeResolve = safeResolve;
9
+ exports.dispatch = dispatch;
10
+ const crypto_1 = require("crypto");
11
+ const child_process_1 = require("child_process");
12
+ const fs_1 = require("fs");
13
+ const os_1 = require("os");
14
+ const path_1 = require("path");
15
+ // Directories skipped during file listing — matches Python/TS daemon
16
+ const SKIP_DIRS = new Set([
17
+ 'venv', 'node_modules', 'env', '.venv', '__pycache__', '.git',
18
+ '.tox', 'dist', 'build',
19
+ ]);
20
+ // ---------------------------------------------------------------------------
21
+ // Job registry
22
+ // ---------------------------------------------------------------------------
23
+ const _jobs = new Map();
24
+ // ---------------------------------------------------------------------------
25
+ // Path safety — mirrors Python _safe_resolve()
26
+ // ---------------------------------------------------------------------------
27
+ function safeResolve(workspace, pathStr) {
28
+ const home = (0, os_1.homedir)();
29
+ const tmp = (0, os_1.tmpdir)();
30
+ // On macOS, /tmp is a symlink to /private/tmp — include both so resolve() never surprises us
31
+ const allowed = new Set([workspace, home, tmp, (0, path_1.resolve)(tmp)].filter(Boolean));
32
+ if ((0, path_1.isAbsolute)(pathStr)) {
33
+ const r = (0, path_1.resolve)(pathStr);
34
+ return [...allowed].some(a => r === a || r.startsWith(a + '/')) ? r : null;
35
+ }
36
+ const r = (0, path_1.resolve)((0, path_1.join)(workspace, pathStr));
37
+ return r === workspace || r.startsWith(workspace + '/') ? r : null;
38
+ }
39
+ // ---------------------------------------------------------------------------
40
+ // Action handlers
41
+ // ---------------------------------------------------------------------------
42
+ function hCreateSession(cmd) {
43
+ const sid = cmd.session_id ??
44
+ cmd.payload?.['session_id'] ??
45
+ (0, crypto_1.randomUUID)();
46
+ return {
47
+ request_id: cmd.request_id,
48
+ status: 'success',
49
+ data: { coding_session_id: sid },
50
+ };
51
+ }
52
+ function hWriteCode(cmd, workspace) {
53
+ const { filename, code } = cmd;
54
+ if (!filename || code === undefined) {
55
+ return { request_id: cmd.request_id, status: 'error', error: 'filename and code are required' };
56
+ }
57
+ const workdir = cmd.workdir ?? '';
58
+ // Use resolve() not join() so absolute workdir replaces workspace (mirrors Python os.path.join behaviour)
59
+ const base = workdir ? ((0, path_1.isAbsolute)(workdir) ? workdir : (0, path_1.join)(workspace, workdir)) : workspace;
60
+ const full = safeResolve(base, filename) ?? safeResolve(workspace, filename);
61
+ if (!full) {
62
+ console.warn(`[write_code] BLOCKED path=${filename} (outside workspace/tmp)`);
63
+ return { request_id: cmd.request_id, status: 'error', error: `Path escapes allowed directories: ${filename}` };
64
+ }
65
+ (0, fs_1.mkdirSync)((0, path_1.dirname)(full), { recursive: true });
66
+ (0, fs_1.writeFileSync)(full, code, 'utf8');
67
+ console.log(`[write_code] wrote ${full}`);
68
+ return {
69
+ request_id: cmd.request_id,
70
+ status: 'success',
71
+ data: { file_path: full, workdir: workdir || workspace },
72
+ };
73
+ }
74
+ function hGetFile(cmd, workspace) {
75
+ const fp = cmd.file_path;
76
+ if (!fp) {
77
+ return { request_id: cmd.request_id, status: 'error', error: 'file_path is required' };
78
+ }
79
+ const full = safeResolve(workspace, fp);
80
+ if (!full || !(0, fs_1.existsSync)(full) || !(0, fs_1.statSync)(full).isFile()) {
81
+ return { request_id: cmd.request_id, status: 'error', error: `File not found: ${fp}` };
82
+ }
83
+ const content = (0, fs_1.readFileSync)(full, 'utf8');
84
+ return {
85
+ request_id: cmd.request_id,
86
+ status: 'success',
87
+ data: { file_content: content, file_path: full },
88
+ };
89
+ }
90
+ function hRunSubprocess(cmd, workspace) {
91
+ const { command } = cmd;
92
+ if (!command) {
93
+ return { request_id: cmd.request_id, status: 'error', error: 'command is required' };
94
+ }
95
+ // Ensure workspace exists before spawning — cwd must exist or spawn throws ENOENT
96
+ (0, fs_1.mkdirSync)(workspace, { recursive: true });
97
+ console.log(`[run_subprocess] cwd=${workspace} cmd=${command.slice(0, 120)}`);
98
+ const jobId = (0, crypto_1.randomUUID)();
99
+ const proc = (0, child_process_1.spawn)(command, { shell: true, cwd: workspace });
100
+ const job = { proc, stdout: '', stderr: '', exitCode: null };
101
+ _jobs.set(jobId, job);
102
+ proc.stdout.on('data', (chunk) => { job.stdout += chunk.toString(); });
103
+ proc.stderr.on('data', (chunk) => { job.stderr += chunk.toString(); });
104
+ proc.on('close', (code) => { job.exitCode = code ?? -1; });
105
+ return {
106
+ request_id: cmd.request_id,
107
+ status: 'success',
108
+ data: { job_id: jobId, detached: true, message: 'Job started in background' },
109
+ };
110
+ }
111
+ function hGetJobStatus(cmd) {
112
+ const { job_id } = cmd;
113
+ const job = job_id ? _jobs.get(job_id) : undefined;
114
+ if (!job) {
115
+ return { request_id: cmd.request_id, status: 'error', error: `Job not found: ${job_id ?? ''}` };
116
+ }
117
+ const done = job.exitCode !== null;
118
+ return {
119
+ request_id: cmd.request_id,
120
+ status: done ? 'completed' : 'pending',
121
+ data: {
122
+ job_id,
123
+ stdout: job.stdout,
124
+ stderr: job.stderr,
125
+ exit_code: job.exitCode,
126
+ completed: done,
127
+ },
128
+ };
129
+ }
130
+ function hTerminateJob(cmd) {
131
+ const { job_id } = cmd;
132
+ const job = job_id ? _jobs.get(job_id) : undefined;
133
+ if (!job) {
134
+ return { request_id: cmd.request_id, status: 'error', error: `Job not found: ${job_id ?? ''}` };
135
+ }
136
+ try {
137
+ job.proc.kill('SIGTERM');
138
+ }
139
+ catch { /* already exited */ }
140
+ job.exitCode = -15; // SIGTERM
141
+ job.stderr += '\n[terminated by daemon]';
142
+ return {
143
+ request_id: cmd.request_id,
144
+ status: 'success',
145
+ data: { job_id, terminated: true },
146
+ };
147
+ }
148
+ function hListFiles(cmd, workspace) {
149
+ const payload = cmd.payload ?? {};
150
+ const directory = cmd.directory ?? payload['directory'] ?? workspace;
151
+ const maxDepth = Number(cmd.max_depth ?? payload['max_depth'] ?? 10);
152
+ const includeHidden = Boolean(cmd.include_hidden ?? payload['include_hidden'] ?? false);
153
+ const target = (0, path_1.isAbsolute)(directory)
154
+ ? (0, path_1.resolve)(directory)
155
+ : (safeResolve(workspace, directory) ?? workspace);
156
+ if (!(0, fs_1.existsSync)(target) || !(0, fs_1.statSync)(target).isDirectory()) {
157
+ return { request_id: cmd.request_id, status: 'error', error: `Directory not found: ${directory}` };
158
+ }
159
+ const lines = [`${target}|d|0`];
160
+ function walk(dir, depth) {
161
+ if (depth > maxDepth)
162
+ return;
163
+ let entries;
164
+ try {
165
+ entries = (0, fs_1.readdirSync)(dir, { withFileTypes: true });
166
+ }
167
+ catch {
168
+ return;
169
+ }
170
+ entries.sort((a, b) => a.name.localeCompare(b.name));
171
+ for (const entry of entries) {
172
+ if (!includeHidden && entry.name.startsWith('.'))
173
+ continue;
174
+ const fullPath = (0, path_1.join)(dir, entry.name);
175
+ if (entry.isDirectory()) {
176
+ lines.push(`${fullPath}|d|0`);
177
+ if (!SKIP_DIRS.has(entry.name))
178
+ walk(fullPath, depth + 1);
179
+ }
180
+ else {
181
+ let size = 0;
182
+ try {
183
+ size = (0, fs_1.statSync)(fullPath).size;
184
+ }
185
+ catch { /* ignore */ }
186
+ lines.push(`${fullPath}|f|${size}`);
187
+ }
188
+ }
189
+ }
190
+ walk(target, 1);
191
+ return {
192
+ request_id: cmd.request_id,
193
+ status: 'success',
194
+ data: { stdout: lines.join('\n'), file_count: lines.length, directory: target },
195
+ };
196
+ }
197
+ // ---------------------------------------------------------------------------
198
+ // Dispatch
199
+ // ---------------------------------------------------------------------------
200
+ async function dispatch(cmd, workspace) {
201
+ console.log(`[dispatch] action=${cmd.action} request_id=${cmd.request_id}`);
202
+ try {
203
+ switch (cmd.action) {
204
+ case 'create_session': return hCreateSession(cmd);
205
+ case 'write_code': return hWriteCode(cmd, workspace);
206
+ case 'get_file': return hGetFile(cmd, workspace);
207
+ case 'run_subprocess': return hRunSubprocess(cmd, workspace);
208
+ case 'get_job_status': return hGetJobStatus(cmd);
209
+ case 'terminate_job': return hTerminateJob(cmd);
210
+ case 'list_files': return hListFiles(cmd, workspace);
211
+ default:
212
+ return { request_id: cmd.request_id, status: 'error', error: `Unknown action: ${cmd.action}` };
213
+ }
214
+ }
215
+ catch (err) {
216
+ console.error(`[dispatch] error in ${cmd.action}:`, err);
217
+ return { request_id: cmd.request_id, status: 'error', error: String(err) };
218
+ }
219
+ }
220
+ //# sourceMappingURL=executor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"executor.js","sourceRoot":"","sources":["../src/executor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * neo-mcp-daemon — entry point
4
+ *
5
+ * Usage:
6
+ * npx neo-mcp-daemon [/path/to/workspace] [--deployment-id UUID]
7
+ *
8
+ * Environment:
9
+ * NEO_SECRET_KEY — API key (sk-v1-...) — primary auth
10
+ * NEO_DEPLOYMENT_ID — optional UUID override
11
+ * NEO_API_URL — optional, defaults to https://master.heyneo.so
12
+ */
13
+ export {};
14
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;;;;;;;GAUG"}
package/dist/index.js ADDED
@@ -0,0 +1,35 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ /**
4
+ * neo-mcp-daemon — entry point
5
+ *
6
+ * Usage:
7
+ * npx neo-mcp-daemon [/path/to/workspace] [--deployment-id UUID]
8
+ *
9
+ * Environment:
10
+ * NEO_SECRET_KEY — API key (sk-v1-...) — primary auth
11
+ * NEO_DEPLOYMENT_ID — optional UUID override
12
+ * NEO_API_URL — optional, defaults to https://master.heyneo.so
13
+ */
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ const daemon_js_1 = require("./daemon.js");
16
+ function parseArgs() {
17
+ const args = process.argv.slice(2);
18
+ let workspace;
19
+ let deploymentId;
20
+ for (let i = 0; i < args.length; i++) {
21
+ if (args[i] === '--deployment-id' && args[i + 1]) {
22
+ deploymentId = args[++i];
23
+ }
24
+ else if (args[i] && !args[i].startsWith('-')) {
25
+ workspace = args[i];
26
+ }
27
+ }
28
+ return { workspace, deploymentId };
29
+ }
30
+ const { workspace, deploymentId } = parseArgs();
31
+ (0, daemon_js_1.runDaemon)({ workspace, deploymentId }).catch(err => {
32
+ console.error('Fatal daemon error:', err);
33
+ process.exit(1);
34
+ });
35
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;AACA;;;;;;;;;;GAUG;;AAEH,2CAAwC;AAExC,SAAS,SAAS;IAChB,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACnC,IAAI,SAA6B,CAAC;IAClC,IAAI,YAAgC,CAAC;IAErC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,iBAAiB,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;YACjD,YAAY,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;QAC3B,CAAC;aAAM,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YAC/C,SAAS,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QACtB,CAAC;IACH,CAAC;IACD,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,CAAC;AACrC,CAAC;AAED,MAAM,EAAE,SAAS,EAAE,YAAY,EAAE,GAAG,SAAS,EAAE,CAAC;AAChD,IAAA,qBAAS,EAAC,EAAE,SAAS,EAAE,YAAY,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE;IACjD,OAAO,CAAC,KAAK,CAAC,qBAAqB,EAAE,GAAG,CAAC,CAAC;IAC1C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,9 @@
1
+ export declare const NEO_HOME: string;
2
+ export declare const DAEMON_DIR: string;
3
+ export declare const STANDALONE_UUID_FILE: string;
4
+ export declare const DAEMON_LOG: string;
5
+ export declare const NPM_PID_FILE: string;
6
+ export declare const WORKSPACES_FILE: string;
7
+ /** Per-deployment PID file — matches Python daemon's naming for compatibility. */
8
+ export declare function pidFileForDeployment(deploymentId: string): string;
9
+ //# sourceMappingURL=paths.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,QAAQ,QAA0B,CAAC;AAChD,eAAO,MAAM,UAAU,QAA2B,CAAC;AACnD,eAAO,MAAM,oBAAoB,QAA+C,CAAC;AACjF,eAAO,MAAM,UAAU,QAAiC,CAAC;AACzD,eAAO,MAAM,YAAY,QAAqC,CAAC;AAC/D,eAAO,MAAM,eAAe,QAA6C,CAAC;AAE1E,kFAAkF;AAClF,wBAAgB,oBAAoB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAEjE"}
package/dist/paths.js ADDED
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.WORKSPACES_FILE = exports.NPM_PID_FILE = exports.DAEMON_LOG = exports.STANDALONE_UUID_FILE = exports.DAEMON_DIR = exports.NEO_HOME = void 0;
4
+ exports.pidFileForDeployment = pidFileForDeployment;
5
+ const os_1 = require("os");
6
+ const path_1 = require("path");
7
+ exports.NEO_HOME = (0, path_1.join)((0, os_1.homedir)(), '.neo');
8
+ exports.DAEMON_DIR = (0, path_1.join)(exports.NEO_HOME, 'daemon');
9
+ exports.STANDALONE_UUID_FILE = (0, path_1.join)(exports.DAEMON_DIR, 'standalone_deployment_id');
10
+ exports.DAEMON_LOG = (0, path_1.join)(exports.DAEMON_DIR, 'daemon.log');
11
+ exports.NPM_PID_FILE = (0, path_1.join)(exports.DAEMON_DIR, 'npm_daemon.pid');
12
+ exports.WORKSPACES_FILE = (0, path_1.join)(exports.DAEMON_DIR, 'thread-workspaces.json');
13
+ /** Per-deployment PID file — matches Python daemon's naming for compatibility. */
14
+ function pidFileForDeployment(deploymentId) {
15
+ return (0, path_1.join)(exports.DAEMON_DIR, `daemon_${deploymentId.slice(0, 8)}.pid`);
16
+ }
17
+ //# sourceMappingURL=paths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.js","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":";;;AAWA,oDAEC;AAbD,2BAA6B;AAC7B,+BAA4B;AAEf,QAAA,QAAQ,GAAG,IAAA,WAAI,EAAC,IAAA,YAAO,GAAE,EAAE,MAAM,CAAC,CAAC;AACnC,QAAA,UAAU,GAAG,IAAA,WAAI,EAAC,gBAAQ,EAAE,QAAQ,CAAC,CAAC;AACtC,QAAA,oBAAoB,GAAG,IAAA,WAAI,EAAC,kBAAU,EAAE,0BAA0B,CAAC,CAAC;AACpE,QAAA,UAAU,GAAG,IAAA,WAAI,EAAC,kBAAU,EAAE,YAAY,CAAC,CAAC;AAC5C,QAAA,YAAY,GAAG,IAAA,WAAI,EAAC,kBAAU,EAAE,gBAAgB,CAAC,CAAC;AAClD,QAAA,eAAe,GAAG,IAAA,WAAI,EAAC,kBAAU,EAAE,wBAAwB,CAAC,CAAC;AAE1E,kFAAkF;AAClF,SAAgB,oBAAoB,CAAC,YAAoB;IACvD,OAAO,IAAA,WAAI,EAAC,kBAAU,EAAE,UAAU,YAAY,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC;AACpE,CAAC"}
package/package.json ADDED
@@ -0,0 +1,37 @@
1
+ {
2
+ "name": "neo-mcp-daemon",
3
+ "version": "1.0.1",
4
+ "description": "Neo local execution daemon — runs AI/ML tasks locally, no Python required",
5
+ "main": "dist/index.js",
6
+ "bin": {
7
+ "neo-mcp-daemon": "bin/neo-mcp-daemon"
8
+ },
9
+ "scripts": {
10
+ "build": "tsc",
11
+ "test": "vitest run",
12
+ "test:watch": "vitest",
13
+ "prepublishOnly": "npm run build && npm test"
14
+ },
15
+ "engines": {
16
+ "node": ">=18"
17
+ },
18
+ "files": [
19
+ "dist",
20
+ "bin",
21
+ "README.md"
22
+ ],
23
+ "keywords": [
24
+ "neo",
25
+ "mcp",
26
+ "daemon",
27
+ "ai",
28
+ "ml",
29
+ "local-execution"
30
+ ],
31
+ "license": "MIT",
32
+ "devDependencies": {
33
+ "@types/node": "^22.0.0",
34
+ "typescript": "^5.5.0",
35
+ "vitest": "^2.0.0"
36
+ }
37
+ }