@agentvalet/register 0.3.0 → 0.3.2

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 +375 -81
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  // src/index.ts
4
4
  import { Command } from "commander";
5
- import chalk5 from "chalk";
5
+ import chalk7 from "chalk";
6
6
 
7
7
  // src/wizard.ts
8
8
  import prompts from "prompts";
@@ -79,7 +79,7 @@ async function registerAgent(apiUrl, body) {
79
79
  import { fetch as fetch3 } from "undici";
80
80
  async function waitForApproval(apiUrl, token, timeoutMs, onTick) {
81
81
  const deadline = Date.now() + timeoutMs;
82
- const sseResult = await trySSE(apiUrl, token, Math.min(3e4, timeoutMs), onTick);
82
+ const sseResult = await trySSE(apiUrl, token, timeoutMs, onTick);
83
83
  if (sseResult) return enrichWithKey(apiUrl, token, sseResult);
84
84
  const pollResult = await poll(apiUrl, token, deadline, onTick);
85
85
  return enrichWithKey(apiUrl, token, pollResult);
@@ -191,11 +191,102 @@ async function saveOutput(opts) {
191
191
  }
192
192
 
193
193
  // src/commands/refresh.ts
194
- import { readFileSync, writeFileSync, existsSync, mkdirSync, statSync } from "fs";
194
+ import { readFileSync as readFileSync2, writeFileSync as writeFileSync2, existsSync as existsSync2, mkdirSync, statSync } from "fs";
195
195
  import { createSign, createPrivateKey } from "crypto";
196
196
  import { dirname as dirname2, resolve as resolve2 } from "path";
197
197
 
198
198
  // src/lib/skill-writer.ts
199
+ import { existsSync, writeFileSync } from "fs";
200
+ import { execSync } from "child_process";
201
+ import path from "path";
202
+ import chalk2 from "chalk";
203
+ function writeAgentsMd() {
204
+ const dest = path.join(process.cwd(), "AGENTS.md");
205
+ if (existsSync(dest)) {
206
+ console.log(chalk2.dim(" AGENTS.md already exists \u2014 skipping"));
207
+ return;
208
+ }
209
+ const content = `# AgentValet \u2014 Credential Governance
210
+
211
+ All external platform API calls must go through the AgentValet proxy.
212
+ Never call platform APIs (Slack, Stripe, Gmail, GitHub, etc.) directly.
213
+
214
+ ## Making a platform call
215
+
216
+ Use the \`use_platform\` MCP tool:
217
+
218
+ \`\`\`
219
+ use_platform({
220
+ platform: "slack",
221
+ endpoint: "/api/chat.postMessage",
222
+ method: "POST",
223
+ scope: "slack:write",
224
+ data: { channel: "#general", text: "Hello" }
225
+ })
226
+ \`\`\`
227
+
228
+ ## Before any platform session
229
+
230
+ 1. Call \`list_platforms\` to see approved platforms and scopes
231
+ 2. Call \`authzen_evaluate\` before destructive operations
232
+ 3. If a call returns \`pending_approval\` \u2014 wait, do not retry
233
+
234
+ ## If AgentValet MCP is not available
235
+
236
+ Do not call platform APIs directly. Tell the user:
237
+ "AgentValet MCP is not connected. Run: npx @agentvalet/register"
238
+ `;
239
+ writeFileSync(dest, content, "utf8");
240
+ console.log(chalk2.green(" \u2713 AGENTS.md created in current directory"));
241
+ console.log(chalk2.dim(" Commit this file to your repo"));
242
+ }
243
+ function writeSkillMd() {
244
+ const dest = path.join(process.cwd(), "SKILL.md");
245
+ if (existsSync(dest)) {
246
+ console.log(chalk2.dim(" SKILL.md already exists \u2014 skipping"));
247
+ return;
248
+ }
249
+ const content = `# AgentValet Skill
250
+
251
+ Routes all platform API calls through AgentValet's credential proxy.
252
+
253
+ ## Making platform calls
254
+
255
+ Use the \`use_platform\` tool instead of calling APIs directly:
256
+
257
+ \`\`\`
258
+ use_platform({
259
+ platform: "slack",
260
+ endpoint: "/api/chat.postMessage",
261
+ method: "POST",
262
+ scope: "slack:write",
263
+ data: { channel: "#general", text: "Hello" }
264
+ })
265
+ \`\`\`
266
+
267
+ ## Rules
268
+
269
+ 1. Never call platform APIs directly
270
+ 2. Call \`list_platforms\` before assuming a platform is available
271
+ 3. Call \`authzen_evaluate\` before destructive operations
272
+ 4. Wait for human approval when required \u2014 do not retry aggressively
273
+
274
+ Dashboard: https://app.agentvalet.ai
275
+ `;
276
+ writeFileSync(dest, content, "utf8");
277
+ console.log(chalk2.green(" \u2713 SKILL.md created in current directory"));
278
+ console.log(chalk2.dim(" Commit this file to your repo"));
279
+ }
280
+ function ensureMcpServer() {
281
+ try {
282
+ execSync("npx --yes @agentvalet/mcp-server --version", {
283
+ stdio: "ignore",
284
+ timeout: 1e4
285
+ });
286
+ } catch {
287
+ console.log(chalk2.dim(" @agentvalet/mcp-server will be fetched on first use via npx"));
288
+ }
289
+ }
199
290
  function generatePermissionsFile(agentId, ownerId, permissions) {
200
291
  const now = (/* @__PURE__ */ new Date()).toISOString();
201
292
  const platformSections = permissions.length === 0 ? "_No platforms approved yet. Visit https://agentvalet.ai to connect platforms._" : permissions.map((p) => {
@@ -274,7 +365,7 @@ function writePermissionsFromEvent(agentId, ownerId, platforms, outputPath = "./
274
365
  const content = generatePermissionsFile(agentId, ownerId, platforms);
275
366
  const resolvedPath = resolve2(outputPath);
276
367
  mkdirSync(dirname2(resolvedPath), { recursive: true });
277
- writeFileSync(resolvedPath, content, "utf-8");
368
+ writeFileSync2(resolvedPath, content, "utf-8");
278
369
  embedInClaudeMd(content);
279
370
  ensureHook();
280
371
  }
@@ -285,7 +376,7 @@ async function runRefresh(options) {
285
376
  const stat = statSync(outputPath);
286
377
  const fileIsFresh = Date.now() - stat.mtimeMs < 36e5;
287
378
  const claudeMdPath = resolve2("CLAUDE.md");
288
- const claudeMd = existsSync(claudeMdPath) ? readFileSync(claudeMdPath, "utf-8") : "";
379
+ const claudeMd = existsSync2(claudeMdPath) ? readFileSync2(claudeMdPath, "utf-8") : "";
289
380
  const blockStart = claudeMd.indexOf(CLAUDE_START);
290
381
  const blockEnd = claudeMd.indexOf(CLAUDE_END);
291
382
  const blockContent = blockStart !== -1 && blockEnd !== -1 ? claudeMd.slice(blockStart, blockEnd) : "";
@@ -297,7 +388,7 @@ async function runRefresh(options) {
297
388
  const envPath = resolve2(options.envFile);
298
389
  let envVars;
299
390
  try {
300
- envVars = parseEnvFile(readFileSync(envPath, "utf-8"));
391
+ envVars = parseEnvFile(readFileSync2(envPath, "utf-8"));
301
392
  } catch {
302
393
  throw new Error(`Cannot read env file: ${envPath}
303
394
  Run 'agentvalet-register' first to create it.`);
@@ -311,7 +402,7 @@ Run 'agentvalet-register' first to create it.`);
311
402
  }
312
403
  let privateKeyPem;
313
404
  try {
314
- privateKeyPem = readFileSync(keyPath, "utf-8");
405
+ privateKeyPem = readFileSync2(keyPath, "utf-8");
315
406
  } catch {
316
407
  throw new Error(`Cannot read private key: ${keyPath}`);
317
408
  }
@@ -330,7 +421,7 @@ Run 'agentvalet-register' first to create it.`);
330
421
  const platforms = json.data?.platforms ?? [];
331
422
  const content = generatePermissionsFile(agentId, ownerId, platforms);
332
423
  mkdirSync(dirname2(outputPath), { recursive: true });
333
- writeFileSync(outputPath, content, "utf-8");
424
+ writeFileSync2(outputPath, content, "utf-8");
334
425
  embedInClaudeMd(content);
335
426
  ensureHook();
336
427
  if (!options.quiet) {
@@ -342,23 +433,23 @@ function embedInClaudeMd(permissionsContent) {
342
433
  const block = `${CLAUDE_START}
343
434
  ${permissionsContent.trimEnd()}
344
435
  ${CLAUDE_END}`;
345
- if (!existsSync(claudeMdPath)) {
346
- writeFileSync(claudeMdPath, `# Agent Instructions
436
+ if (!existsSync2(claudeMdPath)) {
437
+ writeFileSync2(claudeMdPath, `# Agent Instructions
347
438
 
348
439
  ${block}
349
440
  `, "utf-8");
350
441
  return;
351
442
  }
352
- const existing = readFileSync(claudeMdPath, "utf-8");
443
+ const existing = readFileSync2(claudeMdPath, "utf-8");
353
444
  if (existing.includes(CLAUDE_START)) {
354
445
  const replaced = existing.replace(
355
446
  new RegExp(`${CLAUDE_START}[\\s\\S]*?${CLAUDE_END}`, "m"),
356
447
  block
357
448
  );
358
- writeFileSync(claudeMdPath, replaced, "utf-8");
449
+ writeFileSync2(claudeMdPath, replaced, "utf-8");
359
450
  } else {
360
451
  const cleaned = existing.replace(/^@\.claude\/agentvalet-permissions\.md\s*$/m, "").trimEnd();
361
- writeFileSync(claudeMdPath, `${cleaned}
452
+ writeFileSync2(claudeMdPath, `${cleaned}
362
453
 
363
454
  ${block}
364
455
  `, "utf-8");
@@ -367,9 +458,9 @@ ${block}
367
458
  function ensureHook() {
368
459
  const settingsPath = resolve2(".claude/settings.local.json");
369
460
  let settings = {};
370
- if (existsSync(settingsPath)) {
461
+ if (existsSync2(settingsPath)) {
371
462
  try {
372
- settings = JSON.parse(readFileSync(settingsPath, "utf-8"));
463
+ settings = JSON.parse(readFileSync2(settingsPath, "utf-8"));
373
464
  } catch {
374
465
  return;
375
466
  }
@@ -392,15 +483,15 @@ function ensureHook() {
392
483
  settings.permissions = perms;
393
484
  }
394
485
  mkdirSync(dirname2(settingsPath), { recursive: true });
395
- writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n", "utf-8");
486
+ writeFileSync2(settingsPath, JSON.stringify(settings, null, 2) + "\n", "utf-8");
396
487
  ensureMcpJson();
397
488
  }
398
489
  function ensureMcpJson() {
399
490
  const mcpJsonPath = resolve2(".mcp.json");
400
491
  let mcpConfig = {};
401
- if (existsSync(mcpJsonPath)) {
492
+ if (existsSync2(mcpJsonPath)) {
402
493
  try {
403
- mcpConfig = JSON.parse(readFileSync(mcpJsonPath, "utf-8"));
494
+ mcpConfig = JSON.parse(readFileSync2(mcpJsonPath, "utf-8"));
404
495
  } catch {
405
496
  return;
406
497
  }
@@ -408,10 +499,10 @@ function ensureMcpJson() {
408
499
  const servers = mcpConfig.mcpServers ?? {};
409
500
  if (servers["agent-authority"]) return;
410
501
  const envPath = resolve2(".env.agentvalet");
411
- if (!existsSync(envPath)) return;
502
+ if (!existsSync2(envPath)) return;
412
503
  let envVars;
413
504
  try {
414
- envVars = parseEnvFile(readFileSync(envPath, "utf-8"));
505
+ envVars = parseEnvFile(readFileSync2(envPath, "utf-8"));
415
506
  } catch {
416
507
  return;
417
508
  }
@@ -431,18 +522,18 @@ function ensureMcpJson() {
431
522
  }
432
523
  };
433
524
  mcpConfig.mcpServers = servers;
434
- writeFileSync(mcpJsonPath, JSON.stringify(mcpConfig, null, 2) + "\n", "utf-8");
525
+ writeFileSync2(mcpJsonPath, JSON.stringify(mcpConfig, null, 2) + "\n", "utf-8");
435
526
  }
436
527
 
437
528
  // src/commands/onboard.ts
438
- import chalk4 from "chalk";
529
+ import chalk6 from "chalk";
439
530
  import ora from "ora";
440
- import prompts2 from "prompts";
531
+ import prompts3 from "prompts";
441
532
 
442
533
  // src/auth/github-device-flow.ts
443
534
  import { createOAuthDeviceAuth } from "@octokit/auth-oauth-device";
444
535
  import open from "open";
445
- import chalk2 from "chalk";
536
+ import chalk3 from "chalk";
446
537
  var GITHUB_CLIENT_ID = process.env.AGENTVALET_GITHUB_CLIENT_ID ?? "Ov23liXXXXXXXXXXXXXX";
447
538
  async function authenticateWithGitHub() {
448
539
  const auth = createOAuthDeviceAuth({
@@ -451,15 +542,15 @@ async function authenticateWithGitHub() {
451
542
  scopes: ["user:email", "read:user"],
452
543
  onVerification(verification) {
453
544
  console.log("");
454
- console.log(chalk2.bold(" Authenticate with GitHub"));
545
+ console.log(chalk3.bold(" Authenticate with GitHub"));
455
546
  console.log("");
456
- console.log(` 1. Open: ${chalk2.cyan.underline(verification.verification_uri)}`);
457
- console.log(` 2. Enter code: ${chalk2.bold.yellow(verification.user_code)}`);
547
+ console.log(` 1. Open: ${chalk3.cyan.underline(verification.verification_uri)}`);
548
+ console.log(` 2. Enter code: ${chalk3.bold.yellow(verification.user_code)}`);
458
549
  console.log("");
459
550
  open(verification.verification_uri).catch(() => {
460
- console.log(chalk2.dim(" (Could not open browser \u2014 navigate to the URL above manually)"));
551
+ console.log(chalk3.dim(" (Could not open browser \u2014 navigate to the URL above manually)"));
461
552
  });
462
- console.log(chalk2.dim(" Waiting for authorisation..."));
553
+ console.log(chalk3.dim(" Waiting for authorisation..."));
463
554
  }
464
555
  });
465
556
  const tokenAuth = await auth({ type: "oauth" });
@@ -566,12 +657,12 @@ function isAuthenticated() {
566
657
 
567
658
  // src/config/local.ts
568
659
  import { mkdir as mkdir2, writeFile as writeFile2, appendFile, readFile } from "fs/promises";
569
- import path from "path";
660
+ import path2 from "path";
570
661
  async function writeLocalConfig(config) {
571
- const dir = path.join(process.cwd(), ".agentvalet");
662
+ const dir = path2.join(process.cwd(), ".agentvalet");
572
663
  await mkdir2(dir, { recursive: true });
573
664
  await writeFile2(
574
- path.join(dir, "config.json"),
665
+ path2.join(dir, "config.json"),
575
666
  JSON.stringify({
576
667
  agent_id: config.agentId,
577
668
  agent_name: config.agentName,
@@ -581,14 +672,14 @@ async function writeLocalConfig(config) {
581
672
  { encoding: "utf8", mode: 384 }
582
673
  );
583
674
  await writeFile2(
584
- path.join(dir, "agent.key"),
675
+ path2.join(dir, "agent.key"),
585
676
  config.privateKeyPem,
586
677
  { encoding: "utf8", mode: 384 }
587
678
  );
588
679
  if (process.platform === "win32") {
589
680
  console.warn(" Note: file permissions (0o600) are not enforced on Windows. Keep .agentvalet/ in a secure location.");
590
681
  }
591
- const gitignorePath = path.join(process.cwd(), ".gitignore");
682
+ const gitignorePath = path2.join(process.cwd(), ".gitignore");
592
683
  const gitignoreContent = await readFile(gitignorePath, "utf8").catch(() => null);
593
684
  if (gitignoreContent !== null) {
594
685
  const lines = gitignoreContent.split("\n").map((l) => l.trim());
@@ -599,30 +690,196 @@ async function writeLocalConfig(config) {
599
690
  }
600
691
 
601
692
  // src/output/env.ts
602
- import chalk3 from "chalk";
693
+ import chalk4 from "chalk";
603
694
  import { appendFile as appendFile2, writeFile as writeFile3 } from "fs/promises";
604
- import { existsSync as existsSync2 } from "fs";
605
- import path2 from "path";
695
+ import { existsSync as existsSync3 } from "fs";
696
+ import path3 from "path";
606
697
  function formatEnvBlock(vars) {
607
698
  return Object.entries(vars).map(([key, value]) => {
608
699
  const truncated = value.length > 60 ? value.substring(0, 40) + "..." + value.substring(value.length - 10) : value;
609
- return ` ${chalk3.dim(key + "=")}${chalk3.white(truncated)}`;
700
+ return ` ${chalk4.dim(key + "=")}${chalk4.white(truncated)}`;
610
701
  }).join("\n");
611
702
  }
612
703
 
613
- // src/commands/onboard.ts
704
+ // src/config/ide.ts
705
+ import { mkdir as mkdir3, writeFile as writeFile4, readFile as readFile2, appendFile as appendFile3 } from "fs/promises";
706
+ import { existsSync as existsSync4 } from "fs";
707
+ import path4 from "path";
614
708
  import os from "os";
709
+ function buildMcpEntry(params) {
710
+ return {
711
+ command: "npx",
712
+ args: ["-y", "@agentvalet/register", "mcp-server"],
713
+ env: {
714
+ AGENT_ID: params.agentId,
715
+ OWNER_ID: params.ownerId,
716
+ PROXY_URL: params.proxyUrl,
717
+ AGENT_PRIVATE_KEY_PATH: params.keyPath
718
+ }
719
+ };
720
+ }
721
+ async function mergeJsonFile(filePath, key, value) {
722
+ let existing = {};
723
+ if (existsSync4(filePath)) {
724
+ try {
725
+ const text = await readFile2(filePath, "utf8");
726
+ existing = JSON.parse(text);
727
+ } catch {
728
+ }
729
+ }
730
+ const mcpServers = existing.mcpServers ?? {};
731
+ mcpServers[key] = value;
732
+ existing.mcpServers = mcpServers;
733
+ await writeFile4(filePath, JSON.stringify(existing, null, 2) + "\n", "utf8");
734
+ }
735
+ async function writeGlobalFrameworkConfigs(params) {
736
+ const written = [];
737
+ const privateKeyEscaped = params.privateKeyPem.replace(/\n/g, "\\n");
738
+ const codexConfigPath = path4.join(os.homedir(), ".codex", "config.toml");
739
+ if (existsSync4(codexConfigPath)) {
740
+ try {
741
+ const existing = await readFile2(codexConfigPath, "utf8");
742
+ if (!existing.includes("[mcp.servers.agentvalet]")) {
743
+ const addition = `
744
+ [mcp.servers.agentvalet]
745
+ command = "npx"
746
+ args = ["-y", "@agentvalet/mcp-server"]
747
+
748
+ [mcp.servers.agentvalet.env]
749
+ AGENT_ID = "${params.agentId}"
750
+ OWNER_ID = "${params.ownerId}"
751
+ PROXY_URL = "${params.proxyUrl}"
752
+ AGENT_PRIVATE_KEY = "${privateKeyEscaped}"
753
+ `;
754
+ await appendFile3(codexConfigPath, addition, "utf8");
755
+ written.push("~/.codex/config.toml");
756
+ }
757
+ } catch (err) {
758
+ console.warn(` Warning: could not write Codex CLI config: ${err.message}`);
759
+ }
760
+ }
761
+ const claudeConfigPath = path4.join(os.homedir(), ".claude", "claude_desktop_config.json");
762
+ if (existsSync4(claudeConfigPath)) {
763
+ try {
764
+ let config = {};
765
+ try {
766
+ const text = await readFile2(claudeConfigPath, "utf8");
767
+ config = JSON.parse(text);
768
+ } catch {
769
+ console.warn(" Warning: ~/.claude/claude_desktop_config.json is malformed \u2014 skipping");
770
+ config = null;
771
+ }
772
+ if (config !== null) {
773
+ if (config.mcpServers?.agentvalet) {
774
+ } else {
775
+ config.mcpServers = config.mcpServers ?? {};
776
+ config.mcpServers.agentvalet = {
777
+ command: "npx",
778
+ args: ["-y", "@agentvalet/mcp-server"],
779
+ env: {
780
+ AGENT_ID: params.agentId,
781
+ OWNER_ID: params.ownerId,
782
+ PROXY_URL: params.proxyUrl,
783
+ AGENT_PRIVATE_KEY: privateKeyEscaped
784
+ }
785
+ };
786
+ await writeFile4(claudeConfigPath, JSON.stringify(config, null, 2) + "\n", "utf8");
787
+ written.push("~/.claude/claude_desktop_config.json");
788
+ }
789
+ }
790
+ } catch (err) {
791
+ console.warn(` Warning: could not write Claude Code global config: ${err.message}`);
792
+ }
793
+ }
794
+ return written;
795
+ }
796
+ async function writeIdeConfigs(params) {
797
+ const cwd = process.cwd();
798
+ const written = [];
799
+ const entry = buildMcpEntry(params);
800
+ const claudeMcpPath = path4.join(cwd, ".mcp.json");
801
+ if (existsSync4(claudeMcpPath) || existsSync4(path4.join(cwd, "CLAUDE.md"))) {
802
+ try {
803
+ await mergeJsonFile(claudeMcpPath, "agentvalet", entry);
804
+ written.push(".mcp.json");
805
+ } catch (err) {
806
+ console.warn(` Warning: could not write .mcp.json: ${err.message}`);
807
+ }
808
+ }
809
+ const cursorDir = path4.join(cwd, ".cursor");
810
+ const cursorMcpPath = path4.join(cursorDir, "mcp.json");
811
+ if (existsSync4(cursorDir)) {
812
+ try {
813
+ await mkdir3(cursorDir, { recursive: true });
814
+ await mergeJsonFile(cursorMcpPath, "agentvalet", entry);
815
+ written.push(".cursor/mcp.json");
816
+ } catch (err) {
817
+ console.warn(` Warning: could not write .cursor/mcp.json: ${err.message}`);
818
+ }
819
+ }
820
+ return written;
821
+ }
822
+
823
+ // src/config/frameworks.ts
824
+ import { existsSync as existsSync5 } from "fs";
825
+ import os2 from "os";
826
+ import path5 from "path";
827
+ import prompts2 from "prompts";
828
+ import chalk5 from "chalk";
829
+ function detectFrameworks() {
830
+ const home = os2.homedir();
831
+ return {
832
+ codex: existsSync5(path5.join(home, ".codex", "config.toml")),
833
+ claudeCode: existsSync5(path5.join(home, ".claude")),
834
+ cursor: existsSync5(path5.join(process.cwd(), ".cursor")),
835
+ openclaw: existsSync5(path5.join(home, ".openclaw"))
836
+ };
837
+ }
838
+ async function frameworkSetupConsent(detected) {
839
+ const items = [];
840
+ if (detected.codex) {
841
+ items.push("Codex CLI \u2192 add MCP server to ~/.codex/config.toml");
842
+ items.push(" \u2192 copy AGENTS.md to current directory");
843
+ }
844
+ if (detected.openclaw) {
845
+ items.push("OpenClaw \u2192 copy SKILL.md to current directory");
846
+ }
847
+ if (detected.claudeCode) {
848
+ items.push("Claude Code \u2192 ~/.claude/claude_desktop_config.json");
849
+ }
850
+ if (detected.cursor) {
851
+ items.push("Cursor \u2192 .cursor/mcp.json");
852
+ }
853
+ if (items.length === 0) return false;
854
+ console.log("");
855
+ console.log(chalk5.bold(" Agent framework setup"));
856
+ for (const item of items) {
857
+ console.log(chalk5.dim(` ${item}`));
858
+ }
859
+ console.log("");
860
+ const { confirm } = await prompts2({
861
+ type: "confirm",
862
+ name: "confirm",
863
+ message: "Configure these automatically?",
864
+ initial: true
865
+ });
866
+ return confirm ?? false;
867
+ }
868
+
869
+ // src/commands/onboard.ts
870
+ import os3 from "os";
871
+ import path6 from "path";
615
872
  async function runOnboard() {
616
873
  console.log("");
617
- console.log(chalk4.bold(" AgentValet \u2014 Agent Registration"));
618
- console.log(chalk4.dim(" agentvalet.ai"));
874
+ console.log(chalk6.bold(" AgentValet \u2014 Agent Registration"));
875
+ console.log(chalk6.dim(" agentvalet.ai"));
619
876
  console.log("");
620
877
  if (isAuthenticated()) {
621
878
  const stored = getStoredConfig();
622
879
  console.log(
623
- chalk4.green(" \u2713 Already authenticated as") + chalk4.bold(` ${stored.email}`)
880
+ chalk6.green(" \u2713 Already authenticated as") + chalk6.bold(` ${stored.email}`)
624
881
  );
625
- const { action } = await prompts2({
882
+ const { action } = await prompts3({
626
883
  type: "select",
627
884
  name: "action",
628
885
  message: "What would you like to do?",
@@ -641,7 +898,7 @@ async function runOnboard() {
641
898
  }
642
899
  if (action === "signout") {
643
900
  clearConfig();
644
- console.log(chalk4.dim(" Signed out. Run again to re-authenticate."));
901
+ console.log(chalk6.dim(" Signed out. Run again to re-authenticate."));
645
902
  return;
646
903
  }
647
904
  await registerAgentFlow(stored.apiKey, stored.ownerId);
@@ -653,20 +910,20 @@ async function runOnboard() {
653
910
  const result = await authenticateWithGitHub();
654
911
  githubToken = result.token;
655
912
  } catch (err) {
656
- console.error(chalk4.red(` \u2717 Authentication failed: ${err.message}`));
913
+ console.error(chalk6.red(` \u2717 Authentication failed: ${err.message}`));
657
914
  process.exit(1);
658
915
  }
659
916
  spinner = ora(" Fetching your GitHub profile...").start();
660
917
  let githubUser;
661
918
  try {
662
919
  githubUser = await getGitHubUser(githubToken);
663
- spinner.succeed(` GitHub: ${chalk4.bold("@" + githubUser.login)}`);
920
+ spinner.succeed(` GitHub: ${chalk6.bold("@" + githubUser.login)}`);
664
921
  } catch (err) {
665
922
  spinner.fail(` Failed to fetch GitHub profile: ${err.message}`);
666
923
  process.exit(1);
667
924
  }
668
925
  if (!githubUser.email) {
669
- const { email } = await prompts2({
926
+ const { email } = await prompts3({
670
927
  type: "text",
671
928
  name: "email",
672
929
  message: "Your email address (not visible on GitHub):",
@@ -707,9 +964,9 @@ async function runOnboard() {
707
964
  await registerAgentFlow(account.owner_id, account.owner_id);
708
965
  }
709
966
  async function registerAgentFlow(apiKey, ownerId) {
710
- const hostname = os.hostname().split(".")[0];
967
+ const hostname = os3.hostname().split(".")[0];
711
968
  const dirName = process.cwd().split("/").pop() ?? process.cwd().split("\\").pop() ?? "agent";
712
- const { agentName } = await prompts2({
969
+ const { agentName } = await prompts3({
713
970
  type: "text",
714
971
  name: "agentName",
715
972
  message: "Name for this agent:",
@@ -727,7 +984,7 @@ async function registerAgentFlow(apiKey, ownerId) {
727
984
  name: agentName.trim(),
728
985
  source: "cli"
729
986
  }, apiKey);
730
- spinner.succeed(` Agent registered: ${chalk4.bold(agent.agent_id)}`);
987
+ spinner.succeed(` Agent registered: ${chalk6.bold(agent.agent_id)}`);
731
988
  } catch (err) {
732
989
  spinner.fail(` Registration failed: ${err.message}`);
733
990
  process.exit(1);
@@ -740,37 +997,74 @@ async function registerAgentFlow(apiKey, ownerId) {
740
997
  privateKeyPem: agent.private_key_pem
741
998
  });
742
999
  } catch (err) {
743
- console.error(chalk4.red(` \u2717 Failed to write local config: ${err.message}`));
744
- console.log(chalk4.dim(" Agent was registered \u2014 run again to save config locally."));
1000
+ console.error(chalk6.red(` \u2717 Failed to write local config: ${err.message}`));
1001
+ console.log(chalk6.dim(" Agent was registered \u2014 run again to save config locally."));
745
1002
  process.exit(1);
746
1003
  }
1004
+ const detected = detectFrameworks();
1005
+ const shouldSetup = await frameworkSetupConsent(detected);
1006
+ if (shouldSetup) {
1007
+ console.log("");
1008
+ console.log(chalk6.bold(" Configuring agent frameworks..."));
1009
+ console.log("");
1010
+ const ideResults = await writeIdeConfigs({
1011
+ agentId: agent.agent_id,
1012
+ ownerId,
1013
+ proxyUrl: getStoredConfig().proxyUrl,
1014
+ keyPath: path6.join(process.cwd(), ".agentvalet", "agent.key")
1015
+ });
1016
+ for (const r of ideResults) {
1017
+ console.log(chalk6.green(` \u2713 ${r}`));
1018
+ }
1019
+ const globalResults = await writeGlobalFrameworkConfigs({
1020
+ agentId: agent.agent_id,
1021
+ ownerId,
1022
+ proxyUrl: getStoredConfig().proxyUrl,
1023
+ privateKeyPem: agent.private_key_pem
1024
+ });
1025
+ for (const r of globalResults) {
1026
+ console.log(chalk6.green(` \u2713 ${r}`));
1027
+ }
1028
+ if (detected.codex) {
1029
+ writeAgentsMd();
1030
+ }
1031
+ if (detected.openclaw) {
1032
+ writeSkillMd();
1033
+ }
1034
+ ensureMcpServer();
1035
+ } else if (shouldSetup === false) {
1036
+ console.log("");
1037
+ console.log(chalk6.dim(" To configure agent frameworks manually:"));
1038
+ console.log(chalk6.dim(" https://docs.agentvalet.ai/setup"));
1039
+ }
747
1040
  console.log("");
748
- console.log(chalk4.bold.green(" \u2713 All done!"));
1041
+ console.log(chalk6.bold.green(" \u2713 All done!"));
749
1042
  console.log("");
750
1043
  console.log(" Set these in your environment:");
751
1044
  console.log("");
752
1045
  console.log(formatEnvBlock({
753
- AGENTVALET_PROXY_URL: getStoredConfig().proxyUrl,
754
- AGENTVALET_AGENT_ID: agent.agent_id,
755
- AGENTVALET_PRIVATE_KEY: agent.private_key_pem.replace(/\n/g, "\\n")
1046
+ AGENT_ID: agent.agent_id,
1047
+ OWNER_ID: ownerId,
1048
+ PROXY_URL: getStoredConfig().proxyUrl,
1049
+ AGENT_PRIVATE_KEY_PATH: path6.join(process.cwd(), ".agentvalet", "agent.key")
756
1050
  }));
757
1051
  console.log("");
758
- console.log(chalk4.dim(" Private key also saved to: .agentvalet/agent.key"));
759
- console.log(chalk4.dim(" Add .agentvalet/ to your .gitignore"));
1052
+ console.log(chalk6.dim(" Private key also saved to: .agentvalet/agent.key"));
1053
+ console.log(chalk6.dim(" Add .agentvalet/ to your .gitignore"));
760
1054
  console.log("");
761
1055
  console.log(
762
- ` Dashboard: ${chalk4.cyan.underline("https://app.agentvalet.ai")}`
1056
+ ` Dashboard: ${chalk6.cyan.underline("https://app.agentvalet.ai")}`
763
1057
  );
764
- console.log(chalk4.dim(" Approve this agent in your dashboard to activate it."));
1058
+ console.log(chalk6.dim(" Approve this agent in your dashboard to activate it."));
765
1059
  console.log("");
766
1060
  }
767
1061
  function showCredentials(config) {
768
1062
  console.log("");
769
1063
  console.log(" Your AgentValet credentials:");
770
1064
  console.log("");
771
- console.log(` Owner ID: ${chalk4.bold(config.ownerId)}`);
772
- console.log(` Proxy URL: ${chalk4.bold(config.proxyUrl)}`);
773
- console.log(` Email: ${chalk4.bold(config.email)}`);
1065
+ console.log(` Owner ID: ${chalk6.bold(config.ownerId)}`);
1066
+ console.log(` Proxy URL: ${chalk6.bold(config.proxyUrl)}`);
1067
+ console.log(` Email: ${chalk6.bold(config.email)}`);
774
1068
  console.log("");
775
1069
  }
776
1070
 
@@ -805,7 +1099,7 @@ program.name("agentvalet-register").description("Self-register an AI agent with
805
1099
  console.error(JSON.stringify({ error: "--owner or AGENTVALET_OWNER is required" }));
806
1100
  process.exit(3);
807
1101
  }
808
- console.error(chalk5.red("Error: --owner or AGENTVALET_OWNER environment variable is required"));
1102
+ console.error(chalk7.red("Error: --owner or AGENTVALET_OWNER environment variable is required"));
809
1103
  process.exit(3);
810
1104
  }
811
1105
  const scopeMap = /* @__PURE__ */ new Map();
@@ -813,7 +1107,7 @@ program.name("agentvalet-register").description("Self-register an AI agent with
813
1107
  const colon = s.indexOf(":");
814
1108
  if (colon === -1) {
815
1109
  console.error(
816
- isJson ? JSON.stringify({ error: `Invalid scope format: ${s} (expected platform:scope)` }) : chalk5.red(`Invalid scope format: ${s} (expected platform:scope)`)
1110
+ isJson ? JSON.stringify({ error: `Invalid scope format: ${s} (expected platform:scope)` }) : chalk7.red(`Invalid scope format: ${s} (expected platform:scope)`)
817
1111
  );
818
1112
  process.exit(3);
819
1113
  }
@@ -836,11 +1130,11 @@ program.name("agentvalet-register").description("Self-register an AI agent with
836
1130
  });
837
1131
  } catch (err) {
838
1132
  const msg = err instanceof Error ? err.message : String(err);
839
- console.error(isJson ? JSON.stringify({ error: msg }) : chalk5.red(`Registration failed: ${msg}`));
1133
+ console.error(isJson ? JSON.stringify({ error: msg }) : chalk7.red(`Registration failed: ${msg}`));
840
1134
  process.exit(3);
841
1135
  }
842
1136
  if (!isJson) {
843
- console.log(chalk5.cyan(`
1137
+ console.log(chalk7.cyan(`
844
1138
  Approve at: https://agentvalet.ai/registrations
845
1139
  `));
846
1140
  }
@@ -848,7 +1142,7 @@ Approve at: https://agentvalet.ai/registrations
848
1142
  if (isJson) {
849
1143
  console.log(JSON.stringify({ status: "pending", token }));
850
1144
  } else {
851
- console.log(chalk5.yellow("Registration submitted (--no-wait). Token:"), token);
1145
+ console.log(chalk7.yellow("Registration submitted (--no-wait). Token:"), token);
852
1146
  }
853
1147
  process.exit(0);
854
1148
  }
@@ -859,14 +1153,14 @@ Approve at: https://agentvalet.ai/registrations
859
1153
  });
860
1154
  } catch (err) {
861
1155
  const msg = err instanceof Error ? err.message : String(err);
862
- console.error(isJson ? JSON.stringify({ error: msg }) : chalk5.red(`Wait failed: ${msg}`));
1156
+ console.error(isJson ? JSON.stringify({ error: msg }) : chalk7.red(`Wait failed: ${msg}`));
863
1157
  process.exit(3);
864
1158
  }
865
1159
  if (result.status === "rejected") {
866
1160
  if (isJson) {
867
1161
  console.log(JSON.stringify({ status: "rejected" }));
868
1162
  } else {
869
- console.log(chalk5.red("\nRegistration denied by owner."));
1163
+ console.log(chalk7.red("\nRegistration denied by owner."));
870
1164
  }
871
1165
  process.exit(1);
872
1166
  }
@@ -874,7 +1168,7 @@ Approve at: https://agentvalet.ai/registrations
874
1168
  if (isJson) {
875
1169
  console.log(JSON.stringify({ status: "timeout" }));
876
1170
  } else {
877
- console.log(chalk5.yellow("\nTimed out waiting for approval."));
1171
+ console.log(chalk7.yellow("\nTimed out waiting for approval."));
878
1172
  }
879
1173
  process.exit(2);
880
1174
  }
@@ -893,30 +1187,30 @@ Approve at: https://agentvalet.ai/registrations
893
1187
  }));
894
1188
  } catch (err) {
895
1189
  const msg = err instanceof Error ? err.message : String(err);
896
- console.error(isJson ? JSON.stringify({ error: msg }) : chalk5.red(`Failed to save output: ${msg}`));
1190
+ console.error(isJson ? JSON.stringify({ error: msg }) : chalk7.red(`Failed to save output: ${msg}`));
897
1191
  process.exit(3);
898
1192
  }
899
1193
  const keyWritten = !!privateKey;
900
1194
  if (isJson) {
901
1195
  console.log(JSON.stringify({ status: "approved", agentId, keyPath: keyWritten ? keyPath : null, envPath }));
902
1196
  } else {
903
- console.log(chalk5.green(`
1197
+ console.log(chalk7.green(`
904
1198
  Approved! Agent ID: ${agentId}`));
905
1199
  if (keyWritten) {
906
- console.log(chalk5.gray(`Key: ${keyPath}`));
1200
+ console.log(chalk7.gray(`Key: ${keyPath}`));
907
1201
  } else {
908
- console.log(chalk5.yellow(`Key: not written \u2014 copy it from the dashboard and paste into ${keyPath}`));
1202
+ console.log(chalk7.yellow(`Key: not written \u2014 copy it from the dashboard and paste into ${keyPath}`));
909
1203
  }
910
- console.log(chalk5.gray(`Env file: ${envPath}`));
1204
+ console.log(chalk7.gray(`Env file: ${envPath}`));
911
1205
  console.log(`
912
1206
  Source the env file before calling any tool:`);
913
- console.log(chalk5.cyan(` source ${envPath}`));
1207
+ console.log(chalk7.cyan(` source ${envPath}`));
914
1208
  }
915
1209
  if (keyWritten) {
916
1210
  try {
917
1211
  if (grantedPlatforms && grantedPlatforms.length > 0) {
918
1212
  writePermissionsFromEvent(agentId, resolvedOwnerId, grantedPlatforms);
919
- if (!isJson) console.log(chalk5.gray(`Permissions: .claude/agentvalet-permissions.md`));
1213
+ if (!isJson) console.log(chalk7.gray(`Permissions: .claude/agentvalet-permissions.md`));
920
1214
  } else {
921
1215
  await runRefresh({
922
1216
  envFile: opts.output,
@@ -924,10 +1218,10 @@ Source the env file before calling any tool:`);
924
1218
  ifStale: false,
925
1219
  quiet: isJson
926
1220
  });
927
- if (!isJson) console.log(chalk5.gray(`Permissions: .claude/agentvalet-permissions.md`));
1221
+ if (!isJson) console.log(chalk7.gray(`Permissions: .claude/agentvalet-permissions.md`));
928
1222
  }
929
1223
  } catch {
930
- if (!isJson) console.log(chalk5.yellow(`Permissions: run 'agentvalet-register refresh' to generate`));
1224
+ if (!isJson) console.log(chalk7.yellow(`Permissions: run 'agentvalet-register refresh' to generate`));
931
1225
  }
932
1226
  }
933
1227
  process.exit(0);
@@ -942,7 +1236,7 @@ program.command("refresh").description("Refresh approved permissions and update
942
1236
  });
943
1237
  } catch (err) {
944
1238
  const msg = err instanceof Error ? err.message : String(err);
945
- console.error(chalk5.red(`Refresh failed: ${msg}`));
1239
+ console.error(chalk7.red(`Refresh failed: ${msg}`));
946
1240
  process.exit(3);
947
1241
  }
948
1242
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentvalet/register",
3
- "version": "0.3.0",
3
+ "version": "0.3.2",
4
4
  "description": "Self-register AI agents with AgentValet",
5
5
  "type": "module",
6
6
  "bin": {