wolverine-ai 2.4.4 → 2.4.5
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/platform/auto-update.js +47 -24
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wolverine-ai",
|
|
3
|
-
"version": "2.4.
|
|
3
|
+
"version": "2.4.5",
|
|
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": {
|
|
@@ -91,25 +91,46 @@ function isNewer(latest, current) {
|
|
|
91
91
|
}
|
|
92
92
|
|
|
93
93
|
/**
|
|
94
|
-
* Protect
|
|
94
|
+
* Protect ALL user files before update and restore after.
|
|
95
|
+
* The entire server/ directory is sacred — auto-update must never touch it.
|
|
96
|
+
* Also protects .env files and any user config.
|
|
95
97
|
*/
|
|
96
|
-
function
|
|
97
|
-
const configs = [
|
|
98
|
-
"server/config/settings.json",
|
|
99
|
-
".env.local",
|
|
100
|
-
".env",
|
|
101
|
-
];
|
|
98
|
+
function backupUserFiles(cwd) {
|
|
102
99
|
const backups = {};
|
|
103
|
-
|
|
100
|
+
|
|
101
|
+
// Protect individual config files
|
|
102
|
+
const protectedFiles = [".env.local", ".env", ".wolverine/mcp.json", ".wolverine/pricing.json"];
|
|
103
|
+
for (const file of protectedFiles) {
|
|
104
104
|
const fullPath = path.join(cwd, file);
|
|
105
105
|
if (fs.existsSync(fullPath)) {
|
|
106
106
|
backups[file] = fs.readFileSync(fullPath, "utf-8");
|
|
107
107
|
}
|
|
108
108
|
}
|
|
109
|
+
|
|
110
|
+
// Protect entire server/ directory (recursive)
|
|
111
|
+
const serverDir = path.join(cwd, "server");
|
|
112
|
+
if (fs.existsSync(serverDir)) {
|
|
113
|
+
const walk = (dir, base) => {
|
|
114
|
+
try {
|
|
115
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
116
|
+
for (const entry of entries) {
|
|
117
|
+
if (entry.name === "node_modules") continue;
|
|
118
|
+
const fullPath = path.join(dir, entry.name);
|
|
119
|
+
const relPath = path.join(base, entry.name).replace(/\\/g, "/");
|
|
120
|
+
if (entry.isDirectory()) { walk(fullPath, relPath); }
|
|
121
|
+
else {
|
|
122
|
+
try { backups[relPath] = fs.readFileSync(fullPath, "utf-8"); } catch {}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
} catch {}
|
|
126
|
+
};
|
|
127
|
+
walk(serverDir, "server");
|
|
128
|
+
}
|
|
129
|
+
|
|
109
130
|
return backups;
|
|
110
131
|
}
|
|
111
132
|
|
|
112
|
-
function
|
|
133
|
+
function restoreUserFiles(cwd, backups) {
|
|
113
134
|
for (const [file, content] of Object.entries(backups)) {
|
|
114
135
|
const fullPath = path.join(cwd, file);
|
|
115
136
|
try {
|
|
@@ -144,33 +165,35 @@ function upgrade(cwd, logger) {
|
|
|
144
165
|
console.log(chalk.blue(`\n 🔄 Wolverine update available: ${current} → ${latest}`));
|
|
145
166
|
if (logger) logger.info("update.start", `Upgrading ${current} → ${latest}`, { from: current, to: latest });
|
|
146
167
|
|
|
147
|
-
// Back up configs
|
|
148
|
-
const
|
|
149
|
-
console.log(chalk.gray(` 🔒 Backed up ${Object.keys(
|
|
168
|
+
// Back up ALL user files (server/, .env, configs)
|
|
169
|
+
const userBackups = backupUserFiles(cwd);
|
|
170
|
+
console.log(chalk.gray(` 🔒 Backed up ${Object.keys(userBackups).length} user files (server/ protected)`));
|
|
150
171
|
|
|
151
172
|
try {
|
|
152
|
-
// Detect install method: git clone or npm package
|
|
153
173
|
const useGit = isGitRepo(cwd);
|
|
154
|
-
let cmd;
|
|
155
174
|
|
|
156
175
|
if (useGit) {
|
|
157
|
-
// Git-cloned:
|
|
158
|
-
|
|
159
|
-
console.log(chalk.blue(` 📦 Git repo
|
|
176
|
+
// Git-cloned: ONLY update framework files, NEVER touch server/
|
|
177
|
+
// Fetch latest, then selectively checkout only framework dirs
|
|
178
|
+
console.log(chalk.blue(` 📦 Git repo — selective framework update (server/ untouched)`));
|
|
179
|
+
execSync("git fetch origin master", { cwd, stdio: "pipe", timeout: 30000 });
|
|
180
|
+
// Only update: src/, bin/, package.json, examples/, tests/, CLAUDE.md, README.md, CHANGELOG.md
|
|
181
|
+
const frameworkPaths = "src/ bin/ package.json package-lock.json examples/ tests/ CLAUDE.md README.md CHANGELOG.md .npmignore";
|
|
182
|
+
execSync(`git checkout origin/master -- ${frameworkPaths}`, { cwd, stdio: "pipe", timeout: 30000 });
|
|
183
|
+
execSync("npm install", { cwd, stdio: "pipe", timeout: 120000 });
|
|
160
184
|
} else {
|
|
161
185
|
// npm-installed: update the package
|
|
162
186
|
const isGlobal = __dirname.includes("node_modules") && !cwd.includes("node_modules");
|
|
163
|
-
cmd = isGlobal
|
|
187
|
+
const cmd = isGlobal
|
|
164
188
|
? `npm install -g ${PACKAGE_NAME}@${latest}`
|
|
165
189
|
: `npm install ${PACKAGE_NAME}@${latest}`;
|
|
190
|
+
console.log(chalk.blue(` 📦 Running: ${cmd}`));
|
|
191
|
+
execSync(cmd, { cwd, stdio: "pipe", timeout: 120000 });
|
|
166
192
|
}
|
|
167
193
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
// Restore configs (npm might have overwritten them)
|
|
172
|
-
restoreConfigs(cwd, configBackups);
|
|
173
|
-
console.log(chalk.gray(` 🔒 Restored config files`));
|
|
194
|
+
// Restore ALL user files (server/, .env, configs) — belt AND suspenders
|
|
195
|
+
restoreUserFiles(cwd, userBackups);
|
|
196
|
+
console.log(chalk.gray(` 🔒 Restored ${Object.keys(userBackups).length} user files`));
|
|
174
197
|
|
|
175
198
|
// Clear version cache
|
|
176
199
|
_currentVersion = null;
|