@agentvalet/register 1.4.0 → 1.6.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/index.js +109 -21
  2. package/package.json +11 -12
package/dist/index.js CHANGED
@@ -10,8 +10,8 @@ import {
10
10
 
11
11
  // src/index.ts
12
12
  import { createRequire as createRequire2 } from "module";
13
- import { Command as Command7 } from "commander";
14
- import chalk14 from "chalk";
13
+ import { Command as Command8 } from "commander";
14
+ import chalk15 from "chalk";
15
15
 
16
16
  // src/wizard.ts
17
17
  import prompts from "prompts";
@@ -661,8 +661,15 @@ function generatePermissionsFile(agentId, ownerId, permissions) {
661
661
  const gated = new Set(p.approvalScopes ?? []);
662
662
  const scopeList = p.scopes.map((s) => ` - \`${s}\`${gated.has(s) ? " \u2014 requires human approval" : ""}`).join("\n");
663
663
  const approvalNote = p.requireApproval ? "\n > Requires human approval before executing.\n" : "";
664
+ const vendorBits = [
665
+ p.serverName ? `reports itself as \`${p.serverName}\`` : null,
666
+ p.serverHost ? `served from \`${p.serverHost}\`` : null
667
+ ].filter(Boolean);
668
+ const vendorNote = vendorBits.length ? `
669
+ _MCP server \u2014 ${vendorBits.join(", ")}._
670
+ ` : "";
664
671
  return `### ${p.platformName} (\`${p.platformId}\`)
665
-
672
+ ${vendorNote}
666
673
  Approved scopes:
667
674
  ${scopeList}
668
675
  ${approvalNote}`;
@@ -758,6 +765,14 @@ function parseEnvFile(content) {
758
765
  }
759
766
  return result;
760
767
  }
768
+ function resolveAgent(envFile = ".env.agentvalet") {
769
+ const creds = tryResolveAgent(envFile);
770
+ if (!creds) {
771
+ process.stderr.write(NO_AGENT_MSG + "\n");
772
+ process.exit(1);
773
+ }
774
+ return creds;
775
+ }
761
776
  function tryResolveAgent(envFile = ".env.agentvalet") {
762
777
  let agentId;
763
778
  let ownerId;
@@ -2772,13 +2787,84 @@ Or run 'agentvalet-register inject' to write this into ~/.claude.json automatica
2772
2787
  });
2773
2788
  }
2774
2789
 
2790
+ // src/commands/git-credential.ts
2791
+ import { Command as Command7 } from "commander";
2792
+ import { readFileSync as readFileSync6 } from "fs";
2793
+ import { execFileSync } from "child_process";
2794
+ import chalk14 from "chalk";
2795
+ var GIT_USERNAME = "agentvalet";
2796
+ function parseCredentialInput(input) {
2797
+ const out = {};
2798
+ for (const raw of input.split("\n")) {
2799
+ const line = raw.replace(/\r$/, "");
2800
+ if (line === "") break;
2801
+ const eq = line.indexOf("=");
2802
+ if (eq <= 0) continue;
2803
+ out[line.slice(0, eq)] = line.slice(eq + 1);
2804
+ }
2805
+ return out;
2806
+ }
2807
+ function respondToCredentialRequest(action, request2, creds, privateKeyPem) {
2808
+ if (action !== "get") return "";
2809
+ let proxyHost;
2810
+ try {
2811
+ proxyHost = new URL(creds.apiUrl).host.toLowerCase();
2812
+ } catch {
2813
+ return "";
2814
+ }
2815
+ if ((request2.host ?? "").toLowerCase() !== proxyHost) return "";
2816
+ const jwt = signJwt(creds.agentId, creds.ownerId, privateKeyPem);
2817
+ return `username=${GIT_USERNAME}
2818
+ password=${jwt}
2819
+ `;
2820
+ }
2821
+ function gitConfigLine(apiUrl) {
2822
+ const origin = new URL(apiUrl).origin;
2823
+ return [`credential.${origin}.helper`, "!agentvalet git-credential"];
2824
+ }
2825
+ async function readStdin() {
2826
+ const chunks = [];
2827
+ for await (const c of process.stdin) chunks.push(Buffer.isBuffer(c) ? c : Buffer.from(c));
2828
+ return Buffer.concat(chunks).toString("utf8");
2829
+ }
2830
+ function gitCredentialCommand() {
2831
+ return new Command7("git-credential").description("git credential helper: answers the AgentValet proxy with this agent's JWT (used via `agentvalet git-setup`)").argument("<action>", "get | store | erase (supplied by git)").action(async (action) => {
2832
+ const creds = resolveAgent();
2833
+ const request2 = parseCredentialInput(await readStdin());
2834
+ if (action !== "get") return;
2835
+ const pem = readFileSync6(creds.keyPath, "utf8");
2836
+ const reply = respondToCredentialRequest(action, request2, creds, pem);
2837
+ if (reply) process.stdout.write(reply);
2838
+ });
2839
+ }
2840
+ function gitSetupCommand() {
2841
+ return new Command7("git-setup").description("Configure git to authenticate to the AgentValet proxy with this agent's key").option("--local", "Write to the current repository's .git/config instead of the global config").option("--print", "Print the git config command instead of running it").action((opts) => {
2842
+ const creds = resolveAgent();
2843
+ const [key, value] = gitConfigLine(creds.apiUrl);
2844
+ const args = ["config", opts.local ? "--local" : "--global", key, value];
2845
+ if (opts.print) {
2846
+ process.stdout.write(`git ${args.map((a) => /\s|!/.test(a) ? JSON.stringify(a) : a).join(" ")}
2847
+ `);
2848
+ return;
2849
+ }
2850
+ execFileSync("git", args, { stdio: "inherit" });
2851
+ const origin = new URL(creds.apiUrl).origin;
2852
+ process.stderr.write(
2853
+ chalk14.green("\n \u2713 git will authenticate to ") + origin + chalk14.green(" as agent ") + creds.agentId + "\n" + chalk14.dim(`
2854
+ Use remotes of the form ${origin}/git/<owner>/<repo>.git
2855
+
2856
+ `)
2857
+ );
2858
+ });
2859
+ }
2860
+
2775
2861
  // src/index.ts
2776
2862
  var require2 = createRequire2(import.meta.url);
2777
2863
  var { version } = require2("../package.json");
2778
2864
  function collectScope(value, previous) {
2779
2865
  return [...previous, value];
2780
2866
  }
2781
- var program = new Command7();
2867
+ var program = new Command8();
2782
2868
  program.name("agentvalet-register").description("Self-register an AI agent with AgentValet").version(version).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("--json", "Machine-readable JSON output").option("--no-wait", "Register only, do not wait for approval").option("--timeout <seconds>", "Approval wait timeout in seconds", "300").option("--project", "Write project-scoped MCP configs (.mcp.json, .cursor/mcp.json) instead of user-scoped (~/.claude.json, ~/.cursor/mcp.json)").option("--force", "Replace an existing agent's key (a timestamped backup is written first)").action(async (opts) => {
2783
2869
  const isJson = !!opts.json;
2784
2870
  let ownerId = opts.owner ?? process.env.AGENTVALET_OWNER ?? "";
@@ -2812,7 +2898,7 @@ program.name("agentvalet-register").description("Self-register an AI agent with
2812
2898
  console.error(JSON.stringify({ error: "--owner or AGENTVALET_OWNER is required" }));
2813
2899
  process.exit(3);
2814
2900
  }
2815
- console.error(chalk14.red("Error: --owner or AGENTVALET_OWNER environment variable is required"));
2901
+ console.error(chalk15.red("Error: --owner or AGENTVALET_OWNER environment variable is required"));
2816
2902
  process.exit(3);
2817
2903
  }
2818
2904
  const scopeMap = /* @__PURE__ */ new Map();
@@ -2820,7 +2906,7 @@ program.name("agentvalet-register").description("Self-register an AI agent with
2820
2906
  const colon = s.indexOf(":");
2821
2907
  if (colon === -1) {
2822
2908
  console.error(
2823
- isJson ? JSON.stringify({ error: `Invalid scope format: ${s} (expected platform:scope)` }) : chalk14.red(`Invalid scope format: ${s} (expected platform:scope)`)
2909
+ isJson ? JSON.stringify({ error: `Invalid scope format: ${s} (expected platform:scope)` }) : chalk15.red(`Invalid scope format: ${s} (expected platform:scope)`)
2824
2910
  );
2825
2911
  process.exit(3);
2826
2912
  }
@@ -2843,11 +2929,11 @@ program.name("agentvalet-register").description("Self-register an AI agent with
2843
2929
  });
2844
2930
  } catch (err) {
2845
2931
  const msg = err instanceof Error ? err.message : String(err);
2846
- console.error(isJson ? JSON.stringify({ error: msg }) : chalk14.red(`Registration failed: ${msg}`));
2932
+ console.error(isJson ? JSON.stringify({ error: msg }) : chalk15.red(`Registration failed: ${msg}`));
2847
2933
  process.exit(3);
2848
2934
  }
2849
2935
  if (!isJson) {
2850
- console.log(chalk14.cyan(`
2936
+ console.log(chalk15.cyan(`
2851
2937
  Approve at: https://app.agentvalet.ai/agents
2852
2938
  `));
2853
2939
  }
@@ -2855,7 +2941,7 @@ Approve at: https://app.agentvalet.ai/agents
2855
2941
  if (isJson) {
2856
2942
  console.log(JSON.stringify({ status: "pending", token }));
2857
2943
  } else {
2858
- console.log(chalk14.yellow("Registration submitted (--no-wait). Token:"), token);
2944
+ console.log(chalk15.yellow("Registration submitted (--no-wait). Token:"), token);
2859
2945
  }
2860
2946
  process.exit(0);
2861
2947
  }
@@ -2866,14 +2952,14 @@ Approve at: https://app.agentvalet.ai/agents
2866
2952
  });
2867
2953
  } catch (err) {
2868
2954
  const msg = err instanceof Error ? err.message : String(err);
2869
- console.error(isJson ? JSON.stringify({ error: msg }) : chalk14.red(`Wait failed: ${msg}`));
2955
+ console.error(isJson ? JSON.stringify({ error: msg }) : chalk15.red(`Wait failed: ${msg}`));
2870
2956
  process.exit(3);
2871
2957
  }
2872
2958
  if (result.status === "rejected") {
2873
2959
  if (isJson) {
2874
2960
  console.log(JSON.stringify({ status: "rejected" }));
2875
2961
  } else {
2876
- console.log(chalk14.red("\nRegistration denied by owner."));
2962
+ console.log(chalk15.red("\nRegistration denied by owner."));
2877
2963
  }
2878
2964
  process.exit(1);
2879
2965
  }
@@ -2881,7 +2967,7 @@ Approve at: https://app.agentvalet.ai/agents
2881
2967
  if (isJson) {
2882
2968
  console.log(JSON.stringify({ status: "timeout" }));
2883
2969
  } else {
2884
- console.log(chalk14.yellow("\nTimed out waiting for approval."));
2970
+ console.log(chalk15.yellow("\nTimed out waiting for approval."));
2885
2971
  }
2886
2972
  process.exit(2);
2887
2973
  }
@@ -2901,10 +2987,10 @@ Approve at: https://app.agentvalet.ai/agents
2901
2987
  } catch (err) {
2902
2988
  const msg = err instanceof Error ? err.message : String(err);
2903
2989
  if (err instanceof KeyClobberError) {
2904
- console.error(isJson ? JSON.stringify({ error: msg, existing_agent_id: err.existingAgentId }) : chalk14.red(msg));
2990
+ console.error(isJson ? JSON.stringify({ error: msg, existing_agent_id: err.existingAgentId }) : chalk15.red(msg));
2905
2991
  process.exit(3);
2906
2992
  }
2907
- console.error(isJson ? JSON.stringify({ error: msg }) : chalk14.red(`Failed to save output: ${msg}`));
2993
+ console.error(isJson ? JSON.stringify({ error: msg }) : chalk15.red(`Failed to save output: ${msg}`));
2908
2994
  process.exit(3);
2909
2995
  }
2910
2996
  } else {
@@ -2914,25 +3000,25 @@ Approve at: https://app.agentvalet.ai/agents
2914
3000
  if (isJson) {
2915
3001
  console.log(JSON.stringify({ status: "approved", agentId, keyPath: keyWritten ? keyPath : null }));
2916
3002
  } else {
2917
- console.log(chalk14.green(`
3003
+ console.log(chalk15.green(`
2918
3004
  Approved! Agent ID: ${agentId}`));
2919
3005
  if (keyWritten) {
2920
- console.log(chalk14.gray(`Key: ${keyPath}`));
3006
+ console.log(chalk15.gray(`Key: ${keyPath}`));
2921
3007
  } else {
2922
- console.log(chalk14.yellow(`Key: not written \u2014 copy it from the dashboard and paste into ${keyPath}`));
3008
+ console.log(chalk15.yellow(`Key: not written \u2014 copy it from the dashboard and paste into ${keyPath}`));
2923
3009
  }
2924
3010
  }
2925
3011
  if (keyWritten) {
2926
3012
  try {
2927
3013
  if (grantedPlatforms && grantedPlatforms.length > 0) {
2928
3014
  writePermissionsFromEvent(agentId, resolvedOwnerId, grantedPlatforms);
2929
- if (!isJson) console.log(chalk14.gray(`Permissions: .claude/agentvalet-permissions.md`));
3015
+ if (!isJson) console.log(chalk15.gray(`Permissions: .claude/agentvalet-permissions.md`));
2930
3016
  } else {
2931
3017
  await runRefresh({ envFile: ".env.agentvalet", outputPath: ".claude/agentvalet-permissions.md", ifStale: false, quiet: isJson });
2932
- if (!isJson) console.log(chalk14.gray(`Permissions: .claude/agentvalet-permissions.md`));
3018
+ if (!isJson) console.log(chalk15.gray(`Permissions: .claude/agentvalet-permissions.md`));
2933
3019
  }
2934
3020
  } catch {
2935
- if (!isJson) console.log(chalk14.yellow(`Permissions: run 'agentvalet-register refresh' to generate`));
3021
+ if (!isJson) console.log(chalk15.yellow(`Permissions: run 'agentvalet-register refresh' to generate`));
2936
3022
  }
2937
3023
  }
2938
3024
  process.exit(0);
@@ -2947,7 +3033,7 @@ program.command("refresh").description("Refresh approved permissions and update
2947
3033
  });
2948
3034
  } catch (err) {
2949
3035
  const msg = err instanceof Error ? err.message : String(err);
2950
- console.error(chalk14.red(`Refresh failed: ${msg}`));
3036
+ console.error(chalk15.red(`Refresh failed: ${msg}`));
2951
3037
  process.exit(3);
2952
3038
  }
2953
3039
  });
@@ -2957,6 +3043,8 @@ program.command("mcp-server").description("Start the AgentValet MCP server (stdi
2957
3043
  });
2958
3044
  program.addCommand(listCommand());
2959
3045
  program.addCommand(revokeCommand());
3046
+ program.addCommand(gitCredentialCommand());
3047
+ program.addCommand(gitSetupCommand());
2960
3048
  program.addCommand(injectCommand());
2961
3049
  program.addCommand(uninstallCommand());
2962
3050
  program.addCommand(installCommand());
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentvalet/register",
3
- "version": "1.4.0",
3
+ "version": "1.6.0",
4
4
  "description": "Self-register AI agents with AgentValet",
5
5
  "type": "module",
6
6
  "bin": {
@@ -10,13 +10,6 @@
10
10
  "dist",
11
11
  "README.md"
12
12
  ],
13
- "scripts": {
14
- "build": "tsup src/index.ts --format esm --dts --clean --shims",
15
- "dev": "tsx src/index.ts",
16
- "test": "vitest run",
17
- "typecheck": "tsc --noEmit",
18
- "prepublishOnly": "node ../../scripts/no-secrets.mjs && pnpm build && node ../../scripts/no-workspace-protocol.mjs"
19
- },
20
13
  "dependencies": {
21
14
  "@modelcontextprotocol/sdk": "^1.29.0",
22
15
  "@octokit/auth-oauth-device": "^7.0.0",
@@ -29,13 +22,13 @@
29
22
  "undici": "^6.0.0"
30
23
  },
31
24
  "devDependencies": {
32
- "@agentvalet/mcp-server": "workspace:^",
33
25
  "@types/node": "^20.0.0",
34
26
  "@types/prompts": "^2.4.0",
35
27
  "tsup": "^8.0.0",
36
28
  "tsx": "^4.0.0",
37
29
  "typescript": "^5.0.0",
38
- "vitest": "^1.5.0"
30
+ "vitest": "^1.5.0",
31
+ "@agentvalet/mcp-server": "^1.14.0"
39
32
  },
40
33
  "engines": {
41
34
  "node": ">=18"
@@ -61,5 +54,11 @@
61
54
  "valet",
62
55
  "agentvalet"
63
56
  ],
64
- "license": "MIT"
65
- }
57
+ "license": "MIT",
58
+ "scripts": {
59
+ "build": "tsup src/index.ts --format esm --dts --clean --shims",
60
+ "dev": "tsx src/index.ts",
61
+ "test": "vitest run",
62
+ "typecheck": "tsc --noEmit"
63
+ }
64
+ }