wolverine-ai 4.0.0 → 4.0.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 +2 -2
- package/src/core/ai-client.js +38 -6
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wolverine-ai",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.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": {
|
|
@@ -63,7 +63,7 @@
|
|
|
63
63
|
"pg": "^8.0.0"
|
|
64
64
|
},
|
|
65
65
|
"optionalDependencies": {
|
|
66
|
-
"@privy-io/server-auth": "
|
|
66
|
+
"@privy-io/server-auth": "1.14.0",
|
|
67
67
|
"better-sqlite3": "^11.0.0",
|
|
68
68
|
"ethers": "^6.0.0",
|
|
69
69
|
"stripe": "^18.0.0"
|
package/src/core/ai-client.js
CHANGED
|
@@ -51,12 +51,10 @@ function getClient(provider) {
|
|
|
51
51
|
return _getOpenAIClient();
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
+
let _wolverineDirectClient = null;
|
|
55
|
+
|
|
54
56
|
function _getWolverineClient() {
|
|
55
57
|
if (!_wolverineClient) {
|
|
56
|
-
// Wolverine inference: always route through billing proxy when API key is set.
|
|
57
|
-
// WOLVERINE_API_KEY = billed API key (credits deducted per call)
|
|
58
|
-
// WOLVERINE_GPU_KEY = direct GPU access (no billing, admin/internal only)
|
|
59
|
-
// Priority: API_KEY (billed) > GPU_KEY (direct) — billing is the default path
|
|
60
58
|
const apiKey = process.env.WOLVERINE_API_KEY || process.env.WOLVERINE_GPU_KEY || "none";
|
|
61
59
|
const baseURL = process.env.WOLVERINE_INFERENCE_URL
|
|
62
60
|
? process.env.WOLVERINE_INFERENCE_URL + "/v1"
|
|
@@ -66,6 +64,17 @@ function _getWolverineClient() {
|
|
|
66
64
|
return _wolverineClient;
|
|
67
65
|
}
|
|
68
66
|
|
|
67
|
+
// Direct GPU client — bypasses billing proxy. Used as fallback when proxy is down.
|
|
68
|
+
function _getWolverineDirectClient() {
|
|
69
|
+
if (!_wolverineDirectClient && process.env.WOLVERINE_GPU_URL && process.env.WOLVERINE_GPU_KEY) {
|
|
70
|
+
_wolverineDirectClient = new OpenAI({
|
|
71
|
+
apiKey: process.env.WOLVERINE_GPU_KEY,
|
|
72
|
+
baseURL: process.env.WOLVERINE_GPU_URL + "/v1",
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
return _wolverineDirectClient;
|
|
76
|
+
}
|
|
77
|
+
|
|
69
78
|
function _getOpenAIClient() {
|
|
70
79
|
if (!_openaiClient) {
|
|
71
80
|
const apiKey = process.env.OPENAI_API_KEY;
|
|
@@ -219,7 +228,19 @@ async function aiCall({ model, systemPrompt, userPrompt, maxTokens = 2048, tools
|
|
|
219
228
|
if (provider === "anthropic") {
|
|
220
229
|
result = await _anthropicCall({ model, systemPrompt, userPrompt, maxTokens, tools, toolChoice });
|
|
221
230
|
} else if (provider === "wolverine") {
|
|
222
|
-
|
|
231
|
+
try {
|
|
232
|
+
result = await _chatCall(_getWolverineClient(), { model, systemPrompt, userPrompt, maxTokens, tools, toolChoice });
|
|
233
|
+
} catch (proxyErr) {
|
|
234
|
+
// If billing proxy is down (server crashing), fall back to direct GPU
|
|
235
|
+
const isConnErr = /ECONNREFUSED|ECONNRESET|ETIMEDOUT|fetch failed/i.test(proxyErr.message || "");
|
|
236
|
+
const directClient = _getWolverineDirectClient();
|
|
237
|
+
if (isConnErr && directClient) {
|
|
238
|
+
console.log(chalk.yellow(" ⚠️ Billing proxy down — using direct GPU (unbilled)"));
|
|
239
|
+
result = await _chatCall(directClient, { model, systemPrompt, userPrompt, maxTokens, tools, toolChoice });
|
|
240
|
+
} else {
|
|
241
|
+
throw proxyErr;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
223
244
|
} else if (isResponsesModel(model)) {
|
|
224
245
|
result = await _responsesCall(_getOpenAIClient(), { model, systemPrompt, userPrompt, maxTokens, tools });
|
|
225
246
|
} else {
|
|
@@ -245,7 +266,18 @@ async function aiCallWithHistory({ model, messages, tools, maxTokens = 4096, cat
|
|
|
245
266
|
if (provider === "anthropic") {
|
|
246
267
|
result = await _anthropicCallWithHistory({ model, messages, tools, maxTokens });
|
|
247
268
|
} else if (provider === "wolverine") {
|
|
248
|
-
|
|
269
|
+
try {
|
|
270
|
+
result = await _chatCallWithHistory(_getWolverineClient(), { model, messages, tools, maxTokens });
|
|
271
|
+
} catch (proxyErr) {
|
|
272
|
+
const isConnErr = /ECONNREFUSED|ECONNRESET|ETIMEDOUT|fetch failed/i.test(proxyErr.message || "");
|
|
273
|
+
const directClient = _getWolverineDirectClient();
|
|
274
|
+
if (isConnErr && directClient) {
|
|
275
|
+
console.log(chalk.yellow(" ⚠️ Billing proxy down — using direct GPU (unbilled)"));
|
|
276
|
+
result = await _chatCallWithHistory(directClient, { model, messages, tools, maxTokens });
|
|
277
|
+
} else {
|
|
278
|
+
throw proxyErr;
|
|
279
|
+
}
|
|
280
|
+
}
|
|
249
281
|
} else if (isResponsesModel(model)) {
|
|
250
282
|
result = await _responsesCallWithHistory(_getOpenAIClient(), { model, messages, tools, maxTokens });
|
|
251
283
|
} else {
|