@webannotates/runner 0.1.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/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +143 -0
- package/package.json +35 -0
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { promises as fs } from 'node:fs';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { LocalCodeAgentRunner, RunnerApiClient, defaultRunnerName, detectCapabilities, diagnose, loadConfig, loadLocalJobs, saveConfig, updateConfig, validateRepository } from '@webannotates/code-agent-runner-core';
|
|
5
|
+
function usage() {
|
|
6
|
+
console.log(`WebAnnotate local coding-agent runner
|
|
7
|
+
|
|
8
|
+
Commands:
|
|
9
|
+
connect <code> <owner/repository> <local-path> [--url URL] [--provider codex|claude]
|
|
10
|
+
pair <code> [--url URL] [--name NAME]
|
|
11
|
+
map <owner/repository> <local-path>
|
|
12
|
+
unmap <owner/repository>
|
|
13
|
+
doctor
|
|
14
|
+
jobs
|
|
15
|
+
rotate-token
|
|
16
|
+
start
|
|
17
|
+
config`);
|
|
18
|
+
}
|
|
19
|
+
function flag(name) { const index = process.argv.indexOf(name); return index >= 0 ? process.argv[index + 1] : undefined; }
|
|
20
|
+
async function main() {
|
|
21
|
+
const command = process.argv[2];
|
|
22
|
+
if (!command || ['help', '--help', '-h'].includes(command))
|
|
23
|
+
return usage();
|
|
24
|
+
if (command === 'connect') {
|
|
25
|
+
const code = process.argv[3], repository = process.argv[4], localPath = process.argv[5];
|
|
26
|
+
if (!code || !repository || !localPath)
|
|
27
|
+
throw new Error('Usage: connect <code> <owner/repository> <local-path> [--url URL] [--provider codex|claude]');
|
|
28
|
+
const current = await loadConfig();
|
|
29
|
+
const baseUrl = flag('--url') || current.baseUrl;
|
|
30
|
+
const name = flag('--name') || defaultRunnerName();
|
|
31
|
+
const provider = flag('--provider') || 'codex';
|
|
32
|
+
if (!['codex', 'claude'].includes(provider))
|
|
33
|
+
throw new Error('Provider must be codex or claude.');
|
|
34
|
+
const resolved = path.resolve(localPath);
|
|
35
|
+
await validateRepository(resolved, repository);
|
|
36
|
+
const preflightConfig = { ...current, baseUrl, repositories: { ...current.repositories, [repository]: resolved } };
|
|
37
|
+
const capabilities = await detectCapabilities(preflightConfig);
|
|
38
|
+
if (provider === 'codex' && !capabilities.codex) {
|
|
39
|
+
throw new Error(capabilities.codexInstalled ? 'Codex is installed but not authenticated. Run: codex login --device-auth' : 'Codex CLI was not found. Install it, then run this command again.');
|
|
40
|
+
}
|
|
41
|
+
if (provider === 'claude' && !capabilities.claude) {
|
|
42
|
+
throw new Error(capabilities.claudeInstalled ? 'Claude Code is installed but not authenticated. Run: claude auth login' : 'Claude Code CLI was not found. Install it, then run this command again.');
|
|
43
|
+
}
|
|
44
|
+
const result = await new RunnerApiClient({ ...preflightConfig, token: undefined }).pair(code, name);
|
|
45
|
+
const config = {
|
|
46
|
+
...preflightConfig,
|
|
47
|
+
token: result.token,
|
|
48
|
+
runnerId: result.runner.id,
|
|
49
|
+
runnerName: result.runner.name,
|
|
50
|
+
};
|
|
51
|
+
await saveConfig(config);
|
|
52
|
+
await new RunnerApiClient(config).heartbeat(capabilities);
|
|
53
|
+
console.log(`Connected ${result.runner.name} to ${repository}. Processing jobs now; keep this terminal running.`);
|
|
54
|
+
const runner = new LocalCodeAgentRunner(config, (event, detail) => {
|
|
55
|
+
const output = [new Date().toISOString(), event, detail || ''];
|
|
56
|
+
if (event === 'error')
|
|
57
|
+
console.error(...output);
|
|
58
|
+
else
|
|
59
|
+
console.log(...output);
|
|
60
|
+
});
|
|
61
|
+
process.on('SIGINT', () => runner.stop());
|
|
62
|
+
process.on('SIGTERM', () => runner.stop());
|
|
63
|
+
await runner.run();
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
if (command === 'pair') {
|
|
67
|
+
const code = process.argv[3];
|
|
68
|
+
if (!code)
|
|
69
|
+
throw new Error('Pairing code is required.');
|
|
70
|
+
const current = await loadConfig();
|
|
71
|
+
const baseUrl = flag('--url') || current.baseUrl;
|
|
72
|
+
const name = flag('--name') || defaultRunnerName();
|
|
73
|
+
const result = await new RunnerApiClient({ ...current, baseUrl, token: undefined }).pair(code, name);
|
|
74
|
+
const config = { ...current, baseUrl, token: result.token, runnerId: result.runner.id, runnerName: result.runner.name };
|
|
75
|
+
await saveConfig(config);
|
|
76
|
+
await new RunnerApiClient(config).heartbeat(await detectCapabilities(config));
|
|
77
|
+
console.log(`Paired runner ${result.runner.name}.`);
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
if (command === 'map') {
|
|
81
|
+
const repository = process.argv[3], localPath = process.argv[4];
|
|
82
|
+
if (!repository || !localPath)
|
|
83
|
+
throw new Error('Usage: map <owner/repository> <local-path>');
|
|
84
|
+
const resolved = path.resolve(localPath);
|
|
85
|
+
if (!(await fs.stat(resolved)).isDirectory())
|
|
86
|
+
throw new Error('Local repository path must be a directory.');
|
|
87
|
+
await validateRepository(resolved, repository);
|
|
88
|
+
const config = await loadConfig();
|
|
89
|
+
const next = await updateConfig({ repositories: { ...config.repositories, [repository]: resolved } });
|
|
90
|
+
if (next.token)
|
|
91
|
+
await new RunnerApiClient(next).heartbeat(await detectCapabilities(next));
|
|
92
|
+
console.log(`Mapped ${repository} to ${resolved}.`);
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
if (command === 'unmap') {
|
|
96
|
+
const repository = process.argv[3];
|
|
97
|
+
if (!repository)
|
|
98
|
+
throw new Error('Repository name is required.');
|
|
99
|
+
const config = await loadConfig(), repositories = { ...config.repositories };
|
|
100
|
+
delete repositories[repository];
|
|
101
|
+
await updateConfig({ repositories });
|
|
102
|
+
console.log(`Removed mapping for ${repository}.`);
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
if (command === 'doctor') {
|
|
106
|
+
console.log(JSON.stringify(await diagnose(await loadConfig()), null, 2));
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
if (command === 'jobs') {
|
|
110
|
+
console.log(JSON.stringify(await loadLocalJobs(), null, 2));
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
if (command === 'rotate-token') {
|
|
114
|
+
const config = await loadConfig();
|
|
115
|
+
if (!config.token)
|
|
116
|
+
throw new Error('Runner is not paired.');
|
|
117
|
+
const result = await new RunnerApiClient(config).rotateToken();
|
|
118
|
+
await saveConfig({ ...config, token: result.token });
|
|
119
|
+
console.log('Runner token rotated.');
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
if (command === 'config') {
|
|
123
|
+
const config = await loadConfig();
|
|
124
|
+
console.log(JSON.stringify({ ...config, token: config.token ? '[stored locally]' : undefined }, null, 2));
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
if (command === 'start') {
|
|
128
|
+
const runner = new LocalCodeAgentRunner(await loadConfig(), (event, detail) => {
|
|
129
|
+
const output = [new Date().toISOString(), event, detail || ''];
|
|
130
|
+
if (event === 'error')
|
|
131
|
+
console.error(...output);
|
|
132
|
+
else
|
|
133
|
+
console.log(...output);
|
|
134
|
+
});
|
|
135
|
+
process.on('SIGINT', () => runner.stop());
|
|
136
|
+
process.on('SIGTERM', () => runner.stop());
|
|
137
|
+
await runner.run();
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
usage();
|
|
141
|
+
process.exitCode = 1;
|
|
142
|
+
}
|
|
143
|
+
main().catch(error => { console.error(error?.message || error); process.exitCode = 1; });
|
package/package.json
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@webannotates/runner",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"private": false,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"webannotate-runner": "./dist/cli.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"build": "tsc -p tsconfig.json",
|
|
11
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
12
|
+
"lint": "eslint src",
|
|
13
|
+
"format": "prettier --write \"src/**/*.ts\"",
|
|
14
|
+
"start": "node dist/cli.js",
|
|
15
|
+
"prepack": "npm run build"
|
|
16
|
+
},
|
|
17
|
+
"dependencies": {
|
|
18
|
+
"@webannotates/code-agent-runner-core": "0.1.0"
|
|
19
|
+
},
|
|
20
|
+
"devDependencies": {
|
|
21
|
+
"@types/node": "^25.1.0",
|
|
22
|
+
"@workspace/eslint-config": "*",
|
|
23
|
+
"@workspace/typescript-config": "*",
|
|
24
|
+
"typescript": "5.9.3"
|
|
25
|
+
},
|
|
26
|
+
"files": [
|
|
27
|
+
"dist"
|
|
28
|
+
],
|
|
29
|
+
"engines": {
|
|
30
|
+
"node": ">=20"
|
|
31
|
+
},
|
|
32
|
+
"publishConfig": {
|
|
33
|
+
"access": "public"
|
|
34
|
+
}
|
|
35
|
+
}
|