@agentvalet/register 0.4.12 → 0.4.13

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 +298 -7
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -192,7 +192,7 @@ async function saveOutput(opts) {
192
192
  }
193
193
 
194
194
  // src/commands/refresh.ts
195
- import { readFileSync as readFileSync3, writeFileSync as writeFileSync2, existsSync as existsSync3, mkdirSync, statSync } from "fs";
195
+ import { readFileSync as readFileSync3, writeFileSync as writeFileSync2, existsSync as existsSync3, mkdirSync as mkdirSync2, statSync } from "fs";
196
196
  import { dirname as dirname2, resolve as resolve3 } from "path";
197
197
 
198
198
  // src/lib/jwt.ts
@@ -211,7 +211,7 @@ function signJwt(agentId, ownerId, privateKeyPem) {
211
211
  }
212
212
 
213
213
  // src/lib/skill-writer.ts
214
- import { existsSync, writeFileSync } from "fs";
214
+ import { existsSync, writeFileSync, mkdirSync } from "fs";
215
215
  import { execSync } from "child_process";
216
216
  import path from "path";
217
217
  import chalk2 from "chalk";
@@ -316,6 +316,11 @@ The \`.mcp.json\` in this directory has been configured. Run \`/mcp\` in Claude
316
316
  if (detected.openclaw) {
317
317
  lines.push(`### OpenClaw
318
318
  See \`SKILL.md\` for platform call instructions.`);
319
+ }
320
+ if (detected.factoryDroid) {
321
+ lines.push(`### Factory Droid
322
+ \`~/.factory/mcp.json\` has been updated with the AgentValet MCP server block.
323
+ Type \`@AgentValet\` in Factory Droid to activate governance. Use \`/av-status\` to verify connections.`);
319
324
  }
320
325
  if (lines.length === 0) {
321
326
  lines.push(`Add the MCP server to your IDE manually. See: https://docs.agentvalet.ai/setup`);
@@ -370,6 +375,203 @@ AGENT_PRIVATE_KEY_PATH=${keyPath}
370
375
  console.log(chalk2.green(" \u2713 AGENTVALET.md created \u2014 quick reference for this agent"));
371
376
  console.log(chalk2.dim(" Add to .gitignore if it contains sensitive paths"));
372
377
  }
378
+ function writeFactoryDroidDroid() {
379
+ const droidsDir = path.join(process.cwd(), ".factory", "droids");
380
+ if (!existsSync(droidsDir)) mkdirSync(droidsDir, { recursive: true });
381
+ const dest = path.join(droidsDir, "agentvalet.yaml");
382
+ if (existsSync(dest)) {
383
+ console.log(chalk2.dim(" Factory Droid: .factory/droids/agentvalet.yaml already exists"));
384
+ return;
385
+ }
386
+ const content = `# AgentValet Governance Droid
387
+ # Automatically created by @agentvalet/register
388
+ # Commit this file to your repo
389
+
390
+ name: AgentValet
391
+ description: >
392
+ Routes all platform API calls through AgentValet's credential
393
+ proxy. Enforces per-agent permissions, rate limits, and human
394
+ approval for high-risk operations. Every call is logged.
395
+
396
+ model: inherit
397
+
398
+ mcp_servers:
399
+ - agentvalet
400
+
401
+ autonomy: Low
402
+
403
+ instructions: |
404
+ You are operating under AgentValet credential governance.
405
+
406
+ ## Rules \u2014 read before every platform call
407
+
408
+ 1. NEVER call platform APIs (Slack, Stripe, Gmail, GitHub, etc.) directly.
409
+ Always use the \`use_platform\` MCP tool.
410
+
411
+ 2. Call \`list_platforms\` at the start of any session that involves
412
+ platform calls. Do not assume platforms are available.
413
+
414
+ 3. Call \`authzen_evaluate\` before any destructive operation
415
+ (delete, send, charge, publish). Do not proceed if decision=false.
416
+
417
+ 4. If \`use_platform\` returns \`{ status: "pending_approval" }\`,
418
+ wait for human approval. Do not retry the call.
419
+
420
+ 5. If AgentValet MCP tools are unavailable, stop and tell the user:
421
+ "AgentValet MCP is not connected. Run: npx @agentvalet/register"
422
+ Do not attempt platform calls without governance.
423
+
424
+ ## Making a platform call
425
+
426
+ \`\`\`
427
+ use_platform({
428
+ platform: "slack",
429
+ endpoint: "/api/chat.postMessage",
430
+ method: "POST",
431
+ scope: "slack:write",
432
+ data: { channel: "#general", text: "Hello" }
433
+ })
434
+ \`\`\`
435
+
436
+ ## Scope categories
437
+
438
+ - Read scopes (*.read, *.list) \u2014 lower risk, may auto-approve
439
+ - Write scopes (*.write, *.create) \u2014 check authzen_evaluate first
440
+ - Destructive scopes (*.delete, stripe:charge, mail:send) \u2014 always
441
+ call authzen_evaluate, always inform user before proceeding
442
+
443
+ Dashboard: https://app.agentvalet.ai
444
+ Docs: https://docs.agentvalet.ai
445
+ `;
446
+ writeFileSync(dest, content, "utf8");
447
+ console.log(chalk2.green(" \u2713 Factory Droid: created .factory/droids/agentvalet.yaml"));
448
+ console.log(chalk2.dim(" Commit this file to your repo"));
449
+ }
450
+ function writeFactoryDroidCommand() {
451
+ const commandsDir = path.join(process.cwd(), ".factory", "commands");
452
+ if (!existsSync(commandsDir)) mkdirSync(commandsDir, { recursive: true });
453
+ const statusDest = path.join(commandsDir, "av-status.md");
454
+ if (!existsSync(statusDest)) {
455
+ const statusContent = `# /av-status
456
+
457
+ Check your AgentValet agent status and approved platform connections.
458
+
459
+ ## Instructions for the droid
460
+
461
+ 1. Call \`list_platforms\` using the AgentValet MCP server
462
+ 2. Display the results in a clean table:
463
+ - Platform name
464
+ - Approved scopes
465
+ - Whether any scope requires human approval
466
+ 3. If no platforms are approved yet, tell the user to visit
467
+ https://app.agentvalet.ai/agents to configure permissions
468
+ 4. If AgentValet MCP is not connected, explain how to set it up:
469
+ Run: npx @agentvalet/register
470
+ `;
471
+ writeFileSync(statusDest, statusContent, "utf8");
472
+ console.log(chalk2.green(" \u2713 Factory Droid: created .factory/commands/av-status.md"));
473
+ } else {
474
+ console.log(chalk2.dim(" Factory Droid: .factory/commands/av-status.md already exists"));
475
+ }
476
+ const registerDest = path.join(commandsDir, "av-register.md");
477
+ if (!existsSync(registerDest)) {
478
+ const registerContent = `# /av-register
479
+
480
+ Register or re-register this project with AgentValet.
481
+
482
+ ## Instructions for the droid
483
+
484
+ Tell the user to run the following command in their terminal:
485
+
486
+ \`\`\`bash
487
+ npx @agentvalet/register
488
+ \`\`\`
489
+
490
+ This will:
491
+ 1. Authenticate with GitHub (opens browser)
492
+ 2. Create or find their AgentValet account
493
+ 3. Register this machine as an agent
494
+ 4. Configure Factory Droid MCP integration automatically
495
+
496
+ After running, approve the agent at: https://app.agentvalet.ai/agents
497
+ `;
498
+ writeFileSync(registerDest, registerContent, "utf8");
499
+ console.log(chalk2.green(" \u2713 Factory Droid: created .factory/commands/av-register.md"));
500
+ }
501
+ }
502
+ function writeFactoryDroidReliabilityDroid() {
503
+ const droidsDir = path.join(process.cwd(), ".factory", "droids");
504
+ if (!existsSync(droidsDir)) mkdirSync(droidsDir, { recursive: true });
505
+ const dest = path.join(droidsDir, "agentvalet-reliability.yaml");
506
+ if (existsSync(dest)) return;
507
+ const content = `# AgentValet Reliability Droid
508
+ # Monitors agent call patterns and surfaces governance issues
509
+ # Commit this file to your repo
510
+
511
+ name: AgentValet Reliability
512
+ description: >
513
+ Monitors AI agent behaviour against AgentValet governance rules.
514
+ Surfaces approval-required actions, scope violations, rate limit
515
+ warnings, and audit anomalies directly in Factory Droid.
516
+
517
+ type: reliability
518
+ model: inherit
519
+ mcp_servers:
520
+ - agentvalet
521
+ autonomy: Low
522
+
523
+ triggers:
524
+ - on_agent_action: true
525
+ - on_approval_required: true
526
+ - on_scope_violation: true
527
+
528
+ instructions: |
529
+ You are a governance monitor. You observe what the other droids
530
+ are doing and flag any actions that require human oversight.
531
+
532
+ ## Your responsibilities
533
+
534
+ 1. BEFORE any droid makes a platform API call, check if the scope
535
+ requires approval using \`authzen_evaluate\`:
536
+ - If decision=false: block the call, explain why, suggest alternatives
537
+ - If decision=true: allow, but log it
538
+
539
+ 2. WHEN a droid calls \`use_platform\`, verify:
540
+ - The platform is in the approved list from \`list_platforms\`
541
+ - The scope matches what was approved
542
+ - The call hasn't exceeded rate limits
543
+
544
+ 3. SURFACE approval-required actions clearly:
545
+ "\u26A0 This action requires human approval: [action description]
546
+ Waiting for approval at app.agentvalet.ai/approvals"
547
+
548
+ 4. MONITOR for unusual patterns:
549
+ - Multiple calls to the same destructive scope in quick succession
550
+ - Calls to platforms not in the approved list
551
+ - Call volume spikes beyond normal operation
552
+
553
+ 5. REPORT governance status when asked:
554
+ - Current approved platforms and scopes
555
+ - Pending approvals
556
+ - Recent audit log entries (call list_platforms + agent_status)
557
+
558
+ ## What you do NOT do
559
+
560
+ - You do not make platform API calls yourself
561
+ - You do not approve actions on behalf of the human
562
+ - You do not bypass governance even if another droid requests it
563
+
564
+ ## Escalation
565
+
566
+ If you detect a potential security concern (unexpected scope,
567
+ unusual call pattern), immediately tell the human:
568
+ "\u{1F534} Governance alert: [description]. Recommend reviewing at
569
+ app.agentvalet.ai/audit"
570
+ `;
571
+ writeFileSync(dest, content, "utf8");
572
+ console.log(chalk2.green(" \u2713 Factory Droid: created .factory/droids/agentvalet-reliability.yaml"));
573
+ console.log(chalk2.dim(" Commit this file to your repo"));
574
+ }
373
575
  function ensureMcpServer() {
374
576
  try {
375
577
  execSync("npx --yes @agentvalet/mcp-server --version", {
@@ -518,7 +720,7 @@ var HOOK_MARKER = "agentvalet/register refresh";
518
720
  function writePermissionsFromEvent(agentId, ownerId, platforms, outputPath = "./.claude/agentvalet-permissions.md") {
519
721
  const content = generatePermissionsFile(agentId, ownerId, platforms);
520
722
  const resolvedPath = resolve3(outputPath);
521
- mkdirSync(dirname2(resolvedPath), { recursive: true });
723
+ mkdirSync2(dirname2(resolvedPath), { recursive: true });
522
724
  writeFileSync2(resolvedPath, content, "utf-8");
523
725
  embedInClaudeMd(content);
524
726
  ensureHook();
@@ -565,7 +767,7 @@ async function runRefresh(options) {
565
767
  const json = await res.json();
566
768
  const platforms = json.data?.platforms ?? [];
567
769
  const content = generatePermissionsFile(agentId, ownerId, platforms);
568
- mkdirSync(dirname2(outputPath), { recursive: true });
770
+ mkdirSync2(dirname2(outputPath), { recursive: true });
569
771
  writeFileSync2(outputPath, content, "utf-8");
570
772
  embedInClaudeMd(content);
571
773
  ensureHook();
@@ -627,7 +829,7 @@ function ensureHook() {
627
829
  perms.allow = [...allow, ...missing];
628
830
  settings.permissions = perms;
629
831
  }
630
- mkdirSync(dirname2(settingsPath), { recursive: true });
832
+ mkdirSync2(dirname2(settingsPath), { recursive: true });
631
833
  writeFileSync2(settingsPath, JSON.stringify(settings, null, 2) + "\n", "utf-8");
632
834
  ensureMcpJson();
633
835
  }
@@ -849,7 +1051,7 @@ function formatEnvBlock(vars) {
849
1051
  }
850
1052
 
851
1053
  // src/config/ide.ts
852
- import { mkdir as mkdir3, writeFile as writeFile4, readFile as readFile2, appendFile as appendFile3 } from "fs/promises";
1054
+ import { mkdir as mkdir3, writeFile as writeFile4, readFile as readFile2, appendFile as appendFile3, copyFile } from "fs/promises";
853
1055
  import { existsSync as existsSync5 } from "fs";
854
1056
  import path4 from "path";
855
1057
  import os from "os";
@@ -980,6 +1182,72 @@ async function writeIdeConfigs(params) {
980
1182
  console.warn(` Warning: could not write .cursor/mcp.json: ${err.message}`);
981
1183
  }
982
1184
  }
1185
+ if (detected.factoryDroid) {
1186
+ const fdResults = await writeFactoryDroidConfig(mcpParams);
1187
+ written.push(...fdResults);
1188
+ }
1189
+ return written;
1190
+ }
1191
+ async function mergeFactoryDroidMcpJson(filePath, key, value) {
1192
+ let existing = {};
1193
+ if (existsSync5(filePath)) {
1194
+ try {
1195
+ const text = await readFile2(filePath, "utf8");
1196
+ existing = JSON.parse(text);
1197
+ } catch {
1198
+ await copyFile(filePath, filePath + ".backup");
1199
+ }
1200
+ }
1201
+ if (existing[key]) return;
1202
+ existing[key] = value;
1203
+ await writeFile4(filePath, JSON.stringify(existing, null, 2) + "\n", "utf8");
1204
+ }
1205
+ async function updateGitignoreForFactoryDroid() {
1206
+ const gitignorePath = path4.join(process.cwd(), ".gitignore");
1207
+ if (!existsSync5(gitignorePath)) return;
1208
+ const existing = await readFile2(gitignorePath, "utf8");
1209
+ if (existing.includes(".factory/mcp.json")) return;
1210
+ const additions = [
1211
+ "",
1212
+ "# Factory Droid \u2014 private key in MCP config",
1213
+ ".factory/mcp.json",
1214
+ "",
1215
+ "# Factory Droid \u2014 commit these:",
1216
+ "# .factory/droids/",
1217
+ "# .factory/commands/"
1218
+ ].join("\n");
1219
+ await appendFile3(gitignorePath, additions + "\n", "utf8");
1220
+ }
1221
+ async function writeFactoryDroidConfig(params) {
1222
+ const home = os.homedir();
1223
+ const written = [];
1224
+ const entry = buildMcpEntry(params);
1225
+ const globalDir = path4.join(home, ".factory");
1226
+ const projectDir = path4.join(process.cwd(), ".factory");
1227
+ const globalDirExists = existsSync5(globalDir);
1228
+ const projectDirExists = existsSync5(projectDir);
1229
+ if (globalDirExists) {
1230
+ try {
1231
+ await mergeFactoryDroidMcpJson(path4.join(globalDir, "mcp.json"), "agentvalet", entry);
1232
+ written.push("~/.factory/mcp.json");
1233
+ } catch (err) {
1234
+ console.warn(` Warning: could not write ~/.factory/mcp.json: ${err.message}`);
1235
+ }
1236
+ }
1237
+ if (projectDirExists && !globalDirExists) {
1238
+ try {
1239
+ await mergeFactoryDroidMcpJson(path4.join(projectDir, "mcp.json"), "agentvalet", entry);
1240
+ written.push(".factory/mcp.json");
1241
+ } catch (err) {
1242
+ console.warn(` Warning: could not write .factory/mcp.json: ${err.message}`);
1243
+ }
1244
+ }
1245
+ if (written.length > 0) {
1246
+ try {
1247
+ await updateGitignoreForFactoryDroid();
1248
+ } catch {
1249
+ }
1250
+ }
983
1251
  return written;
984
1252
  }
985
1253
 
@@ -1017,7 +1285,8 @@ function detectFrameworks() {
1017
1285
  codex: existsSync6(path5.join(home, ".codex")) || tryBinary("codex"),
1018
1286
  claudeCode: existsSync6(path5.join(home, ".claude")) || tryBinary("claude"),
1019
1287
  cursor: existsSync6(path5.join(process.cwd(), ".cursor")) || cursorInstalled(),
1020
- openclaw: existsSync6(path5.join(home, ".openclaw"))
1288
+ openclaw: existsSync6(path5.join(home, ".openclaw")),
1289
+ factoryDroid: existsSync6(path5.join(home, ".factory")) || existsSync6(path5.join(process.cwd(), ".factory"))
1021
1290
  };
1022
1291
  }
1023
1292
  async function frameworkSetupConsent(detected) {
@@ -1036,6 +1305,11 @@ async function frameworkSetupConsent(detected) {
1036
1305
  if (detected.openclaw) {
1037
1306
  items.push("OpenClaw \u2192 SKILL.md (usage rules)");
1038
1307
  }
1308
+ if (detected.factoryDroid) {
1309
+ items.push("Factory Droid \u2192 add MCP server to ~/.factory/mcp.json");
1310
+ items.push(" \u2192 create .factory/droids/agentvalet.yaml");
1311
+ items.push(" \u2192 create .factory/commands/av-status.md");
1312
+ }
1039
1313
  if (items.length === 0) return false;
1040
1314
  console.log("");
1041
1315
  console.log(chalk6.bold(" Detected agent frameworks"));
@@ -1255,6 +1529,16 @@ async function registerAgentFlow(apiKey, ownerId) {
1255
1529
  }
1256
1530
  const detected = detectFrameworks();
1257
1531
  const shouldSetup = await frameworkSetupConsent(detected);
1532
+ let installReliabilityDroid = false;
1533
+ if (detected.factoryDroid && shouldSetup) {
1534
+ const { reliability } = await prompts3({
1535
+ type: "confirm",
1536
+ name: "reliability",
1537
+ message: "Also install AgentValet Reliability Droid for Factory Droid? (monitors agent governance)",
1538
+ initial: false
1539
+ });
1540
+ installReliabilityDroid = reliability ?? false;
1541
+ }
1258
1542
  if (shouldSetup) {
1259
1543
  console.log("");
1260
1544
  console.log(chalk7.bold(" Configuring agent frameworks..."));
@@ -1284,6 +1568,13 @@ async function registerAgentFlow(apiKey, ownerId) {
1284
1568
  if (detected.openclaw) {
1285
1569
  writeSkillMd();
1286
1570
  }
1571
+ if (detected.factoryDroid) {
1572
+ writeFactoryDroidDroid();
1573
+ writeFactoryDroidCommand();
1574
+ if (installReliabilityDroid) {
1575
+ writeFactoryDroidReliabilityDroid();
1576
+ }
1577
+ }
1287
1578
  writeQuickstartDoc({
1288
1579
  agentId: agent.agent_id,
1289
1580
  ownerId,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentvalet/register",
3
- "version": "0.4.12",
3
+ "version": "0.4.13",
4
4
  "description": "Self-register AI agents with AgentValet",
5
5
  "type": "module",
6
6
  "bin": {