@agent-commons/cli 0.2.4 → 0.4.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/LICENSE +21 -0
- package/README.md +206 -0
- package/dist/bin.js +1773 -508
- package/package.json +25 -4
package/dist/bin.js
CHANGED
|
@@ -24,17 +24,14 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
24
24
|
));
|
|
25
25
|
|
|
26
26
|
// src/bin.ts
|
|
27
|
-
var
|
|
28
|
-
var import_path5 = require("path");
|
|
29
|
-
var import_os4 = require("os");
|
|
27
|
+
var import_commander22 = require("commander");
|
|
30
28
|
var import_child_process3 = require("child_process");
|
|
31
29
|
|
|
32
30
|
// src/commands/login.ts
|
|
33
31
|
var import_commander = require("commander");
|
|
34
|
-
var readline = __toESM(require("readline"));
|
|
35
32
|
var import_fs2 = require("fs");
|
|
36
|
-
var import_path2 = require("path");
|
|
37
33
|
var import_os2 = require("os");
|
|
34
|
+
var import_path2 = require("path");
|
|
38
35
|
|
|
39
36
|
// src/config.ts
|
|
40
37
|
var import_fs = require("fs");
|
|
@@ -44,9 +41,16 @@ var import_sdk = require("@agent-commons/sdk");
|
|
|
44
41
|
var CONFIG_DIR = (0, import_path.join)((0, import_os.homedir)(), ".agc");
|
|
45
42
|
var CONFIG_FILE = (0, import_path.join)(CONFIG_DIR, "config.json");
|
|
46
43
|
var DEFAULT_API_URL = process.env.AGC_API_URL ?? "https://api.agentcommons.io";
|
|
47
|
-
var DEFAULT_APP_URL = "https://www.agentcommons.io";
|
|
48
44
|
var DEFAULT_IDENTITY_URL = process.env.COMMONS_IDENTITY_URL ?? "https://auth.agentcommons.io";
|
|
49
45
|
var DEFAULT_IDENTITY_CLIENT_ID = process.env.COMMONS_IDENTITY_CLIENT_ID ?? "commons-cli";
|
|
46
|
+
function readStoredConfig() {
|
|
47
|
+
if (!(0, import_fs.existsSync)(CONFIG_FILE)) return {};
|
|
48
|
+
try {
|
|
49
|
+
return JSON.parse((0, import_fs.readFileSync)(CONFIG_FILE, "utf8"));
|
|
50
|
+
} catch {
|
|
51
|
+
return {};
|
|
52
|
+
}
|
|
53
|
+
}
|
|
50
54
|
function loadConfig() {
|
|
51
55
|
const fromEnv = {
|
|
52
56
|
...process.env.AGC_API_URL && { apiUrl: process.env.AGC_API_URL },
|
|
@@ -56,13 +60,7 @@ function loadConfig() {
|
|
|
56
60
|
...process.env.AGC_INITIATOR && { initiator: process.env.AGC_INITIATOR },
|
|
57
61
|
...process.env.AGC_AGENT_ID && { defaultAgentId: process.env.AGC_AGENT_ID }
|
|
58
62
|
};
|
|
59
|
-
|
|
60
|
-
if ((0, import_fs.existsSync)(CONFIG_FILE)) {
|
|
61
|
-
try {
|
|
62
|
-
fromFile = JSON.parse((0, import_fs.readFileSync)(CONFIG_FILE, "utf8"));
|
|
63
|
-
} catch {
|
|
64
|
-
}
|
|
65
|
-
}
|
|
63
|
+
const fromFile = readStoredConfig();
|
|
66
64
|
return {
|
|
67
65
|
apiUrl: DEFAULT_API_URL,
|
|
68
66
|
identityUrl: DEFAULT_IDENTITY_URL,
|
|
@@ -72,32 +70,44 @@ function loadConfig() {
|
|
|
72
70
|
};
|
|
73
71
|
}
|
|
74
72
|
function saveConfig(updates) {
|
|
75
|
-
const
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
73
|
+
const next = {
|
|
74
|
+
apiUrl: DEFAULT_API_URL,
|
|
75
|
+
identityUrl: DEFAULT_IDENTITY_URL,
|
|
76
|
+
identityClientId: DEFAULT_IDENTITY_CLIENT_ID,
|
|
77
|
+
...readStoredConfig(),
|
|
78
|
+
...updates
|
|
79
|
+
};
|
|
80
|
+
if (!(0, import_fs.existsSync)(CONFIG_DIR)) {
|
|
81
|
+
(0, import_fs.mkdirSync)(CONFIG_DIR, { recursive: true, mode: 448 });
|
|
82
|
+
}
|
|
83
|
+
(0, import_fs.chmodSync)(CONFIG_DIR, 448);
|
|
84
|
+
const temporaryFile = (0, import_path.join)(CONFIG_DIR, `.config-${process.pid}.tmp`);
|
|
85
|
+
(0, import_fs.writeFileSync)(temporaryFile, JSON.stringify(next, null, 2) + "\n", {
|
|
86
|
+
mode: 384
|
|
87
|
+
});
|
|
88
|
+
(0, import_fs.renameSync)(temporaryFile, CONFIG_FILE);
|
|
89
|
+
(0, import_fs.chmodSync)(CONFIG_FILE, 384);
|
|
79
90
|
}
|
|
80
91
|
function clearConfig() {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
{ mode: 384 }
|
|
94
|
-
);
|
|
95
|
-
}
|
|
92
|
+
saveConfig({
|
|
93
|
+
sessionToken: void 0,
|
|
94
|
+
accessToken: void 0,
|
|
95
|
+
accessTokenExpiresAt: void 0,
|
|
96
|
+
userId: void 0,
|
|
97
|
+
userEmail: void 0,
|
|
98
|
+
userName: void 0,
|
|
99
|
+
workspaceId: void 0,
|
|
100
|
+
apiKey: void 0,
|
|
101
|
+
initiator: void 0,
|
|
102
|
+
defaultAgentId: void 0
|
|
103
|
+
});
|
|
96
104
|
}
|
|
97
105
|
function makeClient(overrides) {
|
|
98
106
|
const cfg = { ...loadConfig(), ...overrides };
|
|
99
107
|
return new import_sdk.CommonsClient({
|
|
100
108
|
baseUrl: cfg.apiUrl,
|
|
109
|
+
identityUrl: cfg.identityUrl,
|
|
110
|
+
identityToken: cfg.sessionToken,
|
|
101
111
|
apiKey: cfg.accessToken ?? cfg.apiKey,
|
|
102
112
|
initiator: cfg.userId ?? cfg.initiator
|
|
103
113
|
});
|
|
@@ -113,6 +123,7 @@ function decodeJwtPayload(token) {
|
|
|
113
123
|
}
|
|
114
124
|
async function ensureAccessToken() {
|
|
115
125
|
const cfg = loadConfig();
|
|
126
|
+
if (cfg.accessToken && !cfg.sessionToken) return cfg;
|
|
116
127
|
if (cfg.apiKey && !cfg.sessionToken) return cfg;
|
|
117
128
|
if (cfg.accessToken && cfg.accessTokenExpiresAt && cfg.accessTokenExpiresAt > Date.now() + 3e4) {
|
|
118
129
|
return cfg;
|
|
@@ -122,9 +133,14 @@ async function ensureAccessToken() {
|
|
|
122
133
|
`${cfg.identityUrl.replace(/\/$/, "")}/api/auth/token`,
|
|
123
134
|
{ headers: { Authorization: `Bearer ${cfg.sessionToken}` } }
|
|
124
135
|
);
|
|
125
|
-
if (
|
|
136
|
+
if (response.status === 401 || response.status === 403) {
|
|
126
137
|
throw new Error("Your Commons login has expired. Run `agc login` again.");
|
|
127
138
|
}
|
|
139
|
+
if (!response.ok) {
|
|
140
|
+
throw new Error(
|
|
141
|
+
`Commons Identity is unavailable (${response.status}). Please try again.`
|
|
142
|
+
);
|
|
143
|
+
}
|
|
128
144
|
const data = await response.json();
|
|
129
145
|
if (!data.token) throw new Error("Commons Identity did not return an access token.");
|
|
130
146
|
const claims = decodeJwtPayload(data.token);
|
|
@@ -132,6 +148,8 @@ async function ensureAccessToken() {
|
|
|
132
148
|
accessToken: data.token,
|
|
133
149
|
accessTokenExpiresAt: typeof claims.exp === "number" ? claims.exp * 1e3 : Date.now() + 10 * 60 * 1e3,
|
|
134
150
|
userId: typeof claims.sub === "string" ? claims.sub : cfg.userId,
|
|
151
|
+
userEmail: typeof claims.email === "string" ? claims.email : cfg.userEmail,
|
|
152
|
+
userName: typeof claims.name === "string" ? claims.name : cfg.userName,
|
|
135
153
|
workspaceId: typeof claims.workspace_id === "string" ? claims.workspace_id : cfg.workspaceId,
|
|
136
154
|
initiator: typeof claims.sub === "string" ? claims.sub : cfg.initiator
|
|
137
155
|
};
|
|
@@ -160,15 +178,15 @@ var sym = {
|
|
|
160
178
|
bullet: import_chalk.default.dim("\u2022"),
|
|
161
179
|
dot: import_chalk.default.dim("\xB7")
|
|
162
180
|
};
|
|
163
|
-
function banner(version = "0.
|
|
164
|
-
const line = import_chalk.default.cyan(" \u2500".padEnd(2) + "\u2500".repeat(44));
|
|
181
|
+
function banner(version = "0.4.0") {
|
|
165
182
|
console.log("");
|
|
166
|
-
console.log(
|
|
183
|
+
console.log(import_chalk.default.cyan(" \u25C7"));
|
|
184
|
+
console.log(import_chalk.default.cyan(" \u256D\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256E"));
|
|
167
185
|
console.log(
|
|
168
|
-
import_chalk.default.cyan("
|
|
186
|
+
import_chalk.default.cyan(" \u2502 ") + import_chalk.default.bold.white("AGENT COMMONS") + import_chalk.default.dim(" // CLI") + import_chalk.default.cyan(` v${version}`) + import_chalk.default.cyan(" \u2502")
|
|
169
187
|
);
|
|
170
|
-
console.log(import_chalk.default.cyan("
|
|
171
|
-
console.log(
|
|
188
|
+
console.log(import_chalk.default.cyan(" \u2570\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256F"));
|
|
189
|
+
console.log(import_chalk.default.dim(" Build \xB7 run \xB7 connect \xB7 collaborate"));
|
|
172
190
|
console.log("");
|
|
173
191
|
}
|
|
174
192
|
function step(n, total, title) {
|
|
@@ -177,7 +195,7 @@ function step(n, total, title) {
|
|
|
177
195
|
${import_chalk.default.cyan.bold(" Step " + n)} ${fraction} ${import_chalk.default.bold(title)}`);
|
|
178
196
|
console.log(import_chalk.default.dim(" " + "\u2500".repeat(38)));
|
|
179
197
|
}
|
|
180
|
-
async function select(
|
|
198
|
+
async function select(prompt, choices) {
|
|
181
199
|
if (!process.stdin.isTTY) {
|
|
182
200
|
return choices[0].value;
|
|
183
201
|
}
|
|
@@ -187,7 +205,7 @@ async function select(prompt2, choices) {
|
|
|
187
205
|
if (!first) {
|
|
188
206
|
process.stdout.write(`\x1B[${total + 2}A\x1B[0J`);
|
|
189
207
|
}
|
|
190
|
-
console.log("\n" + import_chalk.default.bold(" " +
|
|
208
|
+
console.log("\n" + import_chalk.default.bold(" " + prompt));
|
|
191
209
|
for (let i = 0; i < total; i++) {
|
|
192
210
|
const { label, hint } = choices[i];
|
|
193
211
|
if (i === idx) {
|
|
@@ -230,9 +248,14 @@ async function select(prompt2, choices) {
|
|
|
230
248
|
});
|
|
231
249
|
}
|
|
232
250
|
function openBrowser(url) {
|
|
233
|
-
const
|
|
234
|
-
(0, import_child_process.
|
|
251
|
+
const command = process.platform === "darwin" ? { file: "open", args: [url] } : process.platform === "win32" ? { file: "cmd", args: ["/c", "start", "", url] } : { file: "xdg-open", args: [url] };
|
|
252
|
+
const child = (0, import_child_process.spawn)(command.file, command.args, {
|
|
253
|
+
detached: true,
|
|
254
|
+
stdio: "ignore"
|
|
255
|
+
});
|
|
256
|
+
child.on("error", () => {
|
|
235
257
|
});
|
|
258
|
+
child.unref();
|
|
236
259
|
}
|
|
237
260
|
function spin(text) {
|
|
238
261
|
return (0, import_ora.default)({ text, color: "cyan" }).start();
|
|
@@ -273,11 +296,13 @@ function relativeTime(iso) {
|
|
|
273
296
|
}
|
|
274
297
|
function printError(err) {
|
|
275
298
|
if (err instanceof Error) {
|
|
276
|
-
console.error(
|
|
277
|
-
|
|
299
|
+
console.error(`
|
|
300
|
+
${sym.fail} ${c.error(err.message)}
|
|
301
|
+
`);
|
|
278
302
|
} else {
|
|
279
|
-
console.error(
|
|
280
|
-
|
|
303
|
+
console.error(`
|
|
304
|
+
${sym.fail} ${c.error(String(err))}
|
|
305
|
+
`);
|
|
281
306
|
}
|
|
282
307
|
}
|
|
283
308
|
function jsonOut(data) {
|
|
@@ -311,252 +336,302 @@ function statusBadge(status) {
|
|
|
311
336
|
|
|
312
337
|
// src/commands/login.ts
|
|
313
338
|
var CONFIG_FILE2 = (0, import_path2.join)((0, import_os2.homedir)(), ".agc", "config.json");
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
339
|
+
var CLI_SCOPES = [
|
|
340
|
+
"openid",
|
|
341
|
+
"profile",
|
|
342
|
+
"email",
|
|
343
|
+
"offline_access",
|
|
344
|
+
"activity:read",
|
|
345
|
+
"agents:create",
|
|
346
|
+
"agents:read",
|
|
347
|
+
"agents:write",
|
|
348
|
+
"agents:run",
|
|
349
|
+
"compute:read",
|
|
350
|
+
"compute:write",
|
|
351
|
+
"usage:read"
|
|
352
|
+
].join(" ");
|
|
353
|
+
async function jsonResponse(response) {
|
|
354
|
+
return response.json().catch(() => ({}));
|
|
355
|
+
}
|
|
356
|
+
async function signInWithCommons(options) {
|
|
357
|
+
step(1, 2, "Connect your Commons account");
|
|
358
|
+
const starting = spin("Creating a secure sign-in request\u2026");
|
|
359
|
+
const response = await fetch(`${options.identityUrl}/api/auth/device/code`, {
|
|
360
|
+
method: "POST",
|
|
361
|
+
headers: { "Content-Type": "application/json" },
|
|
362
|
+
body: JSON.stringify({
|
|
363
|
+
client_id: options.clientId,
|
|
364
|
+
scope: CLI_SCOPES
|
|
365
|
+
})
|
|
366
|
+
});
|
|
367
|
+
const device = await jsonResponse(response);
|
|
368
|
+
starting.stop();
|
|
369
|
+
if (!response.ok || !device.device_code || !device.user_code) {
|
|
370
|
+
throw new Error(
|
|
371
|
+
device.error_description ?? device.error ?? `Could not start Commons sign-in (${response.status}).`
|
|
372
|
+
);
|
|
373
|
+
}
|
|
374
|
+
const verificationUrl = device.verification_uri_complete ?? `${device.verification_uri ?? `${options.identityUrl}/device`}?user_code=${encodeURIComponent(device.user_code)}`;
|
|
375
|
+
console.log(`
|
|
376
|
+
${c.dim("Open this page to approve the CLI:")}`);
|
|
377
|
+
console.log(` ${c.primary(verificationUrl)}`);
|
|
378
|
+
console.log(`
|
|
379
|
+
${c.dim("One-time code")} ${c.bold(device.user_code)}
|
|
380
|
+
`);
|
|
381
|
+
if (options.openBrowser) {
|
|
382
|
+
openBrowser(verificationUrl);
|
|
383
|
+
console.log(` ${sym.arrow} ${c.dim("Your browser should open automatically.")}`);
|
|
384
|
+
} else {
|
|
385
|
+
console.log(` ${sym.arrow} ${c.dim("Open the URL in any browser.")}`);
|
|
386
|
+
}
|
|
387
|
+
step(2, 2, "Approve in your browser");
|
|
388
|
+
const waiting = spin("Waiting for approval\u2026");
|
|
389
|
+
const deadline = Date.now() + (device.expires_in ?? 600) * 1e3;
|
|
390
|
+
let intervalMs = Math.max(device.interval ?? 5, 1) * 1e3;
|
|
391
|
+
let sessionToken;
|
|
392
|
+
while (Date.now() < deadline) {
|
|
393
|
+
await new Promise((resolve2) => setTimeout(resolve2, intervalMs));
|
|
394
|
+
const tokenResponse = await fetch(
|
|
395
|
+
`${options.identityUrl}/api/auth/device/token`,
|
|
396
|
+
{
|
|
397
|
+
method: "POST",
|
|
398
|
+
headers: { "Content-Type": "application/json" },
|
|
399
|
+
body: JSON.stringify({
|
|
400
|
+
grant_type: "urn:ietf:params:oauth:grant-type:device_code",
|
|
401
|
+
device_code: device.device_code,
|
|
402
|
+
client_id: options.clientId
|
|
403
|
+
})
|
|
404
|
+
}
|
|
405
|
+
);
|
|
406
|
+
const token = await jsonResponse(tokenResponse);
|
|
407
|
+
if (tokenResponse.ok && token.access_token) {
|
|
408
|
+
sessionToken = token.access_token;
|
|
409
|
+
break;
|
|
410
|
+
}
|
|
411
|
+
if (token.error === "slow_down") {
|
|
412
|
+
intervalMs += 1e3;
|
|
413
|
+
continue;
|
|
414
|
+
}
|
|
415
|
+
if (token.error === "authorization_pending") continue;
|
|
416
|
+
waiting.stop();
|
|
417
|
+
throw new Error(
|
|
418
|
+
token.error_description ?? token.error ?? "Commons sign-in failed."
|
|
419
|
+
);
|
|
420
|
+
}
|
|
421
|
+
waiting.stop();
|
|
422
|
+
if (!sessionToken) {
|
|
423
|
+
throw new Error("The sign-in request expired before it was approved.");
|
|
424
|
+
}
|
|
425
|
+
saveConfig({
|
|
426
|
+
apiUrl: options.apiUrl,
|
|
427
|
+
identityUrl: options.identityUrl,
|
|
428
|
+
identityClientId: options.clientId,
|
|
429
|
+
sessionToken,
|
|
430
|
+
accessToken: void 0,
|
|
431
|
+
accessTokenExpiresAt: void 0,
|
|
432
|
+
apiKey: void 0
|
|
433
|
+
});
|
|
434
|
+
const authenticated = await ensureAccessToken();
|
|
435
|
+
const identity = authenticated.userEmail ?? authenticated.userName ?? authenticated.userId ?? "Commons user";
|
|
436
|
+
console.log(`
|
|
437
|
+
${sym.ok} ${c.success("Signed in")} ${c.bold(identity)}`);
|
|
438
|
+
if (authenticated.workspaceId) {
|
|
439
|
+
console.log(
|
|
440
|
+
` ${sym.ok} ${c.dim("Workspace")} ${c.id(authenticated.workspaceId)}`
|
|
441
|
+
);
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
async function useApiKey(options) {
|
|
445
|
+
step(1, 1, "Verify API key");
|
|
446
|
+
const checking = spin("Checking credentials\u2026");
|
|
447
|
+
try {
|
|
448
|
+
const { CommonsClient: CommonsClient2 } = await import("@agent-commons/sdk");
|
|
449
|
+
const client = new CommonsClient2({
|
|
450
|
+
baseUrl: options.apiUrl,
|
|
451
|
+
apiKey: options.apiKey
|
|
320
452
|
});
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
453
|
+
const principal = await client.auth.me();
|
|
454
|
+
const initiator = options.initiator ?? (principal.principalType === "user" ? principal.principalId ?? void 0 : void 0);
|
|
455
|
+
saveConfig({
|
|
456
|
+
apiUrl: options.apiUrl,
|
|
457
|
+
apiKey: options.apiKey,
|
|
458
|
+
initiator,
|
|
459
|
+
sessionToken: void 0,
|
|
460
|
+
accessToken: void 0,
|
|
461
|
+
accessTokenExpiresAt: void 0,
|
|
462
|
+
userId: initiator
|
|
463
|
+
});
|
|
464
|
+
checking.stop();
|
|
465
|
+
console.log(`
|
|
466
|
+
${sym.ok} ${c.success("API key verified")}`);
|
|
467
|
+
if (principal.principalId) {
|
|
468
|
+
console.log(
|
|
469
|
+
` ${sym.ok} ${c.dim("Principal")} ${c.id(principal.principalId)}`
|
|
470
|
+
);
|
|
334
471
|
}
|
|
335
|
-
})
|
|
472
|
+
} catch (error) {
|
|
473
|
+
checking.stop();
|
|
474
|
+
throw error;
|
|
475
|
+
}
|
|
336
476
|
}
|
|
337
477
|
function loginCommand() {
|
|
338
|
-
|
|
339
|
-
cmd.option("--api-url <url>", "API base URL", DEFAULT_API_URL).option("--identity-url <url>", "Commons Identity URL", DEFAULT_IDENTITY_URL).option("--api-key <key>", "API key (or set AGC_API_KEY env var)").option("--initiator <id>", "User/initiator ID (advanced \u2014 usually auto-detected)").action(async (opts) => {
|
|
478
|
+
return new import_commander.Command("login").description("Sign in with your Commons account").option("--api-url <url>", "Use a custom Agent Commons API endpoint").option("--identity-url <url>", "Use a custom Commons Identity endpoint").option("--client-id <id>", "Override the public CLI identity client ID").option("--no-browser", "Do not open the authorization page automatically").option("--api-key <key>", "Use a project API key for automation").option("--initiator <id>", "Optional delegated principal for compatible keys").action(async (opts) => {
|
|
340
479
|
try {
|
|
341
480
|
const current = loadConfig();
|
|
342
|
-
const
|
|
481
|
+
const firstRun = !(0, import_fs2.existsSync)(CONFIG_FILE2);
|
|
482
|
+
const apiUrl = String(opts.apiUrl ?? current.apiUrl ?? DEFAULT_API_URL).replace(
|
|
483
|
+
/\/$/,
|
|
484
|
+
""
|
|
485
|
+
);
|
|
486
|
+
const identityUrl = String(
|
|
487
|
+
opts.identityUrl ?? current.identityUrl ?? DEFAULT_IDENTITY_URL
|
|
488
|
+
).replace(/\/$/, "");
|
|
489
|
+
const clientId = String(
|
|
490
|
+
opts.clientId ?? current.identityClientId ?? DEFAULT_IDENTITY_CLIENT_ID
|
|
491
|
+
);
|
|
343
492
|
banner();
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
`);
|
|
360
|
-
} else {
|
|
361
|
-
apiUrl = DEFAULT_API_URL;
|
|
362
|
-
}
|
|
363
|
-
const appUrl = apiUrl.includes("localhost") ? "http://localhost:3000" : DEFAULT_APP_URL;
|
|
364
|
-
const apiKeysUrl = `${appUrl}/settings/api-keys`;
|
|
365
|
-
if (!opts.apiKey) {
|
|
366
|
-
step(1, 1, "Commons account");
|
|
367
|
-
const identityUrl = String(opts.identityUrl).replace(/\/$/, "");
|
|
368
|
-
const clientId = DEFAULT_IDENTITY_CLIENT_ID;
|
|
369
|
-
const deviceResponse = await fetch(`${identityUrl}/api/auth/device/code`, {
|
|
370
|
-
method: "POST",
|
|
371
|
-
headers: { "Content-Type": "application/json" },
|
|
372
|
-
body: JSON.stringify({
|
|
373
|
-
client_id: clientId,
|
|
374
|
-
scope: "openid profile email offline_access agents:read agents:write agents:run compute:read compute:write activity:read usage:read"
|
|
375
|
-
})
|
|
493
|
+
console.log(
|
|
494
|
+
c.bold(
|
|
495
|
+
firstRun ? " Welcome \u2014 let\u2019s connect your Agent Commons account." : " Sign in to Agent Commons"
|
|
496
|
+
)
|
|
497
|
+
);
|
|
498
|
+
console.log(
|
|
499
|
+
c.dim(
|
|
500
|
+
opts.apiKey ? " API-key mode is intended for automation and CI.\n" : " A browser approval keeps passwords and API keys out of your terminal.\n"
|
|
501
|
+
)
|
|
502
|
+
);
|
|
503
|
+
if (opts.apiKey) {
|
|
504
|
+
await useApiKey({
|
|
505
|
+
apiUrl,
|
|
506
|
+
apiKey: String(opts.apiKey),
|
|
507
|
+
initiator: opts.initiator
|
|
376
508
|
});
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
throw new Error(device.error_description || "Could not start Commons login.");
|
|
380
|
-
}
|
|
381
|
-
const verificationUrl = device.verification_uri_complete ?? `${identityUrl}/device?user_code=${encodeURIComponent(device.user_code)}`;
|
|
382
|
-
console.log(` ${c.dim("Authorize this CLI in your browser:")}`);
|
|
383
|
-
console.log(` ${c.primary(verificationUrl)}`);
|
|
384
|
-
console.log(` ${c.dim("Code:")} ${c.bold(device.user_code)}
|
|
385
|
-
`);
|
|
386
|
-
openBrowser(verificationUrl);
|
|
387
|
-
const deadline = Date.now() + (device.expires_in ?? 600) * 1e3;
|
|
388
|
-
let intervalMs = Math.max(device.interval ?? 5, 1) * 1e3;
|
|
389
|
-
let sessionToken;
|
|
390
|
-
while (Date.now() < deadline) {
|
|
391
|
-
await new Promise((resolve2) => setTimeout(resolve2, intervalMs));
|
|
392
|
-
const tokenResponse = await fetch(`${identityUrl}/api/auth/device/token`, {
|
|
393
|
-
method: "POST",
|
|
394
|
-
headers: { "Content-Type": "application/json" },
|
|
395
|
-
body: JSON.stringify({
|
|
396
|
-
grant_type: "urn:ietf:params:oauth:grant-type:device_code",
|
|
397
|
-
device_code: device.device_code,
|
|
398
|
-
client_id: clientId
|
|
399
|
-
})
|
|
400
|
-
});
|
|
401
|
-
const token = await tokenResponse.json();
|
|
402
|
-
if (tokenResponse.ok && token.access_token) {
|
|
403
|
-
sessionToken = token.access_token;
|
|
404
|
-
break;
|
|
405
|
-
}
|
|
406
|
-
if (token.error === "slow_down") {
|
|
407
|
-
intervalMs += 1e3;
|
|
408
|
-
continue;
|
|
409
|
-
}
|
|
410
|
-
if (token.error === "authorization_pending") continue;
|
|
411
|
-
throw new Error(token.error_description || token.error || "Commons login failed.");
|
|
412
|
-
}
|
|
413
|
-
if (!sessionToken) throw new Error("Commons login expired before approval.");
|
|
414
|
-
saveConfig({
|
|
509
|
+
} else {
|
|
510
|
+
await signInWithCommons({
|
|
415
511
|
apiUrl,
|
|
416
512
|
identityUrl,
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
accessToken: void 0,
|
|
420
|
-
accessTokenExpiresAt: void 0,
|
|
421
|
-
apiKey: void 0
|
|
513
|
+
clientId,
|
|
514
|
+
openBrowser: opts.browser !== false
|
|
422
515
|
});
|
|
423
|
-
const authenticated = await ensureAccessToken();
|
|
424
|
-
console.log(
|
|
425
|
-
` ${sym.ok} ${c.success("Signed in")} as ${c.id(authenticated.userId ?? "Commons user")}`
|
|
426
|
-
);
|
|
427
|
-
console.log(`
|
|
428
|
-
${sym.ok} ${c.success("All set!")} Credentials saved to ${c.dim("~/.agc/config.json")}
|
|
429
|
-
`);
|
|
430
|
-
return;
|
|
431
|
-
}
|
|
432
|
-
step(1, 1, "Legacy API Key");
|
|
433
|
-
let apiKey = opts.apiKey;
|
|
434
|
-
if (!apiKey) {
|
|
435
|
-
console.log(` ${c.dim("You'll need an API key from your Agent Commons account.")}`);
|
|
436
|
-
console.log(` ${c.dim("We'll open the API Keys page in your browser.")}
|
|
437
|
-
`);
|
|
438
|
-
console.log(` ${c.dim("On that page:")}`);
|
|
439
|
-
console.log(` ${sym.bullet} ${c.dim("Click")} ${c.bold('"Generate new key"')}`);
|
|
440
|
-
console.log(` ${sym.bullet} ${c.dim("Copy the key (it starts with")} ${c.bold("sk-ac-\u2026")}${c.dim(")")}`);
|
|
441
|
-
console.log(` ${sym.bullet} ${c.dim("Paste it here when prompted")}
|
|
442
|
-
`);
|
|
443
|
-
const openNow = await prompt(` ${c.dim("Open browser now? [Y/n]:")} `);
|
|
444
|
-
if (!openNow || openNow.toLowerCase() !== "n") {
|
|
445
|
-
openBrowser(apiKeysUrl);
|
|
446
|
-
console.log(` ${sym.ok} ${c.dim("Opened:")} ${c.primary(apiKeysUrl)}
|
|
447
|
-
`);
|
|
448
|
-
} else {
|
|
449
|
-
console.log(` ${c.dim("You can open it manually:")} ${c.primary(apiKeysUrl)}
|
|
450
|
-
`);
|
|
451
|
-
}
|
|
452
|
-
console.log(c.dim(" Paste your API key below (input is hidden):"));
|
|
453
|
-
apiKey = await prompt(` ${c.dim("API Key:")} `, true);
|
|
454
|
-
if (!apiKey) apiKey = current.apiKey;
|
|
455
|
-
}
|
|
456
|
-
if (!apiKey) {
|
|
457
|
-
console.log(`
|
|
458
|
-
${c.warn("\u26A0")} No API key provided \u2014 set one later with ${c.bold("agc config set apiKey <key>")}`);
|
|
459
|
-
} else {
|
|
460
|
-
console.log(` ${sym.ok} ${c.dim("Key saved:")} ****${apiKey.slice(-4)}`);
|
|
461
|
-
}
|
|
462
|
-
let initiator = opts.initiator ?? current.initiator;
|
|
463
|
-
if (!initiator && apiKey) {
|
|
464
|
-
try {
|
|
465
|
-
const { CommonsClient: CommonsClient2 } = await import("@agent-commons/sdk");
|
|
466
|
-
const client = new CommonsClient2({ baseUrl: apiUrl, apiKey });
|
|
467
|
-
const me = await client.auth.me();
|
|
468
|
-
if (me?.principalId && me.principalType === "user") {
|
|
469
|
-
initiator = me.principalId;
|
|
470
|
-
console.log(` ${sym.ok} ${c.dim("Identity detected:")} ${c.id(initiator.slice(0, 10) + "\u2026" + initiator.slice(-6))}`);
|
|
471
|
-
}
|
|
472
|
-
} catch {
|
|
473
|
-
}
|
|
474
516
|
}
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
${sym.ok} ${c.success("
|
|
478
|
-
|
|
479
|
-
${c.dim("
|
|
480
|
-
console.log(
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
517
|
+
console.log(
|
|
518
|
+
`
|
|
519
|
+
${sym.ok} ${c.success("Ready.")} ${c.dim("Credentials are stored with user-only permissions.")}`
|
|
520
|
+
);
|
|
521
|
+
console.log(` ${sym.arrow} ${c.bold("agc")} ${c.dim("open the command center")}`);
|
|
522
|
+
console.log(
|
|
523
|
+
` ${sym.arrow} ${c.bold("agc agents list")} ${c.dim("list your agents")}`
|
|
524
|
+
);
|
|
525
|
+
console.log(
|
|
526
|
+
` ${sym.arrow} ${c.bold("agc chat")} ${c.dim("start a conversation")}
|
|
527
|
+
`
|
|
528
|
+
);
|
|
529
|
+
} catch (error) {
|
|
530
|
+
printError(error);
|
|
531
|
+
process.exitCode = 1;
|
|
487
532
|
}
|
|
488
533
|
});
|
|
489
|
-
return cmd;
|
|
490
534
|
}
|
|
491
535
|
function logoutCommand() {
|
|
492
|
-
return new import_commander.Command("logout").description("
|
|
536
|
+
return new import_commander.Command("logout").description("Sign out and clear locally stored credentials").action(() => {
|
|
493
537
|
clearConfig();
|
|
494
|
-
console.log(
|
|
538
|
+
console.log(`
|
|
539
|
+
${sym.ok} Signed out. Local credentials were cleared.
|
|
540
|
+
`);
|
|
495
541
|
});
|
|
496
542
|
}
|
|
497
543
|
function whoamiCommand() {
|
|
498
|
-
return new import_commander.Command("whoami").description("Show
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
544
|
+
return new import_commander.Command("whoami").description("Show the active identity and verify API access").option("--json", "Output as JSON").action(async (opts) => {
|
|
545
|
+
try {
|
|
546
|
+
const cfg = await ensureAccessToken();
|
|
547
|
+
const authenticated = Boolean(
|
|
548
|
+
cfg.sessionToken || cfg.accessToken || cfg.apiKey
|
|
549
|
+
);
|
|
550
|
+
let principal;
|
|
551
|
+
if (authenticated) principal = await makeClient().auth.me();
|
|
552
|
+
const output = {
|
|
502
553
|
apiUrl: cfg.apiUrl,
|
|
503
554
|
identityUrl: cfg.identityUrl,
|
|
504
|
-
userId: cfg.userId ?? cfg.initiator,
|
|
555
|
+
userId: cfg.userId ?? cfg.initiator ?? principal?.principalId,
|
|
556
|
+
email: cfg.userEmail,
|
|
557
|
+
name: cfg.userName,
|
|
505
558
|
workspaceId: cfg.workspaceId,
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
["API URL", cfg.apiUrl],
|
|
514
|
-
["Identity", cfg.userId ?? cfg.initiator ?? c.dim("(not set)")],
|
|
515
|
-
["Workspace", cfg.workspaceId ?? c.dim("(not set)")],
|
|
516
|
-
["Auth", cfg.sessionToken ? "Commons account" : cfg.apiKey ? "Legacy API key" : c.dim("(not set)")],
|
|
517
|
-
["Agent ID", cfg.defaultAgentId ?? c.dim("(not set)")]
|
|
518
|
-
]);
|
|
519
|
-
try {
|
|
520
|
-
const client = makeClient();
|
|
521
|
-
if (cfg.initiator) {
|
|
522
|
-
await client.agents.list(cfg.initiator);
|
|
523
|
-
console.log(`
|
|
524
|
-
${sym.ok} ${c.success("Connected")} to ${cfg.apiUrl}`);
|
|
525
|
-
} else {
|
|
526
|
-
console.log(`
|
|
527
|
-
${c.warn("\u26A0")} Set an initiator to verify connectivity.`);
|
|
559
|
+
principalType: principal?.principalType,
|
|
560
|
+
authMode: cfg.sessionToken ? "commons-account" : cfg.apiKey ? "api-key" : cfg.accessToken ? "access-token" : "none",
|
|
561
|
+
authenticated
|
|
562
|
+
};
|
|
563
|
+
if (opts.json) {
|
|
564
|
+
console.log(JSON.stringify(output, null, 2));
|
|
565
|
+
return;
|
|
528
566
|
}
|
|
529
|
-
} catch (err) {
|
|
530
567
|
console.log(`
|
|
531
|
-
${
|
|
568
|
+
${c.bold("Identity")}`);
|
|
569
|
+
detail([
|
|
570
|
+
["Account", cfg.userEmail ?? cfg.userName ?? c.dim("(not available)")],
|
|
571
|
+
["User ID", output.userId ?? c.dim("(not available)")],
|
|
572
|
+
["Workspace", cfg.workspaceId ?? c.dim("(not available)")],
|
|
573
|
+
["Auth", output.authMode],
|
|
574
|
+
["API", cfg.apiUrl],
|
|
575
|
+
["Default agent", cfg.defaultAgentId ?? c.dim("(not set)")]
|
|
576
|
+
]);
|
|
577
|
+
console.log(
|
|
578
|
+
authenticated ? `
|
|
579
|
+
${sym.ok} ${c.success("Authenticated and connected")}
|
|
580
|
+
` : `
|
|
581
|
+
${c.warn("\u25CB")} Not signed in. Run ${c.bold("agc login")}.
|
|
582
|
+
`
|
|
583
|
+
);
|
|
584
|
+
} catch (error) {
|
|
585
|
+
printError(error);
|
|
586
|
+
process.exitCode = 1;
|
|
532
587
|
}
|
|
533
588
|
});
|
|
534
589
|
}
|
|
535
590
|
function configCommand() {
|
|
536
|
-
const
|
|
537
|
-
|
|
538
|
-
|
|
591
|
+
const command = new import_commander.Command("config").description(
|
|
592
|
+
"Inspect or update CLI preferences"
|
|
593
|
+
);
|
|
594
|
+
const allowed = [
|
|
595
|
+
"apiUrl",
|
|
596
|
+
"identityUrl",
|
|
597
|
+
"apiKey",
|
|
598
|
+
"initiator",
|
|
599
|
+
"defaultAgentId"
|
|
600
|
+
];
|
|
601
|
+
command.command("set <key> <value>").description(`Set a preference (${allowed.join(", ")})`).action((key, value) => {
|
|
539
602
|
if (!allowed.includes(key)) {
|
|
540
|
-
console.error(
|
|
541
|
-
|
|
603
|
+
console.error(
|
|
604
|
+
c.error(`Unknown key "${key}". Allowed: ${allowed.join(", ")}`)
|
|
605
|
+
);
|
|
606
|
+
process.exitCode = 1;
|
|
607
|
+
return;
|
|
542
608
|
}
|
|
543
609
|
saveConfig({ [key]: value });
|
|
544
|
-
console.log(
|
|
610
|
+
console.log(
|
|
611
|
+
`${sym.ok} ${key} = ${key === "apiKey" ? `****${value.slice(-4)}` : value}`
|
|
612
|
+
);
|
|
545
613
|
});
|
|
546
|
-
|
|
614
|
+
command.command("get [key]").description("Show one preference or the complete non-secret configuration").action((key) => {
|
|
547
615
|
const cfg = loadConfig();
|
|
548
616
|
if (key) {
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
]);
|
|
617
|
+
if (["apiKey", "sessionToken", "accessToken"].includes(key)) {
|
|
618
|
+
const value = cfg[key];
|
|
619
|
+
console.log(value ? `****${value.slice(-4)}` : c.dim("(not set)"));
|
|
620
|
+
return;
|
|
621
|
+
}
|
|
622
|
+
console.log(String(cfg[key] ?? c.dim("(not set)")));
|
|
623
|
+
return;
|
|
557
624
|
}
|
|
625
|
+
detail([
|
|
626
|
+
["apiUrl", cfg.apiUrl],
|
|
627
|
+
["identityUrl", cfg.identityUrl],
|
|
628
|
+
["user", cfg.userEmail ?? cfg.userId ?? cfg.initiator ?? ""],
|
|
629
|
+
["workspaceId", cfg.workspaceId ?? ""],
|
|
630
|
+
["auth", cfg.sessionToken ? "Commons account" : cfg.apiKey ? "API key" : ""],
|
|
631
|
+
["defaultAgentId", cfg.defaultAgentId ?? ""]
|
|
632
|
+
]);
|
|
558
633
|
});
|
|
559
|
-
return
|
|
634
|
+
return command;
|
|
560
635
|
}
|
|
561
636
|
|
|
562
637
|
// src/commands/agents.ts
|
|
@@ -577,10 +652,11 @@ function agentsCommand() {
|
|
|
577
652
|
agents.map((a) => ({
|
|
578
653
|
ID: a.agentId.slice(0, 8) + "\u2026",
|
|
579
654
|
Name: a.name,
|
|
655
|
+
Runtime: a.runtimeType ?? "native",
|
|
580
656
|
Model: `${a.modelProvider}/${a.modelId}`,
|
|
581
657
|
Created: relativeTime(a.createdAt)
|
|
582
658
|
})),
|
|
583
|
-
["ID", "Name", "Model", "Created"]
|
|
659
|
+
["ID", "Name", "Runtime", "Model", "Created"]
|
|
584
660
|
);
|
|
585
661
|
} catch (err) {
|
|
586
662
|
spinner.stop();
|
|
@@ -588,11 +664,11 @@ function agentsCommand() {
|
|
|
588
664
|
process.exit(1);
|
|
589
665
|
}
|
|
590
666
|
});
|
|
591
|
-
cmd.command("get <agentId>").description("Show details for an agent").option("--json", "Output as JSON").action(async (
|
|
667
|
+
cmd.command("get <agentId>").description("Show details for an agent").option("--json", "Output as JSON").action(async (agentId2, opts) => {
|
|
592
668
|
const spinner = spin("Fetching agent\u2026");
|
|
593
669
|
try {
|
|
594
670
|
const client = makeClient();
|
|
595
|
-
const res = await client.agents.get(
|
|
671
|
+
const res = await client.agents.get(agentId2);
|
|
596
672
|
const agent = res?.data ?? res;
|
|
597
673
|
spinner.stop();
|
|
598
674
|
if (opts.json) return jsonOut(agent);
|
|
@@ -600,8 +676,15 @@ function agentsCommand() {
|
|
|
600
676
|
detail([
|
|
601
677
|
["Agent ID", c.id(agent.agentId)],
|
|
602
678
|
["Provider", `${agent.modelProvider} / ${agent.modelId}`],
|
|
679
|
+
["Runtime", agent.runtimeType ?? "native"],
|
|
680
|
+
["Runtime status", agent.runtimeStatus ?? "ready"],
|
|
603
681
|
["Instructions", agent.instructions?.slice(0, 80) ?? c.dim("(none)")],
|
|
604
|
-
[
|
|
682
|
+
[
|
|
683
|
+
"Tools",
|
|
684
|
+
[...agent.commonTools ?? [], ...agent.externalTools ?? []].join(
|
|
685
|
+
", "
|
|
686
|
+
) || c.dim("(none)")
|
|
687
|
+
],
|
|
605
688
|
["Created", relativeTime(agent.createdAt)]
|
|
606
689
|
]);
|
|
607
690
|
} catch (err) {
|
|
@@ -610,7 +693,18 @@ function agentsCommand() {
|
|
|
610
693
|
process.exit(1);
|
|
611
694
|
}
|
|
612
695
|
});
|
|
613
|
-
cmd.command("create").description("Create a new agent").requiredOption("--name <name>", "Agent name").option("--instructions <text>", "System instructions").option(
|
|
696
|
+
cmd.command("create").description("Create a new agent").requiredOption("--name <name>", "Agent name").option("--instructions <text>", "System instructions").option(
|
|
697
|
+
"--provider <provider>",
|
|
698
|
+
"Model provider (openai|anthropic|google|groq|openrouter|xai|ollama|custom)",
|
|
699
|
+
"openai"
|
|
700
|
+
).option("--model <id>", "Model ID", "gpt-5.4-mini").option("--model-api-key <key>", "Provider API key (BYOK)").option(
|
|
701
|
+
"--model-base-url <url>",
|
|
702
|
+
"Base URL for custom or local OpenAI-compatible providers"
|
|
703
|
+
).option(
|
|
704
|
+
"--runtime <runtime>",
|
|
705
|
+
"Agent runtime (native|openclaw|hermes|custom)",
|
|
706
|
+
"native"
|
|
707
|
+
).option("--json", "Output as JSON").action(async (opts) => {
|
|
614
708
|
const cfg = loadConfig();
|
|
615
709
|
if (!cfg.initiator) {
|
|
616
710
|
console.error(c.error("No initiator set. Run `agc login` first."));
|
|
@@ -618,6 +712,9 @@ function agentsCommand() {
|
|
|
618
712
|
}
|
|
619
713
|
const spinner = spin("Creating agent\u2026");
|
|
620
714
|
try {
|
|
715
|
+
if (!["native", "openclaw", "hermes", "custom"].includes(opts.runtime)) {
|
|
716
|
+
throw new Error(`Unsupported runtime "${opts.runtime}"`);
|
|
717
|
+
}
|
|
621
718
|
const client = makeClient();
|
|
622
719
|
const res = await client.agents.create({
|
|
623
720
|
name: opts.name,
|
|
@@ -626,7 +723,8 @@ function agentsCommand() {
|
|
|
626
723
|
modelProvider: opts.provider,
|
|
627
724
|
modelId: opts.model,
|
|
628
725
|
modelApiKey: opts.modelApiKey,
|
|
629
|
-
modelBaseUrl: opts.modelBaseUrl
|
|
726
|
+
modelBaseUrl: opts.modelBaseUrl,
|
|
727
|
+
runtimeType: opts.runtime
|
|
630
728
|
});
|
|
631
729
|
const agent = res?.data ?? res;
|
|
632
730
|
spinner.stop();
|
|
@@ -636,15 +734,57 @@ ${sym.ok} Agent created`);
|
|
|
636
734
|
detail([
|
|
637
735
|
["Agent ID", c.id(agent.agentId)],
|
|
638
736
|
["Name", agent.name],
|
|
639
|
-
["Model", `${agent.modelProvider}/${agent.modelId}`]
|
|
737
|
+
["Model", `${agent.modelProvider}/${agent.modelId}`],
|
|
738
|
+
["Runtime", agent.runtimeType ?? opts.runtime]
|
|
739
|
+
]);
|
|
740
|
+
console.log(
|
|
741
|
+
c.dim("\n Tip: agc config set defaultAgentId " + agent.agentId)
|
|
742
|
+
);
|
|
743
|
+
} catch (err) {
|
|
744
|
+
spinner.stop();
|
|
745
|
+
printError(err);
|
|
746
|
+
process.exit(1);
|
|
747
|
+
}
|
|
748
|
+
});
|
|
749
|
+
const runtime = cmd.command("runtime").description("Manage an agent runtime");
|
|
750
|
+
runtime.command("status <agentId>").description("Show managed runtime status and capabilities").option("--json", "Output as JSON").action(async (agentId2, opts) => {
|
|
751
|
+
const spinner = spin("Fetching runtime status\u2026");
|
|
752
|
+
try {
|
|
753
|
+
const result = await makeClient().agents.getRuntime(agentId2);
|
|
754
|
+
spinner.stop();
|
|
755
|
+
if (opts.json) return jsonOut(result.data);
|
|
756
|
+
detail([
|
|
757
|
+
["Runtime", result.data.runtimeType],
|
|
758
|
+
["Status", result.data.status],
|
|
759
|
+
["Managed", result.data.managed ? "yes" : "no"],
|
|
760
|
+
["Computer", result.data.computer?.computerId ?? c.dim("(none)")]
|
|
640
761
|
]);
|
|
641
|
-
console.log(c.dim("\n Tip: agc config set defaultAgentId " + agent.agentId));
|
|
642
762
|
} catch (err) {
|
|
643
763
|
spinner.stop();
|
|
644
764
|
printError(err);
|
|
645
765
|
process.exit(1);
|
|
646
766
|
}
|
|
647
767
|
});
|
|
768
|
+
for (const action of ["deploy", "restart", "sleep"]) {
|
|
769
|
+
runtime.command(`${action} <agentId>`).description(
|
|
770
|
+
`${action[0].toUpperCase()}${action.slice(1)} the managed agent runtime`
|
|
771
|
+
).action(async (agentId2) => {
|
|
772
|
+
const spinner = spin(
|
|
773
|
+
`${action[0].toUpperCase()}${action.slice(1)}ing runtime\u2026`
|
|
774
|
+
);
|
|
775
|
+
try {
|
|
776
|
+
const client = makeClient();
|
|
777
|
+
const result = action === "deploy" ? await client.agents.deployRuntime(agentId2) : action === "restart" ? await client.agents.restartRuntime(agentId2) : await client.agents.sleepRuntime(agentId2);
|
|
778
|
+
spinner.stop();
|
|
779
|
+
console.log(`
|
|
780
|
+
${sym.ok} Runtime ${result.data.status}`);
|
|
781
|
+
} catch (err) {
|
|
782
|
+
spinner.stop();
|
|
783
|
+
printError(err);
|
|
784
|
+
process.exit(1);
|
|
785
|
+
}
|
|
786
|
+
});
|
|
787
|
+
}
|
|
648
788
|
const autonomy = cmd.command("autonomy").description("Manage agent heartbeat");
|
|
649
789
|
autonomy.command("status").description("Show autonomy status for an agent").requiredOption("--agent <agentId>", "Agent ID").option("--json", "Output as JSON").action(async (opts) => {
|
|
650
790
|
const client = makeClient();
|
|
@@ -660,8 +800,14 @@ ${c.bold("Heartbeat Status")}`);
|
|
|
660
800
|
["Enabled", s.enabled ? c.bold("yes") : "no"],
|
|
661
801
|
["Interval", s.intervalSec ? `${s.intervalSec}s` : "n/a"],
|
|
662
802
|
["Armed", s.isArmed ? c.bold("yes") : "no"],
|
|
663
|
-
[
|
|
664
|
-
|
|
803
|
+
[
|
|
804
|
+
"Last beat",
|
|
805
|
+
s.lastBeatAt ? new Date(s.lastBeatAt).toLocaleString() : "never"
|
|
806
|
+
],
|
|
807
|
+
[
|
|
808
|
+
"Next beat",
|
|
809
|
+
s.nextBeatAt ? new Date(s.nextBeatAt).toLocaleString() : "n/a"
|
|
810
|
+
]
|
|
665
811
|
]);
|
|
666
812
|
} catch (err) {
|
|
667
813
|
spinner.stop();
|
|
@@ -669,7 +815,11 @@ ${c.bold("Heartbeat Status")}`);
|
|
|
669
815
|
process.exit(1);
|
|
670
816
|
}
|
|
671
817
|
});
|
|
672
|
-
autonomy.command("enable").description("Enable heartbeat for an agent").requiredOption("--agent <agentId>", "Agent ID").option(
|
|
818
|
+
autonomy.command("enable").description("Enable heartbeat for an agent").requiredOption("--agent <agentId>", "Agent ID").option(
|
|
819
|
+
"--interval <seconds>",
|
|
820
|
+
"Heartbeat interval in seconds (min 30)",
|
|
821
|
+
"300"
|
|
822
|
+
).action(async (opts) => {
|
|
673
823
|
const client = makeClient();
|
|
674
824
|
const spinner = spin("Enabling autonomy\u2026");
|
|
675
825
|
try {
|
|
@@ -678,8 +828,10 @@ ${c.bold("Heartbeat Status")}`);
|
|
|
678
828
|
intervalSec: parseInt(opts.interval, 10)
|
|
679
829
|
});
|
|
680
830
|
spinner.stop();
|
|
681
|
-
console.log(
|
|
682
|
-
|
|
831
|
+
console.log(
|
|
832
|
+
`
|
|
833
|
+
${sym.ok} Autonomy enabled for agent ${c.id(opts.agent)}`
|
|
834
|
+
);
|
|
683
835
|
console.log(c.dim(` Heartbeat every ${opts.interval}s`));
|
|
684
836
|
} catch (err) {
|
|
685
837
|
spinner.stop();
|
|
@@ -693,8 +845,10 @@ ${sym.ok} Autonomy enabled for agent ${c.id(opts.agent)}`);
|
|
|
693
845
|
try {
|
|
694
846
|
await client.agents.setAutonomy(opts.agent, { enabled: false });
|
|
695
847
|
spinner.stop();
|
|
696
|
-
console.log(
|
|
697
|
-
|
|
848
|
+
console.log(
|
|
849
|
+
`
|
|
850
|
+
${sym.ok} Autonomy disabled for agent ${c.id(opts.agent)}`
|
|
851
|
+
);
|
|
698
852
|
} catch (err) {
|
|
699
853
|
spinner.stop();
|
|
700
854
|
printError(err);
|
|
@@ -707,8 +861,10 @@ ${sym.ok} Autonomy disabled for agent ${c.id(opts.agent)}`);
|
|
|
707
861
|
try {
|
|
708
862
|
await client.agents.triggerHeartbeat(opts.agent);
|
|
709
863
|
spinner.stop();
|
|
710
|
-
console.log(
|
|
711
|
-
|
|
864
|
+
console.log(
|
|
865
|
+
`
|
|
866
|
+
${sym.ok} Heartbeat triggered for agent ${c.id(opts.agent)}`
|
|
867
|
+
);
|
|
712
868
|
} catch (err) {
|
|
713
869
|
spinner.stop();
|
|
714
870
|
printError(err);
|
|
@@ -731,12 +887,12 @@ function sessionsCommand() {
|
|
|
731
887
|
const spinner = spin("Fetching sessions\u2026");
|
|
732
888
|
try {
|
|
733
889
|
const client = makeClient();
|
|
734
|
-
const
|
|
735
|
-
const res =
|
|
890
|
+
const agentId2 = opts.agent ?? cfg.defaultAgentId;
|
|
891
|
+
const res = agentId2 ? await client.sessions.list(agentId2, cfg.initiator) : await client.sessions.listByUser(cfg.initiator);
|
|
736
892
|
const sessions = res?.data ?? res ?? [];
|
|
737
893
|
spinner.stop();
|
|
738
894
|
if (opts.json) return jsonOut(sessions);
|
|
739
|
-
section(`Sessions (${sessions.length})${
|
|
895
|
+
section(`Sessions (${sessions.length})${agentId2 ? ` \u2014 agent ${agentId2.slice(0, 8)}\u2026` : " \u2014 all agents"}`);
|
|
740
896
|
table(
|
|
741
897
|
sessions.map((s) => ({
|
|
742
898
|
ID: s.sessionId.slice(0, 8) + "\u2026",
|
|
@@ -777,8 +933,8 @@ function sessionsCommand() {
|
|
|
777
933
|
});
|
|
778
934
|
cmd.command("create").description("Create a new session").option("--agent <agentId>", "Agent ID").option("--title <title>", "Session title").option("--model <id>", "Model ID (e.g. gpt-5.4-mini, claude-sonnet-4-6)").option("--provider <provider>", "Model provider").option("--json", "Output as JSON").action(async (opts) => {
|
|
779
935
|
const cfg = loadConfig();
|
|
780
|
-
const
|
|
781
|
-
if (!
|
|
936
|
+
const agentId2 = opts.agent ?? cfg.defaultAgentId;
|
|
937
|
+
if (!agentId2) {
|
|
782
938
|
console.error(c.error("Specify --agent <agentId> or set defaultAgentId"));
|
|
783
939
|
process.exit(1);
|
|
784
940
|
}
|
|
@@ -790,7 +946,7 @@ function sessionsCommand() {
|
|
|
790
946
|
try {
|
|
791
947
|
const client = makeClient();
|
|
792
948
|
const res = await client.sessions.create({
|
|
793
|
-
agentId,
|
|
949
|
+
agentId: agentId2,
|
|
794
950
|
initiator: cfg.initiator,
|
|
795
951
|
title: opts.title,
|
|
796
952
|
...opts.model && { model: { modelId: opts.model, provider: opts.provider } }
|
|
@@ -810,6 +966,34 @@ ${sym.ok} Session created`);
|
|
|
810
966
|
process.exit(1);
|
|
811
967
|
}
|
|
812
968
|
});
|
|
969
|
+
cmd.command("rename <sessionId> <title>").description("Rename a session").option("--json", "Output as JSON").action(async (sessionId, title, opts) => {
|
|
970
|
+
const spinner = spin("Renaming session\u2026");
|
|
971
|
+
try {
|
|
972
|
+
const result = await makeClient().sessions.rename(sessionId, title);
|
|
973
|
+
spinner.stop();
|
|
974
|
+
if (opts.json) return jsonOut(result.data);
|
|
975
|
+
console.log(`
|
|
976
|
+
${sym.ok} Session renamed to ${c.bold(result.data.title ?? title)}`);
|
|
977
|
+
} catch (err) {
|
|
978
|
+
spinner.stop();
|
|
979
|
+
printError(err);
|
|
980
|
+
process.exit(1);
|
|
981
|
+
}
|
|
982
|
+
});
|
|
983
|
+
cmd.command("delete <sessionId>").description("Delete a session").option("--json", "Output as JSON").action(async (sessionId, opts) => {
|
|
984
|
+
const spinner = spin("Deleting session\u2026");
|
|
985
|
+
try {
|
|
986
|
+
const result = await makeClient().sessions.delete(sessionId);
|
|
987
|
+
spinner.stop();
|
|
988
|
+
if (opts.json) return jsonOut(result.data);
|
|
989
|
+
console.log(`
|
|
990
|
+
${sym.ok} Session deleted.`);
|
|
991
|
+
} catch (err) {
|
|
992
|
+
spinner.stop();
|
|
993
|
+
printError(err);
|
|
994
|
+
process.exit(1);
|
|
995
|
+
}
|
|
996
|
+
});
|
|
813
997
|
return cmd;
|
|
814
998
|
}
|
|
815
999
|
|
|
@@ -918,8 +1102,8 @@ ${sym.ok} Tool created`);
|
|
|
918
1102
|
});
|
|
919
1103
|
cmd.command("exec <toolName>").description("Execute a tool directly by name").option("--agent <agentId>", "Agent context for tool execution").option("--args <json>", "Tool arguments as JSON object", "{}").option("--json", "Output result as JSON").action(async (toolName, opts) => {
|
|
920
1104
|
const cfg = loadConfig();
|
|
921
|
-
const
|
|
922
|
-
if (!
|
|
1105
|
+
const agentId2 = opts.agent ?? cfg.defaultAgentId;
|
|
1106
|
+
if (!agentId2) {
|
|
923
1107
|
console.error(c.error("Specify --agent <agentId> or set defaultAgentId with `agc config set defaultAgentId <id>`"));
|
|
924
1108
|
process.exit(1);
|
|
925
1109
|
}
|
|
@@ -930,13 +1114,13 @@ ${sym.ok} Tool created`);
|
|
|
930
1114
|
console.error(c.error("--args must be valid JSON"));
|
|
931
1115
|
process.exit(1);
|
|
932
1116
|
}
|
|
933
|
-
const
|
|
1117
|
+
const prompt = `Call the tool "${toolName}" with these arguments: ${JSON.stringify(args)}. Return only the tool result, nothing else.`;
|
|
934
1118
|
const spinner = spin(`Executing ${toolName}\u2026`);
|
|
935
1119
|
try {
|
|
936
1120
|
const client = makeClient();
|
|
937
1121
|
const result = await client.run.once({
|
|
938
|
-
agentId,
|
|
939
|
-
messages: [{ role: "user", content:
|
|
1122
|
+
agentId: agentId2,
|
|
1123
|
+
messages: [{ role: "user", content: prompt }],
|
|
940
1124
|
...cfg.initiator && { initiatorId: cfg.initiator }
|
|
941
1125
|
});
|
|
942
1126
|
spinner.stop();
|
|
@@ -954,61 +1138,38 @@ ${sym.ok} ${c.label(toolName)}`);
|
|
|
954
1138
|
return cmd;
|
|
955
1139
|
}
|
|
956
1140
|
|
|
957
|
-
// src/commands/
|
|
1141
|
+
// src/commands/connections.ts
|
|
958
1142
|
var import_commander5 = require("commander");
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
const client = makeClient();
|
|
965
|
-
const template = (0, import_sdk2.buildWorkflowTemplate)(params.templateName, params.ctx);
|
|
966
|
-
const toolIds = {};
|
|
967
|
-
const createdTools = [];
|
|
968
|
-
for (const tool of template.tools) {
|
|
969
|
-
const created = await client.tools.create({
|
|
970
|
-
...tool.payload,
|
|
971
|
-
owner: params.ctx.ownerId,
|
|
972
|
-
ownerType: "user"
|
|
973
|
-
});
|
|
974
|
-
const createdTool = created?.data ?? created;
|
|
975
|
-
toolIds[tool.key] = createdTool.toolId;
|
|
976
|
-
createdTools.push(createdTool);
|
|
977
|
-
}
|
|
978
|
-
const workflow = await client.workflows.create({
|
|
979
|
-
name: template.name,
|
|
980
|
-
description: template.description,
|
|
981
|
-
ownerId: params.ctx.ownerId,
|
|
982
|
-
ownerType: "user",
|
|
983
|
-
isPublic: params.isPublic,
|
|
984
|
-
category: template.category,
|
|
985
|
-
tags: template.tags,
|
|
986
|
-
definition: template.buildDefinition(toolIds, params.ctx)
|
|
987
|
-
});
|
|
988
|
-
return { template, workflow, createdTools };
|
|
989
|
-
}
|
|
990
|
-
cmd.command("list").description("List workflows owned by the current initiator").option("--json", "Output as JSON").action(async (opts) => {
|
|
1143
|
+
function connectionsCommand() {
|
|
1144
|
+
const cmd = new import_commander5.Command("connections").description(
|
|
1145
|
+
"Manage OAuth account connections (Google Workspace, GitHub, Slack, \u2026) that agents act with"
|
|
1146
|
+
);
|
|
1147
|
+
cmd.command("list", { isDefault: true }).description("List your connected accounts").option("--json", "Output as JSON").action(async (opts) => {
|
|
991
1148
|
const cfg = loadConfig();
|
|
992
|
-
|
|
993
|
-
console.error(c.error("No initiator set. Run `agc login` first."));
|
|
994
|
-
process.exit(1);
|
|
995
|
-
}
|
|
996
|
-
const spinner = spin("Fetching workflows\u2026");
|
|
1149
|
+
const spinner = spin("Fetching connections\u2026");
|
|
997
1150
|
try {
|
|
998
1151
|
const client = makeClient();
|
|
999
|
-
const
|
|
1152
|
+
const res = await client.oauth.listConnections(
|
|
1153
|
+
cfg.initiator ? { ownerId: cfg.initiator, ownerType: "user" } : void 0
|
|
1154
|
+
);
|
|
1155
|
+
const connections = res?.connections ?? [];
|
|
1000
1156
|
spinner.stop();
|
|
1001
|
-
if (opts.json) return jsonOut(
|
|
1002
|
-
section(`
|
|
1157
|
+
if (opts.json) return jsonOut(connections);
|
|
1158
|
+
section(`Connections (${connections.length})`);
|
|
1159
|
+
if (connections.length === 0) {
|
|
1160
|
+
console.log(c.dim(" No connected accounts. Run `agc connections connect <provider>`."));
|
|
1161
|
+
return;
|
|
1162
|
+
}
|
|
1003
1163
|
table(
|
|
1004
|
-
|
|
1005
|
-
ID:
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1164
|
+
connections.map((conn) => ({
|
|
1165
|
+
ID: (conn.connectionId ?? "").slice(0, 8) + "\u2026",
|
|
1166
|
+
Provider: conn.providerDisplayName || conn.providerKey || "",
|
|
1167
|
+
Account: conn.providerUserEmail || conn.providerUserName || "",
|
|
1168
|
+
Status: conn.status ?? "",
|
|
1169
|
+
Scopes: String((conn.scopes ?? []).length),
|
|
1170
|
+
Used: conn.lastUsedAt ? relativeTime(conn.lastUsedAt) : c.dim("never")
|
|
1010
1171
|
})),
|
|
1011
|
-
["ID", "
|
|
1172
|
+
["ID", "Provider", "Account", "Status", "Scopes", "Used"]
|
|
1012
1173
|
);
|
|
1013
1174
|
} catch (err) {
|
|
1014
1175
|
spinner.stop();
|
|
@@ -1016,10 +1177,205 @@ function workflowCommand() {
|
|
|
1016
1177
|
process.exit(1);
|
|
1017
1178
|
}
|
|
1018
1179
|
});
|
|
1019
|
-
cmd.command("
|
|
1020
|
-
const
|
|
1021
|
-
|
|
1022
|
-
|
|
1180
|
+
cmd.command("providers").description("List OAuth providers available to connect").option("--json", "Output as JSON").action(async (opts) => {
|
|
1181
|
+
const spinner = spin("Fetching providers\u2026");
|
|
1182
|
+
try {
|
|
1183
|
+
const client = makeClient();
|
|
1184
|
+
const res = await client.oauth.listProviders();
|
|
1185
|
+
const providers = res?.providers ?? [];
|
|
1186
|
+
spinner.stop();
|
|
1187
|
+
if (opts.json) return jsonOut(providers);
|
|
1188
|
+
section(`Providers (${providers.length})`);
|
|
1189
|
+
table(
|
|
1190
|
+
providers.map((p) => ({
|
|
1191
|
+
Key: p.providerKey ?? "",
|
|
1192
|
+
Name: p.displayName ?? "",
|
|
1193
|
+
Active: p.isActive ? "yes" : "no"
|
|
1194
|
+
})),
|
|
1195
|
+
["Key", "Name", "Active"]
|
|
1196
|
+
);
|
|
1197
|
+
} catch (err) {
|
|
1198
|
+
spinner.stop();
|
|
1199
|
+
printError(err);
|
|
1200
|
+
process.exit(1);
|
|
1201
|
+
}
|
|
1202
|
+
});
|
|
1203
|
+
cmd.command("connect <providerKey>").description("Connect an account: prints an authorization URL to open in your browser").option("--scopes <scopes>", "Space-separated OAuth scopes to request").option("--no-browser", "Do not open the authorization URL automatically").option("--json", "Output as JSON").action(async (providerKey, opts) => {
|
|
1204
|
+
const cfg = loadConfig();
|
|
1205
|
+
if (!cfg.initiator) {
|
|
1206
|
+
console.error(c.error("No initiator set. Run `agc login` first."));
|
|
1207
|
+
process.exit(1);
|
|
1208
|
+
}
|
|
1209
|
+
const spinner = spin("Starting OAuth flow\u2026");
|
|
1210
|
+
try {
|
|
1211
|
+
const client = makeClient();
|
|
1212
|
+
const res = await client.oauth.connect({
|
|
1213
|
+
providerKey,
|
|
1214
|
+
...opts.scopes ? { scopes: String(opts.scopes).split(/\s+/).filter(Boolean) } : {}
|
|
1215
|
+
});
|
|
1216
|
+
spinner.stop();
|
|
1217
|
+
if (opts.json) return jsonOut(res);
|
|
1218
|
+
if (opts.browser !== false) openBrowser(res.authorizationUrl);
|
|
1219
|
+
console.log(`
|
|
1220
|
+
${sym.ok} Authorize the connection in your browser:`);
|
|
1221
|
+
console.log(`
|
|
1222
|
+
${c.id(res.authorizationUrl)}
|
|
1223
|
+
`);
|
|
1224
|
+
console.log(c.dim(" After approving, the connection appears in `agc connections list`."));
|
|
1225
|
+
} catch (err) {
|
|
1226
|
+
spinner.stop();
|
|
1227
|
+
printError(err);
|
|
1228
|
+
process.exit(1);
|
|
1229
|
+
}
|
|
1230
|
+
});
|
|
1231
|
+
cmd.command("get <connectionId>").description("Show a connected account").option("--json", "Output as JSON").action(async (connectionId, opts) => {
|
|
1232
|
+
const spinner = spin("Fetching connection\u2026");
|
|
1233
|
+
try {
|
|
1234
|
+
const result = await makeClient().oauth.getConnection(connectionId);
|
|
1235
|
+
spinner.stop();
|
|
1236
|
+
if (opts.json) return jsonOut(result.connection);
|
|
1237
|
+
const connection = result.connection;
|
|
1238
|
+
detail([
|
|
1239
|
+
["Connection ID", c.id(connection.connectionId)],
|
|
1240
|
+
["Provider", connection.providerDisplayName ?? connection.providerKey],
|
|
1241
|
+
["Account", connection.providerUserEmail ?? connection.providerUserName ?? ""],
|
|
1242
|
+
["Status", connection.status],
|
|
1243
|
+
["Scopes", connection.scopes.join(", ")],
|
|
1244
|
+
["Expires", connection.expiresAt ?? c.dim("(not reported)")]
|
|
1245
|
+
]);
|
|
1246
|
+
} catch (err) {
|
|
1247
|
+
spinner.stop();
|
|
1248
|
+
printError(err);
|
|
1249
|
+
process.exit(1);
|
|
1250
|
+
}
|
|
1251
|
+
});
|
|
1252
|
+
cmd.command("refresh <connectionId>").description("Refresh a connected account token").action(async (connectionId) => {
|
|
1253
|
+
const spinner = spin("Refreshing connection\u2026");
|
|
1254
|
+
try {
|
|
1255
|
+
await makeClient().oauth.refresh(connectionId);
|
|
1256
|
+
spinner.stop();
|
|
1257
|
+
console.log(`${sym.ok} Connection refreshed.`);
|
|
1258
|
+
} catch (err) {
|
|
1259
|
+
spinner.stop();
|
|
1260
|
+
printError(err);
|
|
1261
|
+
process.exit(1);
|
|
1262
|
+
}
|
|
1263
|
+
});
|
|
1264
|
+
cmd.command("rename <connectionId> <name>").description("Set a friendly name for a connected account").action(async (connectionId, name) => {
|
|
1265
|
+
const spinner = spin("Updating connection\u2026");
|
|
1266
|
+
try {
|
|
1267
|
+
await makeClient().oauth.updateConnection(connectionId, {
|
|
1268
|
+
displayName: name
|
|
1269
|
+
});
|
|
1270
|
+
spinner.stop();
|
|
1271
|
+
console.log(`${sym.ok} Connection renamed to ${c.bold(name)}.`);
|
|
1272
|
+
} catch (err) {
|
|
1273
|
+
spinner.stop();
|
|
1274
|
+
printError(err);
|
|
1275
|
+
process.exit(1);
|
|
1276
|
+
}
|
|
1277
|
+
});
|
|
1278
|
+
cmd.command("test <connectionId>").description("Check that a connection is active and its token is valid").option("--json", "Output as JSON").action(async (connectionId, opts) => {
|
|
1279
|
+
const spinner = spin("Testing connection\u2026");
|
|
1280
|
+
try {
|
|
1281
|
+
const client = makeClient();
|
|
1282
|
+
const res = await client.oauth.test(connectionId);
|
|
1283
|
+
spinner.stop();
|
|
1284
|
+
if (opts.json) return jsonOut(res);
|
|
1285
|
+
detail([
|
|
1286
|
+
["Status", res.status],
|
|
1287
|
+
["Token valid", res.accessTokenValid ? "yes" : "no"],
|
|
1288
|
+
["Account", res.providerUserEmail ?? c.dim("(unknown)")],
|
|
1289
|
+
["Last error", res.error ?? c.dim("(none)")]
|
|
1290
|
+
]);
|
|
1291
|
+
} catch (err) {
|
|
1292
|
+
spinner.stop();
|
|
1293
|
+
printError(err);
|
|
1294
|
+
process.exit(1);
|
|
1295
|
+
}
|
|
1296
|
+
});
|
|
1297
|
+
cmd.command("revoke <connectionId>").description("Revoke a connection and delete its stored tokens").action(async (connectionId) => {
|
|
1298
|
+
const spinner = spin("Revoking connection\u2026");
|
|
1299
|
+
try {
|
|
1300
|
+
const client = makeClient();
|
|
1301
|
+
await client.oauth.revoke(connectionId);
|
|
1302
|
+
spinner.stop();
|
|
1303
|
+
console.log(`${sym.ok} Connection revoked.`);
|
|
1304
|
+
} catch (err) {
|
|
1305
|
+
spinner.stop();
|
|
1306
|
+
printError(err);
|
|
1307
|
+
process.exit(1);
|
|
1308
|
+
}
|
|
1309
|
+
});
|
|
1310
|
+
return cmd;
|
|
1311
|
+
}
|
|
1312
|
+
|
|
1313
|
+
// src/commands/workflow.ts
|
|
1314
|
+
var import_commander6 = require("commander");
|
|
1315
|
+
var import_fs4 = require("fs");
|
|
1316
|
+
var import_sdk2 = require("@agent-commons/sdk");
|
|
1317
|
+
function workflowCommand() {
|
|
1318
|
+
const cmd = new import_commander6.Command("workflow").description("Run and monitor workflows").alias("wf");
|
|
1319
|
+
async function createTemplateWorkflow(params) {
|
|
1320
|
+
const client = makeClient();
|
|
1321
|
+
const template = (0, import_sdk2.buildWorkflowTemplate)(params.templateName, params.ctx);
|
|
1322
|
+
const toolIds = {};
|
|
1323
|
+
const createdTools = [];
|
|
1324
|
+
for (const tool of template.tools) {
|
|
1325
|
+
const created = await client.tools.create({
|
|
1326
|
+
...tool.payload,
|
|
1327
|
+
owner: params.ctx.ownerId,
|
|
1328
|
+
ownerType: "user"
|
|
1329
|
+
});
|
|
1330
|
+
const createdTool = created?.data ?? created;
|
|
1331
|
+
toolIds[tool.key] = createdTool.toolId;
|
|
1332
|
+
createdTools.push(createdTool);
|
|
1333
|
+
}
|
|
1334
|
+
const workflow = await client.workflows.create({
|
|
1335
|
+
name: template.name,
|
|
1336
|
+
description: template.description,
|
|
1337
|
+
ownerId: params.ctx.ownerId,
|
|
1338
|
+
ownerType: "user",
|
|
1339
|
+
isPublic: params.isPublic,
|
|
1340
|
+
category: template.category,
|
|
1341
|
+
tags: template.tags,
|
|
1342
|
+
definition: template.buildDefinition(toolIds, params.ctx)
|
|
1343
|
+
});
|
|
1344
|
+
return { template, workflow, createdTools };
|
|
1345
|
+
}
|
|
1346
|
+
cmd.command("list").description("List workflows owned by the current initiator").option("--json", "Output as JSON").action(async (opts) => {
|
|
1347
|
+
const cfg = loadConfig();
|
|
1348
|
+
if (!cfg.initiator) {
|
|
1349
|
+
console.error(c.error("No initiator set. Run `agc login` first."));
|
|
1350
|
+
process.exit(1);
|
|
1351
|
+
}
|
|
1352
|
+
const spinner = spin("Fetching workflows\u2026");
|
|
1353
|
+
try {
|
|
1354
|
+
const client = makeClient();
|
|
1355
|
+
const workflows = await client.workflows.list(cfg.initiator, "user");
|
|
1356
|
+
spinner.stop();
|
|
1357
|
+
if (opts.json) return jsonOut(workflows);
|
|
1358
|
+
section(`Workflows (${workflows.length})`);
|
|
1359
|
+
table(
|
|
1360
|
+
workflows.map((w) => ({
|
|
1361
|
+
ID: w.workflowId.slice(0, 8) + "\u2026",
|
|
1362
|
+
Name: w.name,
|
|
1363
|
+
Nodes: String((w.definition?.nodes ?? []).length),
|
|
1364
|
+
Public: w.isPublic ? "yes" : "no",
|
|
1365
|
+
Created: relativeTime(w.createdAt)
|
|
1366
|
+
})),
|
|
1367
|
+
["ID", "Name", "Nodes", "Public", "Created"]
|
|
1368
|
+
);
|
|
1369
|
+
} catch (err) {
|
|
1370
|
+
spinner.stop();
|
|
1371
|
+
printError(err);
|
|
1372
|
+
process.exit(1);
|
|
1373
|
+
}
|
|
1374
|
+
});
|
|
1375
|
+
cmd.command("create").description("Create a workflow from a JSON file").requiredOption("--file <path>", "Path to a workflow payload or definition JSON file").option("--name <name>", "Workflow name").option("--description <text>", "Workflow description").option("--public", "Make workflow public").option("--json", "Output as JSON").action(async (opts) => {
|
|
1376
|
+
const cfg = loadConfig();
|
|
1377
|
+
if (!cfg.initiator) {
|
|
1378
|
+
console.error(c.error("No initiator set. Run `agc login` first."));
|
|
1023
1379
|
process.exit(1);
|
|
1024
1380
|
}
|
|
1025
1381
|
let fileJson;
|
|
@@ -1089,8 +1445,8 @@ ${sym.ok} Workflow created`);
|
|
|
1089
1445
|
}
|
|
1090
1446
|
const templateName = templateNameRaw;
|
|
1091
1447
|
const needsAgent = templateName === "agent-research-summary" || templateName === "multi-agent-field-report";
|
|
1092
|
-
const
|
|
1093
|
-
if (needsAgent && !
|
|
1448
|
+
const agentId2 = opts.agent ?? cfg.defaultAgentId;
|
|
1449
|
+
if (needsAgent && !agentId2) {
|
|
1094
1450
|
console.error(c.error("This template requires --agent <agentId> or a configured defaultAgentId."));
|
|
1095
1451
|
process.exit(1);
|
|
1096
1452
|
}
|
|
@@ -1114,7 +1470,7 @@ ${sym.ok} Workflow created`);
|
|
|
1114
1470
|
const ctx = {
|
|
1115
1471
|
ownerId: cfg.initiator,
|
|
1116
1472
|
prefix,
|
|
1117
|
-
agentId,
|
|
1473
|
+
agentId: agentId2,
|
|
1118
1474
|
reviewerAgentId: opts.reviewerAgent,
|
|
1119
1475
|
childWorkflowId
|
|
1120
1476
|
};
|
|
@@ -1134,7 +1490,7 @@ ${sym.ok} Workflow created`);
|
|
|
1134
1490
|
}
|
|
1135
1491
|
}
|
|
1136
1492
|
execution = await makeClient().workflows.execute(result.workflow.workflowId, {
|
|
1137
|
-
agentId,
|
|
1493
|
+
agentId: agentId2,
|
|
1138
1494
|
inputData,
|
|
1139
1495
|
userId: cfg.initiator
|
|
1140
1496
|
});
|
|
@@ -1205,7 +1561,7 @@ ${sym.ok} Execution started: ${c.id(execution.executionId)}`);
|
|
|
1205
1561
|
});
|
|
1206
1562
|
cmd.command("run <workflowId>").description("Execute a workflow").option("--agent <agentId>", "Agent context").option("--session <sessionId>", "Session context").option("--input <json>", "Input data as JSON string", "{}").option("--watch", "Stream execution progress via SSE").option("--json", "Output result as JSON").action(async (workflowId, opts) => {
|
|
1207
1563
|
const cfg = loadConfig();
|
|
1208
|
-
const
|
|
1564
|
+
const agentId2 = opts.agent ?? cfg.defaultAgentId;
|
|
1209
1565
|
let inputData = {};
|
|
1210
1566
|
try {
|
|
1211
1567
|
inputData = JSON.parse(opts.input);
|
|
@@ -1217,7 +1573,7 @@ ${sym.ok} Execution started: ${c.id(execution.executionId)}`);
|
|
|
1217
1573
|
try {
|
|
1218
1574
|
const client = makeClient();
|
|
1219
1575
|
const execution = await client.workflows.execute(workflowId, {
|
|
1220
|
-
agentId,
|
|
1576
|
+
agentId: agentId2,
|
|
1221
1577
|
sessionId: opts.session,
|
|
1222
1578
|
inputData
|
|
1223
1579
|
});
|
|
@@ -1357,17 +1713,17 @@ ${c.warn("\u23F8 Awaiting approval")} at node ${c.id(e.pausedAtNode ?? "")}`);
|
|
|
1357
1713
|
}
|
|
1358
1714
|
|
|
1359
1715
|
// src/commands/task.ts
|
|
1360
|
-
var
|
|
1716
|
+
var import_commander7 = require("commander");
|
|
1361
1717
|
function taskCommand() {
|
|
1362
|
-
const cmd = new
|
|
1718
|
+
const cmd = new import_commander7.Command("task").description("Manage and execute tasks").alias("t");
|
|
1363
1719
|
cmd.command("list").description("List tasks").option("--agent <agentId>", "Filter by agent ID").option("--session <sessionId>", "Filter by session ID").option("--json", "Output as JSON").action(async (opts) => {
|
|
1364
1720
|
const cfg = loadConfig();
|
|
1365
|
-
const
|
|
1721
|
+
const agentId2 = opts.agent ?? cfg.defaultAgentId;
|
|
1366
1722
|
const spinner = spin("Fetching tasks\u2026");
|
|
1367
1723
|
try {
|
|
1368
1724
|
const client = makeClient();
|
|
1369
1725
|
const filter = {};
|
|
1370
|
-
if (
|
|
1726
|
+
if (agentId2) filter.agentId = agentId2;
|
|
1371
1727
|
if (opts.session) filter.sessionId = opts.session;
|
|
1372
1728
|
if (cfg.initiator) {
|
|
1373
1729
|
filter.ownerId = cfg.initiator;
|
|
@@ -1423,8 +1779,8 @@ function taskCommand() {
|
|
|
1423
1779
|
});
|
|
1424
1780
|
cmd.command("create").description("Create a new task").requiredOption("--title <title>", "Task title").option("--agent <agentId>", "Agent ID").option("--session <sessionId>", "Session ID").option("--workflow <workflowId>", "Workflow ID to attach").option("--input <json>", "Input data as JSON", "{}").option("--timeout <ms>", "Execution timeout in milliseconds").option("--execute", "Execute immediately after creation").option("--watch", "Stream execution progress (implies --execute)").option("--json", "Output as JSON").action(async (opts) => {
|
|
1425
1781
|
const cfg = loadConfig();
|
|
1426
|
-
const
|
|
1427
|
-
if (!
|
|
1782
|
+
const agentId2 = opts.agent ?? cfg.defaultAgentId;
|
|
1783
|
+
if (!agentId2) {
|
|
1428
1784
|
console.error(c.error("Specify --agent <agentId> or set defaultAgentId with `agc config set defaultAgentId <id>`"));
|
|
1429
1785
|
process.exit(1);
|
|
1430
1786
|
}
|
|
@@ -1440,7 +1796,7 @@ function taskCommand() {
|
|
|
1440
1796
|
const client = makeClient();
|
|
1441
1797
|
const res = await client.tasks.create({
|
|
1442
1798
|
title: opts.title,
|
|
1443
|
-
agentId,
|
|
1799
|
+
agentId: agentId2,
|
|
1444
1800
|
sessionId: opts.session,
|
|
1445
1801
|
workflowId: opts.workflow,
|
|
1446
1802
|
inputData,
|
|
@@ -1544,14 +1900,14 @@ ${sym.fail} ${c.error(event.message ?? event.type)}`);
|
|
|
1544
1900
|
}
|
|
1545
1901
|
|
|
1546
1902
|
// src/commands/run.ts
|
|
1547
|
-
var
|
|
1548
|
-
var
|
|
1903
|
+
var import_commander8 = require("commander");
|
|
1904
|
+
var readline2 = __toESM(require("readline"));
|
|
1549
1905
|
|
|
1550
1906
|
// src/local-tools.ts
|
|
1551
1907
|
var import_fs5 = require("fs");
|
|
1552
1908
|
var import_path3 = require("path");
|
|
1553
1909
|
var import_child_process2 = require("child_process");
|
|
1554
|
-
var
|
|
1910
|
+
var readline = __toESM(require("readline"));
|
|
1555
1911
|
var pdfParse = require("pdf-parse/lib/pdf-parse.js");
|
|
1556
1912
|
var managedProcesses = /* @__PURE__ */ new Map();
|
|
1557
1913
|
function capBuffer(existing, chunk, maxBytes) {
|
|
@@ -1701,11 +2057,11 @@ function extractToolCall(text) {
|
|
|
1701
2057
|
}
|
|
1702
2058
|
return null;
|
|
1703
2059
|
}
|
|
1704
|
-
function injectAgcTrailer(command, args,
|
|
2060
|
+
function injectAgcTrailer(command, args, agentId2, agentName) {
|
|
1705
2061
|
if (command !== "git") return args;
|
|
1706
2062
|
if (!args.some((a) => a === "commit")) return args;
|
|
1707
2063
|
if (args.some((a) => a.includes("Co-Authored-By: agc"))) return args;
|
|
1708
|
-
const identity = agentName ? `${agentName} (agc)` :
|
|
2064
|
+
const identity = agentName ? `${agentName} (agc)` : agentId2 ? `agc/${agentId2}` : "agc agent";
|
|
1709
2065
|
return [...args, "--trailer", `Co-Authored-By: ${identity} <agc-agent@users.noreply.github.com>`];
|
|
1710
2066
|
}
|
|
1711
2067
|
var AGC_HOOK_MARKER = "# agc-session:";
|
|
@@ -1722,7 +2078,7 @@ function findGitDir(rootDir) {
|
|
|
1722
2078
|
}
|
|
1723
2079
|
return null;
|
|
1724
2080
|
}
|
|
1725
|
-
function installGitHook(rootDir, sessionId,
|
|
2081
|
+
function installGitHook(rootDir, sessionId, agentId2, agentName) {
|
|
1726
2082
|
const gitDir = findGitDir(rootDir);
|
|
1727
2083
|
if (!gitDir) return;
|
|
1728
2084
|
const hooksDir = (0, import_path3.join)(gitDir, "hooks");
|
|
@@ -1734,7 +2090,7 @@ function installGitHook(rootDir, sessionId, agentId, agentName) {
|
|
|
1734
2090
|
(0, import_fs5.writeFileSync)(hookPath + HOOK_BACKUP_SUFFIX, existing, { mode: 493 });
|
|
1735
2091
|
}
|
|
1736
2092
|
}
|
|
1737
|
-
const identity = agentName ? `${agentName} (agc)` :
|
|
2093
|
+
const identity = agentName ? `${agentName} (agc)` : agentId2 ? `agc/${agentId2}` : "agc agent";
|
|
1738
2094
|
const trailer = `Co-Authored-By: ${identity} <agc-agent@users.noreply.github.com>`;
|
|
1739
2095
|
const chainLine = (0, import_fs5.existsSync)(hookPath + HOOK_BACKUP_SUFFIX) ? `
|
|
1740
2096
|
# chain pre-existing hook
|
|
@@ -1798,7 +2154,7 @@ async function confirm(message, config, permissionKey) {
|
|
|
1798
2154
|
if (cached === "allow") return true;
|
|
1799
2155
|
if (cached === "deny") return false;
|
|
1800
2156
|
return new Promise((resolve2) => {
|
|
1801
|
-
const rl =
|
|
2157
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
1802
2158
|
process.stdout.write(
|
|
1803
2159
|
`
|
|
1804
2160
|
\x1B[33m\u26A0\x1B[0m ${message}
|
|
@@ -2177,10 +2533,10 @@ async function runLocalTool(call, cfg) {
|
|
|
2177
2533
|
|
|
2178
2534
|
// src/commands/run.ts
|
|
2179
2535
|
function runCommand() {
|
|
2180
|
-
return new
|
|
2536
|
+
return new import_commander8.Command("run").description("Send a single prompt to an agent and stream the response").argument("<prompt>", "Prompt text to send").option("--agent <agentId>", "Agent ID").option("--session <sessionId>", "Resume an existing session by ID").option("--new-session", "Create a new session and print its ID for future use").option("--computer", "Give the agent access to its persistent cloud computer").option("--local", "Enable local file system access (with permission prompts)").option("-y, --yes", "Enable local file system access and auto-approve all operations").option("--no-stream", "Disable streaming (wait for full response)").option("--json", "Output raw event stream as JSON lines").action(async (prompt, opts) => {
|
|
2181
2537
|
const cfg = loadConfig();
|
|
2182
|
-
const
|
|
2183
|
-
if (!
|
|
2538
|
+
const agentId2 = opts.agent ?? cfg.defaultAgentId;
|
|
2539
|
+
if (!agentId2) {
|
|
2184
2540
|
console.error(c.error("Specify --agent <agentId> or set defaultAgentId with `agc config set defaultAgentId <id>`"));
|
|
2185
2541
|
process.exit(1);
|
|
2186
2542
|
}
|
|
@@ -2205,7 +2561,7 @@ function runCommand() {
|
|
|
2205
2561
|
const spinner = spin("Creating session\u2026");
|
|
2206
2562
|
try {
|
|
2207
2563
|
const res = await client.sessions.create({
|
|
2208
|
-
agentId,
|
|
2564
|
+
agentId: agentId2,
|
|
2209
2565
|
initiator: cfg.initiator ?? "",
|
|
2210
2566
|
title: `agc run ${(/* @__PURE__ */ new Date()).toISOString().slice(0, 16)}`,
|
|
2211
2567
|
source: "cli"
|
|
@@ -2231,7 +2587,7 @@ function runCommand() {
|
|
|
2231
2587
|
appendLog: () => {
|
|
2232
2588
|
},
|
|
2233
2589
|
permissions: /* @__PURE__ */ new Map(),
|
|
2234
|
-
agentId,
|
|
2590
|
+
agentId: agentId2,
|
|
2235
2591
|
autoApprove
|
|
2236
2592
|
};
|
|
2237
2593
|
const snapshot = buildDirSnapshot(rootDir, 2);
|
|
@@ -2246,16 +2602,20 @@ function runCommand() {
|
|
|
2246
2602
|
if (localEnabled) {
|
|
2247
2603
|
rows.push(["Local tools", autoApprove ? c.warn("enabled (auto-approve on)") : c.success("enabled")]);
|
|
2248
2604
|
}
|
|
2605
|
+
if (opts.computer) {
|
|
2606
|
+
rows.push(["Cloud computer", c.success("enabled") + c.dim(" (persistent, remote)")]);
|
|
2607
|
+
}
|
|
2249
2608
|
if (rows.length) {
|
|
2250
2609
|
detail(rows);
|
|
2251
2610
|
console.log();
|
|
2252
2611
|
}
|
|
2253
2612
|
}
|
|
2254
2613
|
const params = {
|
|
2255
|
-
agentId,
|
|
2614
|
+
agentId: agentId2,
|
|
2256
2615
|
sessionId,
|
|
2257
|
-
messages: [{ role: "user", content:
|
|
2616
|
+
messages: [{ role: "user", content: prompt }],
|
|
2258
2617
|
...cfg.initiator && { initiatorId: cfg.initiator },
|
|
2618
|
+
...opts.computer && { computerRequest: { enabled: true } },
|
|
2259
2619
|
...cliContext && { cliContext }
|
|
2260
2620
|
};
|
|
2261
2621
|
if (opts.noStream && !localEnabled) {
|
|
@@ -2305,16 +2665,12 @@ Session: ${sessionId} (resume with: agc run --session ${sessionId} "<prompt>")`
|
|
|
2305
2665
|
toolOk = false;
|
|
2306
2666
|
}
|
|
2307
2667
|
const elapsed = ((Date.now() - startMs) / 1e3).toFixed(1);
|
|
2308
|
-
|
|
2309
|
-
|
|
2668
|
+
readline2.cursorTo(process.stdout, 0);
|
|
2669
|
+
readline2.clearLine(process.stdout, 0);
|
|
2310
2670
|
process.stdout.write(` ${c.dim("\u2500")} ${c.bold(displayName)} ${toolOk ? sym.ok : sym.fail} ${c.dim("(" + elapsed + "s)")}
|
|
2311
2671
|
`);
|
|
2312
2672
|
try {
|
|
2313
|
-
await
|
|
2314
|
-
method: "POST",
|
|
2315
|
-
headers: { "Content-Type": "application/json", "Authorization": `Bearer ${cfg.apiKey}` },
|
|
2316
|
-
body: JSON.stringify({ requestId, result })
|
|
2317
|
-
});
|
|
2673
|
+
await client.agents.submitCliToolResult(requestId, result);
|
|
2318
2674
|
} catch {
|
|
2319
2675
|
}
|
|
2320
2676
|
} else if (event.type === "toolStart") {
|
|
@@ -2327,8 +2683,8 @@ Session: ${sessionId} (resume with: agc run --session ${sessionId} "<prompt>")`
|
|
|
2327
2683
|
process.stdout.write(` ${c.dim("\u2500")} ${c.bold(lastToolName)}`);
|
|
2328
2684
|
} else if (event.type === "toolEnd") {
|
|
2329
2685
|
const elapsed = ((Date.now() - toolStartMs) / 1e3).toFixed(1);
|
|
2330
|
-
|
|
2331
|
-
|
|
2686
|
+
readline2.cursorTo(process.stdout, 0);
|
|
2687
|
+
readline2.clearLine(process.stdout, 0);
|
|
2332
2688
|
process.stdout.write(` ${c.dim("\u2500")} ${c.bold(lastToolName)} ${sym.ok} ${c.dim("(" + elapsed + "s)")}
|
|
2333
2689
|
`);
|
|
2334
2690
|
} else if (event.type === "final") {
|
|
@@ -2355,8 +2711,8 @@ ${sym.fail} ${c.error(event.message ?? "Error")}`);
|
|
|
2355
2711
|
}
|
|
2356
2712
|
|
|
2357
2713
|
// src/commands/chat.ts
|
|
2358
|
-
var
|
|
2359
|
-
var
|
|
2714
|
+
var import_commander9 = require("commander");
|
|
2715
|
+
var readline3 = __toESM(require("readline"));
|
|
2360
2716
|
var import_fs6 = require("fs");
|
|
2361
2717
|
var import_path4 = require("path");
|
|
2362
2718
|
var import_os3 = require("os");
|
|
@@ -2399,12 +2755,20 @@ var LOCAL_TOOLS_DISCLAIMER = `
|
|
|
2399
2755
|
${c.dim("Session activity is logged to")} ${c.primary("~/.agc/sessions/")}
|
|
2400
2756
|
`;
|
|
2401
2757
|
function chatCommand() {
|
|
2402
|
-
return new
|
|
2758
|
+
return new import_commander9.Command("chat").description("Start an interactive chat REPL with an agent").option("--agent <agentId>", "Agent ID (or set defaultAgentId in config)").option("--resume <sessionId>", "Resume an existing session by ID").option("--computer", "Give the agent access to its persistent cloud computer").option("--no-stream", "Disable token streaming (wait for full response)").option("--no-local", "Disable local file system access for the agent").action(async (opts) => {
|
|
2403
2759
|
const localEnabled = opts.local !== false;
|
|
2404
2760
|
const cfg = loadConfig();
|
|
2405
|
-
|
|
2406
|
-
if (!
|
|
2407
|
-
|
|
2761
|
+
let agentId2 = opts.agent ?? cfg.defaultAgentId;
|
|
2762
|
+
if (!agentId2 && cfg.initiator) {
|
|
2763
|
+
try {
|
|
2764
|
+
const listed = await makeClient().agents.list(cfg.initiator);
|
|
2765
|
+
const agents = listed?.data ?? listed ?? [];
|
|
2766
|
+
agentId2 = agents.find((agent) => agent.isDefault)?.agentId ?? agents[0]?.agentId;
|
|
2767
|
+
} catch {
|
|
2768
|
+
}
|
|
2769
|
+
}
|
|
2770
|
+
if (!agentId2) {
|
|
2771
|
+
console.error(c.error("No default agent is available. Specify --agent <agentId> or run `agc agents list`."));
|
|
2408
2772
|
process.exit(1);
|
|
2409
2773
|
}
|
|
2410
2774
|
if (!cfg.initiator) {
|
|
@@ -2419,7 +2783,7 @@ function chatCommand() {
|
|
|
2419
2783
|
const spinner = spin("Creating session\u2026");
|
|
2420
2784
|
try {
|
|
2421
2785
|
const res = await client.sessions.create({
|
|
2422
|
-
agentId,
|
|
2786
|
+
agentId: agentId2,
|
|
2423
2787
|
initiator,
|
|
2424
2788
|
title: `agc chat ${(/* @__PURE__ */ new Date()).toISOString().slice(0, 16)}`,
|
|
2425
2789
|
source: "cli"
|
|
@@ -2430,7 +2794,7 @@ function chatCommand() {
|
|
|
2430
2794
|
appendSessionLog(sessionId, {
|
|
2431
2795
|
type: "session_start",
|
|
2432
2796
|
sessionId,
|
|
2433
|
-
agentId,
|
|
2797
|
+
agentId: agentId2,
|
|
2434
2798
|
initiator,
|
|
2435
2799
|
source: "cli",
|
|
2436
2800
|
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
@@ -2445,9 +2809,9 @@ function chatCommand() {
|
|
|
2445
2809
|
try {
|
|
2446
2810
|
const res = await client.sessions.get(sessionId);
|
|
2447
2811
|
const session = res?.data ?? res;
|
|
2448
|
-
if (session.agentId && session.agentId !==
|
|
2812
|
+
if (session.agentId && session.agentId !== agentId2) {
|
|
2449
2813
|
spinner.stop();
|
|
2450
|
-
console.log(c.warn(` Note: session ${sessionId} was created with agent ${session.agentId}, not ${
|
|
2814
|
+
console.log(c.warn(` Note: session ${sessionId} was created with agent ${session.agentId}, not ${agentId2}`));
|
|
2451
2815
|
} else {
|
|
2452
2816
|
spinner.stop();
|
|
2453
2817
|
}
|
|
@@ -2460,10 +2824,10 @@ function chatCommand() {
|
|
|
2460
2824
|
let agentName;
|
|
2461
2825
|
let walletLine = "";
|
|
2462
2826
|
await Promise.allSettled([
|
|
2463
|
-
client.agents.get(
|
|
2827
|
+
client.agents.get(agentId2).then((res) => {
|
|
2464
2828
|
agentName = (res?.data ?? res)?.name;
|
|
2465
2829
|
}),
|
|
2466
|
-
client.wallets.primary(
|
|
2830
|
+
client.wallets.primary(agentId2).then(async (primary) => {
|
|
2467
2831
|
const w = primary?.data ?? primary;
|
|
2468
2832
|
if (w?.id) {
|
|
2469
2833
|
const bal = await client.wallets.balance(w.id).catch(() => null);
|
|
@@ -2477,10 +2841,11 @@ function chatCommand() {
|
|
|
2477
2841
|
console.log(`
|
|
2478
2842
|
${c.bold("Agent Commons Chat")}`);
|
|
2479
2843
|
const headerRows = [
|
|
2480
|
-
["Agent", agentName ? `${agentName} ${c.dim(
|
|
2844
|
+
["Agent", agentName ? `${agentName} ${c.dim(agentId2)}` : agentId2],
|
|
2481
2845
|
["Session", c.id(sessionId) + (isResume ? c.dim(" (resumed)") : c.dim(" (new)"))]
|
|
2482
2846
|
];
|
|
2483
2847
|
if (walletLine) headerRows.push(["Wallet", walletLine]);
|
|
2848
|
+
if (opts.computer) headerRows.push(["Cloud computer", c.success("enabled") + c.dim(" (persistent, remote)")]);
|
|
2484
2849
|
if (localEnabled) headerRows.push(["Local tools", c.success("enabled") + c.dim(" (read, write, search, run)")]);
|
|
2485
2850
|
detail(headerRows);
|
|
2486
2851
|
let localToolsCfg = null;
|
|
@@ -2490,12 +2855,12 @@ ${c.bold("Agent Commons Chat")}`);
|
|
|
2490
2855
|
localToolsCfg = {
|
|
2491
2856
|
rootDir,
|
|
2492
2857
|
sessionId,
|
|
2493
|
-
agentId,
|
|
2858
|
+
agentId: agentId2,
|
|
2494
2859
|
agentName,
|
|
2495
2860
|
appendLog: (record) => appendSessionLog(sessionId, record),
|
|
2496
2861
|
permissions: /* @__PURE__ */ new Map()
|
|
2497
2862
|
};
|
|
2498
|
-
installGitHook(rootDir, sessionId,
|
|
2863
|
+
installGitHook(rootDir, sessionId, agentId2, agentName);
|
|
2499
2864
|
appendSessionLog(sessionId, {
|
|
2500
2865
|
type: "local_tools_enabled",
|
|
2501
2866
|
rootDir,
|
|
@@ -2503,7 +2868,7 @@ ${c.bold("Agent Commons Chat")}`);
|
|
|
2503
2868
|
});
|
|
2504
2869
|
}
|
|
2505
2870
|
console.log(c.dim("\nType your message and press Enter. Type /help for commands.\n"));
|
|
2506
|
-
const rl =
|
|
2871
|
+
const rl = readline3.createInterface({
|
|
2507
2872
|
input: process.stdin,
|
|
2508
2873
|
output: process.stdout,
|
|
2509
2874
|
terminal: true,
|
|
@@ -2587,9 +2952,10 @@ ${content}
|
|
|
2587
2952
|
cliContext = buildLocalToolsManifest(rootDir, snapshot, fileContextBlocks);
|
|
2588
2953
|
}
|
|
2589
2954
|
const params = {
|
|
2590
|
-
agentId,
|
|
2955
|
+
agentId: agentId2,
|
|
2591
2956
|
sessionId,
|
|
2592
2957
|
messages: [{ role: "user", content: userMessage }],
|
|
2958
|
+
...opts.computer && { computerRequest: { enabled: true } },
|
|
2593
2959
|
...cliContext && { cliContext }
|
|
2594
2960
|
};
|
|
2595
2961
|
if (opts.noStream) {
|
|
@@ -2646,7 +3012,7 @@ ${sym.fail} ${c.error(err.message ?? String(err))}`);
|
|
|
2646
3012
|
if (isWaiting) {
|
|
2647
3013
|
elapsedInterval = setInterval(() => {
|
|
2648
3014
|
elapsedSec++;
|
|
2649
|
-
|
|
3015
|
+
readline3.cursorTo(process.stdout, 0);
|
|
2650
3016
|
process.stdout.write(` ${c.dim("\u2500")} ${c.bold(displayName)}${argStr ? " " + c.dim(argStr) : ""} ${c.dim(elapsedSec + "s\u2026")}`);
|
|
2651
3017
|
}, 1e3);
|
|
2652
3018
|
}
|
|
@@ -2661,12 +3027,14 @@ ${sym.fail} ${c.error(err.message ?? String(err))}`);
|
|
|
2661
3027
|
if (elapsedInterval) clearInterval(elapsedInterval);
|
|
2662
3028
|
const elapsed = ((Date.now() - startMs) / 1e3).toFixed(1);
|
|
2663
3029
|
const preview = toolOk ? toolResultPreview(displayName, result) : "";
|
|
2664
|
-
|
|
2665
|
-
|
|
3030
|
+
readline3.cursorTo(process.stdout, 0);
|
|
3031
|
+
readline3.clearLine(process.stdout, 0);
|
|
2666
3032
|
const statusIcon = toolOk ? sym.ok : sym.fail;
|
|
2667
3033
|
const previewPart = preview ? ` ${c.dim(preview)}` : "";
|
|
2668
|
-
process.stdout.write(
|
|
2669
|
-
`)
|
|
3034
|
+
process.stdout.write(
|
|
3035
|
+
` ${c.dim("\u2500")} ${c.bold(displayName)}${argStr ? " " + c.dim(argStr) : ""} ${statusIcon}${previewPart} ${c.dim("(" + elapsed + "s)")}
|
|
3036
|
+
`
|
|
3037
|
+
);
|
|
2670
3038
|
appendSessionLog(sessionId, {
|
|
2671
3039
|
type: "local_tool_result",
|
|
2672
3040
|
tool: toolName,
|
|
@@ -2674,14 +3042,7 @@ ${sym.fail} ${c.error(err.message ?? String(err))}`);
|
|
|
2674
3042
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
2675
3043
|
});
|
|
2676
3044
|
try {
|
|
2677
|
-
await
|
|
2678
|
-
method: "POST",
|
|
2679
|
-
headers: {
|
|
2680
|
-
"Content-Type": "application/json",
|
|
2681
|
-
"Authorization": `Bearer ${cfg.apiKey}`
|
|
2682
|
-
},
|
|
2683
|
-
body: JSON.stringify({ requestId, result })
|
|
2684
|
-
});
|
|
3045
|
+
await client.agents.submitCliToolResult(requestId, result);
|
|
2685
3046
|
} catch (postErr) {
|
|
2686
3047
|
console.error(c.warn(`
|
|
2687
3048
|
[local] Failed to submit tool result: ${postErr?.message}`));
|
|
@@ -2696,8 +3057,8 @@ ${sym.fail} ${c.error(err.message ?? String(err))}`);
|
|
|
2696
3057
|
hasOutput = false;
|
|
2697
3058
|
} else if (event.type === "toolEnd") {
|
|
2698
3059
|
const elapsed = ((Date.now() - toolStartMs) / 1e3).toFixed(1);
|
|
2699
|
-
|
|
2700
|
-
|
|
3060
|
+
readline3.cursorTo(process.stdout, 0);
|
|
3061
|
+
readline3.clearLine(process.stdout, 0);
|
|
2701
3062
|
process.stdout.write(` ${c.dim("\u2500")} ${c.bold(lastToolName)} ${sym.ok} ${c.dim("(" + elapsed + "s)")}
|
|
2702
3063
|
`);
|
|
2703
3064
|
process.stdout.write(c.primary("agent") + c.dim(" \u203A "));
|
|
@@ -2723,7 +3084,13 @@ ${sym.fail} ${c.error(err.message ?? String(err))}`);
|
|
|
2723
3084
|
type: "message",
|
|
2724
3085
|
role: "assistant",
|
|
2725
3086
|
content: agentContent,
|
|
2726
|
-
usage: {
|
|
3087
|
+
usage: {
|
|
3088
|
+
inputTokens: inputTok,
|
|
3089
|
+
outputTokens: outputTok,
|
|
3090
|
+
cachedTokens: cachedTok,
|
|
3091
|
+
totalTokens: total,
|
|
3092
|
+
costUsd: usage.costUsd
|
|
3093
|
+
},
|
|
2727
3094
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
2728
3095
|
});
|
|
2729
3096
|
} else {
|
|
@@ -2746,7 +3113,7 @@ ${sym.fail} ${c.error(event.message ?? "Stream error")}`);
|
|
|
2746
3113
|
if (thinkingSpinner.isSpinning) thinkingSpinner.stop();
|
|
2747
3114
|
process.stdout.write("\n");
|
|
2748
3115
|
if (localToolsCfg && agentContent) {
|
|
2749
|
-
await handleLocalToolLoop(agentContent, localToolsCfg, client,
|
|
3116
|
+
await handleLocalToolLoop(agentContent, localToolsCfg, client, agentId2, sessionId, appendSessionLog, !!opts.computer);
|
|
2750
3117
|
}
|
|
2751
3118
|
} catch (err) {
|
|
2752
3119
|
process.stdout.write("\n");
|
|
@@ -2754,8 +3121,8 @@ ${sym.fail} ${c.error(event.message ?? "Stream error")}`);
|
|
|
2754
3121
|
}
|
|
2755
3122
|
}
|
|
2756
3123
|
console.log();
|
|
2757
|
-
|
|
2758
|
-
|
|
3124
|
+
readline3.cursorTo(process.stdout, 0);
|
|
3125
|
+
readline3.clearLine(process.stdout, 0);
|
|
2759
3126
|
rl.resume();
|
|
2760
3127
|
rl.prompt();
|
|
2761
3128
|
});
|
|
@@ -2775,7 +3142,7 @@ Session preserved. Resume with: agc chat --resume ${sessionId}`));
|
|
|
2775
3142
|
});
|
|
2776
3143
|
}
|
|
2777
3144
|
var MAX_TOOL_DEPTH = 10;
|
|
2778
|
-
async function handleLocalToolLoop(agentText, cfg, client,
|
|
3145
|
+
async function handleLocalToolLoop(agentText, cfg, client, agentId2, sessionId, appendLog, computerEnabled = false, depth = 0) {
|
|
2779
3146
|
if (depth >= MAX_TOOL_DEPTH) {
|
|
2780
3147
|
console.log(c.dim(`
|
|
2781
3148
|
[local] Max tool depth reached (${MAX_TOOL_DEPTH}). Stopping tool loop.
|
|
@@ -2798,11 +3165,13 @@ async function handleLocalToolLoop(agentText, cfg, client, agentId, sessionId, a
|
|
|
2798
3165
|
}
|
|
2799
3166
|
const elapsed = ((Date.now() - startMs) / 1e3).toFixed(1);
|
|
2800
3167
|
const preview = toolOk ? toolResultPreview(toolCall.tool, result) : "";
|
|
2801
|
-
|
|
2802
|
-
|
|
3168
|
+
readline3.cursorTo(process.stdout, 0);
|
|
3169
|
+
readline3.clearLine(process.stdout, 0);
|
|
2803
3170
|
const previewPart = preview ? ` ${c.dim(preview)}` : "";
|
|
2804
|
-
process.stdout.write(
|
|
2805
|
-
`)
|
|
3171
|
+
process.stdout.write(
|
|
3172
|
+
` ${c.dim("\u2500")} ${c.bold(toolCall.tool)}${argStr ? " " + c.dim(argStr) : ""} ${toolOk ? sym.ok : sym.fail}${previewPart} ${c.dim("(" + elapsed + "s)")}
|
|
3173
|
+
`
|
|
3174
|
+
);
|
|
2806
3175
|
const resultMsg = `[Tool result: ${toolCall.tool}]
|
|
2807
3176
|
\`\`\`
|
|
2808
3177
|
${result}
|
|
@@ -2820,9 +3189,10 @@ ${result}
|
|
|
2820
3189
|
let loopToolName = "";
|
|
2821
3190
|
let loopToolStartMs = 0;
|
|
2822
3191
|
for await (const evt of client.agents.stream({
|
|
2823
|
-
agentId,
|
|
3192
|
+
agentId: agentId2,
|
|
2824
3193
|
sessionId,
|
|
2825
|
-
messages: [{ role: "user", content: resultMsg }]
|
|
3194
|
+
messages: [{ role: "user", content: resultMsg }],
|
|
3195
|
+
...computerEnabled && { computerRequest: { enabled: true } }
|
|
2826
3196
|
})) {
|
|
2827
3197
|
if (evt.type === "token") {
|
|
2828
3198
|
const tok = evt.content ?? "";
|
|
@@ -2835,8 +3205,8 @@ ${result}
|
|
|
2835
3205
|
process.stdout.write(` ${c.dim("\u2500")} ${c.bold(loopToolName)}`);
|
|
2836
3206
|
} else if (evt.type === "toolEnd") {
|
|
2837
3207
|
const elapsed2 = ((Date.now() - loopToolStartMs) / 1e3).toFixed(1);
|
|
2838
|
-
|
|
2839
|
-
|
|
3208
|
+
readline3.cursorTo(process.stdout, 0);
|
|
3209
|
+
readline3.clearLine(process.stdout, 0);
|
|
2840
3210
|
process.stdout.write(` ${c.dim("\u2500")} ${c.bold(loopToolName)} ${sym.ok} ${c.dim("(" + elapsed2 + "s)")}
|
|
2841
3211
|
`);
|
|
2842
3212
|
process.stdout.write(c.primary("agent") + c.dim(" \u203A "));
|
|
@@ -2846,7 +3216,12 @@ ${result}
|
|
|
2846
3216
|
process.stdout.write(txt);
|
|
2847
3217
|
followContent += txt;
|
|
2848
3218
|
}
|
|
2849
|
-
appendLog(sessionId, {
|
|
3219
|
+
appendLog(sessionId, {
|
|
3220
|
+
type: "message",
|
|
3221
|
+
role: "assistant",
|
|
3222
|
+
content: followContent,
|
|
3223
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
3224
|
+
});
|
|
2850
3225
|
break;
|
|
2851
3226
|
} else if (evt.type === "error") {
|
|
2852
3227
|
console.error(`
|
|
@@ -2860,7 +3235,7 @@ ${sym.fail} ${c.error(evt.message ?? "Stream error")}`);
|
|
|
2860
3235
|
console.error(`${sym.fail} ${c.error(err?.message ?? String(err))}`);
|
|
2861
3236
|
return;
|
|
2862
3237
|
}
|
|
2863
|
-
await handleLocalToolLoop(followContent, cfg, client,
|
|
3238
|
+
await handleLocalToolLoop(followContent, cfg, client, agentId2, sessionId, appendLog, computerEnabled, depth + 1);
|
|
2864
3239
|
}
|
|
2865
3240
|
function truncate(s, max) {
|
|
2866
3241
|
const str = String(s ?? "");
|
|
@@ -2949,9 +3324,9 @@ function extractText(payload) {
|
|
|
2949
3324
|
}
|
|
2950
3325
|
|
|
2951
3326
|
// src/commands/mcp.ts
|
|
2952
|
-
var
|
|
3327
|
+
var import_commander10 = require("commander");
|
|
2953
3328
|
function mcpCommand() {
|
|
2954
|
-
const cmd = new
|
|
3329
|
+
const cmd = new import_commander10.Command("mcp").description("Manage MCP (Model Context Protocol) servers");
|
|
2955
3330
|
cmd.command("list").description("List MCP servers for the current initiator").option("--agent <agentId>", "List servers owned by an agent instead of the user").option("--json", "Output as JSON").action(async (opts) => {
|
|
2956
3331
|
const cfg = loadConfig();
|
|
2957
3332
|
if (!cfg.initiator && !opts.agent) {
|
|
@@ -3249,9 +3624,9 @@ ${sym.ok} MCP server registered`);
|
|
|
3249
3624
|
}
|
|
3250
3625
|
|
|
3251
3626
|
// src/commands/skills.ts
|
|
3252
|
-
var
|
|
3627
|
+
var import_commander11 = require("commander");
|
|
3253
3628
|
function skillsCommand() {
|
|
3254
|
-
const cmd = new
|
|
3629
|
+
const cmd = new import_commander11.Command("skills").description("Discover and manage skills");
|
|
3255
3630
|
cmd.command("list").description("List available skills").option("--owner <id>", "Filter by owner ID").option("--platform", "Show platform-only skills").option("--json", "Output as JSON").action(async (opts) => {
|
|
3256
3631
|
const spinner = spin("Fetching skills\u2026");
|
|
3257
3632
|
try {
|
|
@@ -3474,8 +3849,8 @@ function skillsCommand() {
|
|
|
3474
3849
|
});
|
|
3475
3850
|
cmd.command("delete <slug>").description("Permanently delete a skill").option("--yes", "Skip confirmation prompt").option("--json", "Output result as JSON").action(async (slug, opts) => {
|
|
3476
3851
|
if (!opts.yes) {
|
|
3477
|
-
const
|
|
3478
|
-
const rl =
|
|
3852
|
+
const readline4 = await import("readline");
|
|
3853
|
+
const rl = readline4.createInterface({ input: process.stdin, output: process.stdout });
|
|
3479
3854
|
const answer = await new Promise(
|
|
3480
3855
|
(resolve2) => rl.question(c.warn(`Delete skill "${slug}"? This cannot be undone. [y/N] `), resolve2)
|
|
3481
3856
|
);
|
|
@@ -3502,24 +3877,24 @@ function skillsCommand() {
|
|
|
3502
3877
|
}
|
|
3503
3878
|
|
|
3504
3879
|
// src/commands/wallet.ts
|
|
3505
|
-
var
|
|
3880
|
+
var import_commander12 = require("commander");
|
|
3506
3881
|
function walletCommand() {
|
|
3507
|
-
const cmd = new
|
|
3882
|
+
const cmd = new import_commander12.Command("wallet").description("Manage agent wallets");
|
|
3508
3883
|
cmd.command("list").description("List all wallets for an agent").option("--agent <agentId>", "Agent ID (or use defaultAgentId from config)").option("--json", "Output as JSON").action(async (opts) => {
|
|
3509
3884
|
const cfg = loadConfig();
|
|
3510
|
-
const
|
|
3511
|
-
if (!
|
|
3885
|
+
const agentId2 = opts.agent ?? cfg.defaultAgentId;
|
|
3886
|
+
if (!agentId2) {
|
|
3512
3887
|
console.error(c.error("Specify --agent <agentId> or set defaultAgentId with `agc config set defaultAgentId <id>`"));
|
|
3513
3888
|
process.exit(1);
|
|
3514
3889
|
}
|
|
3515
3890
|
const spinner = spin("Fetching wallets\u2026");
|
|
3516
3891
|
try {
|
|
3517
3892
|
const client = makeClient();
|
|
3518
|
-
const wallets = await client.wallets.list(
|
|
3893
|
+
const wallets = await client.wallets.list(agentId2);
|
|
3519
3894
|
spinner.stop();
|
|
3520
3895
|
if (opts.json) return jsonOut(wallets);
|
|
3521
3896
|
const list = wallets?.data ?? wallets ?? [];
|
|
3522
|
-
section(`Wallets for agent ${
|
|
3897
|
+
section(`Wallets for agent ${agentId2.slice(0, 8)}\u2026 (${list.length})`);
|
|
3523
3898
|
table(
|
|
3524
3899
|
list.map((w) => ({
|
|
3525
3900
|
ID: w.id.slice(0, 8) + "\u2026",
|
|
@@ -3539,19 +3914,19 @@ function walletCommand() {
|
|
|
3539
3914
|
});
|
|
3540
3915
|
cmd.command("show").description("Show the agent's primary wallet address").option("--agent <agentId>", "Agent ID (or use defaultAgentId from config)").option("--json", "Output as JSON").action(async (opts) => {
|
|
3541
3916
|
const cfg = loadConfig();
|
|
3542
|
-
const
|
|
3543
|
-
if (!
|
|
3917
|
+
const agentId2 = opts.agent ?? cfg.defaultAgentId;
|
|
3918
|
+
if (!agentId2) {
|
|
3544
3919
|
console.error(c.error("Specify --agent <agentId> or set defaultAgentId with `agc config set defaultAgentId <id>`"));
|
|
3545
3920
|
process.exit(1);
|
|
3546
3921
|
}
|
|
3547
3922
|
const spinner = spin("Fetching primary wallet\u2026");
|
|
3548
3923
|
try {
|
|
3549
3924
|
const client = makeClient();
|
|
3550
|
-
const wallet = await client.wallets.primary(
|
|
3925
|
+
const wallet = await client.wallets.primary(agentId2);
|
|
3551
3926
|
spinner.stop();
|
|
3552
3927
|
if (!wallet) {
|
|
3553
|
-
console.log(c.warn(` No wallet found for agent ${
|
|
3554
|
-
console.log(c.dim(` Run: agc wallet create --agent ${
|
|
3928
|
+
console.log(c.warn(` No wallet found for agent ${agentId2}`));
|
|
3929
|
+
console.log(c.dim(` Run: agc wallet create --agent ${agentId2}`));
|
|
3555
3930
|
return;
|
|
3556
3931
|
}
|
|
3557
3932
|
const w = wallet?.data ?? wallet;
|
|
@@ -3572,8 +3947,8 @@ function walletCommand() {
|
|
|
3572
3947
|
});
|
|
3573
3948
|
cmd.command("balance").description("Show the agent's wallet USDC and ETH balance").option("--agent <agentId>", "Agent ID (or use defaultAgentId from config)").option("--wallet <walletId>", "Specific wallet ID (defaults to primary)").option("--json", "Output as JSON").action(async (opts) => {
|
|
3574
3949
|
const cfg = loadConfig();
|
|
3575
|
-
const
|
|
3576
|
-
if (!
|
|
3950
|
+
const agentId2 = opts.agent ?? cfg.defaultAgentId;
|
|
3951
|
+
if (!agentId2) {
|
|
3577
3952
|
console.error(c.error("Specify --agent <agentId> or set defaultAgentId with `agc config set defaultAgentId <id>`"));
|
|
3578
3953
|
process.exit(1);
|
|
3579
3954
|
}
|
|
@@ -3582,11 +3957,11 @@ function walletCommand() {
|
|
|
3582
3957
|
const client = makeClient();
|
|
3583
3958
|
let walletId = opts.wallet;
|
|
3584
3959
|
if (!walletId) {
|
|
3585
|
-
const primary = await client.wallets.primary(
|
|
3960
|
+
const primary = await client.wallets.primary(agentId2);
|
|
3586
3961
|
const w = primary?.data ?? primary;
|
|
3587
3962
|
if (!w) {
|
|
3588
3963
|
spinner.stop();
|
|
3589
|
-
console.log(c.warn(` No wallet found. Run: agc wallet create --agent ${
|
|
3964
|
+
console.log(c.warn(` No wallet found. Run: agc wallet create --agent ${agentId2}`));
|
|
3590
3965
|
return;
|
|
3591
3966
|
}
|
|
3592
3967
|
walletId = w.id;
|
|
@@ -3613,8 +3988,8 @@ function walletCommand() {
|
|
|
3613
3988
|
});
|
|
3614
3989
|
cmd.command("create").description("Create a new wallet for an agent").option("--agent <agentId>", "Agent ID (or use defaultAgentId from config)").option("--type <type>", "Wallet type: eoa | external (default: eoa)", "eoa").option("--label <label>", "Wallet label (default: Primary)", "Primary").option("--address <address>", "For --type external: owner-provided address").option("--json", "Output as JSON").action(async (opts) => {
|
|
3615
3990
|
const cfg = loadConfig();
|
|
3616
|
-
const
|
|
3617
|
-
if (!
|
|
3991
|
+
const agentId2 = opts.agent ?? cfg.defaultAgentId;
|
|
3992
|
+
if (!agentId2) {
|
|
3618
3993
|
console.error(c.error("Specify --agent <agentId> or set defaultAgentId with `agc config set defaultAgentId <id>`"));
|
|
3619
3994
|
process.exit(1);
|
|
3620
3995
|
}
|
|
@@ -3626,7 +4001,7 @@ function walletCommand() {
|
|
|
3626
4001
|
try {
|
|
3627
4002
|
const client = makeClient();
|
|
3628
4003
|
const wallet = await client.wallets.create({
|
|
3629
|
-
agentId,
|
|
4004
|
+
agentId: agentId2,
|
|
3630
4005
|
walletType: opts.type,
|
|
3631
4006
|
label: opts.label,
|
|
3632
4007
|
externalAddress: opts.address
|
|
@@ -3734,9 +4109,9 @@ function chainName(chainId) {
|
|
|
3734
4109
|
}
|
|
3735
4110
|
|
|
3736
4111
|
// src/commands/models.ts
|
|
3737
|
-
var
|
|
4112
|
+
var import_commander13 = require("commander");
|
|
3738
4113
|
function modelsCommand() {
|
|
3739
|
-
const cmd = new
|
|
4114
|
+
const cmd = new import_commander13.Command("models").description("List available LLM models");
|
|
3740
4115
|
cmd.command("ls").description("List all available models grouped by provider").option("--provider <name>", "Filter by provider (openai, anthropic, google, mistral, groq, ollama)").option("--json", "Output as JSON").action(async (opts) => {
|
|
3741
4116
|
const client = makeClient();
|
|
3742
4117
|
const spinner = spin("Fetching models\u2026");
|
|
@@ -3779,27 +4154,27 @@ ${c.bold(provider.toUpperCase())}`);
|
|
|
3779
4154
|
}
|
|
3780
4155
|
|
|
3781
4156
|
// src/commands/memory.ts
|
|
3782
|
-
var
|
|
4157
|
+
var import_commander14 = require("commander");
|
|
3783
4158
|
function memoryCommand() {
|
|
3784
|
-
const cmd = new
|
|
4159
|
+
const cmd = new import_commander14.Command("memory").description("View and manage agent memories");
|
|
3785
4160
|
cmd.command("list").description("List memories for an agent").option("--agent <agentId>", "Agent ID (defaults to configured agent)").option("--type <type>", "Filter by type: episodic | semantic | procedural").option("--limit <n>", "Max results", "50").option("--json", "Output as JSON").action(async (opts) => {
|
|
3786
4161
|
const cfg = loadConfig();
|
|
3787
|
-
const
|
|
3788
|
-
if (!
|
|
4162
|
+
const agentId2 = opts.agent ?? cfg.defaultAgentId;
|
|
4163
|
+
if (!agentId2) {
|
|
3789
4164
|
console.error(c.error("Specify --agent <agentId> or set defaultAgentId"));
|
|
3790
4165
|
process.exit(1);
|
|
3791
4166
|
}
|
|
3792
4167
|
const spinner = spin("Fetching memories\u2026");
|
|
3793
4168
|
try {
|
|
3794
4169
|
const client = makeClient();
|
|
3795
|
-
const res = await client.memory.list(
|
|
4170
|
+
const res = await client.memory.list(agentId2, {
|
|
3796
4171
|
type: opts.type,
|
|
3797
4172
|
limit: parseInt(opts.limit, 10)
|
|
3798
4173
|
});
|
|
3799
4174
|
const memories = res?.data ?? res ?? [];
|
|
3800
4175
|
spinner.stop();
|
|
3801
4176
|
if (opts.json) return jsonOut(memories);
|
|
3802
|
-
section(`Memories for ${
|
|
4177
|
+
section(`Memories for ${agentId2.slice(0, 12)}\u2026 (${memories.length})`);
|
|
3803
4178
|
if (memories.length === 0) {
|
|
3804
4179
|
console.log(c.dim(" No memories yet"));
|
|
3805
4180
|
return;
|
|
@@ -3821,15 +4196,15 @@ function memoryCommand() {
|
|
|
3821
4196
|
});
|
|
3822
4197
|
cmd.command("stats").description("Show memory statistics for an agent").option("--agent <agentId>", "Agent ID").option("--json", "Output as JSON").action(async (opts) => {
|
|
3823
4198
|
const cfg = loadConfig();
|
|
3824
|
-
const
|
|
3825
|
-
if (!
|
|
4199
|
+
const agentId2 = opts.agent ?? cfg.defaultAgentId;
|
|
4200
|
+
if (!agentId2) {
|
|
3826
4201
|
console.error(c.error("Specify --agent <agentId>"));
|
|
3827
4202
|
process.exit(1);
|
|
3828
4203
|
}
|
|
3829
4204
|
const spinner = spin("Fetching stats\u2026");
|
|
3830
4205
|
try {
|
|
3831
4206
|
const client = makeClient();
|
|
3832
|
-
const res = await client.memory.stats(
|
|
4207
|
+
const res = await client.memory.stats(agentId2);
|
|
3833
4208
|
const stats = res?.data ?? res;
|
|
3834
4209
|
spinner.stop();
|
|
3835
4210
|
if (opts.json) return jsonOut(stats);
|
|
@@ -3889,15 +4264,15 @@ ${sym.ok} Memory ${c.id(memoryId)} deleted`);
|
|
|
3889
4264
|
});
|
|
3890
4265
|
cmd.command("search <query>").description("Semantic search over agent memories").option("--agent <agentId>", "Agent ID").option("--limit <n>", "Max results", "10").option("--json", "Output as JSON").action(async (query, opts) => {
|
|
3891
4266
|
const cfg = loadConfig();
|
|
3892
|
-
const
|
|
3893
|
-
if (!
|
|
4267
|
+
const agentId2 = opts.agent ?? cfg.defaultAgentId;
|
|
4268
|
+
if (!agentId2) {
|
|
3894
4269
|
console.error(c.error("Specify --agent <agentId>"));
|
|
3895
4270
|
process.exit(1);
|
|
3896
4271
|
}
|
|
3897
4272
|
const spinner = spin("Searching memories\u2026");
|
|
3898
4273
|
try {
|
|
3899
4274
|
const client = makeClient();
|
|
3900
|
-
const res = await client.memory.retrieve(
|
|
4275
|
+
const res = await client.memory.retrieve(agentId2, query, parseInt(opts.limit, 10));
|
|
3901
4276
|
const memories = res?.data ?? res ?? [];
|
|
3902
4277
|
spinner.stop();
|
|
3903
4278
|
if (opts.json) return jsonOut(memories);
|
|
@@ -3921,9 +4296,9 @@ ${sym.ok} Memory ${c.id(memoryId)} deleted`);
|
|
|
3921
4296
|
}
|
|
3922
4297
|
|
|
3923
4298
|
// src/commands/usage.ts
|
|
3924
|
-
var
|
|
4299
|
+
var import_commander15 = require("commander");
|
|
3925
4300
|
function usageCommand() {
|
|
3926
|
-
const cmd = new
|
|
4301
|
+
const cmd = new import_commander15.Command("usage").description("View token usage and cost by agent");
|
|
3927
4302
|
cmd.command("agents").description("Show usage summary for all your agents").option("--owner <address>", "Owner address (defaults to configured initiator)").option("--from <date>", "Start date (ISO, e.g. 2025-01-01)").option("--to <date>", "End date (ISO)").option("--json", "Output as JSON").action(async (opts) => {
|
|
3928
4303
|
const cfg = loadConfig();
|
|
3929
4304
|
const owner = opts.owner ?? cfg.initiator;
|
|
@@ -3986,18 +4361,18 @@ function usageCommand() {
|
|
|
3986
4361
|
process.exit(1);
|
|
3987
4362
|
}
|
|
3988
4363
|
});
|
|
3989
|
-
cmd.command("agent <agentId>").description("Show detailed usage for a specific agent").option("--from <date>", "Start date (ISO)").option("--to <date>", "End date (ISO)").option("--json", "Output as JSON").action(async (
|
|
4364
|
+
cmd.command("agent <agentId>").description("Show detailed usage for a specific agent").option("--from <date>", "Start date (ISO)").option("--to <date>", "End date (ISO)").option("--json", "Output as JSON").action(async (agentId2, opts) => {
|
|
3990
4365
|
const spinner = spin("Fetching usage\u2026");
|
|
3991
4366
|
try {
|
|
3992
4367
|
const client = makeClient();
|
|
3993
|
-
const res = await client.usage.getAgentUsage(
|
|
4368
|
+
const res = await client.usage.getAgentUsage(agentId2, {
|
|
3994
4369
|
from: opts.from,
|
|
3995
4370
|
to: opts.to
|
|
3996
4371
|
});
|
|
3997
4372
|
const data = res?.data ?? res;
|
|
3998
4373
|
spinner.stop();
|
|
3999
4374
|
if (opts.json) return jsonOut(data);
|
|
4000
|
-
section(`Usage \u2014 ${
|
|
4375
|
+
section(`Usage \u2014 ${agentId2.slice(0, 12)}\u2026`);
|
|
4001
4376
|
detail([
|
|
4002
4377
|
["Calls", (data.callCount ?? 0).toLocaleString()],
|
|
4003
4378
|
["Input tokens", (data.totalInputTokens ?? 0).toLocaleString()],
|
|
@@ -4014,8 +4389,114 @@ function usageCommand() {
|
|
|
4014
4389
|
return cmd;
|
|
4015
4390
|
}
|
|
4016
4391
|
|
|
4392
|
+
// src/commands/billing.ts
|
|
4393
|
+
var import_commander16 = require("commander");
|
|
4394
|
+
function creditsCommand() {
|
|
4395
|
+
const cmd = new import_commander16.Command("credits").description("View your credit balance and ledger");
|
|
4396
|
+
cmd.command("balance", { isDefault: true }).description("Show your current credit balance").option("--json", "Output as JSON").action(async (opts) => {
|
|
4397
|
+
const spinner = spin("Fetching balance\u2026");
|
|
4398
|
+
try {
|
|
4399
|
+
const client = makeClient();
|
|
4400
|
+
const res = await client.credits.balance();
|
|
4401
|
+
spinner.stop();
|
|
4402
|
+
if (opts.json) return jsonOut(res.data);
|
|
4403
|
+
section("Credits");
|
|
4404
|
+
detail([["Balance", String(res?.data?.balance ?? 0)]]);
|
|
4405
|
+
} catch (e) {
|
|
4406
|
+
spinner.stop();
|
|
4407
|
+
console.error(c.error(e.message));
|
|
4408
|
+
process.exit(1);
|
|
4409
|
+
}
|
|
4410
|
+
});
|
|
4411
|
+
cmd.command("ledger").description("Show recent credit ledger entries").option("--limit <n>", "Max entries", "20").option("--json", "Output as JSON").action(async (opts) => {
|
|
4412
|
+
const spinner = spin("Fetching ledger\u2026");
|
|
4413
|
+
try {
|
|
4414
|
+
const client = makeClient();
|
|
4415
|
+
const res = await client.credits.ledger({ limit: Number(opts.limit) });
|
|
4416
|
+
spinner.stop();
|
|
4417
|
+
const rows = res?.data ?? [];
|
|
4418
|
+
if (opts.json) return jsonOut(rows);
|
|
4419
|
+
section("Credit ledger");
|
|
4420
|
+
for (const e of rows) {
|
|
4421
|
+
const sign = e.amount >= 0 ? "+" : "";
|
|
4422
|
+
console.log(
|
|
4423
|
+
`${c.dim(new Date(e.createdAt).toLocaleString())} ${sign}${e.amount} ${e.description || e.eventType}`
|
|
4424
|
+
);
|
|
4425
|
+
}
|
|
4426
|
+
if (!rows.length) console.log(c.dim("No entries."));
|
|
4427
|
+
} catch (e) {
|
|
4428
|
+
spinner.stop();
|
|
4429
|
+
console.error(c.error(e.message));
|
|
4430
|
+
process.exit(1);
|
|
4431
|
+
}
|
|
4432
|
+
});
|
|
4433
|
+
return cmd;
|
|
4434
|
+
}
|
|
4435
|
+
function billingCommand() {
|
|
4436
|
+
const cmd = new import_commander16.Command("billing").description("Manage your subscription and top-ups");
|
|
4437
|
+
cmd.command("status", { isDefault: true }).description("Show your current plan and entitlements").option("--json", "Output as JSON").action(async (opts) => {
|
|
4438
|
+
const spinner = spin("Fetching plan\u2026");
|
|
4439
|
+
try {
|
|
4440
|
+
const client = makeClient();
|
|
4441
|
+
const res = await client.billing.subscription();
|
|
4442
|
+
spinner.stop();
|
|
4443
|
+
if (opts.json) return jsonOut(res.data);
|
|
4444
|
+
const d = res.data;
|
|
4445
|
+
section("Subscription");
|
|
4446
|
+
detail([
|
|
4447
|
+
["Plan", `${d.planName} (${d.planKey})`],
|
|
4448
|
+
["Status", d.status],
|
|
4449
|
+
["Monthly credits", String(d.monthlyCredits)],
|
|
4450
|
+
["Computer use", d.entitlements?.computerUse ? "yes" : "no"],
|
|
4451
|
+
[
|
|
4452
|
+
"Renews",
|
|
4453
|
+
d.currentPeriodEnd ? new Date(d.currentPeriodEnd).toLocaleDateString() : void 0
|
|
4454
|
+
]
|
|
4455
|
+
]);
|
|
4456
|
+
} catch (e) {
|
|
4457
|
+
spinner.stop();
|
|
4458
|
+
console.error(c.error(e.message));
|
|
4459
|
+
process.exit(1);
|
|
4460
|
+
}
|
|
4461
|
+
});
|
|
4462
|
+
cmd.command("upgrade <plan>").description("Start a checkout to upgrade (plus | pro | max)").action(async (plan) => {
|
|
4463
|
+
try {
|
|
4464
|
+
const client = makeClient();
|
|
4465
|
+
const res = await client.billing.subscribe(plan);
|
|
4466
|
+
const url = res?.data?.url;
|
|
4467
|
+
if (!url) {
|
|
4468
|
+
console.error(c.error("Could not create checkout session"));
|
|
4469
|
+
process.exit(1);
|
|
4470
|
+
}
|
|
4471
|
+
console.log(c.dim("Opening checkout in your browser:"));
|
|
4472
|
+
console.log(url);
|
|
4473
|
+
await openBrowser(url);
|
|
4474
|
+
} catch (e) {
|
|
4475
|
+
console.error(c.error(e.message));
|
|
4476
|
+
process.exit(1);
|
|
4477
|
+
}
|
|
4478
|
+
});
|
|
4479
|
+
cmd.command("topup <pack>").description("Buy a one-time credit pack (small | medium | large)").action(async (pack) => {
|
|
4480
|
+
try {
|
|
4481
|
+
const client = makeClient();
|
|
4482
|
+
const res = await client.billing.topup(pack);
|
|
4483
|
+
const url = res?.data?.url;
|
|
4484
|
+
if (!url) {
|
|
4485
|
+
console.error(c.error("Could not create checkout session"));
|
|
4486
|
+
process.exit(1);
|
|
4487
|
+
}
|
|
4488
|
+
console.log(url);
|
|
4489
|
+
await openBrowser(url);
|
|
4490
|
+
} catch (e) {
|
|
4491
|
+
console.error(c.error(e.message));
|
|
4492
|
+
process.exit(1);
|
|
4493
|
+
}
|
|
4494
|
+
});
|
|
4495
|
+
return cmd;
|
|
4496
|
+
}
|
|
4497
|
+
|
|
4017
4498
|
// src/commands/logs.ts
|
|
4018
|
-
var
|
|
4499
|
+
var import_commander17 = require("commander");
|
|
4019
4500
|
var STATUS_COLOR = {
|
|
4020
4501
|
success: (s) => c.bold(s),
|
|
4021
4502
|
error: (s) => c.error(s),
|
|
@@ -4025,25 +4506,26 @@ function colorStatus(status) {
|
|
|
4025
4506
|
return (STATUS_COLOR[status] ?? c.dim)(status);
|
|
4026
4507
|
}
|
|
4027
4508
|
function logsCommand() {
|
|
4028
|
-
const cmd = new
|
|
4509
|
+
const cmd = new import_commander17.Command("logs").description("View agent activity logs");
|
|
4029
4510
|
cmd.command("list").alias("ls").description("List recent log entries for an agent").option("--agent <agentId>", "Agent ID (defaults to configured agent)").option("--session <sessionId>", "Filter by session ID").option("--status <status>", "Filter: success | error | warning").option("--limit <n>", "Max entries to show", "50").option("--json", "Output as JSON").action(async (opts) => {
|
|
4030
4511
|
const cfg = loadConfig();
|
|
4031
|
-
const
|
|
4032
|
-
if (!
|
|
4512
|
+
const agentId2 = opts.agent ?? cfg.defaultAgentId;
|
|
4513
|
+
if (!agentId2) {
|
|
4033
4514
|
console.error(c.error("Specify --agent <agentId> or set defaultAgentId"));
|
|
4034
4515
|
process.exit(1);
|
|
4035
4516
|
}
|
|
4036
4517
|
const spinner = spin("Fetching logs\u2026");
|
|
4037
4518
|
try {
|
|
4038
4519
|
const client = makeClient();
|
|
4039
|
-
const
|
|
4040
|
-
|
|
4041
|
-
|
|
4520
|
+
const res = await client.logs.list(agentId2, {
|
|
4521
|
+
limit: Number(opts.limit),
|
|
4522
|
+
sessionId: opts.session
|
|
4523
|
+
});
|
|
4042
4524
|
let logs = res?.data ?? res ?? [];
|
|
4043
4525
|
if (opts.status) logs = logs.filter((l) => l.status === opts.status);
|
|
4044
4526
|
spinner.stop();
|
|
4045
4527
|
if (opts.json) return jsonOut(logs);
|
|
4046
|
-
section(`Logs \u2014 ${
|
|
4528
|
+
section(`Logs \u2014 ${agentId2.slice(0, 12)}\u2026 (${logs.length})`);
|
|
4047
4529
|
if (logs.length === 0) {
|
|
4048
4530
|
console.log(c.dim(" No logs yet"));
|
|
4049
4531
|
return;
|
|
@@ -4061,26 +4543,28 @@ function logsCommand() {
|
|
|
4061
4543
|
console.log("");
|
|
4062
4544
|
});
|
|
4063
4545
|
} catch (err) {
|
|
4064
|
-
|
|
4546
|
+
spinner.stop();
|
|
4065
4547
|
printError(err);
|
|
4066
4548
|
process.exit(1);
|
|
4067
4549
|
}
|
|
4068
4550
|
});
|
|
4069
4551
|
cmd.command("errors").description("Show only error log entries for an agent").option("--agent <agentId>", "Agent ID").option("--limit <n>", "Max entries", "20").option("--json", "Output as JSON").action(async (opts) => {
|
|
4070
4552
|
const cfg = loadConfig();
|
|
4071
|
-
const
|
|
4072
|
-
if (!
|
|
4553
|
+
const agentId2 = opts.agent ?? cfg.defaultAgentId;
|
|
4554
|
+
if (!agentId2) {
|
|
4073
4555
|
console.error(c.error("Specify --agent <agentId>"));
|
|
4074
4556
|
process.exit(1);
|
|
4075
4557
|
}
|
|
4076
4558
|
const spinner = spin("Fetching error logs\u2026");
|
|
4077
4559
|
try {
|
|
4078
4560
|
const client = makeClient();
|
|
4079
|
-
const res = await client.
|
|
4561
|
+
const res = await client.logs.list(agentId2, {
|
|
4562
|
+
limit: Number(opts.limit)
|
|
4563
|
+
});
|
|
4080
4564
|
const errors = (res?.data ?? []).filter((l) => l.status === "error");
|
|
4081
4565
|
spinner.stop();
|
|
4082
4566
|
if (opts.json) return jsonOut(errors);
|
|
4083
|
-
section(`Errors \u2014 ${
|
|
4567
|
+
section(`Errors \u2014 ${agentId2.slice(0, 12)}\u2026 (${errors.length})`);
|
|
4084
4568
|
if (errors.length === 0) {
|
|
4085
4569
|
console.log(`${sym.ok} No errors found`);
|
|
4086
4570
|
return;
|
|
@@ -4099,33 +4583,783 @@ function logsCommand() {
|
|
|
4099
4583
|
return cmd;
|
|
4100
4584
|
}
|
|
4101
4585
|
|
|
4102
|
-
// src/
|
|
4103
|
-
var
|
|
4104
|
-
|
|
4105
|
-
|
|
4106
|
-
|
|
4107
|
-
|
|
4108
|
-
|
|
4109
|
-
|
|
4110
|
-
|
|
4111
|
-
|
|
4112
|
-
|
|
4113
|
-
|
|
4586
|
+
// src/commands/computer.ts
|
|
4587
|
+
var import_commander18 = require("commander");
|
|
4588
|
+
var RESOURCE_PROFILES = [
|
|
4589
|
+
"starter",
|
|
4590
|
+
"standard",
|
|
4591
|
+
"performance",
|
|
4592
|
+
"gpu"
|
|
4593
|
+
];
|
|
4594
|
+
var RESOURCE_MODES = ["fixed", "elastic"];
|
|
4595
|
+
function resolveAgentId(opts) {
|
|
4596
|
+
const agentId2 = opts.agent ?? loadConfig().defaultAgentId;
|
|
4597
|
+
if (!agentId2) {
|
|
4598
|
+
throw new Error(
|
|
4599
|
+
"Specify --agent <agentId> or set defaultAgentId with `agc config set defaultAgentId <id>`."
|
|
4600
|
+
);
|
|
4601
|
+
}
|
|
4602
|
+
return agentId2;
|
|
4603
|
+
}
|
|
4604
|
+
function unwrap(response) {
|
|
4605
|
+
return response?.data ?? response;
|
|
4606
|
+
}
|
|
4607
|
+
function displayComputer(computer) {
|
|
4608
|
+
if (!computer) {
|
|
4609
|
+
section("Persistent cloud computer");
|
|
4610
|
+
detail([
|
|
4611
|
+
["Status", statusBadge("disabled")],
|
|
4612
|
+
["Persistence", "persistent"],
|
|
4613
|
+
["Computer ID", c.dim("(not provisioned)")]
|
|
4614
|
+
]);
|
|
4615
|
+
console.log(c.dim(" Enable it with: agc computer enable --agent <agentId>"));
|
|
4114
4616
|
return;
|
|
4115
4617
|
}
|
|
4116
|
-
|
|
4117
|
-
|
|
4618
|
+
const wire = computer;
|
|
4619
|
+
const resources = computer.resources ?? {};
|
|
4620
|
+
const gpu = resources.gpu ?? (wire.gpuCount ? { count: wire.gpuCount, type: wire.gpuType } : null);
|
|
4621
|
+
const cpu = resources.vcpu ?? wire.cpuRequest ?? wire.cpuLimit;
|
|
4622
|
+
const memory = resources.memoryGiB != null ? `${resources.memoryGiB} GiB` : wire.memoryRequest ?? wire.memoryLimit;
|
|
4623
|
+
const storage = resources.storageGiB != null ? `${resources.storageGiB} GiB` : wire.storageLimit;
|
|
4624
|
+
section("Persistent cloud computer");
|
|
4625
|
+
detail([
|
|
4626
|
+
["Computer ID", computer.computerId ? c.id(computer.computerId) : c.dim("(not provisioned)")],
|
|
4627
|
+
["Enabled", computer.enabled === false ? "no" : c.success("yes")],
|
|
4628
|
+
["Status", statusBadge(computer.status ?? "disabled")],
|
|
4629
|
+
["Desired state", computer.desiredState ?? c.dim("n/a")],
|
|
4630
|
+
["Persistence", computer.persistence ?? wire.lifecycle ?? "persistent"],
|
|
4631
|
+
["Profile", computer.resourceProfile ?? c.dim("n/a")],
|
|
4632
|
+
["Mode", computer.resourceMode ?? c.dim("n/a")],
|
|
4633
|
+
["CPU", cpu != null ? String(cpu) : c.dim("n/a")],
|
|
4634
|
+
["Memory", memory != null ? String(memory) : c.dim("n/a")],
|
|
4635
|
+
["Storage", storage != null ? String(storage) : c.dim("n/a")],
|
|
4636
|
+
["GPU", gpu?.count ? `${gpu.count} \xD7 ${gpu.type ?? "provider default"}` : "none"],
|
|
4637
|
+
["Region", computer.region ?? c.dim("automatic")],
|
|
4638
|
+
["Workspace", computer.workspaceRoot ?? c.dim("not mounted")],
|
|
4639
|
+
["Last activity", computer.lastActivityAt ? relativeTime(computer.lastActivityAt) : c.dim("never")],
|
|
4640
|
+
["Error", computer.errorMessage ?? void 0]
|
|
4641
|
+
]);
|
|
4642
|
+
}
|
|
4643
|
+
function parseNumber(value, name, options) {
|
|
4644
|
+
if (value === void 0) return void 0;
|
|
4645
|
+
const parsed = Number(value);
|
|
4646
|
+
const minimum = options?.allowZero ? 0 : Number.MIN_VALUE;
|
|
4647
|
+
if (!Number.isFinite(parsed) || parsed < minimum || options?.integer && !Number.isInteger(parsed)) {
|
|
4648
|
+
const qualifier = options?.integer ? "whole number" : "number";
|
|
4649
|
+
throw new Error(`${name} must be a ${options?.allowZero ? "non-negative" : "positive"} ${qualifier}.`);
|
|
4650
|
+
}
|
|
4651
|
+
return parsed;
|
|
4652
|
+
}
|
|
4653
|
+
async function changeEnabled(agentId2, enabled, json) {
|
|
4654
|
+
const spinner = spin(`${enabled ? "Enabling" : "Disabling"} persistent cloud computer\u2026`);
|
|
4655
|
+
try {
|
|
4656
|
+
const response = await makeClient().agents.updateComputerConfig(agentId2, { enabled });
|
|
4657
|
+
const config = unwrap(response);
|
|
4658
|
+
spinner.stop();
|
|
4659
|
+
if (json) return jsonOut(config);
|
|
4660
|
+
console.log(`
|
|
4661
|
+
${sym.ok} Persistent cloud computer ${enabled ? "enabled" : "disabled"} for agent ${c.id(agentId2)}`);
|
|
4662
|
+
if (enabled) {
|
|
4663
|
+
console.log(c.dim(` Wake it now with: agc computer wake --agent ${agentId2}`));
|
|
4664
|
+
}
|
|
4665
|
+
} catch (error) {
|
|
4666
|
+
spinner.stop();
|
|
4667
|
+
printError(error);
|
|
4668
|
+
process.exitCode = 1;
|
|
4669
|
+
}
|
|
4670
|
+
}
|
|
4671
|
+
async function lifecycleAction(action, agentId2, reason, json) {
|
|
4672
|
+
const verb = action === "wake" ? "Waking" : action === "sleep" ? "Sleeping" : "Restarting";
|
|
4673
|
+
const spinner = spin(`${verb} persistent cloud computer\u2026`);
|
|
4674
|
+
try {
|
|
4675
|
+
const client = makeClient();
|
|
4676
|
+
const response = action === "wake" ? await client.agents.wakeComputer(agentId2, reason ? { reason } : void 0) : action === "sleep" ? await client.agents.sleepComputer(agentId2, reason ? { reason } : void 0) : await client.agents.restartComputer(agentId2, reason ? { reason } : void 0);
|
|
4677
|
+
const computer = unwrap(response);
|
|
4678
|
+
spinner.stop();
|
|
4679
|
+
if (json) return jsonOut(computer);
|
|
4680
|
+
console.log(`
|
|
4681
|
+
${sym.ok} Persistent cloud computer ${action === "sleep" ? "is sleeping" : action === "wake" ? "is awake" : "restarted"}`);
|
|
4682
|
+
displayComputer(computer);
|
|
4683
|
+
} catch (error) {
|
|
4684
|
+
spinner.stop();
|
|
4685
|
+
printError(error);
|
|
4686
|
+
process.exitCode = 1;
|
|
4687
|
+
}
|
|
4688
|
+
}
|
|
4689
|
+
function addAgentOption(command) {
|
|
4690
|
+
return command.option("--agent <agentId>", "Agent ID (defaults to configured agent)");
|
|
4691
|
+
}
|
|
4692
|
+
function computerCommand() {
|
|
4693
|
+
const command = new import_commander18.Command("computer").description("Manage an agent's one persistent cloud computer");
|
|
4694
|
+
addAgentOption(command.command("status").description("Show persistent cloud computer status")).option("--json", "Output as JSON").action(async (opts) => {
|
|
4695
|
+
let agentId2;
|
|
4696
|
+
try {
|
|
4697
|
+
agentId2 = resolveAgentId(opts);
|
|
4698
|
+
} catch (error) {
|
|
4699
|
+
printError(error);
|
|
4700
|
+
process.exitCode = 1;
|
|
4701
|
+
return;
|
|
4702
|
+
}
|
|
4703
|
+
const spinner = spin("Fetching persistent cloud computer\u2026");
|
|
4704
|
+
try {
|
|
4705
|
+
const computer = unwrap(await makeClient().agents.getComputer(agentId2));
|
|
4706
|
+
spinner.stop();
|
|
4707
|
+
if (opts.json) return jsonOut(computer);
|
|
4708
|
+
displayComputer(computer);
|
|
4709
|
+
} catch (error) {
|
|
4710
|
+
spinner.stop();
|
|
4711
|
+
printError(error);
|
|
4712
|
+
process.exitCode = 1;
|
|
4713
|
+
}
|
|
4714
|
+
});
|
|
4715
|
+
addAgentOption(command.command("enable").description("Enable a persistent cloud computer for an agent")).option("--json", "Output as JSON").action(async (opts) => {
|
|
4716
|
+
try {
|
|
4717
|
+
await changeEnabled(resolveAgentId(opts), true, !!opts.json);
|
|
4718
|
+
} catch (error) {
|
|
4719
|
+
printError(error);
|
|
4720
|
+
process.exitCode = 1;
|
|
4721
|
+
}
|
|
4722
|
+
});
|
|
4723
|
+
addAgentOption(command.command("disable").description("Disable the agent cloud computer")).option("--json", "Output as JSON").action(async (opts) => {
|
|
4724
|
+
try {
|
|
4725
|
+
await changeEnabled(resolveAgentId(opts), false, !!opts.json);
|
|
4726
|
+
} catch (error) {
|
|
4727
|
+
printError(error);
|
|
4728
|
+
process.exitCode = 1;
|
|
4729
|
+
}
|
|
4730
|
+
});
|
|
4731
|
+
for (const action of ["wake", "sleep", "restart"]) {
|
|
4732
|
+
const descriptions = {
|
|
4733
|
+
wake: "Wake the persistent cloud computer",
|
|
4734
|
+
sleep: "Sleep compute while preserving the persistent workspace",
|
|
4735
|
+
restart: "Restart the runtime while preserving the persistent workspace"
|
|
4736
|
+
};
|
|
4737
|
+
addAgentOption(command.command(action).description(descriptions[action])).option("--reason <text>", `Reason for the ${action}`).option("--json", "Output as JSON").action(async (opts) => {
|
|
4738
|
+
try {
|
|
4739
|
+
await lifecycleAction(action, resolveAgentId(opts), opts.reason, !!opts.json);
|
|
4740
|
+
} catch (error) {
|
|
4741
|
+
printError(error);
|
|
4742
|
+
process.exitCode = 1;
|
|
4743
|
+
}
|
|
4744
|
+
});
|
|
4745
|
+
}
|
|
4746
|
+
addAgentOption(command.command("resize").description("Resize the persistent cloud computer")).option("--profile <profile>", `Resource profile: ${RESOURCE_PROFILES.join(" | ")}`).option("--mode <mode>", `Resource mode: ${RESOURCE_MODES.join(" | ")}`).option("--vcpu <count>", "Requested virtual CPU count").option("--cpu <count>", "Alias for --vcpu").option("--memory <gib>", "Requested memory in GiB").option("--storage <gib>", "Requested persistent storage in GiB").option("--gpu-type <type>", "GPU type, such as nvidia-h100").option("--gpu-count <count>", "GPU count (0 removes GPU allocation)").option("--json", "Output as JSON").action(async (opts) => {
|
|
4747
|
+
let agentId2;
|
|
4748
|
+
let resize;
|
|
4749
|
+
try {
|
|
4750
|
+
agentId2 = resolveAgentId(opts);
|
|
4751
|
+
if (opts.profile && !RESOURCE_PROFILES.includes(opts.profile)) {
|
|
4752
|
+
throw new Error(`--profile must be one of: ${RESOURCE_PROFILES.join(", ")}.`);
|
|
4753
|
+
}
|
|
4754
|
+
if (opts.mode && !RESOURCE_MODES.includes(opts.mode)) {
|
|
4755
|
+
throw new Error(`--mode must be one of: ${RESOURCE_MODES.join(", ")}.`);
|
|
4756
|
+
}
|
|
4757
|
+
if (opts.vcpu !== void 0 && opts.cpu !== void 0) {
|
|
4758
|
+
throw new Error("Use either --vcpu or --cpu, not both.");
|
|
4759
|
+
}
|
|
4760
|
+
const vcpu = parseNumber(opts.vcpu ?? opts.cpu, "CPU");
|
|
4761
|
+
const memoryGiB = parseNumber(opts.memory, "Memory");
|
|
4762
|
+
const storageGiB = parseNumber(opts.storage, "Storage");
|
|
4763
|
+
const gpuCount = parseNumber(opts.gpuCount, "GPU count", { integer: true, allowZero: true });
|
|
4764
|
+
const resources = {
|
|
4765
|
+
...vcpu !== void 0 && { vcpu },
|
|
4766
|
+
...memoryGiB !== void 0 && { memoryGiB },
|
|
4767
|
+
...storageGiB !== void 0 && { storageGiB },
|
|
4768
|
+
...(gpuCount !== void 0 || opts.gpuType) && {
|
|
4769
|
+
gpu: { count: gpuCount ?? 1, ...opts.gpuType && { type: opts.gpuType } }
|
|
4770
|
+
}
|
|
4771
|
+
};
|
|
4772
|
+
resize = {
|
|
4773
|
+
...opts.profile && { resourceProfile: opts.profile },
|
|
4774
|
+
...opts.mode && { resourceMode: opts.mode },
|
|
4775
|
+
...Object.keys(resources).length > 0 && { resources }
|
|
4776
|
+
};
|
|
4777
|
+
if (Object.keys(resize).length === 0) {
|
|
4778
|
+
throw new Error("Specify --profile, --mode, or at least one resource value.");
|
|
4779
|
+
}
|
|
4780
|
+
} catch (error) {
|
|
4781
|
+
printError(error);
|
|
4782
|
+
process.exitCode = 1;
|
|
4783
|
+
return;
|
|
4784
|
+
}
|
|
4785
|
+
const spinner = spin("Resizing persistent cloud computer\u2026");
|
|
4786
|
+
try {
|
|
4787
|
+
const computer = unwrap(await makeClient().agents.resizeComputer(agentId2, resize));
|
|
4788
|
+
spinner.stop();
|
|
4789
|
+
if (opts.json) return jsonOut(computer);
|
|
4790
|
+
console.log(`
|
|
4791
|
+
${sym.ok} Persistent cloud computer resize requested`);
|
|
4792
|
+
displayComputer(computer);
|
|
4793
|
+
} catch (error) {
|
|
4794
|
+
spinner.stop();
|
|
4795
|
+
printError(error);
|
|
4796
|
+
process.exitCode = 1;
|
|
4797
|
+
}
|
|
4798
|
+
});
|
|
4799
|
+
addAgentOption(
|
|
4800
|
+
command.command("exec").description("Run a command in the persistent cloud computer").argument("<command...>", "Command and arguments to run")
|
|
4801
|
+
).option("--cwd <path>", "Working directory").option("--timeout <seconds>", "Command timeout in seconds", "120").option("--json", "Output as JSON").action(async (commandParts, opts) => {
|
|
4802
|
+
let agentId2;
|
|
4803
|
+
let timeoutSeconds;
|
|
4804
|
+
try {
|
|
4805
|
+
agentId2 = resolveAgentId(opts);
|
|
4806
|
+
timeoutSeconds = parseNumber(opts.timeout, "Timeout");
|
|
4807
|
+
} catch (error) {
|
|
4808
|
+
printError(error);
|
|
4809
|
+
process.exitCode = 1;
|
|
4810
|
+
return;
|
|
4811
|
+
}
|
|
4812
|
+
const spinner = spin("Running command in persistent cloud computer\u2026");
|
|
4813
|
+
try {
|
|
4814
|
+
const result = unwrap(await makeClient().agents.execComputer(agentId2, {
|
|
4815
|
+
command: commandParts.join(" "),
|
|
4816
|
+
...opts.cwd && { cwd: opts.cwd },
|
|
4817
|
+
...timeoutSeconds !== void 0 && { timeoutSeconds }
|
|
4818
|
+
}));
|
|
4819
|
+
spinner.stop();
|
|
4820
|
+
if (opts.json) return jsonOut(result);
|
|
4821
|
+
const stdout = result?.stdout ?? result?.output ?? result?.result ?? "";
|
|
4822
|
+
const stderr = result?.stderr ?? "";
|
|
4823
|
+
if (stdout) process.stdout.write(String(stdout).replace(/\n?$/, "\n"));
|
|
4824
|
+
if (stderr) process.stderr.write(c.error(String(stderr).replace(/\n?$/, "\n")));
|
|
4825
|
+
const exitCode = result?.exitCode ?? result?.exit_code;
|
|
4826
|
+
if (exitCode !== void 0 && exitCode !== 0) process.exitCode = Number(exitCode);
|
|
4827
|
+
} catch (error) {
|
|
4828
|
+
spinner.stop();
|
|
4829
|
+
printError(error);
|
|
4830
|
+
process.exitCode = 1;
|
|
4831
|
+
}
|
|
4832
|
+
});
|
|
4833
|
+
addAgentOption(command.command("events").description("List recent persistent cloud computer events")).option("--limit <count>", "Maximum events", "50").option("--json", "Output as JSON").action(async (opts) => {
|
|
4834
|
+
let agentId2;
|
|
4835
|
+
let limit;
|
|
4836
|
+
try {
|
|
4837
|
+
agentId2 = resolveAgentId(opts);
|
|
4838
|
+
limit = parseNumber(opts.limit, "Limit", { integer: true });
|
|
4839
|
+
} catch (error) {
|
|
4840
|
+
printError(error);
|
|
4841
|
+
process.exitCode = 1;
|
|
4842
|
+
return;
|
|
4843
|
+
}
|
|
4844
|
+
const spinner = spin("Fetching persistent cloud computer events\u2026");
|
|
4845
|
+
try {
|
|
4846
|
+
const events = unwrap(await makeClient().agents.listComputerEvents(agentId2, limit));
|
|
4847
|
+
spinner.stop();
|
|
4848
|
+
if (opts.json) return jsonOut(events);
|
|
4849
|
+
section(`Cloud computer events (${events.length})`);
|
|
4850
|
+
table(
|
|
4851
|
+
events.map((event) => ({
|
|
4852
|
+
Event: event.eventType ?? "",
|
|
4853
|
+
Summary: event.summary ?? "",
|
|
4854
|
+
Actor: event.actorType ?? "",
|
|
4855
|
+
When: event.createdAt ? relativeTime(event.createdAt) : ""
|
|
4856
|
+
})),
|
|
4857
|
+
["Event", "Summary", "Actor", "When"]
|
|
4858
|
+
);
|
|
4859
|
+
} catch (error) {
|
|
4860
|
+
spinner.stop();
|
|
4861
|
+
printError(error);
|
|
4862
|
+
process.exitCode = 1;
|
|
4863
|
+
}
|
|
4864
|
+
});
|
|
4865
|
+
return command;
|
|
4866
|
+
}
|
|
4867
|
+
|
|
4868
|
+
// src/commands/library.ts
|
|
4869
|
+
var import_commander19 = require("commander");
|
|
4870
|
+
var import_fs7 = require("fs");
|
|
4871
|
+
var import_path5 = require("path");
|
|
4872
|
+
function libraryCommand() {
|
|
4873
|
+
const command = new import_commander19.Command("library").alias("files").description("Upload, find, and manage files in your Commons library");
|
|
4874
|
+
command.command("list", { isDefault: true }).alias("ls").description("List library items").option("--query <text>", "Search names and descriptions").option("--source <source>", "Filter by source").option("--session <sessionId>", "Filter by session").option("--favorites", "Show favorites only").option("--limit <n>", "Maximum items", "50").option("--json", "Output as JSON").action(async (opts) => {
|
|
4875
|
+
const spinner = spin("Fetching your library\u2026");
|
|
4876
|
+
try {
|
|
4877
|
+
const result = await makeClient().library.list({
|
|
4878
|
+
query: opts.query,
|
|
4879
|
+
source: opts.source,
|
|
4880
|
+
sessionId: opts.session,
|
|
4881
|
+
favorite: opts.favorites ? true : void 0,
|
|
4882
|
+
limit: Number(opts.limit)
|
|
4883
|
+
});
|
|
4884
|
+
spinner.stop();
|
|
4885
|
+
if (opts.json) return jsonOut(result);
|
|
4886
|
+
section(`Library (${result.data.length})`);
|
|
4887
|
+
table(
|
|
4888
|
+
result.data.map((item) => ({
|
|
4889
|
+
ID: String(item.itemId ?? item.fileId).slice(0, 10) + "\u2026",
|
|
4890
|
+
Name: item.name ?? item.originalName ?? "(untitled)",
|
|
4891
|
+
Type: item.mimeType ?? "",
|
|
4892
|
+
Size: typeof item.size === "number" ? `${Math.ceil(item.size / 1024)} KB` : "",
|
|
4893
|
+
Favorite: item.isFavorite ? "\u2605" : "",
|
|
4894
|
+
Created: item.createdAt ? relativeTime(item.createdAt) : ""
|
|
4895
|
+
})),
|
|
4896
|
+
["ID", "Name", "Type", "Size", "Favorite", "Created"]
|
|
4897
|
+
);
|
|
4898
|
+
} catch (error) {
|
|
4899
|
+
spinner.stop();
|
|
4900
|
+
printError(error);
|
|
4901
|
+
process.exit(1);
|
|
4902
|
+
}
|
|
4903
|
+
});
|
|
4904
|
+
command.command("get <itemId>").description("Show library item details").option("--json", "Output as JSON").action(async (itemId, opts) => {
|
|
4905
|
+
const spinner = spin("Fetching library item\u2026");
|
|
4906
|
+
try {
|
|
4907
|
+
const result = await makeClient().library.get(itemId);
|
|
4908
|
+
spinner.stop();
|
|
4909
|
+
if (opts.json) return jsonOut(result.data);
|
|
4910
|
+
const item = result.data;
|
|
4911
|
+
detail([
|
|
4912
|
+
["Item ID", c.id(String(item.itemId ?? item.fileId))],
|
|
4913
|
+
["Name", item.name ?? item.originalName ?? "(untitled)"],
|
|
4914
|
+
["Description", item.description ?? ""],
|
|
4915
|
+
["Type", item.mimeType ?? ""],
|
|
4916
|
+
["Storage", item.storageProvider ?? ""],
|
|
4917
|
+
["Favorite", item.isFavorite ? "yes" : "no"],
|
|
4918
|
+
["Created", item.createdAt ? relativeTime(item.createdAt) : ""]
|
|
4919
|
+
]);
|
|
4920
|
+
} catch (error) {
|
|
4921
|
+
spinner.stop();
|
|
4922
|
+
printError(error);
|
|
4923
|
+
process.exit(1);
|
|
4924
|
+
}
|
|
4925
|
+
});
|
|
4926
|
+
command.command("upload <paths...>").description("Upload one or more local files").option("--agent <agentId>", "Associate files with an agent").option("--session <sessionId>", "Associate files with a session").option("--storage <provider>", "Storage provider: s3 | ipfs").option("--json", "Output as JSON").action(async (paths, opts) => {
|
|
4927
|
+
const spinner = spin(`Uploading ${paths.length} file${paths.length === 1 ? "" : "s"}\u2026`);
|
|
4928
|
+
try {
|
|
4929
|
+
if (opts.storage && opts.storage !== "s3" && opts.storage !== "ipfs") {
|
|
4930
|
+
throw new Error("--storage must be either s3 or ipfs.");
|
|
4931
|
+
}
|
|
4932
|
+
const files = paths.map((path) => ({
|
|
4933
|
+
data: new Blob([new Uint8Array((0, import_fs7.readFileSync)(path))]),
|
|
4934
|
+
name: (0, import_path5.basename)(path)
|
|
4935
|
+
}));
|
|
4936
|
+
const result = await makeClient().files.upload(files, {
|
|
4937
|
+
agentId: opts.agent,
|
|
4938
|
+
sessionId: opts.session,
|
|
4939
|
+
storageProvider: opts.storage
|
|
4940
|
+
});
|
|
4941
|
+
spinner.stop();
|
|
4942
|
+
if (opts.json) return jsonOut(result.data);
|
|
4943
|
+
console.log(
|
|
4944
|
+
`
|
|
4945
|
+
${sym.ok} Uploaded ${result.data.length} file${result.data.length === 1 ? "" : "s"}.`
|
|
4946
|
+
);
|
|
4947
|
+
for (const file of result.data) {
|
|
4948
|
+
console.log(
|
|
4949
|
+
` ${sym.arrow} ${c.bold(file.name ?? file.originalName ?? file.fileId)} ${c.dim(file.fileId)}`
|
|
4950
|
+
);
|
|
4951
|
+
}
|
|
4952
|
+
} catch (error) {
|
|
4953
|
+
spinner.stop();
|
|
4954
|
+
printError(error);
|
|
4955
|
+
process.exit(1);
|
|
4956
|
+
}
|
|
4957
|
+
});
|
|
4958
|
+
for (const favorite of [true, false]) {
|
|
4959
|
+
command.command(`${favorite ? "favorite" : "unfavorite"} <itemId>`).description(`${favorite ? "Add" : "Remove"} a library item ${favorite ? "to" : "from"} favorites`).action(async (itemId) => {
|
|
4960
|
+
const spinner = spin("Updating library item\u2026");
|
|
4961
|
+
try {
|
|
4962
|
+
await makeClient().library.update(itemId, {
|
|
4963
|
+
isFavorite: favorite
|
|
4964
|
+
});
|
|
4965
|
+
spinner.stop();
|
|
4966
|
+
console.log(
|
|
4967
|
+
`${sym.ok} Item ${favorite ? "added to" : "removed from"} favorites.`
|
|
4968
|
+
);
|
|
4969
|
+
} catch (error) {
|
|
4970
|
+
spinner.stop();
|
|
4971
|
+
printError(error);
|
|
4972
|
+
process.exit(1);
|
|
4973
|
+
}
|
|
4974
|
+
});
|
|
4975
|
+
}
|
|
4976
|
+
command.command("delete <itemId>").description("Delete a library item").action(async (itemId) => {
|
|
4977
|
+
const spinner = spin("Deleting library item\u2026");
|
|
4978
|
+
try {
|
|
4979
|
+
await makeClient().library.delete(itemId);
|
|
4980
|
+
spinner.stop();
|
|
4981
|
+
console.log(`${sym.ok} Library item deleted.`);
|
|
4982
|
+
} catch (error) {
|
|
4983
|
+
spinner.stop();
|
|
4984
|
+
printError(error);
|
|
4985
|
+
process.exit(1);
|
|
4986
|
+
}
|
|
4987
|
+
});
|
|
4988
|
+
return command;
|
|
4989
|
+
}
|
|
4990
|
+
|
|
4991
|
+
// src/commands/projects.ts
|
|
4992
|
+
var import_commander20 = require("commander");
|
|
4993
|
+
var import_fs8 = require("fs");
|
|
4994
|
+
function agentId(value) {
|
|
4995
|
+
const resolved = value ?? loadConfig().defaultAgentId;
|
|
4996
|
+
if (!resolved) {
|
|
4997
|
+
throw new Error(
|
|
4998
|
+
"Specify --agent <agentId> or set a default with `agc config set defaultAgentId <id>`."
|
|
4999
|
+
);
|
|
5000
|
+
}
|
|
5001
|
+
return resolved;
|
|
5002
|
+
}
|
|
5003
|
+
function projectFiles(path) {
|
|
5004
|
+
if (!path) return void 0;
|
|
5005
|
+
const parsed = JSON.parse((0, import_fs8.readFileSync)(path, "utf8"));
|
|
5006
|
+
const files = Array.isArray(parsed) ? parsed : parsed.files;
|
|
5007
|
+
if (!Array.isArray(files)) {
|
|
5008
|
+
throw new Error("The files document must be an array or an object with a files array.");
|
|
5009
|
+
}
|
|
5010
|
+
return files;
|
|
5011
|
+
}
|
|
5012
|
+
function projectsCommand() {
|
|
5013
|
+
const command = new import_commander20.Command("projects").alias("project").description("Build, publish, and export agent code projects");
|
|
5014
|
+
command.command("list", { isDefault: true }).alias("ls").description("List projects for an agent").option("--agent <agentId>", "Agent ID").option("--json", "Output as JSON").action(async (opts) => {
|
|
5015
|
+
const spinner = spin("Fetching projects\u2026");
|
|
5016
|
+
try {
|
|
5017
|
+
const result = await makeClient().projects.list(agentId(opts.agent));
|
|
5018
|
+
spinner.stop();
|
|
5019
|
+
if (opts.json) return jsonOut(result.data);
|
|
5020
|
+
section(`Projects (${result.data.length})`);
|
|
5021
|
+
table(
|
|
5022
|
+
result.data.map((project) => ({
|
|
5023
|
+
ID: project.projectId.slice(0, 10) + "\u2026",
|
|
5024
|
+
Name: project.name,
|
|
5025
|
+
Files: String(project.files?.length ?? ""),
|
|
5026
|
+
Preview: project.previewUrl ?? project.previewSlug ?? "",
|
|
5027
|
+
Updated: project.updatedAt ?? ""
|
|
5028
|
+
})),
|
|
5029
|
+
["ID", "Name", "Files", "Preview", "Updated"]
|
|
5030
|
+
);
|
|
5031
|
+
} catch (error) {
|
|
5032
|
+
spinner.stop();
|
|
5033
|
+
printError(error);
|
|
5034
|
+
process.exit(1);
|
|
5035
|
+
}
|
|
5036
|
+
});
|
|
5037
|
+
command.command("get <projectId>").description("Show a code project").option("--agent <agentId>", "Agent ID").option("--json", "Output as JSON").action(async (projectId, opts) => {
|
|
5038
|
+
const spinner = spin("Fetching project\u2026");
|
|
5039
|
+
try {
|
|
5040
|
+
const result = await makeClient().projects.get(
|
|
5041
|
+
agentId(opts.agent),
|
|
5042
|
+
projectId
|
|
5043
|
+
);
|
|
5044
|
+
spinner.stop();
|
|
5045
|
+
if (opts.json) return jsonOut(result.data);
|
|
5046
|
+
const project = result.data;
|
|
5047
|
+
section(project.name);
|
|
5048
|
+
detail([
|
|
5049
|
+
["Project ID", c.id(project.projectId)],
|
|
5050
|
+
["Agent ID", project.agentId],
|
|
5051
|
+
["Description", project.description ?? ""],
|
|
5052
|
+
["Files", String(project.files?.length ?? 0)],
|
|
5053
|
+
["Preview", project.previewUrl ?? project.previewSlug ?? ""],
|
|
5054
|
+
["Updated", project.updatedAt ?? ""]
|
|
5055
|
+
]);
|
|
5056
|
+
} catch (error) {
|
|
5057
|
+
spinner.stop();
|
|
5058
|
+
printError(error);
|
|
5059
|
+
process.exit(1);
|
|
5060
|
+
}
|
|
5061
|
+
});
|
|
5062
|
+
command.command("create").description("Create a code project").requiredOption("--name <name>", "Project name").option("--description <text>", "Project description").option("--agent <agentId>", "Agent ID").option("--session <sessionId>", "Associated session").option("--files <json>", "JSON file containing [{ path, content }]").option("--json", "Output as JSON").action(async (opts) => {
|
|
5063
|
+
const spinner = spin("Creating project\u2026");
|
|
5064
|
+
try {
|
|
5065
|
+
const result = await makeClient().projects.create(
|
|
5066
|
+
agentId(opts.agent),
|
|
5067
|
+
{
|
|
5068
|
+
name: opts.name,
|
|
5069
|
+
description: opts.description,
|
|
5070
|
+
sessionId: opts.session,
|
|
5071
|
+
files: projectFiles(opts.files)
|
|
5072
|
+
}
|
|
5073
|
+
);
|
|
5074
|
+
spinner.stop();
|
|
5075
|
+
if (opts.json) return jsonOut(result.data);
|
|
5076
|
+
console.log(`
|
|
5077
|
+
${sym.ok} Project created.`);
|
|
5078
|
+
detail([
|
|
5079
|
+
["Project ID", c.id(result.data.projectId)],
|
|
5080
|
+
["Name", result.data.name]
|
|
5081
|
+
]);
|
|
5082
|
+
} catch (error) {
|
|
5083
|
+
spinner.stop();
|
|
5084
|
+
printError(error);
|
|
5085
|
+
process.exit(1);
|
|
5086
|
+
}
|
|
5087
|
+
});
|
|
5088
|
+
command.command("write <projectId> <json>").description("Write project files from a JSON document").option("--agent <agentId>", "Agent ID").option("--replace", "Replace all existing files").option("--json", "Output as JSON").action(async (projectId, json, opts) => {
|
|
5089
|
+
const spinner = spin("Writing project files\u2026");
|
|
5090
|
+
try {
|
|
5091
|
+
const result = await makeClient().projects.writeFiles(
|
|
5092
|
+
agentId(opts.agent),
|
|
5093
|
+
projectId,
|
|
5094
|
+
projectFiles(json) ?? [],
|
|
5095
|
+
Boolean(opts.replace)
|
|
5096
|
+
);
|
|
5097
|
+
spinner.stop();
|
|
5098
|
+
if (opts.json) return jsonOut(result.data);
|
|
5099
|
+
console.log(`${sym.ok} Project files updated.`);
|
|
5100
|
+
} catch (error) {
|
|
5101
|
+
spinner.stop();
|
|
5102
|
+
printError(error);
|
|
5103
|
+
process.exit(1);
|
|
5104
|
+
}
|
|
5105
|
+
});
|
|
5106
|
+
command.command("publish <projectId>").description("Build and publish a project preview").option("--agent <agentId>", "Agent ID").option("--json", "Output as JSON").action(async (projectId, opts) => {
|
|
5107
|
+
const spinner = spin("Building and publishing project\u2026");
|
|
5108
|
+
try {
|
|
5109
|
+
const result = await makeClient().projects.publish(
|
|
5110
|
+
agentId(opts.agent),
|
|
5111
|
+
projectId
|
|
5112
|
+
);
|
|
5113
|
+
spinner.stop();
|
|
5114
|
+
if (opts.json) return jsonOut(result.data);
|
|
5115
|
+
console.log(`
|
|
5116
|
+
${sym.ok} Project published.`);
|
|
5117
|
+
jsonOut(result.data);
|
|
5118
|
+
} catch (error) {
|
|
5119
|
+
spinner.stop();
|
|
5120
|
+
printError(error);
|
|
5121
|
+
process.exit(1);
|
|
5122
|
+
}
|
|
5123
|
+
});
|
|
5124
|
+
command.command("export <projectId>").description("Export a project to the agent computer").option("--agent <agentId>", "Agent ID").option("--directory <path>", "Destination directory").option("--session <sessionId>", "Associated session").option("--json", "Output as JSON").action(async (projectId, opts) => {
|
|
5125
|
+
const spinner = spin("Exporting project\u2026");
|
|
5126
|
+
try {
|
|
5127
|
+
const result = await makeClient().projects.exportToComputer(
|
|
5128
|
+
agentId(opts.agent),
|
|
5129
|
+
projectId,
|
|
5130
|
+
{ directory: opts.directory, sessionId: opts.session }
|
|
5131
|
+
);
|
|
5132
|
+
spinner.stop();
|
|
5133
|
+
if (opts.json) return jsonOut(result.data);
|
|
5134
|
+
console.log(`${sym.ok} Project exported to the agent computer.`);
|
|
5135
|
+
jsonOut(result.data);
|
|
5136
|
+
} catch (error) {
|
|
5137
|
+
spinner.stop();
|
|
5138
|
+
printError(error);
|
|
5139
|
+
process.exit(1);
|
|
5140
|
+
}
|
|
5141
|
+
});
|
|
5142
|
+
command.command("github <projectId>").description("Export a project to a GitHub repository").option("--agent <agentId>", "Agent ID").option("--repository <name>", "Repository name").option("--public", "Create a public repository").option("--json", "Output as JSON").action(async (projectId, opts) => {
|
|
5143
|
+
const spinner = spin("Exporting project to GitHub\u2026");
|
|
5144
|
+
try {
|
|
5145
|
+
const result = await makeClient().projects.exportToGitHub(
|
|
5146
|
+
agentId(opts.agent),
|
|
5147
|
+
projectId,
|
|
5148
|
+
{
|
|
5149
|
+
repositoryName: opts.repository,
|
|
5150
|
+
private: !opts.public
|
|
5151
|
+
}
|
|
5152
|
+
);
|
|
5153
|
+
spinner.stop();
|
|
5154
|
+
if (opts.json) return jsonOut(result.data);
|
|
5155
|
+
console.log(`${sym.ok} Project exported to GitHub.`);
|
|
5156
|
+
jsonOut(result.data);
|
|
5157
|
+
} catch (error) {
|
|
5158
|
+
spinner.stop();
|
|
5159
|
+
printError(error);
|
|
5160
|
+
process.exit(1);
|
|
5161
|
+
}
|
|
5162
|
+
});
|
|
5163
|
+
return command;
|
|
5164
|
+
}
|
|
5165
|
+
|
|
5166
|
+
// src/commands/api-keys.ts
|
|
5167
|
+
var import_commander21 = require("commander");
|
|
5168
|
+
async function resolveProject(projectId) {
|
|
5169
|
+
const projects = (await makeClient().developer.listProjects()).data;
|
|
5170
|
+
const project = projectId ? projects.find((candidate) => candidate.id === projectId) : projects[0];
|
|
5171
|
+
if (!project) {
|
|
5172
|
+
throw new Error(
|
|
5173
|
+
projectId ? `Developer project "${projectId}" was not found.` : "No developer project exists. Create one with `agc keys projects create --name <name>`."
|
|
5174
|
+
);
|
|
5175
|
+
}
|
|
5176
|
+
return project;
|
|
5177
|
+
}
|
|
5178
|
+
function apiKeysCommand() {
|
|
5179
|
+
const command = new import_commander21.Command("keys").alias("api-keys").description("Create and manage project-scoped developer API keys");
|
|
5180
|
+
command.command("list", { isDefault: true }).alias("ls").description("List API keys for a developer project").option("--project <projectId>", "Developer project ID (defaults to newest)").option("--json", "Output as JSON").action(async (opts) => {
|
|
5181
|
+
const spinner = spin("Fetching developer keys\u2026");
|
|
5182
|
+
try {
|
|
5183
|
+
const project = await resolveProject(opts.project);
|
|
5184
|
+
const result = await makeClient().developer.listApiKeys(project.id);
|
|
5185
|
+
spinner.stop();
|
|
5186
|
+
if (opts.json) {
|
|
5187
|
+
return jsonOut({ project, keys: result.data });
|
|
5188
|
+
}
|
|
5189
|
+
section(`${project.name} \xB7 API keys (${result.data.length})`);
|
|
5190
|
+
table(
|
|
5191
|
+
result.data.map((key) => ({
|
|
5192
|
+
ID: key.id.slice(0, 10) + "\u2026",
|
|
5193
|
+
Name: key.name,
|
|
5194
|
+
Prefix: key.keyPrefix,
|
|
5195
|
+
Status: key.status,
|
|
5196
|
+
Scopes: String(key.scopes.length),
|
|
5197
|
+
Expires: key.expiresAt ? new Date(key.expiresAt).toLocaleDateString() : "never",
|
|
5198
|
+
Used: key.lastUsedAt ? new Date(key.lastUsedAt).toLocaleDateString() : "never"
|
|
5199
|
+
})),
|
|
5200
|
+
["ID", "Name", "Prefix", "Status", "Scopes", "Expires", "Used"]
|
|
5201
|
+
);
|
|
5202
|
+
} catch (error) {
|
|
5203
|
+
spinner.stop();
|
|
5204
|
+
printError(error);
|
|
5205
|
+
process.exit(1);
|
|
5206
|
+
}
|
|
5207
|
+
});
|
|
5208
|
+
command.command("create").description("Create a project-scoped API key").requiredOption("--name <name>", "Key name").option("--project <projectId>", "Developer project ID (defaults to newest)").option("--scopes <scopes>", "Comma-separated scopes (defaults to all project scopes)").option("--expires <iso>", "Expiration timestamp in ISO 8601 format").option("--json", "Output as JSON").action(async (opts) => {
|
|
5209
|
+
const spinner = spin("Creating developer key\u2026");
|
|
5210
|
+
try {
|
|
5211
|
+
const project = await resolveProject(opts.project);
|
|
5212
|
+
const scopes = opts.scopes ? String(opts.scopes).split(",").map((scope) => scope.trim()).filter(Boolean) : void 0;
|
|
5213
|
+
const result = await makeClient().developer.createApiKey(project.id, {
|
|
5214
|
+
name: opts.name,
|
|
5215
|
+
scopes,
|
|
5216
|
+
expiresAt: opts.expires
|
|
5217
|
+
});
|
|
5218
|
+
spinner.stop();
|
|
5219
|
+
if (opts.json) return jsonOut(result.data);
|
|
5220
|
+
console.log(`
|
|
5221
|
+
${sym.ok} ${c.success("Developer API key created")}`);
|
|
5222
|
+
detail([
|
|
5223
|
+
["Project", project.name],
|
|
5224
|
+
["Name", result.data.name],
|
|
5225
|
+
["Scopes", result.data.scopes.join(", ")],
|
|
5226
|
+
["Expires", result.data.expiresAt ?? "never"]
|
|
5227
|
+
]);
|
|
5228
|
+
console.log(
|
|
5229
|
+
`
|
|
5230
|
+
${c.warn("Copy this key now. It will not be shown again.")}`
|
|
5231
|
+
);
|
|
5232
|
+
console.log(`
|
|
5233
|
+
${c.bold(result.data.key)}
|
|
5234
|
+
`);
|
|
5235
|
+
} catch (error) {
|
|
5236
|
+
spinner.stop();
|
|
5237
|
+
printError(error);
|
|
5238
|
+
process.exit(1);
|
|
5239
|
+
}
|
|
5240
|
+
});
|
|
5241
|
+
command.command("revoke <keyId>").description("Revoke a developer API key").action(async (keyId) => {
|
|
5242
|
+
const spinner = spin("Revoking developer key\u2026");
|
|
5243
|
+
try {
|
|
5244
|
+
await makeClient().developer.revokeApiKey(keyId);
|
|
5245
|
+
spinner.stop();
|
|
5246
|
+
console.log(`${sym.ok} Developer API key revoked.`);
|
|
5247
|
+
} catch (error) {
|
|
5248
|
+
spinner.stop();
|
|
5249
|
+
printError(error);
|
|
5250
|
+
process.exit(1);
|
|
5251
|
+
}
|
|
5252
|
+
});
|
|
5253
|
+
command.command("scopes").description("List supported developer API scopes").option("--json", "Output as JSON").action(async (opts) => {
|
|
5254
|
+
const spinner = spin("Fetching API scopes\u2026");
|
|
5255
|
+
try {
|
|
5256
|
+
const result = await makeClient().developer.scopes();
|
|
5257
|
+
spinner.stop();
|
|
5258
|
+
if (opts.json) return jsonOut(result.data);
|
|
5259
|
+
section("Developer API scopes");
|
|
5260
|
+
for (const scope of result.data) {
|
|
5261
|
+
console.log(` ${sym.bullet} ${scope}`);
|
|
5262
|
+
}
|
|
5263
|
+
} catch (error) {
|
|
5264
|
+
spinner.stop();
|
|
5265
|
+
printError(error);
|
|
5266
|
+
process.exit(1);
|
|
5267
|
+
}
|
|
5268
|
+
});
|
|
5269
|
+
const projects = command.command("projects").description("Manage developer projects");
|
|
5270
|
+
projects.command("list", { isDefault: true }).alias("ls").description("List developer projects").option("--json", "Output as JSON").action(async (opts) => {
|
|
5271
|
+
const spinner = spin("Fetching developer projects\u2026");
|
|
5272
|
+
try {
|
|
5273
|
+
const result = await makeClient().developer.listProjects();
|
|
5274
|
+
spinner.stop();
|
|
5275
|
+
if (opts.json) return jsonOut(result.data);
|
|
5276
|
+
section(`Developer projects (${result.data.length})`);
|
|
5277
|
+
table(
|
|
5278
|
+
result.data.map((project) => ({
|
|
5279
|
+
ID: project.id,
|
|
5280
|
+
Name: project.name,
|
|
5281
|
+
Environment: project.environment,
|
|
5282
|
+
Status: project.status
|
|
5283
|
+
})),
|
|
5284
|
+
["ID", "Name", "Environment", "Status"]
|
|
5285
|
+
);
|
|
5286
|
+
} catch (error) {
|
|
5287
|
+
spinner.stop();
|
|
5288
|
+
printError(error);
|
|
5289
|
+
process.exit(1);
|
|
5290
|
+
}
|
|
5291
|
+
});
|
|
5292
|
+
projects.command("create").description("Create a developer project").requiredOption("--name <name>", "Project name").option(
|
|
5293
|
+
"--environment <environment>",
|
|
5294
|
+
"production | development | staging",
|
|
5295
|
+
"development"
|
|
5296
|
+
).option("--workspace <workspaceId>", "Workspace ID (defaults to signed-in workspace)").option("--json", "Output as JSON").action(async (opts) => {
|
|
5297
|
+
const workspaceId = opts.workspace ?? loadConfig().workspaceId;
|
|
5298
|
+
if (!workspaceId) {
|
|
5299
|
+
throw new Error(
|
|
5300
|
+
"No workspace is configured. Pass --workspace or sign in again."
|
|
5301
|
+
);
|
|
5302
|
+
}
|
|
5303
|
+
if (!["production", "development", "staging"].includes(opts.environment)) {
|
|
5304
|
+
throw new Error(
|
|
5305
|
+
"--environment must be production, development, or staging."
|
|
5306
|
+
);
|
|
5307
|
+
}
|
|
5308
|
+
const spinner = spin("Creating developer project\u2026");
|
|
5309
|
+
try {
|
|
5310
|
+
const result = await makeClient().developer.createProject({
|
|
5311
|
+
workspaceId,
|
|
5312
|
+
name: opts.name,
|
|
5313
|
+
environment: opts.environment
|
|
5314
|
+
});
|
|
5315
|
+
spinner.stop();
|
|
5316
|
+
if (opts.json) return jsonOut(result.data);
|
|
5317
|
+
console.log(`
|
|
5318
|
+
${sym.ok} Developer project created.`);
|
|
5319
|
+
detail([
|
|
5320
|
+
["Project ID", c.id(result.data.id)],
|
|
5321
|
+
["Name", result.data.name],
|
|
5322
|
+
["Environment", result.data.environment]
|
|
5323
|
+
]);
|
|
5324
|
+
} catch (error) {
|
|
5325
|
+
spinner.stop();
|
|
5326
|
+
printError(error);
|
|
5327
|
+
process.exit(1);
|
|
5328
|
+
}
|
|
5329
|
+
});
|
|
5330
|
+
return command;
|
|
5331
|
+
}
|
|
5332
|
+
|
|
5333
|
+
// src/bin.ts
|
|
5334
|
+
async function interactiveMenu() {
|
|
5335
|
+
banner();
|
|
5336
|
+
const cfg = loadConfig();
|
|
5337
|
+
const isSetup = !!((cfg.accessToken || cfg.apiKey || cfg.sessionToken) && (cfg.userId || cfg.initiator));
|
|
5338
|
+
if (!isSetup) {
|
|
5339
|
+
console.log(c.bold(" Welcome to Agent Commons CLI!"));
|
|
5340
|
+
console.log(c.dim(" Looks like this is your first time here \u2014 let's get you set up.\n"));
|
|
5341
|
+
console.log(` ${sym.arrow} Running ${c.bold("agc login")} to configure your credentials\u2026
|
|
5342
|
+
`);
|
|
5343
|
+
runSubcommand(["login"]);
|
|
5344
|
+
return;
|
|
5345
|
+
}
|
|
5346
|
+
console.log(
|
|
5347
|
+
` ${c.dim("Connected to")} ${c.primary(cfg.apiUrl)} ${c.dim("\xB7")} ${c.dim("Identity")} ${c.id((cfg.userId ?? cfg.initiator).slice(0, 8) + "\u2026" + (cfg.userId ?? cfg.initiator).slice(-4))}
|
|
4118
5348
|
`
|
|
4119
5349
|
);
|
|
4120
5350
|
const action = await select("What would you like to do?", [
|
|
4121
5351
|
{ label: "Chat with an agent", value: "chat", hint: "agc chat" },
|
|
4122
5352
|
{ label: "Run an agent (one-shot)", value: "run", hint: "agc run" },
|
|
5353
|
+
{ label: "Manage an agent cloud computer", value: "computer", hint: "agc computer status" },
|
|
4123
5354
|
{ label: "View sessions", value: "sessions", hint: "agc sessions list" },
|
|
4124
5355
|
{ label: "Manage agents", value: "agents", hint: "agc agents list" },
|
|
4125
5356
|
{ label: "Tasks", value: "tasks", hint: "agc task list" },
|
|
4126
5357
|
{ label: "Workflows", value: "workflows", hint: "agc workflow list" },
|
|
4127
5358
|
{ label: "MCP servers", value: "mcp", hint: "agc mcp list" },
|
|
4128
5359
|
{ label: "Skills", value: "skills", hint: "agc skills list" },
|
|
5360
|
+
{ label: "Library & files", value: "library", hint: "agc library list" },
|
|
5361
|
+
{ label: "Code projects", value: "projects", hint: "agc projects list" },
|
|
5362
|
+
{ label: "Developer API keys", value: "keys", hint: "agc keys list" },
|
|
4129
5363
|
{ label: "Wallet & balance", value: "wallet", hint: "agc wallet balance" },
|
|
4130
5364
|
{ label: "Usage & cost", value: "usage", hint: "agc usage" },
|
|
4131
5365
|
{ label: "Logs", value: "logs", hint: "agc logs" },
|
|
@@ -4135,24 +5369,29 @@ async function interactiveMenu() {
|
|
|
4135
5369
|
if (action === "exit") {
|
|
4136
5370
|
process.exit(0);
|
|
4137
5371
|
}
|
|
4138
|
-
const
|
|
4139
|
-
|
|
5372
|
+
const needsAgent = action === "chat" || action === "run" || action === "computer";
|
|
5373
|
+
const agentId2 = needsAgent ? cfg.defaultAgentId ?? await pickAgentInteractively(action) : void 0;
|
|
5374
|
+
if (needsAgent && !agentId2) return;
|
|
4140
5375
|
if (action === "run") {
|
|
4141
|
-
const
|
|
4142
|
-
if (!
|
|
4143
|
-
runSubcommand(["run", "--agent",
|
|
5376
|
+
const prompt = await askPrompt("Enter your prompt:");
|
|
5377
|
+
if (!prompt) return;
|
|
5378
|
+
runSubcommand(["run", "--agent", agentId2, prompt]);
|
|
4144
5379
|
return;
|
|
4145
5380
|
}
|
|
4146
5381
|
const commandMap = {
|
|
4147
|
-
chat: ["chat", "--agent",
|
|
5382
|
+
chat: ["chat", "--agent", agentId2],
|
|
4148
5383
|
run: [],
|
|
4149
5384
|
// handled above
|
|
5385
|
+
computer: ["computer", "status", "--agent", agentId2],
|
|
4150
5386
|
sessions: ["sessions", "list"],
|
|
4151
5387
|
agents: ["agents", "list"],
|
|
4152
5388
|
tasks: ["task", "list"],
|
|
4153
5389
|
workflows: ["workflow", "list"],
|
|
4154
5390
|
mcp: ["mcp", "list"],
|
|
4155
5391
|
skills: ["skills", "list"],
|
|
5392
|
+
library: ["library", "list"],
|
|
5393
|
+
projects: ["projects", "list"],
|
|
5394
|
+
keys: ["keys", "list"],
|
|
4156
5395
|
wallet: ["wallet", "balance"],
|
|
4157
5396
|
usage: ["usage"],
|
|
4158
5397
|
logs: ["logs"],
|
|
@@ -4162,9 +5401,9 @@ async function interactiveMenu() {
|
|
|
4162
5401
|
runSubcommand(commandMap[action]);
|
|
4163
5402
|
}
|
|
4164
5403
|
async function askPrompt(question) {
|
|
4165
|
-
const { createInterface:
|
|
5404
|
+
const { createInterface: createInterface3 } = await import("readline");
|
|
4166
5405
|
return new Promise((resolve2) => {
|
|
4167
|
-
const rl =
|
|
5406
|
+
const rl = createInterface3({ input: process.stdin, output: process.stdout });
|
|
4168
5407
|
process.stdout.write(`
|
|
4169
5408
|
${c.bold(question)}
|
|
4170
5409
|
${c.primary("\u203A")} `);
|
|
@@ -4193,7 +5432,7 @@ async function pickAgentInteractively(action) {
|
|
|
4193
5432
|
} catch {
|
|
4194
5433
|
spinner.stop();
|
|
4195
5434
|
console.log(`
|
|
4196
|
-
${c.warn("\u26A0")} Could not fetch agents. Check your
|
|
5435
|
+
${c.warn("\u26A0")} Could not fetch agents. Check your sign-in and connection.
|
|
4197
5436
|
`);
|
|
4198
5437
|
return null;
|
|
4199
5438
|
}
|
|
@@ -4211,8 +5450,8 @@ async function pickAgentInteractively(action) {
|
|
|
4211
5450
|
return null;
|
|
4212
5451
|
}
|
|
4213
5452
|
console.log();
|
|
4214
|
-
const
|
|
4215
|
-
`Choose an agent to ${action} with:`,
|
|
5453
|
+
const agentId2 = await select(
|
|
5454
|
+
action === "computer" ? "Choose the agent whose cloud computer you want to manage:" : `Choose an agent to ${action} with:`,
|
|
4216
5455
|
agents.map((a) => ({
|
|
4217
5456
|
label: a.name,
|
|
4218
5457
|
value: a.agentId,
|
|
@@ -4224,15 +5463,29 @@ async function pickAgentInteractively(action) {
|
|
|
4224
5463
|
{ label: "No \u2014 just this once", value: false }
|
|
4225
5464
|
]);
|
|
4226
5465
|
if (saveDefault) {
|
|
4227
|
-
saveConfig({ defaultAgentId:
|
|
4228
|
-
const chosen = agents.find((a) => a.agentId ===
|
|
4229
|
-
console.log(` ${sym.ok} ${c.dim("Default agent set to")} ${c.bold(chosen?.name ??
|
|
5466
|
+
saveConfig({ defaultAgentId: agentId2 });
|
|
5467
|
+
const chosen = agents.find((a) => a.agentId === agentId2);
|
|
5468
|
+
console.log(` ${sym.ok} ${c.dim("Default agent set to")} ${c.bold(chosen?.name ?? agentId2)}
|
|
4230
5469
|
`);
|
|
4231
5470
|
}
|
|
4232
|
-
return
|
|
5471
|
+
return agentId2;
|
|
4233
5472
|
}
|
|
4234
|
-
var program = new
|
|
4235
|
-
program.name("agc").description("Agent Commons CLI \u2014 interact with the Agent Commons platform").version("0.
|
|
5473
|
+
var program = new import_commander22.Command();
|
|
5474
|
+
program.name("agc").description("Agent Commons CLI \u2014 interact with the Agent Commons platform").version("0.4.0", "-v, --version").showHelpAfterError("(run `agc --help` for usage)").configureHelp({
|
|
5475
|
+
sortOptions: true,
|
|
5476
|
+
sortSubcommands: true
|
|
5477
|
+
}).addHelpText(
|
|
5478
|
+
"after",
|
|
5479
|
+
`
|
|
5480
|
+
Examples:
|
|
5481
|
+
$ agc login
|
|
5482
|
+
$ agc agents list
|
|
5483
|
+
$ agc run --agent <id> "Summarize this week"
|
|
5484
|
+
$ agc keys create --name "CI" --scopes agents:read,agents:run
|
|
5485
|
+
|
|
5486
|
+
Docs: https://docs.agentcommons.io/docs/cli
|
|
5487
|
+
`
|
|
5488
|
+
).action(async () => {
|
|
4236
5489
|
await interactiveMenu();
|
|
4237
5490
|
});
|
|
4238
5491
|
program.hook("preAction", async (_thisCommand, actionCommand) => {
|
|
@@ -4246,10 +5499,15 @@ program.addCommand(configCommand());
|
|
|
4246
5499
|
program.addCommand(agentsCommand());
|
|
4247
5500
|
program.addCommand(sessionsCommand());
|
|
4248
5501
|
program.addCommand(toolsCommand());
|
|
5502
|
+
program.addCommand(connectionsCommand());
|
|
5503
|
+
program.addCommand(libraryCommand());
|
|
5504
|
+
program.addCommand(projectsCommand());
|
|
5505
|
+
program.addCommand(apiKeysCommand());
|
|
4249
5506
|
program.addCommand(workflowCommand());
|
|
4250
5507
|
program.addCommand(taskCommand());
|
|
4251
5508
|
program.addCommand(runCommand());
|
|
4252
5509
|
program.addCommand(chatCommand());
|
|
5510
|
+
program.addCommand(computerCommand());
|
|
4253
5511
|
program.addCommand(mcpCommand());
|
|
4254
5512
|
program.addCommand(skillsCommand());
|
|
4255
5513
|
program.addCommand(walletCommand());
|
|
@@ -4257,6 +5515,8 @@ program.addCommand(modelsCommand());
|
|
|
4257
5515
|
program.addCommand(memoryCommand());
|
|
4258
5516
|
program.addCommand(usageCommand());
|
|
4259
5517
|
program.addCommand(logsCommand());
|
|
5518
|
+
program.addCommand(creditsCommand());
|
|
5519
|
+
program.addCommand(billingCommand());
|
|
4260
5520
|
program.on("command:*", () => {
|
|
4261
5521
|
console.error(
|
|
4262
5522
|
`
|
|
@@ -4266,4 +5526,9 @@ program.on("command:*", () => {
|
|
|
4266
5526
|
);
|
|
4267
5527
|
process.exit(1);
|
|
4268
5528
|
});
|
|
4269
|
-
program.
|
|
5529
|
+
program.parseAsync(process.argv).catch((error) => {
|
|
5530
|
+
console.error(`
|
|
5531
|
+
${sym.fail} ${c.error(error instanceof Error ? error.message : String(error))}
|
|
5532
|
+
`);
|
|
5533
|
+
process.exitCode = 1;
|
|
5534
|
+
});
|