@agentvalet/register 0.4.5 → 0.4.7

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/index.js +218 -22
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/index.ts
4
- import { Command } from "commander";
5
- import chalk8 from "chalk";
4
+ import { Command as Command4 } from "commander";
5
+ import chalk11 from "chalk";
6
6
 
7
7
  // src/wizard.ts
8
8
  import prompts from "prompts";
@@ -1374,12 +1374,205 @@ function showCredentials(config) {
1374
1374
  console.log("");
1375
1375
  }
1376
1376
 
1377
+ // src/commands/list.ts
1378
+ import { Command } from "commander";
1379
+ import chalk8 from "chalk";
1380
+
1381
+ // src/lib/api.ts
1382
+ async function request(path7, options) {
1383
+ const config = getStoredConfig();
1384
+ const token = config.cliToken;
1385
+ if (!token) {
1386
+ throw new Error(
1387
+ "Not authenticated.\nRun 'npx @agentvalet/register' to register and authenticate."
1388
+ );
1389
+ }
1390
+ const proxyUrl = config.proxyUrl ?? "https://api.agentvalet.ai";
1391
+ const response = await fetch(`${proxyUrl}/functions/v1${path7}`, {
1392
+ method: options.method,
1393
+ headers: {
1394
+ "Authorization": `Bearer ${token}`,
1395
+ "Content-Type": "application/json"
1396
+ },
1397
+ body: options.body ? JSON.stringify(options.body) : void 0
1398
+ });
1399
+ if (!response.ok) {
1400
+ const text = await response.text();
1401
+ throw new Error(`API error ${response.status}: ${text}`);
1402
+ }
1403
+ return response.json();
1404
+ }
1405
+ async function revokeAgent(agentId) {
1406
+ return request("/revoke-agent", { method: "POST", body: { agentId } });
1407
+ }
1408
+ async function listAgents() {
1409
+ return request("/list-agents", { method: "GET" });
1410
+ }
1411
+
1412
+ // src/commands/list.ts
1413
+ function listCommand() {
1414
+ return new Command("list").description("List all registered agents").action(async () => {
1415
+ const config = getStoredConfig();
1416
+ if (!config.cliToken) {
1417
+ process.stderr.write(
1418
+ chalk8.red("\n \u2717 No agent registered.\n") + chalk8.dim(" Run the following command first:\n\n npx @agentvalet/register\n\n")
1419
+ );
1420
+ process.exit(1);
1421
+ }
1422
+ try {
1423
+ const agents = await listAgents();
1424
+ if (agents.length === 0) {
1425
+ console.log("No agents registered yet. Run: npx @agentvalet/register");
1426
+ return;
1427
+ }
1428
+ const maxNameLen = Math.max(...agents.map((a) => a.name.length), 4);
1429
+ const header = `${"ID".padEnd(30)} ${"NAME".padEnd(maxNameLen)} STATUS`;
1430
+ console.log(header);
1431
+ console.log("-".repeat(header.length));
1432
+ for (const agent of agents) {
1433
+ const status = agent.status === "active" ? chalk8.green("\u2713 active") : agent.status === "suspended" ? chalk8.yellow("\u26A0 suspended") : chalk8.red("\u2717 revoked");
1434
+ console.log(`${agent.id.padEnd(30)} ${agent.name.padEnd(maxNameLen)} ${status}`);
1435
+ }
1436
+ } catch (err) {
1437
+ console.error(chalk8.red(String(err)));
1438
+ process.exit(1);
1439
+ }
1440
+ });
1441
+ }
1442
+
1443
+ // src/commands/revoke.ts
1444
+ import { Command as Command2 } from "commander";
1445
+ import chalk9 from "chalk";
1446
+ import * as readline from "readline";
1447
+ function revokeCommand() {
1448
+ return new Command2("revoke").description("Revoke an agent (cascades to all child agents)").requiredOption("--agent-id <agentId>", "Agent ID to revoke (agt_...)").action(async (opts) => {
1449
+ const config = getStoredConfig();
1450
+ if (!config.cliToken) {
1451
+ process.stderr.write(
1452
+ chalk9.red("\n \u2717 No agent registered.\n") + chalk9.dim(" Run the following command first:\n\n npx @agentvalet/register\n\n")
1453
+ );
1454
+ process.exit(1);
1455
+ }
1456
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
1457
+ const confirmed = await new Promise((resolve4) => {
1458
+ rl.question(
1459
+ chalk9.yellow(`Revoke ${opts.agentId}? This cascades to all child agents and cannot be undone. (y/N) `),
1460
+ (ans) => {
1461
+ rl.close();
1462
+ resolve4(ans.trim().toLowerCase() === "y");
1463
+ }
1464
+ );
1465
+ });
1466
+ if (!confirmed) {
1467
+ console.log("Cancelled.");
1468
+ return;
1469
+ }
1470
+ try {
1471
+ const result = await revokeAgent(opts.agentId);
1472
+ console.log(chalk9.green(`Revoked ${result.revokedAgentIds.length} agent(s)`));
1473
+ if (result.revokedAgentIds.length > 1) {
1474
+ console.log("Revoked:", result.revokedAgentIds.join(", "));
1475
+ }
1476
+ } catch (err) {
1477
+ console.error(chalk9.red(String(err)));
1478
+ process.exit(1);
1479
+ }
1480
+ });
1481
+ }
1482
+
1483
+ // src/commands/inject.ts
1484
+ import { Command as Command3 } from "commander";
1485
+ import chalk10 from "chalk";
1486
+ import { readFile as readFile5 } from "fs/promises";
1487
+
1488
+ // src/lib/claude-config.ts
1489
+ import { homedir } from "os";
1490
+ import { join as join2 } from "path";
1491
+ import { readFile as readFile3, writeFile as writeFile6, mkdir as mkdir4, access } from "fs/promises";
1492
+ var CLAUDE_CONFIG_PATH = join2(homedir(), ".claude", "config");
1493
+ async function writeKeyToClaudeConfig(agentId, privateKeyPem) {
1494
+ let config = {};
1495
+ try {
1496
+ await access(CLAUDE_CONFIG_PATH);
1497
+ const raw = await readFile3(CLAUDE_CONFIG_PATH, "utf-8");
1498
+ config = JSON.parse(raw);
1499
+ } catch {
1500
+ }
1501
+ config.agent_keys = config.agent_keys ?? {};
1502
+ config.agent_keys[agentId] = Buffer.from(privateKeyPem).toString("base64");
1503
+ await mkdir4(join2(homedir(), ".claude"), { recursive: true });
1504
+ await writeFile6(CLAUDE_CONFIG_PATH, JSON.stringify(config, null, 2), "utf-8");
1505
+ }
1506
+
1507
+ // src/lib/env-writer.ts
1508
+ import { readFile as readFile4, writeFile as writeFile7, access as access2 } from "fs/promises";
1509
+ var ENV_VAR_NAME = (agentId) => `AGENTVALET_PRIVATE_KEY_${agentId.replace(/-/g, "_").toUpperCase()}`;
1510
+ async function writeKeyToEnvLocal(agentId, privateKeyPem) {
1511
+ const varName = ENV_VAR_NAME(agentId);
1512
+ const b64Key = Buffer.from(privateKeyPem).toString("base64");
1513
+ const line = `
1514
+ # AgentValet private key for ${agentId} (base64-encoded PEM)
1515
+ ${varName}=${b64Key}
1516
+ `;
1517
+ let existing = "";
1518
+ try {
1519
+ await access2(".env.local");
1520
+ existing = await readFile4(".env.local", "utf-8");
1521
+ } catch {
1522
+ }
1523
+ if (existing.includes(varName)) {
1524
+ const lines = existing.split("\n");
1525
+ const filtered = lines.filter((l) => !l.startsWith(`${varName}=`));
1526
+ await writeFile7(".env.local", filtered.join("\n") + line, "utf-8");
1527
+ } else {
1528
+ await writeFile7(".env.local", existing + line, "utf-8");
1529
+ }
1530
+ }
1531
+
1532
+ // src/commands/inject.ts
1533
+ function injectCommand() {
1534
+ return new Command3("inject").description("Inject agent private key into Claude Code config or .env.local").requiredOption("--agent-id <agentId>", "Agent ID (agt_...)").requiredOption("--key-file <path>", "Path to the private key PEM file").option("--target <target>", "Injection target: claude-code or env-local", "claude-code").action(async (opts) => {
1535
+ let privateKeyPem;
1536
+ try {
1537
+ privateKeyPem = await readFile5(opts.keyFile, "utf-8");
1538
+ } catch {
1539
+ console.error(chalk10.red(`Could not read key file: ${opts.keyFile}`));
1540
+ process.exit(1);
1541
+ }
1542
+ if (!privateKeyPem.includes("BEGIN PRIVATE KEY")) {
1543
+ console.error(chalk10.red("File does not appear to be a PEM private key"));
1544
+ process.exit(1);
1545
+ }
1546
+ try {
1547
+ if (opts.target === "claude-code") {
1548
+ await writeKeyToClaudeConfig(opts.agentId, privateKeyPem);
1549
+ console.log(chalk10.green("Key injected into ~/.claude/config"));
1550
+ } else if (opts.target === "env-local") {
1551
+ await writeKeyToEnvLocal(opts.agentId, privateKeyPem);
1552
+ console.log(chalk10.green("Key appended to .env.local"));
1553
+ } else {
1554
+ console.error(chalk10.red(`Unknown target: ${opts.target}. Use 'claude-code' or 'env-local'`));
1555
+ process.exit(1);
1556
+ }
1557
+ } catch (err) {
1558
+ console.error(chalk10.red(String(err)));
1559
+ process.exit(1);
1560
+ }
1561
+ if (opts.target === "env-local") {
1562
+ console.log(chalk10.dim("Add .env.local to .gitignore \u2014 do not commit private keys to git."));
1563
+ } else {
1564
+ console.log(chalk10.dim("The key is stored in ~/.claude/config \u2014 it is NOT committed to git."));
1565
+ }
1566
+ console.log(chalk10.green("Done. Your agent is ready to use."));
1567
+ });
1568
+ }
1569
+
1377
1570
  // src/index.ts
1378
1571
  function collectScope(value, previous) {
1379
1572
  return [...previous, value];
1380
1573
  }
1381
- var program = new Command();
1382
- program.name("agentvalet-register").description("Self-register an AI agent with AgentValet").version("0.4.5").option("--owner <uuid>", "Owner ID (or set AGENTVALET_OWNER env var)").option("--name <name>", "Agent name").option("--description <desc>", "Agent description").option("--scope <platform:scope>", "Requested scope, repeatable", collectScope, []).option("--api-url <url>", "AgentValet API base URL", "https://api.agentvalet.ai").option("--output <path>", "Path to write .env file", "./.env.agentvalet").option("--key-path <path>", "Path to write private key", "./agentvalet.key").option("--json", "Machine-readable JSON output").option("--no-wait", "Register only, do not wait for approval").option("--timeout <seconds>", "Approval wait timeout in seconds", "300").action(async (opts) => {
1574
+ var program = new Command4();
1575
+ program.name("agentvalet-register").description("Self-register an AI agent with AgentValet").version("0.4.7").option("--owner <uuid>", "Owner ID (or set AGENTVALET_OWNER env var)").option("--name <name>", "Agent name").option("--description <desc>", "Agent description").option("--scope <platform:scope>", "Requested scope, repeatable", collectScope, []).option("--api-url <url>", "AgentValet API base URL", "https://api.agentvalet.ai").option("--output <path>", "Path to write .env file", "./.env.agentvalet").option("--key-path <path>", "Path to write private key", "./agentvalet.key").option("--json", "Machine-readable JSON output").option("--no-wait", "Register only, do not wait for approval").option("--timeout <seconds>", "Approval wait timeout in seconds", "300").action(async (opts) => {
1383
1576
  const isJson = !!opts.json;
1384
1577
  let ownerId = opts.owner ?? process.env.AGENTVALET_OWNER ?? "";
1385
1578
  let agentName = opts.name ?? "";
@@ -1405,7 +1598,7 @@ program.name("agentvalet-register").description("Self-register an AI agent with
1405
1598
  console.error(JSON.stringify({ error: "--owner or AGENTVALET_OWNER is required" }));
1406
1599
  process.exit(3);
1407
1600
  }
1408
- console.error(chalk8.red("Error: --owner or AGENTVALET_OWNER environment variable is required"));
1601
+ console.error(chalk11.red("Error: --owner or AGENTVALET_OWNER environment variable is required"));
1409
1602
  process.exit(3);
1410
1603
  }
1411
1604
  const scopeMap = /* @__PURE__ */ new Map();
@@ -1413,7 +1606,7 @@ program.name("agentvalet-register").description("Self-register an AI agent with
1413
1606
  const colon = s.indexOf(":");
1414
1607
  if (colon === -1) {
1415
1608
  console.error(
1416
- isJson ? JSON.stringify({ error: `Invalid scope format: ${s} (expected platform:scope)` }) : chalk8.red(`Invalid scope format: ${s} (expected platform:scope)`)
1609
+ isJson ? JSON.stringify({ error: `Invalid scope format: ${s} (expected platform:scope)` }) : chalk11.red(`Invalid scope format: ${s} (expected platform:scope)`)
1417
1610
  );
1418
1611
  process.exit(3);
1419
1612
  }
@@ -1436,11 +1629,11 @@ program.name("agentvalet-register").description("Self-register an AI agent with
1436
1629
  });
1437
1630
  } catch (err) {
1438
1631
  const msg = err instanceof Error ? err.message : String(err);
1439
- console.error(isJson ? JSON.stringify({ error: msg }) : chalk8.red(`Registration failed: ${msg}`));
1632
+ console.error(isJson ? JSON.stringify({ error: msg }) : chalk11.red(`Registration failed: ${msg}`));
1440
1633
  process.exit(3);
1441
1634
  }
1442
1635
  if (!isJson) {
1443
- console.log(chalk8.cyan(`
1636
+ console.log(chalk11.cyan(`
1444
1637
  Approve at: https://app.agentvalet.ai/agents
1445
1638
  `));
1446
1639
  }
@@ -1448,7 +1641,7 @@ Approve at: https://app.agentvalet.ai/agents
1448
1641
  if (isJson) {
1449
1642
  console.log(JSON.stringify({ status: "pending", token }));
1450
1643
  } else {
1451
- console.log(chalk8.yellow("Registration submitted (--no-wait). Token:"), token);
1644
+ console.log(chalk11.yellow("Registration submitted (--no-wait). Token:"), token);
1452
1645
  }
1453
1646
  process.exit(0);
1454
1647
  }
@@ -1459,14 +1652,14 @@ Approve at: https://app.agentvalet.ai/agents
1459
1652
  });
1460
1653
  } catch (err) {
1461
1654
  const msg = err instanceof Error ? err.message : String(err);
1462
- console.error(isJson ? JSON.stringify({ error: msg }) : chalk8.red(`Wait failed: ${msg}`));
1655
+ console.error(isJson ? JSON.stringify({ error: msg }) : chalk11.red(`Wait failed: ${msg}`));
1463
1656
  process.exit(3);
1464
1657
  }
1465
1658
  if (result.status === "rejected") {
1466
1659
  if (isJson) {
1467
1660
  console.log(JSON.stringify({ status: "rejected" }));
1468
1661
  } else {
1469
- console.log(chalk8.red("\nRegistration denied by owner."));
1662
+ console.log(chalk11.red("\nRegistration denied by owner."));
1470
1663
  }
1471
1664
  process.exit(1);
1472
1665
  }
@@ -1474,7 +1667,7 @@ Approve at: https://app.agentvalet.ai/agents
1474
1667
  if (isJson) {
1475
1668
  console.log(JSON.stringify({ status: "timeout" }));
1476
1669
  } else {
1477
- console.log(chalk8.yellow("\nTimed out waiting for approval."));
1670
+ console.log(chalk11.yellow("\nTimed out waiting for approval."));
1478
1671
  }
1479
1672
  process.exit(2);
1480
1673
  }
@@ -1493,7 +1686,7 @@ Approve at: https://app.agentvalet.ai/agents
1493
1686
  }));
1494
1687
  } catch (err) {
1495
1688
  const msg = err instanceof Error ? err.message : String(err);
1496
- console.error(isJson ? JSON.stringify({ error: msg }) : chalk8.red(`Failed to save output: ${msg}`));
1689
+ console.error(isJson ? JSON.stringify({ error: msg }) : chalk11.red(`Failed to save output: ${msg}`));
1497
1690
  process.exit(3);
1498
1691
  }
1499
1692
  const keyWritten = !!privateKey;
@@ -1503,23 +1696,23 @@ Approve at: https://app.agentvalet.ai/agents
1503
1696
  if (isJson) {
1504
1697
  console.log(JSON.stringify({ status: "approved", agentId, keyPath: keyWritten ? keyPath : null, envPath }));
1505
1698
  } else {
1506
- console.log(chalk8.green(`
1699
+ console.log(chalk11.green(`
1507
1700
  Approved! Agent ID: ${agentId}`));
1508
1701
  if (keyWritten) {
1509
- console.log(chalk8.gray(`Key: ${keyPath}`));
1702
+ console.log(chalk11.gray(`Key: ${keyPath}`));
1510
1703
  } else {
1511
- console.log(chalk8.yellow(`Key: not written \u2014 copy it from the dashboard and paste into ${keyPath}`));
1704
+ console.log(chalk11.yellow(`Key: not written \u2014 copy it from the dashboard and paste into ${keyPath}`));
1512
1705
  }
1513
- console.log(chalk8.gray(`Env file: ${envPath}`));
1706
+ console.log(chalk11.gray(`Env file: ${envPath}`));
1514
1707
  console.log(`
1515
1708
  Source the env file before calling any tool:`);
1516
- console.log(chalk8.cyan(` source ${envPath}`));
1709
+ console.log(chalk11.cyan(` source ${envPath}`));
1517
1710
  }
1518
1711
  if (keyWritten) {
1519
1712
  try {
1520
1713
  if (grantedPlatforms && grantedPlatforms.length > 0) {
1521
1714
  writePermissionsFromEvent(agentId, resolvedOwnerId, grantedPlatforms);
1522
- if (!isJson) console.log(chalk8.gray(`Permissions: .claude/agentvalet-permissions.md`));
1715
+ if (!isJson) console.log(chalk11.gray(`Permissions: .claude/agentvalet-permissions.md`));
1523
1716
  } else {
1524
1717
  await runRefresh({
1525
1718
  envFile: opts.output,
@@ -1527,10 +1720,10 @@ Source the env file before calling any tool:`);
1527
1720
  ifStale: false,
1528
1721
  quiet: isJson
1529
1722
  });
1530
- if (!isJson) console.log(chalk8.gray(`Permissions: .claude/agentvalet-permissions.md`));
1723
+ if (!isJson) console.log(chalk11.gray(`Permissions: .claude/agentvalet-permissions.md`));
1531
1724
  }
1532
1725
  } catch {
1533
- if (!isJson) console.log(chalk8.yellow(`Permissions: run 'agentvalet-register refresh' to generate`));
1726
+ if (!isJson) console.log(chalk11.yellow(`Permissions: run 'agentvalet-register refresh' to generate`));
1534
1727
  }
1535
1728
  }
1536
1729
  process.exit(0);
@@ -1545,13 +1738,16 @@ program.command("refresh").description("Refresh approved permissions and update
1545
1738
  });
1546
1739
  } catch (err) {
1547
1740
  const msg = err instanceof Error ? err.message : String(err);
1548
- console.error(chalk8.red(`Refresh failed: ${msg}`));
1741
+ console.error(chalk11.red(`Refresh failed: ${msg}`));
1549
1742
  process.exit(3);
1550
1743
  }
1551
1744
  });
1552
1745
  program.command("mcp-server").description("Start the AgentValet MCP server (stdio transport)").action(async () => {
1553
1746
  await import("./mcp-server-SBGWYBP7.js");
1554
1747
  });
1748
+ program.addCommand(listCommand());
1749
+ program.addCommand(revokeCommand());
1750
+ program.addCommand(injectCommand());
1555
1751
  program.parseAsync().catch((err) => {
1556
1752
  console.error(err);
1557
1753
  process.exit(3);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentvalet/register",
3
- "version": "0.4.5",
3
+ "version": "0.4.7",
4
4
  "description": "Self-register AI agents with AgentValet",
5
5
  "type": "module",
6
6
  "bin": {