wolverine-ai 3.7.3 → 3.7.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/bin/wolverine.js CHANGED
@@ -144,9 +144,10 @@ console.log(chalk.yellow.bold("\n 🐺 Wolverine Node.js — Autonomous Server
144
144
  logSystemInfo(systemInfo);
145
145
  console.log("");
146
146
 
147
- console.log(chalk.bold(" Models:"));
147
+ console.log(chalk.bold(` Models (${config.provider}):`));
148
148
  logModelConfig(chalk);
149
149
  console.log("");
150
+ console.log(chalk.gray(` Provider: ${config.provider}`));
150
151
  console.log(chalk.gray(` Script: ${scriptPath}`));
151
152
  console.log(chalk.gray(` Port: ${config.server.port}`));
152
153
  console.log(chalk.gray(` Retries: ${config.server.maxRetries}`));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wolverine-ai",
3
- "version": "3.7.3",
3
+ "version": "3.7.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": {
@@ -414,7 +414,7 @@ class AgentEngine {
414
414
  }
415
415
 
416
416
  let response;
417
- const AI_CALL_TIMEOUT_MS = 45000; // 45s per API call — prevents indefinite hangs
417
+ const AI_CALL_TIMEOUT_MS = parseInt(process.env.WOLVERINE_AI_CALL_TIMEOUT_MS, 10) || 90000; // 90s per API call — self-hosted GPU needs more time
418
418
  try {
419
419
  response = await Promise.race([
420
420
  aiCallWithHistory({
@@ -423,7 +423,7 @@ class AgentEngine {
423
423
  tools: allTools,
424
424
  maxTokens: 4096,
425
425
  }),
426
- new Promise((_, reject) => setTimeout(() => reject(new Error("AI call timed out after 45s")), AI_CALL_TIMEOUT_MS)),
426
+ new Promise((_, reject) => setTimeout(() => reject(new Error(`AI call timed out after ${AI_CALL_TIMEOUT_MS / 1000}s`)), AI_CALL_TIMEOUT_MS)),
427
427
  ]);
428
428
  } catch (err) {
429
429
  console.log(chalk.red(` Agent API error: ${err.message}`));
@@ -169,7 +169,20 @@ async function _withRetry(fn, maxRetries = 3) {
169
169
  try {
170
170
  return await fn();
171
171
  } catch (err) {
172
- const isRateLimit = err.status === 429 || err.code === "rate_limit_exceeded";
172
+ const msg = (err.message || "").toLowerCase();
173
+ const code = (err.code || "").toLowerCase();
174
+
175
+ // Permanent billing/quota errors — never retry, surface immediately
176
+ const isBillingError = err.status === 402
177
+ || /insufficient.*(quota|credits|funds)/i.test(msg)
178
+ || /billing_hard_limit|insufficient_quota|quota_exceeded/i.test(msg)
179
+ || /billing_hard_limit|insufficient_quota|quota_exceeded/i.test(code);
180
+ if (isBillingError) {
181
+ console.log(chalk.red(` 💳 Billing error (not retrying): ${err.message}`));
182
+ throw err;
183
+ }
184
+
185
+ const isRateLimit = err.status === 429 || code === "rate_limit_exceeded";
173
186
  const isServerError = err.status >= 500;
174
187
  if ((isRateLimit || isServerError) && attempt < maxRetries) {
175
188
  const delay = Math.min(1000 * Math.pow(2, attempt) + Math.random() * 1000, 30000);
@@ -43,6 +43,7 @@ function loadConfig() {
43
43
  classifier: process.env.CLASSIFIER_MODEL || modelSource.classifier || "gpt-4o-mini",
44
44
  audit: process.env.AUDIT_MODEL || modelSource.audit || "gpt-4o-mini",
45
45
  compacting: process.env.COMPACTING_MODEL || modelSource.compacting || "gpt-4o-mini",
46
+ utility: process.env.COMPACTING_MODEL || modelSource.compacting || "gpt-4o-mini",
46
47
  research: process.env.RESEARCH_MODEL || modelSource.research || "gpt-4o",
47
48
  embedding: process.env.TEXT_EMBEDDING_MODEL || modelSource.embedding || "text-embedding-3-small",
48
49
  },
@@ -119,9 +119,12 @@ function getModel(role) {
119
119
  function getModelConfig() {
120
120
  const config = {};
121
121
  for (const [role, def] of Object.entries(MODEL_ROLES)) {
122
+ const resolved = getModel(role);
123
+ const fromEnv = !!process.env[def.envKey];
124
+ const fromDefault = resolved === def.default;
122
125
  config[role] = {
123
- model: process.env[def.envKey] || def.default,
124
- source: process.env[def.envKey] ? "env" : "default",
126
+ model: resolved,
127
+ source: fromEnv ? "env" : fromDefault ? "default" : "settings",
125
128
  tier: def.tier,
126
129
  };
127
130
  }
@@ -29,11 +29,17 @@ const HUMAN_REQUIRED_PATTERNS = [
29
29
  { pattern: /(api|auth|token|key|credential).*(expired|revoked|rotated|invalid)/i, category: "auth", hint: "Credential has expired or been revoked" },
30
30
  { pattern: /authentication\s+failed/i, category: "auth", hint: "Authentication failed — check credentials" },
31
31
 
32
- // Billing/Quota
32
+ // Billing/Quota — covers OpenAI, Anthropic, Wolverine, and generic patterns
33
33
  { pattern: /429\s*(too many|rate limit)/i, category: "billing", hint: "Rate limit hit — may need to upgrade plan or wait" },
34
34
  { pattern: /(quota|limit|credits?)\s*(exceeded|exhausted|depleted)/i, category: "billing", hint: "Usage quota or credits exhausted" },
35
35
  { pattern: /billing.*(?:issue|error|failed|inactive)/i, category: "billing", hint: "Billing issue on the account" },
36
36
  { pattern: /insufficient.*(funds|credits|quota)/i, category: "billing", hint: "Insufficient credits or funds" },
37
+ { pattern: /billing_hard_limit_reached/i, category: "billing", hint: "OpenAI billing hard limit reached — add payment method or raise limit" },
38
+ { pattern: /insufficient_quota/i, category: "billing", hint: "API quota exhausted — check billing dashboard" },
39
+ { pattern: /rate_limit_exceeded/i, category: "billing", hint: "API rate limit exceeded — wait or upgrade plan" },
40
+ { pattern: /402\s*(payment|required)/i, category: "billing", hint: "Payment required — check billing status" },
41
+ { pattern: /exceeded.*(?:budget|spending|token)/i, category: "billing", hint: "Spending or token budget exceeded" },
42
+ { pattern: /overloaded_error/i, category: "billing", hint: "Anthropic API overloaded — retry later" },
37
43
 
38
44
  // External service failures
39
45
  { pattern: /ECONNREFUSED/i, category: "service", hint: "External service connection refused — is it running?" },