wolverine-ai 3.7.5 → 3.7.7

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.7.5",
3
+ "version": "3.7.7",
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,6 +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
335
 
335
336
  // Budget constraints (claw-code: QueryEngineConfig)
336
337
  this.maxTurns = options.maxTurns || 15;
@@ -422,6 +423,7 @@ class AgentEngine {
422
423
  messages: this.messages,
423
424
  tools: allTools,
424
425
  maxTokens: 4096,
426
+ category: this.category,
425
427
  }),
426
428
  new Promise((_, reject) => setTimeout(() => reject(new Error(`AI call timed out after ${AI_CALL_TIMEOUT_MS / 1000}s`)), AI_CALL_TIMEOUT_MS)),
427
429
  ]);
@@ -97,6 +97,8 @@ 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
102
  const agent = new AgentEngine({
101
103
  sandbox: options.sandbox,
102
104
  logger: options.logger,
@@ -104,6 +106,7 @@ async function spawnAgent(type, task, options = {}) {
104
106
  mcp: options.mcp,
105
107
  maxTurns: config.maxTurns,
106
108
  maxTokens: config.maxTokens,
109
+ category: categoryMap[type] || "tool",
107
110
  });
108
111
 
109
112
  // Override the system prompt for this agent type
@@ -1,4 +1,4 @@
1
- const { getClient, aiCall, detectProvider } = require("../core/ai-client");
1
+ const { getClient, aiCall, detectProvider, _trackEmbedding } = require("../core/ai-client");
2
2
  const { getModel } = require("../core/models");
3
3
 
4
4
  /**
@@ -45,12 +45,14 @@ async function embed(text) {
45
45
  const openai = getClient("openai");
46
46
  const model = getModel("embedding");
47
47
 
48
+ const startMs = Date.now();
48
49
  const response = await openai.embeddings.create({
49
50
  model,
50
51
  input: text,
51
52
  });
52
53
 
53
54
  const embedding = response.data[0].embedding;
55
+ _trackEmbedding(model, response.usage, Date.now() - startMs, true);
54
56
  _cacheSet(text, embedding);
55
57
  return embedding;
56
58
  }
@@ -83,10 +85,12 @@ async function embedBatch(texts) {
83
85
  const openai = getClient("openai");
84
86
  const model = getModel("embedding");
85
87
 
88
+ const startMs = Date.now();
86
89
  const response = await openai.embeddings.create({
87
90
  model,
88
91
  input: uncached,
89
92
  });
93
+ _trackEmbedding(model, response.usage, Date.now() - startMs, true);
90
94
 
91
95
  // Sort by index to maintain order
92
96
  const sorted = response.data.sort((a, b) => a.index - b.index);
@@ -32,6 +32,12 @@ function _track(model, category, usage, tool, latencyMs, success) {
32
32
  _tracker.record(model, category, input, output, tool, latencyMs, success, cacheCreation, cacheRead);
33
33
  }
34
34
 
35
+ function _trackEmbedding(model, usage, latencyMs, success) {
36
+ if (!_tracker) return;
37
+ const input = usage?.prompt_tokens || usage?.total_tokens || 0;
38
+ _tracker.record(model, "embedding", input, 0, null, latencyMs, success, 0, 0);
39
+ }
40
+
35
41
  // ── Client Management ──
36
42
 
37
43
  function getClient(provider) {
@@ -42,13 +48,14 @@ function getClient(provider) {
42
48
 
43
49
  function _getWolverineClient() {
44
50
  if (!_wolverineClient) {
45
- // Wolverine inference: direct to GPU or via proxy
46
- // WOLVERINE_GPU_KEY = internal key for direct GPU access (llama.cpp --api-key)
47
- // WOLVERINE_API_KEY = user key for billed proxy access (api.wolverinenode.xyz)
51
+ // Wolverine inference: always route through billing proxy when API key is set.
52
+ // WOLVERINE_API_KEY = billed API key (credits deducted per call)
53
+ // WOLVERINE_GPU_KEY = direct GPU access (no billing, admin/internal only)
54
+ // Priority: API_KEY (billed) > GPU_KEY (direct) — billing is the default path
55
+ const apiKey = process.env.WOLVERINE_API_KEY || process.env.WOLVERINE_GPU_KEY || "none";
48
56
  const baseURL = process.env.WOLVERINE_INFERENCE_URL
49
57
  ? process.env.WOLVERINE_INFERENCE_URL + "/v1"
50
58
  : "https://api.wolverinenode.xyz/v1";
51
- const apiKey = process.env.WOLVERINE_GPU_KEY || process.env.WOLVERINE_API_KEY || "none";
52
59
  _wolverineClient = new OpenAI({ apiKey, baseURL });
53
60
  }
54
61
  return _wolverineClient;
@@ -618,4 +625,4 @@ Include both if needed, or just one.`;
618
625
  }
619
626
  }
620
627
 
621
- module.exports = { requestRepair, getClient, tokenParam, aiCall, aiCallWithHistory, isResponsesModel, isAnthropicModel, setTokenTracker, getTrackerSnapshot, detectProvider };
628
+ module.exports = { requestRepair, getClient, tokenParam, aiCall, aiCallWithHistory, isResponsesModel, isAnthropicModel, setTokenTracker, getTrackerSnapshot, detectProvider, _trackEmbedding };