@blockrun/clawrouter 0.6.3 → 0.6.6
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/dist/index.js +105 -17
- package/dist/index.js.map +1 -1
- package/package.json +8 -2
- package/scripts/reinstall.sh +7 -7
package/dist/index.js
CHANGED
|
@@ -26,6 +26,7 @@ var MODEL_ALIASES = {
|
|
|
26
26
|
// NVIDIA (free)
|
|
27
27
|
nvidia: "nvidia/gpt-oss-120b",
|
|
28
28
|
"gpt-120b": "nvidia/gpt-oss-120b",
|
|
29
|
+
"gpt-20b": "nvidia/gpt-oss-20b",
|
|
29
30
|
free: "nvidia/gpt-oss-120b"
|
|
30
31
|
};
|
|
31
32
|
function resolveModelAlias(model) {
|
|
@@ -168,7 +169,15 @@ var BLOCKRUN_MODELS = [
|
|
|
168
169
|
maxOutput: 65536,
|
|
169
170
|
reasoning: true
|
|
170
171
|
},
|
|
171
|
-
|
|
172
|
+
{
|
|
173
|
+
id: "openai/o4-mini",
|
|
174
|
+
name: "o4-mini",
|
|
175
|
+
inputPrice: 1.1,
|
|
176
|
+
outputPrice: 4.4,
|
|
177
|
+
contextWindow: 128e3,
|
|
178
|
+
maxOutput: 65536,
|
|
179
|
+
reasoning: true
|
|
180
|
+
},
|
|
172
181
|
// Anthropic - all Claude models excel at agentic workflows
|
|
173
182
|
{
|
|
174
183
|
id: "anthropic/claude-haiku-4.5",
|
|
@@ -365,7 +374,15 @@ var BLOCKRUN_MODELS = [
|
|
|
365
374
|
inputPrice: 0,
|
|
366
375
|
outputPrice: 0,
|
|
367
376
|
contextWindow: 128e3,
|
|
368
|
-
maxOutput:
|
|
377
|
+
maxOutput: 16384
|
|
378
|
+
},
|
|
379
|
+
{
|
|
380
|
+
id: "nvidia/gpt-oss-20b",
|
|
381
|
+
name: "NVIDIA GPT-OSS 20B",
|
|
382
|
+
inputPrice: 0,
|
|
383
|
+
outputPrice: 0,
|
|
384
|
+
contextWindow: 128e3,
|
|
385
|
+
maxOutput: 16384
|
|
369
386
|
},
|
|
370
387
|
{
|
|
371
388
|
id: "nvidia/kimi-k2.5",
|
|
@@ -373,7 +390,7 @@ var BLOCKRUN_MODELS = [
|
|
|
373
390
|
inputPrice: 1e-3,
|
|
374
391
|
outputPrice: 1e-3,
|
|
375
392
|
contextWindow: 262144,
|
|
376
|
-
maxOutput:
|
|
393
|
+
maxOutput: 16384
|
|
377
394
|
}
|
|
378
395
|
];
|
|
379
396
|
function toOpenClawModel(m) {
|
|
@@ -450,6 +467,7 @@ var blockrunProvider = {
|
|
|
450
467
|
|
|
451
468
|
// src/proxy.ts
|
|
452
469
|
import { createServer } from "http";
|
|
470
|
+
import { finished } from "stream";
|
|
453
471
|
import { privateKeyToAccount as privateKeyToAccount2 } from "viem/accounts";
|
|
454
472
|
|
|
455
473
|
// src/x402.ts
|
|
@@ -2348,6 +2366,15 @@ function prioritizeNonRateLimited(models) {
|
|
|
2348
2366
|
}
|
|
2349
2367
|
return [...available, ...rateLimited];
|
|
2350
2368
|
}
|
|
2369
|
+
function canWrite(res) {
|
|
2370
|
+
return !res.writableEnded && !res.destroyed && res.socket !== null && !res.socket.destroyed && res.socket.writable;
|
|
2371
|
+
}
|
|
2372
|
+
function safeWrite(res, data) {
|
|
2373
|
+
if (!canWrite(res)) {
|
|
2374
|
+
return false;
|
|
2375
|
+
}
|
|
2376
|
+
return res.write(data);
|
|
2377
|
+
}
|
|
2351
2378
|
var BALANCE_CHECK_BUFFER = 1.5;
|
|
2352
2379
|
function getProxyPort() {
|
|
2353
2380
|
const envPort = process.env.BLOCKRUN_PROXY_PORT;
|
|
@@ -2556,7 +2583,24 @@ async function startProxy(options) {
|
|
|
2556
2583
|
};
|
|
2557
2584
|
const deduplicator = new RequestDeduplicator();
|
|
2558
2585
|
const sessionStore = new SessionStore(options.sessionConfig);
|
|
2586
|
+
const connections = /* @__PURE__ */ new Set();
|
|
2559
2587
|
const server = createServer(async (req, res) => {
|
|
2588
|
+
req.on("error", (err) => {
|
|
2589
|
+
console.error(`[ClawRouter] Request stream error: ${err.message}`);
|
|
2590
|
+
});
|
|
2591
|
+
res.on("error", (err) => {
|
|
2592
|
+
console.error(`[ClawRouter] Response stream error: ${err.message}`);
|
|
2593
|
+
});
|
|
2594
|
+
finished(res, (err) => {
|
|
2595
|
+
if (err && err.code !== "ERR_STREAM_DESTROYED") {
|
|
2596
|
+
console.error(`[ClawRouter] Response finished with error: ${err.message}`);
|
|
2597
|
+
}
|
|
2598
|
+
});
|
|
2599
|
+
finished(req, (err) => {
|
|
2600
|
+
if (err && err.code !== "ERR_STREAM_DESTROYED") {
|
|
2601
|
+
console.error(`[ClawRouter] Request finished with error: ${err.message}`);
|
|
2602
|
+
}
|
|
2603
|
+
});
|
|
2560
2604
|
if (req.url === "/health" || req.url?.startsWith("/health?")) {
|
|
2561
2605
|
const url = new URL(req.url, "http://localhost");
|
|
2562
2606
|
const full = url.searchParams.get("full") === "true";
|
|
@@ -2669,14 +2713,54 @@ async function startProxy(options) {
|
|
|
2669
2713
|
const port = addr.port;
|
|
2670
2714
|
const baseUrl = `http://127.0.0.1:${port}`;
|
|
2671
2715
|
options.onReady?.(port);
|
|
2716
|
+
server.on("error", (err) => {
|
|
2717
|
+
console.error(`[ClawRouter] Server runtime error: ${err.message}`);
|
|
2718
|
+
options.onError?.(err);
|
|
2719
|
+
});
|
|
2720
|
+
server.on("clientError", (err, socket) => {
|
|
2721
|
+
console.error(`[ClawRouter] Client error: ${err.message}`);
|
|
2722
|
+
if (socket.writable && !socket.destroyed) {
|
|
2723
|
+
socket.end("HTTP/1.1 400 Bad Request\r\n\r\n");
|
|
2724
|
+
}
|
|
2725
|
+
});
|
|
2726
|
+
server.on("connection", (socket) => {
|
|
2727
|
+
connections.add(socket);
|
|
2728
|
+
socket.setTimeout(3e5);
|
|
2729
|
+
socket.on("timeout", () => {
|
|
2730
|
+
console.error(`[ClawRouter] Socket timeout, destroying connection`);
|
|
2731
|
+
socket.destroy();
|
|
2732
|
+
});
|
|
2733
|
+
socket.on("end", () => {
|
|
2734
|
+
});
|
|
2735
|
+
socket.on("error", (err) => {
|
|
2736
|
+
console.error(`[ClawRouter] Socket error: ${err.message}`);
|
|
2737
|
+
});
|
|
2738
|
+
socket.on("close", () => {
|
|
2739
|
+
connections.delete(socket);
|
|
2740
|
+
});
|
|
2741
|
+
});
|
|
2672
2742
|
resolve({
|
|
2673
2743
|
port,
|
|
2674
2744
|
baseUrl,
|
|
2675
2745
|
walletAddress: account.address,
|
|
2676
2746
|
balanceMonitor,
|
|
2677
2747
|
close: () => new Promise((res, rej) => {
|
|
2748
|
+
const timeout = setTimeout(() => {
|
|
2749
|
+
rej(new Error("[ClawRouter] Close timeout after 4s"));
|
|
2750
|
+
}, 4e3);
|
|
2678
2751
|
sessionStore.close();
|
|
2679
|
-
|
|
2752
|
+
for (const socket of connections) {
|
|
2753
|
+
socket.destroy();
|
|
2754
|
+
}
|
|
2755
|
+
connections.clear();
|
|
2756
|
+
server.close((err) => {
|
|
2757
|
+
clearTimeout(timeout);
|
|
2758
|
+
if (err) {
|
|
2759
|
+
rej(err);
|
|
2760
|
+
} else {
|
|
2761
|
+
res();
|
|
2762
|
+
}
|
|
2763
|
+
});
|
|
2680
2764
|
})
|
|
2681
2765
|
});
|
|
2682
2766
|
});
|
|
@@ -2884,10 +2968,13 @@ async function proxyRequest(req, res, apiBase, payFetch, options, routerOpts, de
|
|
|
2884
2968
|
connection: "keep-alive"
|
|
2885
2969
|
});
|
|
2886
2970
|
headersSentEarly = true;
|
|
2887
|
-
res
|
|
2971
|
+
safeWrite(res, ": heartbeat\n\n");
|
|
2888
2972
|
heartbeatInterval = setInterval(() => {
|
|
2889
|
-
if (
|
|
2890
|
-
res
|
|
2973
|
+
if (canWrite(res)) {
|
|
2974
|
+
safeWrite(res, ": heartbeat\n\n");
|
|
2975
|
+
} else {
|
|
2976
|
+
clearInterval(heartbeatInterval);
|
|
2977
|
+
heartbeatInterval = void 0;
|
|
2891
2978
|
}
|
|
2892
2979
|
}, HEARTBEAT_INTERVAL_MS);
|
|
2893
2980
|
}
|
|
@@ -3005,8 +3092,8 @@ async function proxyRequest(req, res, apiBase, payFetch, options, routerOpts, de
|
|
|
3005
3092
|
const errEvent = `data: ${JSON.stringify({ error: { message: errBody, type: "provider_error", status: errStatus } })}
|
|
3006
3093
|
|
|
3007
3094
|
`;
|
|
3008
|
-
res
|
|
3009
|
-
res
|
|
3095
|
+
safeWrite(res, errEvent);
|
|
3096
|
+
safeWrite(res, "data: [DONE]\n\n");
|
|
3010
3097
|
res.end();
|
|
3011
3098
|
const errBuf = Buffer.from(errEvent + "data: [DONE]\n\n");
|
|
3012
3099
|
deduplicator.complete(dedupKey, {
|
|
@@ -3071,7 +3158,7 @@ async function proxyRequest(req, res, apiBase, payFetch, options, routerOpts, de
|
|
|
3071
3158
|
const roleData = `data: ${JSON.stringify(roleChunk)}
|
|
3072
3159
|
|
|
3073
3160
|
`;
|
|
3074
|
-
res
|
|
3161
|
+
safeWrite(res, roleData);
|
|
3075
3162
|
responseChunks.push(Buffer.from(roleData));
|
|
3076
3163
|
if (content) {
|
|
3077
3164
|
const contentChunk = {
|
|
@@ -3081,7 +3168,7 @@ async function proxyRequest(req, res, apiBase, payFetch, options, routerOpts, de
|
|
|
3081
3168
|
const contentData = `data: ${JSON.stringify(contentChunk)}
|
|
3082
3169
|
|
|
3083
3170
|
`;
|
|
3084
|
-
res
|
|
3171
|
+
safeWrite(res, contentData);
|
|
3085
3172
|
responseChunks.push(Buffer.from(contentData));
|
|
3086
3173
|
}
|
|
3087
3174
|
const toolCalls = choice.message?.tool_calls ?? choice.delta?.tool_calls;
|
|
@@ -3100,7 +3187,7 @@ async function proxyRequest(req, res, apiBase, payFetch, options, routerOpts, de
|
|
|
3100
3187
|
const toolCallData = `data: ${JSON.stringify(toolCallChunk)}
|
|
3101
3188
|
|
|
3102
3189
|
`;
|
|
3103
|
-
res
|
|
3190
|
+
safeWrite(res, toolCallData);
|
|
3104
3191
|
responseChunks.push(Buffer.from(toolCallData));
|
|
3105
3192
|
}
|
|
3106
3193
|
const finishChunk = {
|
|
@@ -3117,7 +3204,7 @@ async function proxyRequest(req, res, apiBase, payFetch, options, routerOpts, de
|
|
|
3117
3204
|
const finishData = `data: ${JSON.stringify(finishChunk)}
|
|
3118
3205
|
|
|
3119
3206
|
`;
|
|
3120
|
-
res
|
|
3207
|
+
safeWrite(res, finishData);
|
|
3121
3208
|
responseChunks.push(Buffer.from(finishData));
|
|
3122
3209
|
}
|
|
3123
3210
|
}
|
|
@@ -3125,11 +3212,11 @@ async function proxyRequest(req, res, apiBase, payFetch, options, routerOpts, de
|
|
|
3125
3212
|
const sseData = `data: ${jsonStr}
|
|
3126
3213
|
|
|
3127
3214
|
`;
|
|
3128
|
-
res
|
|
3215
|
+
safeWrite(res, sseData);
|
|
3129
3216
|
responseChunks.push(Buffer.from(sseData));
|
|
3130
3217
|
}
|
|
3131
3218
|
}
|
|
3132
|
-
res
|
|
3219
|
+
safeWrite(res, "data: [DONE]\n\n");
|
|
3133
3220
|
responseChunks.push(Buffer.from("data: [DONE]\n\n"));
|
|
3134
3221
|
res.end();
|
|
3135
3222
|
deduplicator.complete(dedupKey, {
|
|
@@ -3152,8 +3239,9 @@ async function proxyRequest(req, res, apiBase, payFetch, options, routerOpts, de
|
|
|
3152
3239
|
while (true) {
|
|
3153
3240
|
const { done, value } = await reader.read();
|
|
3154
3241
|
if (done) break;
|
|
3155
|
-
|
|
3156
|
-
|
|
3242
|
+
const chunk = Buffer.from(value);
|
|
3243
|
+
safeWrite(res, chunk);
|
|
3244
|
+
responseChunks.push(chunk);
|
|
3157
3245
|
}
|
|
3158
3246
|
} finally {
|
|
3159
3247
|
reader.releaseLock();
|