@agentvalet/register 0.3.1 → 0.3.3

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 +324 -100
  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";
@@ -14,7 +14,7 @@ async function runWizard(prefilled) {
14
14
  questions.push({
15
15
  type: "text",
16
16
  name: "ownerId",
17
- message: "Owner ID (from https://agentvalet.ai/settings):",
17
+ message: "Owner ID (from https://app.agentvalet.ai/settings):",
18
18
  validate: (v) => v.trim() ? true : "Owner ID is required"
19
19
  });
20
20
  }
@@ -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,14 +191,105 @@ 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
- const platformSections = permissions.length === 0 ? "_No platforms approved yet. Visit https://agentvalet.ai to connect platforms._" : permissions.map((p) => {
292
+ const platformSections = permissions.length === 0 ? "_No platforms approved yet. Visit https://app.agentvalet.ai to connect platforms._" : permissions.map((p) => {
202
293
  const scopeList = p.scopes.map((s) => ` - \`${s}\``).join("\n");
203
294
  const approvalNote = p.requireApproval ? "\n > Requires human approval before executing.\n" : "";
204
295
  return `### ${p.platformName} (\`${p.platformId}\`)
@@ -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,21 +690,22 @@ 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
704
  // src/config/ide.ts
614
- import { mkdir as mkdir3, writeFile as writeFile4, readFile as readFile2 } from "fs/promises";
615
- import { existsSync as existsSync3 } from "fs";
616
- import path3 from "path";
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";
708
+ import os from "os";
617
709
  function buildMcpEntry(params) {
618
710
  return {
619
711
  command: "npx",
@@ -628,7 +720,7 @@ function buildMcpEntry(params) {
628
720
  }
629
721
  async function mergeJsonFile(filePath, key, value) {
630
722
  let existing = {};
631
- if (existsSync3(filePath)) {
723
+ if (existsSync4(filePath)) {
632
724
  try {
633
725
  const text = await readFile2(filePath, "utf8");
634
726
  existing = JSON.parse(text);
@@ -640,12 +732,73 @@ async function mergeJsonFile(filePath, key, value) {
640
732
  existing.mcpServers = mcpServers;
641
733
  await writeFile4(filePath, JSON.stringify(existing, null, 2) + "\n", "utf8");
642
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
+ }
643
796
  async function writeIdeConfigs(params) {
644
797
  const cwd = process.cwd();
645
798
  const written = [];
646
799
  const entry = buildMcpEntry(params);
647
- const claudeMcpPath = path3.join(cwd, ".mcp.json");
648
- if (existsSync3(claudeMcpPath) || existsSync3(path3.join(cwd, "CLAUDE.md"))) {
800
+ const claudeMcpPath = path4.join(cwd, ".mcp.json");
801
+ if (existsSync4(claudeMcpPath) || existsSync4(path4.join(cwd, "CLAUDE.md"))) {
649
802
  try {
650
803
  await mergeJsonFile(claudeMcpPath, "agentvalet", entry);
651
804
  written.push(".mcp.json");
@@ -653,9 +806,9 @@ async function writeIdeConfigs(params) {
653
806
  console.warn(` Warning: could not write .mcp.json: ${err.message}`);
654
807
  }
655
808
  }
656
- const cursorDir = path3.join(cwd, ".cursor");
657
- const cursorMcpPath = path3.join(cursorDir, "mcp.json");
658
- if (existsSync3(cursorDir)) {
809
+ const cursorDir = path4.join(cwd, ".cursor");
810
+ const cursorMcpPath = path4.join(cursorDir, "mcp.json");
811
+ if (existsSync4(cursorDir)) {
659
812
  try {
660
813
  await mkdir3(cursorDir, { recursive: true });
661
814
  await mergeJsonFile(cursorMcpPath, "agentvalet", entry);
@@ -667,20 +820,66 @@ async function writeIdeConfigs(params) {
667
820
  return written;
668
821
  }
669
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
+
670
869
  // src/commands/onboard.ts
671
- import os from "os";
672
- import path4 from "path";
870
+ import os3 from "os";
871
+ import path6 from "path";
673
872
  async function runOnboard() {
674
873
  console.log("");
675
- console.log(chalk4.bold(" AgentValet \u2014 Agent Registration"));
676
- console.log(chalk4.dim(" agentvalet.ai"));
874
+ console.log(chalk6.bold(" AgentValet \u2014 Agent Registration"));
875
+ console.log(chalk6.dim(" app.agentvalet.ai"));
677
876
  console.log("");
678
877
  if (isAuthenticated()) {
679
878
  const stored = getStoredConfig();
680
879
  console.log(
681
- chalk4.green(" \u2713 Already authenticated as") + chalk4.bold(` ${stored.email}`)
880
+ chalk6.green(" \u2713 Already authenticated as") + chalk6.bold(` ${stored.email}`)
682
881
  );
683
- const { action } = await prompts2({
882
+ const { action } = await prompts3({
684
883
  type: "select",
685
884
  name: "action",
686
885
  message: "What would you like to do?",
@@ -699,7 +898,7 @@ async function runOnboard() {
699
898
  }
700
899
  if (action === "signout") {
701
900
  clearConfig();
702
- console.log(chalk4.dim(" Signed out. Run again to re-authenticate."));
901
+ console.log(chalk6.dim(" Signed out. Run again to re-authenticate."));
703
902
  return;
704
903
  }
705
904
  await registerAgentFlow(stored.apiKey, stored.ownerId);
@@ -711,20 +910,20 @@ async function runOnboard() {
711
910
  const result = await authenticateWithGitHub();
712
911
  githubToken = result.token;
713
912
  } catch (err) {
714
- console.error(chalk4.red(` \u2717 Authentication failed: ${err.message}`));
913
+ console.error(chalk6.red(` \u2717 Authentication failed: ${err.message}`));
715
914
  process.exit(1);
716
915
  }
717
916
  spinner = ora(" Fetching your GitHub profile...").start();
718
917
  let githubUser;
719
918
  try {
720
919
  githubUser = await getGitHubUser(githubToken);
721
- spinner.succeed(` GitHub: ${chalk4.bold("@" + githubUser.login)}`);
920
+ spinner.succeed(` GitHub: ${chalk6.bold("@" + githubUser.login)}`);
722
921
  } catch (err) {
723
922
  spinner.fail(` Failed to fetch GitHub profile: ${err.message}`);
724
923
  process.exit(1);
725
924
  }
726
925
  if (!githubUser.email) {
727
- const { email } = await prompts2({
926
+ const { email } = await prompts3({
728
927
  type: "text",
729
928
  name: "email",
730
929
  message: "Your email address (not visible on GitHub):",
@@ -765,9 +964,9 @@ async function runOnboard() {
765
964
  await registerAgentFlow(account.owner_id, account.owner_id);
766
965
  }
767
966
  async function registerAgentFlow(apiKey, ownerId) {
768
- const hostname = os.hostname().split(".")[0];
967
+ const hostname = os3.hostname().split(".")[0];
769
968
  const dirName = process.cwd().split("/").pop() ?? process.cwd().split("\\").pop() ?? "agent";
770
- const { agentName } = await prompts2({
969
+ const { agentName } = await prompts3({
771
970
  type: "text",
772
971
  name: "agentName",
773
972
  message: "Name for this agent:",
@@ -785,7 +984,7 @@ async function registerAgentFlow(apiKey, ownerId) {
785
984
  name: agentName.trim(),
786
985
  source: "cli"
787
986
  }, apiKey);
788
- spinner.succeed(` Agent registered: ${chalk4.bold(agent.agent_id)}`);
987
+ spinner.succeed(` Agent registered: ${chalk6.bold(agent.agent_id)}`);
789
988
  } catch (err) {
790
989
  spinner.fail(` Registration failed: ${err.message}`);
791
990
  process.exit(1);
@@ -798,23 +997,48 @@ async function registerAgentFlow(apiKey, ownerId) {
798
997
  privateKeyPem: agent.private_key_pem
799
998
  });
800
999
  } catch (err) {
801
- console.error(chalk4.red(` \u2717 Failed to write local config: ${err.message}`));
802
- 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."));
803
1002
  process.exit(1);
804
1003
  }
805
- const ideResults = await writeIdeConfigs({
806
- agentId: agent.agent_id,
807
- ownerId,
808
- proxyUrl: getStoredConfig().proxyUrl,
809
- keyPath: path4.join(process.cwd(), ".agentvalet", "agent.key")
810
- });
811
- if (ideResults.length > 0) {
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
+ });
812
1016
  for (const r of ideResults) {
813
- console.log(chalk4.dim(` MCP config written: ${r}`));
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();
814
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"));
815
1039
  }
816
1040
  console.log("");
817
- console.log(chalk4.bold.green(" \u2713 All done!"));
1041
+ console.log(chalk6.bold.green(" \u2713 All done!"));
818
1042
  console.log("");
819
1043
  console.log(" Set these in your environment:");
820
1044
  console.log("");
@@ -822,25 +1046,25 @@ async function registerAgentFlow(apiKey, ownerId) {
822
1046
  AGENT_ID: agent.agent_id,
823
1047
  OWNER_ID: ownerId,
824
1048
  PROXY_URL: getStoredConfig().proxyUrl,
825
- AGENT_PRIVATE_KEY_PATH: path4.join(process.cwd(), ".agentvalet", "agent.key")
1049
+ AGENT_PRIVATE_KEY_PATH: path6.join(process.cwd(), ".agentvalet", "agent.key")
826
1050
  }));
827
1051
  console.log("");
828
- console.log(chalk4.dim(" Private key also saved to: .agentvalet/agent.key"));
829
- 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"));
830
1054
  console.log("");
831
1055
  console.log(
832
- ` Dashboard: ${chalk4.cyan.underline("https://app.agentvalet.ai")}`
1056
+ ` Dashboard: ${chalk6.cyan.underline("https://app.agentvalet.ai")}`
833
1057
  );
834
- 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."));
835
1059
  console.log("");
836
1060
  }
837
1061
  function showCredentials(config) {
838
1062
  console.log("");
839
1063
  console.log(" Your AgentValet credentials:");
840
1064
  console.log("");
841
- console.log(` Owner ID: ${chalk4.bold(config.ownerId)}`);
842
- console.log(` Proxy URL: ${chalk4.bold(config.proxyUrl)}`);
843
- 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)}`);
844
1068
  console.log("");
845
1069
  }
846
1070
 
@@ -875,7 +1099,7 @@ program.name("agentvalet-register").description("Self-register an AI agent with
875
1099
  console.error(JSON.stringify({ error: "--owner or AGENTVALET_OWNER is required" }));
876
1100
  process.exit(3);
877
1101
  }
878
- 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"));
879
1103
  process.exit(3);
880
1104
  }
881
1105
  const scopeMap = /* @__PURE__ */ new Map();
@@ -883,7 +1107,7 @@ program.name("agentvalet-register").description("Self-register an AI agent with
883
1107
  const colon = s.indexOf(":");
884
1108
  if (colon === -1) {
885
1109
  console.error(
886
- 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)`)
887
1111
  );
888
1112
  process.exit(3);
889
1113
  }
@@ -906,19 +1130,19 @@ program.name("agentvalet-register").description("Self-register an AI agent with
906
1130
  });
907
1131
  } catch (err) {
908
1132
  const msg = err instanceof Error ? err.message : String(err);
909
- 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}`));
910
1134
  process.exit(3);
911
1135
  }
912
1136
  if (!isJson) {
913
- console.log(chalk5.cyan(`
914
- Approve at: https://agentvalet.ai/registrations
1137
+ console.log(chalk7.cyan(`
1138
+ Approve at: https://app.agentvalet.ai/agents
915
1139
  `));
916
1140
  }
917
1141
  if (!opts.wait) {
918
1142
  if (isJson) {
919
1143
  console.log(JSON.stringify({ status: "pending", token }));
920
1144
  } else {
921
- console.log(chalk5.yellow("Registration submitted (--no-wait). Token:"), token);
1145
+ console.log(chalk7.yellow("Registration submitted (--no-wait). Token:"), token);
922
1146
  }
923
1147
  process.exit(0);
924
1148
  }
@@ -929,14 +1153,14 @@ Approve at: https://agentvalet.ai/registrations
929
1153
  });
930
1154
  } catch (err) {
931
1155
  const msg = err instanceof Error ? err.message : String(err);
932
- 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}`));
933
1157
  process.exit(3);
934
1158
  }
935
1159
  if (result.status === "rejected") {
936
1160
  if (isJson) {
937
1161
  console.log(JSON.stringify({ status: "rejected" }));
938
1162
  } else {
939
- console.log(chalk5.red("\nRegistration denied by owner."));
1163
+ console.log(chalk7.red("\nRegistration denied by owner."));
940
1164
  }
941
1165
  process.exit(1);
942
1166
  }
@@ -944,7 +1168,7 @@ Approve at: https://agentvalet.ai/registrations
944
1168
  if (isJson) {
945
1169
  console.log(JSON.stringify({ status: "timeout" }));
946
1170
  } else {
947
- console.log(chalk5.yellow("\nTimed out waiting for approval."));
1171
+ console.log(chalk7.yellow("\nTimed out waiting for approval."));
948
1172
  }
949
1173
  process.exit(2);
950
1174
  }
@@ -963,30 +1187,30 @@ Approve at: https://agentvalet.ai/registrations
963
1187
  }));
964
1188
  } catch (err) {
965
1189
  const msg = err instanceof Error ? err.message : String(err);
966
- 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}`));
967
1191
  process.exit(3);
968
1192
  }
969
1193
  const keyWritten = !!privateKey;
970
1194
  if (isJson) {
971
1195
  console.log(JSON.stringify({ status: "approved", agentId, keyPath: keyWritten ? keyPath : null, envPath }));
972
1196
  } else {
973
- console.log(chalk5.green(`
1197
+ console.log(chalk7.green(`
974
1198
  Approved! Agent ID: ${agentId}`));
975
1199
  if (keyWritten) {
976
- console.log(chalk5.gray(`Key: ${keyPath}`));
1200
+ console.log(chalk7.gray(`Key: ${keyPath}`));
977
1201
  } else {
978
- 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}`));
979
1203
  }
980
- console.log(chalk5.gray(`Env file: ${envPath}`));
1204
+ console.log(chalk7.gray(`Env file: ${envPath}`));
981
1205
  console.log(`
982
1206
  Source the env file before calling any tool:`);
983
- console.log(chalk5.cyan(` source ${envPath}`));
1207
+ console.log(chalk7.cyan(` source ${envPath}`));
984
1208
  }
985
1209
  if (keyWritten) {
986
1210
  try {
987
1211
  if (grantedPlatforms && grantedPlatforms.length > 0) {
988
1212
  writePermissionsFromEvent(agentId, resolvedOwnerId, grantedPlatforms);
989
- if (!isJson) console.log(chalk5.gray(`Permissions: .claude/agentvalet-permissions.md`));
1213
+ if (!isJson) console.log(chalk7.gray(`Permissions: .claude/agentvalet-permissions.md`));
990
1214
  } else {
991
1215
  await runRefresh({
992
1216
  envFile: opts.output,
@@ -994,10 +1218,10 @@ Source the env file before calling any tool:`);
994
1218
  ifStale: false,
995
1219
  quiet: isJson
996
1220
  });
997
- if (!isJson) console.log(chalk5.gray(`Permissions: .claude/agentvalet-permissions.md`));
1221
+ if (!isJson) console.log(chalk7.gray(`Permissions: .claude/agentvalet-permissions.md`));
998
1222
  }
999
1223
  } catch {
1000
- 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`));
1001
1225
  }
1002
1226
  }
1003
1227
  process.exit(0);
@@ -1012,7 +1236,7 @@ program.command("refresh").description("Refresh approved permissions and update
1012
1236
  });
1013
1237
  } catch (err) {
1014
1238
  const msg = err instanceof Error ? err.message : String(err);
1015
- console.error(chalk5.red(`Refresh failed: ${msg}`));
1239
+ console.error(chalk7.red(`Refresh failed: ${msg}`));
1016
1240
  process.exit(3);
1017
1241
  }
1018
1242
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentvalet/register",
3
- "version": "0.3.1",
3
+ "version": "0.3.3",
4
4
  "description": "Self-register AI agents with AgentValet",
5
5
  "type": "module",
6
6
  "bin": {