@agent-commons/cli 0.3.0 → 0.5.0

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