wolverine-ai 3.8.1 → 3.8.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.8.1",
3
+ "version": "3.8.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 || "tool"; // Analytics category for token tracking
334
+ this.category = options.category || "reasoning"; // Analytics category matches model role
335
335
 
336
336
  // Budget constraints (claw-code: QueryEngineConfig)
337
337
  this.maxTurns = options.maxTurns || 15;
@@ -97,8 +97,9 @@ async function spawnAgent(type, task, options = {}) {
97
97
  });
98
98
  }
99
99
 
100
- // Map sub-agent type to analytics category: triage agents = classifier, fix/db = coding
101
- const categoryMap = { explore: "classifier", plan: "classifier", verify: "classifier", research: "research", fix: "coding", database: "coding", security: "audit" };
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" };
102
103
  const agent = new AgentEngine({
103
104
  sandbox: options.sandbox,
104
105
  logger: options.logger,
@@ -114,7 +114,7 @@ const SEED_DOCS = [
114
114
  metadata: { topic: "sub-agent-tools" },
115
115
  },
116
116
  {
117
- text: "Heal pipeline escalation with cost optimization: Iteration 1 uses fast path (CODING_MODEL, tracked as 'coding' category). For simple errors (TypeError/ReferenceError/SyntaxError), verifier trusts syntax+boot and skips route probe ErrorMonitor is safety net. Iteration 2 uses single agent (REASONING_MODEL, 4 turns for simple, 8 for complex, tracked as 'tool' category). Iteration 3+ uses sub-agents: explore/plan/verify use classifier model (tracked as 'classifier'), fixer uses coding model (tracked as 'coding'), research sub-agent tracked as 'research', security as 'audit'. All calls billed through unified credit system framework authenticates as a normal API user via WOLVERINE_API_KEY through the billing proxy. Billing errors (402, insufficient_quota) immediately stop healing, no token waste.",
117
+ text: "Heal pipeline with analytics categories matching 9 model roles: (1) Injection scan AUDIT_MODEL 'audit'. (2) Fast path single-shot repair CODING_MODEL 'coding'. (3) Main agent with tools REASONING_MODEL 'reasoning'. (4) Sub-agents: explore/plan/verify CLASSIFIER_MODEL 'classifier'; fix/database TOOL_MODEL → 'tool'; research RESEARCH_MODEL 'research'; security AUDIT_MODEL 'audit'. (5) Brain compaction COMPACTING_MODEL 'compacting'. (6) Embeddings EMBEDDING_MODEL 'embedding'. (7) Notifier/perf summaries → CHAT_MODEL → 'chat'. All 9 roles tracked: reasoning, coding, chat, tool, classifier, audit, compacting, research, embedding. Billing: all calls go through unified credit proxy (WOLVERINE_API_KEY). Billing errors (402) stop healing immediately.",
118
118
  metadata: { topic: "heal-escalation" },
119
119
  },
120
120
  {
@@ -339,6 +339,7 @@ async function _healImpl({ stderr, cwd, sandbox, notifier, rateLimiter, backupMa
339
339
  sandbox, logger, cwd, mcp,
340
340
  maxTurns: agentMaxTurns,
341
341
  maxTokens: tokenBudget.agent,
342
+ category: "reasoning",
342
343
  });
343
344
 
344
345
  const agentResult = await agent.run({
@@ -487,8 +488,11 @@ async function tryOperationalFix(parsed, cwd, logger) {
487
488
  }
488
489
  }
489
490
 
490
- // Pattern 2: ENOENT on config/data files the server expects
491
- const enoent = msg.match(/ENOENT.*?'([^']+)'/);
491
+ // Pattern 2: Missing files — ENOENT or error messages mentioning missing file paths
492
+ const enoent = msg.match(/ENOENT.*?'([^']+)'/)
493
+ || msg.match(/[Mm]issing\s+(?:required\s+)?(?:config\s+)?file:\s*([^\s,."]+\.\w+)/)
494
+ || msg.match(/no such file.*?'([^']+)'/)
495
+ || msg.match(/cannot find.*?'([^']+\.\w+)'/i);
492
496
  if (enoent) {
493
497
  const missingFile = enoent[1];
494
498
  const fs = require("fs");
@@ -501,10 +505,31 @@ async function tryOperationalFix(parsed, cwd, logger) {
501
505
  fs.mkdirSync(path.dirname(missingFile), { recursive: true });
502
506
  const ext = path.extname(missingFile).toLowerCase();
503
507
 
504
- // For JSON config files, try to infer expected structure from the code that loads them
508
+ // For JSON config files, try to infer expected structure from the code or error message
505
509
  let content = "";
506
510
  if (ext === ".json") {
507
- content = _inferJsonConfig(missingFile, cwd, parsed) || "{}";
511
+ content = _inferJsonConfig(missingFile, cwd, parsed);
512
+ // Also try to extract fields from the error message: "Expected JSON with { field1, field2 }"
513
+ if (!content) {
514
+ const fieldsMatch = msg.match(/(?:expected|with|fields?)[:\s]*\{\s*([^}]+)\}/i);
515
+ if (fieldsMatch) {
516
+ const fields = fieldsMatch[1].split(/[,\s]+/).filter(f => /^[a-zA-Z_]\w*$/.test(f.trim()));
517
+ if (fields.length > 0) {
518
+ const config = {};
519
+ for (const f of fields) {
520
+ const lower = f.toLowerCase();
521
+ if (/url|endpoint|host|uri/.test(lower)) config[f] = "http://localhost:3000";
522
+ else if (/timeout|delay/.test(lower)) config[f] = 5000;
523
+ else if (/port/.test(lower)) config[f] = 3000;
524
+ else if (/enabled|active/.test(lower)) config[f] = true;
525
+ else config[f] = "";
526
+ }
527
+ console.log(chalk.gray(` 🔍 Inferred ${fields.length} fields from error message: ${fields.join(", ")}`));
528
+ content = JSON.stringify(config, null, 2);
529
+ }
530
+ }
531
+ }
532
+ content = content || "{}";
508
533
  } else {
509
534
  const defaults = { ".yaml": "", ".yml": "", ".log": "", ".txt": "", ".csv": "", ".env": "" };
510
535
  content = defaults[ext] || "";
@@ -236,7 +236,7 @@ Provide a brief analysis and actionable suggestions. Focus on:
236
236
 
237
237
  Keep your response under 300 words. Be specific and actionable.`,
238
238
  maxTokens: 512,
239
- category: "audit",
239
+ category: "chat",
240
240
  });
241
241
 
242
242
  const analysis = result.content;
@@ -178,7 +178,7 @@ class Notifier {
178
178
  systemPrompt: "You summarize server errors for developers. Write 1-2 short sentences. Be direct and actionable. Do not include any secrets, passwords, or API key values — only refer to them by name (e.g. 'the OPENAI_API_KEY').",
179
179
  userPrompt: `Summarize this error for a developer notification:\n\nCategory: ${classification.category}\nError: ${safeError}\n\nStack (first 300 chars): ${safeStack.slice(0, 300)}`,
180
180
  maxTokens: 100,
181
- category: "audit",
181
+ category: "chat",
182
182
  });
183
183
 
184
184
  // Double-sanitize the AI response (in case the AI echoes something)