wolverine-ai 6.2.1 → 6.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/claw/setup.js +169 -22
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wolverine-ai",
|
|
3
|
-
"version": "6.2.
|
|
3
|
+
"version": "6.2.3",
|
|
4
4
|
"description": "Self-healing Node.js server framework powered by AI. Catches crashes, diagnoses errors, generates fixes, verifies, and restarts — automatically.",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"bin": {
|
package/src/claw/setup.js
CHANGED
|
@@ -247,19 +247,41 @@ function detectWolverine(cwd) {
|
|
|
247
247
|
brainExists: fs.existsSync(path.join(cwd, ".wolverine", "brain")),
|
|
248
248
|
};
|
|
249
249
|
|
|
250
|
+
// Check if we're inside the wolverine repo itself
|
|
250
251
|
try {
|
|
251
252
|
const pkg = JSON.parse(fs.readFileSync(path.join(cwd, "package.json"), "utf-8"));
|
|
252
|
-
if (pkg.name === "wolverine-ai"
|
|
253
|
+
if (pkg.name === "wolverine-ai") {
|
|
253
254
|
result.installed = true;
|
|
254
|
-
result.version = pkg.version
|
|
255
|
+
result.version = pkg.version;
|
|
256
|
+
return result;
|
|
255
257
|
}
|
|
256
|
-
//
|
|
257
|
-
|
|
258
|
+
// Check if wolverine-ai is a dependency
|
|
259
|
+
const deps = { ...pkg.dependencies, ...pkg.devDependencies, ...pkg.optionalDependencies };
|
|
260
|
+
if (deps["wolverine-ai"]) {
|
|
258
261
|
result.installed = true;
|
|
259
|
-
result.version =
|
|
262
|
+
result.version = deps["wolverine-ai"];
|
|
260
263
|
}
|
|
261
264
|
} catch {}
|
|
262
265
|
|
|
266
|
+
// Check if wolverine.js exists in src/ (repo checkout)
|
|
267
|
+
if (fs.existsSync(path.join(cwd, "src", "core", "wolverine.js"))) {
|
|
268
|
+
result.installed = true;
|
|
269
|
+
try {
|
|
270
|
+
const pkg = JSON.parse(fs.readFileSync(path.join(cwd, "package.json"), "utf-8"));
|
|
271
|
+
result.version = pkg.version;
|
|
272
|
+
} catch {}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
// Check node_modules
|
|
276
|
+
if (!result.installed) {
|
|
277
|
+
try {
|
|
278
|
+
const pkgPath = require.resolve("wolverine-ai/package.json", { paths: [cwd] });
|
|
279
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
|
|
280
|
+
result.installed = true;
|
|
281
|
+
result.version = pkg.version;
|
|
282
|
+
} catch {}
|
|
283
|
+
}
|
|
284
|
+
|
|
263
285
|
return result;
|
|
264
286
|
}
|
|
265
287
|
|
|
@@ -325,13 +347,48 @@ function mergeConfig(openclawConfig, defaults) {
|
|
|
325
347
|
|
|
326
348
|
// ── Scaffolding ─────────────────────────────────────────────────
|
|
327
349
|
|
|
350
|
+
/**
|
|
351
|
+
* Find the wolverine-ai template directory.
|
|
352
|
+
* Works whether wolverine is the project root OR installed in node_modules.
|
|
353
|
+
*/
|
|
354
|
+
function _findTemplateDir() {
|
|
355
|
+
// 1. Relative to this file (we're in src/claw/setup.js → ../../wolverine-claw/)
|
|
356
|
+
const fromSrc = path.join(__dirname, "..", "..", "wolverine-claw");
|
|
357
|
+
if (fs.existsSync(path.join(fromSrc, "index.js"))) return fromSrc;
|
|
358
|
+
|
|
359
|
+
// 2. Via require.resolve (works when wolverine-ai is a node_modules dep)
|
|
360
|
+
try {
|
|
361
|
+
const pkgPath = require.resolve("wolverine-ai/package.json");
|
|
362
|
+
const pkgDir = path.dirname(pkgPath);
|
|
363
|
+
const fromPkg = path.join(pkgDir, "wolverine-claw");
|
|
364
|
+
if (fs.existsSync(path.join(fromPkg, "index.js"))) return fromPkg;
|
|
365
|
+
} catch {}
|
|
366
|
+
|
|
367
|
+
// 3. Check common node_modules locations
|
|
368
|
+
const candidates = [
|
|
369
|
+
path.join(process.cwd(), "node_modules", "wolverine-ai", "wolverine-claw"),
|
|
370
|
+
path.join(os.homedir(), "node_modules", "wolverine-ai", "wolverine-claw"),
|
|
371
|
+
];
|
|
372
|
+
for (const c of candidates) {
|
|
373
|
+
if (fs.existsSync(path.join(c, "index.js"))) return c;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
return null;
|
|
377
|
+
}
|
|
378
|
+
|
|
328
379
|
/**
|
|
329
380
|
* Scaffold the wolverine-claw directory from template + merged config.
|
|
330
381
|
*/
|
|
331
382
|
function scaffold(cwd, mergedConfig, env) {
|
|
332
383
|
const clawDir = path.join(cwd, "wolverine-claw");
|
|
384
|
+
const templateDir = _findTemplateDir();
|
|
333
385
|
const results = { created: [], skipped: [], errors: [] };
|
|
334
386
|
|
|
387
|
+
if (!templateDir) {
|
|
388
|
+
results.errors.push("Could not find wolverine-ai templates. Is wolverine-ai installed?");
|
|
389
|
+
return results;
|
|
390
|
+
}
|
|
391
|
+
|
|
335
392
|
// Create directories
|
|
336
393
|
const dirs = ["config", "plugins", "workspace", "skills"];
|
|
337
394
|
for (const d of dirs) {
|
|
@@ -352,12 +409,11 @@ function scaffold(cwd, mergedConfig, env) {
|
|
|
352
409
|
}
|
|
353
410
|
|
|
354
411
|
// Copy index.js from template
|
|
355
|
-
const
|
|
356
|
-
if (!fs.existsSync(
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
fs.copyFileSync(templateIndex, indexSrc);
|
|
412
|
+
const indexDest = path.join(clawDir, "index.js");
|
|
413
|
+
if (!fs.existsSync(indexDest)) {
|
|
414
|
+
const indexSrc = path.join(templateDir, "index.js");
|
|
415
|
+
if (fs.existsSync(indexSrc)) {
|
|
416
|
+
fs.copyFileSync(indexSrc, indexDest);
|
|
361
417
|
results.created.push("index.js");
|
|
362
418
|
}
|
|
363
419
|
} else {
|
|
@@ -367,15 +423,10 @@ function scaffold(cwd, mergedConfig, env) {
|
|
|
367
423
|
// Copy plugin
|
|
368
424
|
const pluginDest = path.join(clawDir, "plugins", "wolverine-integration.js");
|
|
369
425
|
if (!fs.existsSync(pluginDest)) {
|
|
370
|
-
const pluginSrc = path.join(
|
|
426
|
+
const pluginSrc = path.join(templateDir, "plugins", "wolverine-integration.js");
|
|
371
427
|
if (fs.existsSync(pluginSrc)) {
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
const templatePlugin = path.join(__dirname, "..", "..", "wolverine-claw", "plugins", "wolverine-integration.js");
|
|
375
|
-
if (fs.existsSync(templatePlugin)) {
|
|
376
|
-
fs.copyFileSync(templatePlugin, pluginDest);
|
|
377
|
-
results.created.push("plugins/wolverine-integration.js");
|
|
378
|
-
}
|
|
428
|
+
fs.copyFileSync(pluginSrc, pluginDest);
|
|
429
|
+
results.created.push("plugins/wolverine-integration.js");
|
|
379
430
|
}
|
|
380
431
|
} else {
|
|
381
432
|
results.skipped.push("plugins/wolverine-integration.js (already exists)");
|
|
@@ -471,6 +522,79 @@ function ensureEnvFile(cwd, env) {
|
|
|
471
522
|
return result;
|
|
472
523
|
}
|
|
473
524
|
|
|
525
|
+
/**
|
|
526
|
+
* Ensure wolverine-ai is installed as a dependency.
|
|
527
|
+
* Skips if we're running from the wolverine repo itself.
|
|
528
|
+
*/
|
|
529
|
+
function ensureWolverineDep(cwd) {
|
|
530
|
+
// If we're inside the wolverine repo, skip
|
|
531
|
+
const pkgPath = path.join(cwd, "package.json");
|
|
532
|
+
try {
|
|
533
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
|
|
534
|
+
if (pkg.name === "wolverine-ai") {
|
|
535
|
+
return { installed: true, isRepo: true, alreadyPresent: true };
|
|
536
|
+
}
|
|
537
|
+
// Already a dependency?
|
|
538
|
+
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
539
|
+
if (deps["wolverine-ai"]) {
|
|
540
|
+
return { installed: true, alreadyPresent: true };
|
|
541
|
+
}
|
|
542
|
+
} catch {}
|
|
543
|
+
|
|
544
|
+
// Install it
|
|
545
|
+
if (!fs.existsSync(pkgPath)) {
|
|
546
|
+
return { installed: false, reason: "no package.json" };
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
try {
|
|
550
|
+
console.log(chalk.gray(" Installing wolverine-ai..."));
|
|
551
|
+
execSync("npm install wolverine-ai@latest 2>&1", {
|
|
552
|
+
cwd,
|
|
553
|
+
encoding: "utf-8",
|
|
554
|
+
timeout: 120000,
|
|
555
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
556
|
+
});
|
|
557
|
+
return { installed: true, alreadyPresent: false };
|
|
558
|
+
} catch (err) {
|
|
559
|
+
return { installed: false, reason: `npm install failed: ${err.message?.split("\n")[0]}` };
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
/**
|
|
564
|
+
* Add claw-related npm scripts to the user's package.json.
|
|
565
|
+
*/
|
|
566
|
+
function addClawScripts(cwd) {
|
|
567
|
+
const pkgPath = path.join(cwd, "package.json");
|
|
568
|
+
if (!fs.existsSync(pkgPath)) return { added: 0 };
|
|
569
|
+
|
|
570
|
+
try {
|
|
571
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
|
|
572
|
+
if (!pkg.scripts) pkg.scripts = {};
|
|
573
|
+
|
|
574
|
+
const toAdd = {
|
|
575
|
+
"claw": "wolverine-claw",
|
|
576
|
+
"claw:direct": "wolverine-claw --direct",
|
|
577
|
+
"claw:info": "wolverine-claw --info",
|
|
578
|
+
};
|
|
579
|
+
|
|
580
|
+
let added = 0;
|
|
581
|
+
for (const [name, cmd] of Object.entries(toAdd)) {
|
|
582
|
+
if (!pkg.scripts[name]) {
|
|
583
|
+
pkg.scripts[name] = cmd;
|
|
584
|
+
added++;
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
if (added > 0) {
|
|
589
|
+
fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + "\n");
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
return { added, skipped: added === 0 };
|
|
593
|
+
} catch {
|
|
594
|
+
return { added: 0 };
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
|
|
474
598
|
/**
|
|
475
599
|
* Ensure openclaw is installed as a dependency.
|
|
476
600
|
*/
|
|
@@ -730,9 +854,21 @@ async function setup(cwd, options = {}) {
|
|
|
730
854
|
|
|
731
855
|
log("");
|
|
732
856
|
|
|
733
|
-
// ── Step 6: Install
|
|
857
|
+
// ── Step 6: Install dependencies ─────────────────────────────
|
|
858
|
+
log(chalk.bold(" Dependencies...\n"));
|
|
859
|
+
|
|
860
|
+
// 6a: Install wolverine-ai itself if not already a dep
|
|
861
|
+
const wolverineDepResult = ensureWolverineDep(cwd);
|
|
862
|
+
if (wolverineDepResult.installed) {
|
|
863
|
+
log(chalk.green(` ✅ wolverine-ai ${wolverineDepResult.alreadyPresent ? "already installed" : "installed"}`));
|
|
864
|
+
} else if (wolverineDepResult.isRepo) {
|
|
865
|
+
log(chalk.gray(" ○ wolverine-ai (running from repo)"));
|
|
866
|
+
} else {
|
|
867
|
+
log(chalk.yellow(` ⚠️ wolverine-ai: ${wolverineDepResult.reason}`));
|
|
868
|
+
}
|
|
869
|
+
|
|
870
|
+
// 6b: Install openclaw if not already present
|
|
734
871
|
if (!env.openclaw.localInstall) {
|
|
735
|
-
log(chalk.bold(" Dependencies...\n"));
|
|
736
872
|
const depResult = ensureOpenClawDep(cwd);
|
|
737
873
|
if (depResult.installed) {
|
|
738
874
|
log(chalk.green(` ✅ openclaw ${depResult.alreadyPresent ? "already installed" : "installed"}`));
|
|
@@ -742,9 +878,18 @@ async function setup(cwd, options = {}) {
|
|
|
742
878
|
log(chalk.gray(` ${depResult.fallback}`));
|
|
743
879
|
}
|
|
744
880
|
}
|
|
745
|
-
log("");
|
|
746
881
|
}
|
|
747
882
|
|
|
883
|
+
// 6c: Add claw npm scripts to user's package.json
|
|
884
|
+
const scriptsResult = addClawScripts(cwd);
|
|
885
|
+
if (scriptsResult.added > 0) {
|
|
886
|
+
log(chalk.green(` ✅ Added ${scriptsResult.added} npm scripts (claw, claw:info, claw:direct)`));
|
|
887
|
+
} else if (scriptsResult.skipped) {
|
|
888
|
+
log(chalk.gray(" ○ npm scripts already present"));
|
|
889
|
+
}
|
|
890
|
+
|
|
891
|
+
log("");
|
|
892
|
+
|
|
748
893
|
// ── Step 7: Validate ───────────────────────────────────────
|
|
749
894
|
log(chalk.bold(" Validating...\n"));
|
|
750
895
|
|
|
@@ -873,4 +1018,6 @@ module.exports = {
|
|
|
873
1018
|
validate,
|
|
874
1019
|
ensureEnvFile,
|
|
875
1020
|
ensureOpenClawDep,
|
|
1021
|
+
ensureWolverineDep,
|
|
1022
|
+
addClawScripts,
|
|
876
1023
|
};
|