@agent-commons/cli 0.3.0 → 0.5.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 +1219 -467
- 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.5.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"
|
|
235
255
|
});
|
|
256
|
+
child.on("error", () => {
|
|
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
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
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;
|
|
334
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
|
|
335
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
|
|
452
|
+
});
|
|
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
|
+
);
|
|
471
|
+
}
|
|
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
|
|
@@ -589,11 +664,11 @@ function agentsCommand() {
|
|
|
589
664
|
process.exit(1);
|
|
590
665
|
}
|
|
591
666
|
});
|
|
592
|
-
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) => {
|
|
593
668
|
const spinner = spin("Fetching agent\u2026");
|
|
594
669
|
try {
|
|
595
670
|
const client = makeClient();
|
|
596
|
-
const res = await client.agents.get(
|
|
671
|
+
const res = await client.agents.get(agentId2);
|
|
597
672
|
const agent = res?.data ?? res;
|
|
598
673
|
spinner.stop();
|
|
599
674
|
if (opts.json) return jsonOut(agent);
|
|
@@ -672,10 +747,10 @@ ${sym.ok} Agent created`);
|
|
|
672
747
|
}
|
|
673
748
|
});
|
|
674
749
|
const runtime = cmd.command("runtime").description("Manage an agent runtime");
|
|
675
|
-
runtime.command("status <agentId>").description("Show managed runtime status and capabilities").option("--json", "Output as JSON").action(async (
|
|
750
|
+
runtime.command("status <agentId>").description("Show managed runtime status and capabilities").option("--json", "Output as JSON").action(async (agentId2, opts) => {
|
|
676
751
|
const spinner = spin("Fetching runtime status\u2026");
|
|
677
752
|
try {
|
|
678
|
-
const result = await makeClient().agents.getRuntime(
|
|
753
|
+
const result = await makeClient().agents.getRuntime(agentId2);
|
|
679
754
|
spinner.stop();
|
|
680
755
|
if (opts.json) return jsonOut(result.data);
|
|
681
756
|
detail([
|
|
@@ -693,13 +768,13 @@ ${sym.ok} Agent created`);
|
|
|
693
768
|
for (const action of ["deploy", "restart", "sleep"]) {
|
|
694
769
|
runtime.command(`${action} <agentId>`).description(
|
|
695
770
|
`${action[0].toUpperCase()}${action.slice(1)} the managed agent runtime`
|
|
696
|
-
).action(async (
|
|
771
|
+
).action(async (agentId2) => {
|
|
697
772
|
const spinner = spin(
|
|
698
773
|
`${action[0].toUpperCase()}${action.slice(1)}ing runtime\u2026`
|
|
699
774
|
);
|
|
700
775
|
try {
|
|
701
776
|
const client = makeClient();
|
|
702
|
-
const result = action === "deploy" ? await client.agents.deployRuntime(
|
|
777
|
+
const result = action === "deploy" ? await client.agents.deployRuntime(agentId2) : action === "restart" ? await client.agents.restartRuntime(agentId2) : await client.agents.sleepRuntime(agentId2);
|
|
703
778
|
spinner.stop();
|
|
704
779
|
console.log(`
|
|
705
780
|
${sym.ok} Runtime ${result.data.status}`);
|
|
@@ -812,12 +887,12 @@ function sessionsCommand() {
|
|
|
812
887
|
const spinner = spin("Fetching sessions\u2026");
|
|
813
888
|
try {
|
|
814
889
|
const client = makeClient();
|
|
815
|
-
const
|
|
816
|
-
const res =
|
|
890
|
+
const agentId2 = opts.agent;
|
|
891
|
+
const res = agentId2 ? await client.sessions.list(agentId2, cfg.initiator) : await client.sessions.listByUser(cfg.initiator);
|
|
817
892
|
const sessions = res?.data ?? res ?? [];
|
|
818
893
|
spinner.stop();
|
|
819
894
|
if (opts.json) return jsonOut(sessions);
|
|
820
|
-
section(`Sessions (${sessions.length})${
|
|
895
|
+
section(`Sessions (${sessions.length})${agentId2 ? ` \u2014 agent ${agentId2.slice(0, 8)}\u2026` : " \u2014 all agents"}`);
|
|
821
896
|
table(
|
|
822
897
|
sessions.map((s) => ({
|
|
823
898
|
ID: s.sessionId.slice(0, 8) + "\u2026",
|
|
@@ -858,8 +933,8 @@ function sessionsCommand() {
|
|
|
858
933
|
});
|
|
859
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) => {
|
|
860
935
|
const cfg = loadConfig();
|
|
861
|
-
const
|
|
862
|
-
if (!
|
|
936
|
+
const agentId2 = opts.agent ?? cfg.defaultAgentId;
|
|
937
|
+
if (!agentId2) {
|
|
863
938
|
console.error(c.error("Specify --agent <agentId> or set defaultAgentId"));
|
|
864
939
|
process.exit(1);
|
|
865
940
|
}
|
|
@@ -871,7 +946,7 @@ function sessionsCommand() {
|
|
|
871
946
|
try {
|
|
872
947
|
const client = makeClient();
|
|
873
948
|
const res = await client.sessions.create({
|
|
874
|
-
agentId,
|
|
949
|
+
agentId: agentId2,
|
|
875
950
|
initiator: cfg.initiator,
|
|
876
951
|
title: opts.title,
|
|
877
952
|
...opts.model && { model: { modelId: opts.model, provider: opts.provider } }
|
|
@@ -891,6 +966,34 @@ ${sym.ok} Session created`);
|
|
|
891
966
|
process.exit(1);
|
|
892
967
|
}
|
|
893
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
|
+
});
|
|
894
997
|
return cmd;
|
|
895
998
|
}
|
|
896
999
|
|
|
@@ -999,8 +1102,8 @@ ${sym.ok} Tool created`);
|
|
|
999
1102
|
});
|
|
1000
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) => {
|
|
1001
1104
|
const cfg = loadConfig();
|
|
1002
|
-
const
|
|
1003
|
-
if (!
|
|
1105
|
+
const agentId2 = opts.agent ?? cfg.defaultAgentId;
|
|
1106
|
+
if (!agentId2) {
|
|
1004
1107
|
console.error(c.error("Specify --agent <agentId> or set defaultAgentId with `agc config set defaultAgentId <id>`"));
|
|
1005
1108
|
process.exit(1);
|
|
1006
1109
|
}
|
|
@@ -1011,13 +1114,13 @@ ${sym.ok} Tool created`);
|
|
|
1011
1114
|
console.error(c.error("--args must be valid JSON"));
|
|
1012
1115
|
process.exit(1);
|
|
1013
1116
|
}
|
|
1014
|
-
const
|
|
1117
|
+
const prompt = `Call the tool "${toolName}" with these arguments: ${JSON.stringify(args)}. Return only the tool result, nothing else.`;
|
|
1015
1118
|
const spinner = spin(`Executing ${toolName}\u2026`);
|
|
1016
1119
|
try {
|
|
1017
1120
|
const client = makeClient();
|
|
1018
1121
|
const result = await client.run.once({
|
|
1019
|
-
agentId,
|
|
1020
|
-
messages: [{ role: "user", content:
|
|
1122
|
+
agentId: agentId2,
|
|
1123
|
+
messages: [{ role: "user", content: prompt }],
|
|
1021
1124
|
...cfg.initiator && { initiatorId: cfg.initiator }
|
|
1022
1125
|
});
|
|
1023
1126
|
spinner.stop();
|
|
@@ -1097,7 +1200,7 @@ function connectionsCommand() {
|
|
|
1097
1200
|
process.exit(1);
|
|
1098
1201
|
}
|
|
1099
1202
|
});
|
|
1100
|
-
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("--json", "Output as JSON").action(async (providerKey, opts) => {
|
|
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) => {
|
|
1101
1204
|
const cfg = loadConfig();
|
|
1102
1205
|
if (!cfg.initiator) {
|
|
1103
1206
|
console.error(c.error("No initiator set. Run `agc login` first."));
|
|
@@ -1112,8 +1215,9 @@ function connectionsCommand() {
|
|
|
1112
1215
|
});
|
|
1113
1216
|
spinner.stop();
|
|
1114
1217
|
if (opts.json) return jsonOut(res);
|
|
1218
|
+
if (opts.browser !== false) openBrowser(res.authorizationUrl);
|
|
1115
1219
|
console.log(`
|
|
1116
|
-
${sym.ok}
|
|
1220
|
+
${sym.ok} Authorize the connection in your browser:`);
|
|
1117
1221
|
console.log(`
|
|
1118
1222
|
${c.id(res.authorizationUrl)}
|
|
1119
1223
|
`);
|
|
@@ -1124,6 +1228,56 @@ ${sym.ok} Open this URL in your browser to authorize:`);
|
|
|
1124
1228
|
process.exit(1);
|
|
1125
1229
|
}
|
|
1126
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
|
+
[
|
|
1245
|
+
"Expires",
|
|
1246
|
+
connection.accessTokenExpiresAt ?? connection.expiresAt ?? c.dim("(does not expire)")
|
|
1247
|
+
]
|
|
1248
|
+
]);
|
|
1249
|
+
} catch (err) {
|
|
1250
|
+
spinner.stop();
|
|
1251
|
+
printError(err);
|
|
1252
|
+
process.exit(1);
|
|
1253
|
+
}
|
|
1254
|
+
});
|
|
1255
|
+
cmd.command("refresh <connectionId>").description("Refresh a connected account token").action(async (connectionId) => {
|
|
1256
|
+
const spinner = spin("Refreshing connection\u2026");
|
|
1257
|
+
try {
|
|
1258
|
+
await makeClient().oauth.refresh(connectionId);
|
|
1259
|
+
spinner.stop();
|
|
1260
|
+
console.log(`${sym.ok} Connection refreshed.`);
|
|
1261
|
+
} catch (err) {
|
|
1262
|
+
spinner.stop();
|
|
1263
|
+
printError(err);
|
|
1264
|
+
process.exit(1);
|
|
1265
|
+
}
|
|
1266
|
+
});
|
|
1267
|
+
cmd.command("rename <connectionId> <name>").description("Set a friendly name for a connected account").action(async (connectionId, name) => {
|
|
1268
|
+
const spinner = spin("Updating connection\u2026");
|
|
1269
|
+
try {
|
|
1270
|
+
await makeClient().oauth.updateConnection(connectionId, {
|
|
1271
|
+
displayName: name
|
|
1272
|
+
});
|
|
1273
|
+
spinner.stop();
|
|
1274
|
+
console.log(`${sym.ok} Connection renamed to ${c.bold(name)}.`);
|
|
1275
|
+
} catch (err) {
|
|
1276
|
+
spinner.stop();
|
|
1277
|
+
printError(err);
|
|
1278
|
+
process.exit(1);
|
|
1279
|
+
}
|
|
1280
|
+
});
|
|
1127
1281
|
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) => {
|
|
1128
1282
|
const spinner = spin("Testing connection\u2026");
|
|
1129
1283
|
try {
|
|
@@ -1294,8 +1448,8 @@ ${sym.ok} Workflow created`);
|
|
|
1294
1448
|
}
|
|
1295
1449
|
const templateName = templateNameRaw;
|
|
1296
1450
|
const needsAgent = templateName === "agent-research-summary" || templateName === "multi-agent-field-report";
|
|
1297
|
-
const
|
|
1298
|
-
if (needsAgent && !
|
|
1451
|
+
const agentId2 = opts.agent ?? cfg.defaultAgentId;
|
|
1452
|
+
if (needsAgent && !agentId2) {
|
|
1299
1453
|
console.error(c.error("This template requires --agent <agentId> or a configured defaultAgentId."));
|
|
1300
1454
|
process.exit(1);
|
|
1301
1455
|
}
|
|
@@ -1319,7 +1473,7 @@ ${sym.ok} Workflow created`);
|
|
|
1319
1473
|
const ctx = {
|
|
1320
1474
|
ownerId: cfg.initiator,
|
|
1321
1475
|
prefix,
|
|
1322
|
-
agentId,
|
|
1476
|
+
agentId: agentId2,
|
|
1323
1477
|
reviewerAgentId: opts.reviewerAgent,
|
|
1324
1478
|
childWorkflowId
|
|
1325
1479
|
};
|
|
@@ -1339,7 +1493,7 @@ ${sym.ok} Workflow created`);
|
|
|
1339
1493
|
}
|
|
1340
1494
|
}
|
|
1341
1495
|
execution = await makeClient().workflows.execute(result.workflow.workflowId, {
|
|
1342
|
-
agentId,
|
|
1496
|
+
agentId: agentId2,
|
|
1343
1497
|
inputData,
|
|
1344
1498
|
userId: cfg.initiator
|
|
1345
1499
|
});
|
|
@@ -1410,7 +1564,7 @@ ${sym.ok} Execution started: ${c.id(execution.executionId)}`);
|
|
|
1410
1564
|
});
|
|
1411
1565
|
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) => {
|
|
1412
1566
|
const cfg = loadConfig();
|
|
1413
|
-
const
|
|
1567
|
+
const agentId2 = opts.agent ?? cfg.defaultAgentId;
|
|
1414
1568
|
let inputData = {};
|
|
1415
1569
|
try {
|
|
1416
1570
|
inputData = JSON.parse(opts.input);
|
|
@@ -1422,7 +1576,7 @@ ${sym.ok} Execution started: ${c.id(execution.executionId)}`);
|
|
|
1422
1576
|
try {
|
|
1423
1577
|
const client = makeClient();
|
|
1424
1578
|
const execution = await client.workflows.execute(workflowId, {
|
|
1425
|
-
agentId,
|
|
1579
|
+
agentId: agentId2,
|
|
1426
1580
|
sessionId: opts.session,
|
|
1427
1581
|
inputData
|
|
1428
1582
|
});
|
|
@@ -1567,12 +1721,12 @@ function taskCommand() {
|
|
|
1567
1721
|
const cmd = new import_commander7.Command("task").description("Manage and execute tasks").alias("t");
|
|
1568
1722
|
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) => {
|
|
1569
1723
|
const cfg = loadConfig();
|
|
1570
|
-
const
|
|
1724
|
+
const agentId2 = opts.agent ?? cfg.defaultAgentId;
|
|
1571
1725
|
const spinner = spin("Fetching tasks\u2026");
|
|
1572
1726
|
try {
|
|
1573
1727
|
const client = makeClient();
|
|
1574
1728
|
const filter = {};
|
|
1575
|
-
if (
|
|
1729
|
+
if (agentId2) filter.agentId = agentId2;
|
|
1576
1730
|
if (opts.session) filter.sessionId = opts.session;
|
|
1577
1731
|
if (cfg.initiator) {
|
|
1578
1732
|
filter.ownerId = cfg.initiator;
|
|
@@ -1628,8 +1782,8 @@ function taskCommand() {
|
|
|
1628
1782
|
});
|
|
1629
1783
|
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) => {
|
|
1630
1784
|
const cfg = loadConfig();
|
|
1631
|
-
const
|
|
1632
|
-
if (!
|
|
1785
|
+
const agentId2 = opts.agent ?? cfg.defaultAgentId;
|
|
1786
|
+
if (!agentId2) {
|
|
1633
1787
|
console.error(c.error("Specify --agent <agentId> or set defaultAgentId with `agc config set defaultAgentId <id>`"));
|
|
1634
1788
|
process.exit(1);
|
|
1635
1789
|
}
|
|
@@ -1645,7 +1799,7 @@ function taskCommand() {
|
|
|
1645
1799
|
const client = makeClient();
|
|
1646
1800
|
const res = await client.tasks.create({
|
|
1647
1801
|
title: opts.title,
|
|
1648
|
-
agentId,
|
|
1802
|
+
agentId: agentId2,
|
|
1649
1803
|
sessionId: opts.session,
|
|
1650
1804
|
workflowId: opts.workflow,
|
|
1651
1805
|
inputData,
|
|
@@ -1750,13 +1904,13 @@ ${sym.fail} ${c.error(event.message ?? event.type)}`);
|
|
|
1750
1904
|
|
|
1751
1905
|
// src/commands/run.ts
|
|
1752
1906
|
var import_commander8 = require("commander");
|
|
1753
|
-
var
|
|
1907
|
+
var readline2 = __toESM(require("readline"));
|
|
1754
1908
|
|
|
1755
1909
|
// src/local-tools.ts
|
|
1756
1910
|
var import_fs5 = require("fs");
|
|
1757
1911
|
var import_path3 = require("path");
|
|
1758
1912
|
var import_child_process2 = require("child_process");
|
|
1759
|
-
var
|
|
1913
|
+
var readline = __toESM(require("readline"));
|
|
1760
1914
|
var pdfParse = require("pdf-parse/lib/pdf-parse.js");
|
|
1761
1915
|
var managedProcesses = /* @__PURE__ */ new Map();
|
|
1762
1916
|
function capBuffer(existing, chunk, maxBytes) {
|
|
@@ -1906,11 +2060,11 @@ function extractToolCall(text) {
|
|
|
1906
2060
|
}
|
|
1907
2061
|
return null;
|
|
1908
2062
|
}
|
|
1909
|
-
function injectAgcTrailer(command, args,
|
|
2063
|
+
function injectAgcTrailer(command, args, agentId2, agentName) {
|
|
1910
2064
|
if (command !== "git") return args;
|
|
1911
2065
|
if (!args.some((a) => a === "commit")) return args;
|
|
1912
2066
|
if (args.some((a) => a.includes("Co-Authored-By: agc"))) return args;
|
|
1913
|
-
const identity = agentName ? `${agentName} (agc)` :
|
|
2067
|
+
const identity = agentName ? `${agentName} (agc)` : agentId2 ? `agc/${agentId2}` : "agc agent";
|
|
1914
2068
|
return [...args, "--trailer", `Co-Authored-By: ${identity} <agc-agent@users.noreply.github.com>`];
|
|
1915
2069
|
}
|
|
1916
2070
|
var AGC_HOOK_MARKER = "# agc-session:";
|
|
@@ -1927,7 +2081,7 @@ function findGitDir(rootDir) {
|
|
|
1927
2081
|
}
|
|
1928
2082
|
return null;
|
|
1929
2083
|
}
|
|
1930
|
-
function installGitHook(rootDir, sessionId,
|
|
2084
|
+
function installGitHook(rootDir, sessionId, agentId2, agentName) {
|
|
1931
2085
|
const gitDir = findGitDir(rootDir);
|
|
1932
2086
|
if (!gitDir) return;
|
|
1933
2087
|
const hooksDir = (0, import_path3.join)(gitDir, "hooks");
|
|
@@ -1939,7 +2093,7 @@ function installGitHook(rootDir, sessionId, agentId, agentName) {
|
|
|
1939
2093
|
(0, import_fs5.writeFileSync)(hookPath + HOOK_BACKUP_SUFFIX, existing, { mode: 493 });
|
|
1940
2094
|
}
|
|
1941
2095
|
}
|
|
1942
|
-
const identity = agentName ? `${agentName} (agc)` :
|
|
2096
|
+
const identity = agentName ? `${agentName} (agc)` : agentId2 ? `agc/${agentId2}` : "agc agent";
|
|
1943
2097
|
const trailer = `Co-Authored-By: ${identity} <agc-agent@users.noreply.github.com>`;
|
|
1944
2098
|
const chainLine = (0, import_fs5.existsSync)(hookPath + HOOK_BACKUP_SUFFIX) ? `
|
|
1945
2099
|
# chain pre-existing hook
|
|
@@ -2003,7 +2157,7 @@ async function confirm(message, config, permissionKey) {
|
|
|
2003
2157
|
if (cached === "allow") return true;
|
|
2004
2158
|
if (cached === "deny") return false;
|
|
2005
2159
|
return new Promise((resolve2) => {
|
|
2006
|
-
const rl =
|
|
2160
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
2007
2161
|
process.stdout.write(
|
|
2008
2162
|
`
|
|
2009
2163
|
\x1B[33m\u26A0\x1B[0m ${message}
|
|
@@ -2382,10 +2536,10 @@ async function runLocalTool(call, cfg) {
|
|
|
2382
2536
|
|
|
2383
2537
|
// src/commands/run.ts
|
|
2384
2538
|
function runCommand() {
|
|
2385
|
-
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 (
|
|
2539
|
+
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) => {
|
|
2386
2540
|
const cfg = loadConfig();
|
|
2387
|
-
const
|
|
2388
|
-
if (!
|
|
2541
|
+
const agentId2 = opts.agent ?? cfg.defaultAgentId;
|
|
2542
|
+
if (!agentId2) {
|
|
2389
2543
|
console.error(c.error("Specify --agent <agentId> or set defaultAgentId with `agc config set defaultAgentId <id>`"));
|
|
2390
2544
|
process.exit(1);
|
|
2391
2545
|
}
|
|
@@ -2410,7 +2564,7 @@ function runCommand() {
|
|
|
2410
2564
|
const spinner = spin("Creating session\u2026");
|
|
2411
2565
|
try {
|
|
2412
2566
|
const res = await client.sessions.create({
|
|
2413
|
-
agentId,
|
|
2567
|
+
agentId: agentId2,
|
|
2414
2568
|
initiator: cfg.initiator ?? "",
|
|
2415
2569
|
title: `agc run ${(/* @__PURE__ */ new Date()).toISOString().slice(0, 16)}`,
|
|
2416
2570
|
source: "cli"
|
|
@@ -2436,7 +2590,7 @@ function runCommand() {
|
|
|
2436
2590
|
appendLog: () => {
|
|
2437
2591
|
},
|
|
2438
2592
|
permissions: /* @__PURE__ */ new Map(),
|
|
2439
|
-
agentId,
|
|
2593
|
+
agentId: agentId2,
|
|
2440
2594
|
autoApprove
|
|
2441
2595
|
};
|
|
2442
2596
|
const snapshot = buildDirSnapshot(rootDir, 2);
|
|
@@ -2460,9 +2614,9 @@ function runCommand() {
|
|
|
2460
2614
|
}
|
|
2461
2615
|
}
|
|
2462
2616
|
const params = {
|
|
2463
|
-
agentId,
|
|
2617
|
+
agentId: agentId2,
|
|
2464
2618
|
sessionId,
|
|
2465
|
-
messages: [{ role: "user", content:
|
|
2619
|
+
messages: [{ role: "user", content: prompt }],
|
|
2466
2620
|
...cfg.initiator && { initiatorId: cfg.initiator },
|
|
2467
2621
|
...opts.computer && { computerRequest: { enabled: true } },
|
|
2468
2622
|
...cliContext && { cliContext }
|
|
@@ -2514,16 +2668,12 @@ Session: ${sessionId} (resume with: agc run --session ${sessionId} "<prompt>")`
|
|
|
2514
2668
|
toolOk = false;
|
|
2515
2669
|
}
|
|
2516
2670
|
const elapsed = ((Date.now() - startMs) / 1e3).toFixed(1);
|
|
2517
|
-
|
|
2518
|
-
|
|
2671
|
+
readline2.cursorTo(process.stdout, 0);
|
|
2672
|
+
readline2.clearLine(process.stdout, 0);
|
|
2519
2673
|
process.stdout.write(` ${c.dim("\u2500")} ${c.bold(displayName)} ${toolOk ? sym.ok : sym.fail} ${c.dim("(" + elapsed + "s)")}
|
|
2520
2674
|
`);
|
|
2521
2675
|
try {
|
|
2522
|
-
await
|
|
2523
|
-
method: "POST",
|
|
2524
|
-
headers: { "Content-Type": "application/json", "Authorization": `Bearer ${cfg.apiKey}` },
|
|
2525
|
-
body: JSON.stringify({ requestId, result })
|
|
2526
|
-
});
|
|
2676
|
+
await client.agents.submitCliToolResult(requestId, result);
|
|
2527
2677
|
} catch {
|
|
2528
2678
|
}
|
|
2529
2679
|
} else if (event.type === "toolStart") {
|
|
@@ -2536,8 +2686,8 @@ Session: ${sessionId} (resume with: agc run --session ${sessionId} "<prompt>")`
|
|
|
2536
2686
|
process.stdout.write(` ${c.dim("\u2500")} ${c.bold(lastToolName)}`);
|
|
2537
2687
|
} else if (event.type === "toolEnd") {
|
|
2538
2688
|
const elapsed = ((Date.now() - toolStartMs) / 1e3).toFixed(1);
|
|
2539
|
-
|
|
2540
|
-
|
|
2689
|
+
readline2.cursorTo(process.stdout, 0);
|
|
2690
|
+
readline2.clearLine(process.stdout, 0);
|
|
2541
2691
|
process.stdout.write(` ${c.dim("\u2500")} ${c.bold(lastToolName)} ${sym.ok} ${c.dim("(" + elapsed + "s)")}
|
|
2542
2692
|
`);
|
|
2543
2693
|
} else if (event.type === "final") {
|
|
@@ -2565,7 +2715,7 @@ ${sym.fail} ${c.error(event.message ?? "Error")}`);
|
|
|
2565
2715
|
|
|
2566
2716
|
// src/commands/chat.ts
|
|
2567
2717
|
var import_commander9 = require("commander");
|
|
2568
|
-
var
|
|
2718
|
+
var readline3 = __toESM(require("readline"));
|
|
2569
2719
|
var import_fs6 = require("fs");
|
|
2570
2720
|
var import_path4 = require("path");
|
|
2571
2721
|
var import_os3 = require("os");
|
|
@@ -2611,9 +2761,17 @@ function chatCommand() {
|
|
|
2611
2761
|
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) => {
|
|
2612
2762
|
const localEnabled = opts.local !== false;
|
|
2613
2763
|
const cfg = loadConfig();
|
|
2614
|
-
|
|
2615
|
-
if (!
|
|
2616
|
-
|
|
2764
|
+
let agentId2 = opts.agent ?? cfg.defaultAgentId;
|
|
2765
|
+
if (!agentId2 && cfg.initiator) {
|
|
2766
|
+
try {
|
|
2767
|
+
const listed = await makeClient().agents.list(cfg.initiator);
|
|
2768
|
+
const agents = listed?.data ?? listed ?? [];
|
|
2769
|
+
agentId2 = agents.find((agent) => agent.isDefault)?.agentId ?? agents[0]?.agentId;
|
|
2770
|
+
} catch {
|
|
2771
|
+
}
|
|
2772
|
+
}
|
|
2773
|
+
if (!agentId2) {
|
|
2774
|
+
console.error(c.error("No default agent is available. Specify --agent <agentId> or run `agc agents list`."));
|
|
2617
2775
|
process.exit(1);
|
|
2618
2776
|
}
|
|
2619
2777
|
if (!cfg.initiator) {
|
|
@@ -2628,7 +2786,7 @@ function chatCommand() {
|
|
|
2628
2786
|
const spinner = spin("Creating session\u2026");
|
|
2629
2787
|
try {
|
|
2630
2788
|
const res = await client.sessions.create({
|
|
2631
|
-
agentId,
|
|
2789
|
+
agentId: agentId2,
|
|
2632
2790
|
initiator,
|
|
2633
2791
|
title: `agc chat ${(/* @__PURE__ */ new Date()).toISOString().slice(0, 16)}`,
|
|
2634
2792
|
source: "cli"
|
|
@@ -2639,7 +2797,7 @@ function chatCommand() {
|
|
|
2639
2797
|
appendSessionLog(sessionId, {
|
|
2640
2798
|
type: "session_start",
|
|
2641
2799
|
sessionId,
|
|
2642
|
-
agentId,
|
|
2800
|
+
agentId: agentId2,
|
|
2643
2801
|
initiator,
|
|
2644
2802
|
source: "cli",
|
|
2645
2803
|
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
@@ -2654,9 +2812,9 @@ function chatCommand() {
|
|
|
2654
2812
|
try {
|
|
2655
2813
|
const res = await client.sessions.get(sessionId);
|
|
2656
2814
|
const session = res?.data ?? res;
|
|
2657
|
-
if (session.agentId && session.agentId !==
|
|
2815
|
+
if (session.agentId && session.agentId !== agentId2) {
|
|
2658
2816
|
spinner.stop();
|
|
2659
|
-
console.log(c.warn(` Note: session ${sessionId} was created with agent ${session.agentId}, not ${
|
|
2817
|
+
console.log(c.warn(` Note: session ${sessionId} was created with agent ${session.agentId}, not ${agentId2}`));
|
|
2660
2818
|
} else {
|
|
2661
2819
|
spinner.stop();
|
|
2662
2820
|
}
|
|
@@ -2669,10 +2827,10 @@ function chatCommand() {
|
|
|
2669
2827
|
let agentName;
|
|
2670
2828
|
let walletLine = "";
|
|
2671
2829
|
await Promise.allSettled([
|
|
2672
|
-
client.agents.get(
|
|
2830
|
+
client.agents.get(agentId2).then((res) => {
|
|
2673
2831
|
agentName = (res?.data ?? res)?.name;
|
|
2674
2832
|
}),
|
|
2675
|
-
client.wallets.primary(
|
|
2833
|
+
client.wallets.primary(agentId2).then(async (primary) => {
|
|
2676
2834
|
const w = primary?.data ?? primary;
|
|
2677
2835
|
if (w?.id) {
|
|
2678
2836
|
const bal = await client.wallets.balance(w.id).catch(() => null);
|
|
@@ -2686,7 +2844,7 @@ function chatCommand() {
|
|
|
2686
2844
|
console.log(`
|
|
2687
2845
|
${c.bold("Agent Commons Chat")}`);
|
|
2688
2846
|
const headerRows = [
|
|
2689
|
-
["Agent", agentName ? `${agentName} ${c.dim(
|
|
2847
|
+
["Agent", agentName ? `${agentName} ${c.dim(agentId2)}` : agentId2],
|
|
2690
2848
|
["Session", c.id(sessionId) + (isResume ? c.dim(" (resumed)") : c.dim(" (new)"))]
|
|
2691
2849
|
];
|
|
2692
2850
|
if (walletLine) headerRows.push(["Wallet", walletLine]);
|
|
@@ -2700,12 +2858,12 @@ ${c.bold("Agent Commons Chat")}`);
|
|
|
2700
2858
|
localToolsCfg = {
|
|
2701
2859
|
rootDir,
|
|
2702
2860
|
sessionId,
|
|
2703
|
-
agentId,
|
|
2861
|
+
agentId: agentId2,
|
|
2704
2862
|
agentName,
|
|
2705
2863
|
appendLog: (record) => appendSessionLog(sessionId, record),
|
|
2706
2864
|
permissions: /* @__PURE__ */ new Map()
|
|
2707
2865
|
};
|
|
2708
|
-
installGitHook(rootDir, sessionId,
|
|
2866
|
+
installGitHook(rootDir, sessionId, agentId2, agentName);
|
|
2709
2867
|
appendSessionLog(sessionId, {
|
|
2710
2868
|
type: "local_tools_enabled",
|
|
2711
2869
|
rootDir,
|
|
@@ -2713,7 +2871,7 @@ ${c.bold("Agent Commons Chat")}`);
|
|
|
2713
2871
|
});
|
|
2714
2872
|
}
|
|
2715
2873
|
console.log(c.dim("\nType your message and press Enter. Type /help for commands.\n"));
|
|
2716
|
-
const rl =
|
|
2874
|
+
const rl = readline3.createInterface({
|
|
2717
2875
|
input: process.stdin,
|
|
2718
2876
|
output: process.stdout,
|
|
2719
2877
|
terminal: true,
|
|
@@ -2797,7 +2955,7 @@ ${content}
|
|
|
2797
2955
|
cliContext = buildLocalToolsManifest(rootDir, snapshot, fileContextBlocks);
|
|
2798
2956
|
}
|
|
2799
2957
|
const params = {
|
|
2800
|
-
agentId,
|
|
2958
|
+
agentId: agentId2,
|
|
2801
2959
|
sessionId,
|
|
2802
2960
|
messages: [{ role: "user", content: userMessage }],
|
|
2803
2961
|
...opts.computer && { computerRequest: { enabled: true } },
|
|
@@ -2857,7 +3015,7 @@ ${sym.fail} ${c.error(err.message ?? String(err))}`);
|
|
|
2857
3015
|
if (isWaiting) {
|
|
2858
3016
|
elapsedInterval = setInterval(() => {
|
|
2859
3017
|
elapsedSec++;
|
|
2860
|
-
|
|
3018
|
+
readline3.cursorTo(process.stdout, 0);
|
|
2861
3019
|
process.stdout.write(` ${c.dim("\u2500")} ${c.bold(displayName)}${argStr ? " " + c.dim(argStr) : ""} ${c.dim(elapsedSec + "s\u2026")}`);
|
|
2862
3020
|
}, 1e3);
|
|
2863
3021
|
}
|
|
@@ -2872,12 +3030,14 @@ ${sym.fail} ${c.error(err.message ?? String(err))}`);
|
|
|
2872
3030
|
if (elapsedInterval) clearInterval(elapsedInterval);
|
|
2873
3031
|
const elapsed = ((Date.now() - startMs) / 1e3).toFixed(1);
|
|
2874
3032
|
const preview = toolOk ? toolResultPreview(displayName, result) : "";
|
|
2875
|
-
|
|
2876
|
-
|
|
3033
|
+
readline3.cursorTo(process.stdout, 0);
|
|
3034
|
+
readline3.clearLine(process.stdout, 0);
|
|
2877
3035
|
const statusIcon = toolOk ? sym.ok : sym.fail;
|
|
2878
3036
|
const previewPart = preview ? ` ${c.dim(preview)}` : "";
|
|
2879
|
-
process.stdout.write(
|
|
2880
|
-
`)
|
|
3037
|
+
process.stdout.write(
|
|
3038
|
+
` ${c.dim("\u2500")} ${c.bold(displayName)}${argStr ? " " + c.dim(argStr) : ""} ${statusIcon}${previewPart} ${c.dim("(" + elapsed + "s)")}
|
|
3039
|
+
`
|
|
3040
|
+
);
|
|
2881
3041
|
appendSessionLog(sessionId, {
|
|
2882
3042
|
type: "local_tool_result",
|
|
2883
3043
|
tool: toolName,
|
|
@@ -2885,14 +3045,7 @@ ${sym.fail} ${c.error(err.message ?? String(err))}`);
|
|
|
2885
3045
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
2886
3046
|
});
|
|
2887
3047
|
try {
|
|
2888
|
-
await
|
|
2889
|
-
method: "POST",
|
|
2890
|
-
headers: {
|
|
2891
|
-
"Content-Type": "application/json",
|
|
2892
|
-
"Authorization": `Bearer ${cfg.apiKey}`
|
|
2893
|
-
},
|
|
2894
|
-
body: JSON.stringify({ requestId, result })
|
|
2895
|
-
});
|
|
3048
|
+
await client.agents.submitCliToolResult(requestId, result);
|
|
2896
3049
|
} catch (postErr) {
|
|
2897
3050
|
console.error(c.warn(`
|
|
2898
3051
|
[local] Failed to submit tool result: ${postErr?.message}`));
|
|
@@ -2907,8 +3060,8 @@ ${sym.fail} ${c.error(err.message ?? String(err))}`);
|
|
|
2907
3060
|
hasOutput = false;
|
|
2908
3061
|
} else if (event.type === "toolEnd") {
|
|
2909
3062
|
const elapsed = ((Date.now() - toolStartMs) / 1e3).toFixed(1);
|
|
2910
|
-
|
|
2911
|
-
|
|
3063
|
+
readline3.cursorTo(process.stdout, 0);
|
|
3064
|
+
readline3.clearLine(process.stdout, 0);
|
|
2912
3065
|
process.stdout.write(` ${c.dim("\u2500")} ${c.bold(lastToolName)} ${sym.ok} ${c.dim("(" + elapsed + "s)")}
|
|
2913
3066
|
`);
|
|
2914
3067
|
process.stdout.write(c.primary("agent") + c.dim(" \u203A "));
|
|
@@ -2934,7 +3087,13 @@ ${sym.fail} ${c.error(err.message ?? String(err))}`);
|
|
|
2934
3087
|
type: "message",
|
|
2935
3088
|
role: "assistant",
|
|
2936
3089
|
content: agentContent,
|
|
2937
|
-
usage: {
|
|
3090
|
+
usage: {
|
|
3091
|
+
inputTokens: inputTok,
|
|
3092
|
+
outputTokens: outputTok,
|
|
3093
|
+
cachedTokens: cachedTok,
|
|
3094
|
+
totalTokens: total,
|
|
3095
|
+
costUsd: usage.costUsd
|
|
3096
|
+
},
|
|
2938
3097
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
2939
3098
|
});
|
|
2940
3099
|
} else {
|
|
@@ -2957,15 +3116,7 @@ ${sym.fail} ${c.error(event.message ?? "Stream error")}`);
|
|
|
2957
3116
|
if (thinkingSpinner.isSpinning) thinkingSpinner.stop();
|
|
2958
3117
|
process.stdout.write("\n");
|
|
2959
3118
|
if (localToolsCfg && agentContent) {
|
|
2960
|
-
await handleLocalToolLoop(
|
|
2961
|
-
agentContent,
|
|
2962
|
-
localToolsCfg,
|
|
2963
|
-
client,
|
|
2964
|
-
agentId,
|
|
2965
|
-
sessionId,
|
|
2966
|
-
appendSessionLog,
|
|
2967
|
-
!!opts.computer
|
|
2968
|
-
);
|
|
3119
|
+
await handleLocalToolLoop(agentContent, localToolsCfg, client, agentId2, sessionId, appendSessionLog, !!opts.computer);
|
|
2969
3120
|
}
|
|
2970
3121
|
} catch (err) {
|
|
2971
3122
|
process.stdout.write("\n");
|
|
@@ -2973,8 +3124,8 @@ ${sym.fail} ${c.error(event.message ?? "Stream error")}`);
|
|
|
2973
3124
|
}
|
|
2974
3125
|
}
|
|
2975
3126
|
console.log();
|
|
2976
|
-
|
|
2977
|
-
|
|
3127
|
+
readline3.cursorTo(process.stdout, 0);
|
|
3128
|
+
readline3.clearLine(process.stdout, 0);
|
|
2978
3129
|
rl.resume();
|
|
2979
3130
|
rl.prompt();
|
|
2980
3131
|
});
|
|
@@ -2994,7 +3145,7 @@ Session preserved. Resume with: agc chat --resume ${sessionId}`));
|
|
|
2994
3145
|
});
|
|
2995
3146
|
}
|
|
2996
3147
|
var MAX_TOOL_DEPTH = 10;
|
|
2997
|
-
async function handleLocalToolLoop(agentText, cfg, client,
|
|
3148
|
+
async function handleLocalToolLoop(agentText, cfg, client, agentId2, sessionId, appendLog, computerEnabled = false, depth = 0) {
|
|
2998
3149
|
if (depth >= MAX_TOOL_DEPTH) {
|
|
2999
3150
|
console.log(c.dim(`
|
|
3000
3151
|
[local] Max tool depth reached (${MAX_TOOL_DEPTH}). Stopping tool loop.
|
|
@@ -3017,11 +3168,13 @@ async function handleLocalToolLoop(agentText, cfg, client, agentId, sessionId, a
|
|
|
3017
3168
|
}
|
|
3018
3169
|
const elapsed = ((Date.now() - startMs) / 1e3).toFixed(1);
|
|
3019
3170
|
const preview = toolOk ? toolResultPreview(toolCall.tool, result) : "";
|
|
3020
|
-
|
|
3021
|
-
|
|
3171
|
+
readline3.cursorTo(process.stdout, 0);
|
|
3172
|
+
readline3.clearLine(process.stdout, 0);
|
|
3022
3173
|
const previewPart = preview ? ` ${c.dim(preview)}` : "";
|
|
3023
|
-
process.stdout.write(
|
|
3024
|
-
`)
|
|
3174
|
+
process.stdout.write(
|
|
3175
|
+
` ${c.dim("\u2500")} ${c.bold(toolCall.tool)}${argStr ? " " + c.dim(argStr) : ""} ${toolOk ? sym.ok : sym.fail}${previewPart} ${c.dim("(" + elapsed + "s)")}
|
|
3176
|
+
`
|
|
3177
|
+
);
|
|
3025
3178
|
const resultMsg = `[Tool result: ${toolCall.tool}]
|
|
3026
3179
|
\`\`\`
|
|
3027
3180
|
${result}
|
|
@@ -3039,7 +3192,7 @@ ${result}
|
|
|
3039
3192
|
let loopToolName = "";
|
|
3040
3193
|
let loopToolStartMs = 0;
|
|
3041
3194
|
for await (const evt of client.agents.stream({
|
|
3042
|
-
agentId,
|
|
3195
|
+
agentId: agentId2,
|
|
3043
3196
|
sessionId,
|
|
3044
3197
|
messages: [{ role: "user", content: resultMsg }],
|
|
3045
3198
|
...computerEnabled && { computerRequest: { enabled: true } }
|
|
@@ -3055,8 +3208,8 @@ ${result}
|
|
|
3055
3208
|
process.stdout.write(` ${c.dim("\u2500")} ${c.bold(loopToolName)}`);
|
|
3056
3209
|
} else if (evt.type === "toolEnd") {
|
|
3057
3210
|
const elapsed2 = ((Date.now() - loopToolStartMs) / 1e3).toFixed(1);
|
|
3058
|
-
|
|
3059
|
-
|
|
3211
|
+
readline3.cursorTo(process.stdout, 0);
|
|
3212
|
+
readline3.clearLine(process.stdout, 0);
|
|
3060
3213
|
process.stdout.write(` ${c.dim("\u2500")} ${c.bold(loopToolName)} ${sym.ok} ${c.dim("(" + elapsed2 + "s)")}
|
|
3061
3214
|
`);
|
|
3062
3215
|
process.stdout.write(c.primary("agent") + c.dim(" \u203A "));
|
|
@@ -3066,7 +3219,12 @@ ${result}
|
|
|
3066
3219
|
process.stdout.write(txt);
|
|
3067
3220
|
followContent += txt;
|
|
3068
3221
|
}
|
|
3069
|
-
appendLog(sessionId, {
|
|
3222
|
+
appendLog(sessionId, {
|
|
3223
|
+
type: "message",
|
|
3224
|
+
role: "assistant",
|
|
3225
|
+
content: followContent,
|
|
3226
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
3227
|
+
});
|
|
3070
3228
|
break;
|
|
3071
3229
|
} else if (evt.type === "error") {
|
|
3072
3230
|
console.error(`
|
|
@@ -3080,16 +3238,7 @@ ${sym.fail} ${c.error(evt.message ?? "Stream error")}`);
|
|
|
3080
3238
|
console.error(`${sym.fail} ${c.error(err?.message ?? String(err))}`);
|
|
3081
3239
|
return;
|
|
3082
3240
|
}
|
|
3083
|
-
await handleLocalToolLoop(
|
|
3084
|
-
followContent,
|
|
3085
|
-
cfg,
|
|
3086
|
-
client,
|
|
3087
|
-
agentId,
|
|
3088
|
-
sessionId,
|
|
3089
|
-
appendLog,
|
|
3090
|
-
computerEnabled,
|
|
3091
|
-
depth + 1
|
|
3092
|
-
);
|
|
3241
|
+
await handleLocalToolLoop(followContent, cfg, client, agentId2, sessionId, appendLog, computerEnabled, depth + 1);
|
|
3093
3242
|
}
|
|
3094
3243
|
function truncate(s, max) {
|
|
3095
3244
|
const str = String(s ?? "");
|
|
@@ -3703,8 +3852,8 @@ function skillsCommand() {
|
|
|
3703
3852
|
});
|
|
3704
3853
|
cmd.command("delete <slug>").description("Permanently delete a skill").option("--yes", "Skip confirmation prompt").option("--json", "Output result as JSON").action(async (slug, opts) => {
|
|
3705
3854
|
if (!opts.yes) {
|
|
3706
|
-
const
|
|
3707
|
-
const rl =
|
|
3855
|
+
const readline4 = await import("readline");
|
|
3856
|
+
const rl = readline4.createInterface({ input: process.stdin, output: process.stdout });
|
|
3708
3857
|
const answer = await new Promise(
|
|
3709
3858
|
(resolve2) => rl.question(c.warn(`Delete skill "${slug}"? This cannot be undone. [y/N] `), resolve2)
|
|
3710
3859
|
);
|
|
@@ -3736,19 +3885,19 @@ function walletCommand() {
|
|
|
3736
3885
|
const cmd = new import_commander12.Command("wallet").description("Manage agent wallets");
|
|
3737
3886
|
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) => {
|
|
3738
3887
|
const cfg = loadConfig();
|
|
3739
|
-
const
|
|
3740
|
-
if (!
|
|
3888
|
+
const agentId2 = opts.agent ?? cfg.defaultAgentId;
|
|
3889
|
+
if (!agentId2) {
|
|
3741
3890
|
console.error(c.error("Specify --agent <agentId> or set defaultAgentId with `agc config set defaultAgentId <id>`"));
|
|
3742
3891
|
process.exit(1);
|
|
3743
3892
|
}
|
|
3744
3893
|
const spinner = spin("Fetching wallets\u2026");
|
|
3745
3894
|
try {
|
|
3746
3895
|
const client = makeClient();
|
|
3747
|
-
const wallets = await client.wallets.list(
|
|
3896
|
+
const wallets = await client.wallets.list(agentId2);
|
|
3748
3897
|
spinner.stop();
|
|
3749
3898
|
if (opts.json) return jsonOut(wallets);
|
|
3750
3899
|
const list = wallets?.data ?? wallets ?? [];
|
|
3751
|
-
section(`Wallets for agent ${
|
|
3900
|
+
section(`Wallets for agent ${agentId2.slice(0, 8)}\u2026 (${list.length})`);
|
|
3752
3901
|
table(
|
|
3753
3902
|
list.map((w) => ({
|
|
3754
3903
|
ID: w.id.slice(0, 8) + "\u2026",
|
|
@@ -3768,19 +3917,19 @@ function walletCommand() {
|
|
|
3768
3917
|
});
|
|
3769
3918
|
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) => {
|
|
3770
3919
|
const cfg = loadConfig();
|
|
3771
|
-
const
|
|
3772
|
-
if (!
|
|
3920
|
+
const agentId2 = opts.agent ?? cfg.defaultAgentId;
|
|
3921
|
+
if (!agentId2) {
|
|
3773
3922
|
console.error(c.error("Specify --agent <agentId> or set defaultAgentId with `agc config set defaultAgentId <id>`"));
|
|
3774
3923
|
process.exit(1);
|
|
3775
3924
|
}
|
|
3776
3925
|
const spinner = spin("Fetching primary wallet\u2026");
|
|
3777
3926
|
try {
|
|
3778
3927
|
const client = makeClient();
|
|
3779
|
-
const wallet = await client.wallets.primary(
|
|
3928
|
+
const wallet = await client.wallets.primary(agentId2);
|
|
3780
3929
|
spinner.stop();
|
|
3781
3930
|
if (!wallet) {
|
|
3782
|
-
console.log(c.warn(` No wallet found for agent ${
|
|
3783
|
-
console.log(c.dim(` Run: agc wallet create --agent ${
|
|
3931
|
+
console.log(c.warn(` No wallet found for agent ${agentId2}`));
|
|
3932
|
+
console.log(c.dim(` Run: agc wallet create --agent ${agentId2}`));
|
|
3784
3933
|
return;
|
|
3785
3934
|
}
|
|
3786
3935
|
const w = wallet?.data ?? wallet;
|
|
@@ -3801,8 +3950,8 @@ function walletCommand() {
|
|
|
3801
3950
|
});
|
|
3802
3951
|
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) => {
|
|
3803
3952
|
const cfg = loadConfig();
|
|
3804
|
-
const
|
|
3805
|
-
if (!
|
|
3953
|
+
const agentId2 = opts.agent ?? cfg.defaultAgentId;
|
|
3954
|
+
if (!agentId2) {
|
|
3806
3955
|
console.error(c.error("Specify --agent <agentId> or set defaultAgentId with `agc config set defaultAgentId <id>`"));
|
|
3807
3956
|
process.exit(1);
|
|
3808
3957
|
}
|
|
@@ -3811,11 +3960,11 @@ function walletCommand() {
|
|
|
3811
3960
|
const client = makeClient();
|
|
3812
3961
|
let walletId = opts.wallet;
|
|
3813
3962
|
if (!walletId) {
|
|
3814
|
-
const primary = await client.wallets.primary(
|
|
3963
|
+
const primary = await client.wallets.primary(agentId2);
|
|
3815
3964
|
const w = primary?.data ?? primary;
|
|
3816
3965
|
if (!w) {
|
|
3817
3966
|
spinner.stop();
|
|
3818
|
-
console.log(c.warn(` No wallet found. Run: agc wallet create --agent ${
|
|
3967
|
+
console.log(c.warn(` No wallet found. Run: agc wallet create --agent ${agentId2}`));
|
|
3819
3968
|
return;
|
|
3820
3969
|
}
|
|
3821
3970
|
walletId = w.id;
|
|
@@ -3842,8 +3991,8 @@ function walletCommand() {
|
|
|
3842
3991
|
});
|
|
3843
3992
|
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) => {
|
|
3844
3993
|
const cfg = loadConfig();
|
|
3845
|
-
const
|
|
3846
|
-
if (!
|
|
3994
|
+
const agentId2 = opts.agent ?? cfg.defaultAgentId;
|
|
3995
|
+
if (!agentId2) {
|
|
3847
3996
|
console.error(c.error("Specify --agent <agentId> or set defaultAgentId with `agc config set defaultAgentId <id>`"));
|
|
3848
3997
|
process.exit(1);
|
|
3849
3998
|
}
|
|
@@ -3855,7 +4004,7 @@ function walletCommand() {
|
|
|
3855
4004
|
try {
|
|
3856
4005
|
const client = makeClient();
|
|
3857
4006
|
const wallet = await client.wallets.create({
|
|
3858
|
-
agentId,
|
|
4007
|
+
agentId: agentId2,
|
|
3859
4008
|
walletType: opts.type,
|
|
3860
4009
|
label: opts.label,
|
|
3861
4010
|
externalAddress: opts.address
|
|
@@ -4013,22 +4162,22 @@ function memoryCommand() {
|
|
|
4013
4162
|
const cmd = new import_commander14.Command("memory").description("View and manage agent memories");
|
|
4014
4163
|
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) => {
|
|
4015
4164
|
const cfg = loadConfig();
|
|
4016
|
-
const
|
|
4017
|
-
if (!
|
|
4165
|
+
const agentId2 = opts.agent ?? cfg.defaultAgentId;
|
|
4166
|
+
if (!agentId2) {
|
|
4018
4167
|
console.error(c.error("Specify --agent <agentId> or set defaultAgentId"));
|
|
4019
4168
|
process.exit(1);
|
|
4020
4169
|
}
|
|
4021
4170
|
const spinner = spin("Fetching memories\u2026");
|
|
4022
4171
|
try {
|
|
4023
4172
|
const client = makeClient();
|
|
4024
|
-
const res = await client.memory.list(
|
|
4173
|
+
const res = await client.memory.list(agentId2, {
|
|
4025
4174
|
type: opts.type,
|
|
4026
4175
|
limit: parseInt(opts.limit, 10)
|
|
4027
4176
|
});
|
|
4028
4177
|
const memories = res?.data ?? res ?? [];
|
|
4029
4178
|
spinner.stop();
|
|
4030
4179
|
if (opts.json) return jsonOut(memories);
|
|
4031
|
-
section(`Memories for ${
|
|
4180
|
+
section(`Memories for ${agentId2.slice(0, 12)}\u2026 (${memories.length})`);
|
|
4032
4181
|
if (memories.length === 0) {
|
|
4033
4182
|
console.log(c.dim(" No memories yet"));
|
|
4034
4183
|
return;
|
|
@@ -4050,15 +4199,15 @@ function memoryCommand() {
|
|
|
4050
4199
|
});
|
|
4051
4200
|
cmd.command("stats").description("Show memory statistics for an agent").option("--agent <agentId>", "Agent ID").option("--json", "Output as JSON").action(async (opts) => {
|
|
4052
4201
|
const cfg = loadConfig();
|
|
4053
|
-
const
|
|
4054
|
-
if (!
|
|
4202
|
+
const agentId2 = opts.agent ?? cfg.defaultAgentId;
|
|
4203
|
+
if (!agentId2) {
|
|
4055
4204
|
console.error(c.error("Specify --agent <agentId>"));
|
|
4056
4205
|
process.exit(1);
|
|
4057
4206
|
}
|
|
4058
4207
|
const spinner = spin("Fetching stats\u2026");
|
|
4059
4208
|
try {
|
|
4060
4209
|
const client = makeClient();
|
|
4061
|
-
const res = await client.memory.stats(
|
|
4210
|
+
const res = await client.memory.stats(agentId2);
|
|
4062
4211
|
const stats = res?.data ?? res;
|
|
4063
4212
|
spinner.stop();
|
|
4064
4213
|
if (opts.json) return jsonOut(stats);
|
|
@@ -4118,15 +4267,15 @@ ${sym.ok} Memory ${c.id(memoryId)} deleted`);
|
|
|
4118
4267
|
});
|
|
4119
4268
|
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) => {
|
|
4120
4269
|
const cfg = loadConfig();
|
|
4121
|
-
const
|
|
4122
|
-
if (!
|
|
4270
|
+
const agentId2 = opts.agent ?? cfg.defaultAgentId;
|
|
4271
|
+
if (!agentId2) {
|
|
4123
4272
|
console.error(c.error("Specify --agent <agentId>"));
|
|
4124
4273
|
process.exit(1);
|
|
4125
4274
|
}
|
|
4126
4275
|
const spinner = spin("Searching memories\u2026");
|
|
4127
4276
|
try {
|
|
4128
4277
|
const client = makeClient();
|
|
4129
|
-
const res = await client.memory.retrieve(
|
|
4278
|
+
const res = await client.memory.retrieve(agentId2, query, parseInt(opts.limit, 10));
|
|
4130
4279
|
const memories = res?.data ?? res ?? [];
|
|
4131
4280
|
spinner.stop();
|
|
4132
4281
|
if (opts.json) return jsonOut(memories);
|
|
@@ -4215,18 +4364,18 @@ function usageCommand() {
|
|
|
4215
4364
|
process.exit(1);
|
|
4216
4365
|
}
|
|
4217
4366
|
});
|
|
4218
|
-
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 (
|
|
4367
|
+
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) => {
|
|
4219
4368
|
const spinner = spin("Fetching usage\u2026");
|
|
4220
4369
|
try {
|
|
4221
4370
|
const client = makeClient();
|
|
4222
|
-
const res = await client.usage.getAgentUsage(
|
|
4371
|
+
const res = await client.usage.getAgentUsage(agentId2, {
|
|
4223
4372
|
from: opts.from,
|
|
4224
4373
|
to: opts.to
|
|
4225
4374
|
});
|
|
4226
4375
|
const data = res?.data ?? res;
|
|
4227
4376
|
spinner.stop();
|
|
4228
4377
|
if (opts.json) return jsonOut(data);
|
|
4229
|
-
section(`Usage \u2014 ${
|
|
4378
|
+
section(`Usage \u2014 ${agentId2.slice(0, 12)}\u2026`);
|
|
4230
4379
|
detail([
|
|
4231
4380
|
["Calls", (data.callCount ?? 0).toLocaleString()],
|
|
4232
4381
|
["Input tokens", (data.totalInputTokens ?? 0).toLocaleString()],
|
|
@@ -4243,36 +4392,143 @@ function usageCommand() {
|
|
|
4243
4392
|
return cmd;
|
|
4244
4393
|
}
|
|
4245
4394
|
|
|
4246
|
-
// src/commands/
|
|
4395
|
+
// src/commands/billing.ts
|
|
4247
4396
|
var import_commander16 = require("commander");
|
|
4248
|
-
|
|
4249
|
-
|
|
4250
|
-
|
|
4251
|
-
|
|
4252
|
-
|
|
4253
|
-
|
|
4254
|
-
|
|
4255
|
-
|
|
4256
|
-
|
|
4257
|
-
|
|
4258
|
-
|
|
4259
|
-
|
|
4260
|
-
|
|
4261
|
-
|
|
4397
|
+
function creditsCommand() {
|
|
4398
|
+
const cmd = new import_commander16.Command("credits").description("View your credit balance and ledger");
|
|
4399
|
+
cmd.command("balance", { isDefault: true }).description("Show your current credit balance").option("--json", "Output as JSON").action(async (opts) => {
|
|
4400
|
+
const spinner = spin("Fetching balance\u2026");
|
|
4401
|
+
try {
|
|
4402
|
+
const client = makeClient();
|
|
4403
|
+
const res = await client.credits.balance();
|
|
4404
|
+
spinner.stop();
|
|
4405
|
+
if (opts.json) return jsonOut(res.data);
|
|
4406
|
+
section("Credits");
|
|
4407
|
+
detail([["Balance", String(res?.data?.balance ?? 0)]]);
|
|
4408
|
+
} catch (e) {
|
|
4409
|
+
spinner.stop();
|
|
4410
|
+
console.error(c.error(e.message));
|
|
4411
|
+
process.exit(1);
|
|
4412
|
+
}
|
|
4413
|
+
});
|
|
4414
|
+
cmd.command("ledger").description("Show recent credit ledger entries").option("--limit <n>", "Max entries", "20").option("--json", "Output as JSON").action(async (opts) => {
|
|
4415
|
+
const spinner = spin("Fetching ledger\u2026");
|
|
4416
|
+
try {
|
|
4417
|
+
const client = makeClient();
|
|
4418
|
+
const res = await client.credits.ledger({ limit: Number(opts.limit) });
|
|
4419
|
+
spinner.stop();
|
|
4420
|
+
const rows = res?.data ?? [];
|
|
4421
|
+
if (opts.json) return jsonOut(rows);
|
|
4422
|
+
section("Credit ledger");
|
|
4423
|
+
for (const e of rows) {
|
|
4424
|
+
const sign = e.amount >= 0 ? "+" : "";
|
|
4425
|
+
console.log(
|
|
4426
|
+
`${c.dim(new Date(e.createdAt).toLocaleString())} ${sign}${e.amount} ${e.description || e.eventType}`
|
|
4427
|
+
);
|
|
4428
|
+
}
|
|
4429
|
+
if (!rows.length) console.log(c.dim("No entries."));
|
|
4430
|
+
} catch (e) {
|
|
4431
|
+
spinner.stop();
|
|
4432
|
+
console.error(c.error(e.message));
|
|
4433
|
+
process.exit(1);
|
|
4434
|
+
}
|
|
4435
|
+
});
|
|
4436
|
+
return cmd;
|
|
4437
|
+
}
|
|
4438
|
+
function billingCommand() {
|
|
4439
|
+
const cmd = new import_commander16.Command("billing").description("Manage your subscription and top-ups");
|
|
4440
|
+
cmd.command("status", { isDefault: true }).description("Show your current plan and entitlements").option("--json", "Output as JSON").action(async (opts) => {
|
|
4441
|
+
const spinner = spin("Fetching plan\u2026");
|
|
4442
|
+
try {
|
|
4443
|
+
const client = makeClient();
|
|
4444
|
+
const res = await client.billing.subscription();
|
|
4445
|
+
spinner.stop();
|
|
4446
|
+
if (opts.json) return jsonOut(res.data);
|
|
4447
|
+
const d = res.data;
|
|
4448
|
+
section("Subscription");
|
|
4449
|
+
detail([
|
|
4450
|
+
["Plan", `${d.planName} (${d.planKey})`],
|
|
4451
|
+
["Status", d.status],
|
|
4452
|
+
["Monthly credits", String(d.monthlyCredits)],
|
|
4453
|
+
["Computer use", d.entitlements?.computerUse ? "yes" : "no"],
|
|
4454
|
+
[
|
|
4455
|
+
"Renews",
|
|
4456
|
+
d.currentPeriodEnd ? new Date(d.currentPeriodEnd).toLocaleDateString() : void 0
|
|
4457
|
+
]
|
|
4458
|
+
]);
|
|
4459
|
+
} catch (e) {
|
|
4460
|
+
spinner.stop();
|
|
4461
|
+
console.error(c.error(e.message));
|
|
4462
|
+
process.exit(1);
|
|
4463
|
+
}
|
|
4464
|
+
});
|
|
4465
|
+
cmd.command("upgrade <plan>").description("Start a checkout to upgrade (plus | pro | max)").action(async (plan) => {
|
|
4466
|
+
try {
|
|
4467
|
+
const client = makeClient();
|
|
4468
|
+
const res = await client.billing.subscribe(plan);
|
|
4469
|
+
const url = res?.data?.url;
|
|
4470
|
+
if (!url) {
|
|
4471
|
+
console.error(c.error("Could not create checkout session"));
|
|
4472
|
+
process.exit(1);
|
|
4473
|
+
}
|
|
4474
|
+
console.log(c.dim("Opening checkout in your browser:"));
|
|
4475
|
+
console.log(url);
|
|
4476
|
+
await openBrowser(url);
|
|
4477
|
+
} catch (e) {
|
|
4478
|
+
console.error(c.error(e.message));
|
|
4479
|
+
process.exit(1);
|
|
4480
|
+
}
|
|
4481
|
+
});
|
|
4482
|
+
cmd.command("topup <pack>").description("Buy a one-time credit pack (small | medium | large)").action(async (pack) => {
|
|
4483
|
+
try {
|
|
4484
|
+
const client = makeClient();
|
|
4485
|
+
const res = await client.billing.topup(pack);
|
|
4486
|
+
const url = res?.data?.url;
|
|
4487
|
+
if (!url) {
|
|
4488
|
+
console.error(c.error("Could not create checkout session"));
|
|
4489
|
+
process.exit(1);
|
|
4490
|
+
}
|
|
4491
|
+
console.log(url);
|
|
4492
|
+
await openBrowser(url);
|
|
4493
|
+
} catch (e) {
|
|
4494
|
+
console.error(c.error(e.message));
|
|
4495
|
+
process.exit(1);
|
|
4496
|
+
}
|
|
4497
|
+
});
|
|
4498
|
+
return cmd;
|
|
4499
|
+
}
|
|
4500
|
+
|
|
4501
|
+
// src/commands/logs.ts
|
|
4502
|
+
var import_commander17 = require("commander");
|
|
4503
|
+
var STATUS_COLOR = {
|
|
4504
|
+
success: (s) => c.bold(s),
|
|
4505
|
+
error: (s) => c.error(s),
|
|
4506
|
+
warning: (s) => c.warn(s)
|
|
4507
|
+
};
|
|
4508
|
+
function colorStatus(status) {
|
|
4509
|
+
return (STATUS_COLOR[status] ?? c.dim)(status);
|
|
4510
|
+
}
|
|
4511
|
+
function logsCommand() {
|
|
4512
|
+
const cmd = new import_commander17.Command("logs").description("View agent activity logs");
|
|
4513
|
+
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) => {
|
|
4514
|
+
const cfg = loadConfig();
|
|
4515
|
+
const agentId2 = opts.agent ?? cfg.defaultAgentId;
|
|
4516
|
+
if (!agentId2) {
|
|
4262
4517
|
console.error(c.error("Specify --agent <agentId> or set defaultAgentId"));
|
|
4263
4518
|
process.exit(1);
|
|
4264
4519
|
}
|
|
4265
4520
|
const spinner = spin("Fetching logs\u2026");
|
|
4266
4521
|
try {
|
|
4267
4522
|
const client = makeClient();
|
|
4268
|
-
const
|
|
4269
|
-
|
|
4270
|
-
|
|
4523
|
+
const res = await client.logs.list(agentId2, {
|
|
4524
|
+
limit: Number(opts.limit),
|
|
4525
|
+
sessionId: opts.session
|
|
4526
|
+
});
|
|
4271
4527
|
let logs = res?.data ?? res ?? [];
|
|
4272
4528
|
if (opts.status) logs = logs.filter((l) => l.status === opts.status);
|
|
4273
4529
|
spinner.stop();
|
|
4274
4530
|
if (opts.json) return jsonOut(logs);
|
|
4275
|
-
section(`Logs \u2014 ${
|
|
4531
|
+
section(`Logs \u2014 ${agentId2.slice(0, 12)}\u2026 (${logs.length})`);
|
|
4276
4532
|
if (logs.length === 0) {
|
|
4277
4533
|
console.log(c.dim(" No logs yet"));
|
|
4278
4534
|
return;
|
|
@@ -4290,26 +4546,28 @@ function logsCommand() {
|
|
|
4290
4546
|
console.log("");
|
|
4291
4547
|
});
|
|
4292
4548
|
} catch (err) {
|
|
4293
|
-
|
|
4549
|
+
spinner.stop();
|
|
4294
4550
|
printError(err);
|
|
4295
4551
|
process.exit(1);
|
|
4296
4552
|
}
|
|
4297
4553
|
});
|
|
4298
4554
|
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) => {
|
|
4299
4555
|
const cfg = loadConfig();
|
|
4300
|
-
const
|
|
4301
|
-
if (!
|
|
4556
|
+
const agentId2 = opts.agent ?? cfg.defaultAgentId;
|
|
4557
|
+
if (!agentId2) {
|
|
4302
4558
|
console.error(c.error("Specify --agent <agentId>"));
|
|
4303
4559
|
process.exit(1);
|
|
4304
4560
|
}
|
|
4305
4561
|
const spinner = spin("Fetching error logs\u2026");
|
|
4306
4562
|
try {
|
|
4307
4563
|
const client = makeClient();
|
|
4308
|
-
const res = await client.
|
|
4564
|
+
const res = await client.logs.list(agentId2, {
|
|
4565
|
+
limit: Number(opts.limit)
|
|
4566
|
+
});
|
|
4309
4567
|
const errors = (res?.data ?? []).filter((l) => l.status === "error");
|
|
4310
4568
|
spinner.stop();
|
|
4311
4569
|
if (opts.json) return jsonOut(errors);
|
|
4312
|
-
section(`Errors \u2014 ${
|
|
4570
|
+
section(`Errors \u2014 ${agentId2.slice(0, 12)}\u2026 (${errors.length})`);
|
|
4313
4571
|
if (errors.length === 0) {
|
|
4314
4572
|
console.log(`${sym.ok} No errors found`);
|
|
4315
4573
|
return;
|
|
@@ -4329,7 +4587,7 @@ function logsCommand() {
|
|
|
4329
4587
|
}
|
|
4330
4588
|
|
|
4331
4589
|
// src/commands/computer.ts
|
|
4332
|
-
var
|
|
4590
|
+
var import_commander18 = require("commander");
|
|
4333
4591
|
var RESOURCE_PROFILES = [
|
|
4334
4592
|
"starter",
|
|
4335
4593
|
"standard",
|
|
@@ -4338,13 +4596,13 @@ var RESOURCE_PROFILES = [
|
|
|
4338
4596
|
];
|
|
4339
4597
|
var RESOURCE_MODES = ["fixed", "elastic"];
|
|
4340
4598
|
function resolveAgentId(opts) {
|
|
4341
|
-
const
|
|
4342
|
-
if (!
|
|
4599
|
+
const agentId2 = opts.agent ?? loadConfig().defaultAgentId;
|
|
4600
|
+
if (!agentId2) {
|
|
4343
4601
|
throw new Error(
|
|
4344
4602
|
"Specify --agent <agentId> or set defaultAgentId with `agc config set defaultAgentId <id>`."
|
|
4345
4603
|
);
|
|
4346
4604
|
}
|
|
4347
|
-
return
|
|
4605
|
+
return agentId2;
|
|
4348
4606
|
}
|
|
4349
4607
|
function unwrap(response) {
|
|
4350
4608
|
return response?.data ?? response;
|
|
@@ -4395,17 +4653,17 @@ function parseNumber(value, name, options) {
|
|
|
4395
4653
|
}
|
|
4396
4654
|
return parsed;
|
|
4397
4655
|
}
|
|
4398
|
-
async function changeEnabled(
|
|
4656
|
+
async function changeEnabled(agentId2, enabled, json) {
|
|
4399
4657
|
const spinner = spin(`${enabled ? "Enabling" : "Disabling"} persistent cloud computer\u2026`);
|
|
4400
4658
|
try {
|
|
4401
|
-
const response = await makeClient().agents.updateComputerConfig(
|
|
4659
|
+
const response = await makeClient().agents.updateComputerConfig(agentId2, { enabled });
|
|
4402
4660
|
const config = unwrap(response);
|
|
4403
4661
|
spinner.stop();
|
|
4404
4662
|
if (json) return jsonOut(config);
|
|
4405
4663
|
console.log(`
|
|
4406
|
-
${sym.ok} Persistent cloud computer ${enabled ? "enabled" : "disabled"} for agent ${c.id(
|
|
4664
|
+
${sym.ok} Persistent cloud computer ${enabled ? "enabled" : "disabled"} for agent ${c.id(agentId2)}`);
|
|
4407
4665
|
if (enabled) {
|
|
4408
|
-
console.log(c.dim(` Wake it now with: agc computer wake --agent ${
|
|
4666
|
+
console.log(c.dim(` Wake it now with: agc computer wake --agent ${agentId2}`));
|
|
4409
4667
|
}
|
|
4410
4668
|
} catch (error) {
|
|
4411
4669
|
spinner.stop();
|
|
@@ -4413,12 +4671,12 @@ ${sym.ok} Persistent cloud computer ${enabled ? "enabled" : "disabled"} for agen
|
|
|
4413
4671
|
process.exitCode = 1;
|
|
4414
4672
|
}
|
|
4415
4673
|
}
|
|
4416
|
-
async function lifecycleAction(action,
|
|
4674
|
+
async function lifecycleAction(action, agentId2, reason, json) {
|
|
4417
4675
|
const verb = action === "wake" ? "Waking" : action === "sleep" ? "Sleeping" : "Restarting";
|
|
4418
4676
|
const spinner = spin(`${verb} persistent cloud computer\u2026`);
|
|
4419
4677
|
try {
|
|
4420
4678
|
const client = makeClient();
|
|
4421
|
-
const response = action === "wake" ? await client.agents.wakeComputer(
|
|
4679
|
+
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);
|
|
4422
4680
|
const computer = unwrap(response);
|
|
4423
4681
|
spinner.stop();
|
|
4424
4682
|
if (json) return jsonOut(computer);
|
|
@@ -4435,11 +4693,11 @@ function addAgentOption(command) {
|
|
|
4435
4693
|
return command.option("--agent <agentId>", "Agent ID (defaults to configured agent)");
|
|
4436
4694
|
}
|
|
4437
4695
|
function computerCommand() {
|
|
4438
|
-
const command = new
|
|
4696
|
+
const command = new import_commander18.Command("computer").description("Manage an agent's one persistent cloud computer");
|
|
4439
4697
|
addAgentOption(command.command("status").description("Show persistent cloud computer status")).option("--json", "Output as JSON").action(async (opts) => {
|
|
4440
|
-
let
|
|
4698
|
+
let agentId2;
|
|
4441
4699
|
try {
|
|
4442
|
-
|
|
4700
|
+
agentId2 = resolveAgentId(opts);
|
|
4443
4701
|
} catch (error) {
|
|
4444
4702
|
printError(error);
|
|
4445
4703
|
process.exitCode = 1;
|
|
@@ -4447,7 +4705,7 @@ function computerCommand() {
|
|
|
4447
4705
|
}
|
|
4448
4706
|
const spinner = spin("Fetching persistent cloud computer\u2026");
|
|
4449
4707
|
try {
|
|
4450
|
-
const computer = unwrap(await makeClient().agents.getComputer(
|
|
4708
|
+
const computer = unwrap(await makeClient().agents.getComputer(agentId2));
|
|
4451
4709
|
spinner.stop();
|
|
4452
4710
|
if (opts.json) return jsonOut(computer);
|
|
4453
4711
|
displayComputer(computer);
|
|
@@ -4489,10 +4747,10 @@ function computerCommand() {
|
|
|
4489
4747
|
});
|
|
4490
4748
|
}
|
|
4491
4749
|
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) => {
|
|
4492
|
-
let
|
|
4750
|
+
let agentId2;
|
|
4493
4751
|
let resize;
|
|
4494
4752
|
try {
|
|
4495
|
-
|
|
4753
|
+
agentId2 = resolveAgentId(opts);
|
|
4496
4754
|
if (opts.profile && !RESOURCE_PROFILES.includes(opts.profile)) {
|
|
4497
4755
|
throw new Error(`--profile must be one of: ${RESOURCE_PROFILES.join(", ")}.`);
|
|
4498
4756
|
}
|
|
@@ -4529,7 +4787,7 @@ function computerCommand() {
|
|
|
4529
4787
|
}
|
|
4530
4788
|
const spinner = spin("Resizing persistent cloud computer\u2026");
|
|
4531
4789
|
try {
|
|
4532
|
-
const computer = unwrap(await makeClient().agents.resizeComputer(
|
|
4790
|
+
const computer = unwrap(await makeClient().agents.resizeComputer(agentId2, resize));
|
|
4533
4791
|
spinner.stop();
|
|
4534
4792
|
if (opts.json) return jsonOut(computer);
|
|
4535
4793
|
console.log(`
|
|
@@ -4544,10 +4802,10 @@ ${sym.ok} Persistent cloud computer resize requested`);
|
|
|
4544
4802
|
addAgentOption(
|
|
4545
4803
|
command.command("exec").description("Run a command in the persistent cloud computer").argument("<command...>", "Command and arguments to run")
|
|
4546
4804
|
).option("--cwd <path>", "Working directory").option("--timeout <seconds>", "Command timeout in seconds", "120").option("--json", "Output as JSON").action(async (commandParts, opts) => {
|
|
4547
|
-
let
|
|
4805
|
+
let agentId2;
|
|
4548
4806
|
let timeoutSeconds;
|
|
4549
4807
|
try {
|
|
4550
|
-
|
|
4808
|
+
agentId2 = resolveAgentId(opts);
|
|
4551
4809
|
timeoutSeconds = parseNumber(opts.timeout, "Timeout");
|
|
4552
4810
|
} catch (error) {
|
|
4553
4811
|
printError(error);
|
|
@@ -4556,7 +4814,7 @@ ${sym.ok} Persistent cloud computer resize requested`);
|
|
|
4556
4814
|
}
|
|
4557
4815
|
const spinner = spin("Running command in persistent cloud computer\u2026");
|
|
4558
4816
|
try {
|
|
4559
|
-
const result = unwrap(await makeClient().agents.execComputer(
|
|
4817
|
+
const result = unwrap(await makeClient().agents.execComputer(agentId2, {
|
|
4560
4818
|
command: commandParts.join(" "),
|
|
4561
4819
|
...opts.cwd && { cwd: opts.cwd },
|
|
4562
4820
|
...timeoutSeconds !== void 0 && { timeoutSeconds }
|
|
@@ -4576,10 +4834,10 @@ ${sym.ok} Persistent cloud computer resize requested`);
|
|
|
4576
4834
|
}
|
|
4577
4835
|
});
|
|
4578
4836
|
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) => {
|
|
4579
|
-
let
|
|
4837
|
+
let agentId2;
|
|
4580
4838
|
let limit;
|
|
4581
4839
|
try {
|
|
4582
|
-
|
|
4840
|
+
agentId2 = resolveAgentId(opts);
|
|
4583
4841
|
limit = parseNumber(opts.limit, "Limit", { integer: true });
|
|
4584
4842
|
} catch (error) {
|
|
4585
4843
|
printError(error);
|
|
@@ -4588,7 +4846,7 @@ ${sym.ok} Persistent cloud computer resize requested`);
|
|
|
4588
4846
|
}
|
|
4589
4847
|
const spinner = spin("Fetching persistent cloud computer events\u2026");
|
|
4590
4848
|
try {
|
|
4591
|
-
const events = unwrap(await makeClient().agents.listComputerEvents(
|
|
4849
|
+
const events = unwrap(await makeClient().agents.listComputerEvents(agentId2, limit));
|
|
4592
4850
|
spinner.stop();
|
|
4593
4851
|
if (opts.json) return jsonOut(events);
|
|
4594
4852
|
section(`Cloud computer events (${events.length})`);
|
|
@@ -4610,8 +4868,472 @@ ${sym.ok} Persistent cloud computer resize requested`);
|
|
|
4610
4868
|
return command;
|
|
4611
4869
|
}
|
|
4612
4870
|
|
|
4871
|
+
// src/commands/library.ts
|
|
4872
|
+
var import_commander19 = require("commander");
|
|
4873
|
+
var import_fs7 = require("fs");
|
|
4874
|
+
var import_path5 = require("path");
|
|
4875
|
+
function libraryCommand() {
|
|
4876
|
+
const command = new import_commander19.Command("library").alias("files").description("Upload, find, and manage files in your Commons library");
|
|
4877
|
+
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) => {
|
|
4878
|
+
const spinner = spin("Fetching your library\u2026");
|
|
4879
|
+
try {
|
|
4880
|
+
const result = await makeClient().library.list({
|
|
4881
|
+
query: opts.query,
|
|
4882
|
+
source: opts.source,
|
|
4883
|
+
sessionId: opts.session,
|
|
4884
|
+
favorite: opts.favorites ? true : void 0,
|
|
4885
|
+
limit: Number(opts.limit)
|
|
4886
|
+
});
|
|
4887
|
+
spinner.stop();
|
|
4888
|
+
if (opts.json) return jsonOut(result);
|
|
4889
|
+
section(`Library (${result.data.length})`);
|
|
4890
|
+
table(
|
|
4891
|
+
result.data.map((item) => ({
|
|
4892
|
+
ID: String(item.itemId ?? item.fileId).slice(0, 10) + "\u2026",
|
|
4893
|
+
Name: item.name ?? item.originalName ?? "(untitled)",
|
|
4894
|
+
Type: item.mimeType ?? "",
|
|
4895
|
+
Size: typeof item.size === "number" ? `${Math.ceil(item.size / 1024)} KB` : "",
|
|
4896
|
+
Favorite: item.isFavorite ? "\u2605" : "",
|
|
4897
|
+
Created: item.createdAt ? relativeTime(item.createdAt) : ""
|
|
4898
|
+
})),
|
|
4899
|
+
["ID", "Name", "Type", "Size", "Favorite", "Created"]
|
|
4900
|
+
);
|
|
4901
|
+
} catch (error) {
|
|
4902
|
+
spinner.stop();
|
|
4903
|
+
printError(error);
|
|
4904
|
+
process.exit(1);
|
|
4905
|
+
}
|
|
4906
|
+
});
|
|
4907
|
+
command.command("get <itemId>").description("Show library item details").option("--json", "Output as JSON").action(async (itemId, opts) => {
|
|
4908
|
+
const spinner = spin("Fetching library item\u2026");
|
|
4909
|
+
try {
|
|
4910
|
+
const result = await makeClient().library.get(itemId);
|
|
4911
|
+
spinner.stop();
|
|
4912
|
+
if (opts.json) return jsonOut(result.data);
|
|
4913
|
+
const item = result.data;
|
|
4914
|
+
detail([
|
|
4915
|
+
["Item ID", c.id(String(item.itemId ?? item.fileId))],
|
|
4916
|
+
["Name", item.name ?? item.originalName ?? "(untitled)"],
|
|
4917
|
+
["Description", item.description ?? ""],
|
|
4918
|
+
["Type", item.mimeType ?? ""],
|
|
4919
|
+
["Storage", item.storageProvider ?? ""],
|
|
4920
|
+
["Favorite", item.isFavorite ? "yes" : "no"],
|
|
4921
|
+
["Created", item.createdAt ? relativeTime(item.createdAt) : ""]
|
|
4922
|
+
]);
|
|
4923
|
+
} catch (error) {
|
|
4924
|
+
spinner.stop();
|
|
4925
|
+
printError(error);
|
|
4926
|
+
process.exit(1);
|
|
4927
|
+
}
|
|
4928
|
+
});
|
|
4929
|
+
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) => {
|
|
4930
|
+
const spinner = spin(`Uploading ${paths.length} file${paths.length === 1 ? "" : "s"}\u2026`);
|
|
4931
|
+
try {
|
|
4932
|
+
if (opts.storage && opts.storage !== "s3" && opts.storage !== "ipfs") {
|
|
4933
|
+
throw new Error("--storage must be either s3 or ipfs.");
|
|
4934
|
+
}
|
|
4935
|
+
const files = paths.map((path) => ({
|
|
4936
|
+
data: new Blob([new Uint8Array((0, import_fs7.readFileSync)(path))]),
|
|
4937
|
+
name: (0, import_path5.basename)(path)
|
|
4938
|
+
}));
|
|
4939
|
+
const result = await makeClient().files.upload(files, {
|
|
4940
|
+
agentId: opts.agent,
|
|
4941
|
+
sessionId: opts.session,
|
|
4942
|
+
storageProvider: opts.storage
|
|
4943
|
+
});
|
|
4944
|
+
spinner.stop();
|
|
4945
|
+
if (opts.json) return jsonOut(result.data);
|
|
4946
|
+
console.log(
|
|
4947
|
+
`
|
|
4948
|
+
${sym.ok} Uploaded ${result.data.length} file${result.data.length === 1 ? "" : "s"}.`
|
|
4949
|
+
);
|
|
4950
|
+
for (const file of result.data) {
|
|
4951
|
+
console.log(
|
|
4952
|
+
` ${sym.arrow} ${c.bold(file.name ?? file.originalName ?? file.fileId)} ${c.dim(file.fileId)}`
|
|
4953
|
+
);
|
|
4954
|
+
}
|
|
4955
|
+
} catch (error) {
|
|
4956
|
+
spinner.stop();
|
|
4957
|
+
printError(error);
|
|
4958
|
+
process.exit(1);
|
|
4959
|
+
}
|
|
4960
|
+
});
|
|
4961
|
+
for (const favorite of [true, false]) {
|
|
4962
|
+
command.command(`${favorite ? "favorite" : "unfavorite"} <itemId>`).description(`${favorite ? "Add" : "Remove"} a library item ${favorite ? "to" : "from"} favorites`).action(async (itemId) => {
|
|
4963
|
+
const spinner = spin("Updating library item\u2026");
|
|
4964
|
+
try {
|
|
4965
|
+
await makeClient().library.update(itemId, {
|
|
4966
|
+
isFavorite: favorite
|
|
4967
|
+
});
|
|
4968
|
+
spinner.stop();
|
|
4969
|
+
console.log(
|
|
4970
|
+
`${sym.ok} Item ${favorite ? "added to" : "removed from"} favorites.`
|
|
4971
|
+
);
|
|
4972
|
+
} catch (error) {
|
|
4973
|
+
spinner.stop();
|
|
4974
|
+
printError(error);
|
|
4975
|
+
process.exit(1);
|
|
4976
|
+
}
|
|
4977
|
+
});
|
|
4978
|
+
}
|
|
4979
|
+
command.command("delete <itemId>").description("Delete a library item").action(async (itemId) => {
|
|
4980
|
+
const spinner = spin("Deleting library item\u2026");
|
|
4981
|
+
try {
|
|
4982
|
+
await makeClient().library.delete(itemId);
|
|
4983
|
+
spinner.stop();
|
|
4984
|
+
console.log(`${sym.ok} Library item deleted.`);
|
|
4985
|
+
} catch (error) {
|
|
4986
|
+
spinner.stop();
|
|
4987
|
+
printError(error);
|
|
4988
|
+
process.exit(1);
|
|
4989
|
+
}
|
|
4990
|
+
});
|
|
4991
|
+
return command;
|
|
4992
|
+
}
|
|
4993
|
+
|
|
4994
|
+
// src/commands/projects.ts
|
|
4995
|
+
var import_commander20 = require("commander");
|
|
4996
|
+
var import_fs8 = require("fs");
|
|
4997
|
+
function agentId(value) {
|
|
4998
|
+
const resolved = value ?? loadConfig().defaultAgentId;
|
|
4999
|
+
if (!resolved) {
|
|
5000
|
+
throw new Error(
|
|
5001
|
+
"Specify --agent <agentId> or set a default with `agc config set defaultAgentId <id>`."
|
|
5002
|
+
);
|
|
5003
|
+
}
|
|
5004
|
+
return resolved;
|
|
5005
|
+
}
|
|
5006
|
+
function projectFiles(path) {
|
|
5007
|
+
if (!path) return void 0;
|
|
5008
|
+
const parsed = JSON.parse((0, import_fs8.readFileSync)(path, "utf8"));
|
|
5009
|
+
const files = Array.isArray(parsed) ? parsed : parsed.files;
|
|
5010
|
+
if (!Array.isArray(files)) {
|
|
5011
|
+
throw new Error("The files document must be an array or an object with a files array.");
|
|
5012
|
+
}
|
|
5013
|
+
return files;
|
|
5014
|
+
}
|
|
5015
|
+
function projectsCommand() {
|
|
5016
|
+
const command = new import_commander20.Command("projects").alias("project").description("Build, publish, and export agent code projects");
|
|
5017
|
+
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) => {
|
|
5018
|
+
const spinner = spin("Fetching projects\u2026");
|
|
5019
|
+
try {
|
|
5020
|
+
const result = await makeClient().projects.list(agentId(opts.agent));
|
|
5021
|
+
spinner.stop();
|
|
5022
|
+
if (opts.json) return jsonOut(result.data);
|
|
5023
|
+
section(`Projects (${result.data.length})`);
|
|
5024
|
+
table(
|
|
5025
|
+
result.data.map((project) => ({
|
|
5026
|
+
ID: project.projectId.slice(0, 10) + "\u2026",
|
|
5027
|
+
Name: project.name,
|
|
5028
|
+
Files: String(project.files?.length ?? ""),
|
|
5029
|
+
Preview: project.previewUrl ?? project.previewSlug ?? "",
|
|
5030
|
+
Updated: project.updatedAt ?? ""
|
|
5031
|
+
})),
|
|
5032
|
+
["ID", "Name", "Files", "Preview", "Updated"]
|
|
5033
|
+
);
|
|
5034
|
+
} catch (error) {
|
|
5035
|
+
spinner.stop();
|
|
5036
|
+
printError(error);
|
|
5037
|
+
process.exit(1);
|
|
5038
|
+
}
|
|
5039
|
+
});
|
|
5040
|
+
command.command("get <projectId>").description("Show a code project").option("--agent <agentId>", "Agent ID").option("--json", "Output as JSON").action(async (projectId, opts) => {
|
|
5041
|
+
const spinner = spin("Fetching project\u2026");
|
|
5042
|
+
try {
|
|
5043
|
+
const result = await makeClient().projects.get(
|
|
5044
|
+
agentId(opts.agent),
|
|
5045
|
+
projectId
|
|
5046
|
+
);
|
|
5047
|
+
spinner.stop();
|
|
5048
|
+
if (opts.json) return jsonOut(result.data);
|
|
5049
|
+
const project = result.data;
|
|
5050
|
+
section(project.name);
|
|
5051
|
+
detail([
|
|
5052
|
+
["Project ID", c.id(project.projectId)],
|
|
5053
|
+
["Agent ID", project.agentId],
|
|
5054
|
+
["Description", project.description ?? ""],
|
|
5055
|
+
["Files", String(project.files?.length ?? 0)],
|
|
5056
|
+
["Preview", project.previewUrl ?? project.previewSlug ?? ""],
|
|
5057
|
+
["Updated", project.updatedAt ?? ""]
|
|
5058
|
+
]);
|
|
5059
|
+
} catch (error) {
|
|
5060
|
+
spinner.stop();
|
|
5061
|
+
printError(error);
|
|
5062
|
+
process.exit(1);
|
|
5063
|
+
}
|
|
5064
|
+
});
|
|
5065
|
+
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) => {
|
|
5066
|
+
const spinner = spin("Creating project\u2026");
|
|
5067
|
+
try {
|
|
5068
|
+
const result = await makeClient().projects.create(
|
|
5069
|
+
agentId(opts.agent),
|
|
5070
|
+
{
|
|
5071
|
+
name: opts.name,
|
|
5072
|
+
description: opts.description,
|
|
5073
|
+
sessionId: opts.session,
|
|
5074
|
+
files: projectFiles(opts.files)
|
|
5075
|
+
}
|
|
5076
|
+
);
|
|
5077
|
+
spinner.stop();
|
|
5078
|
+
if (opts.json) return jsonOut(result.data);
|
|
5079
|
+
console.log(`
|
|
5080
|
+
${sym.ok} Project created.`);
|
|
5081
|
+
detail([
|
|
5082
|
+
["Project ID", c.id(result.data.projectId)],
|
|
5083
|
+
["Name", result.data.name]
|
|
5084
|
+
]);
|
|
5085
|
+
} catch (error) {
|
|
5086
|
+
spinner.stop();
|
|
5087
|
+
printError(error);
|
|
5088
|
+
process.exit(1);
|
|
5089
|
+
}
|
|
5090
|
+
});
|
|
5091
|
+
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) => {
|
|
5092
|
+
const spinner = spin("Writing project files\u2026");
|
|
5093
|
+
try {
|
|
5094
|
+
const result = await makeClient().projects.writeFiles(
|
|
5095
|
+
agentId(opts.agent),
|
|
5096
|
+
projectId,
|
|
5097
|
+
projectFiles(json) ?? [],
|
|
5098
|
+
Boolean(opts.replace)
|
|
5099
|
+
);
|
|
5100
|
+
spinner.stop();
|
|
5101
|
+
if (opts.json) return jsonOut(result.data);
|
|
5102
|
+
console.log(`${sym.ok} Project files updated.`);
|
|
5103
|
+
} catch (error) {
|
|
5104
|
+
spinner.stop();
|
|
5105
|
+
printError(error);
|
|
5106
|
+
process.exit(1);
|
|
5107
|
+
}
|
|
5108
|
+
});
|
|
5109
|
+
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) => {
|
|
5110
|
+
const spinner = spin("Building and publishing project\u2026");
|
|
5111
|
+
try {
|
|
5112
|
+
const result = await makeClient().projects.publish(
|
|
5113
|
+
agentId(opts.agent),
|
|
5114
|
+
projectId
|
|
5115
|
+
);
|
|
5116
|
+
spinner.stop();
|
|
5117
|
+
if (opts.json) return jsonOut(result.data);
|
|
5118
|
+
console.log(`
|
|
5119
|
+
${sym.ok} Project published.`);
|
|
5120
|
+
jsonOut(result.data);
|
|
5121
|
+
} catch (error) {
|
|
5122
|
+
spinner.stop();
|
|
5123
|
+
printError(error);
|
|
5124
|
+
process.exit(1);
|
|
5125
|
+
}
|
|
5126
|
+
});
|
|
5127
|
+
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) => {
|
|
5128
|
+
const spinner = spin("Exporting project\u2026");
|
|
5129
|
+
try {
|
|
5130
|
+
const result = await makeClient().projects.exportToComputer(
|
|
5131
|
+
agentId(opts.agent),
|
|
5132
|
+
projectId,
|
|
5133
|
+
{ directory: opts.directory, sessionId: opts.session }
|
|
5134
|
+
);
|
|
5135
|
+
spinner.stop();
|
|
5136
|
+
if (opts.json) return jsonOut(result.data);
|
|
5137
|
+
console.log(`${sym.ok} Project exported to the agent computer.`);
|
|
5138
|
+
jsonOut(result.data);
|
|
5139
|
+
} catch (error) {
|
|
5140
|
+
spinner.stop();
|
|
5141
|
+
printError(error);
|
|
5142
|
+
process.exit(1);
|
|
5143
|
+
}
|
|
5144
|
+
});
|
|
5145
|
+
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) => {
|
|
5146
|
+
const spinner = spin("Exporting project to GitHub\u2026");
|
|
5147
|
+
try {
|
|
5148
|
+
const result = await makeClient().projects.exportToGitHub(
|
|
5149
|
+
agentId(opts.agent),
|
|
5150
|
+
projectId,
|
|
5151
|
+
{
|
|
5152
|
+
repositoryName: opts.repository,
|
|
5153
|
+
private: !opts.public
|
|
5154
|
+
}
|
|
5155
|
+
);
|
|
5156
|
+
spinner.stop();
|
|
5157
|
+
if (opts.json) return jsonOut(result.data);
|
|
5158
|
+
console.log(`${sym.ok} Project exported to GitHub.`);
|
|
5159
|
+
jsonOut(result.data);
|
|
5160
|
+
} catch (error) {
|
|
5161
|
+
spinner.stop();
|
|
5162
|
+
printError(error);
|
|
5163
|
+
process.exit(1);
|
|
5164
|
+
}
|
|
5165
|
+
});
|
|
5166
|
+
return command;
|
|
5167
|
+
}
|
|
5168
|
+
|
|
5169
|
+
// src/commands/api-keys.ts
|
|
5170
|
+
var import_commander21 = require("commander");
|
|
5171
|
+
async function resolveProject(projectId) {
|
|
5172
|
+
const projects = (await makeClient().developer.listProjects()).data;
|
|
5173
|
+
const project = projectId ? projects.find((candidate) => candidate.id === projectId) : projects[0];
|
|
5174
|
+
if (!project) {
|
|
5175
|
+
throw new Error(
|
|
5176
|
+
projectId ? `Developer project "${projectId}" was not found.` : "No developer project exists. Create one with `agc keys projects create --name <name>`."
|
|
5177
|
+
);
|
|
5178
|
+
}
|
|
5179
|
+
return project;
|
|
5180
|
+
}
|
|
5181
|
+
function apiKeysCommand() {
|
|
5182
|
+
const command = new import_commander21.Command("keys").alias("api-keys").description("Create and manage project-scoped developer API keys");
|
|
5183
|
+
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) => {
|
|
5184
|
+
const spinner = spin("Fetching developer keys\u2026");
|
|
5185
|
+
try {
|
|
5186
|
+
const project = await resolveProject(opts.project);
|
|
5187
|
+
const result = await makeClient().developer.listApiKeys(project.id);
|
|
5188
|
+
spinner.stop();
|
|
5189
|
+
if (opts.json) {
|
|
5190
|
+
return jsonOut({ project, keys: result.data });
|
|
5191
|
+
}
|
|
5192
|
+
section(`${project.name} \xB7 API keys (${result.data.length})`);
|
|
5193
|
+
table(
|
|
5194
|
+
result.data.map((key) => ({
|
|
5195
|
+
ID: key.id.slice(0, 10) + "\u2026",
|
|
5196
|
+
Name: key.name,
|
|
5197
|
+
Prefix: key.keyPrefix,
|
|
5198
|
+
Status: key.status,
|
|
5199
|
+
Scopes: String(key.scopes.length),
|
|
5200
|
+
Expires: key.expiresAt ? new Date(key.expiresAt).toLocaleDateString() : "never",
|
|
5201
|
+
Used: key.lastUsedAt ? new Date(key.lastUsedAt).toLocaleDateString() : "never"
|
|
5202
|
+
})),
|
|
5203
|
+
["ID", "Name", "Prefix", "Status", "Scopes", "Expires", "Used"]
|
|
5204
|
+
);
|
|
5205
|
+
} catch (error) {
|
|
5206
|
+
spinner.stop();
|
|
5207
|
+
printError(error);
|
|
5208
|
+
process.exit(1);
|
|
5209
|
+
}
|
|
5210
|
+
});
|
|
5211
|
+
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) => {
|
|
5212
|
+
const spinner = spin("Creating developer key\u2026");
|
|
5213
|
+
try {
|
|
5214
|
+
const project = await resolveProject(opts.project);
|
|
5215
|
+
const scopes = opts.scopes ? String(opts.scopes).split(",").map((scope) => scope.trim()).filter(Boolean) : void 0;
|
|
5216
|
+
const result = await makeClient().developer.createApiKey(project.id, {
|
|
5217
|
+
name: opts.name,
|
|
5218
|
+
scopes,
|
|
5219
|
+
expiresAt: opts.expires
|
|
5220
|
+
});
|
|
5221
|
+
spinner.stop();
|
|
5222
|
+
if (opts.json) return jsonOut(result.data);
|
|
5223
|
+
console.log(`
|
|
5224
|
+
${sym.ok} ${c.success("Developer API key created")}`);
|
|
5225
|
+
detail([
|
|
5226
|
+
["Project", project.name],
|
|
5227
|
+
["Name", result.data.name],
|
|
5228
|
+
["Scopes", result.data.scopes.join(", ")],
|
|
5229
|
+
["Expires", result.data.expiresAt ?? "never"]
|
|
5230
|
+
]);
|
|
5231
|
+
console.log(
|
|
5232
|
+
`
|
|
5233
|
+
${c.warn("Copy this key now. It will not be shown again.")}`
|
|
5234
|
+
);
|
|
5235
|
+
console.log(`
|
|
5236
|
+
${c.bold(result.data.key)}
|
|
5237
|
+
`);
|
|
5238
|
+
} catch (error) {
|
|
5239
|
+
spinner.stop();
|
|
5240
|
+
printError(error);
|
|
5241
|
+
process.exit(1);
|
|
5242
|
+
}
|
|
5243
|
+
});
|
|
5244
|
+
command.command("revoke <keyId>").description("Revoke a developer API key").action(async (keyId) => {
|
|
5245
|
+
const spinner = spin("Revoking developer key\u2026");
|
|
5246
|
+
try {
|
|
5247
|
+
await makeClient().developer.revokeApiKey(keyId);
|
|
5248
|
+
spinner.stop();
|
|
5249
|
+
console.log(`${sym.ok} Developer API key revoked.`);
|
|
5250
|
+
} catch (error) {
|
|
5251
|
+
spinner.stop();
|
|
5252
|
+
printError(error);
|
|
5253
|
+
process.exit(1);
|
|
5254
|
+
}
|
|
5255
|
+
});
|
|
5256
|
+
command.command("scopes").description("List supported developer API scopes").option("--json", "Output as JSON").action(async (opts) => {
|
|
5257
|
+
const spinner = spin("Fetching API scopes\u2026");
|
|
5258
|
+
try {
|
|
5259
|
+
const result = await makeClient().developer.scopes();
|
|
5260
|
+
spinner.stop();
|
|
5261
|
+
if (opts.json) return jsonOut(result.data);
|
|
5262
|
+
section("Developer API scopes");
|
|
5263
|
+
for (const scope of result.data) {
|
|
5264
|
+
console.log(` ${sym.bullet} ${scope}`);
|
|
5265
|
+
}
|
|
5266
|
+
} catch (error) {
|
|
5267
|
+
spinner.stop();
|
|
5268
|
+
printError(error);
|
|
5269
|
+
process.exit(1);
|
|
5270
|
+
}
|
|
5271
|
+
});
|
|
5272
|
+
const projects = command.command("projects").description("Manage developer projects");
|
|
5273
|
+
projects.command("list", { isDefault: true }).alias("ls").description("List developer projects").option("--json", "Output as JSON").action(async (opts) => {
|
|
5274
|
+
const spinner = spin("Fetching developer projects\u2026");
|
|
5275
|
+
try {
|
|
5276
|
+
const result = await makeClient().developer.listProjects();
|
|
5277
|
+
spinner.stop();
|
|
5278
|
+
if (opts.json) return jsonOut(result.data);
|
|
5279
|
+
section(`Developer projects (${result.data.length})`);
|
|
5280
|
+
table(
|
|
5281
|
+
result.data.map((project) => ({
|
|
5282
|
+
ID: project.id,
|
|
5283
|
+
Name: project.name,
|
|
5284
|
+
Environment: project.environment,
|
|
5285
|
+
Status: project.status
|
|
5286
|
+
})),
|
|
5287
|
+
["ID", "Name", "Environment", "Status"]
|
|
5288
|
+
);
|
|
5289
|
+
} catch (error) {
|
|
5290
|
+
spinner.stop();
|
|
5291
|
+
printError(error);
|
|
5292
|
+
process.exit(1);
|
|
5293
|
+
}
|
|
5294
|
+
});
|
|
5295
|
+
projects.command("create").description("Create a developer project").requiredOption("--name <name>", "Project name").option(
|
|
5296
|
+
"--environment <environment>",
|
|
5297
|
+
"production | development | staging",
|
|
5298
|
+
"development"
|
|
5299
|
+
).option("--workspace <workspaceId>", "Workspace ID (defaults to signed-in workspace)").option("--json", "Output as JSON").action(async (opts) => {
|
|
5300
|
+
const workspaceId = opts.workspace ?? loadConfig().workspaceId;
|
|
5301
|
+
if (!workspaceId) {
|
|
5302
|
+
throw new Error(
|
|
5303
|
+
"No workspace is configured. Pass --workspace or sign in again."
|
|
5304
|
+
);
|
|
5305
|
+
}
|
|
5306
|
+
if (!["production", "development", "staging"].includes(opts.environment)) {
|
|
5307
|
+
throw new Error(
|
|
5308
|
+
"--environment must be production, development, or staging."
|
|
5309
|
+
);
|
|
5310
|
+
}
|
|
5311
|
+
const spinner = spin("Creating developer project\u2026");
|
|
5312
|
+
try {
|
|
5313
|
+
const result = await makeClient().developer.createProject({
|
|
5314
|
+
workspaceId,
|
|
5315
|
+
name: opts.name,
|
|
5316
|
+
environment: opts.environment
|
|
5317
|
+
});
|
|
5318
|
+
spinner.stop();
|
|
5319
|
+
if (opts.json) return jsonOut(result.data);
|
|
5320
|
+
console.log(`
|
|
5321
|
+
${sym.ok} Developer project created.`);
|
|
5322
|
+
detail([
|
|
5323
|
+
["Project ID", c.id(result.data.id)],
|
|
5324
|
+
["Name", result.data.name],
|
|
5325
|
+
["Environment", result.data.environment]
|
|
5326
|
+
]);
|
|
5327
|
+
} catch (error) {
|
|
5328
|
+
spinner.stop();
|
|
5329
|
+
printError(error);
|
|
5330
|
+
process.exit(1);
|
|
5331
|
+
}
|
|
5332
|
+
});
|
|
5333
|
+
return command;
|
|
5334
|
+
}
|
|
5335
|
+
|
|
4613
5336
|
// src/bin.ts
|
|
4614
|
-
var CONFIG_FILE3 = (0, import_path5.join)((0, import_os4.homedir)(), ".agc", "config.json");
|
|
4615
5337
|
async function interactiveMenu() {
|
|
4616
5338
|
banner();
|
|
4617
5339
|
const cfg = loadConfig();
|
|
@@ -4638,6 +5360,9 @@ async function interactiveMenu() {
|
|
|
4638
5360
|
{ label: "Workflows", value: "workflows", hint: "agc workflow list" },
|
|
4639
5361
|
{ label: "MCP servers", value: "mcp", hint: "agc mcp list" },
|
|
4640
5362
|
{ label: "Skills", value: "skills", hint: "agc skills list" },
|
|
5363
|
+
{ label: "Library & files", value: "library", hint: "agc library list" },
|
|
5364
|
+
{ label: "Code projects", value: "projects", hint: "agc projects list" },
|
|
5365
|
+
{ label: "Developer API keys", value: "keys", hint: "agc keys list" },
|
|
4641
5366
|
{ label: "Wallet & balance", value: "wallet", hint: "agc wallet balance" },
|
|
4642
5367
|
{ label: "Usage & cost", value: "usage", hint: "agc usage" },
|
|
4643
5368
|
{ label: "Logs", value: "logs", hint: "agc logs" },
|
|
@@ -4648,25 +5373,28 @@ async function interactiveMenu() {
|
|
|
4648
5373
|
process.exit(0);
|
|
4649
5374
|
}
|
|
4650
5375
|
const needsAgent = action === "chat" || action === "run" || action === "computer";
|
|
4651
|
-
const
|
|
4652
|
-
if (needsAgent && !
|
|
5376
|
+
const agentId2 = needsAgent ? cfg.defaultAgentId ?? await pickAgentInteractively(action) : void 0;
|
|
5377
|
+
if (needsAgent && !agentId2) return;
|
|
4653
5378
|
if (action === "run") {
|
|
4654
|
-
const
|
|
4655
|
-
if (!
|
|
4656
|
-
runSubcommand(["run", "--agent",
|
|
5379
|
+
const prompt = await askPrompt("Enter your prompt:");
|
|
5380
|
+
if (!prompt) return;
|
|
5381
|
+
runSubcommand(["run", "--agent", agentId2, prompt]);
|
|
4657
5382
|
return;
|
|
4658
5383
|
}
|
|
4659
5384
|
const commandMap = {
|
|
4660
|
-
chat: ["chat", "--agent",
|
|
5385
|
+
chat: ["chat", "--agent", agentId2],
|
|
4661
5386
|
run: [],
|
|
4662
5387
|
// handled above
|
|
4663
|
-
computer: ["computer", "status", "--agent",
|
|
5388
|
+
computer: ["computer", "status", "--agent", agentId2],
|
|
4664
5389
|
sessions: ["sessions", "list"],
|
|
4665
5390
|
agents: ["agents", "list"],
|
|
4666
5391
|
tasks: ["task", "list"],
|
|
4667
5392
|
workflows: ["workflow", "list"],
|
|
4668
5393
|
mcp: ["mcp", "list"],
|
|
4669
5394
|
skills: ["skills", "list"],
|
|
5395
|
+
library: ["library", "list"],
|
|
5396
|
+
projects: ["projects", "list"],
|
|
5397
|
+
keys: ["keys", "list"],
|
|
4670
5398
|
wallet: ["wallet", "balance"],
|
|
4671
5399
|
usage: ["usage"],
|
|
4672
5400
|
logs: ["logs"],
|
|
@@ -4676,9 +5404,9 @@ async function interactiveMenu() {
|
|
|
4676
5404
|
runSubcommand(commandMap[action]);
|
|
4677
5405
|
}
|
|
4678
5406
|
async function askPrompt(question) {
|
|
4679
|
-
const { createInterface:
|
|
5407
|
+
const { createInterface: createInterface3 } = await import("readline");
|
|
4680
5408
|
return new Promise((resolve2) => {
|
|
4681
|
-
const rl =
|
|
5409
|
+
const rl = createInterface3({ input: process.stdin, output: process.stdout });
|
|
4682
5410
|
process.stdout.write(`
|
|
4683
5411
|
${c.bold(question)}
|
|
4684
5412
|
${c.primary("\u203A")} `);
|
|
@@ -4707,7 +5435,7 @@ async function pickAgentInteractively(action) {
|
|
|
4707
5435
|
} catch {
|
|
4708
5436
|
spinner.stop();
|
|
4709
5437
|
console.log(`
|
|
4710
|
-
${c.warn("\u26A0")} Could not fetch agents. Check your
|
|
5438
|
+
${c.warn("\u26A0")} Could not fetch agents. Check your sign-in and connection.
|
|
4711
5439
|
`);
|
|
4712
5440
|
return null;
|
|
4713
5441
|
}
|
|
@@ -4725,7 +5453,7 @@ async function pickAgentInteractively(action) {
|
|
|
4725
5453
|
return null;
|
|
4726
5454
|
}
|
|
4727
5455
|
console.log();
|
|
4728
|
-
const
|
|
5456
|
+
const agentId2 = await select(
|
|
4729
5457
|
action === "computer" ? "Choose the agent whose cloud computer you want to manage:" : `Choose an agent to ${action} with:`,
|
|
4730
5458
|
agents.map((a) => ({
|
|
4731
5459
|
label: a.name,
|
|
@@ -4738,15 +5466,29 @@ async function pickAgentInteractively(action) {
|
|
|
4738
5466
|
{ label: "No \u2014 just this once", value: false }
|
|
4739
5467
|
]);
|
|
4740
5468
|
if (saveDefault) {
|
|
4741
|
-
saveConfig({ defaultAgentId:
|
|
4742
|
-
const chosen = agents.find((a) => a.agentId ===
|
|
4743
|
-
console.log(` ${sym.ok} ${c.dim("Default agent set to")} ${c.bold(chosen?.name ??
|
|
5469
|
+
saveConfig({ defaultAgentId: agentId2 });
|
|
5470
|
+
const chosen = agents.find((a) => a.agentId === agentId2);
|
|
5471
|
+
console.log(` ${sym.ok} ${c.dim("Default agent set to")} ${c.bold(chosen?.name ?? agentId2)}
|
|
4744
5472
|
`);
|
|
4745
5473
|
}
|
|
4746
|
-
return
|
|
5474
|
+
return agentId2;
|
|
4747
5475
|
}
|
|
4748
|
-
var program = new
|
|
4749
|
-
program.name("agc").description("Agent Commons CLI \u2014 interact with the Agent Commons platform").version("0.
|
|
5476
|
+
var program = new import_commander22.Command();
|
|
5477
|
+
program.name("agc").description("Agent Commons CLI \u2014 interact with the Agent Commons platform").version("0.5.0", "-v, --version").showHelpAfterError("(run `agc --help` for usage)").configureHelp({
|
|
5478
|
+
sortOptions: true,
|
|
5479
|
+
sortSubcommands: true
|
|
5480
|
+
}).addHelpText(
|
|
5481
|
+
"after",
|
|
5482
|
+
`
|
|
5483
|
+
Examples:
|
|
5484
|
+
$ agc login
|
|
5485
|
+
$ agc agents list
|
|
5486
|
+
$ agc run --agent <id> "Summarize this week"
|
|
5487
|
+
$ agc keys create --name "CI" --scopes agents:read,agents:run
|
|
5488
|
+
|
|
5489
|
+
Docs: https://docs.agentcommons.io/docs/cli
|
|
5490
|
+
`
|
|
5491
|
+
).action(async () => {
|
|
4750
5492
|
await interactiveMenu();
|
|
4751
5493
|
});
|
|
4752
5494
|
program.hook("preAction", async (_thisCommand, actionCommand) => {
|
|
@@ -4761,6 +5503,9 @@ program.addCommand(agentsCommand());
|
|
|
4761
5503
|
program.addCommand(sessionsCommand());
|
|
4762
5504
|
program.addCommand(toolsCommand());
|
|
4763
5505
|
program.addCommand(connectionsCommand());
|
|
5506
|
+
program.addCommand(libraryCommand());
|
|
5507
|
+
program.addCommand(projectsCommand());
|
|
5508
|
+
program.addCommand(apiKeysCommand());
|
|
4764
5509
|
program.addCommand(workflowCommand());
|
|
4765
5510
|
program.addCommand(taskCommand());
|
|
4766
5511
|
program.addCommand(runCommand());
|
|
@@ -4773,6 +5518,8 @@ program.addCommand(modelsCommand());
|
|
|
4773
5518
|
program.addCommand(memoryCommand());
|
|
4774
5519
|
program.addCommand(usageCommand());
|
|
4775
5520
|
program.addCommand(logsCommand());
|
|
5521
|
+
program.addCommand(creditsCommand());
|
|
5522
|
+
program.addCommand(billingCommand());
|
|
4776
5523
|
program.on("command:*", () => {
|
|
4777
5524
|
console.error(
|
|
4778
5525
|
`
|
|
@@ -4782,4 +5529,9 @@ program.on("command:*", () => {
|
|
|
4782
5529
|
);
|
|
4783
5530
|
process.exit(1);
|
|
4784
5531
|
});
|
|
4785
|
-
program.
|
|
5532
|
+
program.parseAsync(process.argv).catch((error) => {
|
|
5533
|
+
console.error(`
|
|
5534
|
+
${sym.fail} ${c.error(error instanceof Error ? error.message : String(error))}
|
|
5535
|
+
`);
|
|
5536
|
+
process.exitCode = 1;
|
|
5537
|
+
});
|