@agentvault/agentvault 0.14.13 → 0.14.15
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.
- package/README.md +58 -190
- package/dist/__tests__/install-plugin.test.d.ts +2 -0
- package/dist/__tests__/install-plugin.test.d.ts.map +1 -0
- package/dist/cli.js +856 -494
- package/dist/cli.js.map +4 -4
- package/dist/create-agent.d.ts.map +1 -1
- package/dist/doctor.d.ts +41 -0
- package/dist/doctor.d.ts.map +1 -0
- package/dist/index.js +0 -76
- package/dist/index.js.map +1 -1
- package/dist/setup.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/channel.js +0 -2257
- package/dist/channel.js.map +0 -1
- package/dist/crypto-helpers.js +0 -4
- package/dist/crypto-helpers.js.map +0 -1
- package/dist/openclaw-plugin.js +0 -222
- package/dist/openclaw-plugin.js.map +0 -1
- package/dist/setup.js +0 -329
- package/dist/setup.js.map +0 -1
- package/dist/state.js +0 -61
- package/dist/state.js.map +0 -1
- package/dist/transport.js +0 -43
- package/dist/transport.js.map +0 -1
- package/dist/types.js +0 -2
- package/dist/types.js.map +0 -1
package/dist/cli.js
CHANGED
|
@@ -45103,22 +45103,6 @@ var init_scan_engine = __esm({
|
|
|
45103
45103
|
/\bghp_[a-zA-Z0-9]{36,}\b/g,
|
|
45104
45104
|
/\bglpat-[a-zA-Z0-9_-]{20,}\b/g,
|
|
45105
45105
|
/\bxoxb-[0-9]+-[0-9]+-[a-zA-Z0-9]+\b/g
|
|
45106
|
-
],
|
|
45107
|
-
prompt_injection: [
|
|
45108
|
-
/\bignore\s+(?:all\s+)?(?:previous|above|prior)\s+instructions\b/gi,
|
|
45109
|
-
/\byou\s+are\s+now\s+(?:a|an)\s+/gi,
|
|
45110
|
-
/\bsystem\s*:\s*you\b/gi,
|
|
45111
|
-
/\bDAN\s+mode\b/gi,
|
|
45112
|
-
/\bdo\s+anything\s+now\b/gi,
|
|
45113
|
-
/\bdo\s+not\s+follow\s+any\s+(?:other\s+)?rules\b/gi,
|
|
45114
|
-
/\bjailbreak\b/gi
|
|
45115
|
-
],
|
|
45116
|
-
shell_injection: [
|
|
45117
|
-
/\bcurl\s+.*\|\s*(?:sh|bash|zsh)\b/gi,
|
|
45118
|
-
/\beval\s*\(/gi,
|
|
45119
|
-
/\bexec\s*\(/gi,
|
|
45120
|
-
/\bchmod\s+\+x\b/gi,
|
|
45121
|
-
/\brm\s+-rf\s+\//gi
|
|
45122
45106
|
]
|
|
45123
45107
|
};
|
|
45124
45108
|
ScanEngine = class {
|
|
@@ -45230,24 +45214,6 @@ var init_scan_engine = __esm({
|
|
|
45230
45214
|
}
|
|
45231
45215
|
return false;
|
|
45232
45216
|
}
|
|
45233
|
-
if (builtinId === "prompt_injection") {
|
|
45234
|
-
const patterns = BUILTIN_PATTERNS.prompt_injection;
|
|
45235
|
-
for (const p2 of patterns) {
|
|
45236
|
-
const regex = new RegExp(p2.source, p2.flags);
|
|
45237
|
-
if (regex.test(text))
|
|
45238
|
-
return true;
|
|
45239
|
-
}
|
|
45240
|
-
return false;
|
|
45241
|
-
}
|
|
45242
|
-
if (builtinId === "shell_injection") {
|
|
45243
|
-
const patterns = BUILTIN_PATTERNS.shell_injection;
|
|
45244
|
-
for (const p2 of patterns) {
|
|
45245
|
-
const regex = new RegExp(p2.source, p2.flags);
|
|
45246
|
-
if (regex.test(text))
|
|
45247
|
-
return true;
|
|
45248
|
-
}
|
|
45249
|
-
return false;
|
|
45250
|
-
}
|
|
45251
45217
|
return false;
|
|
45252
45218
|
}
|
|
45253
45219
|
_buildMatchSummary(rule) {
|
|
@@ -45267,48 +45233,6 @@ var init_scan_engine = __esm({
|
|
|
45267
45233
|
_escapeRegex(str) {
|
|
45268
45234
|
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
45269
45235
|
}
|
|
45270
|
-
/**
|
|
45271
|
-
* Scan a workspace file (e.g. SOUL.md) against all builtin patterns.
|
|
45272
|
-
* Runs api_keys, pii_*, prompt_injection, and shell_injection checks
|
|
45273
|
-
* regardless of rule direction.
|
|
45274
|
-
*/
|
|
45275
|
-
static scanWorkspaceFile(content) {
|
|
45276
|
-
const violations = [];
|
|
45277
|
-
let blocked = false;
|
|
45278
|
-
let flagged = false;
|
|
45279
|
-
const checks = [
|
|
45280
|
-
{ id: "api_keys", action: "block" },
|
|
45281
|
-
{ id: "prompt_injection", action: "block" },
|
|
45282
|
-
{ id: "shell_injection", action: "block" },
|
|
45283
|
-
{ id: "pii_ssn", action: "flag" },
|
|
45284
|
-
{ id: "pii_credit_card", action: "flag" },
|
|
45285
|
-
{ id: "pii_email", action: "flag" }
|
|
45286
|
-
];
|
|
45287
|
-
for (const check of checks) {
|
|
45288
|
-
const patterns = BUILTIN_PATTERNS[check.id];
|
|
45289
|
-
if (!patterns)
|
|
45290
|
-
continue;
|
|
45291
|
-
for (const p2 of patterns) {
|
|
45292
|
-
const regex = new RegExp(p2.source, p2.flags);
|
|
45293
|
-
if (regex.test(content)) {
|
|
45294
|
-
violations.push({
|
|
45295
|
-
rule_id: `workspace_${check.id}`,
|
|
45296
|
-
rule_name: check.id,
|
|
45297
|
-
action: check.action,
|
|
45298
|
-
scanner_type: "builtin",
|
|
45299
|
-
match_summary: `builtin:${check.id}`
|
|
45300
|
-
});
|
|
45301
|
-
if (check.action === "block")
|
|
45302
|
-
blocked = true;
|
|
45303
|
-
if (check.action === "flag")
|
|
45304
|
-
flagged = true;
|
|
45305
|
-
break;
|
|
45306
|
-
}
|
|
45307
|
-
}
|
|
45308
|
-
}
|
|
45309
|
-
const status = blocked ? "blocked" : flagged ? "flagged" : "clean";
|
|
45310
|
-
return { status, violations };
|
|
45311
|
-
}
|
|
45312
45236
|
};
|
|
45313
45237
|
}
|
|
45314
45238
|
});
|
|
@@ -49268,187 +49192,861 @@ var init_index = __esm({
|
|
|
49268
49192
|
}
|
|
49269
49193
|
});
|
|
49270
49194
|
|
|
49271
|
-
// src/
|
|
49272
|
-
var
|
|
49273
|
-
__export(
|
|
49274
|
-
|
|
49275
|
-
|
|
49276
|
-
|
|
49195
|
+
// src/create-agent.ts
|
|
49196
|
+
var create_agent_exports = {};
|
|
49197
|
+
__export(create_agent_exports, {
|
|
49198
|
+
findNextPort: () => findNextPort,
|
|
49199
|
+
generateWorkspaceFiles: () => generateWorkspaceFiles,
|
|
49200
|
+
openclawHome: () => openclawHome,
|
|
49201
|
+
readOpenClawConfig: () => readOpenClawConfig,
|
|
49202
|
+
runCreateCommand: () => runCreateCommand
|
|
49277
49203
|
});
|
|
49278
|
-
import { execSync
|
|
49279
|
-
import
|
|
49280
|
-
import {
|
|
49281
|
-
|
|
49282
|
-
const
|
|
49283
|
-
|
|
49284
|
-
|
|
49285
|
-
|
|
49286
|
-
|
|
49287
|
-
|
|
49288
|
-
|
|
49289
|
-
|
|
49290
|
-
|
|
49291
|
-
|
|
49292
|
-
|
|
49293
|
-
|
|
49294
|
-
|
|
49295
|
-
|
|
49296
|
-
|
|
49297
|
-
|
|
49298
|
-
|
|
49299
|
-
|
|
49300
|
-
|
|
49301
|
-
|
|
49302
|
-
|
|
49303
|
-
const channel2 = new SecureChannel({
|
|
49304
|
-
inviteToken: token2,
|
|
49305
|
-
dataDir: dataDir2,
|
|
49306
|
-
apiUrl: apiUrl2,
|
|
49307
|
-
agentName: name2,
|
|
49308
|
-
onMessage: () => {
|
|
49309
|
-
},
|
|
49310
|
-
// Not handling messages during setup
|
|
49311
|
-
onStateChange: (state) => {
|
|
49312
|
-
switch (state) {
|
|
49313
|
-
case "enrolling":
|
|
49314
|
-
console.log(" Enrolling with AgentVault server...");
|
|
49315
|
-
break;
|
|
49316
|
-
case "polling":
|
|
49317
|
-
console.log(" Waiting for approval in your AgentVault dashboard...");
|
|
49318
|
-
if (channel2.fingerprint) {
|
|
49319
|
-
console.log(`
|
|
49320
|
-
Fingerprint: ${channel2.fingerprint}`);
|
|
49321
|
-
console.log(" Verify this fingerprint matches the one shown in your dashboard");
|
|
49322
|
-
console.log(" before clicking Approve.\n");
|
|
49323
|
-
}
|
|
49324
|
-
break;
|
|
49325
|
-
case "activating":
|
|
49326
|
-
console.log(" Approved! Setting up encryption...");
|
|
49327
|
-
break;
|
|
49328
|
-
case "ready":
|
|
49329
|
-
enrollDone = true;
|
|
49330
|
-
console.log(" \u2705 Enrollment complete! Secure channel established.\n");
|
|
49331
|
-
break;
|
|
49332
|
-
case "error":
|
|
49333
|
-
console.error(" \u274C Setup encountered an error.");
|
|
49334
|
-
break;
|
|
49204
|
+
import { execSync } from "node:child_process";
|
|
49205
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync, copyFileSync } from "node:fs";
|
|
49206
|
+
import { join as join4 } from "node:path";
|
|
49207
|
+
function openclawHome() {
|
|
49208
|
+
const home = process.env.HOME ?? process.env.USERPROFILE ?? "";
|
|
49209
|
+
return join4(home, ".openclaw");
|
|
49210
|
+
}
|
|
49211
|
+
function readOpenClawConfig(home) {
|
|
49212
|
+
const configPath = join4(home, "openclaw.json");
|
|
49213
|
+
const raw = readFileSync(configPath, "utf-8");
|
|
49214
|
+
return JSON.parse(raw);
|
|
49215
|
+
}
|
|
49216
|
+
function writeOpenClawConfig(home, config, backupSuffix) {
|
|
49217
|
+
const configPath = join4(home, "openclaw.json");
|
|
49218
|
+
const backupPath = `${configPath}.bak.pre-${backupSuffix}`;
|
|
49219
|
+
copyFileSync(configPath, backupPath);
|
|
49220
|
+
writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
|
|
49221
|
+
}
|
|
49222
|
+
function collectPorts(config) {
|
|
49223
|
+
const ports = [];
|
|
49224
|
+
const accounts = config?.channels?.agentvault?.accounts;
|
|
49225
|
+
if (accounts && typeof accounts === "object") {
|
|
49226
|
+
for (const acct of Object.values(accounts)) {
|
|
49227
|
+
if (typeof acct.httpPort === "number") {
|
|
49228
|
+
ports.push(acct.httpPort);
|
|
49335
49229
|
}
|
|
49336
49230
|
}
|
|
49337
|
-
}
|
|
49338
|
-
|
|
49339
|
-
|
|
49340
|
-
|
|
49341
|
-
|
|
49342
|
-
|
|
49343
|
-
|
|
49344
|
-
|
|
49345
|
-
|
|
49346
|
-
|
|
49347
|
-
|
|
49348
|
-
|
|
49349
|
-
|
|
49350
|
-
|
|
49351
|
-
|
|
49352
|
-
clearInterval(check);
|
|
49353
|
-
rej(err);
|
|
49354
|
-
});
|
|
49355
|
-
});
|
|
49356
|
-
await channel2.stop();
|
|
49357
|
-
console.log(" Installing AgentVault plugin in OpenClaw...\n");
|
|
49358
|
-
const home = process.env.HOME ?? "";
|
|
49359
|
-
const extraPaths = [
|
|
49360
|
-
`${home}/.local/bin`,
|
|
49361
|
-
`${home}/.pnpm/bin`,
|
|
49362
|
-
`${home}/Library/pnpm/bin`,
|
|
49363
|
-
"/usr/local/bin",
|
|
49364
|
-
"/opt/homebrew/bin"
|
|
49365
|
-
].join(":");
|
|
49366
|
-
const env = { ...process.env, PATH: `${extraPaths}:${process.env.PATH ?? ""}` };
|
|
49367
|
-
const pluginInstalled = installPlugin(env);
|
|
49368
|
-
if (!pluginInstalled) {
|
|
49369
|
-
if (options.accountId) {
|
|
49370
|
-
console.log(`
|
|
49371
|
-
\u26A0\uFE0F Could not auto-configure OpenClaw (is 'openclaw' in your PATH?).
|
|
49231
|
+
}
|
|
49232
|
+
return ports;
|
|
49233
|
+
}
|
|
49234
|
+
function findNextPort(config, startPort = 18800) {
|
|
49235
|
+
const ports = collectPorts(config);
|
|
49236
|
+
if (ports.length === 0) return startPort;
|
|
49237
|
+
return Math.max(...ports, startPort - 1) + 1;
|
|
49238
|
+
}
|
|
49239
|
+
function isPortInUse(config, port) {
|
|
49240
|
+
return collectPorts(config).includes(port);
|
|
49241
|
+
}
|
|
49242
|
+
function generateWorkspaceFiles(name2) {
|
|
49243
|
+
const displayName = name2.charAt(0).toUpperCase() + name2.slice(1).toLowerCase();
|
|
49244
|
+
return {
|
|
49245
|
+
"IDENTITY.md": `# IDENTITY.md - Who Am I?
|
|
49372
49246
|
|
|
49373
|
-
|
|
49374
|
-
|
|
49247
|
+
- **Name:** ${displayName}
|
|
49248
|
+
- **Creature:** AI assistant \u2014 a capable peer agent in the AgentVault network
|
|
49249
|
+
- **Vibe:** Direct, competent, focused on their specialty domain
|
|
49250
|
+
- **Emoji:** (placeholder \u2014 update to something fitting)
|
|
49251
|
+
- **Avatar:** _(none set yet)_
|
|
49375
49252
|
|
|
49376
|
-
|
|
49377
|
-
|
|
49253
|
+
> TODO: Customize this file to give ${name2} a distinct identity.
|
|
49254
|
+
`,
|
|
49255
|
+
"SOUL.md": `# SOUL.md - Who You Are
|
|
49378
49256
|
|
|
49379
|
-
|
|
49380
|
-
|
|
49381
|
-
agentvault:
|
|
49382
|
-
apiUrl: "${apiUrl2}"
|
|
49383
|
-
accounts:
|
|
49384
|
-
${options.accountId}:
|
|
49385
|
-
dataDir: "${dataDir2}"
|
|
49386
|
-
agentName: "${name2}"
|
|
49257
|
+
> TODO: Define ${name2}'s personality, tone, and behavioral rules.
|
|
49258
|
+
> Copy and adapt from ~/.openclaw/workspace/SOUL.md as a starting point.
|
|
49387
49259
|
|
|
49388
|
-
|
|
49389
|
-
npm install -g pm2
|
|
49390
|
-
pm2 start "openclaw gateway start" --name openclaw-gateway
|
|
49391
|
-
pm2 startup
|
|
49392
|
-
pm2 save
|
|
49260
|
+
## Core Truths
|
|
49393
49261
|
|
|
49394
|
-
|
|
49395
|
-
|
|
49396
|
-
|
|
49397
|
-
} else {
|
|
49398
|
-
console.log(`
|
|
49399
|
-
\u26A0\uFE0F Could not auto-configure OpenClaw (is 'openclaw' in your PATH?).
|
|
49262
|
+
- Be genuinely helpful, not performatively helpful.
|
|
49263
|
+
- Have opinions. Be resourceful before asking.
|
|
49264
|
+
- Earn trust through competence.
|
|
49400
49265
|
|
|
49401
|
-
|
|
49402
|
-
openclaw plugins install @agentvault/agentvault
|
|
49266
|
+
## Channel Reply Rules
|
|
49403
49267
|
|
|
49404
|
-
|
|
49405
|
-
|
|
49268
|
+
- Never include reasoning or internal logic in visible replies.
|
|
49269
|
+
- No narrating your approach before or after tool calls.
|
|
49270
|
+
- Just deliver the answer \u2014 clean and direct.
|
|
49406
49271
|
|
|
49407
|
-
|
|
49408
|
-
channels:
|
|
49409
|
-
agentvault:
|
|
49410
|
-
dataDir: "${dataDir2}"
|
|
49411
|
-
apiUrl: "${apiUrl2}"
|
|
49412
|
-
agentName: "${name2}"
|
|
49272
|
+
## Vibe
|
|
49413
49273
|
|
|
49414
|
-
|
|
49415
|
-
|
|
49416
|
-
|
|
49417
|
-
pm2 startup
|
|
49418
|
-
pm2 save
|
|
49274
|
+
_(Define ${name2}'s specific personality here.)_
|
|
49275
|
+
`,
|
|
49276
|
+
"HEARTBEAT.md": `# Heartbeat
|
|
49419
49277
|
|
|
49420
|
-
|
|
49421
|
-
|
|
49422
|
-
|
|
49423
|
-
|
|
49424
|
-
|
|
49425
|
-
|
|
49426
|
-
|
|
49427
|
-
|
|
49428
|
-
|
|
49429
|
-
|
|
49430
|
-
|
|
49431
|
-
|
|
49432
|
-
|
|
49433
|
-
|
|
49434
|
-
|
|
49435
|
-
|
|
49436
|
-
|
|
49437
|
-
|
|
49438
|
-
|
|
49439
|
-
|
|
49440
|
-
|
|
49441
|
-
|
|
49278
|
+
- Stay available. If nothing needs attention, reply HEARTBEAT_OK.
|
|
49279
|
+
- **Heartbeat replies are INTERNAL ONLY.** Reply with ONLY \`HEARTBEAT_OK\` when nothing needs attention.
|
|
49280
|
+
- If something genuinely urgent needs attention, send it proactively FIRST, THEN reply HEARTBEAT_OK.
|
|
49281
|
+
`,
|
|
49282
|
+
"MEMORY.md": `# MEMORY.md - Long-Term Memory
|
|
49283
|
+
|
|
49284
|
+
_(Empty \u2014 ${name2} starts with a clean memory. Update as the agent learns.)_
|
|
49285
|
+
`
|
|
49286
|
+
};
|
|
49287
|
+
}
|
|
49288
|
+
async function runCreateCommand(options) {
|
|
49289
|
+
const { name: name2, token: token2, apiUrl: apiUrl2, force } = options;
|
|
49290
|
+
const home = openclawHome();
|
|
49291
|
+
const configPath = join4(home, "openclaw.json");
|
|
49292
|
+
const workspaceDir = join4(home, `workspace-${name2}`);
|
|
49293
|
+
const dataDir2 = join4(home, "agents", name2, "agentvault-data");
|
|
49294
|
+
const templateDir = join4(home, "workspace");
|
|
49295
|
+
console.log(`
|
|
49296
|
+
\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557
|
|
49297
|
+
\u2551 AgentVault \u2014 Create New Agent \u2551
|
|
49298
|
+
\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D
|
|
49299
|
+
`);
|
|
49300
|
+
console.log(" Step 1/7 \u2014 Preflight checks...");
|
|
49301
|
+
try {
|
|
49302
|
+
execSync("openclaw --version", { stdio: "pipe" });
|
|
49303
|
+
} catch {
|
|
49304
|
+
console.error(" Error: 'openclaw' not found in PATH. Is OpenClaw installed?");
|
|
49305
|
+
process.exit(1);
|
|
49306
|
+
}
|
|
49307
|
+
if (!existsSync(configPath)) {
|
|
49308
|
+
console.error(` Error: openclaw.json not found at ${configPath}`);
|
|
49309
|
+
process.exit(1);
|
|
49310
|
+
}
|
|
49311
|
+
console.log(" Preflight passed.\n");
|
|
49312
|
+
console.log(" Step 2/7 \u2014 Detecting port...");
|
|
49313
|
+
const config = readOpenClawConfig(home);
|
|
49314
|
+
let port;
|
|
49315
|
+
if (options.port != null) {
|
|
49316
|
+
port = options.port;
|
|
49317
|
+
if (isPortInUse(config, port)) {
|
|
49318
|
+
console.error(` Error: Port ${port} is already in use in openclaw.json.`);
|
|
49319
|
+
process.exit(1);
|
|
49320
|
+
}
|
|
49321
|
+
console.log(` Using explicit port ${port}.
|
|
49322
|
+
`);
|
|
49323
|
+
} else {
|
|
49324
|
+
port = findNextPort(config);
|
|
49325
|
+
console.log(` Auto-assigned port ${port}.
|
|
49326
|
+
`);
|
|
49327
|
+
}
|
|
49328
|
+
console.log(" Step 3/7 \u2014 Creating agent with OpenClaw...");
|
|
49329
|
+
try {
|
|
49330
|
+
execSync(`openclaw agents add -- ${name2}`, { stdio: "pipe" });
|
|
49331
|
+
console.log(` Agent '${name2}' created.
|
|
49332
|
+
`);
|
|
49333
|
+
} catch {
|
|
49334
|
+
console.log(` Warning: 'openclaw agents add' failed \u2014 agent may already exist. Continuing.
|
|
49335
|
+
`);
|
|
49336
|
+
}
|
|
49337
|
+
console.log(" Step 4/7 \u2014 Creating directories...");
|
|
49338
|
+
mkdirSync(workspaceDir, { recursive: true });
|
|
49339
|
+
mkdirSync(dataDir2, { recursive: true });
|
|
49340
|
+
console.log(` Workspace: ${workspaceDir}`);
|
|
49341
|
+
console.log(` DataDir: ${dataDir2}
|
|
49342
|
+
`);
|
|
49343
|
+
console.log(" Step 5/7 \u2014 Writing workspace files...");
|
|
49344
|
+
const files = generateWorkspaceFiles(name2);
|
|
49345
|
+
for (const [filename, content] of Object.entries(files)) {
|
|
49346
|
+
writeFileSync(join4(workspaceDir, filename), content, "utf-8");
|
|
49347
|
+
}
|
|
49348
|
+
for (const copyFile of ["AGENTS.md", "USER.md"]) {
|
|
49349
|
+
const src = join4(templateDir, copyFile);
|
|
49350
|
+
if (existsSync(src)) {
|
|
49351
|
+
copyFileSync(src, join4(workspaceDir, copyFile));
|
|
49352
|
+
console.log(` Copied ${copyFile} from template workspace.`);
|
|
49353
|
+
}
|
|
49354
|
+
}
|
|
49355
|
+
console.log(" Workspace files written.\n");
|
|
49356
|
+
console.log(" Step 6/7 \u2014 Enrolling with AgentVault...\n");
|
|
49357
|
+
await runSetupCommand({
|
|
49358
|
+
token: token2,
|
|
49359
|
+
name: name2,
|
|
49360
|
+
apiUrl: apiUrl2,
|
|
49361
|
+
dataDir: dataDir2,
|
|
49362
|
+
accountId: name2,
|
|
49363
|
+
force
|
|
49364
|
+
});
|
|
49365
|
+
console.log("\n Step 7/7 \u2014 Patching openclaw.json...");
|
|
49366
|
+
try {
|
|
49367
|
+
const freshConfig = readOpenClawConfig(home);
|
|
49368
|
+
let patched = false;
|
|
49369
|
+
const avChannel = freshConfig?.channels?.agentvault;
|
|
49370
|
+
if (avChannel?.accounts) {
|
|
49371
|
+
const acct = avChannel.accounts[name2];
|
|
49372
|
+
if (acct) {
|
|
49373
|
+
acct.httpPort = port;
|
|
49374
|
+
patched = true;
|
|
49375
|
+
}
|
|
49376
|
+
}
|
|
49377
|
+
if (avChannel) {
|
|
49378
|
+
const bindings = avChannel.bindings;
|
|
49379
|
+
const hasWildcard = bindings?.some(
|
|
49380
|
+
(b2) => b2.match?.accountId === "*"
|
|
49381
|
+
);
|
|
49382
|
+
if (!hasWildcard) {
|
|
49383
|
+
avChannel.bindings = [{ match: { accountId: "*" } }, ...bindings ?? []];
|
|
49384
|
+
console.log(` Added wildcard binding (accountId: "*").`);
|
|
49385
|
+
}
|
|
49386
|
+
}
|
|
49387
|
+
if (patched) {
|
|
49388
|
+
writeOpenClawConfig(home, freshConfig, name2);
|
|
49389
|
+
console.log(` httpPort set to ${port}.
|
|
49390
|
+
`);
|
|
49391
|
+
} else {
|
|
49392
|
+
console.log(` Warning: Could not find account '${name2}' in channels.agentvault.accounts.`);
|
|
49393
|
+
console.log(` You may need to manually set httpPort: ${port} in openclaw.json.
|
|
49394
|
+
`);
|
|
49395
|
+
}
|
|
49396
|
+
} catch (err) {
|
|
49397
|
+
console.log(` Warning: Failed to patch openclaw.json: ${err.message}
|
|
49398
|
+
`);
|
|
49399
|
+
}
|
|
49400
|
+
console.log(" Verifying agent...");
|
|
49401
|
+
try {
|
|
49402
|
+
const http = await import("node:http");
|
|
49403
|
+
await new Promise((resolve4) => {
|
|
49404
|
+
const req = http.get(`http://127.0.0.1:${port}/status`, { timeout: 3e3 }, (res) => {
|
|
49405
|
+
console.log(` Port ${port} responded (HTTP ${res.statusCode}).`);
|
|
49406
|
+
res.resume();
|
|
49407
|
+
resolve4();
|
|
49408
|
+
});
|
|
49409
|
+
req.on("error", () => {
|
|
49410
|
+
console.log(` Port ${port} not yet responding \u2014 gateway may need a moment.`);
|
|
49411
|
+
resolve4();
|
|
49412
|
+
});
|
|
49413
|
+
req.on("timeout", () => {
|
|
49414
|
+
req.destroy();
|
|
49415
|
+
console.log(` Port ${port} timed out \u2014 check gateway logs.`);
|
|
49416
|
+
resolve4();
|
|
49417
|
+
});
|
|
49418
|
+
});
|
|
49419
|
+
} catch {
|
|
49420
|
+
console.log(" Verification skipped.");
|
|
49421
|
+
}
|
|
49422
|
+
if (process.platform === "darwin") {
|
|
49423
|
+
const { validatePlist: validatePlist2 } = await init_doctor().then(() => doctor_exports);
|
|
49424
|
+
const plistResult = validatePlist2();
|
|
49425
|
+
if (plistResult.status === "stale") {
|
|
49426
|
+
console.log(`
|
|
49427
|
+
\u26A0\uFE0F macOS LaunchAgent plist has stale paths.
|
|
49428
|
+
Run to diagnose and fix: npx @agentvault/agentvault doctor
|
|
49429
|
+
`);
|
|
49430
|
+
}
|
|
49431
|
+
}
|
|
49432
|
+
console.log(`
|
|
49433
|
+
\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550
|
|
49434
|
+
Agent '${name2}' created successfully!
|
|
49435
|
+
\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550
|
|
49436
|
+
|
|
49437
|
+
Workspace: ${workspaceDir}
|
|
49438
|
+
DataDir: ${dataDir2}
|
|
49439
|
+
HTTP Port: ${port}
|
|
49440
|
+
|
|
49441
|
+
Next steps:
|
|
49442
|
+
1. Edit ${workspaceDir}/SOUL.md \u2014 give ${name2} a personality
|
|
49443
|
+
2. Edit ${workspaceDir}/IDENTITY.md \u2014 set name, emoji, vibe
|
|
49444
|
+
3. Approve the agent in the AgentVault app
|
|
49445
|
+
`);
|
|
49446
|
+
}
|
|
49447
|
+
var init_create_agent = __esm({
|
|
49448
|
+
async "src/create-agent.ts"() {
|
|
49449
|
+
"use strict";
|
|
49450
|
+
await init_setup();
|
|
49451
|
+
}
|
|
49452
|
+
});
|
|
49453
|
+
|
|
49454
|
+
// src/doctor.ts
|
|
49455
|
+
var doctor_exports = {};
|
|
49456
|
+
__export(doctor_exports, {
|
|
49457
|
+
applyPlistFix: () => applyPlistFix,
|
|
49458
|
+
checkAgentDataDirs: () => checkAgentDataDirs,
|
|
49459
|
+
checkAgentVaultChannel: () => checkAgentVaultChannel,
|
|
49460
|
+
checkConfigExists: () => checkConfigExists,
|
|
49461
|
+
checkGatewayPort: () => checkGatewayPort,
|
|
49462
|
+
checkOpenClawInstalled: () => checkOpenClawInstalled,
|
|
49463
|
+
checkPlist: () => checkPlist,
|
|
49464
|
+
checkPluginsAllow: () => checkPluginsAllow,
|
|
49465
|
+
checkPm2Status: () => checkPm2Status,
|
|
49466
|
+
parsePlist: () => parsePlist,
|
|
49467
|
+
plistPath: () => plistPath,
|
|
49468
|
+
runDoctorCommand: () => runDoctorCommand,
|
|
49469
|
+
validatePlist: () => validatePlist
|
|
49470
|
+
});
|
|
49471
|
+
import { execSync as execSync2 } from "node:child_process";
|
|
49472
|
+
import { existsSync as existsSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2, chmodSync } from "node:fs";
|
|
49473
|
+
import { join as join5 } from "node:path";
|
|
49474
|
+
import { createInterface } from "node:readline";
|
|
49475
|
+
function checkOpenClawInstalled() {
|
|
49476
|
+
try {
|
|
49477
|
+
const out = execSync2("openclaw --version", { stdio: "pipe", timeout: 1e4 });
|
|
49478
|
+
const version = out.toString().trim();
|
|
49479
|
+
return { name: "OpenClaw installed", status: "pass", message: version };
|
|
49480
|
+
} catch {
|
|
49481
|
+
return {
|
|
49482
|
+
name: "OpenClaw installed",
|
|
49483
|
+
status: "fail",
|
|
49484
|
+
message: "'openclaw' not found in PATH"
|
|
49485
|
+
};
|
|
49486
|
+
}
|
|
49487
|
+
}
|
|
49488
|
+
function checkConfigExists(home) {
|
|
49489
|
+
const configPath = join5(home, "openclaw.json");
|
|
49490
|
+
if (!existsSync2(configPath)) {
|
|
49491
|
+
return {
|
|
49492
|
+
name: "Config exists",
|
|
49493
|
+
status: "fail",
|
|
49494
|
+
message: `Not found: ${configPath}`
|
|
49495
|
+
};
|
|
49496
|
+
}
|
|
49497
|
+
try {
|
|
49498
|
+
JSON.parse(readFileSync2(configPath, "utf-8"));
|
|
49499
|
+
return { name: "Config exists", status: "pass", message: configPath };
|
|
49500
|
+
} catch {
|
|
49501
|
+
return {
|
|
49502
|
+
name: "Config exists",
|
|
49503
|
+
status: "fail",
|
|
49504
|
+
message: `Invalid JSON: ${configPath}`
|
|
49505
|
+
};
|
|
49506
|
+
}
|
|
49507
|
+
}
|
|
49508
|
+
function checkAgentVaultChannel(config) {
|
|
49509
|
+
if (!config) {
|
|
49510
|
+
return {
|
|
49511
|
+
name: "AgentVault channel",
|
|
49512
|
+
status: "fail",
|
|
49513
|
+
message: "Config is null"
|
|
49514
|
+
};
|
|
49515
|
+
}
|
|
49516
|
+
if (config.channels?.agentvault) {
|
|
49517
|
+
return { name: "AgentVault channel", status: "pass", message: "channels.agentvault present" };
|
|
49518
|
+
}
|
|
49519
|
+
return {
|
|
49520
|
+
name: "AgentVault channel",
|
|
49521
|
+
status: "fail",
|
|
49522
|
+
message: "channels.agentvault not found in config"
|
|
49523
|
+
};
|
|
49524
|
+
}
|
|
49525
|
+
function checkPluginsAllow(config) {
|
|
49526
|
+
if (!config) {
|
|
49527
|
+
return { name: "Plugin allow-listed", status: "warn", message: "Config is null" };
|
|
49528
|
+
}
|
|
49529
|
+
const allow = config.plugins?.allow;
|
|
49530
|
+
if (!Array.isArray(allow)) {
|
|
49531
|
+
return {
|
|
49532
|
+
name: "Plugin allow-listed",
|
|
49533
|
+
status: "warn",
|
|
49534
|
+
message: "plugins.allow not defined"
|
|
49535
|
+
};
|
|
49536
|
+
}
|
|
49537
|
+
if (allow.includes("agentvault")) {
|
|
49538
|
+
return { name: "Plugin allow-listed", status: "pass", message: "agentvault in plugins.allow" };
|
|
49539
|
+
}
|
|
49540
|
+
return {
|
|
49541
|
+
name: "Plugin allow-listed",
|
|
49542
|
+
status: "warn",
|
|
49543
|
+
message: "'agentvault' not in plugins.allow list"
|
|
49544
|
+
};
|
|
49545
|
+
}
|
|
49546
|
+
function checkPlist() {
|
|
49547
|
+
if (process.platform !== "darwin") {
|
|
49548
|
+
return { name: "macOS LaunchAgent plist", status: "skip", message: "Not macOS" };
|
|
49549
|
+
}
|
|
49550
|
+
const result = validatePlist();
|
|
49551
|
+
switch (result.status) {
|
|
49552
|
+
case "ok":
|
|
49553
|
+
return { name: "macOS LaunchAgent plist", status: "pass", message: "Plist paths valid" };
|
|
49554
|
+
case "already-fixed":
|
|
49555
|
+
return { name: "macOS LaunchAgent plist", status: "pass", message: "Wrapper script already configured" };
|
|
49556
|
+
case "stale":
|
|
49557
|
+
return {
|
|
49558
|
+
name: "macOS LaunchAgent plist",
|
|
49559
|
+
status: "fail",
|
|
49560
|
+
message: `Stale path: ${result.stalePaths?.[0] ?? "unknown"}`
|
|
49561
|
+
};
|
|
49562
|
+
case "missing":
|
|
49563
|
+
return {
|
|
49564
|
+
name: "macOS LaunchAgent plist",
|
|
49565
|
+
status: "warn",
|
|
49566
|
+
message: `Plist not found: ${result.plistPath ?? PLIST_FILENAME}`
|
|
49567
|
+
};
|
|
49568
|
+
default:
|
|
49569
|
+
return { name: "macOS LaunchAgent plist", status: "skip", message: "Skipped" };
|
|
49570
|
+
}
|
|
49571
|
+
}
|
|
49572
|
+
function checkGatewayPort() {
|
|
49573
|
+
try {
|
|
49574
|
+
execSync2("curl -sf --max-time 3 http://127.0.0.1:18789/", { stdio: "pipe" });
|
|
49575
|
+
return { name: "Gateway port (18789)", status: "pass", message: "Responding" };
|
|
49576
|
+
} catch {
|
|
49577
|
+
return {
|
|
49578
|
+
name: "Gateway port (18789)",
|
|
49579
|
+
status: "fail",
|
|
49580
|
+
message: "No response on 127.0.0.1:18789"
|
|
49581
|
+
};
|
|
49582
|
+
}
|
|
49583
|
+
}
|
|
49584
|
+
function checkAgentDataDirs(config) {
|
|
49585
|
+
if (!config) {
|
|
49586
|
+
return { name: "Agent data dirs", status: "warn", message: "Config is null" };
|
|
49587
|
+
}
|
|
49588
|
+
const home = process.env.HOME ?? "";
|
|
49589
|
+
const warnings = [];
|
|
49590
|
+
const av = config.channels?.agentvault;
|
|
49591
|
+
if (!av) {
|
|
49592
|
+
return { name: "Agent data dirs", status: "warn", message: "No agentvault channel" };
|
|
49593
|
+
}
|
|
49594
|
+
const checkDir = (label, dataDir2) => {
|
|
49595
|
+
const resolved = dataDir2.replace(/^~/, home);
|
|
49596
|
+
if (!existsSync2(resolved)) {
|
|
49597
|
+
warnings.push(`${label}: dir missing (${resolved})`);
|
|
49598
|
+
return;
|
|
49599
|
+
}
|
|
49600
|
+
const statePath2 = join5(resolved, "agentvault.json");
|
|
49601
|
+
if (!existsSync2(statePath2)) {
|
|
49602
|
+
warnings.push(`${label}: no agentvault.json`);
|
|
49603
|
+
}
|
|
49604
|
+
};
|
|
49605
|
+
if (av.accounts && typeof av.accounts === "object") {
|
|
49606
|
+
for (const [id, acct] of Object.entries(av.accounts)) {
|
|
49607
|
+
if (acct.dataDir) checkDir(id, acct.dataDir);
|
|
49608
|
+
}
|
|
49609
|
+
} else if (av.dataDir) {
|
|
49610
|
+
checkDir("default", av.dataDir);
|
|
49611
|
+
}
|
|
49612
|
+
if (warnings.length > 0) {
|
|
49613
|
+
return { name: "Agent data dirs", status: "warn", message: warnings.join("; ") };
|
|
49614
|
+
}
|
|
49615
|
+
return { name: "Agent data dirs", status: "pass", message: "All data dirs valid" };
|
|
49616
|
+
}
|
|
49617
|
+
function checkPm2Status() {
|
|
49618
|
+
try {
|
|
49619
|
+
execSync2("pm2 --version", { stdio: "pipe", timeout: 5e3 });
|
|
49620
|
+
} catch {
|
|
49621
|
+
return { name: "pm2 status", status: "skip", message: "pm2 not installed" };
|
|
49622
|
+
}
|
|
49623
|
+
try {
|
|
49624
|
+
const info = execSync2("pm2 describe openclaw-gateway", { stdio: "pipe", timeout: 5e3 });
|
|
49625
|
+
const out = info.toString();
|
|
49626
|
+
if (out.includes("online")) {
|
|
49627
|
+
return { name: "pm2 status", status: "pass", message: "openclaw-gateway: online" };
|
|
49628
|
+
}
|
|
49629
|
+
if (out.includes("stopped")) {
|
|
49630
|
+
return { name: "pm2 status", status: "warn", message: "openclaw-gateway: stopped" };
|
|
49631
|
+
}
|
|
49632
|
+
return { name: "pm2 status", status: "warn", message: "openclaw-gateway: unknown state" };
|
|
49633
|
+
} catch {
|
|
49634
|
+
return { name: "pm2 status", status: "warn", message: "openclaw-gateway not registered in pm2" };
|
|
49635
|
+
}
|
|
49636
|
+
}
|
|
49637
|
+
function plistPath() {
|
|
49638
|
+
const home = process.env.HOME ?? "";
|
|
49639
|
+
return join5(home, "Library", "LaunchAgents", PLIST_FILENAME);
|
|
49640
|
+
}
|
|
49641
|
+
function parsePlist(plistFile) {
|
|
49642
|
+
if (!existsSync2(plistFile)) return null;
|
|
49643
|
+
try {
|
|
49644
|
+
const json = execSync2(`plutil -convert json -o - "${plistFile}"`, {
|
|
49645
|
+
stdio: "pipe",
|
|
49646
|
+
timeout: 5e3
|
|
49647
|
+
}).toString();
|
|
49648
|
+
const parsed = JSON.parse(json);
|
|
49649
|
+
const programArgs = parsed.ProgramArguments ?? [];
|
|
49650
|
+
const stalePaths = [];
|
|
49651
|
+
const wrapperPath = join5(process.env.HOME ?? "", ".openclaw", WRAPPER_SCRIPT_NAME);
|
|
49652
|
+
for (const arg of programArgs) {
|
|
49653
|
+
if (arg.startsWith("/") && arg !== "/bin/bash" && arg !== wrapperPath) {
|
|
49654
|
+
if (!existsSync2(arg)) {
|
|
49655
|
+
stalePaths.push(arg);
|
|
49656
|
+
}
|
|
49657
|
+
}
|
|
49658
|
+
}
|
|
49659
|
+
return { plistPath: plistFile, programArgs, stalePaths };
|
|
49660
|
+
} catch {
|
|
49661
|
+
return null;
|
|
49662
|
+
}
|
|
49663
|
+
}
|
|
49664
|
+
function validatePlist() {
|
|
49665
|
+
if (process.platform !== "darwin") {
|
|
49666
|
+
return { status: "skip" };
|
|
49667
|
+
}
|
|
49668
|
+
const path = plistPath();
|
|
49669
|
+
if (!existsSync2(path)) {
|
|
49670
|
+
return { status: "missing", plistPath: path };
|
|
49671
|
+
}
|
|
49672
|
+
const info = parsePlist(path);
|
|
49673
|
+
if (!info) {
|
|
49674
|
+
return { status: "missing", plistPath: path };
|
|
49675
|
+
}
|
|
49676
|
+
const home = process.env.HOME ?? "";
|
|
49677
|
+
const wrapperPath = join5(home, ".openclaw", WRAPPER_SCRIPT_NAME);
|
|
49678
|
+
if (info.programArgs.includes(wrapperPath)) {
|
|
49679
|
+
return { status: "already-fixed", plistPath: path };
|
|
49680
|
+
}
|
|
49681
|
+
if (info.stalePaths.length > 0) {
|
|
49682
|
+
return { status: "stale", plistPath: path, stalePaths: info.stalePaths };
|
|
49683
|
+
}
|
|
49684
|
+
return { status: "ok", plistPath: path };
|
|
49685
|
+
}
|
|
49686
|
+
function applyPlistFix(info) {
|
|
49687
|
+
const home = process.env.HOME ?? "";
|
|
49688
|
+
const openclawDir = join5(home, ".openclaw");
|
|
49689
|
+
const wrapperPath = join5(openclawDir, WRAPPER_SCRIPT_NAME);
|
|
49690
|
+
const wrapperContent = `#!/bin/bash
|
|
49691
|
+
export PATH="$HOME/.local/bin:$HOME/.pnpm/bin:$HOME/Library/pnpm/bin:$HOME/Library/pnpm:/opt/homebrew/bin:/usr/local/bin:$PATH"
|
|
49692
|
+
exec "$(which openclaw)" gateway start "$@"
|
|
49693
|
+
`;
|
|
49694
|
+
try {
|
|
49695
|
+
writeFileSync2(wrapperPath, wrapperContent, "utf-8");
|
|
49696
|
+
chmodSync(wrapperPath, 493);
|
|
49697
|
+
console.log(` Created wrapper: ${wrapperPath}`);
|
|
49698
|
+
} catch (err) {
|
|
49699
|
+
console.error(` Failed to create wrapper script: ${err.message}`);
|
|
49700
|
+
return false;
|
|
49701
|
+
}
|
|
49702
|
+
const plistBuddy = "/usr/libexec/PlistBuddy";
|
|
49703
|
+
const plist = info.plistPath;
|
|
49704
|
+
try {
|
|
49705
|
+
execSync2(`${plistBuddy} -c "Set :ProgramArguments:0 /bin/bash" "${plist}"`, { stdio: "pipe" });
|
|
49706
|
+
try {
|
|
49707
|
+
execSync2(`${plistBuddy} -c "Set :ProgramArguments:1 ${wrapperPath}" "${plist}"`, { stdio: "pipe" });
|
|
49708
|
+
} catch {
|
|
49709
|
+
execSync2(`${plistBuddy} -c "Add :ProgramArguments:1 string ${wrapperPath}" "${plist}"`, { stdio: "pipe" });
|
|
49710
|
+
}
|
|
49711
|
+
let argCount = info.programArgs.length;
|
|
49712
|
+
for (let i2 = argCount - 1; i2 >= 2; i2--) {
|
|
49713
|
+
try {
|
|
49714
|
+
execSync2(`${plistBuddy} -c "Delete :ProgramArguments:${i2}" "${plist}"`, { stdio: "pipe" });
|
|
49715
|
+
} catch {
|
|
49716
|
+
}
|
|
49717
|
+
}
|
|
49718
|
+
console.log(" Updated plist ProgramArguments.");
|
|
49719
|
+
} catch (err) {
|
|
49720
|
+
console.error(` Failed to update plist: ${err.message}`);
|
|
49721
|
+
return false;
|
|
49722
|
+
}
|
|
49723
|
+
try {
|
|
49724
|
+
execSync2(`launchctl unload "${plist}"`, { stdio: "pipe" });
|
|
49725
|
+
} catch {
|
|
49726
|
+
}
|
|
49727
|
+
try {
|
|
49728
|
+
execSync2(`launchctl load "${plist}"`, { stdio: "pipe" });
|
|
49729
|
+
console.log(" Reloaded LaunchAgent.");
|
|
49730
|
+
} catch (err) {
|
|
49731
|
+
console.error(` Failed to reload LaunchAgent: ${err.message}`);
|
|
49732
|
+
console.log(` Try manually: launchctl load "${plist}"`);
|
|
49733
|
+
return false;
|
|
49734
|
+
}
|
|
49735
|
+
return true;
|
|
49736
|
+
}
|
|
49737
|
+
async function runDoctorCommand(options) {
|
|
49738
|
+
const home = openclawHome();
|
|
49739
|
+
console.log(`
|
|
49740
|
+
\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557
|
|
49741
|
+
\u2551 AgentVault \u2014 Doctor Diagnostics \u2551
|
|
49742
|
+
\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D
|
|
49743
|
+
`);
|
|
49744
|
+
const results = [];
|
|
49745
|
+
results.push(checkOpenClawInstalled());
|
|
49746
|
+
results.push(checkConfigExists(home));
|
|
49747
|
+
let config = null;
|
|
49748
|
+
try {
|
|
49749
|
+
config = readOpenClawConfig(home);
|
|
49750
|
+
} catch {
|
|
49751
|
+
}
|
|
49752
|
+
results.push(checkAgentVaultChannel(config));
|
|
49753
|
+
results.push(checkPluginsAllow(config));
|
|
49754
|
+
results.push(checkPlist());
|
|
49755
|
+
results.push(checkGatewayPort());
|
|
49756
|
+
results.push(checkAgentDataDirs(config));
|
|
49757
|
+
results.push(checkPm2Status());
|
|
49758
|
+
const statusLabels = {
|
|
49759
|
+
pass: "pass",
|
|
49760
|
+
warn: "WARN",
|
|
49761
|
+
fail: "FAIL",
|
|
49762
|
+
skip: "skip"
|
|
49763
|
+
};
|
|
49764
|
+
for (const r2 of results) {
|
|
49765
|
+
const label = `[${statusLabels[r2.status]}]`;
|
|
49766
|
+
console.log(` ${label.padEnd(6)} ${r2.name} \u2014 ${r2.message}`);
|
|
49767
|
+
}
|
|
49768
|
+
const passed = results.filter((r2) => r2.status === "pass").length;
|
|
49769
|
+
const warnings = results.filter((r2) => r2.status === "warn").length;
|
|
49770
|
+
const failed = results.filter((r2) => r2.status === "fail").length;
|
|
49771
|
+
console.log(`
|
|
49772
|
+
\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
49773
|
+
${passed} passed ${warnings} warnings ${failed} failed
|
|
49774
|
+
\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
49775
|
+
`);
|
|
49776
|
+
if (failed > 0) {
|
|
49777
|
+
process.exitCode = 1;
|
|
49778
|
+
}
|
|
49779
|
+
const plistResult = validatePlist();
|
|
49780
|
+
if (plistResult.status === "stale") {
|
|
49781
|
+
const plistInfo = parsePlist(plistResult.plistPath);
|
|
49782
|
+
if (!plistInfo) return;
|
|
49783
|
+
if (options?.fix) {
|
|
49784
|
+
console.log(" Applying plist fix (--fix)...\n");
|
|
49785
|
+
const ok = applyPlistFix(plistInfo);
|
|
49786
|
+
if (ok) {
|
|
49787
|
+
console.log("\n \u2705 Plist fixed. Gateway should start cleanly now.\n");
|
|
49788
|
+
} else {
|
|
49789
|
+
console.log("\n \u274C Plist fix failed. See errors above.\n");
|
|
49790
|
+
}
|
|
49791
|
+
} else {
|
|
49792
|
+
const answer = await ask(" Stale plist detected. Apply wrapper script fix? [y/N] ");
|
|
49793
|
+
if (answer.trim().toLowerCase() === "y") {
|
|
49794
|
+
console.log("");
|
|
49795
|
+
const ok = applyPlistFix(plistInfo);
|
|
49796
|
+
if (ok) {
|
|
49797
|
+
console.log("\n \u2705 Plist fixed. Gateway should start cleanly now.\n");
|
|
49798
|
+
} else {
|
|
49799
|
+
console.log("\n \u274C Plist fix failed. See errors above.\n");
|
|
49800
|
+
}
|
|
49801
|
+
} else {
|
|
49802
|
+
console.log(`
|
|
49803
|
+
To fix later, run:
|
|
49804
|
+
npx @agentvault/agentvault doctor --fix
|
|
49805
|
+
`);
|
|
49806
|
+
}
|
|
49807
|
+
}
|
|
49808
|
+
}
|
|
49809
|
+
}
|
|
49810
|
+
function ask(question) {
|
|
49811
|
+
return new Promise((resolve4) => {
|
|
49812
|
+
const rl2 = createInterface({
|
|
49813
|
+
input: process.stdin,
|
|
49814
|
+
output: process.stdout,
|
|
49815
|
+
terminal: true
|
|
49816
|
+
});
|
|
49817
|
+
rl2.question(question, (answer) => {
|
|
49818
|
+
rl2.close();
|
|
49819
|
+
resolve4(answer);
|
|
49820
|
+
});
|
|
49821
|
+
});
|
|
49822
|
+
}
|
|
49823
|
+
var PLIST_FILENAME, WRAPPER_SCRIPT_NAME;
|
|
49824
|
+
var init_doctor = __esm({
|
|
49825
|
+
async "src/doctor.ts"() {
|
|
49826
|
+
"use strict";
|
|
49827
|
+
await init_create_agent();
|
|
49828
|
+
PLIST_FILENAME = "ai.openclaw.gateway.plist";
|
|
49829
|
+
WRAPPER_SCRIPT_NAME = "start-gateway.sh";
|
|
49830
|
+
}
|
|
49831
|
+
});
|
|
49832
|
+
|
|
49833
|
+
// src/setup.ts
|
|
49834
|
+
var setup_exports = {};
|
|
49835
|
+
__export(setup_exports, {
|
|
49836
|
+
configurePm2: () => configurePm2,
|
|
49837
|
+
installPlugin: () => installPlugin,
|
|
49838
|
+
runSetupCommand: () => runSetupCommand
|
|
49839
|
+
});
|
|
49840
|
+
import { execSync as execSync3, spawnSync } from "node:child_process";
|
|
49841
|
+
import * as readline from "node:readline";
|
|
49842
|
+
import { resolve } from "node:path";
|
|
49843
|
+
async function runSetupCommand(options) {
|
|
49844
|
+
const { token: token2, name: name2, apiUrl: apiUrl2 } = options;
|
|
49845
|
+
const dataDir2 = resolve(options.dataDir.replace(/^~/, process.env.HOME ?? "~"));
|
|
49846
|
+
const alreadyEnrolled = await isStateValid(dataDir2);
|
|
49847
|
+
if (alreadyEnrolled && !options.force) {
|
|
49848
|
+
console.log(`
|
|
49849
|
+
Already enrolled (state in ${dataDir2}).
|
|
49850
|
+
Re-enroll with --force, or update plugin with: openclaw plugins update agentvault
|
|
49851
|
+
`);
|
|
49852
|
+
return;
|
|
49853
|
+
}
|
|
49854
|
+
console.log(`
|
|
49855
|
+
\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557
|
|
49856
|
+
\u2551 AgentVault \u2014 First-Time Setup \u2551
|
|
49857
|
+
\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D
|
|
49858
|
+
|
|
49859
|
+
Agent name : ${name2}${options.accountId ? `
|
|
49860
|
+
Account ID : ${options.accountId}` : ""}
|
|
49861
|
+
Data dir : ${dataDir2}
|
|
49862
|
+
API : ${apiUrl2}
|
|
49863
|
+
`);
|
|
49864
|
+
let enrollDone = false;
|
|
49865
|
+
const channel2 = new SecureChannel({
|
|
49866
|
+
inviteToken: token2,
|
|
49867
|
+
dataDir: dataDir2,
|
|
49868
|
+
apiUrl: apiUrl2,
|
|
49869
|
+
agentName: name2,
|
|
49870
|
+
onMessage: () => {
|
|
49871
|
+
},
|
|
49872
|
+
// Not handling messages during setup
|
|
49873
|
+
onStateChange: (state) => {
|
|
49874
|
+
switch (state) {
|
|
49875
|
+
case "enrolling":
|
|
49876
|
+
console.log(" Enrolling with AgentVault server...");
|
|
49877
|
+
break;
|
|
49878
|
+
case "polling":
|
|
49879
|
+
console.log(" Waiting for approval in your AgentVault dashboard...");
|
|
49880
|
+
if (channel2.fingerprint) {
|
|
49881
|
+
console.log(`
|
|
49882
|
+
Fingerprint: ${channel2.fingerprint}`);
|
|
49883
|
+
console.log(" Verify this fingerprint matches the one shown in your dashboard");
|
|
49884
|
+
console.log(" before clicking Approve.\n");
|
|
49885
|
+
}
|
|
49886
|
+
break;
|
|
49887
|
+
case "activating":
|
|
49888
|
+
console.log(" Approved! Setting up encryption...");
|
|
49889
|
+
break;
|
|
49890
|
+
case "ready":
|
|
49891
|
+
enrollDone = true;
|
|
49892
|
+
console.log(" \u2705 Enrollment complete! Secure channel established.\n");
|
|
49893
|
+
break;
|
|
49894
|
+
case "error":
|
|
49895
|
+
console.error(" \u274C Setup encountered an error.");
|
|
49896
|
+
break;
|
|
49897
|
+
}
|
|
49898
|
+
}
|
|
49899
|
+
});
|
|
49900
|
+
channel2.on("error", (err) => {
|
|
49901
|
+
console.error(`
|
|
49902
|
+
\u274C Setup failed: ${err.message}
|
|
49903
|
+
`);
|
|
49904
|
+
process.exit(1);
|
|
49905
|
+
});
|
|
49906
|
+
await new Promise((res, rej) => {
|
|
49907
|
+
const check = setInterval(() => {
|
|
49908
|
+
if (enrollDone) {
|
|
49909
|
+
clearInterval(check);
|
|
49910
|
+
res();
|
|
49911
|
+
}
|
|
49912
|
+
}, 500);
|
|
49913
|
+
channel2.start().catch((err) => {
|
|
49914
|
+
clearInterval(check);
|
|
49915
|
+
rej(err);
|
|
49916
|
+
});
|
|
49917
|
+
});
|
|
49918
|
+
await channel2.stop();
|
|
49919
|
+
console.log(" Installing AgentVault plugin in OpenClaw...\n");
|
|
49920
|
+
const home = process.env.HOME ?? "";
|
|
49921
|
+
const extraPaths = [
|
|
49922
|
+
`${home}/.local/bin`,
|
|
49923
|
+
`${home}/.pnpm/bin`,
|
|
49924
|
+
`${home}/Library/pnpm/bin`,
|
|
49925
|
+
"/usr/local/bin",
|
|
49926
|
+
"/opt/homebrew/bin"
|
|
49927
|
+
].join(":");
|
|
49928
|
+
const env = { ...process.env, PATH: `${extraPaths}:${process.env.PATH ?? ""}` };
|
|
49929
|
+
const pluginInstalled = installPlugin(env);
|
|
49930
|
+
if (!pluginInstalled) {
|
|
49931
|
+
if (options.accountId) {
|
|
49932
|
+
console.log(`
|
|
49933
|
+
\u26A0\uFE0F Could not auto-configure OpenClaw (is 'openclaw' in your PATH?).
|
|
49934
|
+
|
|
49935
|
+
1. Install the plugin:
|
|
49936
|
+
openclaw plugins install @agentvault/agentvault
|
|
49937
|
+
|
|
49938
|
+
2. Register the plugin in the allow list:
|
|
49939
|
+
openclaw config set plugins.allow '["agentvault"]'
|
|
49940
|
+
|
|
49941
|
+
3. Add this to your OpenClaw config (openclaw.yaml or openclaw.json):
|
|
49942
|
+
channels:
|
|
49943
|
+
agentvault:
|
|
49944
|
+
apiUrl: "${apiUrl2}"
|
|
49945
|
+
bindings:
|
|
49946
|
+
- match:
|
|
49947
|
+
accountId: "*"
|
|
49948
|
+
accounts:
|
|
49949
|
+
${options.accountId}:
|
|
49950
|
+
dataDir: "${dataDir2}"
|
|
49951
|
+
agentName: "${name2}"
|
|
49952
|
+
|
|
49953
|
+
4. (Recommended) Install pm2 for auto-restart and crash recovery:
|
|
49954
|
+
npm install -g pm2
|
|
49955
|
+
pm2 start "openclaw gateway start" --name openclaw-gateway
|
|
49956
|
+
pm2 startup
|
|
49957
|
+
pm2 save
|
|
49958
|
+
|
|
49959
|
+
5. Restart the gateway:
|
|
49960
|
+
openclaw gateway restart
|
|
49961
|
+
`);
|
|
49962
|
+
} else {
|
|
49963
|
+
console.log(`
|
|
49964
|
+
\u26A0\uFE0F Could not auto-configure OpenClaw (is 'openclaw' in your PATH?).
|
|
49965
|
+
|
|
49966
|
+
1. Install the plugin:
|
|
49967
|
+
openclaw plugins install @agentvault/agentvault
|
|
49968
|
+
|
|
49969
|
+
2. Register the plugin in the allow list:
|
|
49970
|
+
openclaw config set plugins.allow '["agentvault"]'
|
|
49971
|
+
|
|
49972
|
+
3. Add this to your OpenClaw config (openclaw.yaml or openclaw.json):
|
|
49973
|
+
channels:
|
|
49974
|
+
agentvault:
|
|
49975
|
+
dataDir: "${dataDir2}"
|
|
49976
|
+
apiUrl: "${apiUrl2}"
|
|
49977
|
+
agentName: "${name2}"
|
|
49978
|
+
|
|
49979
|
+
4. (Recommended) Install pm2 for auto-restart and crash recovery:
|
|
49980
|
+
npm install -g pm2
|
|
49981
|
+
pm2 start "openclaw gateway start" --name openclaw-gateway
|
|
49982
|
+
pm2 startup
|
|
49983
|
+
pm2 save
|
|
49984
|
+
|
|
49985
|
+
5. Restart the gateway:
|
|
49986
|
+
openclaw gateway restart
|
|
49987
|
+
`);
|
|
49988
|
+
}
|
|
49989
|
+
return;
|
|
49990
|
+
}
|
|
49991
|
+
console.log("\n Registering AgentVault channel in OpenClaw config...\n");
|
|
49992
|
+
const configPrefix = options.accountId ? `channels.agentvault.accounts.${options.accountId}` : "channels.agentvault";
|
|
49993
|
+
const patchCommands = [
|
|
49994
|
+
// When using multi-agent, set shared apiUrl at top level too
|
|
49995
|
+
...options.accountId ? [`openclaw config set channels.agentvault.apiUrl "${apiUrl2}"`] : [],
|
|
49996
|
+
`openclaw config set ${configPrefix}.dataDir "${dataDir2}"`,
|
|
49997
|
+
`openclaw config set ${configPrefix}.apiUrl "${apiUrl2}"`,
|
|
49998
|
+
`openclaw config set ${configPrefix}.agentName "${name2}"`,
|
|
49999
|
+
`openclaw config set plugins.allow '["agentvault"]'`
|
|
50000
|
+
];
|
|
50001
|
+
let configPatched = false;
|
|
50002
|
+
for (const cmd of patchCommands) {
|
|
50003
|
+
try {
|
|
50004
|
+
execSync3(cmd, { stdio: "pipe", env });
|
|
50005
|
+
configPatched = true;
|
|
50006
|
+
} catch {
|
|
49442
50007
|
configPatched = false;
|
|
49443
50008
|
break;
|
|
49444
50009
|
}
|
|
49445
50010
|
}
|
|
50011
|
+
if (configPatched) {
|
|
50012
|
+
try {
|
|
50013
|
+
const raw = execSync3("openclaw config get channels.agentvault.bindings", {
|
|
50014
|
+
stdio: "pipe",
|
|
50015
|
+
env
|
|
50016
|
+
}).toString().trim();
|
|
50017
|
+
const hasWildcard = raw.includes('"*"') || raw.includes("'*'");
|
|
50018
|
+
if (!hasWildcard) {
|
|
50019
|
+
execSync3(
|
|
50020
|
+
`openclaw config set channels.agentvault.bindings '[{"match":{"accountId":"*"}}]'`,
|
|
50021
|
+
{ stdio: "pipe", env }
|
|
50022
|
+
);
|
|
50023
|
+
}
|
|
50024
|
+
} catch {
|
|
50025
|
+
try {
|
|
50026
|
+
execSync3(
|
|
50027
|
+
`openclaw config set channels.agentvault.bindings '[{"match":{"accountId":"*"}}]'`,
|
|
50028
|
+
{ stdio: "pipe", env }
|
|
50029
|
+
);
|
|
50030
|
+
} catch {
|
|
50031
|
+
}
|
|
50032
|
+
}
|
|
50033
|
+
}
|
|
49446
50034
|
if (configPatched) {
|
|
49447
50035
|
console.log(` \u2705 Channel registered in OpenClaw config.
|
|
49448
50036
|
`);
|
|
49449
50037
|
console.log(" Configuring pm2 process management...\n");
|
|
49450
50038
|
configurePm2(env);
|
|
49451
50039
|
await promptAndRestart(env);
|
|
50040
|
+
if (process.platform === "darwin") {
|
|
50041
|
+
const { validatePlist: validatePlist2 } = await init_doctor().then(() => doctor_exports);
|
|
50042
|
+
const plistResult = validatePlist2();
|
|
50043
|
+
if (plistResult.status === "stale") {
|
|
50044
|
+
console.log(`
|
|
50045
|
+
\u26A0\uFE0F macOS LaunchAgent plist has stale paths.
|
|
50046
|
+
Run to diagnose and fix: npx @agentvault/agentvault doctor
|
|
50047
|
+
`);
|
|
50048
|
+
}
|
|
50049
|
+
}
|
|
49452
50050
|
} else {
|
|
49453
50051
|
if (options.accountId) {
|
|
49454
50052
|
console.log(` \u26A0\uFE0F Could not auto-configure OpenClaw channel.
|
|
@@ -49483,7 +50081,7 @@ async function runSetupCommand(options) {
|
|
|
49483
50081
|
}
|
|
49484
50082
|
function installPlugin(env) {
|
|
49485
50083
|
try {
|
|
49486
|
-
const info =
|
|
50084
|
+
const info = execSync3("openclaw plugins info agentvault", {
|
|
49487
50085
|
stdio: "pipe",
|
|
49488
50086
|
env
|
|
49489
50087
|
});
|
|
@@ -49493,7 +50091,7 @@ function installPlugin(env) {
|
|
|
49493
50091
|
if (installedVersion && installedVersion !== VERSION) {
|
|
49494
50092
|
console.log(` Updating plugin ${installedVersion} \u2192 ${VERSION}...`);
|
|
49495
50093
|
try {
|
|
49496
|
-
|
|
50094
|
+
execSync3("openclaw plugins update agentvault", { stdio: "pipe", env });
|
|
49497
50095
|
console.log(" Plugin updated.");
|
|
49498
50096
|
} catch {
|
|
49499
50097
|
console.log(` \u26A0\uFE0F Update failed \u2014 v${installedVersion} will be used.`);
|
|
@@ -49505,7 +50103,7 @@ function installPlugin(env) {
|
|
|
49505
50103
|
} catch {
|
|
49506
50104
|
}
|
|
49507
50105
|
try {
|
|
49508
|
-
|
|
50106
|
+
execSync3("openclaw plugins install @agentvault/agentvault", {
|
|
49509
50107
|
stdio: "pipe",
|
|
49510
50108
|
env
|
|
49511
50109
|
});
|
|
@@ -49518,7 +50116,7 @@ function installPlugin(env) {
|
|
|
49518
50116
|
}
|
|
49519
50117
|
function configurePm2(env) {
|
|
49520
50118
|
try {
|
|
49521
|
-
|
|
50119
|
+
execSync3("pm2 --version", { stdio: "pipe", env });
|
|
49522
50120
|
} catch {
|
|
49523
50121
|
console.log(`
|
|
49524
50122
|
\u2139\uFE0F pm2 not found. For best reliability, install pm2:
|
|
@@ -49532,7 +50130,7 @@ function configurePm2(env) {
|
|
|
49532
50130
|
return false;
|
|
49533
50131
|
}
|
|
49534
50132
|
try {
|
|
49535
|
-
const info =
|
|
50133
|
+
const info = execSync3("pm2 describe openclaw-gateway", { stdio: "pipe", env });
|
|
49536
50134
|
const infoStr = info.toString();
|
|
49537
50135
|
if (infoStr.includes("online") || infoStr.includes("stopped")) {
|
|
49538
50136
|
console.log(" pm2 process 'openclaw-gateway' already exists.");
|
|
@@ -49543,20 +50141,20 @@ function configurePm2(env) {
|
|
|
49543
50141
|
const isMac = process.platform === "darwin";
|
|
49544
50142
|
const startCmd = isMac ? "caffeinate -i openclaw gateway start" : "openclaw gateway start";
|
|
49545
50143
|
try {
|
|
49546
|
-
|
|
50144
|
+
execSync3(`pm2 start "${startCmd}" --name openclaw-gateway`, { stdio: "pipe", env });
|
|
49547
50145
|
console.log(" \u2705 Gateway registered with pm2.");
|
|
49548
50146
|
} catch (err) {
|
|
49549
50147
|
console.log(` \u26A0\uFE0F Failed to register with pm2: ${err}`);
|
|
49550
50148
|
return false;
|
|
49551
50149
|
}
|
|
49552
50150
|
try {
|
|
49553
|
-
|
|
50151
|
+
execSync3("pm2 startup", { stdio: "pipe", env });
|
|
49554
50152
|
console.log(" \u2705 pm2 startup configured (auto-start on boot).");
|
|
49555
50153
|
} catch {
|
|
49556
50154
|
console.log(" \u26A0\uFE0F pm2 startup failed \u2014 you may need to run 'pm2 startup' manually with sudo.");
|
|
49557
50155
|
}
|
|
49558
50156
|
try {
|
|
49559
|
-
|
|
50157
|
+
execSync3("pm2 save", { stdio: "pipe", env });
|
|
49560
50158
|
console.log(" \u2705 pm2 process list saved.");
|
|
49561
50159
|
} catch {
|
|
49562
50160
|
console.log(" \u26A0\uFE0F pm2 save failed.");
|
|
@@ -49564,7 +50162,7 @@ function configurePm2(env) {
|
|
|
49564
50162
|
return true;
|
|
49565
50163
|
}
|
|
49566
50164
|
async function promptAndRestart(env) {
|
|
49567
|
-
const answer = await
|
|
50165
|
+
const answer = await ask2(
|
|
49568
50166
|
" \u26A0\uFE0F OpenClaw gateway will restart, briefly interrupting any active conversations.\n Restart now? [y/N] "
|
|
49569
50167
|
);
|
|
49570
50168
|
if (answer.trim().toLowerCase() === "y") {
|
|
@@ -49600,7 +50198,7 @@ async function promptAndRestart(env) {
|
|
|
49600
50198
|
`);
|
|
49601
50199
|
}
|
|
49602
50200
|
}
|
|
49603
|
-
function
|
|
50201
|
+
function ask2(question) {
|
|
49604
50202
|
return new Promise((resolve4) => {
|
|
49605
50203
|
const rl2 = readline.createInterface({
|
|
49606
50204
|
input: process.stdin,
|
|
@@ -49622,255 +50220,12 @@ var init_setup = __esm({
|
|
|
49622
50220
|
}
|
|
49623
50221
|
});
|
|
49624
50222
|
|
|
49625
|
-
// src/create-agent.ts
|
|
49626
|
-
var create_agent_exports = {};
|
|
49627
|
-
__export(create_agent_exports, {
|
|
49628
|
-
findNextPort: () => findNextPort,
|
|
49629
|
-
generateWorkspaceFiles: () => generateWorkspaceFiles,
|
|
49630
|
-
openclawHome: () => openclawHome,
|
|
49631
|
-
readOpenClawConfig: () => readOpenClawConfig,
|
|
49632
|
-
runCreateCommand: () => runCreateCommand
|
|
49633
|
-
});
|
|
49634
|
-
import { execSync as execSync2 } from "node:child_process";
|
|
49635
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync, copyFileSync } from "node:fs";
|
|
49636
|
-
import { join as join4 } from "node:path";
|
|
49637
|
-
function openclawHome() {
|
|
49638
|
-
const home = process.env.HOME ?? process.env.USERPROFILE ?? "";
|
|
49639
|
-
return join4(home, ".openclaw");
|
|
49640
|
-
}
|
|
49641
|
-
function readOpenClawConfig(home) {
|
|
49642
|
-
const configPath = join4(home, "openclaw.json");
|
|
49643
|
-
const raw = readFileSync(configPath, "utf-8");
|
|
49644
|
-
return JSON.parse(raw);
|
|
49645
|
-
}
|
|
49646
|
-
function writeOpenClawConfig(home, config, backupSuffix) {
|
|
49647
|
-
const configPath = join4(home, "openclaw.json");
|
|
49648
|
-
const backupPath = `${configPath}.bak.pre-${backupSuffix}`;
|
|
49649
|
-
copyFileSync(configPath, backupPath);
|
|
49650
|
-
writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
|
|
49651
|
-
}
|
|
49652
|
-
function collectPorts(config) {
|
|
49653
|
-
const ports = [];
|
|
49654
|
-
const accounts = config?.channels?.agentvault?.accounts;
|
|
49655
|
-
if (accounts && typeof accounts === "object") {
|
|
49656
|
-
for (const acct of Object.values(accounts)) {
|
|
49657
|
-
if (typeof acct.httpPort === "number") {
|
|
49658
|
-
ports.push(acct.httpPort);
|
|
49659
|
-
}
|
|
49660
|
-
}
|
|
49661
|
-
}
|
|
49662
|
-
return ports;
|
|
49663
|
-
}
|
|
49664
|
-
function findNextPort(config, startPort = 18800) {
|
|
49665
|
-
const ports = collectPorts(config);
|
|
49666
|
-
if (ports.length === 0) return startPort;
|
|
49667
|
-
return Math.max(...ports, startPort - 1) + 1;
|
|
49668
|
-
}
|
|
49669
|
-
function isPortInUse(config, port) {
|
|
49670
|
-
return collectPorts(config).includes(port);
|
|
49671
|
-
}
|
|
49672
|
-
function generateWorkspaceFiles(name2) {
|
|
49673
|
-
const displayName = name2.charAt(0).toUpperCase() + name2.slice(1).toLowerCase();
|
|
49674
|
-
return {
|
|
49675
|
-
"IDENTITY.md": `# IDENTITY.md - Who Am I?
|
|
49676
|
-
|
|
49677
|
-
- **Name:** ${displayName}
|
|
49678
|
-
- **Creature:** AI assistant \u2014 a capable peer agent in the AgentVault network
|
|
49679
|
-
- **Vibe:** Direct, competent, focused on their specialty domain
|
|
49680
|
-
- **Emoji:** (placeholder \u2014 update to something fitting)
|
|
49681
|
-
- **Avatar:** _(none set yet)_
|
|
49682
|
-
|
|
49683
|
-
> TODO: Customize this file to give ${name2} a distinct identity.
|
|
49684
|
-
`,
|
|
49685
|
-
"SOUL.md": `# SOUL.md - Who You Are
|
|
49686
|
-
|
|
49687
|
-
> TODO: Define ${name2}'s personality, tone, and behavioral rules.
|
|
49688
|
-
> Copy and adapt from ~/.openclaw/workspace/SOUL.md as a starting point.
|
|
49689
|
-
|
|
49690
|
-
## Core Truths
|
|
49691
|
-
|
|
49692
|
-
- Be genuinely helpful, not performatively helpful.
|
|
49693
|
-
- Have opinions. Be resourceful before asking.
|
|
49694
|
-
- Earn trust through competence.
|
|
49695
|
-
|
|
49696
|
-
## Channel Reply Rules
|
|
49697
|
-
|
|
49698
|
-
- Never include reasoning or internal logic in visible replies.
|
|
49699
|
-
- No narrating your approach before or after tool calls.
|
|
49700
|
-
- Just deliver the answer \u2014 clean and direct.
|
|
49701
|
-
|
|
49702
|
-
## Vibe
|
|
49703
|
-
|
|
49704
|
-
_(Define ${name2}'s specific personality here.)_
|
|
49705
|
-
`,
|
|
49706
|
-
"HEARTBEAT.md": `# Heartbeat
|
|
49707
|
-
|
|
49708
|
-
- Stay available. If nothing needs attention, reply HEARTBEAT_OK.
|
|
49709
|
-
- **Heartbeat replies are INTERNAL ONLY.** Reply with ONLY \`HEARTBEAT_OK\` when nothing needs attention.
|
|
49710
|
-
- If something genuinely urgent needs attention, send it proactively FIRST, THEN reply HEARTBEAT_OK.
|
|
49711
|
-
`,
|
|
49712
|
-
"MEMORY.md": `# MEMORY.md - Long-Term Memory
|
|
49713
|
-
|
|
49714
|
-
_(Empty \u2014 ${name2} starts with a clean memory. Update as the agent learns.)_
|
|
49715
|
-
`
|
|
49716
|
-
};
|
|
49717
|
-
}
|
|
49718
|
-
async function runCreateCommand(options) {
|
|
49719
|
-
const { name: name2, token: token2, apiUrl: apiUrl2, force } = options;
|
|
49720
|
-
const home = openclawHome();
|
|
49721
|
-
const configPath = join4(home, "openclaw.json");
|
|
49722
|
-
const workspaceDir = join4(home, `workspace-${name2}`);
|
|
49723
|
-
const dataDir2 = join4(home, "agents", name2, "agentvault-data");
|
|
49724
|
-
const templateDir = join4(home, "workspace");
|
|
49725
|
-
console.log(`
|
|
49726
|
-
\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557
|
|
49727
|
-
\u2551 AgentVault \u2014 Create New Agent \u2551
|
|
49728
|
-
\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D
|
|
49729
|
-
`);
|
|
49730
|
-
console.log(" Step 1/7 \u2014 Preflight checks...");
|
|
49731
|
-
try {
|
|
49732
|
-
execSync2("openclaw --version", { stdio: "pipe" });
|
|
49733
|
-
} catch {
|
|
49734
|
-
console.error(" Error: 'openclaw' not found in PATH. Is OpenClaw installed?");
|
|
49735
|
-
process.exit(1);
|
|
49736
|
-
}
|
|
49737
|
-
if (!existsSync(configPath)) {
|
|
49738
|
-
console.error(` Error: openclaw.json not found at ${configPath}`);
|
|
49739
|
-
process.exit(1);
|
|
49740
|
-
}
|
|
49741
|
-
console.log(" Preflight passed.\n");
|
|
49742
|
-
console.log(" Step 2/7 \u2014 Detecting port...");
|
|
49743
|
-
const config = readOpenClawConfig(home);
|
|
49744
|
-
let port;
|
|
49745
|
-
if (options.port != null) {
|
|
49746
|
-
port = options.port;
|
|
49747
|
-
if (isPortInUse(config, port)) {
|
|
49748
|
-
console.error(` Error: Port ${port} is already in use in openclaw.json.`);
|
|
49749
|
-
process.exit(1);
|
|
49750
|
-
}
|
|
49751
|
-
console.log(` Using explicit port ${port}.
|
|
49752
|
-
`);
|
|
49753
|
-
} else {
|
|
49754
|
-
port = findNextPort(config);
|
|
49755
|
-
console.log(` Auto-assigned port ${port}.
|
|
49756
|
-
`);
|
|
49757
|
-
}
|
|
49758
|
-
console.log(" Step 3/7 \u2014 Creating agent with OpenClaw...");
|
|
49759
|
-
try {
|
|
49760
|
-
execSync2(`openclaw agents add -- ${name2}`, { stdio: "pipe" });
|
|
49761
|
-
console.log(` Agent '${name2}' created.
|
|
49762
|
-
`);
|
|
49763
|
-
} catch {
|
|
49764
|
-
console.log(` Warning: 'openclaw agents add' failed \u2014 agent may already exist. Continuing.
|
|
49765
|
-
`);
|
|
49766
|
-
}
|
|
49767
|
-
console.log(" Step 4/7 \u2014 Creating directories...");
|
|
49768
|
-
mkdirSync(workspaceDir, { recursive: true });
|
|
49769
|
-
mkdirSync(dataDir2, { recursive: true });
|
|
49770
|
-
console.log(` Workspace: ${workspaceDir}`);
|
|
49771
|
-
console.log(` DataDir: ${dataDir2}
|
|
49772
|
-
`);
|
|
49773
|
-
console.log(" Step 5/7 \u2014 Writing workspace files...");
|
|
49774
|
-
const files = generateWorkspaceFiles(name2);
|
|
49775
|
-
for (const [filename, content] of Object.entries(files)) {
|
|
49776
|
-
writeFileSync(join4(workspaceDir, filename), content, "utf-8");
|
|
49777
|
-
}
|
|
49778
|
-
for (const copyFile of ["AGENTS.md", "USER.md"]) {
|
|
49779
|
-
const src = join4(templateDir, copyFile);
|
|
49780
|
-
if (existsSync(src)) {
|
|
49781
|
-
copyFileSync(src, join4(workspaceDir, copyFile));
|
|
49782
|
-
console.log(` Copied ${copyFile} from template workspace.`);
|
|
49783
|
-
}
|
|
49784
|
-
}
|
|
49785
|
-
console.log(" Workspace files written.\n");
|
|
49786
|
-
console.log(" Step 6/7 \u2014 Enrolling with AgentVault...\n");
|
|
49787
|
-
await runSetupCommand({
|
|
49788
|
-
token: token2,
|
|
49789
|
-
name: name2,
|
|
49790
|
-
apiUrl: apiUrl2,
|
|
49791
|
-
dataDir: dataDir2,
|
|
49792
|
-
accountId: name2,
|
|
49793
|
-
force
|
|
49794
|
-
});
|
|
49795
|
-
console.log("\n Step 7/7 \u2014 Patching openclaw.json...");
|
|
49796
|
-
try {
|
|
49797
|
-
const freshConfig = readOpenClawConfig(home);
|
|
49798
|
-
let patched = false;
|
|
49799
|
-
const avChannel = freshConfig?.channels?.agentvault;
|
|
49800
|
-
if (avChannel?.accounts) {
|
|
49801
|
-
const acct = avChannel.accounts[name2];
|
|
49802
|
-
if (acct) {
|
|
49803
|
-
acct.httpPort = port;
|
|
49804
|
-
patched = true;
|
|
49805
|
-
}
|
|
49806
|
-
}
|
|
49807
|
-
if (avChannel && !avChannel.bindings) {
|
|
49808
|
-
avChannel.bindings = [{ match: { accountId: "*" } }];
|
|
49809
|
-
console.log(` Added wildcard binding (accountId: "*").`);
|
|
49810
|
-
}
|
|
49811
|
-
if (patched) {
|
|
49812
|
-
writeOpenClawConfig(home, freshConfig, name2);
|
|
49813
|
-
console.log(` httpPort set to ${port}.
|
|
49814
|
-
`);
|
|
49815
|
-
} else {
|
|
49816
|
-
console.log(` Warning: Could not find account '${name2}' in channels.agentvault.accounts.`);
|
|
49817
|
-
console.log(` You may need to manually set httpPort: ${port} in openclaw.json.
|
|
49818
|
-
`);
|
|
49819
|
-
}
|
|
49820
|
-
} catch (err) {
|
|
49821
|
-
console.log(` Warning: Failed to patch openclaw.json: ${err.message}
|
|
49822
|
-
`);
|
|
49823
|
-
}
|
|
49824
|
-
console.log(" Verifying agent...");
|
|
49825
|
-
try {
|
|
49826
|
-
const http = await import("node:http");
|
|
49827
|
-
await new Promise((resolve4) => {
|
|
49828
|
-
const req = http.get(`http://127.0.0.1:${port}/status`, { timeout: 3e3 }, (res) => {
|
|
49829
|
-
console.log(` Port ${port} responded (HTTP ${res.statusCode}).`);
|
|
49830
|
-
res.resume();
|
|
49831
|
-
resolve4();
|
|
49832
|
-
});
|
|
49833
|
-
req.on("error", () => {
|
|
49834
|
-
console.log(` Port ${port} not yet responding \u2014 gateway may need a moment.`);
|
|
49835
|
-
resolve4();
|
|
49836
|
-
});
|
|
49837
|
-
req.on("timeout", () => {
|
|
49838
|
-
req.destroy();
|
|
49839
|
-
console.log(` Port ${port} timed out \u2014 check gateway logs.`);
|
|
49840
|
-
resolve4();
|
|
49841
|
-
});
|
|
49842
|
-
});
|
|
49843
|
-
} catch {
|
|
49844
|
-
console.log(" Verification skipped.");
|
|
49845
|
-
}
|
|
49846
|
-
console.log(`
|
|
49847
|
-
\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550
|
|
49848
|
-
Agent '${name2}' created successfully!
|
|
49849
|
-
\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550
|
|
49850
|
-
|
|
49851
|
-
Workspace: ${workspaceDir}
|
|
49852
|
-
DataDir: ${dataDir2}
|
|
49853
|
-
HTTP Port: ${port}
|
|
49854
|
-
|
|
49855
|
-
Next steps:
|
|
49856
|
-
1. Edit ${workspaceDir}/SOUL.md \u2014 give ${name2} a personality
|
|
49857
|
-
2. Edit ${workspaceDir}/IDENTITY.md \u2014 set name, emoji, vibe
|
|
49858
|
-
3. Approve the agent in the AgentVault app
|
|
49859
|
-
`);
|
|
49860
|
-
}
|
|
49861
|
-
var init_create_agent = __esm({
|
|
49862
|
-
async "src/create-agent.ts"() {
|
|
49863
|
-
"use strict";
|
|
49864
|
-
await init_setup();
|
|
49865
|
-
}
|
|
49866
|
-
});
|
|
49867
|
-
|
|
49868
50223
|
// src/skills-publish.ts
|
|
49869
50224
|
var skills_publish_exports = {};
|
|
49870
50225
|
__export(skills_publish_exports, {
|
|
49871
50226
|
publishSkills: () => publishSkills
|
|
49872
50227
|
});
|
|
49873
|
-
import { readFileSync as
|
|
50228
|
+
import { readFileSync as readFileSync3 } from "node:fs";
|
|
49874
50229
|
import { resolve as resolve2 } from "node:path";
|
|
49875
50230
|
async function publishSkills(opts) {
|
|
49876
50231
|
if (!opts.manifest) {
|
|
@@ -49884,7 +50239,7 @@ async function publishSkills(opts) {
|
|
|
49884
50239
|
const manifestPath = resolve2(opts.manifest);
|
|
49885
50240
|
let raw;
|
|
49886
50241
|
try {
|
|
49887
|
-
raw =
|
|
50242
|
+
raw = readFileSync3(manifestPath, "utf-8");
|
|
49888
50243
|
} catch {
|
|
49889
50244
|
console.error(`Error: Cannot read manifest file: ${manifestPath}`);
|
|
49890
50245
|
process.exit(1);
|
|
@@ -49963,8 +50318,8 @@ var init_skills_publish = __esm({
|
|
|
49963
50318
|
await init_channel();
|
|
49964
50319
|
await init_setup();
|
|
49965
50320
|
import { resolve as resolve3 } from "node:path";
|
|
49966
|
-
import { existsSync as
|
|
49967
|
-
import { createInterface as
|
|
50321
|
+
import { existsSync as existsSync3, readFileSync as readFileSync4 } from "node:fs";
|
|
50322
|
+
import { createInterface as createInterface3 } from "node:readline";
|
|
49968
50323
|
import { createRequire } from "node:module";
|
|
49969
50324
|
var _require = createRequire(import.meta.url);
|
|
49970
50325
|
var PKG_VERSION = (() => {
|
|
@@ -50136,6 +50491,11 @@ if (subcommand === "skills") {
|
|
|
50136
50491
|
console.error(`Usage: agentvault skills publish --manifest=./skill-manifest.json`);
|
|
50137
50492
|
process.exit(1);
|
|
50138
50493
|
}
|
|
50494
|
+
if (subcommand === "doctor") {
|
|
50495
|
+
const { runDoctorCommand: runDoctorCommand2 } = await init_doctor().then(() => doctor_exports);
|
|
50496
|
+
await runDoctorCommand2({ fix: flags["fix"] === "true" });
|
|
50497
|
+
process.exit(0);
|
|
50498
|
+
}
|
|
50139
50499
|
if (!token) {
|
|
50140
50500
|
console.error(`
|
|
50141
50501
|
AgentVault Secure Channel CLI
|
|
@@ -50147,6 +50507,7 @@ Usage:
|
|
|
50147
50507
|
npx @agentvault/agentvault send "message" # Send a message to the owner
|
|
50148
50508
|
npx @agentvault/agentvault status # Check gateway status
|
|
50149
50509
|
npx @agentvault/agentvault skills publish --manifest=FILE # Publish skills from manifest
|
|
50510
|
+
npx @agentvault/agentvault doctor # Diagnose and fix gateway issues
|
|
50150
50511
|
npx @agentvault/agentvault --token=TOKEN # Standalone interactive CLI
|
|
50151
50512
|
|
|
50152
50513
|
Options:
|
|
@@ -50159,6 +50520,7 @@ Options:
|
|
|
50159
50520
|
--webhook-url=URL URL for HTTP webhook notifications on new messages
|
|
50160
50521
|
--no-notifications Disable OS desktop notifications
|
|
50161
50522
|
--port=PORT Gateway port for send/status (default: 18790)
|
|
50523
|
+
--fix Apply fixes automatically (used with doctor)
|
|
50162
50524
|
|
|
50163
50525
|
Environment variables:
|
|
50164
50526
|
AGENTVAULT_INVITE_TOKEN Same as --token
|
|
@@ -50238,9 +50600,9 @@ channel.on("error", (err) => {
|
|
|
50238
50600
|
var resolvedDataDir = resolve3(dataDir);
|
|
50239
50601
|
var statePath = resolve3(resolvedDataDir, "agentvault.json");
|
|
50240
50602
|
var existingDeviceId = null;
|
|
50241
|
-
if (
|
|
50603
|
+
if (existsSync3(statePath)) {
|
|
50242
50604
|
try {
|
|
50243
|
-
const state = JSON.parse(
|
|
50605
|
+
const state = JSON.parse(readFileSync4(statePath, "utf-8"));
|
|
50244
50606
|
existingDeviceId = state.deviceId ?? null;
|
|
50245
50607
|
} catch {
|
|
50246
50608
|
}
|
|
@@ -50263,7 +50625,7 @@ if (existingDeviceId) {
|
|
|
50263
50625
|
`);
|
|
50264
50626
|
}
|
|
50265
50627
|
await channel.start();
|
|
50266
|
-
var rl =
|
|
50628
|
+
var rl = createInterface3({
|
|
50267
50629
|
input: process.stdin,
|
|
50268
50630
|
output: process.stdout,
|
|
50269
50631
|
prompt: "> "
|