@agentvalet/register 0.4.5 → 0.4.6

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 +231 -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,218 @@ 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/config.ts
1382
+ import { homedir } from "os";
1383
+ import { join as join2 } from "path";
1384
+ import { readFile as readFile3, writeFile as writeFile6, mkdir as mkdir4 } from "fs/promises";
1385
+ var CONFIG_PATH = join2(homedir(), ".agentvalet", "config.json");
1386
+ var DEFAULTS = {
1387
+ apiUrl: "https://app.agentvalet.ai",
1388
+ token: null
1389
+ };
1390
+ async function loadConfig() {
1391
+ try {
1392
+ const raw = await readFile3(CONFIG_PATH, "utf-8");
1393
+ return { ...DEFAULTS, ...JSON.parse(raw) };
1394
+ } catch (err) {
1395
+ if (err.code === "ENOENT") return { ...DEFAULTS };
1396
+ throw err;
1397
+ }
1398
+ }
1399
+
1400
+ // src/lib/api.ts
1401
+ async function request(path7, options) {
1402
+ const config = await loadConfig();
1403
+ if (!config.token) throw new Error("Not authenticated. Run: agentvalet login");
1404
+ const response = await fetch(`${config.apiUrl}/functions/v1${path7}`, {
1405
+ method: options.method,
1406
+ headers: {
1407
+ "Authorization": `Bearer ${config.token}`,
1408
+ "Content-Type": "application/json"
1409
+ },
1410
+ body: options.body ? JSON.stringify(options.body) : void 0
1411
+ });
1412
+ if (!response.ok) {
1413
+ const text = await response.text();
1414
+ throw new Error(`API error ${response.status}: ${text}`);
1415
+ }
1416
+ return response.json();
1417
+ }
1418
+ async function revokeAgent(agentId) {
1419
+ return request("/revoke-agent", { method: "POST", body: { agentId } });
1420
+ }
1421
+ async function listAgents() {
1422
+ return request("/list-agents", { method: "GET" });
1423
+ }
1424
+
1425
+ // src/commands/list.ts
1426
+ function listCommand() {
1427
+ return new Command("list").description("List all registered agents").action(async () => {
1428
+ const config = getStoredConfig();
1429
+ if (!config.ownerId) {
1430
+ process.stderr.write(
1431
+ chalk8.red("\n \u2717 No agent registered.\n") + chalk8.dim(" Run the following command first:\n\n npx @agentvalet/register\n\n")
1432
+ );
1433
+ process.exit(1);
1434
+ }
1435
+ try {
1436
+ const agents = await listAgents();
1437
+ if (agents.length === 0) {
1438
+ console.log("No agents registered yet. Run: npx @agentvalet/register");
1439
+ return;
1440
+ }
1441
+ const maxNameLen = Math.max(...agents.map((a) => a.name.length), 4);
1442
+ const header = `${"ID".padEnd(30)} ${"NAME".padEnd(maxNameLen)} STATUS`;
1443
+ console.log(header);
1444
+ console.log("-".repeat(header.length));
1445
+ for (const agent of agents) {
1446
+ const status = agent.status === "active" ? chalk8.green("\u2713 active") : agent.status === "suspended" ? chalk8.yellow("\u26A0 suspended") : chalk8.red("\u2717 revoked");
1447
+ console.log(`${agent.id.padEnd(30)} ${agent.name.padEnd(maxNameLen)} ${status}`);
1448
+ }
1449
+ } catch (err) {
1450
+ console.error(chalk8.red(String(err)));
1451
+ process.exit(1);
1452
+ }
1453
+ });
1454
+ }
1455
+
1456
+ // src/commands/revoke.ts
1457
+ import { Command as Command2 } from "commander";
1458
+ import chalk9 from "chalk";
1459
+ import * as readline from "readline";
1460
+ function revokeCommand() {
1461
+ 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) => {
1462
+ const config = getStoredConfig();
1463
+ if (!config.ownerId) {
1464
+ process.stderr.write(
1465
+ chalk9.red("\n \u2717 No agent registered.\n") + chalk9.dim(" Run the following command first:\n\n npx @agentvalet/register\n\n")
1466
+ );
1467
+ process.exit(1);
1468
+ }
1469
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
1470
+ const confirmed = await new Promise((resolve4) => {
1471
+ rl.question(
1472
+ chalk9.yellow(`Revoke ${opts.agentId}? This cascades to all child agents and cannot be undone. (y/N) `),
1473
+ (ans) => {
1474
+ rl.close();
1475
+ resolve4(ans.trim().toLowerCase() === "y");
1476
+ }
1477
+ );
1478
+ });
1479
+ if (!confirmed) {
1480
+ console.log("Cancelled.");
1481
+ return;
1482
+ }
1483
+ try {
1484
+ const result = await revokeAgent(opts.agentId);
1485
+ console.log(chalk9.green(`Revoked ${result.revokedAgentIds.length} agent(s)`));
1486
+ if (result.revokedAgentIds.length > 1) {
1487
+ console.log("Revoked:", result.revokedAgentIds.join(", "));
1488
+ }
1489
+ } catch (err) {
1490
+ console.error(chalk9.red(String(err)));
1491
+ process.exit(1);
1492
+ }
1493
+ });
1494
+ }
1495
+
1496
+ // src/commands/inject.ts
1497
+ import { Command as Command3 } from "commander";
1498
+ import chalk10 from "chalk";
1499
+ import { readFile as readFile6 } from "fs/promises";
1500
+
1501
+ // src/lib/claude-config.ts
1502
+ import { homedir as homedir2 } from "os";
1503
+ import { join as join3 } from "path";
1504
+ import { readFile as readFile4, writeFile as writeFile7, mkdir as mkdir5, access } from "fs/promises";
1505
+ var CLAUDE_CONFIG_PATH = join3(homedir2(), ".claude", "config");
1506
+ async function writeKeyToClaudeConfig(agentId, privateKeyPem) {
1507
+ let config = {};
1508
+ try {
1509
+ await access(CLAUDE_CONFIG_PATH);
1510
+ const raw = await readFile4(CLAUDE_CONFIG_PATH, "utf-8");
1511
+ config = JSON.parse(raw);
1512
+ } catch {
1513
+ }
1514
+ config.agent_keys = config.agent_keys ?? {};
1515
+ config.agent_keys[agentId] = Buffer.from(privateKeyPem).toString("base64");
1516
+ await mkdir5(join3(homedir2(), ".claude"), { recursive: true });
1517
+ await writeFile7(CLAUDE_CONFIG_PATH, JSON.stringify(config, null, 2), "utf-8");
1518
+ }
1519
+
1520
+ // src/lib/env-writer.ts
1521
+ import { readFile as readFile5, writeFile as writeFile8, access as access2 } from "fs/promises";
1522
+ var ENV_VAR_NAME = (agentId) => `AGENTVALET_PRIVATE_KEY_${agentId.replace(/-/g, "_").toUpperCase()}`;
1523
+ async function writeKeyToEnvLocal(agentId, privateKeyPem) {
1524
+ const varName = ENV_VAR_NAME(agentId);
1525
+ const b64Key = Buffer.from(privateKeyPem).toString("base64");
1526
+ const line = `
1527
+ # AgentValet private key for ${agentId} (base64-encoded PEM)
1528
+ ${varName}=${b64Key}
1529
+ `;
1530
+ let existing = "";
1531
+ try {
1532
+ await access2(".env.local");
1533
+ existing = await readFile5(".env.local", "utf-8");
1534
+ } catch {
1535
+ }
1536
+ if (existing.includes(varName)) {
1537
+ const lines = existing.split("\n");
1538
+ const filtered = lines.filter((l) => !l.startsWith(`${varName}=`));
1539
+ await writeFile8(".env.local", filtered.join("\n") + line, "utf-8");
1540
+ } else {
1541
+ await writeFile8(".env.local", existing + line, "utf-8");
1542
+ }
1543
+ }
1544
+
1545
+ // src/commands/inject.ts
1546
+ function injectCommand() {
1547
+ 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) => {
1548
+ let privateKeyPem;
1549
+ try {
1550
+ privateKeyPem = await readFile6(opts.keyFile, "utf-8");
1551
+ } catch {
1552
+ console.error(chalk10.red(`Could not read key file: ${opts.keyFile}`));
1553
+ process.exit(1);
1554
+ }
1555
+ if (!privateKeyPem.includes("BEGIN PRIVATE KEY")) {
1556
+ console.error(chalk10.red("File does not appear to be a PEM private key"));
1557
+ process.exit(1);
1558
+ }
1559
+ try {
1560
+ if (opts.target === "claude-code") {
1561
+ await writeKeyToClaudeConfig(opts.agentId, privateKeyPem);
1562
+ console.log(chalk10.green("Key injected into ~/.claude/config"));
1563
+ } else if (opts.target === "env-local") {
1564
+ await writeKeyToEnvLocal(opts.agentId, privateKeyPem);
1565
+ console.log(chalk10.green("Key appended to .env.local"));
1566
+ } else {
1567
+ console.error(chalk10.red(`Unknown target: ${opts.target}. Use 'claude-code' or 'env-local'`));
1568
+ process.exit(1);
1569
+ }
1570
+ } catch (err) {
1571
+ console.error(chalk10.red(String(err)));
1572
+ process.exit(1);
1573
+ }
1574
+ if (opts.target === "env-local") {
1575
+ console.log(chalk10.dim("Add .env.local to .gitignore \u2014 do not commit private keys to git."));
1576
+ } else {
1577
+ console.log(chalk10.dim("The key is stored in ~/.claude/config \u2014 it is NOT committed to git."));
1578
+ }
1579
+ console.log(chalk10.green("Done. Your agent is ready to use."));
1580
+ });
1581
+ }
1582
+
1377
1583
  // src/index.ts
1378
1584
  function collectScope(value, previous) {
1379
1585
  return [...previous, value];
1380
1586
  }
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) => {
1587
+ var program = new Command4();
1588
+ program.name("agentvalet-register").description("Self-register an AI agent with AgentValet").version("0.4.6").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
1589
  const isJson = !!opts.json;
1384
1590
  let ownerId = opts.owner ?? process.env.AGENTVALET_OWNER ?? "";
1385
1591
  let agentName = opts.name ?? "";
@@ -1405,7 +1611,7 @@ program.name("agentvalet-register").description("Self-register an AI agent with
1405
1611
  console.error(JSON.stringify({ error: "--owner or AGENTVALET_OWNER is required" }));
1406
1612
  process.exit(3);
1407
1613
  }
1408
- console.error(chalk8.red("Error: --owner or AGENTVALET_OWNER environment variable is required"));
1614
+ console.error(chalk11.red("Error: --owner or AGENTVALET_OWNER environment variable is required"));
1409
1615
  process.exit(3);
1410
1616
  }
1411
1617
  const scopeMap = /* @__PURE__ */ new Map();
@@ -1413,7 +1619,7 @@ program.name("agentvalet-register").description("Self-register an AI agent with
1413
1619
  const colon = s.indexOf(":");
1414
1620
  if (colon === -1) {
1415
1621
  console.error(
1416
- isJson ? JSON.stringify({ error: `Invalid scope format: ${s} (expected platform:scope)` }) : chalk8.red(`Invalid scope format: ${s} (expected platform:scope)`)
1622
+ isJson ? JSON.stringify({ error: `Invalid scope format: ${s} (expected platform:scope)` }) : chalk11.red(`Invalid scope format: ${s} (expected platform:scope)`)
1417
1623
  );
1418
1624
  process.exit(3);
1419
1625
  }
@@ -1436,11 +1642,11 @@ program.name("agentvalet-register").description("Self-register an AI agent with
1436
1642
  });
1437
1643
  } catch (err) {
1438
1644
  const msg = err instanceof Error ? err.message : String(err);
1439
- console.error(isJson ? JSON.stringify({ error: msg }) : chalk8.red(`Registration failed: ${msg}`));
1645
+ console.error(isJson ? JSON.stringify({ error: msg }) : chalk11.red(`Registration failed: ${msg}`));
1440
1646
  process.exit(3);
1441
1647
  }
1442
1648
  if (!isJson) {
1443
- console.log(chalk8.cyan(`
1649
+ console.log(chalk11.cyan(`
1444
1650
  Approve at: https://app.agentvalet.ai/agents
1445
1651
  `));
1446
1652
  }
@@ -1448,7 +1654,7 @@ Approve at: https://app.agentvalet.ai/agents
1448
1654
  if (isJson) {
1449
1655
  console.log(JSON.stringify({ status: "pending", token }));
1450
1656
  } else {
1451
- console.log(chalk8.yellow("Registration submitted (--no-wait). Token:"), token);
1657
+ console.log(chalk11.yellow("Registration submitted (--no-wait). Token:"), token);
1452
1658
  }
1453
1659
  process.exit(0);
1454
1660
  }
@@ -1459,14 +1665,14 @@ Approve at: https://app.agentvalet.ai/agents
1459
1665
  });
1460
1666
  } catch (err) {
1461
1667
  const msg = err instanceof Error ? err.message : String(err);
1462
- console.error(isJson ? JSON.stringify({ error: msg }) : chalk8.red(`Wait failed: ${msg}`));
1668
+ console.error(isJson ? JSON.stringify({ error: msg }) : chalk11.red(`Wait failed: ${msg}`));
1463
1669
  process.exit(3);
1464
1670
  }
1465
1671
  if (result.status === "rejected") {
1466
1672
  if (isJson) {
1467
1673
  console.log(JSON.stringify({ status: "rejected" }));
1468
1674
  } else {
1469
- console.log(chalk8.red("\nRegistration denied by owner."));
1675
+ console.log(chalk11.red("\nRegistration denied by owner."));
1470
1676
  }
1471
1677
  process.exit(1);
1472
1678
  }
@@ -1474,7 +1680,7 @@ Approve at: https://app.agentvalet.ai/agents
1474
1680
  if (isJson) {
1475
1681
  console.log(JSON.stringify({ status: "timeout" }));
1476
1682
  } else {
1477
- console.log(chalk8.yellow("\nTimed out waiting for approval."));
1683
+ console.log(chalk11.yellow("\nTimed out waiting for approval."));
1478
1684
  }
1479
1685
  process.exit(2);
1480
1686
  }
@@ -1493,7 +1699,7 @@ Approve at: https://app.agentvalet.ai/agents
1493
1699
  }));
1494
1700
  } catch (err) {
1495
1701
  const msg = err instanceof Error ? err.message : String(err);
1496
- console.error(isJson ? JSON.stringify({ error: msg }) : chalk8.red(`Failed to save output: ${msg}`));
1702
+ console.error(isJson ? JSON.stringify({ error: msg }) : chalk11.red(`Failed to save output: ${msg}`));
1497
1703
  process.exit(3);
1498
1704
  }
1499
1705
  const keyWritten = !!privateKey;
@@ -1503,23 +1709,23 @@ Approve at: https://app.agentvalet.ai/agents
1503
1709
  if (isJson) {
1504
1710
  console.log(JSON.stringify({ status: "approved", agentId, keyPath: keyWritten ? keyPath : null, envPath }));
1505
1711
  } else {
1506
- console.log(chalk8.green(`
1712
+ console.log(chalk11.green(`
1507
1713
  Approved! Agent ID: ${agentId}`));
1508
1714
  if (keyWritten) {
1509
- console.log(chalk8.gray(`Key: ${keyPath}`));
1715
+ console.log(chalk11.gray(`Key: ${keyPath}`));
1510
1716
  } else {
1511
- console.log(chalk8.yellow(`Key: not written \u2014 copy it from the dashboard and paste into ${keyPath}`));
1717
+ console.log(chalk11.yellow(`Key: not written \u2014 copy it from the dashboard and paste into ${keyPath}`));
1512
1718
  }
1513
- console.log(chalk8.gray(`Env file: ${envPath}`));
1719
+ console.log(chalk11.gray(`Env file: ${envPath}`));
1514
1720
  console.log(`
1515
1721
  Source the env file before calling any tool:`);
1516
- console.log(chalk8.cyan(` source ${envPath}`));
1722
+ console.log(chalk11.cyan(` source ${envPath}`));
1517
1723
  }
1518
1724
  if (keyWritten) {
1519
1725
  try {
1520
1726
  if (grantedPlatforms && grantedPlatforms.length > 0) {
1521
1727
  writePermissionsFromEvent(agentId, resolvedOwnerId, grantedPlatforms);
1522
- if (!isJson) console.log(chalk8.gray(`Permissions: .claude/agentvalet-permissions.md`));
1728
+ if (!isJson) console.log(chalk11.gray(`Permissions: .claude/agentvalet-permissions.md`));
1523
1729
  } else {
1524
1730
  await runRefresh({
1525
1731
  envFile: opts.output,
@@ -1527,10 +1733,10 @@ Source the env file before calling any tool:`);
1527
1733
  ifStale: false,
1528
1734
  quiet: isJson
1529
1735
  });
1530
- if (!isJson) console.log(chalk8.gray(`Permissions: .claude/agentvalet-permissions.md`));
1736
+ if (!isJson) console.log(chalk11.gray(`Permissions: .claude/agentvalet-permissions.md`));
1531
1737
  }
1532
1738
  } catch {
1533
- if (!isJson) console.log(chalk8.yellow(`Permissions: run 'agentvalet-register refresh' to generate`));
1739
+ if (!isJson) console.log(chalk11.yellow(`Permissions: run 'agentvalet-register refresh' to generate`));
1534
1740
  }
1535
1741
  }
1536
1742
  process.exit(0);
@@ -1545,13 +1751,16 @@ program.command("refresh").description("Refresh approved permissions and update
1545
1751
  });
1546
1752
  } catch (err) {
1547
1753
  const msg = err instanceof Error ? err.message : String(err);
1548
- console.error(chalk8.red(`Refresh failed: ${msg}`));
1754
+ console.error(chalk11.red(`Refresh failed: ${msg}`));
1549
1755
  process.exit(3);
1550
1756
  }
1551
1757
  });
1552
1758
  program.command("mcp-server").description("Start the AgentValet MCP server (stdio transport)").action(async () => {
1553
1759
  await import("./mcp-server-SBGWYBP7.js");
1554
1760
  });
1761
+ program.addCommand(listCommand());
1762
+ program.addCommand(revokeCommand());
1763
+ program.addCommand(injectCommand());
1555
1764
  program.parseAsync().catch((err) => {
1556
1765
  console.error(err);
1557
1766
  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.6",
4
4
  "description": "Self-register AI agents with AgentValet",
5
5
  "type": "module",
6
6
  "bin": {