@agent-commons/cli 0.1.17 → 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.
- package/dist/bin.js +314 -116
- 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.
|
|
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-
|
|
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-
|
|
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) {
|
|
@@ -1184,73 +1186,7 @@ ${sym.fail} ${c.error(event.message ?? event.type)}`);
|
|
|
1184
1186
|
|
|
1185
1187
|
// src/commands/run.ts
|
|
1186
1188
|
var import_commander7 = require("commander");
|
|
1187
|
-
function runCommand() {
|
|
1188
|
-
return new import_commander7.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>", "Session ID").option("--no-stream", "Disable streaming (wait for full response)").option("--json", "Output raw event stream as JSON lines").action(async (prompt2, opts) => {
|
|
1189
|
-
const cfg = loadConfig();
|
|
1190
|
-
const agentId = opts.agent ?? cfg.defaultAgentId;
|
|
1191
|
-
if (!agentId) {
|
|
1192
|
-
console.error(c.error("Specify --agent <agentId> or set defaultAgentId with `agc config set defaultAgentId <id>`"));
|
|
1193
|
-
process.exit(1);
|
|
1194
|
-
}
|
|
1195
|
-
const params = {
|
|
1196
|
-
agentId,
|
|
1197
|
-
sessionId: opts.session,
|
|
1198
|
-
messages: [{ role: "user", content: prompt2 }],
|
|
1199
|
-
...cfg.initiator && { initiatorId: cfg.initiator }
|
|
1200
|
-
};
|
|
1201
|
-
if (opts.noStream) {
|
|
1202
|
-
const spinner = spin("Running\u2026");
|
|
1203
|
-
try {
|
|
1204
|
-
const client = makeClient();
|
|
1205
|
-
const result = await client.run.once(params);
|
|
1206
|
-
spinner.stop();
|
|
1207
|
-
if (opts.json) return jsonOut(result);
|
|
1208
|
-
const text = result?.content ?? result?.text ?? result?.message ?? JSON.stringify(result);
|
|
1209
|
-
console.log(text);
|
|
1210
|
-
} catch (err) {
|
|
1211
|
-
spinner.stop();
|
|
1212
|
-
printError(err);
|
|
1213
|
-
process.exit(1);
|
|
1214
|
-
}
|
|
1215
|
-
return;
|
|
1216
|
-
}
|
|
1217
|
-
try {
|
|
1218
|
-
const client = makeClient();
|
|
1219
|
-
let hasOutput = false;
|
|
1220
|
-
for await (const event of client.agents.stream(params)) {
|
|
1221
|
-
if (opts.json) {
|
|
1222
|
-
console.log(JSON.stringify(event));
|
|
1223
|
-
continue;
|
|
1224
|
-
}
|
|
1225
|
-
if (event.type === "token") {
|
|
1226
|
-
process.stdout.write(event.content ?? "");
|
|
1227
|
-
hasOutput = true;
|
|
1228
|
-
} else if (event.type === "final") {
|
|
1229
|
-
if (hasOutput) process.stdout.write("\n");
|
|
1230
|
-
const e = event;
|
|
1231
|
-
if (e.content && !hasOutput) console.log(e.content);
|
|
1232
|
-
break;
|
|
1233
|
-
} else if (event.type === "error") {
|
|
1234
|
-
if (hasOutput) process.stdout.write("\n");
|
|
1235
|
-
console.error(`
|
|
1236
|
-
${sym.fail} ${c.error(event.message ?? "Error")}`);
|
|
1237
|
-
process.exit(1);
|
|
1238
|
-
}
|
|
1239
|
-
}
|
|
1240
|
-
if (hasOutput && !opts.json) process.stdout.write("\n");
|
|
1241
|
-
} catch (err) {
|
|
1242
|
-
printError(err);
|
|
1243
|
-
process.exit(1);
|
|
1244
|
-
}
|
|
1245
|
-
});
|
|
1246
|
-
}
|
|
1247
|
-
|
|
1248
|
-
// src/commands/chat.ts
|
|
1249
|
-
var import_commander8 = require("commander");
|
|
1250
1189
|
var readline3 = __toESM(require("readline"));
|
|
1251
|
-
var import_fs4 = require("fs");
|
|
1252
|
-
var import_path4 = require("path");
|
|
1253
|
-
var import_os3 = require("os");
|
|
1254
1190
|
|
|
1255
1191
|
// src/local-tools.ts
|
|
1256
1192
|
var import_fs3 = require("fs");
|
|
@@ -1310,7 +1246,7 @@ function readFileForContext(rootDir, filePath) {
|
|
|
1310
1246
|
return `[error reading file: ${err?.message}]`;
|
|
1311
1247
|
}
|
|
1312
1248
|
}
|
|
1313
|
-
function buildLocalToolsManifest(rootDir, snapshot, fileContextBlocks = []) {
|
|
1249
|
+
function buildLocalToolsManifest(rootDir, snapshot, fileContextBlocks = [], autoApprove = false) {
|
|
1314
1250
|
const fileSection = fileContextBlocks.length ? `
|
|
1315
1251
|
### File contents included in this turn
|
|
1316
1252
|
|
|
@@ -1333,10 +1269,12 @@ ${fileSection}
|
|
|
1333
1269
|
### MANDATORY RULES \u2014 READ CAREFULLY
|
|
1334
1270
|
|
|
1335
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.
|
|
1336
|
-
2. **
|
|
1337
|
-
3. **
|
|
1338
|
-
4. **
|
|
1339
|
-
5. **
|
|
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\`.
|
|
1340
1278
|
|
|
1341
1279
|
### Available CLI tools
|
|
1342
1280
|
|
|
@@ -1369,12 +1307,12 @@ ${fileSection}
|
|
|
1369
1307
|
|
|
1370
1308
|
For long commands like \`npx create-next-app@latest my-app --yes\`:
|
|
1371
1309
|
|
|
1372
|
-
1. Call \`cli_start_process\` \u2014 returns \`{processId, status: "running"}\` immediately.
|
|
1373
|
-
2. Call \`cli_wait_for_process\` with \`{"processId": "...", "wait_seconds": 60}
|
|
1374
|
-
3. Repeat step 2 until \`status\` is \`"done"\` or \`"error"
|
|
1375
|
-
4.
|
|
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.
|
|
1376
1314
|
|
|
1377
|
-
|
|
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.
|
|
1378
1316
|
|
|
1379
1317
|
### Example \u2014 scaffolding a Next.js project
|
|
1380
1318
|
|
|
@@ -1382,18 +1320,14 @@ Never hold the user in silence. Between each \`cli_wait_for_process\` call, tell
|
|
|
1382
1320
|
cli_start_process: {"command": "npx", "args": ["create-next-app@latest", "my-app", "--yes"], "cwd": "Desktop"}
|
|
1383
1321
|
\u2192 {processId: "proc_1a2b", status: "running"}
|
|
1384
1322
|
|
|
1385
|
-
Tell user: "Started! Installing dependencies, this takes a minute or two. Checking in 60s\u2026"
|
|
1386
|
-
|
|
1387
1323
|
cli_wait_for_process: {"processId": "proc_1a2b", "wait_seconds": 60}
|
|
1388
1324
|
\u2192 {status: "running", elapsedSec: 60, stdout: "Creating project...
|
|
1389
1325
|
Installing packages\u2026"}
|
|
1390
1326
|
|
|
1391
|
-
Tell user: "Still installing \u2014 here's output so far: [stdout]. Checking again\u2026"
|
|
1392
|
-
|
|
1393
1327
|
cli_wait_for_process: {"processId": "proc_1a2b", "wait_seconds": 60}
|
|
1394
1328
|
\u2192 {status: "done", exitCode: 0, elapsedSec: 93, stdout: "Success! Created my-app"}
|
|
1395
1329
|
|
|
1396
|
-
|
|
1330
|
+
Continue by running the requested checks and opening/inspecting the app when the assignment requires it.
|
|
1397
1331
|
\`\`\`
|
|
1398
1332
|
`;
|
|
1399
1333
|
}
|
|
@@ -1408,6 +1342,72 @@ function extractToolCall(text) {
|
|
|
1408
1342
|
}
|
|
1409
1343
|
return null;
|
|
1410
1344
|
}
|
|
1345
|
+
function injectAgcTrailer(command, args, agentId, agentName) {
|
|
1346
|
+
if (command !== "git") return args;
|
|
1347
|
+
if (!args.some((a) => a === "commit")) return args;
|
|
1348
|
+
if (args.some((a) => a.includes("Co-Authored-By: agc"))) return args;
|
|
1349
|
+
const identity = agentName ? `${agentName} (agc)` : agentId ? `agc/${agentId}` : "agc agent";
|
|
1350
|
+
return [...args, "--trailer", `Co-Authored-By: ${identity} <agc-agent@users.noreply.github.com>`];
|
|
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
|
+
}
|
|
1411
1411
|
function safePath(root, userPath) {
|
|
1412
1412
|
const abs = (0, import_path3.resolve)(root, userPath);
|
|
1413
1413
|
const rel = (0, import_path3.relative)(root, abs);
|
|
@@ -1434,6 +1434,7 @@ function assertNotSensitive(abs) {
|
|
|
1434
1434
|
}
|
|
1435
1435
|
}
|
|
1436
1436
|
async function confirm(message, config, permissionKey) {
|
|
1437
|
+
if (config.autoApprove) return true;
|
|
1437
1438
|
const cached = config.permissions.get(permissionKey);
|
|
1438
1439
|
if (cached === "allow") return true;
|
|
1439
1440
|
if (cached === "deny") return false;
|
|
@@ -1612,7 +1613,8 @@ async function toolRunCommand(args, cfg) {
|
|
|
1612
1613
|
if (!command || typeof command !== "string") throw new Error('run_command requires a "command" string');
|
|
1613
1614
|
if (!Array.isArray(cmdArgs)) throw new Error('"args" must be an array of strings');
|
|
1614
1615
|
const workDir = cwd ? safePath(cfg.rootDir, cwd) : cfg.rootDir;
|
|
1615
|
-
const
|
|
1616
|
+
const injectedArgs = injectAgcTrailer(command, cmdArgs, cfg.agentId, cfg.agentName);
|
|
1617
|
+
const preview = [command, ...injectedArgs].join(" ");
|
|
1616
1618
|
const timeoutMs = Math.min((typeof timeout_seconds === "number" ? timeout_seconds : 120) * 1e3, 3e5);
|
|
1617
1619
|
const ok = await confirm(
|
|
1618
1620
|
`Agent wants to run: \x1B[1m${preview}\x1B[0m
|
|
@@ -1623,7 +1625,7 @@ async function toolRunCommand(args, cfg) {
|
|
|
1623
1625
|
if (!ok) return "User denied command execution.";
|
|
1624
1626
|
if (interactive) {
|
|
1625
1627
|
return new Promise((resolve2) => {
|
|
1626
|
-
const child = (0, import_child_process2.spawn)(command,
|
|
1628
|
+
const child = (0, import_child_process2.spawn)(command, injectedArgs.map(String), { cwd: workDir, stdio: "inherit" });
|
|
1627
1629
|
const timer = setTimeout(() => {
|
|
1628
1630
|
child.kill();
|
|
1629
1631
|
resolve2(`(command timed out after ${timeoutMs / 1e3}s)`);
|
|
@@ -1639,7 +1641,7 @@ async function toolRunCommand(args, cfg) {
|
|
|
1639
1641
|
});
|
|
1640
1642
|
}
|
|
1641
1643
|
return new Promise((resolve2) => {
|
|
1642
|
-
(0, import_child_process2.execFile)(command,
|
|
1644
|
+
(0, import_child_process2.execFile)(command, injectedArgs.map(String), { cwd: workDir, timeout: timeoutMs, maxBuffer: 1024 * 1024 }, (err, stdout, stderr) => {
|
|
1643
1645
|
const out = [stdout, stderr].filter(Boolean).join("\n--- stderr ---\n");
|
|
1644
1646
|
if (err && !out) return resolve2(`Error: ${err.message}`);
|
|
1645
1647
|
resolve2(out || "(no output)");
|
|
@@ -1814,7 +1816,191 @@ async function runLocalTool(call, cfg) {
|
|
|
1814
1816
|
return result;
|
|
1815
1817
|
}
|
|
1816
1818
|
|
|
1819
|
+
// src/commands/run.ts
|
|
1820
|
+
function runCommand() {
|
|
1821
|
+
return new import_commander7.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("--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) => {
|
|
1822
|
+
const cfg = loadConfig();
|
|
1823
|
+
const agentId = opts.agent ?? cfg.defaultAgentId;
|
|
1824
|
+
if (!agentId) {
|
|
1825
|
+
console.error(c.error("Specify --agent <agentId> or set defaultAgentId with `agc config set defaultAgentId <id>`"));
|
|
1826
|
+
process.exit(1);
|
|
1827
|
+
}
|
|
1828
|
+
if (opts.session && opts.newSession) {
|
|
1829
|
+
console.error(c.error("Cannot use --session and --new-session together."));
|
|
1830
|
+
process.exit(1);
|
|
1831
|
+
}
|
|
1832
|
+
const client = makeClient();
|
|
1833
|
+
let sessionId = opts.session;
|
|
1834
|
+
if (opts.session) {
|
|
1835
|
+
const spinner = spin("Loading session\u2026");
|
|
1836
|
+
try {
|
|
1837
|
+
await client.sessions.get(opts.session);
|
|
1838
|
+
spinner.stop();
|
|
1839
|
+
} catch {
|
|
1840
|
+
spinner.stop();
|
|
1841
|
+
console.error(c.error(`Session "${opts.session}" not found.`));
|
|
1842
|
+
process.exit(1);
|
|
1843
|
+
}
|
|
1844
|
+
}
|
|
1845
|
+
if (opts.newSession) {
|
|
1846
|
+
const spinner = spin("Creating session\u2026");
|
|
1847
|
+
try {
|
|
1848
|
+
const res = await client.sessions.create({
|
|
1849
|
+
agentId,
|
|
1850
|
+
initiator: cfg.initiator ?? "",
|
|
1851
|
+
title: `agc run ${(/* @__PURE__ */ new Date()).toISOString().slice(0, 16)}`,
|
|
1852
|
+
source: "cli"
|
|
1853
|
+
});
|
|
1854
|
+
const session = res?.data ?? res;
|
|
1855
|
+
sessionId = session.sessionId;
|
|
1856
|
+
spinner.stop();
|
|
1857
|
+
} catch (err) {
|
|
1858
|
+
spinner.stop();
|
|
1859
|
+
printError(err);
|
|
1860
|
+
process.exit(1);
|
|
1861
|
+
}
|
|
1862
|
+
}
|
|
1863
|
+
const localEnabled = opts.yes || opts.local;
|
|
1864
|
+
const autoApprove = !!opts.yes;
|
|
1865
|
+
let localToolsCfg = null;
|
|
1866
|
+
let cliContext;
|
|
1867
|
+
if (localEnabled) {
|
|
1868
|
+
const rootDir = process.cwd();
|
|
1869
|
+
localToolsCfg = {
|
|
1870
|
+
rootDir,
|
|
1871
|
+
sessionId: sessionId ?? "run",
|
|
1872
|
+
appendLog: () => {
|
|
1873
|
+
},
|
|
1874
|
+
permissions: /* @__PURE__ */ new Map(),
|
|
1875
|
+
agentId,
|
|
1876
|
+
autoApprove
|
|
1877
|
+
};
|
|
1878
|
+
const snapshot = buildDirSnapshot(rootDir, 2);
|
|
1879
|
+
cliContext = buildLocalToolsManifest(rootDir, snapshot, [], autoApprove);
|
|
1880
|
+
}
|
|
1881
|
+
if (!opts.json) {
|
|
1882
|
+
const rows = [];
|
|
1883
|
+
if (sessionId) {
|
|
1884
|
+
const label = opts.newSession ? `${c.id(sessionId)}${c.dim(" (new)")}` : `${c.id(sessionId)}${c.dim(" (resumed)")}`;
|
|
1885
|
+
rows.push(["Session", label]);
|
|
1886
|
+
}
|
|
1887
|
+
if (localEnabled) {
|
|
1888
|
+
rows.push(["Local tools", autoApprove ? c.warn("enabled (auto-approve on)") : c.success("enabled")]);
|
|
1889
|
+
}
|
|
1890
|
+
if (rows.length) {
|
|
1891
|
+
detail(rows);
|
|
1892
|
+
console.log();
|
|
1893
|
+
}
|
|
1894
|
+
}
|
|
1895
|
+
const params = {
|
|
1896
|
+
agentId,
|
|
1897
|
+
sessionId,
|
|
1898
|
+
messages: [{ role: "user", content: prompt2 }],
|
|
1899
|
+
...cfg.initiator && { initiatorId: cfg.initiator },
|
|
1900
|
+
...cliContext && { cliContext }
|
|
1901
|
+
};
|
|
1902
|
+
if (opts.noStream && !localEnabled) {
|
|
1903
|
+
const spinner = spin("Running\u2026");
|
|
1904
|
+
try {
|
|
1905
|
+
const result = await client.run.once(params);
|
|
1906
|
+
spinner.stop();
|
|
1907
|
+
if (opts.json) return jsonOut(result);
|
|
1908
|
+
const text = result?.content ?? result?.text ?? result?.message ?? JSON.stringify(result);
|
|
1909
|
+
console.log(text);
|
|
1910
|
+
if (sessionId) console.log(c.dim(`
|
|
1911
|
+
Session: ${sessionId} (resume with: agc run --session ${sessionId} "<prompt>")`));
|
|
1912
|
+
} catch (err) {
|
|
1913
|
+
spinner.stop();
|
|
1914
|
+
printError(err);
|
|
1915
|
+
process.exit(1);
|
|
1916
|
+
}
|
|
1917
|
+
return;
|
|
1918
|
+
}
|
|
1919
|
+
try {
|
|
1920
|
+
let hasOutput = false;
|
|
1921
|
+
let toolStartMs = 0;
|
|
1922
|
+
let lastToolName = "";
|
|
1923
|
+
for await (const event of client.agents.stream(params)) {
|
|
1924
|
+
if (opts.json) {
|
|
1925
|
+
console.log(JSON.stringify(event));
|
|
1926
|
+
continue;
|
|
1927
|
+
}
|
|
1928
|
+
if (event.type === "token") {
|
|
1929
|
+
process.stdout.write(event.content ?? "");
|
|
1930
|
+
hasOutput = true;
|
|
1931
|
+
} else if (event.type === "cli_tool_request" && localToolsCfg) {
|
|
1932
|
+
const { requestId, tool: toolName, args } = event;
|
|
1933
|
+
const displayName = String(toolName).replace("cli_", "");
|
|
1934
|
+
if (hasOutput) {
|
|
1935
|
+
process.stdout.write("\n");
|
|
1936
|
+
hasOutput = false;
|
|
1937
|
+
}
|
|
1938
|
+
process.stdout.write(` ${c.dim("\u2500")} ${c.bold(displayName)}`);
|
|
1939
|
+
const startMs = Date.now();
|
|
1940
|
+
let result;
|
|
1941
|
+
let toolOk = true;
|
|
1942
|
+
try {
|
|
1943
|
+
result = await runLocalTool({ tool: displayName, args: args ?? {} }, localToolsCfg);
|
|
1944
|
+
} catch (err) {
|
|
1945
|
+
result = `Error: ${err?.message ?? String(err)}`;
|
|
1946
|
+
toolOk = false;
|
|
1947
|
+
}
|
|
1948
|
+
const elapsed = ((Date.now() - startMs) / 1e3).toFixed(1);
|
|
1949
|
+
readline3.cursorTo(process.stdout, 0);
|
|
1950
|
+
readline3.clearLine(process.stdout, 0);
|
|
1951
|
+
process.stdout.write(` ${c.dim("\u2500")} ${c.bold(displayName)} ${toolOk ? sym.ok : sym.fail} ${c.dim("(" + elapsed + "s)")}
|
|
1952
|
+
`);
|
|
1953
|
+
try {
|
|
1954
|
+
await fetch(`${cfg.apiUrl}/v1/agents/cli-tool-result`, {
|
|
1955
|
+
method: "POST",
|
|
1956
|
+
headers: { "Content-Type": "application/json", "Authorization": `Bearer ${cfg.apiKey}` },
|
|
1957
|
+
body: JSON.stringify({ requestId, result })
|
|
1958
|
+
});
|
|
1959
|
+
} catch {
|
|
1960
|
+
}
|
|
1961
|
+
} else if (event.type === "toolStart") {
|
|
1962
|
+
lastToolName = event.toolName ?? "";
|
|
1963
|
+
toolStartMs = Date.now();
|
|
1964
|
+
if (hasOutput) {
|
|
1965
|
+
process.stdout.write("\n");
|
|
1966
|
+
hasOutput = false;
|
|
1967
|
+
}
|
|
1968
|
+
process.stdout.write(` ${c.dim("\u2500")} ${c.bold(lastToolName)}`);
|
|
1969
|
+
} else if (event.type === "toolEnd") {
|
|
1970
|
+
const elapsed = ((Date.now() - toolStartMs) / 1e3).toFixed(1);
|
|
1971
|
+
readline3.cursorTo(process.stdout, 0);
|
|
1972
|
+
readline3.clearLine(process.stdout, 0);
|
|
1973
|
+
process.stdout.write(` ${c.dim("\u2500")} ${c.bold(lastToolName)} ${sym.ok} ${c.dim("(" + elapsed + "s)")}
|
|
1974
|
+
`);
|
|
1975
|
+
} else if (event.type === "final") {
|
|
1976
|
+
if (hasOutput) process.stdout.write("\n");
|
|
1977
|
+
const e = event;
|
|
1978
|
+
const finalText = e.content ?? e.payload?.content ?? e.payload?.text ?? e.payload?.message;
|
|
1979
|
+
if (finalText && !hasOutput) console.log(finalText);
|
|
1980
|
+
if (sessionId) console.log(c.dim(`
|
|
1981
|
+
Session: ${sessionId} (resume with: agc run --session ${sessionId} "<prompt>")`));
|
|
1982
|
+
break;
|
|
1983
|
+
} else if (event.type === "error") {
|
|
1984
|
+
if (hasOutput) process.stdout.write("\n");
|
|
1985
|
+
console.error(`
|
|
1986
|
+
${sym.fail} ${c.error(event.message ?? "Error")}`);
|
|
1987
|
+
process.exit(1);
|
|
1988
|
+
}
|
|
1989
|
+
}
|
|
1990
|
+
if (hasOutput && !opts.json) process.stdout.write("\n");
|
|
1991
|
+
} catch (err) {
|
|
1992
|
+
printError(err);
|
|
1993
|
+
process.exit(1);
|
|
1994
|
+
}
|
|
1995
|
+
});
|
|
1996
|
+
}
|
|
1997
|
+
|
|
1817
1998
|
// src/commands/chat.ts
|
|
1999
|
+
var import_commander8 = require("commander");
|
|
2000
|
+
var readline4 = __toESM(require("readline"));
|
|
2001
|
+
var import_fs4 = require("fs");
|
|
2002
|
+
var import_path4 = require("path");
|
|
2003
|
+
var import_os3 = require("os");
|
|
1818
2004
|
var SESSIONS_DIR = (0, import_path4.join)((0, import_os3.homedir)(), ".agc", "sessions");
|
|
1819
2005
|
function ensureSessionsDir() {
|
|
1820
2006
|
if (!(0, import_fs4.existsSync)(SESSIONS_DIR)) (0, import_fs4.mkdirSync)(SESSIONS_DIR, { recursive: true });
|
|
@@ -1912,23 +2098,27 @@ function chatCommand() {
|
|
|
1912
2098
|
process.exit(1);
|
|
1913
2099
|
}
|
|
1914
2100
|
}
|
|
2101
|
+
let agentName;
|
|
1915
2102
|
let walletLine = "";
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
const
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
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
|
+
]);
|
|
1928
2118
|
console.log(`
|
|
1929
2119
|
${c.bold("Agent Commons Chat")}`);
|
|
1930
2120
|
const headerRows = [
|
|
1931
|
-
["Agent", agentId],
|
|
2121
|
+
["Agent", agentName ? `${agentName} ${c.dim(agentId)}` : agentId],
|
|
1932
2122
|
["Session", c.id(sessionId) + (isResume ? c.dim(" (resumed)") : c.dim(" (new)"))]
|
|
1933
2123
|
];
|
|
1934
2124
|
if (walletLine) headerRows.push(["Wallet", walletLine]);
|
|
@@ -1941,9 +2131,12 @@ ${c.bold("Agent Commons Chat")}`);
|
|
|
1941
2131
|
localToolsCfg = {
|
|
1942
2132
|
rootDir,
|
|
1943
2133
|
sessionId,
|
|
2134
|
+
agentId,
|
|
2135
|
+
agentName,
|
|
1944
2136
|
appendLog: (record) => appendSessionLog(sessionId, record),
|
|
1945
2137
|
permissions: /* @__PURE__ */ new Map()
|
|
1946
2138
|
};
|
|
2139
|
+
installGitHook(rootDir, sessionId, agentId, agentName);
|
|
1947
2140
|
appendSessionLog(sessionId, {
|
|
1948
2141
|
type: "local_tools_enabled",
|
|
1949
2142
|
rootDir,
|
|
@@ -1951,7 +2144,7 @@ ${c.bold("Agent Commons Chat")}`);
|
|
|
1951
2144
|
});
|
|
1952
2145
|
}
|
|
1953
2146
|
console.log(c.dim("\nType your message and press Enter. Type /help for commands.\n"));
|
|
1954
|
-
const rl =
|
|
2147
|
+
const rl = readline4.createInterface({
|
|
1955
2148
|
input: process.stdin,
|
|
1956
2149
|
output: process.stdout,
|
|
1957
2150
|
terminal: true,
|
|
@@ -2094,7 +2287,7 @@ ${sym.fail} ${c.error(err.message ?? String(err))}`);
|
|
|
2094
2287
|
if (isWaiting) {
|
|
2095
2288
|
elapsedInterval = setInterval(() => {
|
|
2096
2289
|
elapsedSec++;
|
|
2097
|
-
|
|
2290
|
+
readline4.cursorTo(process.stdout, 0);
|
|
2098
2291
|
process.stdout.write(` ${c.dim("\u2500")} ${c.bold(displayName)}${argStr ? " " + c.dim(argStr) : ""} ${c.dim(elapsedSec + "s\u2026")}`);
|
|
2099
2292
|
}, 1e3);
|
|
2100
2293
|
}
|
|
@@ -2109,8 +2302,8 @@ ${sym.fail} ${c.error(err.message ?? String(err))}`);
|
|
|
2109
2302
|
if (elapsedInterval) clearInterval(elapsedInterval);
|
|
2110
2303
|
const elapsed = ((Date.now() - startMs) / 1e3).toFixed(1);
|
|
2111
2304
|
const preview = toolOk ? toolResultPreview(displayName, result) : "";
|
|
2112
|
-
|
|
2113
|
-
|
|
2305
|
+
readline4.cursorTo(process.stdout, 0);
|
|
2306
|
+
readline4.clearLine(process.stdout, 0);
|
|
2114
2307
|
const statusIcon = toolOk ? sym.ok : sym.fail;
|
|
2115
2308
|
const previewPart = preview ? ` ${c.dim(preview)}` : "";
|
|
2116
2309
|
process.stdout.write(` ${c.dim("\u2500")} ${c.bold(displayName)}${argStr ? " " + c.dim(argStr) : ""} ${statusIcon}${previewPart} ${c.dim("(" + elapsed + "s)")}
|
|
@@ -2144,8 +2337,8 @@ ${sym.fail} ${c.error(err.message ?? String(err))}`);
|
|
|
2144
2337
|
hasOutput = false;
|
|
2145
2338
|
} else if (event.type === "toolEnd") {
|
|
2146
2339
|
const elapsed = ((Date.now() - toolStartMs) / 1e3).toFixed(1);
|
|
2147
|
-
|
|
2148
|
-
|
|
2340
|
+
readline4.cursorTo(process.stdout, 0);
|
|
2341
|
+
readline4.clearLine(process.stdout, 0);
|
|
2149
2342
|
process.stdout.write(` ${c.dim("\u2500")} ${c.bold(lastToolName)} ${sym.ok} ${c.dim("(" + elapsed + "s)")}
|
|
2150
2343
|
`);
|
|
2151
2344
|
process.stdout.write(c.primary("agent") + c.dim(" \u203A "));
|
|
@@ -2202,15 +2395,20 @@ ${sym.fail} ${c.error(event.message ?? "Stream error")}`);
|
|
|
2202
2395
|
}
|
|
2203
2396
|
}
|
|
2204
2397
|
console.log();
|
|
2205
|
-
|
|
2206
|
-
|
|
2398
|
+
readline4.cursorTo(process.stdout, 0);
|
|
2399
|
+
readline4.clearLine(process.stdout, 0);
|
|
2207
2400
|
rl.resume();
|
|
2208
2401
|
rl.prompt();
|
|
2209
2402
|
});
|
|
2403
|
+
const cleanup = () => {
|
|
2404
|
+
if (localToolsCfg) removeGitHook(localToolsCfg.rootDir);
|
|
2405
|
+
};
|
|
2210
2406
|
rl.on("close", () => {
|
|
2407
|
+
cleanup();
|
|
2211
2408
|
process.exit(0);
|
|
2212
2409
|
});
|
|
2213
2410
|
process.on("SIGINT", () => {
|
|
2411
|
+
cleanup();
|
|
2214
2412
|
console.log(c.dim(`
|
|
2215
2413
|
Session preserved. Resume with: agc chat --resume ${sessionId}`));
|
|
2216
2414
|
process.exit(130);
|
|
@@ -2241,8 +2439,8 @@ async function handleLocalToolLoop(agentText, cfg, client, agentId, sessionId, a
|
|
|
2241
2439
|
}
|
|
2242
2440
|
const elapsed = ((Date.now() - startMs) / 1e3).toFixed(1);
|
|
2243
2441
|
const preview = toolOk ? toolResultPreview(toolCall.tool, result) : "";
|
|
2244
|
-
|
|
2245
|
-
|
|
2442
|
+
readline4.cursorTo(process.stdout, 0);
|
|
2443
|
+
readline4.clearLine(process.stdout, 0);
|
|
2246
2444
|
const previewPart = preview ? ` ${c.dim(preview)}` : "";
|
|
2247
2445
|
process.stdout.write(` ${c.dim("\u2500")} ${c.bold(toolCall.tool)}${argStr ? " " + c.dim(argStr) : ""} ${toolOk ? sym.ok : sym.fail}${previewPart} ${c.dim("(" + elapsed + "s)")}
|
|
2248
2446
|
`);
|
|
@@ -2278,8 +2476,8 @@ ${result}
|
|
|
2278
2476
|
process.stdout.write(` ${c.dim("\u2500")} ${c.bold(loopToolName)}`);
|
|
2279
2477
|
} else if (evt.type === "toolEnd") {
|
|
2280
2478
|
const elapsed2 = ((Date.now() - loopToolStartMs) / 1e3).toFixed(1);
|
|
2281
|
-
|
|
2282
|
-
|
|
2479
|
+
readline4.cursorTo(process.stdout, 0);
|
|
2480
|
+
readline4.clearLine(process.stdout, 0);
|
|
2283
2481
|
process.stdout.write(` ${c.dim("\u2500")} ${c.bold(loopToolName)} ${sym.ok} ${c.dim("(" + elapsed2 + "s)")}
|
|
2284
2482
|
`);
|
|
2285
2483
|
process.stdout.write(c.primary("agent") + c.dim(" \u203A "));
|
|
@@ -2917,8 +3115,8 @@ function skillsCommand() {
|
|
|
2917
3115
|
});
|
|
2918
3116
|
cmd.command("delete <slug>").description("Permanently delete a skill").option("--yes", "Skip confirmation prompt").option("--json", "Output result as JSON").action(async (slug, opts) => {
|
|
2919
3117
|
if (!opts.yes) {
|
|
2920
|
-
const
|
|
2921
|
-
const rl =
|
|
3118
|
+
const readline5 = await import("readline");
|
|
3119
|
+
const rl = readline5.createInterface({ input: process.stdin, output: process.stdout });
|
|
2922
3120
|
const answer = await new Promise(
|
|
2923
3121
|
(resolve2) => rl.question(c.warn(`Delete skill "${slug}"? This cannot be undone. [y/N] `), resolve2)
|
|
2924
3122
|
);
|
|
@@ -3674,7 +3872,7 @@ async function pickAgentInteractively(action) {
|
|
|
3674
3872
|
return agentId;
|
|
3675
3873
|
}
|
|
3676
3874
|
var program = new import_commander16.Command();
|
|
3677
|
-
program.name("agc").description("Agent Commons CLI \u2014 interact with the Agent Commons platform").version("0.
|
|
3875
|
+
program.name("agc").description("Agent Commons CLI \u2014 interact with the Agent Commons platform").version("0.2.0", "-v, --version").action(async () => {
|
|
3678
3876
|
await interactiveMenu();
|
|
3679
3877
|
});
|
|
3680
3878
|
program.addCommand(loginCommand());
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agent-commons/cli",
|
|
3
|
-
"version": "0.
|
|
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.
|
|
19
|
+
"@agent-commons/sdk": "0.2.0"
|
|
20
20
|
},
|
|
21
21
|
"devDependencies": {
|
|
22
22
|
"@types/node": "^22.10.2",
|