@openagents-org/agent-launcher 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/README.md +86 -0
- package/bin/agent-connector.js +4 -0
- package/package.json +42 -0
- package/registry.json +457 -0
- package/src/adapters/base.js +327 -0
- package/src/adapters/claude.js +420 -0
- package/src/adapters/codex.js +260 -0
- package/src/adapters/index.js +39 -0
- package/src/adapters/openclaw.js +264 -0
- package/src/adapters/utils.js +83 -0
- package/src/adapters/workspace-prompt.js +293 -0
- package/src/autostart.js +178 -0
- package/src/cli.js +556 -0
- package/src/config.js +322 -0
- package/src/daemon.js +666 -0
- package/src/env.js +111 -0
- package/src/index.js +205 -0
- package/src/installer.js +588 -0
- package/src/paths.js +276 -0
- package/src/registry.js +197 -0
- package/src/tui.js +540 -0
- package/src/utils.js +93 -0
- package/src/workspace-client.js +338 -0
package/src/cli.js
ADDED
|
@@ -0,0 +1,556 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { AgentConnector, Daemon } = require('./index');
|
|
4
|
+
|
|
5
|
+
// ---------------------------------------------------------------------------
|
|
6
|
+
// Arg parsing
|
|
7
|
+
// ---------------------------------------------------------------------------
|
|
8
|
+
|
|
9
|
+
function parseArgs(argv) {
|
|
10
|
+
const args = argv.slice(2);
|
|
11
|
+
const flags = {};
|
|
12
|
+
const allPositional = [];
|
|
13
|
+
|
|
14
|
+
for (let i = 0; i < args.length; i++) {
|
|
15
|
+
const a = args[i];
|
|
16
|
+
if (a.startsWith('--')) {
|
|
17
|
+
const eq = a.indexOf('=');
|
|
18
|
+
if (eq > 0) {
|
|
19
|
+
flags[a.slice(2, eq)] = a.slice(eq + 1);
|
|
20
|
+
} else if (i + 1 < args.length && !args[i + 1].startsWith('--')) {
|
|
21
|
+
flags[a.slice(2)] = args[i + 1];
|
|
22
|
+
i++;
|
|
23
|
+
} else {
|
|
24
|
+
flags[a.slice(2)] = true;
|
|
25
|
+
}
|
|
26
|
+
} else {
|
|
27
|
+
allPositional.push(a);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const cmd = allPositional[0] || 'status';
|
|
32
|
+
const positional = allPositional.slice(1);
|
|
33
|
+
|
|
34
|
+
return { cmd, flags, positional };
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// ---------------------------------------------------------------------------
|
|
38
|
+
// Helpers
|
|
39
|
+
// ---------------------------------------------------------------------------
|
|
40
|
+
|
|
41
|
+
function getConnector(flags) {
|
|
42
|
+
const opts = {};
|
|
43
|
+
if (flags.config) opts.configDir = flags.config;
|
|
44
|
+
return new AgentConnector(opts);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function print(msg) { process.stdout.write(msg + '\n'); }
|
|
48
|
+
|
|
49
|
+
function table(rows, headers) {
|
|
50
|
+
if (rows.length === 0) return;
|
|
51
|
+
const widths = headers.map((h, i) =>
|
|
52
|
+
Math.max(h.length, ...rows.map((r) => String(r[i] || '').length))
|
|
53
|
+
);
|
|
54
|
+
print(headers.map((h, i) => h.padEnd(widths[i])).join(' '));
|
|
55
|
+
print(widths.map((w) => '-'.repeat(w)).join(' '));
|
|
56
|
+
for (const row of rows) {
|
|
57
|
+
print(row.map((c, i) => String(c || '').padEnd(widths[i])).join(' '));
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// ---------------------------------------------------------------------------
|
|
62
|
+
// Commands
|
|
63
|
+
// ---------------------------------------------------------------------------
|
|
64
|
+
|
|
65
|
+
async function cmdUp(connector, flags) {
|
|
66
|
+
if (flags.foreground) {
|
|
67
|
+
// Run in foreground (used by daemonize child) — skip PID check
|
|
68
|
+
// because the parent already wrote our PID to the file.
|
|
69
|
+
const daemon = connector.createDaemon();
|
|
70
|
+
await daemon.start();
|
|
71
|
+
} else {
|
|
72
|
+
const pid = connector.getDaemonPid();
|
|
73
|
+
if (pid) {
|
|
74
|
+
print(`Daemon already running (PID ${pid})`);
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
// Daemonize
|
|
78
|
+
const foregroundArgs = [process.argv[1], 'up', '--foreground'];
|
|
79
|
+
if (flags.config) foregroundArgs.push('--config', flags.config);
|
|
80
|
+
connector.startDaemon(foregroundArgs);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
async function cmdDown(connector) {
|
|
85
|
+
const stopped = connector.stopDaemon();
|
|
86
|
+
if (stopped) {
|
|
87
|
+
print('Daemon stopped');
|
|
88
|
+
} else {
|
|
89
|
+
print('Daemon is not running');
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
async function cmdStatus(connector) {
|
|
94
|
+
const pid = connector.getDaemonPid();
|
|
95
|
+
if (!pid) {
|
|
96
|
+
print('Daemon is not running');
|
|
97
|
+
} else {
|
|
98
|
+
print(`Daemon running (PID ${pid})`);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const agents = connector.listAgents();
|
|
102
|
+
if (agents.length === 0) {
|
|
103
|
+
print('\nNo agents configured. Run: openagents create <name> --type <type>');
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const status = connector.getDaemonStatus();
|
|
108
|
+
const rows = agents.map((a) => {
|
|
109
|
+
const s = status[a.name] || {};
|
|
110
|
+
const state = s.state || (pid ? 'stopped' : '-');
|
|
111
|
+
const restarts = s.restarts || 0;
|
|
112
|
+
return [a.name, a.type, state, a.network || '(local)', restarts > 0 ? `${restarts}` : ''];
|
|
113
|
+
});
|
|
114
|
+
print('');
|
|
115
|
+
table(rows, ['NAME', 'TYPE', 'STATE', 'NETWORK', 'RESTARTS']);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
async function cmdCreate(connector, flags, positional) {
|
|
119
|
+
const name = positional[0];
|
|
120
|
+
if (!name) { print('Usage: openagents create <name> [--type <type>]'); return; }
|
|
121
|
+
const type = flags.type || 'openclaw';
|
|
122
|
+
const role = flags.role || 'worker';
|
|
123
|
+
|
|
124
|
+
try {
|
|
125
|
+
connector.addAgent({ name, type, role, path: flags.path });
|
|
126
|
+
print(`Agent '${name}' created (type: ${type})`);
|
|
127
|
+
|
|
128
|
+
// Auto-install if not installed
|
|
129
|
+
if (!connector.isInstalled(type)) {
|
|
130
|
+
print(`Installing ${type}...`);
|
|
131
|
+
try {
|
|
132
|
+
await connector.install(type);
|
|
133
|
+
print(`${type} installed`);
|
|
134
|
+
} catch (e) {
|
|
135
|
+
print(`Warning: install failed: ${e.message}`);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
} catch (e) {
|
|
139
|
+
print(`Error: ${e.message}`);
|
|
140
|
+
process.exitCode = 1;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
async function cmdRemove(connector, _flags, positional) {
|
|
145
|
+
const name = positional[0];
|
|
146
|
+
if (!name) { print('Usage: openagents remove <name>'); return; }
|
|
147
|
+
connector.removeAgent(name);
|
|
148
|
+
print(`Agent '${name}' removed`);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
async function cmdStart(connector, _flags, positional) {
|
|
152
|
+
const name = positional[0];
|
|
153
|
+
if (!name) { print('Usage: openagents start <name>'); return; }
|
|
154
|
+
connector.sendDaemonCommand(`restart:${name}`);
|
|
155
|
+
print(`Sent start command for '${name}'`);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
async function cmdStop(connector, _flags, positional) {
|
|
159
|
+
const name = positional[0];
|
|
160
|
+
if (!name) { print('Usage: openagents stop <name>'); return; }
|
|
161
|
+
connector.sendDaemonCommand(`stop:${name}`);
|
|
162
|
+
print(`Sent stop command for '${name}'`);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
async function cmdInstall(connector, _flags, positional) {
|
|
166
|
+
const type = positional[0];
|
|
167
|
+
if (!type) { print('Usage: openagents install <type>'); return; }
|
|
168
|
+
|
|
169
|
+
if (connector.isInstalled(type)) {
|
|
170
|
+
print(`${type} is already installed`);
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
print(`Installing ${type}...`);
|
|
175
|
+
try {
|
|
176
|
+
const result = await connector.install(type);
|
|
177
|
+
print(`${type} installed successfully`);
|
|
178
|
+
if (result.output) print(result.output);
|
|
179
|
+
} catch (e) {
|
|
180
|
+
print(`Error: ${e.message}`);
|
|
181
|
+
process.exitCode = 1;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
async function cmdUninstall(connector, _flags, positional) {
|
|
186
|
+
const type = positional[0];
|
|
187
|
+
if (!type) { print('Usage: openagents uninstall <type>'); return; }
|
|
188
|
+
|
|
189
|
+
print(`Uninstalling ${type}...`);
|
|
190
|
+
try {
|
|
191
|
+
const result = await connector.uninstall(type);
|
|
192
|
+
print(`${type} uninstalled`);
|
|
193
|
+
if (result.output) print(result.output);
|
|
194
|
+
} catch (e) {
|
|
195
|
+
print(`Error: ${e.message}`);
|
|
196
|
+
process.exitCode = 1;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
async function cmdSearch(connector, flags, positional) {
|
|
201
|
+
const query = positional[0] || '';
|
|
202
|
+
let catalog;
|
|
203
|
+
try {
|
|
204
|
+
catalog = await connector.getCatalog();
|
|
205
|
+
} catch {
|
|
206
|
+
catalog = connector.registry.getCatalogSync().map((e) => ({
|
|
207
|
+
...e,
|
|
208
|
+
installed: connector.isInstalled(e.name),
|
|
209
|
+
}));
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
if (query) {
|
|
213
|
+
const q = query.toLowerCase();
|
|
214
|
+
catalog = catalog.filter((e) =>
|
|
215
|
+
e.name.includes(q) || (e.label || '').toLowerCase().includes(q) ||
|
|
216
|
+
(e.description || '').toLowerCase().includes(q) ||
|
|
217
|
+
(e.tags || []).some((t) => t.includes(q))
|
|
218
|
+
);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
if (catalog.length === 0) {
|
|
222
|
+
print(query ? `No agents matching '${query}'` : 'No agents in catalog');
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
const rows = catalog.map((e) => [
|
|
227
|
+
e.name,
|
|
228
|
+
e.label || e.name,
|
|
229
|
+
e.installed ? 'installed' : '',
|
|
230
|
+
(e.description || '').slice(0, 50),
|
|
231
|
+
]);
|
|
232
|
+
table(rows, ['NAME', 'LABEL', 'STATUS', 'DESCRIPTION']);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
async function cmdList(connector) {
|
|
236
|
+
const agents = connector.listAgents();
|
|
237
|
+
if (agents.length === 0) {
|
|
238
|
+
print('No agents configured');
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
const rows = agents.map((a) => [
|
|
242
|
+
a.name, a.type, a.role, a.network || '(local)',
|
|
243
|
+
]);
|
|
244
|
+
table(rows, ['NAME', 'TYPE', 'ROLE', 'NETWORK']);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
async function cmdRuntimes(connector) {
|
|
248
|
+
let catalog;
|
|
249
|
+
try {
|
|
250
|
+
catalog = await connector.getCatalog();
|
|
251
|
+
} catch {
|
|
252
|
+
catalog = connector.registry.getCatalogSync().map((e) => ({
|
|
253
|
+
...e, installed: connector.isInstalled(e.name),
|
|
254
|
+
}));
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
const installed = catalog.filter((e) => e.installed);
|
|
258
|
+
if (installed.length === 0) {
|
|
259
|
+
print('No agent runtimes installed');
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
const rows = installed.map((e) => {
|
|
264
|
+
const binary = connector.installer.which(e.name) || '-';
|
|
265
|
+
return [e.name, e.label || e.name, binary];
|
|
266
|
+
});
|
|
267
|
+
table(rows, ['NAME', 'LABEL', 'PATH']);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
async function cmdConnect(connector, flags, positional) {
|
|
271
|
+
const name = positional[0];
|
|
272
|
+
const token = positional[1] || flags.token;
|
|
273
|
+
if (!name || !token) {
|
|
274
|
+
print('Usage: openagents connect <agent-name> <token>');
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
print(`Resolving workspace token...`);
|
|
279
|
+
try {
|
|
280
|
+
const info = await connector.resolveToken(token);
|
|
281
|
+
const slug = info.slug || info.workspace_id;
|
|
282
|
+
const wsName = info.name || slug;
|
|
283
|
+
|
|
284
|
+
// Save network
|
|
285
|
+
connector.config.addNetwork({
|
|
286
|
+
id: info.workspace_id,
|
|
287
|
+
slug,
|
|
288
|
+
name: wsName,
|
|
289
|
+
endpoint: info.endpoint || connector.workspace.endpoint,
|
|
290
|
+
token,
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
// Connect agent
|
|
294
|
+
connector.connectWorkspace(name, slug);
|
|
295
|
+
print(`'${name}' connected to workspace '${wsName}'`);
|
|
296
|
+
|
|
297
|
+
// Signal daemon reload
|
|
298
|
+
const pid = connector.getDaemonPid();
|
|
299
|
+
if (pid) {
|
|
300
|
+
connector.sendDaemonCommand(`restart:${name}`);
|
|
301
|
+
print('Daemon notified');
|
|
302
|
+
}
|
|
303
|
+
} catch (e) {
|
|
304
|
+
print(`Error: ${e.message}`);
|
|
305
|
+
process.exitCode = 1;
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
async function cmdDisconnect(connector, _flags, positional) {
|
|
310
|
+
const name = positional[0];
|
|
311
|
+
if (!name) { print('Usage: openagents disconnect <agent-name>'); return; }
|
|
312
|
+
connector.disconnectWorkspace(name);
|
|
313
|
+
print(`'${name}' disconnected from workspace`);
|
|
314
|
+
|
|
315
|
+
const pid = connector.getDaemonPid();
|
|
316
|
+
if (pid) {
|
|
317
|
+
connector.sendDaemonCommand(`restart:${name}`);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
async function cmdLogs(connector, flags, positional) {
|
|
322
|
+
const agent = positional[0] || flags.agent;
|
|
323
|
+
const lines = parseInt(flags.lines || flags.n || '50', 10);
|
|
324
|
+
const logLines = connector.getLogs(agent, lines);
|
|
325
|
+
for (const line of logLines) {
|
|
326
|
+
if (line) print(line);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
async function cmdAutostart(connector, flags) {
|
|
331
|
+
const autostart = require('./autostart');
|
|
332
|
+
if (flags.disable) {
|
|
333
|
+
autostart.disable();
|
|
334
|
+
print('Autostart disabled.');
|
|
335
|
+
} else {
|
|
336
|
+
const result = autostart.enable(connector._config ? connector._config.configDir : require('path').join(require('os').homedir(), '.openagents'));
|
|
337
|
+
print(`Autostart enabled.${result.path ? ` Config: ${result.path}` : ''}`);
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
async function cmdWorkspace(connector, flags, positional) {
|
|
342
|
+
const sub = positional[0] || 'list';
|
|
343
|
+
const subArgs = positional.slice(1);
|
|
344
|
+
|
|
345
|
+
switch (sub) {
|
|
346
|
+
case 'create': {
|
|
347
|
+
const name = subArgs[0] || flags.name || 'My Workspace';
|
|
348
|
+
print(`Creating workspace '${name}'...`);
|
|
349
|
+
try {
|
|
350
|
+
const result = await connector.createWorkspace({ name });
|
|
351
|
+
print(`Workspace created: ${result.name}`);
|
|
352
|
+
print(` Slug: ${result.slug}`);
|
|
353
|
+
print(` Token: ${result.token}`);
|
|
354
|
+
print(` URL: ${result.url}`);
|
|
355
|
+
} catch (e) {
|
|
356
|
+
print(`Error: ${e.message}`);
|
|
357
|
+
process.exitCode = 1;
|
|
358
|
+
}
|
|
359
|
+
break;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
case 'join': {
|
|
363
|
+
const token = subArgs[0] || flags.token;
|
|
364
|
+
if (!token) { print('Usage: openagents workspace join <token>'); return; }
|
|
365
|
+
try {
|
|
366
|
+
const info = await connector.resolveToken(token);
|
|
367
|
+
connector.config.addNetwork({
|
|
368
|
+
id: info.workspace_id,
|
|
369
|
+
slug: info.slug || info.workspace_id,
|
|
370
|
+
name: info.name || info.slug,
|
|
371
|
+
endpoint: info.endpoint || connector.workspace.endpoint,
|
|
372
|
+
token,
|
|
373
|
+
});
|
|
374
|
+
print(`Joined workspace '${info.name || info.slug}'`);
|
|
375
|
+
} catch (e) {
|
|
376
|
+
print(`Error: ${e.message}`);
|
|
377
|
+
process.exitCode = 1;
|
|
378
|
+
}
|
|
379
|
+
break;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
case 'list':
|
|
383
|
+
default: {
|
|
384
|
+
const workspaces = connector.listWorkspaces();
|
|
385
|
+
if (workspaces.length === 0) {
|
|
386
|
+
print('No workspaces configured');
|
|
387
|
+
return;
|
|
388
|
+
}
|
|
389
|
+
const rows = workspaces.map((w) => [w.slug, w.name, w.endpoint || '-']);
|
|
390
|
+
table(rows, ['SLUG', 'NAME', 'ENDPOINT']);
|
|
391
|
+
break;
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
async function cmdEnv(connector, flags, positional) {
|
|
397
|
+
const type = positional[0];
|
|
398
|
+
if (!type) { print('Usage: openagents env <type> [--set KEY=VALUE]'); return; }
|
|
399
|
+
|
|
400
|
+
const setVal = flags.set;
|
|
401
|
+
if (setVal) {
|
|
402
|
+
const eq = setVal.indexOf('=');
|
|
403
|
+
if (eq < 1) { print('Usage: --set KEY=VALUE'); return; }
|
|
404
|
+
const key = setVal.slice(0, eq);
|
|
405
|
+
const val = setVal.slice(eq + 1);
|
|
406
|
+
connector.saveAgentEnv(type, { [key]: val });
|
|
407
|
+
print(`Saved ${key} for ${type}`);
|
|
408
|
+
return;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
// Show current env
|
|
412
|
+
const env = connector.getAgentEnv(type);
|
|
413
|
+
const fields = connector.getEnvFields(type);
|
|
414
|
+
|
|
415
|
+
if (fields.length > 0) {
|
|
416
|
+
for (const field of fields) {
|
|
417
|
+
const val = env[field.name];
|
|
418
|
+
const display = field.password && val ? '***' : (val || '(not set)');
|
|
419
|
+
print(` ${field.name}: ${display} ${field.required ? '(required)' : ''}`);
|
|
420
|
+
}
|
|
421
|
+
} else {
|
|
422
|
+
const entries = Object.entries(env);
|
|
423
|
+
if (entries.length === 0) {
|
|
424
|
+
print(`No env vars configured for ${type}`);
|
|
425
|
+
} else {
|
|
426
|
+
for (const [k, v] of entries) {
|
|
427
|
+
print(` ${k}: ${v}`);
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
async function cmdTestLLM(connector, _flags, positional) {
|
|
434
|
+
const type = positional[0];
|
|
435
|
+
if (!type) { print('Usage: openagents test-llm <type>'); return; }
|
|
436
|
+
|
|
437
|
+
const env = connector.getAgentEnv(type);
|
|
438
|
+
const resolved = connector.resolveAgentEnv(type, env);
|
|
439
|
+
const effective = { ...env, ...resolved };
|
|
440
|
+
|
|
441
|
+
print(`Testing LLM connection for ${type}...`);
|
|
442
|
+
const result = await connector.testLLM(effective);
|
|
443
|
+
if (result.success) {
|
|
444
|
+
print(`Success! Model: ${result.model}, Response: ${result.response}`);
|
|
445
|
+
} else {
|
|
446
|
+
print(`Failed: ${result.error}`);
|
|
447
|
+
process.exitCode = 1;
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
async function cmdVersion() {
|
|
452
|
+
const pkg = require('../package.json');
|
|
453
|
+
print(`${pkg.name} v${pkg.version}`);
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
async function cmdHelp() {
|
|
457
|
+
print(`Usage: openagents <command> [options]
|
|
458
|
+
|
|
459
|
+
Commands:
|
|
460
|
+
up [--foreground] Start daemon (background by default)
|
|
461
|
+
down Stop daemon
|
|
462
|
+
status Show agent status
|
|
463
|
+
list List configured agents
|
|
464
|
+
create <name> [--type T] Create a new agent
|
|
465
|
+
remove <name> Remove an agent
|
|
466
|
+
start <name> Start a single agent
|
|
467
|
+
stop <name> Stop a single agent
|
|
468
|
+
install <type> Install an agent runtime
|
|
469
|
+
uninstall <type> Uninstall an agent runtime
|
|
470
|
+
search [query] Browse agent catalog
|
|
471
|
+
runtimes List installed runtimes
|
|
472
|
+
connect <agent> <token> Connect agent to workspace
|
|
473
|
+
disconnect <agent> Disconnect agent from workspace
|
|
474
|
+
env <type> [--set K=V] View/set env vars for agent type
|
|
475
|
+
autostart [--disable] Enable/disable auto-start on login
|
|
476
|
+
test-llm <type> Test LLM connection
|
|
477
|
+
logs [agent] [--lines N] View daemon logs
|
|
478
|
+
workspace create [name] Create a new workspace
|
|
479
|
+
workspace join <token> Join workspace with token
|
|
480
|
+
workspace list List configured workspaces
|
|
481
|
+
version Show version
|
|
482
|
+
help Show this help
|
|
483
|
+
|
|
484
|
+
Options:
|
|
485
|
+
--config <dir> Config directory (default: ~/.openagents)
|
|
486
|
+
`);
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
// ---------------------------------------------------------------------------
|
|
490
|
+
// Main
|
|
491
|
+
// ---------------------------------------------------------------------------
|
|
492
|
+
|
|
493
|
+
async function main() {
|
|
494
|
+
const { cmd, flags, positional } = parseArgs(process.argv);
|
|
495
|
+
|
|
496
|
+
if (cmd === 'help' || flags.help) { await cmdHelp(); return; }
|
|
497
|
+
if (cmd === 'version' || flags.version) { await cmdVersion(); return; }
|
|
498
|
+
|
|
499
|
+
const connector = getConnector(flags);
|
|
500
|
+
|
|
501
|
+
// Launch TUI if command is 'tui' or no command with interactive terminal
|
|
502
|
+
if (cmd === 'tui' || (cmd === 'status' && process.argv.length <= 2 && process.stdin.isTTY)) {
|
|
503
|
+
try {
|
|
504
|
+
const { run } = require('./tui');
|
|
505
|
+
run();
|
|
506
|
+
return;
|
|
507
|
+
} catch (e) {
|
|
508
|
+
// Fall through to text-based status if blessed not available
|
|
509
|
+
if (e.code !== 'MODULE_NOT_FOUND') {
|
|
510
|
+
print(`TUI error: ${e.message}`);
|
|
511
|
+
process.exitCode = 1;
|
|
512
|
+
return;
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
const commands = {
|
|
518
|
+
tui: () => { const { run } = require('./tui'); run(); },
|
|
519
|
+
up: () => cmdUp(connector, flags),
|
|
520
|
+
down: () => cmdDown(connector),
|
|
521
|
+
status: () => cmdStatus(connector),
|
|
522
|
+
list: () => cmdList(connector),
|
|
523
|
+
create: () => cmdCreate(connector, flags, positional),
|
|
524
|
+
remove: () => cmdRemove(connector, flags, positional),
|
|
525
|
+
start: () => cmdStart(connector, flags, positional),
|
|
526
|
+
stop: () => cmdStop(connector, flags, positional),
|
|
527
|
+
install: () => cmdInstall(connector, flags, positional),
|
|
528
|
+
uninstall: () => cmdUninstall(connector, flags, positional),
|
|
529
|
+
search: () => cmdSearch(connector, flags, positional),
|
|
530
|
+
runtimes: () => cmdRuntimes(connector),
|
|
531
|
+
connect: () => cmdConnect(connector, flags, positional),
|
|
532
|
+
disconnect: () => cmdDisconnect(connector, flags, positional),
|
|
533
|
+
logs: () => cmdLogs(connector, flags, positional),
|
|
534
|
+
autostart: () => cmdAutostart(connector, flags),
|
|
535
|
+
workspace: () => cmdWorkspace(connector, flags, positional),
|
|
536
|
+
env: () => cmdEnv(connector, flags, positional),
|
|
537
|
+
'test-llm': () => cmdTestLLM(connector, flags, positional),
|
|
538
|
+
};
|
|
539
|
+
|
|
540
|
+
const handler = commands[cmd];
|
|
541
|
+
if (!handler) {
|
|
542
|
+
print(`Unknown command: ${cmd}`);
|
|
543
|
+
print('Run: openagents help');
|
|
544
|
+
process.exitCode = 1;
|
|
545
|
+
return;
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
try {
|
|
549
|
+
await handler();
|
|
550
|
+
} catch (e) {
|
|
551
|
+
print(`Error: ${e.message}`);
|
|
552
|
+
process.exitCode = 1;
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
main();
|