@blockrun/clawrouter 0.10.14 → 0.10.16
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/cli.js +217 -53
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +7 -0
- package/dist/index.js +217 -53
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -476,7 +476,8 @@ function classifyByRules(prompt, systemPrompt, estimatedTokens, config) {
|
|
|
476
476
|
tier: "REASONING",
|
|
477
477
|
confidence: Math.max(confidence2, 0.85),
|
|
478
478
|
signals,
|
|
479
|
-
agenticScore
|
|
479
|
+
agenticScore,
|
|
480
|
+
dimensions
|
|
480
481
|
};
|
|
481
482
|
}
|
|
482
483
|
const { simpleMedium, mediumComplex, complexReasoning } = config.tierBoundaries;
|
|
@@ -500,9 +501,9 @@ function classifyByRules(prompt, systemPrompt, estimatedTokens, config) {
|
|
|
500
501
|
}
|
|
501
502
|
const confidence = calibrateConfidence(distanceFromBoundary, config.confidenceSteepness);
|
|
502
503
|
if (confidence < config.confidenceThreshold) {
|
|
503
|
-
return { score: weightedScore, tier: null, confidence, signals, agenticScore };
|
|
504
|
+
return { score: weightedScore, tier: null, confidence, signals, agenticScore, dimensions };
|
|
504
505
|
}
|
|
505
|
-
return { score: weightedScore, tier, confidence, signals, agenticScore };
|
|
506
|
+
return { score: weightedScore, tier, confidence, signals, agenticScore, dimensions };
|
|
506
507
|
}
|
|
507
508
|
function calibrateConfidence(distance, steepness) {
|
|
508
509
|
return 1 / (1 + Math.exp(-steepness * distance));
|
|
@@ -558,6 +559,11 @@ function calculateModelCost(model, modelPricing, estimatedInputTokens, maxOutput
|
|
|
558
559
|
const savings = routingProfile === "premium" ? 0 : baselineCost > 0 ? Math.max(0, (baselineCost - costEstimate) / baselineCost) : 0;
|
|
559
560
|
return { costEstimate, baselineCost, savings };
|
|
560
561
|
}
|
|
562
|
+
function filterByToolCalling(models, hasTools, supportsToolCalling2) {
|
|
563
|
+
if (!hasTools) return models;
|
|
564
|
+
const filtered = models.filter(supportsToolCalling2);
|
|
565
|
+
return filtered.length > 0 ? filtered : models;
|
|
566
|
+
}
|
|
561
567
|
function getFallbackChainFiltered(tier, tierConfigs, estimatedTotalTokens, getContextWindow) {
|
|
562
568
|
const fullChain = getFallbackChain(tier, tierConfigs);
|
|
563
569
|
const filtered = fullChain.filter((modelId) => {
|
|
@@ -1737,7 +1743,11 @@ var DEFAULT_ROUTING_CONFIG = {
|
|
|
1737
1743
|
MEDIUM: {
|
|
1738
1744
|
primary: "moonshot/kimi-k2.5",
|
|
1739
1745
|
// $0.50/$2.40 - strong tool use, handles function calls correctly
|
|
1740
|
-
fallback: [
|
|
1746
|
+
fallback: [
|
|
1747
|
+
"anthropic/claude-haiku-4.5",
|
|
1748
|
+
"deepseek/deepseek-chat",
|
|
1749
|
+
"xai/grok-4-1-fast-non-reasoning"
|
|
1750
|
+
]
|
|
1741
1751
|
},
|
|
1742
1752
|
COMPLEX: {
|
|
1743
1753
|
primary: "anthropic/claude-sonnet-4.6",
|
|
@@ -1960,7 +1970,8 @@ var BLOCKRUN_MODELS = [
|
|
|
1960
1970
|
maxOutput: 128e3,
|
|
1961
1971
|
reasoning: true,
|
|
1962
1972
|
vision: true,
|
|
1963
|
-
agentic: true
|
|
1973
|
+
agentic: true,
|
|
1974
|
+
toolCalling: true
|
|
1964
1975
|
},
|
|
1965
1976
|
{
|
|
1966
1977
|
id: "openai/gpt-5-mini",
|
|
@@ -1969,7 +1980,8 @@ var BLOCKRUN_MODELS = [
|
|
|
1969
1980
|
inputPrice: 0.25,
|
|
1970
1981
|
outputPrice: 2,
|
|
1971
1982
|
contextWindow: 2e5,
|
|
1972
|
-
maxOutput: 65536
|
|
1983
|
+
maxOutput: 65536,
|
|
1984
|
+
toolCalling: true
|
|
1973
1985
|
},
|
|
1974
1986
|
{
|
|
1975
1987
|
id: "openai/gpt-5-nano",
|
|
@@ -1978,7 +1990,8 @@ var BLOCKRUN_MODELS = [
|
|
|
1978
1990
|
inputPrice: 0.05,
|
|
1979
1991
|
outputPrice: 0.4,
|
|
1980
1992
|
contextWindow: 128e3,
|
|
1981
|
-
maxOutput: 32768
|
|
1993
|
+
maxOutput: 32768,
|
|
1994
|
+
toolCalling: true
|
|
1982
1995
|
},
|
|
1983
1996
|
{
|
|
1984
1997
|
id: "openai/gpt-5.2-pro",
|
|
@@ -1988,7 +2001,8 @@ var BLOCKRUN_MODELS = [
|
|
|
1988
2001
|
outputPrice: 168,
|
|
1989
2002
|
contextWindow: 4e5,
|
|
1990
2003
|
maxOutput: 128e3,
|
|
1991
|
-
reasoning: true
|
|
2004
|
+
reasoning: true,
|
|
2005
|
+
toolCalling: true
|
|
1992
2006
|
},
|
|
1993
2007
|
// OpenAI Codex Family
|
|
1994
2008
|
{
|
|
@@ -1999,7 +2013,8 @@ var BLOCKRUN_MODELS = [
|
|
|
1999
2013
|
outputPrice: 14,
|
|
2000
2014
|
contextWindow: 128e3,
|
|
2001
2015
|
maxOutput: 32e3,
|
|
2002
|
-
agentic: true
|
|
2016
|
+
agentic: true,
|
|
2017
|
+
toolCalling: true
|
|
2003
2018
|
},
|
|
2004
2019
|
// OpenAI GPT-4 Family
|
|
2005
2020
|
{
|
|
@@ -2010,7 +2025,8 @@ var BLOCKRUN_MODELS = [
|
|
|
2010
2025
|
outputPrice: 8,
|
|
2011
2026
|
contextWindow: 128e3,
|
|
2012
2027
|
maxOutput: 16384,
|
|
2013
|
-
vision: true
|
|
2028
|
+
vision: true,
|
|
2029
|
+
toolCalling: true
|
|
2014
2030
|
},
|
|
2015
2031
|
{
|
|
2016
2032
|
id: "openai/gpt-4.1-mini",
|
|
@@ -2019,7 +2035,8 @@ var BLOCKRUN_MODELS = [
|
|
|
2019
2035
|
inputPrice: 0.4,
|
|
2020
2036
|
outputPrice: 1.6,
|
|
2021
2037
|
contextWindow: 128e3,
|
|
2022
|
-
maxOutput: 16384
|
|
2038
|
+
maxOutput: 16384,
|
|
2039
|
+
toolCalling: true
|
|
2023
2040
|
},
|
|
2024
2041
|
{
|
|
2025
2042
|
id: "openai/gpt-4.1-nano",
|
|
@@ -2028,7 +2045,8 @@ var BLOCKRUN_MODELS = [
|
|
|
2028
2045
|
inputPrice: 0.1,
|
|
2029
2046
|
outputPrice: 0.4,
|
|
2030
2047
|
contextWindow: 128e3,
|
|
2031
|
-
maxOutput: 16384
|
|
2048
|
+
maxOutput: 16384,
|
|
2049
|
+
toolCalling: true
|
|
2032
2050
|
},
|
|
2033
2051
|
{
|
|
2034
2052
|
id: "openai/gpt-4o",
|
|
@@ -2039,7 +2057,8 @@ var BLOCKRUN_MODELS = [
|
|
|
2039
2057
|
contextWindow: 128e3,
|
|
2040
2058
|
maxOutput: 16384,
|
|
2041
2059
|
vision: true,
|
|
2042
|
-
agentic: true
|
|
2060
|
+
agentic: true,
|
|
2061
|
+
toolCalling: true
|
|
2043
2062
|
},
|
|
2044
2063
|
{
|
|
2045
2064
|
id: "openai/gpt-4o-mini",
|
|
@@ -2048,7 +2067,8 @@ var BLOCKRUN_MODELS = [
|
|
|
2048
2067
|
inputPrice: 0.15,
|
|
2049
2068
|
outputPrice: 0.6,
|
|
2050
2069
|
contextWindow: 128e3,
|
|
2051
|
-
maxOutput: 16384
|
|
2070
|
+
maxOutput: 16384,
|
|
2071
|
+
toolCalling: true
|
|
2052
2072
|
},
|
|
2053
2073
|
// OpenAI O-series (Reasoning)
|
|
2054
2074
|
{
|
|
@@ -2059,7 +2079,8 @@ var BLOCKRUN_MODELS = [
|
|
|
2059
2079
|
outputPrice: 60,
|
|
2060
2080
|
contextWindow: 2e5,
|
|
2061
2081
|
maxOutput: 1e5,
|
|
2062
|
-
reasoning: true
|
|
2082
|
+
reasoning: true,
|
|
2083
|
+
toolCalling: true
|
|
2063
2084
|
},
|
|
2064
2085
|
{
|
|
2065
2086
|
id: "openai/o1-mini",
|
|
@@ -2069,7 +2090,8 @@ var BLOCKRUN_MODELS = [
|
|
|
2069
2090
|
outputPrice: 4.4,
|
|
2070
2091
|
contextWindow: 128e3,
|
|
2071
2092
|
maxOutput: 65536,
|
|
2072
|
-
reasoning: true
|
|
2093
|
+
reasoning: true,
|
|
2094
|
+
toolCalling: true
|
|
2073
2095
|
},
|
|
2074
2096
|
{
|
|
2075
2097
|
id: "openai/o3",
|
|
@@ -2079,7 +2101,8 @@ var BLOCKRUN_MODELS = [
|
|
|
2079
2101
|
outputPrice: 8,
|
|
2080
2102
|
contextWindow: 2e5,
|
|
2081
2103
|
maxOutput: 1e5,
|
|
2082
|
-
reasoning: true
|
|
2104
|
+
reasoning: true,
|
|
2105
|
+
toolCalling: true
|
|
2083
2106
|
},
|
|
2084
2107
|
{
|
|
2085
2108
|
id: "openai/o3-mini",
|
|
@@ -2089,7 +2112,8 @@ var BLOCKRUN_MODELS = [
|
|
|
2089
2112
|
outputPrice: 4.4,
|
|
2090
2113
|
contextWindow: 128e3,
|
|
2091
2114
|
maxOutput: 65536,
|
|
2092
|
-
reasoning: true
|
|
2115
|
+
reasoning: true,
|
|
2116
|
+
toolCalling: true
|
|
2093
2117
|
},
|
|
2094
2118
|
{
|
|
2095
2119
|
id: "openai/o4-mini",
|
|
@@ -2099,7 +2123,8 @@ var BLOCKRUN_MODELS = [
|
|
|
2099
2123
|
outputPrice: 4.4,
|
|
2100
2124
|
contextWindow: 128e3,
|
|
2101
2125
|
maxOutput: 65536,
|
|
2102
|
-
reasoning: true
|
|
2126
|
+
reasoning: true,
|
|
2127
|
+
toolCalling: true
|
|
2103
2128
|
},
|
|
2104
2129
|
// Anthropic - all Claude models excel at agentic workflows
|
|
2105
2130
|
// Use newest versions (4.6) with full provider prefix
|
|
@@ -2111,7 +2136,8 @@ var BLOCKRUN_MODELS = [
|
|
|
2111
2136
|
outputPrice: 5,
|
|
2112
2137
|
contextWindow: 2e5,
|
|
2113
2138
|
maxOutput: 8192,
|
|
2114
|
-
agentic: true
|
|
2139
|
+
agentic: true,
|
|
2140
|
+
toolCalling: true
|
|
2115
2141
|
},
|
|
2116
2142
|
{
|
|
2117
2143
|
id: "anthropic/claude-sonnet-4.6",
|
|
@@ -2122,7 +2148,8 @@ var BLOCKRUN_MODELS = [
|
|
|
2122
2148
|
contextWindow: 2e5,
|
|
2123
2149
|
maxOutput: 64e3,
|
|
2124
2150
|
reasoning: true,
|
|
2125
|
-
agentic: true
|
|
2151
|
+
agentic: true,
|
|
2152
|
+
toolCalling: true
|
|
2126
2153
|
},
|
|
2127
2154
|
{
|
|
2128
2155
|
id: "anthropic/claude-opus-4.6",
|
|
@@ -2133,7 +2160,8 @@ var BLOCKRUN_MODELS = [
|
|
|
2133
2160
|
contextWindow: 2e5,
|
|
2134
2161
|
maxOutput: 32e3,
|
|
2135
2162
|
reasoning: true,
|
|
2136
|
-
agentic: true
|
|
2163
|
+
agentic: true,
|
|
2164
|
+
toolCalling: true
|
|
2137
2165
|
},
|
|
2138
2166
|
// Google
|
|
2139
2167
|
{
|
|
@@ -2145,7 +2173,8 @@ var BLOCKRUN_MODELS = [
|
|
|
2145
2173
|
contextWindow: 105e4,
|
|
2146
2174
|
maxOutput: 65536,
|
|
2147
2175
|
reasoning: true,
|
|
2148
|
-
vision: true
|
|
2176
|
+
vision: true,
|
|
2177
|
+
toolCalling: true
|
|
2149
2178
|
},
|
|
2150
2179
|
{
|
|
2151
2180
|
id: "google/gemini-3-pro-preview",
|
|
@@ -2156,7 +2185,8 @@ var BLOCKRUN_MODELS = [
|
|
|
2156
2185
|
contextWindow: 105e4,
|
|
2157
2186
|
maxOutput: 65536,
|
|
2158
2187
|
reasoning: true,
|
|
2159
|
-
vision: true
|
|
2188
|
+
vision: true,
|
|
2189
|
+
toolCalling: true
|
|
2160
2190
|
},
|
|
2161
2191
|
{
|
|
2162
2192
|
id: "google/gemini-3-flash-preview",
|
|
@@ -2166,7 +2196,8 @@ var BLOCKRUN_MODELS = [
|
|
|
2166
2196
|
outputPrice: 3,
|
|
2167
2197
|
contextWindow: 1e6,
|
|
2168
2198
|
maxOutput: 65536,
|
|
2169
|
-
vision: true
|
|
2199
|
+
vision: true,
|
|
2200
|
+
toolCalling: true
|
|
2170
2201
|
},
|
|
2171
2202
|
{
|
|
2172
2203
|
id: "google/gemini-2.5-pro",
|
|
@@ -2177,7 +2208,8 @@ var BLOCKRUN_MODELS = [
|
|
|
2177
2208
|
contextWindow: 105e4,
|
|
2178
2209
|
maxOutput: 65536,
|
|
2179
2210
|
reasoning: true,
|
|
2180
|
-
vision: true
|
|
2211
|
+
vision: true,
|
|
2212
|
+
toolCalling: true
|
|
2181
2213
|
},
|
|
2182
2214
|
{
|
|
2183
2215
|
id: "google/gemini-2.5-flash",
|
|
@@ -2186,7 +2218,8 @@ var BLOCKRUN_MODELS = [
|
|
|
2186
2218
|
inputPrice: 0.3,
|
|
2187
2219
|
outputPrice: 2.5,
|
|
2188
2220
|
contextWindow: 1e6,
|
|
2189
|
-
maxOutput: 65536
|
|
2221
|
+
maxOutput: 65536,
|
|
2222
|
+
toolCalling: true
|
|
2190
2223
|
},
|
|
2191
2224
|
{
|
|
2192
2225
|
id: "google/gemini-2.5-flash-lite",
|
|
@@ -2195,7 +2228,8 @@ var BLOCKRUN_MODELS = [
|
|
|
2195
2228
|
inputPrice: 0.1,
|
|
2196
2229
|
outputPrice: 0.4,
|
|
2197
2230
|
contextWindow: 1e6,
|
|
2198
|
-
maxOutput: 65536
|
|
2231
|
+
maxOutput: 65536,
|
|
2232
|
+
toolCalling: true
|
|
2199
2233
|
},
|
|
2200
2234
|
// DeepSeek
|
|
2201
2235
|
{
|
|
@@ -2205,7 +2239,8 @@ var BLOCKRUN_MODELS = [
|
|
|
2205
2239
|
inputPrice: 0.28,
|
|
2206
2240
|
outputPrice: 0.42,
|
|
2207
2241
|
contextWindow: 128e3,
|
|
2208
|
-
maxOutput: 8192
|
|
2242
|
+
maxOutput: 8192,
|
|
2243
|
+
toolCalling: true
|
|
2209
2244
|
},
|
|
2210
2245
|
{
|
|
2211
2246
|
id: "deepseek/deepseek-reasoner",
|
|
@@ -2215,7 +2250,8 @@ var BLOCKRUN_MODELS = [
|
|
|
2215
2250
|
outputPrice: 0.42,
|
|
2216
2251
|
contextWindow: 128e3,
|
|
2217
2252
|
maxOutput: 8192,
|
|
2218
|
-
reasoning: true
|
|
2253
|
+
reasoning: true,
|
|
2254
|
+
toolCalling: true
|
|
2219
2255
|
},
|
|
2220
2256
|
// Moonshot / Kimi - optimized for agentic workflows
|
|
2221
2257
|
{
|
|
@@ -2228,7 +2264,8 @@ var BLOCKRUN_MODELS = [
|
|
|
2228
2264
|
maxOutput: 8192,
|
|
2229
2265
|
reasoning: true,
|
|
2230
2266
|
vision: true,
|
|
2231
|
-
agentic: true
|
|
2267
|
+
agentic: true,
|
|
2268
|
+
toolCalling: true
|
|
2232
2269
|
},
|
|
2233
2270
|
// xAI / Grok
|
|
2234
2271
|
{
|
|
@@ -2239,7 +2276,8 @@ var BLOCKRUN_MODELS = [
|
|
|
2239
2276
|
outputPrice: 15,
|
|
2240
2277
|
contextWindow: 131072,
|
|
2241
2278
|
maxOutput: 16384,
|
|
2242
|
-
reasoning: true
|
|
2279
|
+
reasoning: true,
|
|
2280
|
+
toolCalling: true
|
|
2243
2281
|
},
|
|
2244
2282
|
// grok-3-fast removed - too expensive ($5/$25), use grok-4-fast instead
|
|
2245
2283
|
{
|
|
@@ -2249,7 +2287,8 @@ var BLOCKRUN_MODELS = [
|
|
|
2249
2287
|
inputPrice: 0.3,
|
|
2250
2288
|
outputPrice: 0.5,
|
|
2251
2289
|
contextWindow: 131072,
|
|
2252
|
-
maxOutput: 16384
|
|
2290
|
+
maxOutput: 16384,
|
|
2291
|
+
toolCalling: true
|
|
2253
2292
|
},
|
|
2254
2293
|
// xAI Grok 4 Family - Ultra-cheap fast models
|
|
2255
2294
|
{
|
|
@@ -2260,7 +2299,8 @@ var BLOCKRUN_MODELS = [
|
|
|
2260
2299
|
outputPrice: 0.5,
|
|
2261
2300
|
contextWindow: 131072,
|
|
2262
2301
|
maxOutput: 16384,
|
|
2263
|
-
reasoning: true
|
|
2302
|
+
reasoning: true,
|
|
2303
|
+
toolCalling: true
|
|
2264
2304
|
},
|
|
2265
2305
|
{
|
|
2266
2306
|
id: "xai/grok-4-fast-non-reasoning",
|
|
@@ -2269,7 +2309,8 @@ var BLOCKRUN_MODELS = [
|
|
|
2269
2309
|
inputPrice: 0.2,
|
|
2270
2310
|
outputPrice: 0.5,
|
|
2271
2311
|
contextWindow: 131072,
|
|
2272
|
-
maxOutput: 16384
|
|
2312
|
+
maxOutput: 16384,
|
|
2313
|
+
toolCalling: true
|
|
2273
2314
|
},
|
|
2274
2315
|
{
|
|
2275
2316
|
id: "xai/grok-4-1-fast-reasoning",
|
|
@@ -2279,7 +2320,8 @@ var BLOCKRUN_MODELS = [
|
|
|
2279
2320
|
outputPrice: 0.5,
|
|
2280
2321
|
contextWindow: 131072,
|
|
2281
2322
|
maxOutput: 16384,
|
|
2282
|
-
reasoning: true
|
|
2323
|
+
reasoning: true,
|
|
2324
|
+
toolCalling: true
|
|
2283
2325
|
},
|
|
2284
2326
|
{
|
|
2285
2327
|
id: "xai/grok-4-1-fast-non-reasoning",
|
|
@@ -2288,7 +2330,8 @@ var BLOCKRUN_MODELS = [
|
|
|
2288
2330
|
inputPrice: 0.2,
|
|
2289
2331
|
outputPrice: 0.5,
|
|
2290
2332
|
contextWindow: 131072,
|
|
2291
|
-
maxOutput: 16384
|
|
2333
|
+
maxOutput: 16384,
|
|
2334
|
+
toolCalling: true
|
|
2292
2335
|
},
|
|
2293
2336
|
{
|
|
2294
2337
|
id: "xai/grok-code-fast-1",
|
|
@@ -2297,9 +2340,10 @@ var BLOCKRUN_MODELS = [
|
|
|
2297
2340
|
inputPrice: 0.2,
|
|
2298
2341
|
outputPrice: 1.5,
|
|
2299
2342
|
contextWindow: 131072,
|
|
2300
|
-
maxOutput: 16384
|
|
2301
|
-
|
|
2302
|
-
//
|
|
2343
|
+
maxOutput: 16384
|
|
2344
|
+
// toolCalling intentionally omitted: outputs tool calls as plain text JSON,
|
|
2345
|
+
// not OpenAI-compatible structured function calls. Will be skipped when
|
|
2346
|
+
// request has tools to prevent the "talking to itself" bug.
|
|
2303
2347
|
},
|
|
2304
2348
|
{
|
|
2305
2349
|
id: "xai/grok-4-0709",
|
|
@@ -2309,7 +2353,8 @@ var BLOCKRUN_MODELS = [
|
|
|
2309
2353
|
outputPrice: 1.5,
|
|
2310
2354
|
contextWindow: 131072,
|
|
2311
2355
|
maxOutput: 16384,
|
|
2312
|
-
reasoning: true
|
|
2356
|
+
reasoning: true,
|
|
2357
|
+
toolCalling: true
|
|
2313
2358
|
},
|
|
2314
2359
|
{
|
|
2315
2360
|
id: "xai/grok-2-vision",
|
|
@@ -2319,7 +2364,8 @@ var BLOCKRUN_MODELS = [
|
|
|
2319
2364
|
outputPrice: 10,
|
|
2320
2365
|
contextWindow: 131072,
|
|
2321
2366
|
maxOutput: 16384,
|
|
2322
|
-
vision: true
|
|
2367
|
+
vision: true,
|
|
2368
|
+
toolCalling: true
|
|
2323
2369
|
},
|
|
2324
2370
|
// MiniMax
|
|
2325
2371
|
{
|
|
@@ -2331,7 +2377,8 @@ var BLOCKRUN_MODELS = [
|
|
|
2331
2377
|
contextWindow: 204800,
|
|
2332
2378
|
maxOutput: 16384,
|
|
2333
2379
|
reasoning: true,
|
|
2334
|
-
agentic: true
|
|
2380
|
+
agentic: true,
|
|
2381
|
+
toolCalling: true
|
|
2335
2382
|
},
|
|
2336
2383
|
// NVIDIA - Free/cheap models
|
|
2337
2384
|
{
|
|
@@ -2342,6 +2389,8 @@ var BLOCKRUN_MODELS = [
|
|
|
2342
2389
|
outputPrice: 0,
|
|
2343
2390
|
contextWindow: 128e3,
|
|
2344
2391
|
maxOutput: 16384
|
|
2392
|
+
// toolCalling intentionally omitted: free model, structured function
|
|
2393
|
+
// calling support unverified. Excluded from tool-heavy routing paths.
|
|
2345
2394
|
},
|
|
2346
2395
|
{
|
|
2347
2396
|
id: "nvidia/kimi-k2.5",
|
|
@@ -2350,7 +2399,8 @@ var BLOCKRUN_MODELS = [
|
|
|
2350
2399
|
inputPrice: 0.55,
|
|
2351
2400
|
outputPrice: 2.5,
|
|
2352
2401
|
contextWindow: 262144,
|
|
2353
|
-
maxOutput: 16384
|
|
2402
|
+
maxOutput: 16384,
|
|
2403
|
+
toolCalling: true
|
|
2354
2404
|
}
|
|
2355
2405
|
];
|
|
2356
2406
|
function toOpenClawModel(m) {
|
|
@@ -2379,6 +2429,11 @@ var OPENCLAW_MODELS = [
|
|
|
2379
2429
|
...BLOCKRUN_MODELS.map(toOpenClawModel),
|
|
2380
2430
|
...ALIAS_MODELS
|
|
2381
2431
|
];
|
|
2432
|
+
function supportsToolCalling(modelId) {
|
|
2433
|
+
const normalized = modelId.replace("blockrun/", "");
|
|
2434
|
+
const model = BLOCKRUN_MODELS.find((m) => m.id === normalized);
|
|
2435
|
+
return model?.toolCalling ?? false;
|
|
2436
|
+
}
|
|
2382
2437
|
function getModelContextWindow(modelId) {
|
|
2383
2438
|
const normalized = modelId.replace("blockrun/", "");
|
|
2384
2439
|
const model = BLOCKRUN_MODELS.find((m) => m.id === normalized);
|
|
@@ -5032,6 +5087,7 @@ async function proxyRequest(req, res, apiBase, payFetch, options, routerOpts, de
|
|
|
5032
5087
|
const originalContextSizeKB = Math.ceil(body.length / 1024);
|
|
5033
5088
|
const debugMode = req.headers["x-clawrouter-debug"] !== "false";
|
|
5034
5089
|
let routingDecision;
|
|
5090
|
+
let hasTools = false;
|
|
5035
5091
|
let isStreaming = false;
|
|
5036
5092
|
let modelId = "";
|
|
5037
5093
|
let maxTokens = 4096;
|
|
@@ -5046,10 +5102,11 @@ async function proxyRequest(req, res, apiBase, payFetch, options, routerOpts, de
|
|
|
5046
5102
|
modelId = parsed.model || "";
|
|
5047
5103
|
maxTokens = parsed.max_tokens || 4096;
|
|
5048
5104
|
let bodyModified = false;
|
|
5049
|
-
|
|
5050
|
-
|
|
5051
|
-
|
|
5052
|
-
|
|
5105
|
+
const parsedMessages = Array.isArray(parsed.messages) ? parsed.messages : [];
|
|
5106
|
+
const lastUserMsg = [...parsedMessages].reverse().find((m) => m.role === "user");
|
|
5107
|
+
const lastContent = typeof lastUserMsg?.content === "string" ? lastUserMsg.content : "";
|
|
5108
|
+
if (sessionId && parsedMessages.length > 0) {
|
|
5109
|
+
const messages = parsedMessages;
|
|
5053
5110
|
if (sessionJournal.needsContext(lastContent)) {
|
|
5054
5111
|
const journalText = sessionJournal.format(sessionId);
|
|
5055
5112
|
if (journalText) {
|
|
@@ -5070,6 +5127,106 @@ async function proxyRequest(req, res, apiBase, payFetch, options, routerOpts, de
|
|
|
5070
5127
|
}
|
|
5071
5128
|
}
|
|
5072
5129
|
}
|
|
5130
|
+
if (lastContent.startsWith("/debug")) {
|
|
5131
|
+
const debugPrompt = lastContent.slice("/debug".length).trim() || "hello";
|
|
5132
|
+
const messages = parsed.messages;
|
|
5133
|
+
const systemMsg = messages?.find((m) => m.role === "system");
|
|
5134
|
+
const systemPrompt = typeof systemMsg?.content === "string" ? systemMsg.content : void 0;
|
|
5135
|
+
const fullText = `${systemPrompt ?? ""} ${debugPrompt}`;
|
|
5136
|
+
const estimatedTokens = Math.ceil(fullText.length / 4);
|
|
5137
|
+
const normalizedModel2 = typeof parsed.model === "string" ? parsed.model.trim().toLowerCase() : "";
|
|
5138
|
+
const profileName = normalizedModel2.replace("blockrun/", "");
|
|
5139
|
+
const debugProfile = ["free", "eco", "auto", "premium"].includes(profileName) ? profileName : "auto";
|
|
5140
|
+
const scoring = classifyByRules(
|
|
5141
|
+
debugPrompt,
|
|
5142
|
+
systemPrompt,
|
|
5143
|
+
estimatedTokens,
|
|
5144
|
+
DEFAULT_ROUTING_CONFIG.scoring
|
|
5145
|
+
);
|
|
5146
|
+
const debugRouting = route(debugPrompt, systemPrompt, maxTokens, {
|
|
5147
|
+
...routerOpts,
|
|
5148
|
+
routingProfile: debugProfile
|
|
5149
|
+
});
|
|
5150
|
+
const dimLines = (scoring.dimensions ?? []).map((d) => {
|
|
5151
|
+
const nameStr = (d.name + ":").padEnd(24);
|
|
5152
|
+
const scoreStr = d.score.toFixed(2).padStart(6);
|
|
5153
|
+
const sigStr = d.signal ? ` [${d.signal}]` : "";
|
|
5154
|
+
return ` ${nameStr}${scoreStr}${sigStr}`;
|
|
5155
|
+
}).join("\n");
|
|
5156
|
+
const sess = sessionId ? sessionStore.getSession(sessionId) : void 0;
|
|
5157
|
+
const sessLine = sess ? `Session: ${sessionId.slice(0, 8)}... \u2192 pinned: ${sess.model} (${sess.requestCount} requests)` : sessionId ? `Session: ${sessionId.slice(0, 8)}... \u2192 no pinned model` : "Session: none";
|
|
5158
|
+
const { simpleMedium, mediumComplex, complexReasoning } = DEFAULT_ROUTING_CONFIG.scoring.tierBoundaries;
|
|
5159
|
+
const debugText = [
|
|
5160
|
+
"ClawRouter Debug",
|
|
5161
|
+
"",
|
|
5162
|
+
`Profile: ${debugProfile} | Tier: ${debugRouting.tier} | Model: ${debugRouting.model}`,
|
|
5163
|
+
`Confidence: ${debugRouting.confidence.toFixed(2)} | Cost: $${debugRouting.costEstimate.toFixed(4)} | Savings: ${(debugRouting.savings * 100).toFixed(0)}%`,
|
|
5164
|
+
`Reasoning: ${debugRouting.reasoning}`,
|
|
5165
|
+
"",
|
|
5166
|
+
`Scoring (weighted: ${scoring.score.toFixed(3)})`,
|
|
5167
|
+
dimLines,
|
|
5168
|
+
"",
|
|
5169
|
+
`Tier Boundaries: SIMPLE <${simpleMedium.toFixed(2)} | MEDIUM <${mediumComplex.toFixed(2)} | COMPLEX <${complexReasoning.toFixed(2)} | REASONING >=${complexReasoning.toFixed(2)}`,
|
|
5170
|
+
"",
|
|
5171
|
+
sessLine
|
|
5172
|
+
].join("\n");
|
|
5173
|
+
const completionId = `chatcmpl-debug-${Date.now()}`;
|
|
5174
|
+
const timestamp = Math.floor(Date.now() / 1e3);
|
|
5175
|
+
const syntheticResponse = {
|
|
5176
|
+
id: completionId,
|
|
5177
|
+
object: "chat.completion",
|
|
5178
|
+
created: timestamp,
|
|
5179
|
+
model: "clawrouter/debug",
|
|
5180
|
+
choices: [
|
|
5181
|
+
{
|
|
5182
|
+
index: 0,
|
|
5183
|
+
message: { role: "assistant", content: debugText },
|
|
5184
|
+
finish_reason: "stop"
|
|
5185
|
+
}
|
|
5186
|
+
],
|
|
5187
|
+
usage: { prompt_tokens: 0, completion_tokens: 0, total_tokens: 0 }
|
|
5188
|
+
};
|
|
5189
|
+
if (isStreaming) {
|
|
5190
|
+
res.writeHead(200, {
|
|
5191
|
+
"Content-Type": "text/event-stream",
|
|
5192
|
+
"Cache-Control": "no-cache",
|
|
5193
|
+
Connection: "keep-alive"
|
|
5194
|
+
});
|
|
5195
|
+
const sseChunk = {
|
|
5196
|
+
id: completionId,
|
|
5197
|
+
object: "chat.completion.chunk",
|
|
5198
|
+
created: timestamp,
|
|
5199
|
+
model: "clawrouter/debug",
|
|
5200
|
+
choices: [
|
|
5201
|
+
{
|
|
5202
|
+
index: 0,
|
|
5203
|
+
delta: { role: "assistant", content: debugText },
|
|
5204
|
+
finish_reason: null
|
|
5205
|
+
}
|
|
5206
|
+
]
|
|
5207
|
+
};
|
|
5208
|
+
const sseDone = {
|
|
5209
|
+
id: completionId,
|
|
5210
|
+
object: "chat.completion.chunk",
|
|
5211
|
+
created: timestamp,
|
|
5212
|
+
model: "clawrouter/debug",
|
|
5213
|
+
choices: [{ index: 0, delta: {}, finish_reason: "stop" }]
|
|
5214
|
+
};
|
|
5215
|
+
res.write(`data: ${JSON.stringify(sseChunk)}
|
|
5216
|
+
|
|
5217
|
+
`);
|
|
5218
|
+
res.write(`data: ${JSON.stringify(sseDone)}
|
|
5219
|
+
|
|
5220
|
+
`);
|
|
5221
|
+
res.write("data: [DONE]\n\n");
|
|
5222
|
+
res.end();
|
|
5223
|
+
} else {
|
|
5224
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
5225
|
+
res.end(JSON.stringify(syntheticResponse));
|
|
5226
|
+
}
|
|
5227
|
+
console.log(`[ClawRouter] /debug command \u2192 ${debugRouting.tier} | ${debugRouting.model}`);
|
|
5228
|
+
return;
|
|
5229
|
+
}
|
|
5073
5230
|
if (parsed.stream === true) {
|
|
5074
5231
|
parsed.stream = false;
|
|
5075
5232
|
bodyModified = true;
|
|
@@ -5124,20 +5281,20 @@ async function proxyRequest(req, res, apiBase, payFetch, options, routerOpts, de
|
|
|
5124
5281
|
sessionStore.touchSession(sessionId2);
|
|
5125
5282
|
} else {
|
|
5126
5283
|
const messages = parsed.messages;
|
|
5127
|
-
let
|
|
5284
|
+
let lastUserMsg2;
|
|
5128
5285
|
if (messages) {
|
|
5129
5286
|
for (let i = messages.length - 1; i >= 0; i--) {
|
|
5130
5287
|
if (messages[i].role === "user") {
|
|
5131
|
-
|
|
5288
|
+
lastUserMsg2 = messages[i];
|
|
5132
5289
|
break;
|
|
5133
5290
|
}
|
|
5134
5291
|
}
|
|
5135
5292
|
}
|
|
5136
5293
|
const systemMsg = messages?.find((m) => m.role === "system");
|
|
5137
|
-
const prompt = typeof
|
|
5294
|
+
const prompt = typeof lastUserMsg2?.content === "string" ? lastUserMsg2.content : "";
|
|
5138
5295
|
const systemPrompt = typeof systemMsg?.content === "string" ? systemMsg.content : void 0;
|
|
5139
5296
|
const tools = parsed.tools;
|
|
5140
|
-
|
|
5297
|
+
hasTools = Array.isArray(tools) && tools.length > 0;
|
|
5141
5298
|
if (hasTools && tools) {
|
|
5142
5299
|
console.log(
|
|
5143
5300
|
`[ClawRouter] Tools detected (${tools.length}), agentic mode via keywords`
|
|
@@ -5354,7 +5511,14 @@ async function proxyRequest(req, res, apiBase, payFetch, options, routerOpts, de
|
|
|
5354
5511
|
`[ClawRouter] Context filter (~${estimatedTotalTokens} tokens): excluded ${contextExcluded.join(", ")}`
|
|
5355
5512
|
);
|
|
5356
5513
|
}
|
|
5357
|
-
|
|
5514
|
+
const toolFiltered = filterByToolCalling(contextFiltered, hasTools, supportsToolCalling);
|
|
5515
|
+
const toolExcluded = contextFiltered.filter((m) => !toolFiltered.includes(m));
|
|
5516
|
+
if (toolExcluded.length > 0) {
|
|
5517
|
+
console.log(
|
|
5518
|
+
`[ClawRouter] Tool-calling filter: excluded ${toolExcluded.join(", ")} (no structured function call support)`
|
|
5519
|
+
);
|
|
5520
|
+
}
|
|
5521
|
+
modelsToTry = toolFiltered.slice(0, MAX_FALLBACK_ATTEMPTS);
|
|
5358
5522
|
modelsToTry = prioritizeNonRateLimited(modelsToTry);
|
|
5359
5523
|
} else {
|
|
5360
5524
|
if (modelId && modelId !== FREE_MODEL) {
|