@zlnap/astrolabe 0.0.0-stage → 0.17.0
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 +31 -2
- package/bin/astrolabe.js +28 -0
- package/lib/download.js +355 -0
- package/lib/platforms.js +158 -0
- package/lib/resolve.js +107 -0
- package/lib/run.js +69 -0
- package/lib/setup/args.js +85 -0
- package/lib/setup/clients.js +912 -0
- package/lib/setup/codebuddy.js +93 -0
- package/lib/setup/dsh.js +137 -0
- package/lib/setup/grok.js +81 -0
- package/lib/setup/index.js +16 -0
- package/lib/setup/jsonc.js +334 -0
- package/lib/setup/kimicode.js +94 -0
- package/lib/setup/opencode.js +159 -0
- package/lib/setup/prompt.js +69 -0
- package/lib/setup/run.js +305 -0
- package/lib/setup/vendor/astrolabe-dsh-guard/README.md +93 -0
- package/lib/setup/vendor/astrolabe-dsh-guard/cordis.patch.yml +11 -0
- package/lib/setup/vendor/astrolabe-dsh-guard/lib/index.js +145 -0
- package/lib/setup/vendor/astrolabe-dsh-guard/package.json +38 -0
- package/lib/setup/zcode.js +135 -0
- package/lib/setup.test.js +539 -0
- package/package.json +51 -4
package/lib/run.js
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { spawn } = require('child_process');
|
|
4
|
+
|
|
5
|
+
const FORWARDED = ['SIGINT', 'SIGTERM', 'SIGHUP'];
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Run the native binary with full stdio / exit-code / signal passthrough.
|
|
9
|
+
*
|
|
10
|
+
* MCP JSON-RPC is stdin/stdout; logs are stderr. Inheriting the three fds
|
|
11
|
+
* (no pipes, no buffering, no rewriting) is required or the protocol breaks.
|
|
12
|
+
*
|
|
13
|
+
* `spawnSync` would inherit stdio and exit codes, but it blocks the event
|
|
14
|
+
* loop, so an MCP client SIGTERM aimed at the shim PID would never reach the
|
|
15
|
+
* Rust process. `spawn` plus forward/re-raise is the stdio-equivalent that
|
|
16
|
+
* also transmits signals in both directions.
|
|
17
|
+
*/
|
|
18
|
+
function runBinary(binPath, argv) {
|
|
19
|
+
const child = spawn(binPath, argv, {
|
|
20
|
+
stdio: 'inherit',
|
|
21
|
+
windowsHide: false,
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
const forward = (signal) => {
|
|
25
|
+
if (!child.killed) {
|
|
26
|
+
try {
|
|
27
|
+
child.kill(signal);
|
|
28
|
+
} catch {
|
|
29
|
+
// Child may have already exited.
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
for (const signal of FORWARDED) {
|
|
35
|
+
try {
|
|
36
|
+
process.on(signal, forward);
|
|
37
|
+
} catch {
|
|
38
|
+
// Windows does not implement every POSIX signal.
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const detach = () => {
|
|
43
|
+
for (const signal of FORWARDED) {
|
|
44
|
+
process.removeListener(signal, forward);
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
child.on('error', (error) => {
|
|
49
|
+
detach();
|
|
50
|
+
console.error(`[astrolabe] failed to execute ${binPath}: ${error.message}`);
|
|
51
|
+
process.exit(1);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
child.on('exit', (code, signal) => {
|
|
55
|
+
detach();
|
|
56
|
+
if (signal) {
|
|
57
|
+
try {
|
|
58
|
+
process.kill(process.pid, signal);
|
|
59
|
+
} catch {
|
|
60
|
+
process.exit(1);
|
|
61
|
+
}
|
|
62
|
+
process.exit(1);
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
process.exit(code == null ? 1 : code);
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
module.exports = { runBinary };
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const USAGE = `Configure Astrolabe as an MCP server for local AI coding agents.
|
|
4
|
+
|
|
5
|
+
Usage:
|
|
6
|
+
astrolabe setup [options]
|
|
7
|
+
|
|
8
|
+
Options:
|
|
9
|
+
--yes, -y Configure all detected clients without prompts
|
|
10
|
+
--clients=a,b,c Configure only these client ids (comma-separated)
|
|
11
|
+
--list Print detection results and exit
|
|
12
|
+
--dry-run Preview writes; do not modify files
|
|
13
|
+
--native Use command "astrolabe" on PATH instead of npx
|
|
14
|
+
--command=<bin> Override MCP command (default: npx, or astrolabe with --native)
|
|
15
|
+
--with-hooks Also install drift-guard hooks/plugins where supported
|
|
16
|
+
(OpenCode guard plugin; Codebuddy/Grok/Kimi/ZCode hook recipes;
|
|
17
|
+
DSH always installs its native guard)
|
|
18
|
+
--no-cursor-permissions
|
|
19
|
+
Skip merging Cursor mcpAllowlist
|
|
20
|
+
--cursor-permissions Force Cursor allowlist merge when Cursor is selected (default on)
|
|
21
|
+
--home <dir> Override HOME (tests)
|
|
22
|
+
-h, --help Show this help
|
|
23
|
+
|
|
24
|
+
Client ids:
|
|
25
|
+
claude-code, cursor, codex, windsurf, cline, roo, continue, opencode,
|
|
26
|
+
deepseek-harness (alias: dsh), codebuddy, grok (aliases: grokbuild, grok-build),
|
|
27
|
+
kimicode (aliases: kimi-code, kimi_code, kimi), zcode (aliases: z-code, zai)
|
|
28
|
+
`;
|
|
29
|
+
|
|
30
|
+
function parseArgs(argv) {
|
|
31
|
+
const opts = {
|
|
32
|
+
yes: false,
|
|
33
|
+
list: false,
|
|
34
|
+
dryRun: false,
|
|
35
|
+
native: false,
|
|
36
|
+
help: false,
|
|
37
|
+
home: null,
|
|
38
|
+
clients: null,
|
|
39
|
+
command: null,
|
|
40
|
+
cursorPermissions: true,
|
|
41
|
+
withHooks: false,
|
|
42
|
+
};
|
|
43
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
44
|
+
const arg = argv[i];
|
|
45
|
+
if (arg === '--yes' || arg === '-y') opts.yes = true;
|
|
46
|
+
else if (arg === '--list') opts.list = true;
|
|
47
|
+
else if (arg === '--dry-run') opts.dryRun = true;
|
|
48
|
+
else if (arg === '--native') opts.native = true;
|
|
49
|
+
else if (arg === '--help' || arg === '-h') opts.help = true;
|
|
50
|
+
else if (arg === '--with-hooks') opts.withHooks = true;
|
|
51
|
+
else if (arg === '--no-cursor-permissions') opts.cursorPermissions = false;
|
|
52
|
+
else if (arg === '--cursor-permissions') opts.cursorPermissions = true;
|
|
53
|
+
else if (arg === '--home') {
|
|
54
|
+
const value = argv[i + 1];
|
|
55
|
+
if (!value || value.startsWith('-')) throw new Error('--home needs a directory');
|
|
56
|
+
opts.home = value;
|
|
57
|
+
i += 1;
|
|
58
|
+
} else if (arg.startsWith('--home=')) {
|
|
59
|
+
opts.home = arg.slice('--home='.length);
|
|
60
|
+
if (!opts.home) throw new Error('--home needs a directory');
|
|
61
|
+
} else if (arg.startsWith('--clients=')) {
|
|
62
|
+
const raw = arg.slice('--clients='.length).trim();
|
|
63
|
+
if (!raw) throw new Error('--clients needs a comma-separated list');
|
|
64
|
+
opts.clients = raw.split(',').map((s) => s.trim()).filter(Boolean);
|
|
65
|
+
} else if (arg === '--clients') {
|
|
66
|
+
const value = argv[i + 1];
|
|
67
|
+
if (!value || value.startsWith('-')) throw new Error('--clients needs a comma-separated list');
|
|
68
|
+
opts.clients = value.split(',').map((s) => s.trim()).filter(Boolean);
|
|
69
|
+
i += 1;
|
|
70
|
+
} else if (arg.startsWith('--command=')) {
|
|
71
|
+
opts.command = arg.slice('--command='.length);
|
|
72
|
+
if (!opts.command) throw new Error('--command needs a value');
|
|
73
|
+
} else if (arg === '--command') {
|
|
74
|
+
const value = argv[i + 1];
|
|
75
|
+
if (!value || value.startsWith('-')) throw new Error('--command needs a value');
|
|
76
|
+
opts.command = value;
|
|
77
|
+
i += 1;
|
|
78
|
+
} else {
|
|
79
|
+
throw new Error(`unknown argument: ${arg}`);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return opts;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
module.exports = { parseArgs, USAGE };
|