@agent-commons/cli 0.3.0 → 0.4.0

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