@agent-commons/cli 0.1.18 → 0.2.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 (2) hide show
  1. package/dist/bin.js +106 -35
  2. package/package.json +2 -2
package/dist/bin.js CHANGED
@@ -106,7 +106,7 @@ var sym = {
106
106
  bullet: import_chalk.default.dim("\u2022"),
107
107
  dot: import_chalk.default.dim("\xB7")
108
108
  };
109
- function banner(version = "0.1.18") {
109
+ function banner(version = "0.2.0") {
110
110
  const line = import_chalk.default.cyan(" \u2500".padEnd(2) + "\u2500".repeat(44));
111
111
  console.log("");
112
112
  console.log(line);
@@ -482,7 +482,7 @@ function agentsCommand() {
482
482
  process.exit(1);
483
483
  }
484
484
  });
485
- cmd.command("create").description("Create a new agent").requiredOption("--name <name>", "Agent name").option("--instructions <text>", "System instructions").option("--provider <provider>", "Model provider (openai|anthropic|google|groq)", "openai").option("--model <id>", "Model ID", "gpt-4o").option("--json", "Output as JSON").action(async (opts) => {
485
+ cmd.command("create").description("Create a new agent").requiredOption("--name <name>", "Agent name").option("--instructions <text>", "System instructions").option("--provider <provider>", "Model provider (openai|anthropic|google|groq|openrouter|xai|ollama|custom)", "openai").option("--model <id>", "Model ID", "gpt-5.4-mini").option("--model-api-key <key>", "Provider API key (BYOK)").option("--model-base-url <url>", "Base URL for custom or local OpenAI-compatible providers").option("--json", "Output as JSON").action(async (opts) => {
486
486
  const cfg = loadConfig();
487
487
  if (!cfg.initiator) {
488
488
  console.error(c.error("No initiator set. Run `agc login` first."));
@@ -496,7 +496,9 @@ function agentsCommand() {
496
496
  instructions: opts.instructions,
497
497
  owner: cfg.initiator,
498
498
  modelProvider: opts.provider,
499
- modelId: opts.model
499
+ modelId: opts.model,
500
+ modelApiKey: opts.modelApiKey,
501
+ modelBaseUrl: opts.modelBaseUrl
500
502
  });
501
503
  const agent = res?.data ?? res;
502
504
  spinner.stop();
@@ -645,7 +647,7 @@ function sessionsCommand() {
645
647
  process.exit(1);
646
648
  }
647
649
  });
648
- 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-4o, claude-sonnet-4-6)").option("--provider <provider>", "Model provider").option("--json", "Output as JSON").action(async (opts) => {
650
+ 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) => {
649
651
  const cfg = loadConfig();
650
652
  const agentId = opts.agent ?? cfg.defaultAgentId;
651
653
  if (!agentId) {
@@ -1267,11 +1269,12 @@ ${fileSection}
1267
1269
  ### MANDATORY RULES \u2014 READ CAREFULLY
1268
1270
 
1269
1271
  1. **Call cli_* tools immediately and directly.** Do NOT create tasks (createTask) for local file operations. Do NOT delegate to sub-agents. Do NOT ask the user to run commands themselves.
1270
- 2. **Always show the actual output** returned by the tool in your response. Never say "I listed the files" without showing them. Report exactly what the tool returns.
1271
- 3. **Never fabricate results.** Wait for the real tool output before responding.
1272
- 4. **Sensitive paths are blocked** (.ssh, .gnupg, .aws, .env, credentials). Attempting to access them will return an error.
1273
- 5. ${autoApprove ? "**cli_write_file and cli_run_command execute immediately** \u2014 auto-approve is active, no user confirmation is required." : "**cli_write_file and cli_run_command require the user to confirm** before executing \u2014 you will see the result after they approve."}
1274
- 6. **Git commits must carry the agc co-author trailer.** Always include \`--trailer "Co-Authored-By: <AgentName> (agc) <agc-agent@users.noreply.github.com>"\` when running \`git commit\`. The CLI injects this automatically \u2014 do not omit it or pass \`--no-trailer\`.
1272
+ 2. **Own the request through completion.** Continue across tool calls, process polling, retries, debugging, and verification. Do not stop after describing a plan or asking whether to proceed when the request is already clear.
1273
+ 3. **Use actual tool output as evidence.** Summarize the important result; do not fabricate success or dump noisy logs unless they help diagnose a failure.
1274
+ 4. **Never fabricate results.** Wait for the real tool output before responding.
1275
+ 5. **Sensitive paths are blocked** (.ssh, .gnupg, .aws, .env, credentials). Attempting to access them will return an error.
1276
+ 6. ${autoApprove ? "**cli_write_file and cli_run_command execute immediately** \u2014 auto-approve is active, no user confirmation is required." : "**cli_write_file and cli_run_command require the user to confirm** before executing \u2014 you will see the result after they approve."}
1277
+ 7. **Git commits must carry the agc co-author trailer.** Always include \`--trailer "Co-Authored-By: <AgentName> (agc) <agc-agent@users.noreply.github.com>"\` when running \`git commit\`. The CLI injects this automatically \u2014 do not omit it or pass \`--no-trailer\`.
1275
1278
 
1276
1279
  ### Available CLI tools
1277
1280
 
@@ -1304,12 +1307,12 @@ ${fileSection}
1304
1307
 
1305
1308
  For long commands like \`npx create-next-app@latest my-app --yes\`:
1306
1309
 
1307
- 1. Call \`cli_start_process\` \u2014 returns \`{processId, status: "running"}\` immediately. Tell the user it has started.
1308
- 2. Call \`cli_wait_for_process\` with \`{"processId": "...", "wait_seconds": 60}\` \u2014 blocks up to 60s then returns current stdout/status. Report progress to the user.
1309
- 3. Repeat step 2 until \`status\` is \`"done"\` or \`"error"\`.
1310
- 4. Report the final output to the user.
1310
+ 1. Call \`cli_start_process\` \u2014 it returns \`{processId, status: "running"}\` immediately.
1311
+ 2. Call \`cli_wait_for_process\` with \`{"processId": "...", "wait_seconds": 60}\`.
1312
+ 3. Repeat step 2 until \`status\` is \`"done"\` or \`"error"\`; diagnose and repair errors when possible.
1313
+ 4. Continue with the rest of the assignment and verify the final outcome before responding.
1311
1314
 
1312
- Never hold the user in silence. Between each \`cli_wait_for_process\` call, tell them what you saw so far.
1315
+ Do not end the turn merely because a process is still running. Keep polling within the same run. Progress events may be streamed by the client, but the final answer comes only after completion or a genuine blocker.
1313
1316
 
1314
1317
  ### Example \u2014 scaffolding a Next.js project
1315
1318
 
@@ -1317,18 +1320,14 @@ Never hold the user in silence. Between each \`cli_wait_for_process\` call, tell
1317
1320
  cli_start_process: {"command": "npx", "args": ["create-next-app@latest", "my-app", "--yes"], "cwd": "Desktop"}
1318
1321
  \u2192 {processId: "proc_1a2b", status: "running"}
1319
1322
 
1320
- Tell user: "Started! Installing dependencies, this takes a minute or two. Checking in 60s\u2026"
1321
-
1322
1323
  cli_wait_for_process: {"processId": "proc_1a2b", "wait_seconds": 60}
1323
1324
  \u2192 {status: "running", elapsedSec: 60, stdout: "Creating project...
1324
1325
  Installing packages\u2026"}
1325
1326
 
1326
- Tell user: "Still installing \u2014 here's output so far: [stdout]. Checking again\u2026"
1327
-
1328
1327
  cli_wait_for_process: {"processId": "proc_1a2b", "wait_seconds": 60}
1329
1328
  \u2192 {status: "done", exitCode: 0, elapsedSec: 93, stdout: "Success! Created my-app"}
1330
1329
 
1331
- Tell user: "Done! Project created in Desktop/my-app"
1330
+ Continue by running the requested checks and opening/inspecting the app when the assignment requires it.
1332
1331
  \`\`\`
1333
1332
  `;
1334
1333
  }
@@ -1350,6 +1349,65 @@ function injectAgcTrailer(command, args, agentId, agentName) {
1350
1349
  const identity = agentName ? `${agentName} (agc)` : agentId ? `agc/${agentId}` : "agc agent";
1351
1350
  return [...args, "--trailer", `Co-Authored-By: ${identity} <agc-agent@users.noreply.github.com>`];
1352
1351
  }
1352
+ var AGC_HOOK_MARKER = "# agc-session:";
1353
+ var HOOK_BACKUP_SUFFIX = ".agc-backup";
1354
+ function findGitDir(rootDir) {
1355
+ const gitPath = (0, import_path3.join)(rootDir, ".git");
1356
+ if (!(0, import_fs3.existsSync)(gitPath)) return null;
1357
+ const s = (0, import_fs3.statSync)(gitPath);
1358
+ if (s.isDirectory()) return gitPath;
1359
+ if (s.isFile()) {
1360
+ const content = (0, import_fs3.readFileSync)(gitPath, "utf8");
1361
+ const match = content.match(/^gitdir:\s*(.+)$/m);
1362
+ if (match) return match[1].trim();
1363
+ }
1364
+ return null;
1365
+ }
1366
+ function installGitHook(rootDir, sessionId, agentId, agentName) {
1367
+ const gitDir = findGitDir(rootDir);
1368
+ if (!gitDir) return;
1369
+ const hooksDir = (0, import_path3.join)(gitDir, "hooks");
1370
+ (0, import_fs3.mkdirSync)(hooksDir, { recursive: true });
1371
+ const hookPath = (0, import_path3.join)(hooksDir, "prepare-commit-msg");
1372
+ if ((0, import_fs3.existsSync)(hookPath)) {
1373
+ const existing = (0, import_fs3.readFileSync)(hookPath, "utf8");
1374
+ if (!existing.includes(AGC_HOOK_MARKER)) {
1375
+ (0, import_fs3.writeFileSync)(hookPath + HOOK_BACKUP_SUFFIX, existing, { mode: 493 });
1376
+ }
1377
+ }
1378
+ const identity = agentName ? `${agentName} (agc)` : agentId ? `agc/${agentId}` : "agc agent";
1379
+ const trailer = `Co-Authored-By: ${identity} <agc-agent@users.noreply.github.com>`;
1380
+ const chainLine = (0, import_fs3.existsSync)(hookPath + HOOK_BACKUP_SUFFIX) ? `
1381
+ # chain pre-existing hook
1382
+ "$(dirname "$0")/prepare-commit-msg${HOOK_BACKUP_SUFFIX}" "$@" 2>/dev/null || true
1383
+ ` : "";
1384
+ const hook = `#!/bin/sh
1385
+ ${AGC_HOOK_MARKER}${sessionId}
1386
+ COMMIT_MSG_FILE="$1"
1387
+ COMMIT_SOURCE="$2"
1388
+ ${chainLine}
1389
+ case "$COMMIT_SOURCE" in merge|squash) exit 0 ;; esac
1390
+ TRAILER="${trailer}"
1391
+ grep -qF "$TRAILER" "$COMMIT_MSG_FILE" 2>/dev/null && exit 0
1392
+ printf '\\n%s\\n' "$TRAILER" >> "$COMMIT_MSG_FILE"
1393
+ `;
1394
+ (0, import_fs3.writeFileSync)(hookPath, hook, { mode: 493 });
1395
+ }
1396
+ function removeGitHook(rootDir) {
1397
+ const gitDir = findGitDir(rootDir);
1398
+ if (!gitDir) return;
1399
+ const hookPath = (0, import_path3.join)(gitDir, "hooks", "prepare-commit-msg");
1400
+ if (!(0, import_fs3.existsSync)(hookPath)) return;
1401
+ const content = (0, import_fs3.readFileSync)(hookPath, "utf8");
1402
+ if (!content.includes(AGC_HOOK_MARKER)) return;
1403
+ const backupPath = hookPath + HOOK_BACKUP_SUFFIX;
1404
+ if ((0, import_fs3.existsSync)(backupPath)) {
1405
+ (0, import_fs3.writeFileSync)(hookPath, (0, import_fs3.readFileSync)(backupPath, "utf8"), { mode: 493 });
1406
+ (0, import_fs3.unlinkSync)(backupPath);
1407
+ } else {
1408
+ (0, import_fs3.unlinkSync)(hookPath);
1409
+ }
1410
+ }
1353
1411
  function safePath(root, userPath) {
1354
1412
  const abs = (0, import_path3.resolve)(root, userPath);
1355
1413
  const rel = (0, import_path3.relative)(root, abs);
@@ -1841,7 +1899,7 @@ function runCommand() {
1841
1899
  ...cfg.initiator && { initiatorId: cfg.initiator },
1842
1900
  ...cliContext && { cliContext }
1843
1901
  };
1844
- if (opts.noStream) {
1902
+ if (opts.noStream && !localEnabled) {
1845
1903
  const spinner = spin("Running\u2026");
1846
1904
  try {
1847
1905
  const result = await client.run.once(params);
@@ -1917,7 +1975,8 @@ Session: ${sessionId} (resume with: agc run --session ${sessionId} "<prompt>")`
1917
1975
  } else if (event.type === "final") {
1918
1976
  if (hasOutput) process.stdout.write("\n");
1919
1977
  const e = event;
1920
- if (e.content && !hasOutput) console.log(e.content);
1978
+ const finalText = e.content ?? e.payload?.content ?? e.payload?.text ?? e.payload?.message;
1979
+ if (finalText && !hasOutput) console.log(finalText);
1921
1980
  if (sessionId) console.log(c.dim(`
1922
1981
  Session: ${sessionId} (resume with: agc run --session ${sessionId} "<prompt>")`));
1923
1982
  break;
@@ -2039,23 +2098,27 @@ function chatCommand() {
2039
2098
  process.exit(1);
2040
2099
  }
2041
2100
  }
2101
+ let agentName;
2042
2102
  let walletLine = "";
2043
- try {
2044
- const primary = await client.wallets.primary(agentId);
2045
- const w = primary?.data ?? primary;
2046
- if (w?.id) {
2047
- const bal = await client.wallets.balance(w.id).catch(() => null);
2048
- const b = bal?.data ?? bal;
2049
- const addr = `${w.address.slice(0, 6)}\u2026${w.address.slice(-4)}`;
2050
- const usdc = b?.usdc ?? "0";
2051
- walletLine = `${addr} ${c.bold(usdc + " USDC")}`;
2052
- }
2053
- } catch {
2054
- }
2103
+ await Promise.allSettled([
2104
+ client.agents.get(agentId).then((res) => {
2105
+ agentName = (res?.data ?? res)?.name;
2106
+ }),
2107
+ client.wallets.primary(agentId).then(async (primary) => {
2108
+ const w = primary?.data ?? primary;
2109
+ if (w?.id) {
2110
+ const bal = await client.wallets.balance(w.id).catch(() => null);
2111
+ const b = bal?.data ?? bal;
2112
+ const addr = `${w.address.slice(0, 6)}\u2026${w.address.slice(-4)}`;
2113
+ const usdc = b?.usdc ?? "0";
2114
+ walletLine = `${addr} ${c.bold(usdc + " USDC")}`;
2115
+ }
2116
+ })
2117
+ ]);
2055
2118
  console.log(`
2056
2119
  ${c.bold("Agent Commons Chat")}`);
2057
2120
  const headerRows = [
2058
- ["Agent", agentId],
2121
+ ["Agent", agentName ? `${agentName} ${c.dim(agentId)}` : agentId],
2059
2122
  ["Session", c.id(sessionId) + (isResume ? c.dim(" (resumed)") : c.dim(" (new)"))]
2060
2123
  ];
2061
2124
  if (walletLine) headerRows.push(["Wallet", walletLine]);
@@ -2068,9 +2131,12 @@ ${c.bold("Agent Commons Chat")}`);
2068
2131
  localToolsCfg = {
2069
2132
  rootDir,
2070
2133
  sessionId,
2134
+ agentId,
2135
+ agentName,
2071
2136
  appendLog: (record) => appendSessionLog(sessionId, record),
2072
2137
  permissions: /* @__PURE__ */ new Map()
2073
2138
  };
2139
+ installGitHook(rootDir, sessionId, agentId, agentName);
2074
2140
  appendSessionLog(sessionId, {
2075
2141
  type: "local_tools_enabled",
2076
2142
  rootDir,
@@ -2334,10 +2400,15 @@ ${sym.fail} ${c.error(event.message ?? "Stream error")}`);
2334
2400
  rl.resume();
2335
2401
  rl.prompt();
2336
2402
  });
2403
+ const cleanup = () => {
2404
+ if (localToolsCfg) removeGitHook(localToolsCfg.rootDir);
2405
+ };
2337
2406
  rl.on("close", () => {
2407
+ cleanup();
2338
2408
  process.exit(0);
2339
2409
  });
2340
2410
  process.on("SIGINT", () => {
2411
+ cleanup();
2341
2412
  console.log(c.dim(`
2342
2413
  Session preserved. Resume with: agc chat --resume ${sessionId}`));
2343
2414
  process.exit(130);
@@ -3801,7 +3872,7 @@ async function pickAgentInteractively(action) {
3801
3872
  return agentId;
3802
3873
  }
3803
3874
  var program = new import_commander16.Command();
3804
- program.name("agc").description("Agent Commons CLI \u2014 interact with the Agent Commons platform").version("0.1.18", "-v, --version").action(async () => {
3875
+ program.name("agc").description("Agent Commons CLI \u2014 interact with the Agent Commons platform").version("0.2.0", "-v, --version").action(async () => {
3805
3876
  await interactiveMenu();
3806
3877
  });
3807
3878
  program.addCommand(loginCommand());
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-commons/cli",
3
- "version": "0.1.18",
3
+ "version": "0.2.0",
4
4
  "description": "Agent Commons CLI — chat, run, and manage agents from your terminal",
5
5
  "license": "MIT",
6
6
  "bin": {
@@ -16,7 +16,7 @@
16
16
  "commander": "^12.1.0",
17
17
  "ora": "^8.1.1",
18
18
  "pdf-parse": "^1.1.1",
19
- "@agent-commons/sdk": "0.1.13"
19
+ "@agent-commons/sdk": "0.2.0"
20
20
  },
21
21
  "devDependencies": {
22
22
  "@types/node": "^22.10.2",