@agent-commons/cli 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +206 -0
- package/dist/bin.js +1218 -469
- package/package.json +25 -4
package/dist/bin.js
CHANGED
|
@@ -24,17 +24,14 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
24
24
|
));
|
|
25
25
|
|
|
26
26
|
// src/bin.ts
|
|
27
|
-
var
|
|
28
|
-
var import_path5 = require("path");
|
|
29
|
-
var import_os4 = require("os");
|
|
27
|
+
var import_commander22 = require("commander");
|
|
30
28
|
var import_child_process3 = require("child_process");
|
|
31
29
|
|
|
32
30
|
// src/commands/login.ts
|
|
33
31
|
var import_commander = require("commander");
|
|
34
|
-
var readline = __toESM(require("readline"));
|
|
35
32
|
var import_fs2 = require("fs");
|
|
36
|
-
var import_path2 = require("path");
|
|
37
33
|
var import_os2 = require("os");
|
|
34
|
+
var import_path2 = require("path");
|
|
38
35
|
|
|
39
36
|
// src/config.ts
|
|
40
37
|
var import_fs = require("fs");
|
|
@@ -44,9 +41,16 @@ var import_sdk = require("@agent-commons/sdk");
|
|
|
44
41
|
var CONFIG_DIR = (0, import_path.join)((0, import_os.homedir)(), ".agc");
|
|
45
42
|
var CONFIG_FILE = (0, import_path.join)(CONFIG_DIR, "config.json");
|
|
46
43
|
var DEFAULT_API_URL = process.env.AGC_API_URL ?? "https://api.agentcommons.io";
|
|
47
|
-
var DEFAULT_APP_URL = "https://www.agentcommons.io";
|
|
48
44
|
var DEFAULT_IDENTITY_URL = process.env.COMMONS_IDENTITY_URL ?? "https://auth.agentcommons.io";
|
|
49
45
|
var DEFAULT_IDENTITY_CLIENT_ID = process.env.COMMONS_IDENTITY_CLIENT_ID ?? "commons-cli";
|
|
46
|
+
function readStoredConfig() {
|
|
47
|
+
if (!(0, import_fs.existsSync)(CONFIG_FILE)) return {};
|
|
48
|
+
try {
|
|
49
|
+
return JSON.parse((0, import_fs.readFileSync)(CONFIG_FILE, "utf8"));
|
|
50
|
+
} catch {
|
|
51
|
+
return {};
|
|
52
|
+
}
|
|
53
|
+
}
|
|
50
54
|
function loadConfig() {
|
|
51
55
|
const fromEnv = {
|
|
52
56
|
...process.env.AGC_API_URL && { apiUrl: process.env.AGC_API_URL },
|
|
@@ -56,13 +60,7 @@ function loadConfig() {
|
|
|
56
60
|
...process.env.AGC_INITIATOR && { initiator: process.env.AGC_INITIATOR },
|
|
57
61
|
...process.env.AGC_AGENT_ID && { defaultAgentId: process.env.AGC_AGENT_ID }
|
|
58
62
|
};
|
|
59
|
-
|
|
60
|
-
if ((0, import_fs.existsSync)(CONFIG_FILE)) {
|
|
61
|
-
try {
|
|
62
|
-
fromFile = JSON.parse((0, import_fs.readFileSync)(CONFIG_FILE, "utf8"));
|
|
63
|
-
} catch {
|
|
64
|
-
}
|
|
65
|
-
}
|
|
63
|
+
const fromFile = readStoredConfig();
|
|
66
64
|
return {
|
|
67
65
|
apiUrl: DEFAULT_API_URL,
|
|
68
66
|
identityUrl: DEFAULT_IDENTITY_URL,
|
|
@@ -72,32 +70,44 @@ function loadConfig() {
|
|
|
72
70
|
};
|
|
73
71
|
}
|
|
74
72
|
function saveConfig(updates) {
|
|
75
|
-
const
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
73
|
+
const next = {
|
|
74
|
+
apiUrl: DEFAULT_API_URL,
|
|
75
|
+
identityUrl: DEFAULT_IDENTITY_URL,
|
|
76
|
+
identityClientId: DEFAULT_IDENTITY_CLIENT_ID,
|
|
77
|
+
...readStoredConfig(),
|
|
78
|
+
...updates
|
|
79
|
+
};
|
|
80
|
+
if (!(0, import_fs.existsSync)(CONFIG_DIR)) {
|
|
81
|
+
(0, import_fs.mkdirSync)(CONFIG_DIR, { recursive: true, mode: 448 });
|
|
82
|
+
}
|
|
83
|
+
(0, import_fs.chmodSync)(CONFIG_DIR, 448);
|
|
84
|
+
const temporaryFile = (0, import_path.join)(CONFIG_DIR, `.config-${process.pid}.tmp`);
|
|
85
|
+
(0, import_fs.writeFileSync)(temporaryFile, JSON.stringify(next, null, 2) + "\n", {
|
|
86
|
+
mode: 384
|
|
87
|
+
});
|
|
88
|
+
(0, import_fs.renameSync)(temporaryFile, CONFIG_FILE);
|
|
89
|
+
(0, import_fs.chmodSync)(CONFIG_FILE, 384);
|
|
79
90
|
}
|
|
80
91
|
function clearConfig() {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
{ mode: 384 }
|
|
94
|
-
);
|
|
95
|
-
}
|
|
92
|
+
saveConfig({
|
|
93
|
+
sessionToken: void 0,
|
|
94
|
+
accessToken: void 0,
|
|
95
|
+
accessTokenExpiresAt: void 0,
|
|
96
|
+
userId: void 0,
|
|
97
|
+
userEmail: void 0,
|
|
98
|
+
userName: void 0,
|
|
99
|
+
workspaceId: void 0,
|
|
100
|
+
apiKey: void 0,
|
|
101
|
+
initiator: void 0,
|
|
102
|
+
defaultAgentId: void 0
|
|
103
|
+
});
|
|
96
104
|
}
|
|
97
105
|
function makeClient(overrides) {
|
|
98
106
|
const cfg = { ...loadConfig(), ...overrides };
|
|
99
107
|
return new import_sdk.CommonsClient({
|
|
100
108
|
baseUrl: cfg.apiUrl,
|
|
109
|
+
identityUrl: cfg.identityUrl,
|
|
110
|
+
identityToken: cfg.sessionToken,
|
|
101
111
|
apiKey: cfg.accessToken ?? cfg.apiKey,
|
|
102
112
|
initiator: cfg.userId ?? cfg.initiator
|
|
103
113
|
});
|
|
@@ -113,6 +123,7 @@ function decodeJwtPayload(token) {
|
|
|
113
123
|
}
|
|
114
124
|
async function ensureAccessToken() {
|
|
115
125
|
const cfg = loadConfig();
|
|
126
|
+
if (cfg.accessToken && !cfg.sessionToken) return cfg;
|
|
116
127
|
if (cfg.apiKey && !cfg.sessionToken) return cfg;
|
|
117
128
|
if (cfg.accessToken && cfg.accessTokenExpiresAt && cfg.accessTokenExpiresAt > Date.now() + 3e4) {
|
|
118
129
|
return cfg;
|
|
@@ -122,9 +133,14 @@ async function ensureAccessToken() {
|
|
|
122
133
|
`${cfg.identityUrl.replace(/\/$/, "")}/api/auth/token`,
|
|
123
134
|
{ headers: { Authorization: `Bearer ${cfg.sessionToken}` } }
|
|
124
135
|
);
|
|
125
|
-
if (
|
|
136
|
+
if (response.status === 401 || response.status === 403) {
|
|
126
137
|
throw new Error("Your Commons login has expired. Run `agc login` again.");
|
|
127
138
|
}
|
|
139
|
+
if (!response.ok) {
|
|
140
|
+
throw new Error(
|
|
141
|
+
`Commons Identity is unavailable (${response.status}). Please try again.`
|
|
142
|
+
);
|
|
143
|
+
}
|
|
128
144
|
const data = await response.json();
|
|
129
145
|
if (!data.token) throw new Error("Commons Identity did not return an access token.");
|
|
130
146
|
const claims = decodeJwtPayload(data.token);
|
|
@@ -132,6 +148,8 @@ async function ensureAccessToken() {
|
|
|
132
148
|
accessToken: data.token,
|
|
133
149
|
accessTokenExpiresAt: typeof claims.exp === "number" ? claims.exp * 1e3 : Date.now() + 10 * 60 * 1e3,
|
|
134
150
|
userId: typeof claims.sub === "string" ? claims.sub : cfg.userId,
|
|
151
|
+
userEmail: typeof claims.email === "string" ? claims.email : cfg.userEmail,
|
|
152
|
+
userName: typeof claims.name === "string" ? claims.name : cfg.userName,
|
|
135
153
|
workspaceId: typeof claims.workspace_id === "string" ? claims.workspace_id : cfg.workspaceId,
|
|
136
154
|
initiator: typeof claims.sub === "string" ? claims.sub : cfg.initiator
|
|
137
155
|
};
|
|
@@ -160,15 +178,15 @@ var sym = {
|
|
|
160
178
|
bullet: import_chalk.default.dim("\u2022"),
|
|
161
179
|
dot: import_chalk.default.dim("\xB7")
|
|
162
180
|
};
|
|
163
|
-
function banner(version = "0.
|
|
164
|
-
const line = import_chalk.default.cyan(" \u2500".padEnd(2) + "\u2500".repeat(44));
|
|
181
|
+
function banner(version = "0.4.0") {
|
|
165
182
|
console.log("");
|
|
166
|
-
console.log(
|
|
183
|
+
console.log(import_chalk.default.cyan(" \u25C7"));
|
|
184
|
+
console.log(import_chalk.default.cyan(" \u256D\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256E"));
|
|
167
185
|
console.log(
|
|
168
|
-
import_chalk.default.cyan("
|
|
186
|
+
import_chalk.default.cyan(" \u2502 ") + import_chalk.default.bold.white("AGENT COMMONS") + import_chalk.default.dim(" // CLI") + import_chalk.default.cyan(` v${version}`) + import_chalk.default.cyan(" \u2502")
|
|
169
187
|
);
|
|
170
|
-
console.log(import_chalk.default.cyan("
|
|
171
|
-
console.log(
|
|
188
|
+
console.log(import_chalk.default.cyan(" \u2570\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256F"));
|
|
189
|
+
console.log(import_chalk.default.dim(" Build \xB7 run \xB7 connect \xB7 collaborate"));
|
|
172
190
|
console.log("");
|
|
173
191
|
}
|
|
174
192
|
function step(n, total, title) {
|
|
@@ -177,7 +195,7 @@ function step(n, total, title) {
|
|
|
177
195
|
${import_chalk.default.cyan.bold(" Step " + n)} ${fraction} ${import_chalk.default.bold(title)}`);
|
|
178
196
|
console.log(import_chalk.default.dim(" " + "\u2500".repeat(38)));
|
|
179
197
|
}
|
|
180
|
-
async function select(
|
|
198
|
+
async function select(prompt, choices) {
|
|
181
199
|
if (!process.stdin.isTTY) {
|
|
182
200
|
return choices[0].value;
|
|
183
201
|
}
|
|
@@ -187,7 +205,7 @@ async function select(prompt2, choices) {
|
|
|
187
205
|
if (!first) {
|
|
188
206
|
process.stdout.write(`\x1B[${total + 2}A\x1B[0J`);
|
|
189
207
|
}
|
|
190
|
-
console.log("\n" + import_chalk.default.bold(" " +
|
|
208
|
+
console.log("\n" + import_chalk.default.bold(" " + prompt));
|
|
191
209
|
for (let i = 0; i < total; i++) {
|
|
192
210
|
const { label, hint } = choices[i];
|
|
193
211
|
if (i === idx) {
|
|
@@ -230,9 +248,14 @@ async function select(prompt2, choices) {
|
|
|
230
248
|
});
|
|
231
249
|
}
|
|
232
250
|
function openBrowser(url) {
|
|
233
|
-
const
|
|
234
|
-
(0, import_child_process.
|
|
251
|
+
const command = process.platform === "darwin" ? { file: "open", args: [url] } : process.platform === "win32" ? { file: "cmd", args: ["/c", "start", "", url] } : { file: "xdg-open", args: [url] };
|
|
252
|
+
const child = (0, import_child_process.spawn)(command.file, command.args, {
|
|
253
|
+
detached: true,
|
|
254
|
+
stdio: "ignore"
|
|
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 ?? cfg.defaultAgentId;
|
|
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,53 @@ ${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
|
+
["Expires", connection.expiresAt ?? c.dim("(not reported)")]
|
|
1245
|
+
]);
|
|
1246
|
+
} catch (err) {
|
|
1247
|
+
spinner.stop();
|
|
1248
|
+
printError(err);
|
|
1249
|
+
process.exit(1);
|
|
1250
|
+
}
|
|
1251
|
+
});
|
|
1252
|
+
cmd.command("refresh <connectionId>").description("Refresh a connected account token").action(async (connectionId) => {
|
|
1253
|
+
const spinner = spin("Refreshing connection\u2026");
|
|
1254
|
+
try {
|
|
1255
|
+
await makeClient().oauth.refresh(connectionId);
|
|
1256
|
+
spinner.stop();
|
|
1257
|
+
console.log(`${sym.ok} Connection refreshed.`);
|
|
1258
|
+
} catch (err) {
|
|
1259
|
+
spinner.stop();
|
|
1260
|
+
printError(err);
|
|
1261
|
+
process.exit(1);
|
|
1262
|
+
}
|
|
1263
|
+
});
|
|
1264
|
+
cmd.command("rename <connectionId> <name>").description("Set a friendly name for a connected account").action(async (connectionId, name) => {
|
|
1265
|
+
const spinner = spin("Updating connection\u2026");
|
|
1266
|
+
try {
|
|
1267
|
+
await makeClient().oauth.updateConnection(connectionId, {
|
|
1268
|
+
displayName: name
|
|
1269
|
+
});
|
|
1270
|
+
spinner.stop();
|
|
1271
|
+
console.log(`${sym.ok} Connection renamed to ${c.bold(name)}.`);
|
|
1272
|
+
} catch (err) {
|
|
1273
|
+
spinner.stop();
|
|
1274
|
+
printError(err);
|
|
1275
|
+
process.exit(1);
|
|
1276
|
+
}
|
|
1277
|
+
});
|
|
1127
1278
|
cmd.command("test <connectionId>").description("Check that a connection is active and its token is valid").option("--json", "Output as JSON").action(async (connectionId, opts) => {
|
|
1128
1279
|
const spinner = spin("Testing connection\u2026");
|
|
1129
1280
|
try {
|
|
@@ -1294,8 +1445,8 @@ ${sym.ok} Workflow created`);
|
|
|
1294
1445
|
}
|
|
1295
1446
|
const templateName = templateNameRaw;
|
|
1296
1447
|
const needsAgent = templateName === "agent-research-summary" || templateName === "multi-agent-field-report";
|
|
1297
|
-
const
|
|
1298
|
-
if (needsAgent && !
|
|
1448
|
+
const agentId2 = opts.agent ?? cfg.defaultAgentId;
|
|
1449
|
+
if (needsAgent && !agentId2) {
|
|
1299
1450
|
console.error(c.error("This template requires --agent <agentId> or a configured defaultAgentId."));
|
|
1300
1451
|
process.exit(1);
|
|
1301
1452
|
}
|
|
@@ -1319,7 +1470,7 @@ ${sym.ok} Workflow created`);
|
|
|
1319
1470
|
const ctx = {
|
|
1320
1471
|
ownerId: cfg.initiator,
|
|
1321
1472
|
prefix,
|
|
1322
|
-
agentId,
|
|
1473
|
+
agentId: agentId2,
|
|
1323
1474
|
reviewerAgentId: opts.reviewerAgent,
|
|
1324
1475
|
childWorkflowId
|
|
1325
1476
|
};
|
|
@@ -1339,7 +1490,7 @@ ${sym.ok} Workflow created`);
|
|
|
1339
1490
|
}
|
|
1340
1491
|
}
|
|
1341
1492
|
execution = await makeClient().workflows.execute(result.workflow.workflowId, {
|
|
1342
|
-
agentId,
|
|
1493
|
+
agentId: agentId2,
|
|
1343
1494
|
inputData,
|
|
1344
1495
|
userId: cfg.initiator
|
|
1345
1496
|
});
|
|
@@ -1410,7 +1561,7 @@ ${sym.ok} Execution started: ${c.id(execution.executionId)}`);
|
|
|
1410
1561
|
});
|
|
1411
1562
|
cmd.command("run <workflowId>").description("Execute a workflow").option("--agent <agentId>", "Agent context").option("--session <sessionId>", "Session context").option("--input <json>", "Input data as JSON string", "{}").option("--watch", "Stream execution progress via SSE").option("--json", "Output result as JSON").action(async (workflowId, opts) => {
|
|
1412
1563
|
const cfg = loadConfig();
|
|
1413
|
-
const
|
|
1564
|
+
const agentId2 = opts.agent ?? cfg.defaultAgentId;
|
|
1414
1565
|
let inputData = {};
|
|
1415
1566
|
try {
|
|
1416
1567
|
inputData = JSON.parse(opts.input);
|
|
@@ -1422,7 +1573,7 @@ ${sym.ok} Execution started: ${c.id(execution.executionId)}`);
|
|
|
1422
1573
|
try {
|
|
1423
1574
|
const client = makeClient();
|
|
1424
1575
|
const execution = await client.workflows.execute(workflowId, {
|
|
1425
|
-
agentId,
|
|
1576
|
+
agentId: agentId2,
|
|
1426
1577
|
sessionId: opts.session,
|
|
1427
1578
|
inputData
|
|
1428
1579
|
});
|
|
@@ -1567,12 +1718,12 @@ function taskCommand() {
|
|
|
1567
1718
|
const cmd = new import_commander7.Command("task").description("Manage and execute tasks").alias("t");
|
|
1568
1719
|
cmd.command("list").description("List tasks").option("--agent <agentId>", "Filter by agent ID").option("--session <sessionId>", "Filter by session ID").option("--json", "Output as JSON").action(async (opts) => {
|
|
1569
1720
|
const cfg = loadConfig();
|
|
1570
|
-
const
|
|
1721
|
+
const agentId2 = opts.agent ?? cfg.defaultAgentId;
|
|
1571
1722
|
const spinner = spin("Fetching tasks\u2026");
|
|
1572
1723
|
try {
|
|
1573
1724
|
const client = makeClient();
|
|
1574
1725
|
const filter = {};
|
|
1575
|
-
if (
|
|
1726
|
+
if (agentId2) filter.agentId = agentId2;
|
|
1576
1727
|
if (opts.session) filter.sessionId = opts.session;
|
|
1577
1728
|
if (cfg.initiator) {
|
|
1578
1729
|
filter.ownerId = cfg.initiator;
|
|
@@ -1628,8 +1779,8 @@ function taskCommand() {
|
|
|
1628
1779
|
});
|
|
1629
1780
|
cmd.command("create").description("Create a new task").requiredOption("--title <title>", "Task title").option("--agent <agentId>", "Agent ID").option("--session <sessionId>", "Session ID").option("--workflow <workflowId>", "Workflow ID to attach").option("--input <json>", "Input data as JSON", "{}").option("--timeout <ms>", "Execution timeout in milliseconds").option("--execute", "Execute immediately after creation").option("--watch", "Stream execution progress (implies --execute)").option("--json", "Output as JSON").action(async (opts) => {
|
|
1630
1781
|
const cfg = loadConfig();
|
|
1631
|
-
const
|
|
1632
|
-
if (!
|
|
1782
|
+
const agentId2 = opts.agent ?? cfg.defaultAgentId;
|
|
1783
|
+
if (!agentId2) {
|
|
1633
1784
|
console.error(c.error("Specify --agent <agentId> or set defaultAgentId with `agc config set defaultAgentId <id>`"));
|
|
1634
1785
|
process.exit(1);
|
|
1635
1786
|
}
|
|
@@ -1645,7 +1796,7 @@ function taskCommand() {
|
|
|
1645
1796
|
const client = makeClient();
|
|
1646
1797
|
const res = await client.tasks.create({
|
|
1647
1798
|
title: opts.title,
|
|
1648
|
-
agentId,
|
|
1799
|
+
agentId: agentId2,
|
|
1649
1800
|
sessionId: opts.session,
|
|
1650
1801
|
workflowId: opts.workflow,
|
|
1651
1802
|
inputData,
|
|
@@ -1750,13 +1901,13 @@ ${sym.fail} ${c.error(event.message ?? event.type)}`);
|
|
|
1750
1901
|
|
|
1751
1902
|
// src/commands/run.ts
|
|
1752
1903
|
var import_commander8 = require("commander");
|
|
1753
|
-
var
|
|
1904
|
+
var readline2 = __toESM(require("readline"));
|
|
1754
1905
|
|
|
1755
1906
|
// src/local-tools.ts
|
|
1756
1907
|
var import_fs5 = require("fs");
|
|
1757
1908
|
var import_path3 = require("path");
|
|
1758
1909
|
var import_child_process2 = require("child_process");
|
|
1759
|
-
var
|
|
1910
|
+
var readline = __toESM(require("readline"));
|
|
1760
1911
|
var pdfParse = require("pdf-parse/lib/pdf-parse.js");
|
|
1761
1912
|
var managedProcesses = /* @__PURE__ */ new Map();
|
|
1762
1913
|
function capBuffer(existing, chunk, maxBytes) {
|
|
@@ -1906,11 +2057,11 @@ function extractToolCall(text) {
|
|
|
1906
2057
|
}
|
|
1907
2058
|
return null;
|
|
1908
2059
|
}
|
|
1909
|
-
function injectAgcTrailer(command, args,
|
|
2060
|
+
function injectAgcTrailer(command, args, agentId2, agentName) {
|
|
1910
2061
|
if (command !== "git") return args;
|
|
1911
2062
|
if (!args.some((a) => a === "commit")) return args;
|
|
1912
2063
|
if (args.some((a) => a.includes("Co-Authored-By: agc"))) return args;
|
|
1913
|
-
const identity = agentName ? `${agentName} (agc)` :
|
|
2064
|
+
const identity = agentName ? `${agentName} (agc)` : agentId2 ? `agc/${agentId2}` : "agc agent";
|
|
1914
2065
|
return [...args, "--trailer", `Co-Authored-By: ${identity} <agc-agent@users.noreply.github.com>`];
|
|
1915
2066
|
}
|
|
1916
2067
|
var AGC_HOOK_MARKER = "# agc-session:";
|
|
@@ -1927,7 +2078,7 @@ function findGitDir(rootDir) {
|
|
|
1927
2078
|
}
|
|
1928
2079
|
return null;
|
|
1929
2080
|
}
|
|
1930
|
-
function installGitHook(rootDir, sessionId,
|
|
2081
|
+
function installGitHook(rootDir, sessionId, agentId2, agentName) {
|
|
1931
2082
|
const gitDir = findGitDir(rootDir);
|
|
1932
2083
|
if (!gitDir) return;
|
|
1933
2084
|
const hooksDir = (0, import_path3.join)(gitDir, "hooks");
|
|
@@ -1939,7 +2090,7 @@ function installGitHook(rootDir, sessionId, agentId, agentName) {
|
|
|
1939
2090
|
(0, import_fs5.writeFileSync)(hookPath + HOOK_BACKUP_SUFFIX, existing, { mode: 493 });
|
|
1940
2091
|
}
|
|
1941
2092
|
}
|
|
1942
|
-
const identity = agentName ? `${agentName} (agc)` :
|
|
2093
|
+
const identity = agentName ? `${agentName} (agc)` : agentId2 ? `agc/${agentId2}` : "agc agent";
|
|
1943
2094
|
const trailer = `Co-Authored-By: ${identity} <agc-agent@users.noreply.github.com>`;
|
|
1944
2095
|
const chainLine = (0, import_fs5.existsSync)(hookPath + HOOK_BACKUP_SUFFIX) ? `
|
|
1945
2096
|
# chain pre-existing hook
|
|
@@ -2003,7 +2154,7 @@ async function confirm(message, config, permissionKey) {
|
|
|
2003
2154
|
if (cached === "allow") return true;
|
|
2004
2155
|
if (cached === "deny") return false;
|
|
2005
2156
|
return new Promise((resolve2) => {
|
|
2006
|
-
const rl =
|
|
2157
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
2007
2158
|
process.stdout.write(
|
|
2008
2159
|
`
|
|
2009
2160
|
\x1B[33m\u26A0\x1B[0m ${message}
|
|
@@ -2382,10 +2533,10 @@ async function runLocalTool(call, cfg) {
|
|
|
2382
2533
|
|
|
2383
2534
|
// src/commands/run.ts
|
|
2384
2535
|
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 (
|
|
2536
|
+
return new import_commander8.Command("run").description("Send a single prompt to an agent and stream the response").argument("<prompt>", "Prompt text to send").option("--agent <agentId>", "Agent ID").option("--session <sessionId>", "Resume an existing session by ID").option("--new-session", "Create a new session and print its ID for future use").option("--computer", "Give the agent access to its persistent cloud computer").option("--local", "Enable local file system access (with permission prompts)").option("-y, --yes", "Enable local file system access and auto-approve all operations").option("--no-stream", "Disable streaming (wait for full response)").option("--json", "Output raw event stream as JSON lines").action(async (prompt, opts) => {
|
|
2386
2537
|
const cfg = loadConfig();
|
|
2387
|
-
const
|
|
2388
|
-
if (!
|
|
2538
|
+
const agentId2 = opts.agent ?? cfg.defaultAgentId;
|
|
2539
|
+
if (!agentId2) {
|
|
2389
2540
|
console.error(c.error("Specify --agent <agentId> or set defaultAgentId with `agc config set defaultAgentId <id>`"));
|
|
2390
2541
|
process.exit(1);
|
|
2391
2542
|
}
|
|
@@ -2410,7 +2561,7 @@ function runCommand() {
|
|
|
2410
2561
|
const spinner = spin("Creating session\u2026");
|
|
2411
2562
|
try {
|
|
2412
2563
|
const res = await client.sessions.create({
|
|
2413
|
-
agentId,
|
|
2564
|
+
agentId: agentId2,
|
|
2414
2565
|
initiator: cfg.initiator ?? "",
|
|
2415
2566
|
title: `agc run ${(/* @__PURE__ */ new Date()).toISOString().slice(0, 16)}`,
|
|
2416
2567
|
source: "cli"
|
|
@@ -2436,7 +2587,7 @@ function runCommand() {
|
|
|
2436
2587
|
appendLog: () => {
|
|
2437
2588
|
},
|
|
2438
2589
|
permissions: /* @__PURE__ */ new Map(),
|
|
2439
|
-
agentId,
|
|
2590
|
+
agentId: agentId2,
|
|
2440
2591
|
autoApprove
|
|
2441
2592
|
};
|
|
2442
2593
|
const snapshot = buildDirSnapshot(rootDir, 2);
|
|
@@ -2460,9 +2611,9 @@ function runCommand() {
|
|
|
2460
2611
|
}
|
|
2461
2612
|
}
|
|
2462
2613
|
const params = {
|
|
2463
|
-
agentId,
|
|
2614
|
+
agentId: agentId2,
|
|
2464
2615
|
sessionId,
|
|
2465
|
-
messages: [{ role: "user", content:
|
|
2616
|
+
messages: [{ role: "user", content: prompt }],
|
|
2466
2617
|
...cfg.initiator && { initiatorId: cfg.initiator },
|
|
2467
2618
|
...opts.computer && { computerRequest: { enabled: true } },
|
|
2468
2619
|
...cliContext && { cliContext }
|
|
@@ -2514,16 +2665,12 @@ Session: ${sessionId} (resume with: agc run --session ${sessionId} "<prompt>")`
|
|
|
2514
2665
|
toolOk = false;
|
|
2515
2666
|
}
|
|
2516
2667
|
const elapsed = ((Date.now() - startMs) / 1e3).toFixed(1);
|
|
2517
|
-
|
|
2518
|
-
|
|
2668
|
+
readline2.cursorTo(process.stdout, 0);
|
|
2669
|
+
readline2.clearLine(process.stdout, 0);
|
|
2519
2670
|
process.stdout.write(` ${c.dim("\u2500")} ${c.bold(displayName)} ${toolOk ? sym.ok : sym.fail} ${c.dim("(" + elapsed + "s)")}
|
|
2520
2671
|
`);
|
|
2521
2672
|
try {
|
|
2522
|
-
await
|
|
2523
|
-
method: "POST",
|
|
2524
|
-
headers: { "Content-Type": "application/json", "Authorization": `Bearer ${cfg.apiKey}` },
|
|
2525
|
-
body: JSON.stringify({ requestId, result })
|
|
2526
|
-
});
|
|
2673
|
+
await client.agents.submitCliToolResult(requestId, result);
|
|
2527
2674
|
} catch {
|
|
2528
2675
|
}
|
|
2529
2676
|
} else if (event.type === "toolStart") {
|
|
@@ -2536,8 +2683,8 @@ Session: ${sessionId} (resume with: agc run --session ${sessionId} "<prompt>")`
|
|
|
2536
2683
|
process.stdout.write(` ${c.dim("\u2500")} ${c.bold(lastToolName)}`);
|
|
2537
2684
|
} else if (event.type === "toolEnd") {
|
|
2538
2685
|
const elapsed = ((Date.now() - toolStartMs) / 1e3).toFixed(1);
|
|
2539
|
-
|
|
2540
|
-
|
|
2686
|
+
readline2.cursorTo(process.stdout, 0);
|
|
2687
|
+
readline2.clearLine(process.stdout, 0);
|
|
2541
2688
|
process.stdout.write(` ${c.dim("\u2500")} ${c.bold(lastToolName)} ${sym.ok} ${c.dim("(" + elapsed + "s)")}
|
|
2542
2689
|
`);
|
|
2543
2690
|
} else if (event.type === "final") {
|
|
@@ -2565,7 +2712,7 @@ ${sym.fail} ${c.error(event.message ?? "Error")}`);
|
|
|
2565
2712
|
|
|
2566
2713
|
// src/commands/chat.ts
|
|
2567
2714
|
var import_commander9 = require("commander");
|
|
2568
|
-
var
|
|
2715
|
+
var readline3 = __toESM(require("readline"));
|
|
2569
2716
|
var import_fs6 = require("fs");
|
|
2570
2717
|
var import_path4 = require("path");
|
|
2571
2718
|
var import_os3 = require("os");
|
|
@@ -2611,9 +2758,17 @@ function chatCommand() {
|
|
|
2611
2758
|
return new import_commander9.Command("chat").description("Start an interactive chat REPL with an agent").option("--agent <agentId>", "Agent ID (or set defaultAgentId in config)").option("--resume <sessionId>", "Resume an existing session by ID").option("--computer", "Give the agent access to its persistent cloud computer").option("--no-stream", "Disable token streaming (wait for full response)").option("--no-local", "Disable local file system access for the agent").action(async (opts) => {
|
|
2612
2759
|
const localEnabled = opts.local !== false;
|
|
2613
2760
|
const cfg = loadConfig();
|
|
2614
|
-
|
|
2615
|
-
if (!
|
|
2616
|
-
|
|
2761
|
+
let agentId2 = opts.agent ?? cfg.defaultAgentId;
|
|
2762
|
+
if (!agentId2 && cfg.initiator) {
|
|
2763
|
+
try {
|
|
2764
|
+
const listed = await makeClient().agents.list(cfg.initiator);
|
|
2765
|
+
const agents = listed?.data ?? listed ?? [];
|
|
2766
|
+
agentId2 = agents.find((agent) => agent.isDefault)?.agentId ?? agents[0]?.agentId;
|
|
2767
|
+
} catch {
|
|
2768
|
+
}
|
|
2769
|
+
}
|
|
2770
|
+
if (!agentId2) {
|
|
2771
|
+
console.error(c.error("No default agent is available. Specify --agent <agentId> or run `agc agents list`."));
|
|
2617
2772
|
process.exit(1);
|
|
2618
2773
|
}
|
|
2619
2774
|
if (!cfg.initiator) {
|
|
@@ -2628,7 +2783,7 @@ function chatCommand() {
|
|
|
2628
2783
|
const spinner = spin("Creating session\u2026");
|
|
2629
2784
|
try {
|
|
2630
2785
|
const res = await client.sessions.create({
|
|
2631
|
-
agentId,
|
|
2786
|
+
agentId: agentId2,
|
|
2632
2787
|
initiator,
|
|
2633
2788
|
title: `agc chat ${(/* @__PURE__ */ new Date()).toISOString().slice(0, 16)}`,
|
|
2634
2789
|
source: "cli"
|
|
@@ -2639,7 +2794,7 @@ function chatCommand() {
|
|
|
2639
2794
|
appendSessionLog(sessionId, {
|
|
2640
2795
|
type: "session_start",
|
|
2641
2796
|
sessionId,
|
|
2642
|
-
agentId,
|
|
2797
|
+
agentId: agentId2,
|
|
2643
2798
|
initiator,
|
|
2644
2799
|
source: "cli",
|
|
2645
2800
|
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
@@ -2654,9 +2809,9 @@ function chatCommand() {
|
|
|
2654
2809
|
try {
|
|
2655
2810
|
const res = await client.sessions.get(sessionId);
|
|
2656
2811
|
const session = res?.data ?? res;
|
|
2657
|
-
if (session.agentId && session.agentId !==
|
|
2812
|
+
if (session.agentId && session.agentId !== agentId2) {
|
|
2658
2813
|
spinner.stop();
|
|
2659
|
-
console.log(c.warn(` Note: session ${sessionId} was created with agent ${session.agentId}, not ${
|
|
2814
|
+
console.log(c.warn(` Note: session ${sessionId} was created with agent ${session.agentId}, not ${agentId2}`));
|
|
2660
2815
|
} else {
|
|
2661
2816
|
spinner.stop();
|
|
2662
2817
|
}
|
|
@@ -2669,10 +2824,10 @@ function chatCommand() {
|
|
|
2669
2824
|
let agentName;
|
|
2670
2825
|
let walletLine = "";
|
|
2671
2826
|
await Promise.allSettled([
|
|
2672
|
-
client.agents.get(
|
|
2827
|
+
client.agents.get(agentId2).then((res) => {
|
|
2673
2828
|
agentName = (res?.data ?? res)?.name;
|
|
2674
2829
|
}),
|
|
2675
|
-
client.wallets.primary(
|
|
2830
|
+
client.wallets.primary(agentId2).then(async (primary) => {
|
|
2676
2831
|
const w = primary?.data ?? primary;
|
|
2677
2832
|
if (w?.id) {
|
|
2678
2833
|
const bal = await client.wallets.balance(w.id).catch(() => null);
|
|
@@ -2686,7 +2841,7 @@ function chatCommand() {
|
|
|
2686
2841
|
console.log(`
|
|
2687
2842
|
${c.bold("Agent Commons Chat")}`);
|
|
2688
2843
|
const headerRows = [
|
|
2689
|
-
["Agent", agentName ? `${agentName} ${c.dim(
|
|
2844
|
+
["Agent", agentName ? `${agentName} ${c.dim(agentId2)}` : agentId2],
|
|
2690
2845
|
["Session", c.id(sessionId) + (isResume ? c.dim(" (resumed)") : c.dim(" (new)"))]
|
|
2691
2846
|
];
|
|
2692
2847
|
if (walletLine) headerRows.push(["Wallet", walletLine]);
|
|
@@ -2700,12 +2855,12 @@ ${c.bold("Agent Commons Chat")}`);
|
|
|
2700
2855
|
localToolsCfg = {
|
|
2701
2856
|
rootDir,
|
|
2702
2857
|
sessionId,
|
|
2703
|
-
agentId,
|
|
2858
|
+
agentId: agentId2,
|
|
2704
2859
|
agentName,
|
|
2705
2860
|
appendLog: (record) => appendSessionLog(sessionId, record),
|
|
2706
2861
|
permissions: /* @__PURE__ */ new Map()
|
|
2707
2862
|
};
|
|
2708
|
-
installGitHook(rootDir, sessionId,
|
|
2863
|
+
installGitHook(rootDir, sessionId, agentId2, agentName);
|
|
2709
2864
|
appendSessionLog(sessionId, {
|
|
2710
2865
|
type: "local_tools_enabled",
|
|
2711
2866
|
rootDir,
|
|
@@ -2713,7 +2868,7 @@ ${c.bold("Agent Commons Chat")}`);
|
|
|
2713
2868
|
});
|
|
2714
2869
|
}
|
|
2715
2870
|
console.log(c.dim("\nType your message and press Enter. Type /help for commands.\n"));
|
|
2716
|
-
const rl =
|
|
2871
|
+
const rl = readline3.createInterface({
|
|
2717
2872
|
input: process.stdin,
|
|
2718
2873
|
output: process.stdout,
|
|
2719
2874
|
terminal: true,
|
|
@@ -2797,7 +2952,7 @@ ${content}
|
|
|
2797
2952
|
cliContext = buildLocalToolsManifest(rootDir, snapshot, fileContextBlocks);
|
|
2798
2953
|
}
|
|
2799
2954
|
const params = {
|
|
2800
|
-
agentId,
|
|
2955
|
+
agentId: agentId2,
|
|
2801
2956
|
sessionId,
|
|
2802
2957
|
messages: [{ role: "user", content: userMessage }],
|
|
2803
2958
|
...opts.computer && { computerRequest: { enabled: true } },
|
|
@@ -2857,7 +3012,7 @@ ${sym.fail} ${c.error(err.message ?? String(err))}`);
|
|
|
2857
3012
|
if (isWaiting) {
|
|
2858
3013
|
elapsedInterval = setInterval(() => {
|
|
2859
3014
|
elapsedSec++;
|
|
2860
|
-
|
|
3015
|
+
readline3.cursorTo(process.stdout, 0);
|
|
2861
3016
|
process.stdout.write(` ${c.dim("\u2500")} ${c.bold(displayName)}${argStr ? " " + c.dim(argStr) : ""} ${c.dim(elapsedSec + "s\u2026")}`);
|
|
2862
3017
|
}, 1e3);
|
|
2863
3018
|
}
|
|
@@ -2872,12 +3027,14 @@ ${sym.fail} ${c.error(err.message ?? String(err))}`);
|
|
|
2872
3027
|
if (elapsedInterval) clearInterval(elapsedInterval);
|
|
2873
3028
|
const elapsed = ((Date.now() - startMs) / 1e3).toFixed(1);
|
|
2874
3029
|
const preview = toolOk ? toolResultPreview(displayName, result) : "";
|
|
2875
|
-
|
|
2876
|
-
|
|
3030
|
+
readline3.cursorTo(process.stdout, 0);
|
|
3031
|
+
readline3.clearLine(process.stdout, 0);
|
|
2877
3032
|
const statusIcon = toolOk ? sym.ok : sym.fail;
|
|
2878
3033
|
const previewPart = preview ? ` ${c.dim(preview)}` : "";
|
|
2879
|
-
process.stdout.write(
|
|
2880
|
-
`)
|
|
3034
|
+
process.stdout.write(
|
|
3035
|
+
` ${c.dim("\u2500")} ${c.bold(displayName)}${argStr ? " " + c.dim(argStr) : ""} ${statusIcon}${previewPart} ${c.dim("(" + elapsed + "s)")}
|
|
3036
|
+
`
|
|
3037
|
+
);
|
|
2881
3038
|
appendSessionLog(sessionId, {
|
|
2882
3039
|
type: "local_tool_result",
|
|
2883
3040
|
tool: toolName,
|
|
@@ -2885,14 +3042,7 @@ ${sym.fail} ${c.error(err.message ?? String(err))}`);
|
|
|
2885
3042
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
2886
3043
|
});
|
|
2887
3044
|
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
|
-
});
|
|
3045
|
+
await client.agents.submitCliToolResult(requestId, result);
|
|
2896
3046
|
} catch (postErr) {
|
|
2897
3047
|
console.error(c.warn(`
|
|
2898
3048
|
[local] Failed to submit tool result: ${postErr?.message}`));
|
|
@@ -2907,8 +3057,8 @@ ${sym.fail} ${c.error(err.message ?? String(err))}`);
|
|
|
2907
3057
|
hasOutput = false;
|
|
2908
3058
|
} else if (event.type === "toolEnd") {
|
|
2909
3059
|
const elapsed = ((Date.now() - toolStartMs) / 1e3).toFixed(1);
|
|
2910
|
-
|
|
2911
|
-
|
|
3060
|
+
readline3.cursorTo(process.stdout, 0);
|
|
3061
|
+
readline3.clearLine(process.stdout, 0);
|
|
2912
3062
|
process.stdout.write(` ${c.dim("\u2500")} ${c.bold(lastToolName)} ${sym.ok} ${c.dim("(" + elapsed + "s)")}
|
|
2913
3063
|
`);
|
|
2914
3064
|
process.stdout.write(c.primary("agent") + c.dim(" \u203A "));
|
|
@@ -2934,7 +3084,13 @@ ${sym.fail} ${c.error(err.message ?? String(err))}`);
|
|
|
2934
3084
|
type: "message",
|
|
2935
3085
|
role: "assistant",
|
|
2936
3086
|
content: agentContent,
|
|
2937
|
-
usage: {
|
|
3087
|
+
usage: {
|
|
3088
|
+
inputTokens: inputTok,
|
|
3089
|
+
outputTokens: outputTok,
|
|
3090
|
+
cachedTokens: cachedTok,
|
|
3091
|
+
totalTokens: total,
|
|
3092
|
+
costUsd: usage.costUsd
|
|
3093
|
+
},
|
|
2938
3094
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
2939
3095
|
});
|
|
2940
3096
|
} else {
|
|
@@ -2957,15 +3113,7 @@ ${sym.fail} ${c.error(event.message ?? "Stream error")}`);
|
|
|
2957
3113
|
if (thinkingSpinner.isSpinning) thinkingSpinner.stop();
|
|
2958
3114
|
process.stdout.write("\n");
|
|
2959
3115
|
if (localToolsCfg && agentContent) {
|
|
2960
|
-
await handleLocalToolLoop(
|
|
2961
|
-
agentContent,
|
|
2962
|
-
localToolsCfg,
|
|
2963
|
-
client,
|
|
2964
|
-
agentId,
|
|
2965
|
-
sessionId,
|
|
2966
|
-
appendSessionLog,
|
|
2967
|
-
!!opts.computer
|
|
2968
|
-
);
|
|
3116
|
+
await handleLocalToolLoop(agentContent, localToolsCfg, client, agentId2, sessionId, appendSessionLog, !!opts.computer);
|
|
2969
3117
|
}
|
|
2970
3118
|
} catch (err) {
|
|
2971
3119
|
process.stdout.write("\n");
|
|
@@ -2973,8 +3121,8 @@ ${sym.fail} ${c.error(event.message ?? "Stream error")}`);
|
|
|
2973
3121
|
}
|
|
2974
3122
|
}
|
|
2975
3123
|
console.log();
|
|
2976
|
-
|
|
2977
|
-
|
|
3124
|
+
readline3.cursorTo(process.stdout, 0);
|
|
3125
|
+
readline3.clearLine(process.stdout, 0);
|
|
2978
3126
|
rl.resume();
|
|
2979
3127
|
rl.prompt();
|
|
2980
3128
|
});
|
|
@@ -2994,7 +3142,7 @@ Session preserved. Resume with: agc chat --resume ${sessionId}`));
|
|
|
2994
3142
|
});
|
|
2995
3143
|
}
|
|
2996
3144
|
var MAX_TOOL_DEPTH = 10;
|
|
2997
|
-
async function handleLocalToolLoop(agentText, cfg, client,
|
|
3145
|
+
async function handleLocalToolLoop(agentText, cfg, client, agentId2, sessionId, appendLog, computerEnabled = false, depth = 0) {
|
|
2998
3146
|
if (depth >= MAX_TOOL_DEPTH) {
|
|
2999
3147
|
console.log(c.dim(`
|
|
3000
3148
|
[local] Max tool depth reached (${MAX_TOOL_DEPTH}). Stopping tool loop.
|
|
@@ -3017,11 +3165,13 @@ async function handleLocalToolLoop(agentText, cfg, client, agentId, sessionId, a
|
|
|
3017
3165
|
}
|
|
3018
3166
|
const elapsed = ((Date.now() - startMs) / 1e3).toFixed(1);
|
|
3019
3167
|
const preview = toolOk ? toolResultPreview(toolCall.tool, result) : "";
|
|
3020
|
-
|
|
3021
|
-
|
|
3168
|
+
readline3.cursorTo(process.stdout, 0);
|
|
3169
|
+
readline3.clearLine(process.stdout, 0);
|
|
3022
3170
|
const previewPart = preview ? ` ${c.dim(preview)}` : "";
|
|
3023
|
-
process.stdout.write(
|
|
3024
|
-
`)
|
|
3171
|
+
process.stdout.write(
|
|
3172
|
+
` ${c.dim("\u2500")} ${c.bold(toolCall.tool)}${argStr ? " " + c.dim(argStr) : ""} ${toolOk ? sym.ok : sym.fail}${previewPart} ${c.dim("(" + elapsed + "s)")}
|
|
3173
|
+
`
|
|
3174
|
+
);
|
|
3025
3175
|
const resultMsg = `[Tool result: ${toolCall.tool}]
|
|
3026
3176
|
\`\`\`
|
|
3027
3177
|
${result}
|
|
@@ -3039,7 +3189,7 @@ ${result}
|
|
|
3039
3189
|
let loopToolName = "";
|
|
3040
3190
|
let loopToolStartMs = 0;
|
|
3041
3191
|
for await (const evt of client.agents.stream({
|
|
3042
|
-
agentId,
|
|
3192
|
+
agentId: agentId2,
|
|
3043
3193
|
sessionId,
|
|
3044
3194
|
messages: [{ role: "user", content: resultMsg }],
|
|
3045
3195
|
...computerEnabled && { computerRequest: { enabled: true } }
|
|
@@ -3055,8 +3205,8 @@ ${result}
|
|
|
3055
3205
|
process.stdout.write(` ${c.dim("\u2500")} ${c.bold(loopToolName)}`);
|
|
3056
3206
|
} else if (evt.type === "toolEnd") {
|
|
3057
3207
|
const elapsed2 = ((Date.now() - loopToolStartMs) / 1e3).toFixed(1);
|
|
3058
|
-
|
|
3059
|
-
|
|
3208
|
+
readline3.cursorTo(process.stdout, 0);
|
|
3209
|
+
readline3.clearLine(process.stdout, 0);
|
|
3060
3210
|
process.stdout.write(` ${c.dim("\u2500")} ${c.bold(loopToolName)} ${sym.ok} ${c.dim("(" + elapsed2 + "s)")}
|
|
3061
3211
|
`);
|
|
3062
3212
|
process.stdout.write(c.primary("agent") + c.dim(" \u203A "));
|
|
@@ -3066,7 +3216,12 @@ ${result}
|
|
|
3066
3216
|
process.stdout.write(txt);
|
|
3067
3217
|
followContent += txt;
|
|
3068
3218
|
}
|
|
3069
|
-
appendLog(sessionId, {
|
|
3219
|
+
appendLog(sessionId, {
|
|
3220
|
+
type: "message",
|
|
3221
|
+
role: "assistant",
|
|
3222
|
+
content: followContent,
|
|
3223
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
3224
|
+
});
|
|
3070
3225
|
break;
|
|
3071
3226
|
} else if (evt.type === "error") {
|
|
3072
3227
|
console.error(`
|
|
@@ -3080,16 +3235,7 @@ ${sym.fail} ${c.error(evt.message ?? "Stream error")}`);
|
|
|
3080
3235
|
console.error(`${sym.fail} ${c.error(err?.message ?? String(err))}`);
|
|
3081
3236
|
return;
|
|
3082
3237
|
}
|
|
3083
|
-
await handleLocalToolLoop(
|
|
3084
|
-
followContent,
|
|
3085
|
-
cfg,
|
|
3086
|
-
client,
|
|
3087
|
-
agentId,
|
|
3088
|
-
sessionId,
|
|
3089
|
-
appendLog,
|
|
3090
|
-
computerEnabled,
|
|
3091
|
-
depth + 1
|
|
3092
|
-
);
|
|
3238
|
+
await handleLocalToolLoop(followContent, cfg, client, agentId2, sessionId, appendLog, computerEnabled, depth + 1);
|
|
3093
3239
|
}
|
|
3094
3240
|
function truncate(s, max) {
|
|
3095
3241
|
const str = String(s ?? "");
|
|
@@ -3703,8 +3849,8 @@ function skillsCommand() {
|
|
|
3703
3849
|
});
|
|
3704
3850
|
cmd.command("delete <slug>").description("Permanently delete a skill").option("--yes", "Skip confirmation prompt").option("--json", "Output result as JSON").action(async (slug, opts) => {
|
|
3705
3851
|
if (!opts.yes) {
|
|
3706
|
-
const
|
|
3707
|
-
const rl =
|
|
3852
|
+
const readline4 = await import("readline");
|
|
3853
|
+
const rl = readline4.createInterface({ input: process.stdin, output: process.stdout });
|
|
3708
3854
|
const answer = await new Promise(
|
|
3709
3855
|
(resolve2) => rl.question(c.warn(`Delete skill "${slug}"? This cannot be undone. [y/N] `), resolve2)
|
|
3710
3856
|
);
|
|
@@ -3736,19 +3882,19 @@ function walletCommand() {
|
|
|
3736
3882
|
const cmd = new import_commander12.Command("wallet").description("Manage agent wallets");
|
|
3737
3883
|
cmd.command("list").description("List all wallets for an agent").option("--agent <agentId>", "Agent ID (or use defaultAgentId from config)").option("--json", "Output as JSON").action(async (opts) => {
|
|
3738
3884
|
const cfg = loadConfig();
|
|
3739
|
-
const
|
|
3740
|
-
if (!
|
|
3885
|
+
const agentId2 = opts.agent ?? cfg.defaultAgentId;
|
|
3886
|
+
if (!agentId2) {
|
|
3741
3887
|
console.error(c.error("Specify --agent <agentId> or set defaultAgentId with `agc config set defaultAgentId <id>`"));
|
|
3742
3888
|
process.exit(1);
|
|
3743
3889
|
}
|
|
3744
3890
|
const spinner = spin("Fetching wallets\u2026");
|
|
3745
3891
|
try {
|
|
3746
3892
|
const client = makeClient();
|
|
3747
|
-
const wallets = await client.wallets.list(
|
|
3893
|
+
const wallets = await client.wallets.list(agentId2);
|
|
3748
3894
|
spinner.stop();
|
|
3749
3895
|
if (opts.json) return jsonOut(wallets);
|
|
3750
3896
|
const list = wallets?.data ?? wallets ?? [];
|
|
3751
|
-
section(`Wallets for agent ${
|
|
3897
|
+
section(`Wallets for agent ${agentId2.slice(0, 8)}\u2026 (${list.length})`);
|
|
3752
3898
|
table(
|
|
3753
3899
|
list.map((w) => ({
|
|
3754
3900
|
ID: w.id.slice(0, 8) + "\u2026",
|
|
@@ -3768,19 +3914,19 @@ function walletCommand() {
|
|
|
3768
3914
|
});
|
|
3769
3915
|
cmd.command("show").description("Show the agent's primary wallet address").option("--agent <agentId>", "Agent ID (or use defaultAgentId from config)").option("--json", "Output as JSON").action(async (opts) => {
|
|
3770
3916
|
const cfg = loadConfig();
|
|
3771
|
-
const
|
|
3772
|
-
if (!
|
|
3917
|
+
const agentId2 = opts.agent ?? cfg.defaultAgentId;
|
|
3918
|
+
if (!agentId2) {
|
|
3773
3919
|
console.error(c.error("Specify --agent <agentId> or set defaultAgentId with `agc config set defaultAgentId <id>`"));
|
|
3774
3920
|
process.exit(1);
|
|
3775
3921
|
}
|
|
3776
3922
|
const spinner = spin("Fetching primary wallet\u2026");
|
|
3777
3923
|
try {
|
|
3778
3924
|
const client = makeClient();
|
|
3779
|
-
const wallet = await client.wallets.primary(
|
|
3925
|
+
const wallet = await client.wallets.primary(agentId2);
|
|
3780
3926
|
spinner.stop();
|
|
3781
3927
|
if (!wallet) {
|
|
3782
|
-
console.log(c.warn(` No wallet found for agent ${
|
|
3783
|
-
console.log(c.dim(` Run: agc wallet create --agent ${
|
|
3928
|
+
console.log(c.warn(` No wallet found for agent ${agentId2}`));
|
|
3929
|
+
console.log(c.dim(` Run: agc wallet create --agent ${agentId2}`));
|
|
3784
3930
|
return;
|
|
3785
3931
|
}
|
|
3786
3932
|
const w = wallet?.data ?? wallet;
|
|
@@ -3801,8 +3947,8 @@ function walletCommand() {
|
|
|
3801
3947
|
});
|
|
3802
3948
|
cmd.command("balance").description("Show the agent's wallet USDC and ETH balance").option("--agent <agentId>", "Agent ID (or use defaultAgentId from config)").option("--wallet <walletId>", "Specific wallet ID (defaults to primary)").option("--json", "Output as JSON").action(async (opts) => {
|
|
3803
3949
|
const cfg = loadConfig();
|
|
3804
|
-
const
|
|
3805
|
-
if (!
|
|
3950
|
+
const agentId2 = opts.agent ?? cfg.defaultAgentId;
|
|
3951
|
+
if (!agentId2) {
|
|
3806
3952
|
console.error(c.error("Specify --agent <agentId> or set defaultAgentId with `agc config set defaultAgentId <id>`"));
|
|
3807
3953
|
process.exit(1);
|
|
3808
3954
|
}
|
|
@@ -3811,11 +3957,11 @@ function walletCommand() {
|
|
|
3811
3957
|
const client = makeClient();
|
|
3812
3958
|
let walletId = opts.wallet;
|
|
3813
3959
|
if (!walletId) {
|
|
3814
|
-
const primary = await client.wallets.primary(
|
|
3960
|
+
const primary = await client.wallets.primary(agentId2);
|
|
3815
3961
|
const w = primary?.data ?? primary;
|
|
3816
3962
|
if (!w) {
|
|
3817
3963
|
spinner.stop();
|
|
3818
|
-
console.log(c.warn(` No wallet found. Run: agc wallet create --agent ${
|
|
3964
|
+
console.log(c.warn(` No wallet found. Run: agc wallet create --agent ${agentId2}`));
|
|
3819
3965
|
return;
|
|
3820
3966
|
}
|
|
3821
3967
|
walletId = w.id;
|
|
@@ -3842,8 +3988,8 @@ function walletCommand() {
|
|
|
3842
3988
|
});
|
|
3843
3989
|
cmd.command("create").description("Create a new wallet for an agent").option("--agent <agentId>", "Agent ID (or use defaultAgentId from config)").option("--type <type>", "Wallet type: eoa | external (default: eoa)", "eoa").option("--label <label>", "Wallet label (default: Primary)", "Primary").option("--address <address>", "For --type external: owner-provided address").option("--json", "Output as JSON").action(async (opts) => {
|
|
3844
3990
|
const cfg = loadConfig();
|
|
3845
|
-
const
|
|
3846
|
-
if (!
|
|
3991
|
+
const agentId2 = opts.agent ?? cfg.defaultAgentId;
|
|
3992
|
+
if (!agentId2) {
|
|
3847
3993
|
console.error(c.error("Specify --agent <agentId> or set defaultAgentId with `agc config set defaultAgentId <id>`"));
|
|
3848
3994
|
process.exit(1);
|
|
3849
3995
|
}
|
|
@@ -3855,7 +4001,7 @@ function walletCommand() {
|
|
|
3855
4001
|
try {
|
|
3856
4002
|
const client = makeClient();
|
|
3857
4003
|
const wallet = await client.wallets.create({
|
|
3858
|
-
agentId,
|
|
4004
|
+
agentId: agentId2,
|
|
3859
4005
|
walletType: opts.type,
|
|
3860
4006
|
label: opts.label,
|
|
3861
4007
|
externalAddress: opts.address
|
|
@@ -4013,22 +4159,22 @@ function memoryCommand() {
|
|
|
4013
4159
|
const cmd = new import_commander14.Command("memory").description("View and manage agent memories");
|
|
4014
4160
|
cmd.command("list").description("List memories for an agent").option("--agent <agentId>", "Agent ID (defaults to configured agent)").option("--type <type>", "Filter by type: episodic | semantic | procedural").option("--limit <n>", "Max results", "50").option("--json", "Output as JSON").action(async (opts) => {
|
|
4015
4161
|
const cfg = loadConfig();
|
|
4016
|
-
const
|
|
4017
|
-
if (!
|
|
4162
|
+
const agentId2 = opts.agent ?? cfg.defaultAgentId;
|
|
4163
|
+
if (!agentId2) {
|
|
4018
4164
|
console.error(c.error("Specify --agent <agentId> or set defaultAgentId"));
|
|
4019
4165
|
process.exit(1);
|
|
4020
4166
|
}
|
|
4021
4167
|
const spinner = spin("Fetching memories\u2026");
|
|
4022
4168
|
try {
|
|
4023
4169
|
const client = makeClient();
|
|
4024
|
-
const res = await client.memory.list(
|
|
4170
|
+
const res = await client.memory.list(agentId2, {
|
|
4025
4171
|
type: opts.type,
|
|
4026
4172
|
limit: parseInt(opts.limit, 10)
|
|
4027
4173
|
});
|
|
4028
4174
|
const memories = res?.data ?? res ?? [];
|
|
4029
4175
|
spinner.stop();
|
|
4030
4176
|
if (opts.json) return jsonOut(memories);
|
|
4031
|
-
section(`Memories for ${
|
|
4177
|
+
section(`Memories for ${agentId2.slice(0, 12)}\u2026 (${memories.length})`);
|
|
4032
4178
|
if (memories.length === 0) {
|
|
4033
4179
|
console.log(c.dim(" No memories yet"));
|
|
4034
4180
|
return;
|
|
@@ -4050,15 +4196,15 @@ function memoryCommand() {
|
|
|
4050
4196
|
});
|
|
4051
4197
|
cmd.command("stats").description("Show memory statistics for an agent").option("--agent <agentId>", "Agent ID").option("--json", "Output as JSON").action(async (opts) => {
|
|
4052
4198
|
const cfg = loadConfig();
|
|
4053
|
-
const
|
|
4054
|
-
if (!
|
|
4199
|
+
const agentId2 = opts.agent ?? cfg.defaultAgentId;
|
|
4200
|
+
if (!agentId2) {
|
|
4055
4201
|
console.error(c.error("Specify --agent <agentId>"));
|
|
4056
4202
|
process.exit(1);
|
|
4057
4203
|
}
|
|
4058
4204
|
const spinner = spin("Fetching stats\u2026");
|
|
4059
4205
|
try {
|
|
4060
4206
|
const client = makeClient();
|
|
4061
|
-
const res = await client.memory.stats(
|
|
4207
|
+
const res = await client.memory.stats(agentId2);
|
|
4062
4208
|
const stats = res?.data ?? res;
|
|
4063
4209
|
spinner.stop();
|
|
4064
4210
|
if (opts.json) return jsonOut(stats);
|
|
@@ -4118,15 +4264,15 @@ ${sym.ok} Memory ${c.id(memoryId)} deleted`);
|
|
|
4118
4264
|
});
|
|
4119
4265
|
cmd.command("search <query>").description("Semantic search over agent memories").option("--agent <agentId>", "Agent ID").option("--limit <n>", "Max results", "10").option("--json", "Output as JSON").action(async (query, opts) => {
|
|
4120
4266
|
const cfg = loadConfig();
|
|
4121
|
-
const
|
|
4122
|
-
if (!
|
|
4267
|
+
const agentId2 = opts.agent ?? cfg.defaultAgentId;
|
|
4268
|
+
if (!agentId2) {
|
|
4123
4269
|
console.error(c.error("Specify --agent <agentId>"));
|
|
4124
4270
|
process.exit(1);
|
|
4125
4271
|
}
|
|
4126
4272
|
const spinner = spin("Searching memories\u2026");
|
|
4127
4273
|
try {
|
|
4128
4274
|
const client = makeClient();
|
|
4129
|
-
const res = await client.memory.retrieve(
|
|
4275
|
+
const res = await client.memory.retrieve(agentId2, query, parseInt(opts.limit, 10));
|
|
4130
4276
|
const memories = res?.data ?? res ?? [];
|
|
4131
4277
|
spinner.stop();
|
|
4132
4278
|
if (opts.json) return jsonOut(memories);
|
|
@@ -4215,18 +4361,18 @@ function usageCommand() {
|
|
|
4215
4361
|
process.exit(1);
|
|
4216
4362
|
}
|
|
4217
4363
|
});
|
|
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 (
|
|
4364
|
+
cmd.command("agent <agentId>").description("Show detailed usage for a specific agent").option("--from <date>", "Start date (ISO)").option("--to <date>", "End date (ISO)").option("--json", "Output as JSON").action(async (agentId2, opts) => {
|
|
4219
4365
|
const spinner = spin("Fetching usage\u2026");
|
|
4220
4366
|
try {
|
|
4221
4367
|
const client = makeClient();
|
|
4222
|
-
const res = await client.usage.getAgentUsage(
|
|
4368
|
+
const res = await client.usage.getAgentUsage(agentId2, {
|
|
4223
4369
|
from: opts.from,
|
|
4224
4370
|
to: opts.to
|
|
4225
4371
|
});
|
|
4226
4372
|
const data = res?.data ?? res;
|
|
4227
4373
|
spinner.stop();
|
|
4228
4374
|
if (opts.json) return jsonOut(data);
|
|
4229
|
-
section(`Usage \u2014 ${
|
|
4375
|
+
section(`Usage \u2014 ${agentId2.slice(0, 12)}\u2026`);
|
|
4230
4376
|
detail([
|
|
4231
4377
|
["Calls", (data.callCount ?? 0).toLocaleString()],
|
|
4232
4378
|
["Input tokens", (data.totalInputTokens ?? 0).toLocaleString()],
|
|
@@ -4243,36 +4389,143 @@ function usageCommand() {
|
|
|
4243
4389
|
return cmd;
|
|
4244
4390
|
}
|
|
4245
4391
|
|
|
4246
|
-
// src/commands/
|
|
4392
|
+
// src/commands/billing.ts
|
|
4247
4393
|
var import_commander16 = require("commander");
|
|
4248
|
-
|
|
4249
|
-
|
|
4250
|
-
|
|
4251
|
-
|
|
4252
|
-
|
|
4253
|
-
|
|
4254
|
-
|
|
4255
|
-
|
|
4256
|
-
|
|
4257
|
-
|
|
4258
|
-
|
|
4259
|
-
|
|
4260
|
-
|
|
4261
|
-
|
|
4262
|
-
|
|
4263
|
-
|
|
4394
|
+
function creditsCommand() {
|
|
4395
|
+
const cmd = new import_commander16.Command("credits").description("View your credit balance and ledger");
|
|
4396
|
+
cmd.command("balance", { isDefault: true }).description("Show your current credit balance").option("--json", "Output as JSON").action(async (opts) => {
|
|
4397
|
+
const spinner = spin("Fetching balance\u2026");
|
|
4398
|
+
try {
|
|
4399
|
+
const client = makeClient();
|
|
4400
|
+
const res = await client.credits.balance();
|
|
4401
|
+
spinner.stop();
|
|
4402
|
+
if (opts.json) return jsonOut(res.data);
|
|
4403
|
+
section("Credits");
|
|
4404
|
+
detail([["Balance", String(res?.data?.balance ?? 0)]]);
|
|
4405
|
+
} catch (e) {
|
|
4406
|
+
spinner.stop();
|
|
4407
|
+
console.error(c.error(e.message));
|
|
4408
|
+
process.exit(1);
|
|
4409
|
+
}
|
|
4410
|
+
});
|
|
4411
|
+
cmd.command("ledger").description("Show recent credit ledger entries").option("--limit <n>", "Max entries", "20").option("--json", "Output as JSON").action(async (opts) => {
|
|
4412
|
+
const spinner = spin("Fetching ledger\u2026");
|
|
4413
|
+
try {
|
|
4414
|
+
const client = makeClient();
|
|
4415
|
+
const res = await client.credits.ledger({ limit: Number(opts.limit) });
|
|
4416
|
+
spinner.stop();
|
|
4417
|
+
const rows = res?.data ?? [];
|
|
4418
|
+
if (opts.json) return jsonOut(rows);
|
|
4419
|
+
section("Credit ledger");
|
|
4420
|
+
for (const e of rows) {
|
|
4421
|
+
const sign = e.amount >= 0 ? "+" : "";
|
|
4422
|
+
console.log(
|
|
4423
|
+
`${c.dim(new Date(e.createdAt).toLocaleString())} ${sign}${e.amount} ${e.description || e.eventType}`
|
|
4424
|
+
);
|
|
4425
|
+
}
|
|
4426
|
+
if (!rows.length) console.log(c.dim("No entries."));
|
|
4427
|
+
} catch (e) {
|
|
4428
|
+
spinner.stop();
|
|
4429
|
+
console.error(c.error(e.message));
|
|
4430
|
+
process.exit(1);
|
|
4431
|
+
}
|
|
4432
|
+
});
|
|
4433
|
+
return cmd;
|
|
4434
|
+
}
|
|
4435
|
+
function billingCommand() {
|
|
4436
|
+
const cmd = new import_commander16.Command("billing").description("Manage your subscription and top-ups");
|
|
4437
|
+
cmd.command("status", { isDefault: true }).description("Show your current plan and entitlements").option("--json", "Output as JSON").action(async (opts) => {
|
|
4438
|
+
const spinner = spin("Fetching plan\u2026");
|
|
4439
|
+
try {
|
|
4440
|
+
const client = makeClient();
|
|
4441
|
+
const res = await client.billing.subscription();
|
|
4442
|
+
spinner.stop();
|
|
4443
|
+
if (opts.json) return jsonOut(res.data);
|
|
4444
|
+
const d = res.data;
|
|
4445
|
+
section("Subscription");
|
|
4446
|
+
detail([
|
|
4447
|
+
["Plan", `${d.planName} (${d.planKey})`],
|
|
4448
|
+
["Status", d.status],
|
|
4449
|
+
["Monthly credits", String(d.monthlyCredits)],
|
|
4450
|
+
["Computer use", d.entitlements?.computerUse ? "yes" : "no"],
|
|
4451
|
+
[
|
|
4452
|
+
"Renews",
|
|
4453
|
+
d.currentPeriodEnd ? new Date(d.currentPeriodEnd).toLocaleDateString() : void 0
|
|
4454
|
+
]
|
|
4455
|
+
]);
|
|
4456
|
+
} catch (e) {
|
|
4457
|
+
spinner.stop();
|
|
4458
|
+
console.error(c.error(e.message));
|
|
4459
|
+
process.exit(1);
|
|
4460
|
+
}
|
|
4461
|
+
});
|
|
4462
|
+
cmd.command("upgrade <plan>").description("Start a checkout to upgrade (plus | pro | max)").action(async (plan) => {
|
|
4463
|
+
try {
|
|
4464
|
+
const client = makeClient();
|
|
4465
|
+
const res = await client.billing.subscribe(plan);
|
|
4466
|
+
const url = res?.data?.url;
|
|
4467
|
+
if (!url) {
|
|
4468
|
+
console.error(c.error("Could not create checkout session"));
|
|
4469
|
+
process.exit(1);
|
|
4470
|
+
}
|
|
4471
|
+
console.log(c.dim("Opening checkout in your browser:"));
|
|
4472
|
+
console.log(url);
|
|
4473
|
+
await openBrowser(url);
|
|
4474
|
+
} catch (e) {
|
|
4475
|
+
console.error(c.error(e.message));
|
|
4476
|
+
process.exit(1);
|
|
4477
|
+
}
|
|
4478
|
+
});
|
|
4479
|
+
cmd.command("topup <pack>").description("Buy a one-time credit pack (small | medium | large)").action(async (pack) => {
|
|
4480
|
+
try {
|
|
4481
|
+
const client = makeClient();
|
|
4482
|
+
const res = await client.billing.topup(pack);
|
|
4483
|
+
const url = res?.data?.url;
|
|
4484
|
+
if (!url) {
|
|
4485
|
+
console.error(c.error("Could not create checkout session"));
|
|
4486
|
+
process.exit(1);
|
|
4487
|
+
}
|
|
4488
|
+
console.log(url);
|
|
4489
|
+
await openBrowser(url);
|
|
4490
|
+
} catch (e) {
|
|
4491
|
+
console.error(c.error(e.message));
|
|
4492
|
+
process.exit(1);
|
|
4493
|
+
}
|
|
4494
|
+
});
|
|
4495
|
+
return cmd;
|
|
4496
|
+
}
|
|
4497
|
+
|
|
4498
|
+
// src/commands/logs.ts
|
|
4499
|
+
var import_commander17 = require("commander");
|
|
4500
|
+
var STATUS_COLOR = {
|
|
4501
|
+
success: (s) => c.bold(s),
|
|
4502
|
+
error: (s) => c.error(s),
|
|
4503
|
+
warning: (s) => c.warn(s)
|
|
4504
|
+
};
|
|
4505
|
+
function colorStatus(status) {
|
|
4506
|
+
return (STATUS_COLOR[status] ?? c.dim)(status);
|
|
4507
|
+
}
|
|
4508
|
+
function logsCommand() {
|
|
4509
|
+
const cmd = new import_commander17.Command("logs").description("View agent activity logs");
|
|
4510
|
+
cmd.command("list").alias("ls").description("List recent log entries for an agent").option("--agent <agentId>", "Agent ID (defaults to configured agent)").option("--session <sessionId>", "Filter by session ID").option("--status <status>", "Filter: success | error | warning").option("--limit <n>", "Max entries to show", "50").option("--json", "Output as JSON").action(async (opts) => {
|
|
4511
|
+
const cfg = loadConfig();
|
|
4512
|
+
const agentId2 = opts.agent ?? cfg.defaultAgentId;
|
|
4513
|
+
if (!agentId2) {
|
|
4514
|
+
console.error(c.error("Specify --agent <agentId> or set defaultAgentId"));
|
|
4515
|
+
process.exit(1);
|
|
4264
4516
|
}
|
|
4265
4517
|
const spinner = spin("Fetching logs\u2026");
|
|
4266
4518
|
try {
|
|
4267
4519
|
const client = makeClient();
|
|
4268
|
-
const
|
|
4269
|
-
|
|
4270
|
-
|
|
4520
|
+
const res = await client.logs.list(agentId2, {
|
|
4521
|
+
limit: Number(opts.limit),
|
|
4522
|
+
sessionId: opts.session
|
|
4523
|
+
});
|
|
4271
4524
|
let logs = res?.data ?? res ?? [];
|
|
4272
4525
|
if (opts.status) logs = logs.filter((l) => l.status === opts.status);
|
|
4273
4526
|
spinner.stop();
|
|
4274
4527
|
if (opts.json) return jsonOut(logs);
|
|
4275
|
-
section(`Logs \u2014 ${
|
|
4528
|
+
section(`Logs \u2014 ${agentId2.slice(0, 12)}\u2026 (${logs.length})`);
|
|
4276
4529
|
if (logs.length === 0) {
|
|
4277
4530
|
console.log(c.dim(" No logs yet"));
|
|
4278
4531
|
return;
|
|
@@ -4290,26 +4543,28 @@ function logsCommand() {
|
|
|
4290
4543
|
console.log("");
|
|
4291
4544
|
});
|
|
4292
4545
|
} catch (err) {
|
|
4293
|
-
|
|
4546
|
+
spinner.stop();
|
|
4294
4547
|
printError(err);
|
|
4295
4548
|
process.exit(1);
|
|
4296
4549
|
}
|
|
4297
4550
|
});
|
|
4298
4551
|
cmd.command("errors").description("Show only error log entries for an agent").option("--agent <agentId>", "Agent ID").option("--limit <n>", "Max entries", "20").option("--json", "Output as JSON").action(async (opts) => {
|
|
4299
4552
|
const cfg = loadConfig();
|
|
4300
|
-
const
|
|
4301
|
-
if (!
|
|
4553
|
+
const agentId2 = opts.agent ?? cfg.defaultAgentId;
|
|
4554
|
+
if (!agentId2) {
|
|
4302
4555
|
console.error(c.error("Specify --agent <agentId>"));
|
|
4303
4556
|
process.exit(1);
|
|
4304
4557
|
}
|
|
4305
4558
|
const spinner = spin("Fetching error logs\u2026");
|
|
4306
4559
|
try {
|
|
4307
4560
|
const client = makeClient();
|
|
4308
|
-
const res = await client.
|
|
4561
|
+
const res = await client.logs.list(agentId2, {
|
|
4562
|
+
limit: Number(opts.limit)
|
|
4563
|
+
});
|
|
4309
4564
|
const errors = (res?.data ?? []).filter((l) => l.status === "error");
|
|
4310
4565
|
spinner.stop();
|
|
4311
4566
|
if (opts.json) return jsonOut(errors);
|
|
4312
|
-
section(`Errors \u2014 ${
|
|
4567
|
+
section(`Errors \u2014 ${agentId2.slice(0, 12)}\u2026 (${errors.length})`);
|
|
4313
4568
|
if (errors.length === 0) {
|
|
4314
4569
|
console.log(`${sym.ok} No errors found`);
|
|
4315
4570
|
return;
|
|
@@ -4329,7 +4584,7 @@ function logsCommand() {
|
|
|
4329
4584
|
}
|
|
4330
4585
|
|
|
4331
4586
|
// src/commands/computer.ts
|
|
4332
|
-
var
|
|
4587
|
+
var import_commander18 = require("commander");
|
|
4333
4588
|
var RESOURCE_PROFILES = [
|
|
4334
4589
|
"starter",
|
|
4335
4590
|
"standard",
|
|
@@ -4338,13 +4593,13 @@ var RESOURCE_PROFILES = [
|
|
|
4338
4593
|
];
|
|
4339
4594
|
var RESOURCE_MODES = ["fixed", "elastic"];
|
|
4340
4595
|
function resolveAgentId(opts) {
|
|
4341
|
-
const
|
|
4342
|
-
if (!
|
|
4596
|
+
const agentId2 = opts.agent ?? loadConfig().defaultAgentId;
|
|
4597
|
+
if (!agentId2) {
|
|
4343
4598
|
throw new Error(
|
|
4344
4599
|
"Specify --agent <agentId> or set defaultAgentId with `agc config set defaultAgentId <id>`."
|
|
4345
4600
|
);
|
|
4346
4601
|
}
|
|
4347
|
-
return
|
|
4602
|
+
return agentId2;
|
|
4348
4603
|
}
|
|
4349
4604
|
function unwrap(response) {
|
|
4350
4605
|
return response?.data ?? response;
|
|
@@ -4395,17 +4650,17 @@ function parseNumber(value, name, options) {
|
|
|
4395
4650
|
}
|
|
4396
4651
|
return parsed;
|
|
4397
4652
|
}
|
|
4398
|
-
async function changeEnabled(
|
|
4653
|
+
async function changeEnabled(agentId2, enabled, json) {
|
|
4399
4654
|
const spinner = spin(`${enabled ? "Enabling" : "Disabling"} persistent cloud computer\u2026`);
|
|
4400
4655
|
try {
|
|
4401
|
-
const response = await makeClient().agents.updateComputerConfig(
|
|
4656
|
+
const response = await makeClient().agents.updateComputerConfig(agentId2, { enabled });
|
|
4402
4657
|
const config = unwrap(response);
|
|
4403
4658
|
spinner.stop();
|
|
4404
4659
|
if (json) return jsonOut(config);
|
|
4405
4660
|
console.log(`
|
|
4406
|
-
${sym.ok} Persistent cloud computer ${enabled ? "enabled" : "disabled"} for agent ${c.id(
|
|
4661
|
+
${sym.ok} Persistent cloud computer ${enabled ? "enabled" : "disabled"} for agent ${c.id(agentId2)}`);
|
|
4407
4662
|
if (enabled) {
|
|
4408
|
-
console.log(c.dim(` Wake it now with: agc computer wake --agent ${
|
|
4663
|
+
console.log(c.dim(` Wake it now with: agc computer wake --agent ${agentId2}`));
|
|
4409
4664
|
}
|
|
4410
4665
|
} catch (error) {
|
|
4411
4666
|
spinner.stop();
|
|
@@ -4413,12 +4668,12 @@ ${sym.ok} Persistent cloud computer ${enabled ? "enabled" : "disabled"} for agen
|
|
|
4413
4668
|
process.exitCode = 1;
|
|
4414
4669
|
}
|
|
4415
4670
|
}
|
|
4416
|
-
async function lifecycleAction(action,
|
|
4671
|
+
async function lifecycleAction(action, agentId2, reason, json) {
|
|
4417
4672
|
const verb = action === "wake" ? "Waking" : action === "sleep" ? "Sleeping" : "Restarting";
|
|
4418
4673
|
const spinner = spin(`${verb} persistent cloud computer\u2026`);
|
|
4419
4674
|
try {
|
|
4420
4675
|
const client = makeClient();
|
|
4421
|
-
const response = action === "wake" ? await client.agents.wakeComputer(
|
|
4676
|
+
const response = action === "wake" ? await client.agents.wakeComputer(agentId2, reason ? { reason } : void 0) : action === "sleep" ? await client.agents.sleepComputer(agentId2, reason ? { reason } : void 0) : await client.agents.restartComputer(agentId2, reason ? { reason } : void 0);
|
|
4422
4677
|
const computer = unwrap(response);
|
|
4423
4678
|
spinner.stop();
|
|
4424
4679
|
if (json) return jsonOut(computer);
|
|
@@ -4435,11 +4690,11 @@ function addAgentOption(command) {
|
|
|
4435
4690
|
return command.option("--agent <agentId>", "Agent ID (defaults to configured agent)");
|
|
4436
4691
|
}
|
|
4437
4692
|
function computerCommand() {
|
|
4438
|
-
const command = new
|
|
4693
|
+
const command = new import_commander18.Command("computer").description("Manage an agent's one persistent cloud computer");
|
|
4439
4694
|
addAgentOption(command.command("status").description("Show persistent cloud computer status")).option("--json", "Output as JSON").action(async (opts) => {
|
|
4440
|
-
let
|
|
4695
|
+
let agentId2;
|
|
4441
4696
|
try {
|
|
4442
|
-
|
|
4697
|
+
agentId2 = resolveAgentId(opts);
|
|
4443
4698
|
} catch (error) {
|
|
4444
4699
|
printError(error);
|
|
4445
4700
|
process.exitCode = 1;
|
|
@@ -4447,7 +4702,7 @@ function computerCommand() {
|
|
|
4447
4702
|
}
|
|
4448
4703
|
const spinner = spin("Fetching persistent cloud computer\u2026");
|
|
4449
4704
|
try {
|
|
4450
|
-
const computer = unwrap(await makeClient().agents.getComputer(
|
|
4705
|
+
const computer = unwrap(await makeClient().agents.getComputer(agentId2));
|
|
4451
4706
|
spinner.stop();
|
|
4452
4707
|
if (opts.json) return jsonOut(computer);
|
|
4453
4708
|
displayComputer(computer);
|
|
@@ -4489,10 +4744,10 @@ function computerCommand() {
|
|
|
4489
4744
|
});
|
|
4490
4745
|
}
|
|
4491
4746
|
addAgentOption(command.command("resize").description("Resize the persistent cloud computer")).option("--profile <profile>", `Resource profile: ${RESOURCE_PROFILES.join(" | ")}`).option("--mode <mode>", `Resource mode: ${RESOURCE_MODES.join(" | ")}`).option("--vcpu <count>", "Requested virtual CPU count").option("--cpu <count>", "Alias for --vcpu").option("--memory <gib>", "Requested memory in GiB").option("--storage <gib>", "Requested persistent storage in GiB").option("--gpu-type <type>", "GPU type, such as nvidia-h100").option("--gpu-count <count>", "GPU count (0 removes GPU allocation)").option("--json", "Output as JSON").action(async (opts) => {
|
|
4492
|
-
let
|
|
4747
|
+
let agentId2;
|
|
4493
4748
|
let resize;
|
|
4494
4749
|
try {
|
|
4495
|
-
|
|
4750
|
+
agentId2 = resolveAgentId(opts);
|
|
4496
4751
|
if (opts.profile && !RESOURCE_PROFILES.includes(opts.profile)) {
|
|
4497
4752
|
throw new Error(`--profile must be one of: ${RESOURCE_PROFILES.join(", ")}.`);
|
|
4498
4753
|
}
|
|
@@ -4529,7 +4784,7 @@ function computerCommand() {
|
|
|
4529
4784
|
}
|
|
4530
4785
|
const spinner = spin("Resizing persistent cloud computer\u2026");
|
|
4531
4786
|
try {
|
|
4532
|
-
const computer = unwrap(await makeClient().agents.resizeComputer(
|
|
4787
|
+
const computer = unwrap(await makeClient().agents.resizeComputer(agentId2, resize));
|
|
4533
4788
|
spinner.stop();
|
|
4534
4789
|
if (opts.json) return jsonOut(computer);
|
|
4535
4790
|
console.log(`
|
|
@@ -4544,10 +4799,10 @@ ${sym.ok} Persistent cloud computer resize requested`);
|
|
|
4544
4799
|
addAgentOption(
|
|
4545
4800
|
command.command("exec").description("Run a command in the persistent cloud computer").argument("<command...>", "Command and arguments to run")
|
|
4546
4801
|
).option("--cwd <path>", "Working directory").option("--timeout <seconds>", "Command timeout in seconds", "120").option("--json", "Output as JSON").action(async (commandParts, opts) => {
|
|
4547
|
-
let
|
|
4802
|
+
let agentId2;
|
|
4548
4803
|
let timeoutSeconds;
|
|
4549
4804
|
try {
|
|
4550
|
-
|
|
4805
|
+
agentId2 = resolveAgentId(opts);
|
|
4551
4806
|
timeoutSeconds = parseNumber(opts.timeout, "Timeout");
|
|
4552
4807
|
} catch (error) {
|
|
4553
4808
|
printError(error);
|
|
@@ -4556,7 +4811,7 @@ ${sym.ok} Persistent cloud computer resize requested`);
|
|
|
4556
4811
|
}
|
|
4557
4812
|
const spinner = spin("Running command in persistent cloud computer\u2026");
|
|
4558
4813
|
try {
|
|
4559
|
-
const result = unwrap(await makeClient().agents.execComputer(
|
|
4814
|
+
const result = unwrap(await makeClient().agents.execComputer(agentId2, {
|
|
4560
4815
|
command: commandParts.join(" "),
|
|
4561
4816
|
...opts.cwd && { cwd: opts.cwd },
|
|
4562
4817
|
...timeoutSeconds !== void 0 && { timeoutSeconds }
|
|
@@ -4576,10 +4831,10 @@ ${sym.ok} Persistent cloud computer resize requested`);
|
|
|
4576
4831
|
}
|
|
4577
4832
|
});
|
|
4578
4833
|
addAgentOption(command.command("events").description("List recent persistent cloud computer events")).option("--limit <count>", "Maximum events", "50").option("--json", "Output as JSON").action(async (opts) => {
|
|
4579
|
-
let
|
|
4834
|
+
let agentId2;
|
|
4580
4835
|
let limit;
|
|
4581
4836
|
try {
|
|
4582
|
-
|
|
4837
|
+
agentId2 = resolveAgentId(opts);
|
|
4583
4838
|
limit = parseNumber(opts.limit, "Limit", { integer: true });
|
|
4584
4839
|
} catch (error) {
|
|
4585
4840
|
printError(error);
|
|
@@ -4588,7 +4843,7 @@ ${sym.ok} Persistent cloud computer resize requested`);
|
|
|
4588
4843
|
}
|
|
4589
4844
|
const spinner = spin("Fetching persistent cloud computer events\u2026");
|
|
4590
4845
|
try {
|
|
4591
|
-
const events = unwrap(await makeClient().agents.listComputerEvents(
|
|
4846
|
+
const events = unwrap(await makeClient().agents.listComputerEvents(agentId2, limit));
|
|
4592
4847
|
spinner.stop();
|
|
4593
4848
|
if (opts.json) return jsonOut(events);
|
|
4594
4849
|
section(`Cloud computer events (${events.length})`);
|
|
@@ -4610,8 +4865,472 @@ ${sym.ok} Persistent cloud computer resize requested`);
|
|
|
4610
4865
|
return command;
|
|
4611
4866
|
}
|
|
4612
4867
|
|
|
4868
|
+
// src/commands/library.ts
|
|
4869
|
+
var import_commander19 = require("commander");
|
|
4870
|
+
var import_fs7 = require("fs");
|
|
4871
|
+
var import_path5 = require("path");
|
|
4872
|
+
function libraryCommand() {
|
|
4873
|
+
const command = new import_commander19.Command("library").alias("files").description("Upload, find, and manage files in your Commons library");
|
|
4874
|
+
command.command("list", { isDefault: true }).alias("ls").description("List library items").option("--query <text>", "Search names and descriptions").option("--source <source>", "Filter by source").option("--session <sessionId>", "Filter by session").option("--favorites", "Show favorites only").option("--limit <n>", "Maximum items", "50").option("--json", "Output as JSON").action(async (opts) => {
|
|
4875
|
+
const spinner = spin("Fetching your library\u2026");
|
|
4876
|
+
try {
|
|
4877
|
+
const result = await makeClient().library.list({
|
|
4878
|
+
query: opts.query,
|
|
4879
|
+
source: opts.source,
|
|
4880
|
+
sessionId: opts.session,
|
|
4881
|
+
favorite: opts.favorites ? true : void 0,
|
|
4882
|
+
limit: Number(opts.limit)
|
|
4883
|
+
});
|
|
4884
|
+
spinner.stop();
|
|
4885
|
+
if (opts.json) return jsonOut(result);
|
|
4886
|
+
section(`Library (${result.data.length})`);
|
|
4887
|
+
table(
|
|
4888
|
+
result.data.map((item) => ({
|
|
4889
|
+
ID: String(item.itemId ?? item.fileId).slice(0, 10) + "\u2026",
|
|
4890
|
+
Name: item.name ?? item.originalName ?? "(untitled)",
|
|
4891
|
+
Type: item.mimeType ?? "",
|
|
4892
|
+
Size: typeof item.size === "number" ? `${Math.ceil(item.size / 1024)} KB` : "",
|
|
4893
|
+
Favorite: item.isFavorite ? "\u2605" : "",
|
|
4894
|
+
Created: item.createdAt ? relativeTime(item.createdAt) : ""
|
|
4895
|
+
})),
|
|
4896
|
+
["ID", "Name", "Type", "Size", "Favorite", "Created"]
|
|
4897
|
+
);
|
|
4898
|
+
} catch (error) {
|
|
4899
|
+
spinner.stop();
|
|
4900
|
+
printError(error);
|
|
4901
|
+
process.exit(1);
|
|
4902
|
+
}
|
|
4903
|
+
});
|
|
4904
|
+
command.command("get <itemId>").description("Show library item details").option("--json", "Output as JSON").action(async (itemId, opts) => {
|
|
4905
|
+
const spinner = spin("Fetching library item\u2026");
|
|
4906
|
+
try {
|
|
4907
|
+
const result = await makeClient().library.get(itemId);
|
|
4908
|
+
spinner.stop();
|
|
4909
|
+
if (opts.json) return jsonOut(result.data);
|
|
4910
|
+
const item = result.data;
|
|
4911
|
+
detail([
|
|
4912
|
+
["Item ID", c.id(String(item.itemId ?? item.fileId))],
|
|
4913
|
+
["Name", item.name ?? item.originalName ?? "(untitled)"],
|
|
4914
|
+
["Description", item.description ?? ""],
|
|
4915
|
+
["Type", item.mimeType ?? ""],
|
|
4916
|
+
["Storage", item.storageProvider ?? ""],
|
|
4917
|
+
["Favorite", item.isFavorite ? "yes" : "no"],
|
|
4918
|
+
["Created", item.createdAt ? relativeTime(item.createdAt) : ""]
|
|
4919
|
+
]);
|
|
4920
|
+
} catch (error) {
|
|
4921
|
+
spinner.stop();
|
|
4922
|
+
printError(error);
|
|
4923
|
+
process.exit(1);
|
|
4924
|
+
}
|
|
4925
|
+
});
|
|
4926
|
+
command.command("upload <paths...>").description("Upload one or more local files").option("--agent <agentId>", "Associate files with an agent").option("--session <sessionId>", "Associate files with a session").option("--storage <provider>", "Storage provider: s3 | ipfs").option("--json", "Output as JSON").action(async (paths, opts) => {
|
|
4927
|
+
const spinner = spin(`Uploading ${paths.length} file${paths.length === 1 ? "" : "s"}\u2026`);
|
|
4928
|
+
try {
|
|
4929
|
+
if (opts.storage && opts.storage !== "s3" && opts.storage !== "ipfs") {
|
|
4930
|
+
throw new Error("--storage must be either s3 or ipfs.");
|
|
4931
|
+
}
|
|
4932
|
+
const files = paths.map((path) => ({
|
|
4933
|
+
data: new Blob([new Uint8Array((0, import_fs7.readFileSync)(path))]),
|
|
4934
|
+
name: (0, import_path5.basename)(path)
|
|
4935
|
+
}));
|
|
4936
|
+
const result = await makeClient().files.upload(files, {
|
|
4937
|
+
agentId: opts.agent,
|
|
4938
|
+
sessionId: opts.session,
|
|
4939
|
+
storageProvider: opts.storage
|
|
4940
|
+
});
|
|
4941
|
+
spinner.stop();
|
|
4942
|
+
if (opts.json) return jsonOut(result.data);
|
|
4943
|
+
console.log(
|
|
4944
|
+
`
|
|
4945
|
+
${sym.ok} Uploaded ${result.data.length} file${result.data.length === 1 ? "" : "s"}.`
|
|
4946
|
+
);
|
|
4947
|
+
for (const file of result.data) {
|
|
4948
|
+
console.log(
|
|
4949
|
+
` ${sym.arrow} ${c.bold(file.name ?? file.originalName ?? file.fileId)} ${c.dim(file.fileId)}`
|
|
4950
|
+
);
|
|
4951
|
+
}
|
|
4952
|
+
} catch (error) {
|
|
4953
|
+
spinner.stop();
|
|
4954
|
+
printError(error);
|
|
4955
|
+
process.exit(1);
|
|
4956
|
+
}
|
|
4957
|
+
});
|
|
4958
|
+
for (const favorite of [true, false]) {
|
|
4959
|
+
command.command(`${favorite ? "favorite" : "unfavorite"} <itemId>`).description(`${favorite ? "Add" : "Remove"} a library item ${favorite ? "to" : "from"} favorites`).action(async (itemId) => {
|
|
4960
|
+
const spinner = spin("Updating library item\u2026");
|
|
4961
|
+
try {
|
|
4962
|
+
await makeClient().library.update(itemId, {
|
|
4963
|
+
isFavorite: favorite
|
|
4964
|
+
});
|
|
4965
|
+
spinner.stop();
|
|
4966
|
+
console.log(
|
|
4967
|
+
`${sym.ok} Item ${favorite ? "added to" : "removed from"} favorites.`
|
|
4968
|
+
);
|
|
4969
|
+
} catch (error) {
|
|
4970
|
+
spinner.stop();
|
|
4971
|
+
printError(error);
|
|
4972
|
+
process.exit(1);
|
|
4973
|
+
}
|
|
4974
|
+
});
|
|
4975
|
+
}
|
|
4976
|
+
command.command("delete <itemId>").description("Delete a library item").action(async (itemId) => {
|
|
4977
|
+
const spinner = spin("Deleting library item\u2026");
|
|
4978
|
+
try {
|
|
4979
|
+
await makeClient().library.delete(itemId);
|
|
4980
|
+
spinner.stop();
|
|
4981
|
+
console.log(`${sym.ok} Library item deleted.`);
|
|
4982
|
+
} catch (error) {
|
|
4983
|
+
spinner.stop();
|
|
4984
|
+
printError(error);
|
|
4985
|
+
process.exit(1);
|
|
4986
|
+
}
|
|
4987
|
+
});
|
|
4988
|
+
return command;
|
|
4989
|
+
}
|
|
4990
|
+
|
|
4991
|
+
// src/commands/projects.ts
|
|
4992
|
+
var import_commander20 = require("commander");
|
|
4993
|
+
var import_fs8 = require("fs");
|
|
4994
|
+
function agentId(value) {
|
|
4995
|
+
const resolved = value ?? loadConfig().defaultAgentId;
|
|
4996
|
+
if (!resolved) {
|
|
4997
|
+
throw new Error(
|
|
4998
|
+
"Specify --agent <agentId> or set a default with `agc config set defaultAgentId <id>`."
|
|
4999
|
+
);
|
|
5000
|
+
}
|
|
5001
|
+
return resolved;
|
|
5002
|
+
}
|
|
5003
|
+
function projectFiles(path) {
|
|
5004
|
+
if (!path) return void 0;
|
|
5005
|
+
const parsed = JSON.parse((0, import_fs8.readFileSync)(path, "utf8"));
|
|
5006
|
+
const files = Array.isArray(parsed) ? parsed : parsed.files;
|
|
5007
|
+
if (!Array.isArray(files)) {
|
|
5008
|
+
throw new Error("The files document must be an array or an object with a files array.");
|
|
5009
|
+
}
|
|
5010
|
+
return files;
|
|
5011
|
+
}
|
|
5012
|
+
function projectsCommand() {
|
|
5013
|
+
const command = new import_commander20.Command("projects").alias("project").description("Build, publish, and export agent code projects");
|
|
5014
|
+
command.command("list", { isDefault: true }).alias("ls").description("List projects for an agent").option("--agent <agentId>", "Agent ID").option("--json", "Output as JSON").action(async (opts) => {
|
|
5015
|
+
const spinner = spin("Fetching projects\u2026");
|
|
5016
|
+
try {
|
|
5017
|
+
const result = await makeClient().projects.list(agentId(opts.agent));
|
|
5018
|
+
spinner.stop();
|
|
5019
|
+
if (opts.json) return jsonOut(result.data);
|
|
5020
|
+
section(`Projects (${result.data.length})`);
|
|
5021
|
+
table(
|
|
5022
|
+
result.data.map((project) => ({
|
|
5023
|
+
ID: project.projectId.slice(0, 10) + "\u2026",
|
|
5024
|
+
Name: project.name,
|
|
5025
|
+
Files: String(project.files?.length ?? ""),
|
|
5026
|
+
Preview: project.previewUrl ?? project.previewSlug ?? "",
|
|
5027
|
+
Updated: project.updatedAt ?? ""
|
|
5028
|
+
})),
|
|
5029
|
+
["ID", "Name", "Files", "Preview", "Updated"]
|
|
5030
|
+
);
|
|
5031
|
+
} catch (error) {
|
|
5032
|
+
spinner.stop();
|
|
5033
|
+
printError(error);
|
|
5034
|
+
process.exit(1);
|
|
5035
|
+
}
|
|
5036
|
+
});
|
|
5037
|
+
command.command("get <projectId>").description("Show a code project").option("--agent <agentId>", "Agent ID").option("--json", "Output as JSON").action(async (projectId, opts) => {
|
|
5038
|
+
const spinner = spin("Fetching project\u2026");
|
|
5039
|
+
try {
|
|
5040
|
+
const result = await makeClient().projects.get(
|
|
5041
|
+
agentId(opts.agent),
|
|
5042
|
+
projectId
|
|
5043
|
+
);
|
|
5044
|
+
spinner.stop();
|
|
5045
|
+
if (opts.json) return jsonOut(result.data);
|
|
5046
|
+
const project = result.data;
|
|
5047
|
+
section(project.name);
|
|
5048
|
+
detail([
|
|
5049
|
+
["Project ID", c.id(project.projectId)],
|
|
5050
|
+
["Agent ID", project.agentId],
|
|
5051
|
+
["Description", project.description ?? ""],
|
|
5052
|
+
["Files", String(project.files?.length ?? 0)],
|
|
5053
|
+
["Preview", project.previewUrl ?? project.previewSlug ?? ""],
|
|
5054
|
+
["Updated", project.updatedAt ?? ""]
|
|
5055
|
+
]);
|
|
5056
|
+
} catch (error) {
|
|
5057
|
+
spinner.stop();
|
|
5058
|
+
printError(error);
|
|
5059
|
+
process.exit(1);
|
|
5060
|
+
}
|
|
5061
|
+
});
|
|
5062
|
+
command.command("create").description("Create a code project").requiredOption("--name <name>", "Project name").option("--description <text>", "Project description").option("--agent <agentId>", "Agent ID").option("--session <sessionId>", "Associated session").option("--files <json>", "JSON file containing [{ path, content }]").option("--json", "Output as JSON").action(async (opts) => {
|
|
5063
|
+
const spinner = spin("Creating project\u2026");
|
|
5064
|
+
try {
|
|
5065
|
+
const result = await makeClient().projects.create(
|
|
5066
|
+
agentId(opts.agent),
|
|
5067
|
+
{
|
|
5068
|
+
name: opts.name,
|
|
5069
|
+
description: opts.description,
|
|
5070
|
+
sessionId: opts.session,
|
|
5071
|
+
files: projectFiles(opts.files)
|
|
5072
|
+
}
|
|
5073
|
+
);
|
|
5074
|
+
spinner.stop();
|
|
5075
|
+
if (opts.json) return jsonOut(result.data);
|
|
5076
|
+
console.log(`
|
|
5077
|
+
${sym.ok} Project created.`);
|
|
5078
|
+
detail([
|
|
5079
|
+
["Project ID", c.id(result.data.projectId)],
|
|
5080
|
+
["Name", result.data.name]
|
|
5081
|
+
]);
|
|
5082
|
+
} catch (error) {
|
|
5083
|
+
spinner.stop();
|
|
5084
|
+
printError(error);
|
|
5085
|
+
process.exit(1);
|
|
5086
|
+
}
|
|
5087
|
+
});
|
|
5088
|
+
command.command("write <projectId> <json>").description("Write project files from a JSON document").option("--agent <agentId>", "Agent ID").option("--replace", "Replace all existing files").option("--json", "Output as JSON").action(async (projectId, json, opts) => {
|
|
5089
|
+
const spinner = spin("Writing project files\u2026");
|
|
5090
|
+
try {
|
|
5091
|
+
const result = await makeClient().projects.writeFiles(
|
|
5092
|
+
agentId(opts.agent),
|
|
5093
|
+
projectId,
|
|
5094
|
+
projectFiles(json) ?? [],
|
|
5095
|
+
Boolean(opts.replace)
|
|
5096
|
+
);
|
|
5097
|
+
spinner.stop();
|
|
5098
|
+
if (opts.json) return jsonOut(result.data);
|
|
5099
|
+
console.log(`${sym.ok} Project files updated.`);
|
|
5100
|
+
} catch (error) {
|
|
5101
|
+
spinner.stop();
|
|
5102
|
+
printError(error);
|
|
5103
|
+
process.exit(1);
|
|
5104
|
+
}
|
|
5105
|
+
});
|
|
5106
|
+
command.command("publish <projectId>").description("Build and publish a project preview").option("--agent <agentId>", "Agent ID").option("--json", "Output as JSON").action(async (projectId, opts) => {
|
|
5107
|
+
const spinner = spin("Building and publishing project\u2026");
|
|
5108
|
+
try {
|
|
5109
|
+
const result = await makeClient().projects.publish(
|
|
5110
|
+
agentId(opts.agent),
|
|
5111
|
+
projectId
|
|
5112
|
+
);
|
|
5113
|
+
spinner.stop();
|
|
5114
|
+
if (opts.json) return jsonOut(result.data);
|
|
5115
|
+
console.log(`
|
|
5116
|
+
${sym.ok} Project published.`);
|
|
5117
|
+
jsonOut(result.data);
|
|
5118
|
+
} catch (error) {
|
|
5119
|
+
spinner.stop();
|
|
5120
|
+
printError(error);
|
|
5121
|
+
process.exit(1);
|
|
5122
|
+
}
|
|
5123
|
+
});
|
|
5124
|
+
command.command("export <projectId>").description("Export a project to the agent computer").option("--agent <agentId>", "Agent ID").option("--directory <path>", "Destination directory").option("--session <sessionId>", "Associated session").option("--json", "Output as JSON").action(async (projectId, opts) => {
|
|
5125
|
+
const spinner = spin("Exporting project\u2026");
|
|
5126
|
+
try {
|
|
5127
|
+
const result = await makeClient().projects.exportToComputer(
|
|
5128
|
+
agentId(opts.agent),
|
|
5129
|
+
projectId,
|
|
5130
|
+
{ directory: opts.directory, sessionId: opts.session }
|
|
5131
|
+
);
|
|
5132
|
+
spinner.stop();
|
|
5133
|
+
if (opts.json) return jsonOut(result.data);
|
|
5134
|
+
console.log(`${sym.ok} Project exported to the agent computer.`);
|
|
5135
|
+
jsonOut(result.data);
|
|
5136
|
+
} catch (error) {
|
|
5137
|
+
spinner.stop();
|
|
5138
|
+
printError(error);
|
|
5139
|
+
process.exit(1);
|
|
5140
|
+
}
|
|
5141
|
+
});
|
|
5142
|
+
command.command("github <projectId>").description("Export a project to a GitHub repository").option("--agent <agentId>", "Agent ID").option("--repository <name>", "Repository name").option("--public", "Create a public repository").option("--json", "Output as JSON").action(async (projectId, opts) => {
|
|
5143
|
+
const spinner = spin("Exporting project to GitHub\u2026");
|
|
5144
|
+
try {
|
|
5145
|
+
const result = await makeClient().projects.exportToGitHub(
|
|
5146
|
+
agentId(opts.agent),
|
|
5147
|
+
projectId,
|
|
5148
|
+
{
|
|
5149
|
+
repositoryName: opts.repository,
|
|
5150
|
+
private: !opts.public
|
|
5151
|
+
}
|
|
5152
|
+
);
|
|
5153
|
+
spinner.stop();
|
|
5154
|
+
if (opts.json) return jsonOut(result.data);
|
|
5155
|
+
console.log(`${sym.ok} Project exported to GitHub.`);
|
|
5156
|
+
jsonOut(result.data);
|
|
5157
|
+
} catch (error) {
|
|
5158
|
+
spinner.stop();
|
|
5159
|
+
printError(error);
|
|
5160
|
+
process.exit(1);
|
|
5161
|
+
}
|
|
5162
|
+
});
|
|
5163
|
+
return command;
|
|
5164
|
+
}
|
|
5165
|
+
|
|
5166
|
+
// src/commands/api-keys.ts
|
|
5167
|
+
var import_commander21 = require("commander");
|
|
5168
|
+
async function resolveProject(projectId) {
|
|
5169
|
+
const projects = (await makeClient().developer.listProjects()).data;
|
|
5170
|
+
const project = projectId ? projects.find((candidate) => candidate.id === projectId) : projects[0];
|
|
5171
|
+
if (!project) {
|
|
5172
|
+
throw new Error(
|
|
5173
|
+
projectId ? `Developer project "${projectId}" was not found.` : "No developer project exists. Create one with `agc keys projects create --name <name>`."
|
|
5174
|
+
);
|
|
5175
|
+
}
|
|
5176
|
+
return project;
|
|
5177
|
+
}
|
|
5178
|
+
function apiKeysCommand() {
|
|
5179
|
+
const command = new import_commander21.Command("keys").alias("api-keys").description("Create and manage project-scoped developer API keys");
|
|
5180
|
+
command.command("list", { isDefault: true }).alias("ls").description("List API keys for a developer project").option("--project <projectId>", "Developer project ID (defaults to newest)").option("--json", "Output as JSON").action(async (opts) => {
|
|
5181
|
+
const spinner = spin("Fetching developer keys\u2026");
|
|
5182
|
+
try {
|
|
5183
|
+
const project = await resolveProject(opts.project);
|
|
5184
|
+
const result = await makeClient().developer.listApiKeys(project.id);
|
|
5185
|
+
spinner.stop();
|
|
5186
|
+
if (opts.json) {
|
|
5187
|
+
return jsonOut({ project, keys: result.data });
|
|
5188
|
+
}
|
|
5189
|
+
section(`${project.name} \xB7 API keys (${result.data.length})`);
|
|
5190
|
+
table(
|
|
5191
|
+
result.data.map((key) => ({
|
|
5192
|
+
ID: key.id.slice(0, 10) + "\u2026",
|
|
5193
|
+
Name: key.name,
|
|
5194
|
+
Prefix: key.keyPrefix,
|
|
5195
|
+
Status: key.status,
|
|
5196
|
+
Scopes: String(key.scopes.length),
|
|
5197
|
+
Expires: key.expiresAt ? new Date(key.expiresAt).toLocaleDateString() : "never",
|
|
5198
|
+
Used: key.lastUsedAt ? new Date(key.lastUsedAt).toLocaleDateString() : "never"
|
|
5199
|
+
})),
|
|
5200
|
+
["ID", "Name", "Prefix", "Status", "Scopes", "Expires", "Used"]
|
|
5201
|
+
);
|
|
5202
|
+
} catch (error) {
|
|
5203
|
+
spinner.stop();
|
|
5204
|
+
printError(error);
|
|
5205
|
+
process.exit(1);
|
|
5206
|
+
}
|
|
5207
|
+
});
|
|
5208
|
+
command.command("create").description("Create a project-scoped API key").requiredOption("--name <name>", "Key name").option("--project <projectId>", "Developer project ID (defaults to newest)").option("--scopes <scopes>", "Comma-separated scopes (defaults to all project scopes)").option("--expires <iso>", "Expiration timestamp in ISO 8601 format").option("--json", "Output as JSON").action(async (opts) => {
|
|
5209
|
+
const spinner = spin("Creating developer key\u2026");
|
|
5210
|
+
try {
|
|
5211
|
+
const project = await resolveProject(opts.project);
|
|
5212
|
+
const scopes = opts.scopes ? String(opts.scopes).split(",").map((scope) => scope.trim()).filter(Boolean) : void 0;
|
|
5213
|
+
const result = await makeClient().developer.createApiKey(project.id, {
|
|
5214
|
+
name: opts.name,
|
|
5215
|
+
scopes,
|
|
5216
|
+
expiresAt: opts.expires
|
|
5217
|
+
});
|
|
5218
|
+
spinner.stop();
|
|
5219
|
+
if (opts.json) return jsonOut(result.data);
|
|
5220
|
+
console.log(`
|
|
5221
|
+
${sym.ok} ${c.success("Developer API key created")}`);
|
|
5222
|
+
detail([
|
|
5223
|
+
["Project", project.name],
|
|
5224
|
+
["Name", result.data.name],
|
|
5225
|
+
["Scopes", result.data.scopes.join(", ")],
|
|
5226
|
+
["Expires", result.data.expiresAt ?? "never"]
|
|
5227
|
+
]);
|
|
5228
|
+
console.log(
|
|
5229
|
+
`
|
|
5230
|
+
${c.warn("Copy this key now. It will not be shown again.")}`
|
|
5231
|
+
);
|
|
5232
|
+
console.log(`
|
|
5233
|
+
${c.bold(result.data.key)}
|
|
5234
|
+
`);
|
|
5235
|
+
} catch (error) {
|
|
5236
|
+
spinner.stop();
|
|
5237
|
+
printError(error);
|
|
5238
|
+
process.exit(1);
|
|
5239
|
+
}
|
|
5240
|
+
});
|
|
5241
|
+
command.command("revoke <keyId>").description("Revoke a developer API key").action(async (keyId) => {
|
|
5242
|
+
const spinner = spin("Revoking developer key\u2026");
|
|
5243
|
+
try {
|
|
5244
|
+
await makeClient().developer.revokeApiKey(keyId);
|
|
5245
|
+
spinner.stop();
|
|
5246
|
+
console.log(`${sym.ok} Developer API key revoked.`);
|
|
5247
|
+
} catch (error) {
|
|
5248
|
+
spinner.stop();
|
|
5249
|
+
printError(error);
|
|
5250
|
+
process.exit(1);
|
|
5251
|
+
}
|
|
5252
|
+
});
|
|
5253
|
+
command.command("scopes").description("List supported developer API scopes").option("--json", "Output as JSON").action(async (opts) => {
|
|
5254
|
+
const spinner = spin("Fetching API scopes\u2026");
|
|
5255
|
+
try {
|
|
5256
|
+
const result = await makeClient().developer.scopes();
|
|
5257
|
+
spinner.stop();
|
|
5258
|
+
if (opts.json) return jsonOut(result.data);
|
|
5259
|
+
section("Developer API scopes");
|
|
5260
|
+
for (const scope of result.data) {
|
|
5261
|
+
console.log(` ${sym.bullet} ${scope}`);
|
|
5262
|
+
}
|
|
5263
|
+
} catch (error) {
|
|
5264
|
+
spinner.stop();
|
|
5265
|
+
printError(error);
|
|
5266
|
+
process.exit(1);
|
|
5267
|
+
}
|
|
5268
|
+
});
|
|
5269
|
+
const projects = command.command("projects").description("Manage developer projects");
|
|
5270
|
+
projects.command("list", { isDefault: true }).alias("ls").description("List developer projects").option("--json", "Output as JSON").action(async (opts) => {
|
|
5271
|
+
const spinner = spin("Fetching developer projects\u2026");
|
|
5272
|
+
try {
|
|
5273
|
+
const result = await makeClient().developer.listProjects();
|
|
5274
|
+
spinner.stop();
|
|
5275
|
+
if (opts.json) return jsonOut(result.data);
|
|
5276
|
+
section(`Developer projects (${result.data.length})`);
|
|
5277
|
+
table(
|
|
5278
|
+
result.data.map((project) => ({
|
|
5279
|
+
ID: project.id,
|
|
5280
|
+
Name: project.name,
|
|
5281
|
+
Environment: project.environment,
|
|
5282
|
+
Status: project.status
|
|
5283
|
+
})),
|
|
5284
|
+
["ID", "Name", "Environment", "Status"]
|
|
5285
|
+
);
|
|
5286
|
+
} catch (error) {
|
|
5287
|
+
spinner.stop();
|
|
5288
|
+
printError(error);
|
|
5289
|
+
process.exit(1);
|
|
5290
|
+
}
|
|
5291
|
+
});
|
|
5292
|
+
projects.command("create").description("Create a developer project").requiredOption("--name <name>", "Project name").option(
|
|
5293
|
+
"--environment <environment>",
|
|
5294
|
+
"production | development | staging",
|
|
5295
|
+
"development"
|
|
5296
|
+
).option("--workspace <workspaceId>", "Workspace ID (defaults to signed-in workspace)").option("--json", "Output as JSON").action(async (opts) => {
|
|
5297
|
+
const workspaceId = opts.workspace ?? loadConfig().workspaceId;
|
|
5298
|
+
if (!workspaceId) {
|
|
5299
|
+
throw new Error(
|
|
5300
|
+
"No workspace is configured. Pass --workspace or sign in again."
|
|
5301
|
+
);
|
|
5302
|
+
}
|
|
5303
|
+
if (!["production", "development", "staging"].includes(opts.environment)) {
|
|
5304
|
+
throw new Error(
|
|
5305
|
+
"--environment must be production, development, or staging."
|
|
5306
|
+
);
|
|
5307
|
+
}
|
|
5308
|
+
const spinner = spin("Creating developer project\u2026");
|
|
5309
|
+
try {
|
|
5310
|
+
const result = await makeClient().developer.createProject({
|
|
5311
|
+
workspaceId,
|
|
5312
|
+
name: opts.name,
|
|
5313
|
+
environment: opts.environment
|
|
5314
|
+
});
|
|
5315
|
+
spinner.stop();
|
|
5316
|
+
if (opts.json) return jsonOut(result.data);
|
|
5317
|
+
console.log(`
|
|
5318
|
+
${sym.ok} Developer project created.`);
|
|
5319
|
+
detail([
|
|
5320
|
+
["Project ID", c.id(result.data.id)],
|
|
5321
|
+
["Name", result.data.name],
|
|
5322
|
+
["Environment", result.data.environment]
|
|
5323
|
+
]);
|
|
5324
|
+
} catch (error) {
|
|
5325
|
+
spinner.stop();
|
|
5326
|
+
printError(error);
|
|
5327
|
+
process.exit(1);
|
|
5328
|
+
}
|
|
5329
|
+
});
|
|
5330
|
+
return command;
|
|
5331
|
+
}
|
|
5332
|
+
|
|
4613
5333
|
// src/bin.ts
|
|
4614
|
-
var CONFIG_FILE3 = (0, import_path5.join)((0, import_os4.homedir)(), ".agc", "config.json");
|
|
4615
5334
|
async function interactiveMenu() {
|
|
4616
5335
|
banner();
|
|
4617
5336
|
const cfg = loadConfig();
|
|
@@ -4638,6 +5357,9 @@ async function interactiveMenu() {
|
|
|
4638
5357
|
{ label: "Workflows", value: "workflows", hint: "agc workflow list" },
|
|
4639
5358
|
{ label: "MCP servers", value: "mcp", hint: "agc mcp list" },
|
|
4640
5359
|
{ label: "Skills", value: "skills", hint: "agc skills list" },
|
|
5360
|
+
{ label: "Library & files", value: "library", hint: "agc library list" },
|
|
5361
|
+
{ label: "Code projects", value: "projects", hint: "agc projects list" },
|
|
5362
|
+
{ label: "Developer API keys", value: "keys", hint: "agc keys list" },
|
|
4641
5363
|
{ label: "Wallet & balance", value: "wallet", hint: "agc wallet balance" },
|
|
4642
5364
|
{ label: "Usage & cost", value: "usage", hint: "agc usage" },
|
|
4643
5365
|
{ label: "Logs", value: "logs", hint: "agc logs" },
|
|
@@ -4648,25 +5370,28 @@ async function interactiveMenu() {
|
|
|
4648
5370
|
process.exit(0);
|
|
4649
5371
|
}
|
|
4650
5372
|
const needsAgent = action === "chat" || action === "run" || action === "computer";
|
|
4651
|
-
const
|
|
4652
|
-
if (needsAgent && !
|
|
5373
|
+
const agentId2 = needsAgent ? cfg.defaultAgentId ?? await pickAgentInteractively(action) : void 0;
|
|
5374
|
+
if (needsAgent && !agentId2) return;
|
|
4653
5375
|
if (action === "run") {
|
|
4654
|
-
const
|
|
4655
|
-
if (!
|
|
4656
|
-
runSubcommand(["run", "--agent",
|
|
5376
|
+
const prompt = await askPrompt("Enter your prompt:");
|
|
5377
|
+
if (!prompt) return;
|
|
5378
|
+
runSubcommand(["run", "--agent", agentId2, prompt]);
|
|
4657
5379
|
return;
|
|
4658
5380
|
}
|
|
4659
5381
|
const commandMap = {
|
|
4660
|
-
chat: ["chat", "--agent",
|
|
5382
|
+
chat: ["chat", "--agent", agentId2],
|
|
4661
5383
|
run: [],
|
|
4662
5384
|
// handled above
|
|
4663
|
-
computer: ["computer", "status", "--agent",
|
|
5385
|
+
computer: ["computer", "status", "--agent", agentId2],
|
|
4664
5386
|
sessions: ["sessions", "list"],
|
|
4665
5387
|
agents: ["agents", "list"],
|
|
4666
5388
|
tasks: ["task", "list"],
|
|
4667
5389
|
workflows: ["workflow", "list"],
|
|
4668
5390
|
mcp: ["mcp", "list"],
|
|
4669
5391
|
skills: ["skills", "list"],
|
|
5392
|
+
library: ["library", "list"],
|
|
5393
|
+
projects: ["projects", "list"],
|
|
5394
|
+
keys: ["keys", "list"],
|
|
4670
5395
|
wallet: ["wallet", "balance"],
|
|
4671
5396
|
usage: ["usage"],
|
|
4672
5397
|
logs: ["logs"],
|
|
@@ -4676,9 +5401,9 @@ async function interactiveMenu() {
|
|
|
4676
5401
|
runSubcommand(commandMap[action]);
|
|
4677
5402
|
}
|
|
4678
5403
|
async function askPrompt(question) {
|
|
4679
|
-
const { createInterface:
|
|
5404
|
+
const { createInterface: createInterface3 } = await import("readline");
|
|
4680
5405
|
return new Promise((resolve2) => {
|
|
4681
|
-
const rl =
|
|
5406
|
+
const rl = createInterface3({ input: process.stdin, output: process.stdout });
|
|
4682
5407
|
process.stdout.write(`
|
|
4683
5408
|
${c.bold(question)}
|
|
4684
5409
|
${c.primary("\u203A")} `);
|
|
@@ -4707,7 +5432,7 @@ async function pickAgentInteractively(action) {
|
|
|
4707
5432
|
} catch {
|
|
4708
5433
|
spinner.stop();
|
|
4709
5434
|
console.log(`
|
|
4710
|
-
${c.warn("\u26A0")} Could not fetch agents. Check your
|
|
5435
|
+
${c.warn("\u26A0")} Could not fetch agents. Check your sign-in and connection.
|
|
4711
5436
|
`);
|
|
4712
5437
|
return null;
|
|
4713
5438
|
}
|
|
@@ -4725,7 +5450,7 @@ async function pickAgentInteractively(action) {
|
|
|
4725
5450
|
return null;
|
|
4726
5451
|
}
|
|
4727
5452
|
console.log();
|
|
4728
|
-
const
|
|
5453
|
+
const agentId2 = await select(
|
|
4729
5454
|
action === "computer" ? "Choose the agent whose cloud computer you want to manage:" : `Choose an agent to ${action} with:`,
|
|
4730
5455
|
agents.map((a) => ({
|
|
4731
5456
|
label: a.name,
|
|
@@ -4738,15 +5463,29 @@ async function pickAgentInteractively(action) {
|
|
|
4738
5463
|
{ label: "No \u2014 just this once", value: false }
|
|
4739
5464
|
]);
|
|
4740
5465
|
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 ??
|
|
5466
|
+
saveConfig({ defaultAgentId: agentId2 });
|
|
5467
|
+
const chosen = agents.find((a) => a.agentId === agentId2);
|
|
5468
|
+
console.log(` ${sym.ok} ${c.dim("Default agent set to")} ${c.bold(chosen?.name ?? agentId2)}
|
|
4744
5469
|
`);
|
|
4745
5470
|
}
|
|
4746
|
-
return
|
|
5471
|
+
return agentId2;
|
|
4747
5472
|
}
|
|
4748
|
-
var program = new
|
|
4749
|
-
program.name("agc").description("Agent Commons CLI \u2014 interact with the Agent Commons platform").version("0.
|
|
5473
|
+
var program = new import_commander22.Command();
|
|
5474
|
+
program.name("agc").description("Agent Commons CLI \u2014 interact with the Agent Commons platform").version("0.4.0", "-v, --version").showHelpAfterError("(run `agc --help` for usage)").configureHelp({
|
|
5475
|
+
sortOptions: true,
|
|
5476
|
+
sortSubcommands: true
|
|
5477
|
+
}).addHelpText(
|
|
5478
|
+
"after",
|
|
5479
|
+
`
|
|
5480
|
+
Examples:
|
|
5481
|
+
$ agc login
|
|
5482
|
+
$ agc agents list
|
|
5483
|
+
$ agc run --agent <id> "Summarize this week"
|
|
5484
|
+
$ agc keys create --name "CI" --scopes agents:read,agents:run
|
|
5485
|
+
|
|
5486
|
+
Docs: https://docs.agentcommons.io/docs/cli
|
|
5487
|
+
`
|
|
5488
|
+
).action(async () => {
|
|
4750
5489
|
await interactiveMenu();
|
|
4751
5490
|
});
|
|
4752
5491
|
program.hook("preAction", async (_thisCommand, actionCommand) => {
|
|
@@ -4761,6 +5500,9 @@ program.addCommand(agentsCommand());
|
|
|
4761
5500
|
program.addCommand(sessionsCommand());
|
|
4762
5501
|
program.addCommand(toolsCommand());
|
|
4763
5502
|
program.addCommand(connectionsCommand());
|
|
5503
|
+
program.addCommand(libraryCommand());
|
|
5504
|
+
program.addCommand(projectsCommand());
|
|
5505
|
+
program.addCommand(apiKeysCommand());
|
|
4764
5506
|
program.addCommand(workflowCommand());
|
|
4765
5507
|
program.addCommand(taskCommand());
|
|
4766
5508
|
program.addCommand(runCommand());
|
|
@@ -4773,6 +5515,8 @@ program.addCommand(modelsCommand());
|
|
|
4773
5515
|
program.addCommand(memoryCommand());
|
|
4774
5516
|
program.addCommand(usageCommand());
|
|
4775
5517
|
program.addCommand(logsCommand());
|
|
5518
|
+
program.addCommand(creditsCommand());
|
|
5519
|
+
program.addCommand(billingCommand());
|
|
4776
5520
|
program.on("command:*", () => {
|
|
4777
5521
|
console.error(
|
|
4778
5522
|
`
|
|
@@ -4782,4 +5526,9 @@ program.on("command:*", () => {
|
|
|
4782
5526
|
);
|
|
4783
5527
|
process.exit(1);
|
|
4784
5528
|
});
|
|
4785
|
-
program.
|
|
5529
|
+
program.parseAsync(process.argv).catch((error) => {
|
|
5530
|
+
console.error(`
|
|
5531
|
+
${sym.fail} ${c.error(error instanceof Error ? error.message : String(error))}
|
|
5532
|
+
`);
|
|
5533
|
+
process.exitCode = 1;
|
|
5534
|
+
});
|