wolverine-ai 2.4.0 → 2.4.2

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wolverine-ai",
3
- "version": "2.4.0",
3
+ "version": "2.4.2",
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": {
@@ -76,8 +76,22 @@ function loadConfig() {
76
76
  dashboard: {
77
77
  port: parseInt(process.env.WOLVERINE_DASHBOARD_PORT, 10) || fileConfig.dashboard?.port || null,
78
78
  },
79
+
80
+ autoUpdate: {
81
+ enabled: process.env.WOLVERINE_AUTO_UPDATE !== "false" && (fileConfig.autoUpdate?.enabled !== false),
82
+ intervalMs: parseInt(process.env.WOLVERINE_UPDATE_INTERVAL_MS, 10) || fileConfig.autoUpdate?.intervalMs || 3600000,
83
+ },
84
+
85
+ errorMonitor: {
86
+ threshold: parseInt(process.env.WOLVERINE_ERROR_THRESHOLD, 10) || fileConfig.errorMonitor?.defaultThreshold || 1,
87
+ windowMs: parseInt(process.env.WOLVERINE_ERROR_WINDOW_MS, 10) || fileConfig.errorMonitor?.windowMs || 30000,
88
+ cooldownMs: parseInt(process.env.WOLVERINE_ERROR_COOLDOWN_MS, 10) || fileConfig.errorMonitor?.cooldownMs || 60000,
89
+ },
79
90
  };
80
91
 
92
+ // Merge any missing defaults into the live settings.json
93
+ _ensureDefaults(fileConfig, configPath);
94
+
81
95
  return _config;
82
96
  }
83
97
 
@@ -94,4 +108,35 @@ function getConfig(dotPath) {
94
108
  */
95
109
  function resetConfig() { _config = null; }
96
110
 
111
+ /**
112
+ * Ensure the live settings.json has all required sections.
113
+ * If a section is missing, add it with defaults. Never overwrites existing values.
114
+ */
115
+ function _ensureDefaults(fileConfig, configPath) {
116
+ const DEFAULTS = {
117
+ autoUpdate: { enabled: true, intervalMs: 3600000 },
118
+ errorMonitor: { defaultThreshold: 1, windowMs: 30000, cooldownMs: 60000 },
119
+ healthCheck: { intervalMs: 15000, timeoutMs: 5000, failThreshold: 3, startDelayMs: 10000 },
120
+ rateLimiting: { maxCallsPerWindow: 32, windowMs: 100000, minGapMs: 5000, maxTokensPerHour: 1000000 },
121
+ telemetry: { enabled: true, heartbeatIntervalMs: 60000 },
122
+ cluster: { enabled: false, workers: 0 },
123
+ };
124
+
125
+ let needsWrite = false;
126
+ for (const [key, defaults] of Object.entries(DEFAULTS)) {
127
+ if (!fileConfig[key]) {
128
+ fileConfig[key] = defaults;
129
+ needsWrite = true;
130
+ }
131
+ }
132
+
133
+ if (needsWrite && configPath) {
134
+ try {
135
+ const tmpPath = configPath + ".tmp";
136
+ fs.writeFileSync(tmpPath, JSON.stringify(fileConfig, null, 2), "utf-8");
137
+ fs.renameSync(tmpPath, configPath);
138
+ } catch { /* non-fatal — config still works from defaults in memory */ }
139
+ }
140
+ }
141
+
97
142
  module.exports = { loadConfig, getConfig, resetConfig };
@@ -20,6 +20,7 @@ const { ProcessMonitor } = require("../monitor/process-monitor");
20
20
  const { RouteProber } = require("../monitor/route-prober");
21
21
  const { startHeartbeat, stopHeartbeat } = require("../platform/heartbeat");
22
22
  const { Notifier } = require("../notifications/notifier");
23
+ const { loadConfig } = require("./config");
23
24
  const { ErrorMonitor } = require("../monitor/error-monitor");
24
25
  const { startAutoUpdate, stopAutoUpdate } = require("../platform/auto-update");
25
26
 
@@ -215,20 +216,22 @@ class WolverineRunner {
215
216
  });
216
217
 
217
218
  // Auto-update: check for new wolverine-ai versions
218
- const { getConfig: _gc } = require("./config");
219
- const autoUpdateEnabled = _gc("autoUpdate.enabled") !== false;
219
+ const autoUpdateCfg = loadConfig().autoUpdate || {};
220
+ const autoUpdateEnabled = process.env.WOLVERINE_AUTO_UPDATE !== "false" && autoUpdateCfg.enabled !== false;
220
221
  if (autoUpdateEnabled) {
222
+ const { getCurrentVersion } = require("../platform/auto-update");
223
+ const updateInterval = autoUpdateCfg.intervalMs || 3600000;
221
224
  startAutoUpdate({
222
225
  cwd: this.cwd,
223
226
  logger: this.logger,
224
- intervalMs: parseInt(process.env.WOLVERINE_UPDATE_INTERVAL_MS, 10) || 3600000,
227
+ intervalMs: updateInterval,
225
228
  onUpdate: (result) => {
226
229
  console.log(chalk.blue(` 🔄 Wolverine updated ${result.from} → ${result.to}, restarting...`));
227
230
  this.logger.info("update.restart", `Restarting after update ${result.from} → ${result.to}`);
228
231
  this.restart();
229
232
  },
230
233
  });
231
- console.log(chalk.gray(" 🔄 Auto-update: enabled (checks hourly)"));
234
+ console.log(chalk.gray(` 🔄 Auto-update: enabled (v${getCurrentVersion()}, checks every ${Math.round(updateInterval / 60000)}min)`));
232
235
  } else {
233
236
  console.log(chalk.gray(" 🔄 Auto-update: disabled"));
234
237
  }
@@ -181,7 +181,9 @@ function startAutoUpdate({ cwd, logger, onUpdate, intervalMs }) {
181
181
  const interval = intervalMs || CHECK_INTERVAL_MS;
182
182
 
183
183
  // Check on startup (delayed 30s to not block boot)
184
+ console.log(chalk.gray(` 🔄 Auto-update scheduled: first check in 30s, then every ${Math.round(interval / 60000)}min`));
184
185
  setTimeout(() => {
186
+ console.log(chalk.gray(` 🔄 Checking for updates (v${getCurrentVersion()})...`));
185
187
  const result = checkForUpdate();
186
188
  if (result?.available) {
187
189
  const upgraded = upgrade(cwd, logger);
@@ -189,6 +191,10 @@ function startAutoUpdate({ cwd, logger, onUpdate, intervalMs }) {
189
191
  console.log(chalk.blue(" 🔄 Restarting with new version..."));
190
192
  onUpdate(upgraded);
191
193
  }
194
+ } else if (result) {
195
+ console.log(chalk.gray(` 🔄 Up to date (v${result.current}${result.latest ? ", npm: " + result.latest : ""})`));
196
+ } else {
197
+ console.log(chalk.yellow(" 🔄 Update check failed (npm unreachable?)"));
192
198
  }
193
199
  }, 30000);
194
200