wolverine-ai 3.9.1 → 3.9.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wolverine-ai",
3
- "version": "3.9.1",
3
+ "version": "3.9.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": {
@@ -331,7 +331,7 @@ class AgentEngine {
331
331
  this.logger = options.logger;
332
332
  this.cwd = options.cwd || process.cwd();
333
333
  this.mcp = options.mcp || null; // McpRegistry for external tools
334
- this.category = options.category || "reasoning"; // Analytics category matches model role
334
+ this.category = options.category || "tool"; // Agent uses tools = tool category by default
335
335
 
336
336
  // Budget constraints (claw-code: QueryEngineConfig)
337
337
  this.maxTurns = options.maxTurns || 15;
@@ -97,9 +97,9 @@ async function spawnAgent(type, task, options = {}) {
97
97
  });
98
98
  }
99
99
 
100
- // Map sub-agent type to analytics category matching the 9 model roles:
101
- // explore/plan/verify = classifier (triage), fix/database = tool (uses tools to fix), research = research, security = audit
102
- const categoryMap = { explore: "classifier", plan: "classifier", verify: "classifier", research: "research", fix: "tool", database: "tool", security: "audit" };
100
+ // Map sub-agent type to analytics category by ACTIVITY (what the AI is doing):
101
+ // All agents that use tools = "tool", classification/planning = "classifier", research = "research", security = "audit"
102
+ const categoryMap = { explore: "tool", plan: "classifier", verify: "tool", research: "research", fix: "tool", database: "tool", security: "audit" };
103
103
  const agent = new AgentEngine({
104
104
  sandbox: options.sandbox,
105
105
  logger: options.logger,
@@ -289,14 +289,17 @@ class WolverineRunner {
289
289
  if (this.child) {
290
290
  const oldChild = this.child;
291
291
  this.child = null;
292
+ let spawned = false;
292
293
 
293
294
  // Wait for old process to actually exit before spawning new one
294
295
  const onExit = () => {
296
+ if (spawned) return; // Prevent double-spawn from exit + force-kill timeout
297
+ spawned = true;
295
298
  // Give port time to fully release (TIME_WAIT)
296
299
  setTimeout(() => {
297
300
  this._ensurePortFree();
298
- setTimeout(() => this._spawn(), 200);
299
- }, 300);
301
+ setTimeout(() => this._spawn(), 500);
302
+ }, 500);
300
303
  };
301
304
 
302
305
  oldChild.removeAllListeners("exit");
@@ -305,8 +308,10 @@ class WolverineRunner {
305
308
 
306
309
  // Force kill if it doesn't exit in 3s
307
310
  setTimeout(() => {
308
- this._killProcessTree(oldChild.pid, "SIGKILL");
309
- onExit();
311
+ if (!spawned) {
312
+ this._killProcessTree(oldChild.pid, "SIGKILL");
313
+ onExit();
314
+ }
310
315
  }, 3000);
311
316
  } else {
312
317
  this._ensurePortFree();
@@ -579,7 +584,8 @@ class WolverineRunner {
579
584
  this._healStatus = null;
580
585
  // Clear pending errors — the heal fixed the root cause, stale errors are irrelevant
581
586
  this._pendingErrorHeal = null;
582
- this._spawn();
587
+ // Use restart() to properly kill old child before spawning — prevents EADDRINUSE
588
+ this.restart();
583
589
  } else {
584
590
  console.log(chalk.red(`\n🐺 Wolverine could not heal: ${result.explanation}`));
585
591
 
@@ -367,7 +367,7 @@ async function _healImpl({ stderr, cwd, sandbox, notifier, rateLimiter, backupMa
367
367
  sandbox, logger, cwd, mcp,
368
368
  maxTurns: agentMaxTurns,
369
369
  maxTokens: tokenBudget.agent,
370
- category: "reasoning",
370
+ category: "tool", // Agent uses tools (read_file, write_file, bash_exec) = tool category
371
371
  });
372
372
 
373
373
  const agentResult = await agent.run({