@agentvault/agentvault 0.14.12 → 0.14.14
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/channel.d.ts.map +1 -1
- package/dist/cli.js +859 -490
- 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 +8 -76
- package/dist/index.js.map +2 -2
- package/dist/openclaw-entry.d.ts.map +1 -1
- package/dist/openclaw-entry.js +27 -0
- package/dist/openclaw-entry.js.map +2 -2
- package/dist/setup.d.ts.map +1 -1
- package/dist/types.d.ts +7 -0
- package/dist/types.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
|
});
|
|
@@ -47740,6 +47664,14 @@ var init_channel = __esm({
|
|
|
47740
47664
|
await this._persistState();
|
|
47741
47665
|
}
|
|
47742
47666
|
this.emit("a2a_channel_approved", channelData);
|
|
47667
|
+
if (this.config.onA2AChannelReady && convId) {
|
|
47668
|
+
this.config.onA2AChannelReady({
|
|
47669
|
+
channelId,
|
|
47670
|
+
peerHubAddress: peerHub,
|
|
47671
|
+
role,
|
|
47672
|
+
conversationId: convId
|
|
47673
|
+
});
|
|
47674
|
+
}
|
|
47743
47675
|
}
|
|
47744
47676
|
if (data.event === "a2a_channel_activated") {
|
|
47745
47677
|
const actData = data.data || data;
|
|
@@ -49260,187 +49192,860 @@ var init_index = __esm({
|
|
|
49260
49192
|
}
|
|
49261
49193
|
});
|
|
49262
49194
|
|
|
49263
|
-
// src/
|
|
49264
|
-
var
|
|
49265
|
-
__export(
|
|
49266
|
-
|
|
49267
|
-
|
|
49268
|
-
|
|
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
|
|
49269
49203
|
});
|
|
49270
|
-
import { execSync
|
|
49271
|
-
import
|
|
49272
|
-
import {
|
|
49273
|
-
|
|
49274
|
-
const
|
|
49275
|
-
|
|
49276
|
-
|
|
49277
|
-
|
|
49278
|
-
|
|
49279
|
-
|
|
49280
|
-
|
|
49281
|
-
|
|
49282
|
-
|
|
49283
|
-
|
|
49284
|
-
|
|
49285
|
-
|
|
49286
|
-
|
|
49287
|
-
|
|
49288
|
-
|
|
49289
|
-
|
|
49290
|
-
|
|
49291
|
-
|
|
49292
|
-
|
|
49293
|
-
|
|
49294
|
-
|
|
49295
|
-
const channel2 = new SecureChannel({
|
|
49296
|
-
inviteToken: token2,
|
|
49297
|
-
dataDir: dataDir2,
|
|
49298
|
-
apiUrl: apiUrl2,
|
|
49299
|
-
agentName: name2,
|
|
49300
|
-
onMessage: () => {
|
|
49301
|
-
},
|
|
49302
|
-
// Not handling messages during setup
|
|
49303
|
-
onStateChange: (state) => {
|
|
49304
|
-
switch (state) {
|
|
49305
|
-
case "enrolling":
|
|
49306
|
-
console.log(" Enrolling with AgentVault server...");
|
|
49307
|
-
break;
|
|
49308
|
-
case "polling":
|
|
49309
|
-
console.log(" Waiting for approval in your AgentVault dashboard...");
|
|
49310
|
-
if (channel2.fingerprint) {
|
|
49311
|
-
console.log(`
|
|
49312
|
-
Fingerprint: ${channel2.fingerprint}`);
|
|
49313
|
-
console.log(" Verify this fingerprint matches the one shown in your dashboard");
|
|
49314
|
-
console.log(" before clicking Approve.\n");
|
|
49315
|
-
}
|
|
49316
|
-
break;
|
|
49317
|
-
case "activating":
|
|
49318
|
-
console.log(" Approved! Setting up encryption...");
|
|
49319
|
-
break;
|
|
49320
|
-
case "ready":
|
|
49321
|
-
enrollDone = true;
|
|
49322
|
-
console.log(" \u2705 Enrollment complete! Secure channel established.\n");
|
|
49323
|
-
break;
|
|
49324
|
-
case "error":
|
|
49325
|
-
console.error(" \u274C Setup encountered an error.");
|
|
49326
|
-
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);
|
|
49327
49229
|
}
|
|
49328
49230
|
}
|
|
49329
|
-
}
|
|
49330
|
-
|
|
49331
|
-
|
|
49332
|
-
|
|
49333
|
-
|
|
49334
|
-
|
|
49335
|
-
|
|
49336
|
-
|
|
49337
|
-
|
|
49338
|
-
|
|
49339
|
-
|
|
49340
|
-
|
|
49341
|
-
|
|
49342
|
-
|
|
49343
|
-
|
|
49344
|
-
clearInterval(check);
|
|
49345
|
-
rej(err);
|
|
49346
|
-
});
|
|
49347
|
-
});
|
|
49348
|
-
await channel2.stop();
|
|
49349
|
-
console.log(" Installing AgentVault plugin in OpenClaw...\n");
|
|
49350
|
-
const home = process.env.HOME ?? "";
|
|
49351
|
-
const extraPaths = [
|
|
49352
|
-
`${home}/.local/bin`,
|
|
49353
|
-
`${home}/.pnpm/bin`,
|
|
49354
|
-
`${home}/Library/pnpm/bin`,
|
|
49355
|
-
"/usr/local/bin",
|
|
49356
|
-
"/opt/homebrew/bin"
|
|
49357
|
-
].join(":");
|
|
49358
|
-
const env = { ...process.env, PATH: `${extraPaths}:${process.env.PATH ?? ""}` };
|
|
49359
|
-
const pluginInstalled = installPlugin(env);
|
|
49360
|
-
if (!pluginInstalled) {
|
|
49361
|
-
if (options.accountId) {
|
|
49362
|
-
console.log(`
|
|
49363
|
-
\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?
|
|
49364
49246
|
|
|
49365
|
-
|
|
49366
|
-
|
|
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)_
|
|
49367
49252
|
|
|
49368
|
-
|
|
49369
|
-
|
|
49253
|
+
> TODO: Customize this file to give ${name2} a distinct identity.
|
|
49254
|
+
`,
|
|
49255
|
+
"SOUL.md": `# SOUL.md - Who You Are
|
|
49370
49256
|
|
|
49371
|
-
|
|
49372
|
-
|
|
49373
|
-
agentvault:
|
|
49374
|
-
apiUrl: "${apiUrl2}"
|
|
49375
|
-
accounts:
|
|
49376
|
-
${options.accountId}:
|
|
49377
|
-
dataDir: "${dataDir2}"
|
|
49378
|
-
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.
|
|
49379
49259
|
|
|
49380
|
-
|
|
49381
|
-
npm install -g pm2
|
|
49382
|
-
pm2 start "openclaw gateway start" --name openclaw-gateway
|
|
49383
|
-
pm2 startup
|
|
49384
|
-
pm2 save
|
|
49260
|
+
## Core Truths
|
|
49385
49261
|
|
|
49386
|
-
|
|
49387
|
-
|
|
49388
|
-
|
|
49389
|
-
} else {
|
|
49390
|
-
console.log(`
|
|
49391
|
-
\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.
|
|
49392
49265
|
|
|
49393
|
-
|
|
49394
|
-
openclaw plugins install @agentvault/agentvault
|
|
49266
|
+
## Channel Reply Rules
|
|
49395
49267
|
|
|
49396
|
-
|
|
49397
|
-
|
|
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.
|
|
49398
49271
|
|
|
49399
|
-
|
|
49400
|
-
channels:
|
|
49401
|
-
agentvault:
|
|
49402
|
-
dataDir: "${dataDir2}"
|
|
49403
|
-
apiUrl: "${apiUrl2}"
|
|
49404
|
-
agentName: "${name2}"
|
|
49272
|
+
## Vibe
|
|
49405
49273
|
|
|
49406
|
-
|
|
49407
|
-
|
|
49408
|
-
|
|
49409
|
-
pm2 startup
|
|
49410
|
-
pm2 save
|
|
49274
|
+
_(Define ${name2}'s specific personality here.)_
|
|
49275
|
+
`,
|
|
49276
|
+
"HEARTBEAT.md": `# Heartbeat
|
|
49411
49277
|
|
|
49412
|
-
|
|
49413
|
-
|
|
49414
|
-
|
|
49415
|
-
|
|
49416
|
-
|
|
49417
|
-
|
|
49418
|
-
|
|
49419
|
-
|
|
49420
|
-
|
|
49421
|
-
|
|
49422
|
-
|
|
49423
|
-
|
|
49424
|
-
|
|
49425
|
-
|
|
49426
|
-
|
|
49427
|
-
|
|
49428
|
-
|
|
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
|
+
exec "$(which openclaw)" gateway start "$@"
|
|
49692
|
+
`;
|
|
49693
|
+
try {
|
|
49694
|
+
writeFileSync2(wrapperPath, wrapperContent, "utf-8");
|
|
49695
|
+
chmodSync(wrapperPath, 493);
|
|
49696
|
+
console.log(` Created wrapper: ${wrapperPath}`);
|
|
49697
|
+
} catch (err) {
|
|
49698
|
+
console.error(` Failed to create wrapper script: ${err.message}`);
|
|
49699
|
+
return false;
|
|
49700
|
+
}
|
|
49701
|
+
const plistBuddy = "/usr/libexec/PlistBuddy";
|
|
49702
|
+
const plist = info.plistPath;
|
|
49703
|
+
try {
|
|
49704
|
+
execSync2(`${plistBuddy} -c "Set :ProgramArguments:0 /bin/bash" "${plist}"`, { stdio: "pipe" });
|
|
49705
|
+
try {
|
|
49706
|
+
execSync2(`${plistBuddy} -c "Set :ProgramArguments:1 ${wrapperPath}" "${plist}"`, { stdio: "pipe" });
|
|
49707
|
+
} catch {
|
|
49708
|
+
execSync2(`${plistBuddy} -c "Add :ProgramArguments:1 string ${wrapperPath}" "${plist}"`, { stdio: "pipe" });
|
|
49709
|
+
}
|
|
49710
|
+
let argCount = info.programArgs.length;
|
|
49711
|
+
for (let i2 = argCount - 1; i2 >= 2; i2--) {
|
|
49712
|
+
try {
|
|
49713
|
+
execSync2(`${plistBuddy} -c "Delete :ProgramArguments:${i2}" "${plist}"`, { stdio: "pipe" });
|
|
49714
|
+
} catch {
|
|
49715
|
+
}
|
|
49716
|
+
}
|
|
49717
|
+
console.log(" Updated plist ProgramArguments.");
|
|
49718
|
+
} catch (err) {
|
|
49719
|
+
console.error(` Failed to update plist: ${err.message}`);
|
|
49720
|
+
return false;
|
|
49721
|
+
}
|
|
49722
|
+
try {
|
|
49723
|
+
execSync2(`launchctl unload "${plist}"`, { stdio: "pipe" });
|
|
49724
|
+
} catch {
|
|
49725
|
+
}
|
|
49726
|
+
try {
|
|
49727
|
+
execSync2(`launchctl load "${plist}"`, { stdio: "pipe" });
|
|
49728
|
+
console.log(" Reloaded LaunchAgent.");
|
|
49729
|
+
} catch (err) {
|
|
49730
|
+
console.error(` Failed to reload LaunchAgent: ${err.message}`);
|
|
49731
|
+
console.log(` Try manually: launchctl load "${plist}"`);
|
|
49732
|
+
return false;
|
|
49733
|
+
}
|
|
49734
|
+
return true;
|
|
49735
|
+
}
|
|
49736
|
+
async function runDoctorCommand(options) {
|
|
49737
|
+
const home = openclawHome();
|
|
49738
|
+
console.log(`
|
|
49739
|
+
\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
|
|
49740
|
+
\u2551 AgentVault \u2014 Doctor Diagnostics \u2551
|
|
49741
|
+
\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
|
|
49742
|
+
`);
|
|
49743
|
+
const results = [];
|
|
49744
|
+
results.push(checkOpenClawInstalled());
|
|
49745
|
+
results.push(checkConfigExists(home));
|
|
49746
|
+
let config = null;
|
|
49747
|
+
try {
|
|
49748
|
+
config = readOpenClawConfig(home);
|
|
49749
|
+
} catch {
|
|
49750
|
+
}
|
|
49751
|
+
results.push(checkAgentVaultChannel(config));
|
|
49752
|
+
results.push(checkPluginsAllow(config));
|
|
49753
|
+
results.push(checkPlist());
|
|
49754
|
+
results.push(checkGatewayPort());
|
|
49755
|
+
results.push(checkAgentDataDirs(config));
|
|
49756
|
+
results.push(checkPm2Status());
|
|
49757
|
+
const statusLabels = {
|
|
49758
|
+
pass: "pass",
|
|
49759
|
+
warn: "WARN",
|
|
49760
|
+
fail: "FAIL",
|
|
49761
|
+
skip: "skip"
|
|
49762
|
+
};
|
|
49763
|
+
for (const r2 of results) {
|
|
49764
|
+
const label = `[${statusLabels[r2.status]}]`;
|
|
49765
|
+
console.log(` ${label.padEnd(6)} ${r2.name} \u2014 ${r2.message}`);
|
|
49766
|
+
}
|
|
49767
|
+
const passed = results.filter((r2) => r2.status === "pass").length;
|
|
49768
|
+
const warnings = results.filter((r2) => r2.status === "warn").length;
|
|
49769
|
+
const failed = results.filter((r2) => r2.status === "fail").length;
|
|
49770
|
+
console.log(`
|
|
49771
|
+
\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
|
|
49772
|
+
${passed} passed ${warnings} warnings ${failed} failed
|
|
49773
|
+
\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
|
|
49774
|
+
`);
|
|
49775
|
+
if (failed > 0) {
|
|
49776
|
+
process.exitCode = 1;
|
|
49777
|
+
}
|
|
49778
|
+
const plistResult = validatePlist();
|
|
49779
|
+
if (plistResult.status === "stale") {
|
|
49780
|
+
const plistInfo = parsePlist(plistResult.plistPath);
|
|
49781
|
+
if (!plistInfo) return;
|
|
49782
|
+
if (options?.fix) {
|
|
49783
|
+
console.log(" Applying plist fix (--fix)...\n");
|
|
49784
|
+
const ok = applyPlistFix(plistInfo);
|
|
49785
|
+
if (ok) {
|
|
49786
|
+
console.log("\n \u2705 Plist fixed. Gateway should start cleanly now.\n");
|
|
49787
|
+
} else {
|
|
49788
|
+
console.log("\n \u274C Plist fix failed. See errors above.\n");
|
|
49789
|
+
}
|
|
49790
|
+
} else {
|
|
49791
|
+
const answer = await ask(" Stale plist detected. Apply wrapper script fix? [y/N] ");
|
|
49792
|
+
if (answer.trim().toLowerCase() === "y") {
|
|
49793
|
+
console.log("");
|
|
49794
|
+
const ok = applyPlistFix(plistInfo);
|
|
49795
|
+
if (ok) {
|
|
49796
|
+
console.log("\n \u2705 Plist fixed. Gateway should start cleanly now.\n");
|
|
49797
|
+
} else {
|
|
49798
|
+
console.log("\n \u274C Plist fix failed. See errors above.\n");
|
|
49799
|
+
}
|
|
49800
|
+
} else {
|
|
49801
|
+
console.log(`
|
|
49802
|
+
To fix later, run:
|
|
49803
|
+
npx @agentvault/agentvault doctor --fix
|
|
49804
|
+
`);
|
|
49805
|
+
}
|
|
49806
|
+
}
|
|
49807
|
+
}
|
|
49808
|
+
}
|
|
49809
|
+
function ask(question) {
|
|
49810
|
+
return new Promise((resolve4) => {
|
|
49811
|
+
const rl2 = createInterface({
|
|
49812
|
+
input: process.stdin,
|
|
49813
|
+
output: process.stdout,
|
|
49814
|
+
terminal: true
|
|
49815
|
+
});
|
|
49816
|
+
rl2.question(question, (answer) => {
|
|
49817
|
+
rl2.close();
|
|
49818
|
+
resolve4(answer);
|
|
49819
|
+
});
|
|
49820
|
+
});
|
|
49821
|
+
}
|
|
49822
|
+
var PLIST_FILENAME, WRAPPER_SCRIPT_NAME;
|
|
49823
|
+
var init_doctor = __esm({
|
|
49824
|
+
async "src/doctor.ts"() {
|
|
49825
|
+
"use strict";
|
|
49826
|
+
await init_create_agent();
|
|
49827
|
+
PLIST_FILENAME = "ai.openclaw.gateway.plist";
|
|
49828
|
+
WRAPPER_SCRIPT_NAME = "start-gateway.sh";
|
|
49829
|
+
}
|
|
49830
|
+
});
|
|
49831
|
+
|
|
49832
|
+
// src/setup.ts
|
|
49833
|
+
var setup_exports = {};
|
|
49834
|
+
__export(setup_exports, {
|
|
49835
|
+
configurePm2: () => configurePm2,
|
|
49836
|
+
installPlugin: () => installPlugin,
|
|
49837
|
+
runSetupCommand: () => runSetupCommand
|
|
49838
|
+
});
|
|
49839
|
+
import { execSync as execSync3, spawnSync } from "node:child_process";
|
|
49840
|
+
import * as readline from "node:readline";
|
|
49841
|
+
import { resolve } from "node:path";
|
|
49842
|
+
async function runSetupCommand(options) {
|
|
49843
|
+
const { token: token2, name: name2, apiUrl: apiUrl2 } = options;
|
|
49844
|
+
const dataDir2 = resolve(options.dataDir.replace(/^~/, process.env.HOME ?? "~"));
|
|
49845
|
+
const alreadyEnrolled = await isStateValid(dataDir2);
|
|
49846
|
+
if (alreadyEnrolled && !options.force) {
|
|
49847
|
+
console.log(`
|
|
49848
|
+
Already enrolled (state in ${dataDir2}).
|
|
49849
|
+
Re-enroll with --force, or update plugin with: openclaw plugins update agentvault
|
|
49850
|
+
`);
|
|
49851
|
+
return;
|
|
49852
|
+
}
|
|
49853
|
+
console.log(`
|
|
49854
|
+
\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
|
|
49855
|
+
\u2551 AgentVault \u2014 First-Time Setup \u2551
|
|
49856
|
+
\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
|
|
49857
|
+
|
|
49858
|
+
Agent name : ${name2}${options.accountId ? `
|
|
49859
|
+
Account ID : ${options.accountId}` : ""}
|
|
49860
|
+
Data dir : ${dataDir2}
|
|
49861
|
+
API : ${apiUrl2}
|
|
49862
|
+
`);
|
|
49863
|
+
let enrollDone = false;
|
|
49864
|
+
const channel2 = new SecureChannel({
|
|
49865
|
+
inviteToken: token2,
|
|
49866
|
+
dataDir: dataDir2,
|
|
49867
|
+
apiUrl: apiUrl2,
|
|
49868
|
+
agentName: name2,
|
|
49869
|
+
onMessage: () => {
|
|
49870
|
+
},
|
|
49871
|
+
// Not handling messages during setup
|
|
49872
|
+
onStateChange: (state) => {
|
|
49873
|
+
switch (state) {
|
|
49874
|
+
case "enrolling":
|
|
49875
|
+
console.log(" Enrolling with AgentVault server...");
|
|
49876
|
+
break;
|
|
49877
|
+
case "polling":
|
|
49878
|
+
console.log(" Waiting for approval in your AgentVault dashboard...");
|
|
49879
|
+
if (channel2.fingerprint) {
|
|
49880
|
+
console.log(`
|
|
49881
|
+
Fingerprint: ${channel2.fingerprint}`);
|
|
49882
|
+
console.log(" Verify this fingerprint matches the one shown in your dashboard");
|
|
49883
|
+
console.log(" before clicking Approve.\n");
|
|
49884
|
+
}
|
|
49885
|
+
break;
|
|
49886
|
+
case "activating":
|
|
49887
|
+
console.log(" Approved! Setting up encryption...");
|
|
49888
|
+
break;
|
|
49889
|
+
case "ready":
|
|
49890
|
+
enrollDone = true;
|
|
49891
|
+
console.log(" \u2705 Enrollment complete! Secure channel established.\n");
|
|
49892
|
+
break;
|
|
49893
|
+
case "error":
|
|
49894
|
+
console.error(" \u274C Setup encountered an error.");
|
|
49895
|
+
break;
|
|
49896
|
+
}
|
|
49897
|
+
}
|
|
49898
|
+
});
|
|
49899
|
+
channel2.on("error", (err) => {
|
|
49900
|
+
console.error(`
|
|
49901
|
+
\u274C Setup failed: ${err.message}
|
|
49902
|
+
`);
|
|
49903
|
+
process.exit(1);
|
|
49904
|
+
});
|
|
49905
|
+
await new Promise((res, rej) => {
|
|
49906
|
+
const check = setInterval(() => {
|
|
49907
|
+
if (enrollDone) {
|
|
49908
|
+
clearInterval(check);
|
|
49909
|
+
res();
|
|
49910
|
+
}
|
|
49911
|
+
}, 500);
|
|
49912
|
+
channel2.start().catch((err) => {
|
|
49913
|
+
clearInterval(check);
|
|
49914
|
+
rej(err);
|
|
49915
|
+
});
|
|
49916
|
+
});
|
|
49917
|
+
await channel2.stop();
|
|
49918
|
+
console.log(" Installing AgentVault plugin in OpenClaw...\n");
|
|
49919
|
+
const home = process.env.HOME ?? "";
|
|
49920
|
+
const extraPaths = [
|
|
49921
|
+
`${home}/.local/bin`,
|
|
49922
|
+
`${home}/.pnpm/bin`,
|
|
49923
|
+
`${home}/Library/pnpm/bin`,
|
|
49924
|
+
"/usr/local/bin",
|
|
49925
|
+
"/opt/homebrew/bin"
|
|
49926
|
+
].join(":");
|
|
49927
|
+
const env = { ...process.env, PATH: `${extraPaths}:${process.env.PATH ?? ""}` };
|
|
49928
|
+
const pluginInstalled = installPlugin(env);
|
|
49929
|
+
if (!pluginInstalled) {
|
|
49930
|
+
if (options.accountId) {
|
|
49931
|
+
console.log(`
|
|
49932
|
+
\u26A0\uFE0F Could not auto-configure OpenClaw (is 'openclaw' in your PATH?).
|
|
49933
|
+
|
|
49934
|
+
1. Install the plugin:
|
|
49935
|
+
openclaw plugins install @agentvault/agentvault
|
|
49936
|
+
|
|
49937
|
+
2. Register the plugin in the allow list:
|
|
49938
|
+
openclaw config set plugins.allow '["agentvault"]'
|
|
49939
|
+
|
|
49940
|
+
3. Add this to your OpenClaw config (openclaw.yaml or openclaw.json):
|
|
49941
|
+
channels:
|
|
49942
|
+
agentvault:
|
|
49943
|
+
apiUrl: "${apiUrl2}"
|
|
49944
|
+
bindings:
|
|
49945
|
+
- match:
|
|
49946
|
+
accountId: "*"
|
|
49947
|
+
accounts:
|
|
49948
|
+
${options.accountId}:
|
|
49949
|
+
dataDir: "${dataDir2}"
|
|
49950
|
+
agentName: "${name2}"
|
|
49951
|
+
|
|
49952
|
+
4. (Recommended) Install pm2 for auto-restart and crash recovery:
|
|
49953
|
+
npm install -g pm2
|
|
49954
|
+
pm2 start "openclaw gateway start" --name openclaw-gateway
|
|
49955
|
+
pm2 startup
|
|
49956
|
+
pm2 save
|
|
49957
|
+
|
|
49958
|
+
5. Restart the gateway:
|
|
49959
|
+
openclaw gateway restart
|
|
49960
|
+
`);
|
|
49961
|
+
} else {
|
|
49962
|
+
console.log(`
|
|
49963
|
+
\u26A0\uFE0F Could not auto-configure OpenClaw (is 'openclaw' in your PATH?).
|
|
49964
|
+
|
|
49965
|
+
1. Install the plugin:
|
|
49966
|
+
openclaw plugins install @agentvault/agentvault
|
|
49967
|
+
|
|
49968
|
+
2. Register the plugin in the allow list:
|
|
49969
|
+
openclaw config set plugins.allow '["agentvault"]'
|
|
49970
|
+
|
|
49971
|
+
3. Add this to your OpenClaw config (openclaw.yaml or openclaw.json):
|
|
49972
|
+
channels:
|
|
49973
|
+
agentvault:
|
|
49974
|
+
dataDir: "${dataDir2}"
|
|
49975
|
+
apiUrl: "${apiUrl2}"
|
|
49976
|
+
agentName: "${name2}"
|
|
49977
|
+
|
|
49978
|
+
4. (Recommended) Install pm2 for auto-restart and crash recovery:
|
|
49979
|
+
npm install -g pm2
|
|
49980
|
+
pm2 start "openclaw gateway start" --name openclaw-gateway
|
|
49981
|
+
pm2 startup
|
|
49982
|
+
pm2 save
|
|
49983
|
+
|
|
49984
|
+
5. Restart the gateway:
|
|
49985
|
+
openclaw gateway restart
|
|
49986
|
+
`);
|
|
49987
|
+
}
|
|
49988
|
+
return;
|
|
49989
|
+
}
|
|
49990
|
+
console.log("\n Registering AgentVault channel in OpenClaw config...\n");
|
|
49991
|
+
const configPrefix = options.accountId ? `channels.agentvault.accounts.${options.accountId}` : "channels.agentvault";
|
|
49992
|
+
const patchCommands = [
|
|
49993
|
+
// When using multi-agent, set shared apiUrl at top level too
|
|
49994
|
+
...options.accountId ? [`openclaw config set channels.agentvault.apiUrl "${apiUrl2}"`] : [],
|
|
49995
|
+
`openclaw config set ${configPrefix}.dataDir "${dataDir2}"`,
|
|
49996
|
+
`openclaw config set ${configPrefix}.apiUrl "${apiUrl2}"`,
|
|
49997
|
+
`openclaw config set ${configPrefix}.agentName "${name2}"`,
|
|
49998
|
+
`openclaw config set plugins.allow '["agentvault"]'`
|
|
49999
|
+
];
|
|
50000
|
+
let configPatched = false;
|
|
49429
50001
|
for (const cmd of patchCommands) {
|
|
49430
50002
|
try {
|
|
49431
|
-
|
|
50003
|
+
execSync3(cmd, { stdio: "pipe", env });
|
|
49432
50004
|
configPatched = true;
|
|
49433
50005
|
} catch {
|
|
49434
50006
|
configPatched = false;
|
|
49435
50007
|
break;
|
|
49436
50008
|
}
|
|
49437
50009
|
}
|
|
50010
|
+
if (configPatched) {
|
|
50011
|
+
try {
|
|
50012
|
+
const raw = execSync3("openclaw config get channels.agentvault.bindings", {
|
|
50013
|
+
stdio: "pipe",
|
|
50014
|
+
env
|
|
50015
|
+
}).toString().trim();
|
|
50016
|
+
const hasWildcard = raw.includes('"*"') || raw.includes("'*'");
|
|
50017
|
+
if (!hasWildcard) {
|
|
50018
|
+
execSync3(
|
|
50019
|
+
`openclaw config set channels.agentvault.bindings '[{"match":{"accountId":"*"}}]'`,
|
|
50020
|
+
{ stdio: "pipe", env }
|
|
50021
|
+
);
|
|
50022
|
+
}
|
|
50023
|
+
} catch {
|
|
50024
|
+
try {
|
|
50025
|
+
execSync3(
|
|
50026
|
+
`openclaw config set channels.agentvault.bindings '[{"match":{"accountId":"*"}}]'`,
|
|
50027
|
+
{ stdio: "pipe", env }
|
|
50028
|
+
);
|
|
50029
|
+
} catch {
|
|
50030
|
+
}
|
|
50031
|
+
}
|
|
50032
|
+
}
|
|
49438
50033
|
if (configPatched) {
|
|
49439
50034
|
console.log(` \u2705 Channel registered in OpenClaw config.
|
|
49440
50035
|
`);
|
|
49441
50036
|
console.log(" Configuring pm2 process management...\n");
|
|
49442
50037
|
configurePm2(env);
|
|
49443
50038
|
await promptAndRestart(env);
|
|
50039
|
+
if (process.platform === "darwin") {
|
|
50040
|
+
const { validatePlist: validatePlist2 } = await init_doctor().then(() => doctor_exports);
|
|
50041
|
+
const plistResult = validatePlist2();
|
|
50042
|
+
if (plistResult.status === "stale") {
|
|
50043
|
+
console.log(`
|
|
50044
|
+
\u26A0\uFE0F macOS LaunchAgent plist has stale paths.
|
|
50045
|
+
Run to diagnose and fix: npx @agentvault/agentvault doctor
|
|
50046
|
+
`);
|
|
50047
|
+
}
|
|
50048
|
+
}
|
|
49444
50049
|
} else {
|
|
49445
50050
|
if (options.accountId) {
|
|
49446
50051
|
console.log(` \u26A0\uFE0F Could not auto-configure OpenClaw channel.
|
|
@@ -49475,7 +50080,7 @@ async function runSetupCommand(options) {
|
|
|
49475
50080
|
}
|
|
49476
50081
|
function installPlugin(env) {
|
|
49477
50082
|
try {
|
|
49478
|
-
const info =
|
|
50083
|
+
const info = execSync3("openclaw plugins info agentvault", {
|
|
49479
50084
|
stdio: "pipe",
|
|
49480
50085
|
env
|
|
49481
50086
|
});
|
|
@@ -49485,7 +50090,7 @@ function installPlugin(env) {
|
|
|
49485
50090
|
if (installedVersion && installedVersion !== VERSION) {
|
|
49486
50091
|
console.log(` Updating plugin ${installedVersion} \u2192 ${VERSION}...`);
|
|
49487
50092
|
try {
|
|
49488
|
-
|
|
50093
|
+
execSync3("openclaw plugins update agentvault", { stdio: "pipe", env });
|
|
49489
50094
|
console.log(" Plugin updated.");
|
|
49490
50095
|
} catch {
|
|
49491
50096
|
console.log(` \u26A0\uFE0F Update failed \u2014 v${installedVersion} will be used.`);
|
|
@@ -49497,7 +50102,7 @@ function installPlugin(env) {
|
|
|
49497
50102
|
} catch {
|
|
49498
50103
|
}
|
|
49499
50104
|
try {
|
|
49500
|
-
|
|
50105
|
+
execSync3("openclaw plugins install @agentvault/agentvault", {
|
|
49501
50106
|
stdio: "pipe",
|
|
49502
50107
|
env
|
|
49503
50108
|
});
|
|
@@ -49510,7 +50115,7 @@ function installPlugin(env) {
|
|
|
49510
50115
|
}
|
|
49511
50116
|
function configurePm2(env) {
|
|
49512
50117
|
try {
|
|
49513
|
-
|
|
50118
|
+
execSync3("pm2 --version", { stdio: "pipe", env });
|
|
49514
50119
|
} catch {
|
|
49515
50120
|
console.log(`
|
|
49516
50121
|
\u2139\uFE0F pm2 not found. For best reliability, install pm2:
|
|
@@ -49524,7 +50129,7 @@ function configurePm2(env) {
|
|
|
49524
50129
|
return false;
|
|
49525
50130
|
}
|
|
49526
50131
|
try {
|
|
49527
|
-
const info =
|
|
50132
|
+
const info = execSync3("pm2 describe openclaw-gateway", { stdio: "pipe", env });
|
|
49528
50133
|
const infoStr = info.toString();
|
|
49529
50134
|
if (infoStr.includes("online") || infoStr.includes("stopped")) {
|
|
49530
50135
|
console.log(" pm2 process 'openclaw-gateway' already exists.");
|
|
@@ -49535,20 +50140,20 @@ function configurePm2(env) {
|
|
|
49535
50140
|
const isMac = process.platform === "darwin";
|
|
49536
50141
|
const startCmd = isMac ? "caffeinate -i openclaw gateway start" : "openclaw gateway start";
|
|
49537
50142
|
try {
|
|
49538
|
-
|
|
50143
|
+
execSync3(`pm2 start "${startCmd}" --name openclaw-gateway`, { stdio: "pipe", env });
|
|
49539
50144
|
console.log(" \u2705 Gateway registered with pm2.");
|
|
49540
50145
|
} catch (err) {
|
|
49541
50146
|
console.log(` \u26A0\uFE0F Failed to register with pm2: ${err}`);
|
|
49542
50147
|
return false;
|
|
49543
50148
|
}
|
|
49544
50149
|
try {
|
|
49545
|
-
|
|
50150
|
+
execSync3("pm2 startup", { stdio: "pipe", env });
|
|
49546
50151
|
console.log(" \u2705 pm2 startup configured (auto-start on boot).");
|
|
49547
50152
|
} catch {
|
|
49548
50153
|
console.log(" \u26A0\uFE0F pm2 startup failed \u2014 you may need to run 'pm2 startup' manually with sudo.");
|
|
49549
50154
|
}
|
|
49550
50155
|
try {
|
|
49551
|
-
|
|
50156
|
+
execSync3("pm2 save", { stdio: "pipe", env });
|
|
49552
50157
|
console.log(" \u2705 pm2 process list saved.");
|
|
49553
50158
|
} catch {
|
|
49554
50159
|
console.log(" \u26A0\uFE0F pm2 save failed.");
|
|
@@ -49556,7 +50161,7 @@ function configurePm2(env) {
|
|
|
49556
50161
|
return true;
|
|
49557
50162
|
}
|
|
49558
50163
|
async function promptAndRestart(env) {
|
|
49559
|
-
const answer = await
|
|
50164
|
+
const answer = await ask2(
|
|
49560
50165
|
" \u26A0\uFE0F OpenClaw gateway will restart, briefly interrupting any active conversations.\n Restart now? [y/N] "
|
|
49561
50166
|
);
|
|
49562
50167
|
if (answer.trim().toLowerCase() === "y") {
|
|
@@ -49592,7 +50197,7 @@ async function promptAndRestart(env) {
|
|
|
49592
50197
|
`);
|
|
49593
50198
|
}
|
|
49594
50199
|
}
|
|
49595
|
-
function
|
|
50200
|
+
function ask2(question) {
|
|
49596
50201
|
return new Promise((resolve4) => {
|
|
49597
50202
|
const rl2 = readline.createInterface({
|
|
49598
50203
|
input: process.stdin,
|
|
@@ -49614,255 +50219,12 @@ var init_setup = __esm({
|
|
|
49614
50219
|
}
|
|
49615
50220
|
});
|
|
49616
50221
|
|
|
49617
|
-
// src/create-agent.ts
|
|
49618
|
-
var create_agent_exports = {};
|
|
49619
|
-
__export(create_agent_exports, {
|
|
49620
|
-
findNextPort: () => findNextPort,
|
|
49621
|
-
generateWorkspaceFiles: () => generateWorkspaceFiles,
|
|
49622
|
-
openclawHome: () => openclawHome,
|
|
49623
|
-
readOpenClawConfig: () => readOpenClawConfig,
|
|
49624
|
-
runCreateCommand: () => runCreateCommand
|
|
49625
|
-
});
|
|
49626
|
-
import { execSync as execSync2 } from "node:child_process";
|
|
49627
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync, copyFileSync } from "node:fs";
|
|
49628
|
-
import { join as join4 } from "node:path";
|
|
49629
|
-
function openclawHome() {
|
|
49630
|
-
const home = process.env.HOME ?? process.env.USERPROFILE ?? "";
|
|
49631
|
-
return join4(home, ".openclaw");
|
|
49632
|
-
}
|
|
49633
|
-
function readOpenClawConfig(home) {
|
|
49634
|
-
const configPath = join4(home, "openclaw.json");
|
|
49635
|
-
const raw = readFileSync(configPath, "utf-8");
|
|
49636
|
-
return JSON.parse(raw);
|
|
49637
|
-
}
|
|
49638
|
-
function writeOpenClawConfig(home, config, backupSuffix) {
|
|
49639
|
-
const configPath = join4(home, "openclaw.json");
|
|
49640
|
-
const backupPath = `${configPath}.bak.pre-${backupSuffix}`;
|
|
49641
|
-
copyFileSync(configPath, backupPath);
|
|
49642
|
-
writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
|
|
49643
|
-
}
|
|
49644
|
-
function collectPorts(config) {
|
|
49645
|
-
const ports = [];
|
|
49646
|
-
const accounts = config?.channels?.agentvault?.accounts;
|
|
49647
|
-
if (accounts && typeof accounts === "object") {
|
|
49648
|
-
for (const acct of Object.values(accounts)) {
|
|
49649
|
-
if (typeof acct.httpPort === "number") {
|
|
49650
|
-
ports.push(acct.httpPort);
|
|
49651
|
-
}
|
|
49652
|
-
}
|
|
49653
|
-
}
|
|
49654
|
-
return ports;
|
|
49655
|
-
}
|
|
49656
|
-
function findNextPort(config, startPort = 18800) {
|
|
49657
|
-
const ports = collectPorts(config);
|
|
49658
|
-
if (ports.length === 0) return startPort;
|
|
49659
|
-
return Math.max(...ports, startPort - 1) + 1;
|
|
49660
|
-
}
|
|
49661
|
-
function isPortInUse(config, port) {
|
|
49662
|
-
return collectPorts(config).includes(port);
|
|
49663
|
-
}
|
|
49664
|
-
function generateWorkspaceFiles(name2) {
|
|
49665
|
-
const displayName = name2.charAt(0).toUpperCase() + name2.slice(1).toLowerCase();
|
|
49666
|
-
return {
|
|
49667
|
-
"IDENTITY.md": `# IDENTITY.md - Who Am I?
|
|
49668
|
-
|
|
49669
|
-
- **Name:** ${displayName}
|
|
49670
|
-
- **Creature:** AI assistant \u2014 a capable peer agent in the AgentVault network
|
|
49671
|
-
- **Vibe:** Direct, competent, focused on their specialty domain
|
|
49672
|
-
- **Emoji:** (placeholder \u2014 update to something fitting)
|
|
49673
|
-
- **Avatar:** _(none set yet)_
|
|
49674
|
-
|
|
49675
|
-
> TODO: Customize this file to give ${name2} a distinct identity.
|
|
49676
|
-
`,
|
|
49677
|
-
"SOUL.md": `# SOUL.md - Who You Are
|
|
49678
|
-
|
|
49679
|
-
> TODO: Define ${name2}'s personality, tone, and behavioral rules.
|
|
49680
|
-
> Copy and adapt from ~/.openclaw/workspace/SOUL.md as a starting point.
|
|
49681
|
-
|
|
49682
|
-
## Core Truths
|
|
49683
|
-
|
|
49684
|
-
- Be genuinely helpful, not performatively helpful.
|
|
49685
|
-
- Have opinions. Be resourceful before asking.
|
|
49686
|
-
- Earn trust through competence.
|
|
49687
|
-
|
|
49688
|
-
## Channel Reply Rules
|
|
49689
|
-
|
|
49690
|
-
- Never include reasoning or internal logic in visible replies.
|
|
49691
|
-
- No narrating your approach before or after tool calls.
|
|
49692
|
-
- Just deliver the answer \u2014 clean and direct.
|
|
49693
|
-
|
|
49694
|
-
## Vibe
|
|
49695
|
-
|
|
49696
|
-
_(Define ${name2}'s specific personality here.)_
|
|
49697
|
-
`,
|
|
49698
|
-
"HEARTBEAT.md": `# Heartbeat
|
|
49699
|
-
|
|
49700
|
-
- Stay available. If nothing needs attention, reply HEARTBEAT_OK.
|
|
49701
|
-
- **Heartbeat replies are INTERNAL ONLY.** Reply with ONLY \`HEARTBEAT_OK\` when nothing needs attention.
|
|
49702
|
-
- If something genuinely urgent needs attention, send it proactively FIRST, THEN reply HEARTBEAT_OK.
|
|
49703
|
-
`,
|
|
49704
|
-
"MEMORY.md": `# MEMORY.md - Long-Term Memory
|
|
49705
|
-
|
|
49706
|
-
_(Empty \u2014 ${name2} starts with a clean memory. Update as the agent learns.)_
|
|
49707
|
-
`
|
|
49708
|
-
};
|
|
49709
|
-
}
|
|
49710
|
-
async function runCreateCommand(options) {
|
|
49711
|
-
const { name: name2, token: token2, apiUrl: apiUrl2, force } = options;
|
|
49712
|
-
const home = openclawHome();
|
|
49713
|
-
const configPath = join4(home, "openclaw.json");
|
|
49714
|
-
const workspaceDir = join4(home, `workspace-${name2}`);
|
|
49715
|
-
const dataDir2 = join4(home, "agents", name2, "agentvault-data");
|
|
49716
|
-
const templateDir = join4(home, "workspace");
|
|
49717
|
-
console.log(`
|
|
49718
|
-
\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
|
|
49719
|
-
\u2551 AgentVault \u2014 Create New Agent \u2551
|
|
49720
|
-
\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
|
|
49721
|
-
`);
|
|
49722
|
-
console.log(" Step 1/7 \u2014 Preflight checks...");
|
|
49723
|
-
try {
|
|
49724
|
-
execSync2("openclaw --version", { stdio: "pipe" });
|
|
49725
|
-
} catch {
|
|
49726
|
-
console.error(" Error: 'openclaw' not found in PATH. Is OpenClaw installed?");
|
|
49727
|
-
process.exit(1);
|
|
49728
|
-
}
|
|
49729
|
-
if (!existsSync(configPath)) {
|
|
49730
|
-
console.error(` Error: openclaw.json not found at ${configPath}`);
|
|
49731
|
-
process.exit(1);
|
|
49732
|
-
}
|
|
49733
|
-
console.log(" Preflight passed.\n");
|
|
49734
|
-
console.log(" Step 2/7 \u2014 Detecting port...");
|
|
49735
|
-
const config = readOpenClawConfig(home);
|
|
49736
|
-
let port;
|
|
49737
|
-
if (options.port != null) {
|
|
49738
|
-
port = options.port;
|
|
49739
|
-
if (isPortInUse(config, port)) {
|
|
49740
|
-
console.error(` Error: Port ${port} is already in use in openclaw.json.`);
|
|
49741
|
-
process.exit(1);
|
|
49742
|
-
}
|
|
49743
|
-
console.log(` Using explicit port ${port}.
|
|
49744
|
-
`);
|
|
49745
|
-
} else {
|
|
49746
|
-
port = findNextPort(config);
|
|
49747
|
-
console.log(` Auto-assigned port ${port}.
|
|
49748
|
-
`);
|
|
49749
|
-
}
|
|
49750
|
-
console.log(" Step 3/7 \u2014 Creating agent with OpenClaw...");
|
|
49751
|
-
try {
|
|
49752
|
-
execSync2(`openclaw agents add -- ${name2}`, { stdio: "pipe" });
|
|
49753
|
-
console.log(` Agent '${name2}' created.
|
|
49754
|
-
`);
|
|
49755
|
-
} catch {
|
|
49756
|
-
console.log(` Warning: 'openclaw agents add' failed \u2014 agent may already exist. Continuing.
|
|
49757
|
-
`);
|
|
49758
|
-
}
|
|
49759
|
-
console.log(" Step 4/7 \u2014 Creating directories...");
|
|
49760
|
-
mkdirSync(workspaceDir, { recursive: true });
|
|
49761
|
-
mkdirSync(dataDir2, { recursive: true });
|
|
49762
|
-
console.log(` Workspace: ${workspaceDir}`);
|
|
49763
|
-
console.log(` DataDir: ${dataDir2}
|
|
49764
|
-
`);
|
|
49765
|
-
console.log(" Step 5/7 \u2014 Writing workspace files...");
|
|
49766
|
-
const files = generateWorkspaceFiles(name2);
|
|
49767
|
-
for (const [filename, content] of Object.entries(files)) {
|
|
49768
|
-
writeFileSync(join4(workspaceDir, filename), content, "utf-8");
|
|
49769
|
-
}
|
|
49770
|
-
for (const copyFile of ["AGENTS.md", "USER.md"]) {
|
|
49771
|
-
const src = join4(templateDir, copyFile);
|
|
49772
|
-
if (existsSync(src)) {
|
|
49773
|
-
copyFileSync(src, join4(workspaceDir, copyFile));
|
|
49774
|
-
console.log(` Copied ${copyFile} from template workspace.`);
|
|
49775
|
-
}
|
|
49776
|
-
}
|
|
49777
|
-
console.log(" Workspace files written.\n");
|
|
49778
|
-
console.log(" Step 6/7 \u2014 Enrolling with AgentVault...\n");
|
|
49779
|
-
await runSetupCommand({
|
|
49780
|
-
token: token2,
|
|
49781
|
-
name: name2,
|
|
49782
|
-
apiUrl: apiUrl2,
|
|
49783
|
-
dataDir: dataDir2,
|
|
49784
|
-
accountId: name2,
|
|
49785
|
-
force
|
|
49786
|
-
});
|
|
49787
|
-
console.log("\n Step 7/7 \u2014 Patching openclaw.json...");
|
|
49788
|
-
try {
|
|
49789
|
-
const freshConfig = readOpenClawConfig(home);
|
|
49790
|
-
let patched = false;
|
|
49791
|
-
const avChannel = freshConfig?.channels?.agentvault;
|
|
49792
|
-
if (avChannel?.accounts) {
|
|
49793
|
-
const acct = avChannel.accounts[name2];
|
|
49794
|
-
if (acct) {
|
|
49795
|
-
acct.httpPort = port;
|
|
49796
|
-
patched = true;
|
|
49797
|
-
}
|
|
49798
|
-
}
|
|
49799
|
-
if (avChannel && !avChannel.bindings) {
|
|
49800
|
-
avChannel.bindings = [{ match: { accountId: "*" } }];
|
|
49801
|
-
console.log(` Added wildcard binding (accountId: "*").`);
|
|
49802
|
-
}
|
|
49803
|
-
if (patched) {
|
|
49804
|
-
writeOpenClawConfig(home, freshConfig, name2);
|
|
49805
|
-
console.log(` httpPort set to ${port}.
|
|
49806
|
-
`);
|
|
49807
|
-
} else {
|
|
49808
|
-
console.log(` Warning: Could not find account '${name2}' in channels.agentvault.accounts.`);
|
|
49809
|
-
console.log(` You may need to manually set httpPort: ${port} in openclaw.json.
|
|
49810
|
-
`);
|
|
49811
|
-
}
|
|
49812
|
-
} catch (err) {
|
|
49813
|
-
console.log(` Warning: Failed to patch openclaw.json: ${err.message}
|
|
49814
|
-
`);
|
|
49815
|
-
}
|
|
49816
|
-
console.log(" Verifying agent...");
|
|
49817
|
-
try {
|
|
49818
|
-
const http = await import("node:http");
|
|
49819
|
-
await new Promise((resolve4) => {
|
|
49820
|
-
const req = http.get(`http://127.0.0.1:${port}/status`, { timeout: 3e3 }, (res) => {
|
|
49821
|
-
console.log(` Port ${port} responded (HTTP ${res.statusCode}).`);
|
|
49822
|
-
res.resume();
|
|
49823
|
-
resolve4();
|
|
49824
|
-
});
|
|
49825
|
-
req.on("error", () => {
|
|
49826
|
-
console.log(` Port ${port} not yet responding \u2014 gateway may need a moment.`);
|
|
49827
|
-
resolve4();
|
|
49828
|
-
});
|
|
49829
|
-
req.on("timeout", () => {
|
|
49830
|
-
req.destroy();
|
|
49831
|
-
console.log(` Port ${port} timed out \u2014 check gateway logs.`);
|
|
49832
|
-
resolve4();
|
|
49833
|
-
});
|
|
49834
|
-
});
|
|
49835
|
-
} catch {
|
|
49836
|
-
console.log(" Verification skipped.");
|
|
49837
|
-
}
|
|
49838
|
-
console.log(`
|
|
49839
|
-
\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550
|
|
49840
|
-
Agent '${name2}' created successfully!
|
|
49841
|
-
\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550
|
|
49842
|
-
|
|
49843
|
-
Workspace: ${workspaceDir}
|
|
49844
|
-
DataDir: ${dataDir2}
|
|
49845
|
-
HTTP Port: ${port}
|
|
49846
|
-
|
|
49847
|
-
Next steps:
|
|
49848
|
-
1. Edit ${workspaceDir}/SOUL.md \u2014 give ${name2} a personality
|
|
49849
|
-
2. Edit ${workspaceDir}/IDENTITY.md \u2014 set name, emoji, vibe
|
|
49850
|
-
3. Approve the agent in the AgentVault app
|
|
49851
|
-
`);
|
|
49852
|
-
}
|
|
49853
|
-
var init_create_agent = __esm({
|
|
49854
|
-
async "src/create-agent.ts"() {
|
|
49855
|
-
"use strict";
|
|
49856
|
-
await init_setup();
|
|
49857
|
-
}
|
|
49858
|
-
});
|
|
49859
|
-
|
|
49860
50222
|
// src/skills-publish.ts
|
|
49861
50223
|
var skills_publish_exports = {};
|
|
49862
50224
|
__export(skills_publish_exports, {
|
|
49863
50225
|
publishSkills: () => publishSkills
|
|
49864
50226
|
});
|
|
49865
|
-
import { readFileSync as
|
|
50227
|
+
import { readFileSync as readFileSync3 } from "node:fs";
|
|
49866
50228
|
import { resolve as resolve2 } from "node:path";
|
|
49867
50229
|
async function publishSkills(opts) {
|
|
49868
50230
|
if (!opts.manifest) {
|
|
@@ -49876,7 +50238,7 @@ async function publishSkills(opts) {
|
|
|
49876
50238
|
const manifestPath = resolve2(opts.manifest);
|
|
49877
50239
|
let raw;
|
|
49878
50240
|
try {
|
|
49879
|
-
raw =
|
|
50241
|
+
raw = readFileSync3(manifestPath, "utf-8");
|
|
49880
50242
|
} catch {
|
|
49881
50243
|
console.error(`Error: Cannot read manifest file: ${manifestPath}`);
|
|
49882
50244
|
process.exit(1);
|
|
@@ -49955,8 +50317,8 @@ var init_skills_publish = __esm({
|
|
|
49955
50317
|
await init_channel();
|
|
49956
50318
|
await init_setup();
|
|
49957
50319
|
import { resolve as resolve3 } from "node:path";
|
|
49958
|
-
import { existsSync as
|
|
49959
|
-
import { createInterface as
|
|
50320
|
+
import { existsSync as existsSync3, readFileSync as readFileSync4 } from "node:fs";
|
|
50321
|
+
import { createInterface as createInterface3 } from "node:readline";
|
|
49960
50322
|
import { createRequire } from "node:module";
|
|
49961
50323
|
var _require = createRequire(import.meta.url);
|
|
49962
50324
|
var PKG_VERSION = (() => {
|
|
@@ -50128,6 +50490,11 @@ if (subcommand === "skills") {
|
|
|
50128
50490
|
console.error(`Usage: agentvault skills publish --manifest=./skill-manifest.json`);
|
|
50129
50491
|
process.exit(1);
|
|
50130
50492
|
}
|
|
50493
|
+
if (subcommand === "doctor") {
|
|
50494
|
+
const { runDoctorCommand: runDoctorCommand2 } = await init_doctor().then(() => doctor_exports);
|
|
50495
|
+
await runDoctorCommand2({ fix: flags["fix"] === "true" });
|
|
50496
|
+
process.exit(0);
|
|
50497
|
+
}
|
|
50131
50498
|
if (!token) {
|
|
50132
50499
|
console.error(`
|
|
50133
50500
|
AgentVault Secure Channel CLI
|
|
@@ -50139,6 +50506,7 @@ Usage:
|
|
|
50139
50506
|
npx @agentvault/agentvault send "message" # Send a message to the owner
|
|
50140
50507
|
npx @agentvault/agentvault status # Check gateway status
|
|
50141
50508
|
npx @agentvault/agentvault skills publish --manifest=FILE # Publish skills from manifest
|
|
50509
|
+
npx @agentvault/agentvault doctor # Diagnose and fix gateway issues
|
|
50142
50510
|
npx @agentvault/agentvault --token=TOKEN # Standalone interactive CLI
|
|
50143
50511
|
|
|
50144
50512
|
Options:
|
|
@@ -50151,6 +50519,7 @@ Options:
|
|
|
50151
50519
|
--webhook-url=URL URL for HTTP webhook notifications on new messages
|
|
50152
50520
|
--no-notifications Disable OS desktop notifications
|
|
50153
50521
|
--port=PORT Gateway port for send/status (default: 18790)
|
|
50522
|
+
--fix Apply fixes automatically (used with doctor)
|
|
50154
50523
|
|
|
50155
50524
|
Environment variables:
|
|
50156
50525
|
AGENTVAULT_INVITE_TOKEN Same as --token
|
|
@@ -50230,9 +50599,9 @@ channel.on("error", (err) => {
|
|
|
50230
50599
|
var resolvedDataDir = resolve3(dataDir);
|
|
50231
50600
|
var statePath = resolve3(resolvedDataDir, "agentvault.json");
|
|
50232
50601
|
var existingDeviceId = null;
|
|
50233
|
-
if (
|
|
50602
|
+
if (existsSync3(statePath)) {
|
|
50234
50603
|
try {
|
|
50235
|
-
const state = JSON.parse(
|
|
50604
|
+
const state = JSON.parse(readFileSync4(statePath, "utf-8"));
|
|
50236
50605
|
existingDeviceId = state.deviceId ?? null;
|
|
50237
50606
|
} catch {
|
|
50238
50607
|
}
|
|
@@ -50255,7 +50624,7 @@ if (existingDeviceId) {
|
|
|
50255
50624
|
`);
|
|
50256
50625
|
}
|
|
50257
50626
|
await channel.start();
|
|
50258
|
-
var rl =
|
|
50627
|
+
var rl = createInterface3({
|
|
50259
50628
|
input: process.stdin,
|
|
50260
50629
|
output: process.stdout,
|
|
50261
50630
|
prompt: "> "
|