@almyty/runner 1.2.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 +72 -0
- package/dist/binaries.d.ts +30 -0
- package/dist/binaries.js +99 -0
- package/dist/binaries.js.map +1 -0
- package/dist/cli.d.ts +12 -0
- package/dist/cli.js +128 -0
- package/dist/cli.js.map +1 -0
- package/dist/coding-agents/detect.d.ts +12 -0
- package/dist/coding-agents/detect.js +35 -0
- package/dist/coding-agents/detect.js.map +1 -0
- package/dist/coding-agents/index.d.ts +15 -0
- package/dist/coding-agents/index.js +15 -0
- package/dist/coding-agents/index.js.map +1 -0
- package/dist/coding-agents/registry.d.ts +9 -0
- package/dist/coding-agents/registry.js +260 -0
- package/dist/coding-agents/registry.js.map +1 -0
- package/dist/coding-agents/spawn-spec.d.ts +47 -0
- package/dist/coding-agents/spawn-spec.js +58 -0
- package/dist/coding-agents/spawn-spec.js.map +1 -0
- package/dist/coding-agents/status.d.ts +38 -0
- package/dist/coding-agents/status.js +111 -0
- package/dist/coding-agents/status.js.map +1 -0
- package/dist/coding-agents/types.d.ts +104 -0
- package/dist/coding-agents/types.js +18 -0
- package/dist/coding-agents/types.js.map +1 -0
- package/dist/coding-sessions.d.ts +80 -0
- package/dist/coding-sessions.js +121 -0
- package/dist/coding-sessions.js.map +1 -0
- package/dist/config.d.ts +49 -0
- package/dist/config.js +180 -0
- package/dist/config.js.map +1 -0
- package/dist/daemon.d.ts +71 -0
- package/dist/daemon.js +353 -0
- package/dist/daemon.js.map +1 -0
- package/dist/handlers.d.ts +39 -0
- package/dist/handlers.js +299 -0
- package/dist/handlers.js.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -0
- package/dist/policy.d.ts +16 -0
- package/dist/policy.js +134 -0
- package/dist/policy.js.map +1 -0
- package/dist/process-manager.d.ts +107 -0
- package/dist/process-manager.js +334 -0
- package/dist/process-manager.js.map +1 -0
- package/dist/protocol.d.ts +53 -0
- package/dist/protocol.js +39 -0
- package/dist/protocol.js.map +1 -0
- package/dist/runtime-info.d.ts +23 -0
- package/dist/runtime-info.js +35 -0
- package/dist/runtime-info.js.map +1 -0
- package/dist/streamable-client.d.ts +69 -0
- package/dist/streamable-client.js +204 -0
- package/dist/streamable-client.js.map +1 -0
- package/dist/types.d.ts +112 -0
- package/dist/types.js +21 -0
- package/dist/types.js.map +1 -0
- package/package.json +54 -0
package/README.md
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# @almyty/runner
|
|
2
|
+
|
|
3
|
+
A long-running CLI daemon that executes processes on a user's machine on behalf of almyty agents. Lets a workflow orchestrate any CLI coding agent (Claude Code, Codex, Gemini, aider, …) on your codebase, in one coherent workspace.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
npx @almyty/runner start --name my-laptop
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Three commands in three minutes:
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
npx @almyty/auth login # if you haven't already
|
|
15
|
+
npx @almyty/runner start --name my-laptop --label os=macos
|
|
16
|
+
# in another terminal:
|
|
17
|
+
npx @almyty/runner status
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Stop with `npx @almyty/runner stop` or ctrl-c in the daemon's terminal.
|
|
21
|
+
|
|
22
|
+
Or use the UI: log into your almyty account and head to **Runners → Start a runner**. The page generates the exact start command for you and waits for the daemon to come online before redirecting to the runner detail.
|
|
23
|
+
|
|
24
|
+
## What the runner does
|
|
25
|
+
|
|
26
|
+
The runner exposes a small process surface (spawn, write, read, signal, wait_for_idle, wait, list, shell.exec, runner.info) over a persistent connection to almyty. Agents call those methods, scoped to a workspace, and the runner runs the actual processes on your machine. It does not bake in any tool-specific knowledge: there is no `claude_code.run` or `codex.run`. Tool intelligence lives in agent prompts; the runner is generic.
|
|
27
|
+
|
|
28
|
+
## Config
|
|
29
|
+
|
|
30
|
+
JSON, layered lowest precedence first:
|
|
31
|
+
|
|
32
|
+
1. Built-in defaults (most restrictive: container isolation, no installs, no network)
|
|
33
|
+
2. `~/.almyty/config.json` (global)
|
|
34
|
+
3. `./.almyty/config.json` (project-local)
|
|
35
|
+
4. Environment variables (`ALMYTY_URL`, `ALMYTY_TOKEN`, `ALMYTY_RUNNER_NAME`, `ALMYTY_RUNNER_ISOLATION`)
|
|
36
|
+
5. CLI flags (`--name`, `--label`, `--config`, `--url`)
|
|
37
|
+
6. Backend overrides (constrain-only; never escalate)
|
|
38
|
+
|
|
39
|
+
A minimal `~/.almyty/config.json`:
|
|
40
|
+
|
|
41
|
+
```json
|
|
42
|
+
{
|
|
43
|
+
"name": "my-laptop",
|
|
44
|
+
"labels": { "env": "dev", "os": "macos" },
|
|
45
|
+
"config": {
|
|
46
|
+
"defaultIsolation": "host",
|
|
47
|
+
"maxConcurrent": 4,
|
|
48
|
+
"allowedCwdRoots": ["/Users/frane/workspace"],
|
|
49
|
+
"denyPatterns": [],
|
|
50
|
+
"networkBlocked": false,
|
|
51
|
+
"installBlocked": true
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Architecture
|
|
57
|
+
|
|
58
|
+
See [docs/runner.md](../../docs/runner.md) for the load-bearing design decisions: Streamable HTTP transport, no per-tool wrappers, PTY by default, detected vs configured fields, resource scoping, and config layering.
|
|
59
|
+
|
|
60
|
+
.
|
|
61
|
+
|
|
62
|
+
## About almyty
|
|
63
|
+
|
|
64
|
+
almyty is the full-stack platform for AI agents, agnostic by design: any LLM, any
|
|
65
|
+
API turned into tools, served over MCP, A2A, UTCP, and Agent Skills. Open source,
|
|
66
|
+
no lock-in.
|
|
67
|
+
|
|
68
|
+
- Website — https://almyty.com
|
|
69
|
+
- Docs — https://docs.almyty.com
|
|
70
|
+
- Source — https://github.com/almyty-inc/almyty
|
|
71
|
+
|
|
72
|
+
Apache-2.0 © Almyty Inc.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export interface BinaryProbe {
|
|
2
|
+
name: string;
|
|
3
|
+
/**
|
|
4
|
+
* Override the default exec function. Tests inject a stub that
|
|
5
|
+
* returns canned stdout/stderr/exit without spawning a real
|
|
6
|
+
* subprocess. Default implementation calls child_process.spawn.
|
|
7
|
+
*/
|
|
8
|
+
exec?: ProbeExec;
|
|
9
|
+
}
|
|
10
|
+
export type ProbeExec = (bin: string, args: string[]) => Promise<{
|
|
11
|
+
stdout: string;
|
|
12
|
+
stderr: string;
|
|
13
|
+
exitCode: number | null;
|
|
14
|
+
timedOut: boolean;
|
|
15
|
+
}>;
|
|
16
|
+
export declare const realExec: ProbeExec;
|
|
17
|
+
/**
|
|
18
|
+
* Probe a single binary. Returns the version string (first line of
|
|
19
|
+
* stdout or stderr) or `null` if absent. Empty output with exit 0 is
|
|
20
|
+
* still treated as truthy presence — the binary is on PATH and exits
|
|
21
|
+
* cleanly, so it counts; we report 'unknown' so the catalog reflects
|
|
22
|
+
* presence even when version output is empty.
|
|
23
|
+
*/
|
|
24
|
+
export declare function probe(name: string, execImpl?: ProbeExec): Promise<string | null>;
|
|
25
|
+
/**
|
|
26
|
+
* Probe a list of binaries concurrently. Bounded by the OS subprocess
|
|
27
|
+
* cap implicitly; in practice a 15-binary probe finishes well under
|
|
28
|
+
* a second on macOS/Linux.
|
|
29
|
+
*/
|
|
30
|
+
export declare function probeAll(names: string[], execImpl?: ProbeExec): Promise<Record<string, string | null>>;
|
package/dist/binaries.js
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { spawn } from 'child_process';
|
|
2
|
+
const VERSION_TIMEOUT_MS = 1500;
|
|
3
|
+
/**
|
|
4
|
+
* Probe `binary --version` (or equivalent) with a tight timeout.
|
|
5
|
+
* Returns the first non-empty line of stdout/stderr the binary emits,
|
|
6
|
+
* or `null` if the binary is not on PATH or did not respond inside
|
|
7
|
+
* the timeout. Some tools print version to stderr (cargo, rustc); we
|
|
8
|
+
* accept output from either stream.
|
|
9
|
+
*
|
|
10
|
+
* The probe runs on a few binaries that don't accept --version (none
|
|
11
|
+
* in the default list at the moment, but `aider` and others have
|
|
12
|
+
* special-cased flags in the past). We pick a list of fallback flags
|
|
13
|
+
* per-binary; if none of them produce output, we still return null
|
|
14
|
+
* rather than mis-reporting the binary as missing.
|
|
15
|
+
*/
|
|
16
|
+
const VERSION_FLAGS_DEFAULT = ['--version', '-V', '-v', 'version'];
|
|
17
|
+
const PER_BINARY_FLAGS = {
|
|
18
|
+
// gemini's CLI prints version on plain `gemini --version`, no special.
|
|
19
|
+
// claude code prints version on `claude --version` since the
|
|
20
|
+
// 1.0 stable release; older nightlies needed `--help`.
|
|
21
|
+
// Keep the mapping empty until we hit a binary that needs an override.
|
|
22
|
+
};
|
|
23
|
+
export const realExec = (bin, args) => {
|
|
24
|
+
return new Promise(resolve => {
|
|
25
|
+
let stdout = '';
|
|
26
|
+
let stderr = '';
|
|
27
|
+
let timedOut = false;
|
|
28
|
+
let child;
|
|
29
|
+
try {
|
|
30
|
+
child = spawn(bin, args, { stdio: ['ignore', 'pipe', 'pipe'] });
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
// ENOENT or similar; surface as exit code 127 (command not found).
|
|
34
|
+
resolve({ stdout: '', stderr: '', exitCode: 127, timedOut: false });
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
child.on('error', () => {
|
|
38
|
+
resolve({ stdout: '', stderr: '', exitCode: 127, timedOut: false });
|
|
39
|
+
});
|
|
40
|
+
child.stdout?.on('data', d => { stdout += d.toString(); });
|
|
41
|
+
child.stderr?.on('data', d => { stderr += d.toString(); });
|
|
42
|
+
const timer = setTimeout(() => {
|
|
43
|
+
timedOut = true;
|
|
44
|
+
try {
|
|
45
|
+
child.kill('SIGKILL');
|
|
46
|
+
}
|
|
47
|
+
catch { /* */ }
|
|
48
|
+
}, VERSION_TIMEOUT_MS);
|
|
49
|
+
timer.unref?.();
|
|
50
|
+
child.on('close', (code) => {
|
|
51
|
+
clearTimeout(timer);
|
|
52
|
+
resolve({ stdout, stderr, exitCode: code, timedOut });
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
};
|
|
56
|
+
/**
|
|
57
|
+
* Probe a single binary. Returns the version string (first line of
|
|
58
|
+
* stdout or stderr) or `null` if absent. Empty output with exit 0 is
|
|
59
|
+
* still treated as truthy presence — the binary is on PATH and exits
|
|
60
|
+
* cleanly, so it counts; we report 'unknown' so the catalog reflects
|
|
61
|
+
* presence even when version output is empty.
|
|
62
|
+
*/
|
|
63
|
+
export async function probe(name, execImpl = realExec) {
|
|
64
|
+
const flags = [...(PER_BINARY_FLAGS[name] ?? []), ...VERSION_FLAGS_DEFAULT];
|
|
65
|
+
for (const flag of flags) {
|
|
66
|
+
const result = await execImpl(name, [flag]);
|
|
67
|
+
if (result.timedOut)
|
|
68
|
+
return null;
|
|
69
|
+
if (result.exitCode === 127) {
|
|
70
|
+
// Command not found across all flags - try next, but this
|
|
71
|
+
// usually fails for everything else too.
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
const out = (result.stdout || result.stderr).trim();
|
|
75
|
+
if (out.length > 0) {
|
|
76
|
+
return firstLine(out);
|
|
77
|
+
}
|
|
78
|
+
if (result.exitCode === 0) {
|
|
79
|
+
// Exited cleanly but said nothing. Treat as present-but-unknown.
|
|
80
|
+
return 'unknown';
|
|
81
|
+
}
|
|
82
|
+
// Non-zero exit, no output: try next flag.
|
|
83
|
+
}
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Probe a list of binaries concurrently. Bounded by the OS subprocess
|
|
88
|
+
* cap implicitly; in practice a 15-binary probe finishes well under
|
|
89
|
+
* a second on macOS/Linux.
|
|
90
|
+
*/
|
|
91
|
+
export async function probeAll(names, execImpl = realExec) {
|
|
92
|
+
const entries = await Promise.all(names.map(async (n) => [n, await probe(n, execImpl)]));
|
|
93
|
+
return Object.fromEntries(entries);
|
|
94
|
+
}
|
|
95
|
+
function firstLine(s) {
|
|
96
|
+
const idx = s.indexOf('\n');
|
|
97
|
+
return idx === -1 ? s : s.slice(0, idx);
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=binaries.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"binaries.js","sourceRoot":"","sources":["../src/binaries.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* almyty-runner CLI.
|
|
4
|
+
*
|
|
5
|
+
* almyty-runner start [--name X] [--label k=v]... [--config path] [--url URL]
|
|
6
|
+
* almyty-runner status
|
|
7
|
+
* almyty-runner stop
|
|
8
|
+
*
|
|
9
|
+
* Auth: ALMYTY_TOKEN env or ~/.almyty/credentials.json (run
|
|
10
|
+
* `npx @almyty/auth login` first if neither is configured).
|
|
11
|
+
*/
|
|
12
|
+
export {};
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* almyty-runner CLI.
|
|
4
|
+
*
|
|
5
|
+
* almyty-runner start [--name X] [--label k=v]... [--config path] [--url URL]
|
|
6
|
+
* almyty-runner status
|
|
7
|
+
* almyty-runner stop
|
|
8
|
+
*
|
|
9
|
+
* Auth: ALMYTY_TOKEN env or ~/.almyty/credentials.json (run
|
|
10
|
+
* `npx @almyty/auth login` first if neither is configured).
|
|
11
|
+
*/
|
|
12
|
+
import { RunnerDaemon, readStatus, stopDaemon } from './daemon.js';
|
|
13
|
+
import { RUNNER_VERSION } from './runtime-info.js';
|
|
14
|
+
function parseArgs(argv) {
|
|
15
|
+
const args = argv.slice(2);
|
|
16
|
+
if (args.length === 0)
|
|
17
|
+
return { command: 'help' };
|
|
18
|
+
const command = args[0];
|
|
19
|
+
if (command === '--version' || command === '-v')
|
|
20
|
+
return { command: 'version' };
|
|
21
|
+
if (command === '--help' || command === '-h')
|
|
22
|
+
return { command: 'help' };
|
|
23
|
+
if (!['start', 'status', 'stop', 'help', 'version'].includes(command)) {
|
|
24
|
+
return { command: 'help' };
|
|
25
|
+
}
|
|
26
|
+
const flags = { command: command };
|
|
27
|
+
for (let i = 1; i < args.length; i++) {
|
|
28
|
+
const a = args[i];
|
|
29
|
+
if (a === '--name' && args[i + 1]) {
|
|
30
|
+
flags.name = args[++i];
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
if (a === '--config' && args[i + 1]) {
|
|
34
|
+
flags.configPath = args[++i];
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
if (a === '--url' && args[i + 1]) {
|
|
38
|
+
flags.url = args[++i];
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
if (a === '--label' && args[i + 1]) {
|
|
42
|
+
const kv = args[++i];
|
|
43
|
+
const eq = kv.indexOf('=');
|
|
44
|
+
if (eq <= 0) {
|
|
45
|
+
process.stderr.write(`--label expects key=value, got: ${kv}\n`);
|
|
46
|
+
process.exit(2);
|
|
47
|
+
}
|
|
48
|
+
flags.labels = flags.labels ?? {};
|
|
49
|
+
flags.labels[kv.slice(0, eq)] = kv.slice(eq + 1);
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
if (a === '--help' || a === '-h') {
|
|
53
|
+
flags.command = 'help';
|
|
54
|
+
return flags;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return flags;
|
|
58
|
+
}
|
|
59
|
+
function printHelp() {
|
|
60
|
+
process.stdout.write(`almyty-runner v${RUNNER_VERSION}
|
|
61
|
+
|
|
62
|
+
Usage:
|
|
63
|
+
almyty-runner start [options] Register and run the daemon
|
|
64
|
+
almyty-runner status Show local daemon status
|
|
65
|
+
almyty-runner stop Send SIGTERM to the local daemon
|
|
66
|
+
|
|
67
|
+
Options for start:
|
|
68
|
+
--name <name> Runner name (matches [a-zA-Z0-9_-]{1,64})
|
|
69
|
+
--label key=value Add a routing label; repeat for multiple
|
|
70
|
+
--config <path> Path to a JSON config file (overrides global+project)
|
|
71
|
+
--url <backend-url> Override backend URL (e.g. https://api.almyty.com)
|
|
72
|
+
|
|
73
|
+
Auth:
|
|
74
|
+
ALMYTY_TOKEN env or ~/.almyty/credentials.json (\`npx @almyty/auth login\`).
|
|
75
|
+
`);
|
|
76
|
+
}
|
|
77
|
+
async function main() {
|
|
78
|
+
const flags = parseArgs(process.argv);
|
|
79
|
+
switch (flags.command) {
|
|
80
|
+
case 'version':
|
|
81
|
+
process.stdout.write(`${RUNNER_VERSION}\n`);
|
|
82
|
+
return;
|
|
83
|
+
case 'help':
|
|
84
|
+
printHelp();
|
|
85
|
+
return;
|
|
86
|
+
case 'status': {
|
|
87
|
+
const status = readStatus();
|
|
88
|
+
if (!status) {
|
|
89
|
+
process.stdout.write('runner: not running\n');
|
|
90
|
+
process.exit(1);
|
|
91
|
+
}
|
|
92
|
+
process.stdout.write(JSON.stringify(status, null, 2) + '\n');
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
case 'stop': {
|
|
96
|
+
const ok = stopDaemon();
|
|
97
|
+
if (!ok) {
|
|
98
|
+
process.stdout.write('runner: not running\n');
|
|
99
|
+
process.exit(1);
|
|
100
|
+
}
|
|
101
|
+
process.stdout.write('runner: stop signal sent\n');
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
case 'start': {
|
|
105
|
+
const daemon = new RunnerDaemon();
|
|
106
|
+
try {
|
|
107
|
+
await daemon.start({
|
|
108
|
+
name: flags.name,
|
|
109
|
+
labels: flags.labels,
|
|
110
|
+
backendUrl: flags.url,
|
|
111
|
+
configPath: flags.configPath,
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
catch (err) {
|
|
115
|
+
process.stderr.write(`failed to start: ${err.message}\n`);
|
|
116
|
+
process.exit(1);
|
|
117
|
+
}
|
|
118
|
+
// Keep the process alive; signal handlers exit cleanly.
|
|
119
|
+
await new Promise(() => { });
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
main().catch(err => {
|
|
125
|
+
process.stderr.write(`unexpected error: ${err?.message ?? err}\n`);
|
|
126
|
+
process.exit(1);
|
|
127
|
+
});
|
|
128
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Detect which coding-agent platforms are installed on this machine.
|
|
3
|
+
*
|
|
4
|
+
* Probes each platform's binary (and any aliases — e.g. cursor resolves via
|
|
5
|
+
* `cursor-agent` or `agent`) using the same version-probe the runtime catalog
|
|
6
|
+
* uses, then returns the available platforms with their capabilities. This is
|
|
7
|
+
* what makes the runner report "I can drive claude, codex, gemini here" to the
|
|
8
|
+
* backend at registration, instead of just a flat binary map.
|
|
9
|
+
*/
|
|
10
|
+
import { type ProbeExec } from '../binaries.js';
|
|
11
|
+
import type { DetectedCodingAgent } from './types.js';
|
|
12
|
+
export declare function detectCodingAgents(exec?: ProbeExec): Promise<DetectedCodingAgent[]>;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Detect which coding-agent platforms are installed on this machine.
|
|
3
|
+
*
|
|
4
|
+
* Probes each platform's binary (and any aliases — e.g. cursor resolves via
|
|
5
|
+
* `cursor-agent` or `agent`) using the same version-probe the runtime catalog
|
|
6
|
+
* uses, then returns the available platforms with their capabilities. This is
|
|
7
|
+
* what makes the runner report "I can drive claude, codex, gemini here" to the
|
|
8
|
+
* backend at registration, instead of just a flat binary map.
|
|
9
|
+
*/
|
|
10
|
+
import { probe, realExec } from '../binaries.js';
|
|
11
|
+
import { listCodingAgents } from './registry.js';
|
|
12
|
+
export async function detectCodingAgents(exec = realExec) {
|
|
13
|
+
const results = await Promise.all(listCodingAgents().map(async (spec) => {
|
|
14
|
+
// Probe the primary binary first, then aliases; first hit wins.
|
|
15
|
+
for (const name of [spec.binary, ...spec.binaryAliases]) {
|
|
16
|
+
const version = await probe(name, exec);
|
|
17
|
+
if (version !== null) {
|
|
18
|
+
const detected = {
|
|
19
|
+
id: spec.id,
|
|
20
|
+
displayName: spec.displayName,
|
|
21
|
+
binary: spec.binary,
|
|
22
|
+
resolvedBinary: name,
|
|
23
|
+
version,
|
|
24
|
+
providerFamily: spec.providerFamily,
|
|
25
|
+
supportsMcp: spec.supportsMcp,
|
|
26
|
+
canManage: spec.canManage,
|
|
27
|
+
};
|
|
28
|
+
return detected;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return null;
|
|
32
|
+
}));
|
|
33
|
+
return results.filter((r) => r !== null);
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=detect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detect.js","sourceRoot":"","sources":["../../src/coding-agents/detect.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAkB,MAAM,gBAAgB,CAAC;AACjE,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAGjD,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,OAAkB,QAAQ;IACjE,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,CAC/B,gBAAgB,EAAE,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;QACpC,gEAAgE;QAChE,KAAK,MAAM,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,aAAa,CAAC,EAAE,CAAC;YACxD,MAAM,OAAO,GAAG,MAAM,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;YACxC,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;gBACrB,MAAM,QAAQ,GAAwB;oBACpC,EAAE,EAAE,IAAI,CAAC,EAAE;oBACX,WAAW,EAAE,IAAI,CAAC,WAAW;oBAC7B,MAAM,EAAE,IAAI,CAAC,MAAM;oBACnB,cAAc,EAAE,IAAI;oBACpB,OAAO;oBACP,cAAc,EAAE,IAAI,CAAC,cAAc;oBACnC,WAAW,EAAE,IAAI,CAAC,WAAW;oBAC7B,SAAS,EAAE,IAAI,CAAC,SAAS;iBAC1B,CAAC;gBACF,OAAO,QAAQ,CAAC;YAClB,CAAC;QACH,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC,CAAC,CACH,CAAC;IACF,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAA4B,EAAE,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC;AACrE,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Coding-agent platform support for the runner — the orchestration substrate.
|
|
3
|
+
*
|
|
4
|
+
* Turns the runner's generic process surface into a fleet that KNOWS the
|
|
5
|
+
* coding CLIs maco supports (claude, codex, gemini, cursor, opencode, crush,
|
|
6
|
+
* copilot, grok, hermes, mistral_vibe, openclaw, + aider): detect them, build
|
|
7
|
+
* an unattended spawn spec (headless auth + isolated config home + auto-approve
|
|
8
|
+
* + resume), and classify each live pane's status (busy / idle / awaiting input
|
|
9
|
+
* / awaiting auth / error).
|
|
10
|
+
*/
|
|
11
|
+
export { CODING_AGENTS, CODING_AGENT_IDS, listCodingAgents, getCodingAgent, findByBinary, allProbeBinaries, } from './registry.js';
|
|
12
|
+
export { buildAgentSpawn, resumeArgv, type AgentSpawnInput } from './spawn-spec.js';
|
|
13
|
+
export { classifyStatus, stripVtEscapes, lastFrameResetIndex, SPINNER_GLYPHS, PULSE_GLYPHS, AUTH_MARKERS, ERROR_MARKERS, } from './status.js';
|
|
14
|
+
export { detectCodingAgents } from './detect.js';
|
|
15
|
+
export type { CodingAgentId, CodingAgentSpec, DetectedCodingAgent, AgentStatus, StatusPatterns, SessionFlavor, } from './types.js';
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Coding-agent platform support for the runner — the orchestration substrate.
|
|
3
|
+
*
|
|
4
|
+
* Turns the runner's generic process surface into a fleet that KNOWS the
|
|
5
|
+
* coding CLIs maco supports (claude, codex, gemini, cursor, opencode, crush,
|
|
6
|
+
* copilot, grok, hermes, mistral_vibe, openclaw, + aider): detect them, build
|
|
7
|
+
* an unattended spawn spec (headless auth + isolated config home + auto-approve
|
|
8
|
+
* + resume), and classify each live pane's status (busy / idle / awaiting input
|
|
9
|
+
* / awaiting auth / error).
|
|
10
|
+
*/
|
|
11
|
+
export { CODING_AGENTS, CODING_AGENT_IDS, listCodingAgents, getCodingAgent, findByBinary, allProbeBinaries, } from './registry.js';
|
|
12
|
+
export { buildAgentSpawn, resumeArgv } from './spawn-spec.js';
|
|
13
|
+
export { classifyStatus, stripVtEscapes, lastFrameResetIndex, SPINNER_GLYPHS, PULSE_GLYPHS, AUTH_MARKERS, ERROR_MARKERS, } from './status.js';
|
|
14
|
+
export { detectCodingAgents } from './detect.js';
|
|
15
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/coding-agents/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EACL,aAAa,EACb,gBAAgB,EAChB,gBAAgB,EAChB,cAAc,EACd,YAAY,EACZ,gBAAgB,GACjB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,eAAe,EAAE,UAAU,EAAwB,MAAM,iBAAiB,CAAC;AACpF,OAAO,EACL,cAAc,EACd,cAAc,EACd,mBAAmB,EACnB,cAAc,EACd,YAAY,EACZ,YAAY,EACZ,aAAa,GACd,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { CodingAgentId, CodingAgentSpec } from './types.js';
|
|
2
|
+
export declare const CODING_AGENTS: Record<CodingAgentId, CodingAgentSpec>;
|
|
3
|
+
export declare const CODING_AGENT_IDS: CodingAgentId[];
|
|
4
|
+
export declare function listCodingAgents(): CodingAgentSpec[];
|
|
5
|
+
export declare function getCodingAgent(id: string): CodingAgentSpec | undefined;
|
|
6
|
+
/** Resolve a spec by binary name or alias (e.g. "cursor-agent" → cursor). */
|
|
7
|
+
export declare function findByBinary(binaryName: string): CodingAgentSpec | undefined;
|
|
8
|
+
/** Every binary name (primary + aliases) for the probe list. */
|
|
9
|
+
export declare function allProbeBinaries(): string[];
|