@blockrun/clawrouter 0.12.240 → 0.12.242
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/README.md +16 -17
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +1649 -140
- package/dist/index.d.ts +13 -176
- package/dist/index.js +1649 -140
- package/dist/router/index.d.ts +1 -0
- package/dist/router/index.js +3292 -0
- package/docs/anthropic-cost-savings.md +1 -1
- package/docs/anthropic-third-party-harness-changes.md +2 -2
- package/docs/clawrouter-cuts-llm-api-costs-500x.md +1 -1
- package/docs/clawrouter-vs-openrouter-llm-routing-comparison.md +3 -3
- package/package.json +7 -2
- package/skills/clawrouter/SKILL.md +3 -3
- package/src/top-models.json +0 -1
package/dist/index.js
CHANGED
|
@@ -93,7 +93,6 @@ var init_top_models = __esm({
|
|
|
93
93
|
"deepseek/deepseek-chat",
|
|
94
94
|
"deepseek/deepseek-reasoner",
|
|
95
95
|
"free/deepseek-v4-flash",
|
|
96
|
-
"free/seed-oss-36b",
|
|
97
96
|
"free/nemotron-3-nano-omni-30b-a3b-reasoning",
|
|
98
97
|
"free/mistral-nemotron",
|
|
99
98
|
"free/step-3.7-flash",
|
|
@@ -403,9 +402,10 @@ var init_models = __esm({
|
|
|
403
402
|
"free/deepseek-v4-pro": "free/deepseek-v4-flash",
|
|
404
403
|
"nvidia/deepseek-v4-flash": "free/deepseek-v4-flash",
|
|
405
404
|
"nvidia/nemotron-3-nano-omni-30b-a3b-reasoning": "free/nemotron-3-nano-omni-30b-a3b-reasoning",
|
|
406
|
-
// qwen3-coder-480b retired (NVIDIA EOL 2026-06-14)
|
|
407
|
-
//
|
|
408
|
-
//
|
|
405
|
+
// qwen3-coder-480b retired (NVIDIA EOL 2026-06-14). Its server-side redirect used
|
|
406
|
+
// to be seed-oss-36b, but that EOL'd too on 2026-08-03, so blockrun re-pointed it
|
|
407
|
+
// at gpt-oss-120b. Keep the explicit id mappings for pinned callers (BlockRun still
|
|
408
|
+
// resolves them); the generic coding shorthands follow the gateway to gpt-oss-120b.
|
|
409
409
|
"nvidia/qwen3-coder-480b": "free/qwen3-coder-480b",
|
|
410
410
|
"qwen/qwen3-coder-480b-a35b-instruct": "free/qwen3-coder-480b",
|
|
411
411
|
// glm-4.7 pin keeps the real id — blockrun redirects it server-side (→ gpt-oss-120b).
|
|
@@ -451,13 +451,14 @@ var init_models = __esm({
|
|
|
451
451
|
"v4-flash": "free/deepseek-v4-flash",
|
|
452
452
|
"mistral-free": "free/mistral-nemotron",
|
|
453
453
|
// mistral-large-3-675b EOL'd 2026-07-28 → last live free Mistral (blockrun demoted its /free-mistral primary the same way)
|
|
454
|
-
"glm-free": "free/
|
|
455
|
-
//
|
|
454
|
+
"glm-free": "free/gpt-oss-120b",
|
|
455
|
+
// seed-oss-36b (the prior target) EOL'd 2026-08-03
|
|
456
456
|
"llama-free": "free/gpt-oss-120b",
|
|
457
457
|
// no live free Llama left (maverick died 2026-07)
|
|
458
|
-
|
|
459
|
-
//
|
|
460
|
-
"qwen-coder
|
|
458
|
+
// qwen3-coder-480b retired 2026-06-14 → seed-oss-36b, which then EOL'd 2026-08-03.
|
|
459
|
+
// Follow the gateway's own retarget rather than chaining to a second dead model.
|
|
460
|
+
"qwen-coder": "free/gpt-oss-120b",
|
|
461
|
+
"qwen-coder-free": "free/gpt-oss-120b",
|
|
461
462
|
"qwen-thinking": "free/gpt-oss-120b",
|
|
462
463
|
// qwen3-next died 2026-07-17; no live free Qwen left
|
|
463
464
|
"qwen3-next": "free/qwen3-next-80b-a3b-instruct",
|
|
@@ -466,9 +467,11 @@ var init_models = __esm({
|
|
|
466
467
|
"mistral-small": "free/mistral-nemotron",
|
|
467
468
|
// closest live Mistral-family free model
|
|
468
469
|
// New live free models (2026-06-14 BlockRun free-tier refresh)
|
|
470
|
+
// seed-oss pins name the model itself — kept routable, the gateway redirects them.
|
|
469
471
|
"seed-oss": "free/seed-oss-36b",
|
|
470
472
|
"seed-oss-36b": "free/seed-oss-36b",
|
|
471
|
-
"coder-free": "free/
|
|
473
|
+
"coder-free": "free/gpt-oss-120b",
|
|
474
|
+
// generic "a free coder" → follows the gateway retarget
|
|
472
475
|
"mistral-nemotron": "free/mistral-nemotron",
|
|
473
476
|
"step-flash": "free/step-3.7-flash",
|
|
474
477
|
"step-3.7-flash": "free/step-3.7-flash",
|
|
@@ -489,8 +492,9 @@ var init_models = __esm({
|
|
|
489
492
|
"nemotron-super": "free/gpt-oss-120b",
|
|
490
493
|
"nemotron-49b": "free/gpt-oss-120b",
|
|
491
494
|
"nemotron-120b": "free/gpt-oss-120b",
|
|
492
|
-
devstral: "free/
|
|
493
|
-
|
|
495
|
+
devstral: "free/gpt-oss-120b",
|
|
496
|
+
// seed-oss-36b EOL'd 2026-08-03; matches blockrun's own retarget
|
|
497
|
+
"devstral-2": "free/gpt-oss-120b",
|
|
494
498
|
maverick: "free/llama-4-maverick",
|
|
495
499
|
// explicit-ish pin — gateway redirects
|
|
496
500
|
free: "free/gpt-oss-120b",
|
|
@@ -1613,8 +1617,13 @@ var init_models = __esm({
|
|
|
1613
1617
|
reasoning: true
|
|
1614
1618
|
},
|
|
1615
1619
|
{
|
|
1616
|
-
// ByteDance Seed-OSS 36B:
|
|
1617
|
-
//
|
|
1620
|
+
// ByteDance Seed-OSS 36B: was the free coder, and the redirect target for the
|
|
1621
|
+
// retired qwen3-coder-480b. EOL'd 2026-08-03 — blockrun's probe got HTTP 410
|
|
1622
|
+
// Gone from NVIDIA on both passes and the prod health gate fired
|
|
1623
|
+
// [ALERT][free-model-dead] kind=gone the same day; upstream now hides it and
|
|
1624
|
+
// re-pointed its own dependents (qwen3-coder-480b, devstral-2) at gpt-oss-120b.
|
|
1625
|
+
// Entry kept so explicit pins stay routable; off the picker, the FREE_MODELS
|
|
1626
|
+
// cascade, and the router fallback chains.
|
|
1618
1627
|
id: "free/seed-oss-36b",
|
|
1619
1628
|
name: "[Free] Seed-OSS 36B",
|
|
1620
1629
|
version: "oss-36b",
|
|
@@ -34768,7 +34777,7 @@ var init_esm5 = __esm({
|
|
|
34768
34777
|
}
|
|
34769
34778
|
});
|
|
34770
34779
|
|
|
34771
|
-
//
|
|
34780
|
+
// node_modules/@blockrun/router-core/dist/index.js
|
|
34772
34781
|
function scoreTokenCount(estimatedTokens, thresholds) {
|
|
34773
34782
|
if (estimatedTokens < thresholds.simple) {
|
|
34774
34783
|
return { name: "tokenCount", score: -1, signal: `short (${estimatedTokens} tokens)` };
|
|
@@ -35008,13 +35017,6 @@ function classifyByRules(prompt, systemPrompt, estimatedTokens, config) {
|
|
|
35008
35017
|
function calibrateConfidence(distance, steepness) {
|
|
35009
35018
|
return 1 / (1 + Math.exp(-steepness * distance));
|
|
35010
35019
|
}
|
|
35011
|
-
var init_rules = __esm({
|
|
35012
|
-
"src/router/rules.ts"() {
|
|
35013
|
-
"use strict";
|
|
35014
|
-
}
|
|
35015
|
-
});
|
|
35016
|
-
|
|
35017
|
-
// src/router/selector.ts
|
|
35018
35020
|
function selectModel(tier, confidence, method, reasoning, tierConfigs, modelPricing, estimatedInputTokens, maxOutputTokens, routingProfile, agenticScore) {
|
|
35019
35021
|
const tierConfig = tierConfigs[tier];
|
|
35020
35022
|
const model = tierConfig.primary;
|
|
@@ -35103,19 +35105,14 @@ function getFallbackChainFiltered(tier, tierConfigs, estimatedTotalTokens, getCo
|
|
|
35103
35105
|
}
|
|
35104
35106
|
return filtered;
|
|
35105
35107
|
}
|
|
35106
|
-
|
|
35107
|
-
|
|
35108
|
-
|
|
35109
|
-
|
|
35110
|
-
|
|
35111
|
-
|
|
35112
|
-
|
|
35113
|
-
|
|
35114
|
-
MIN_PAYMENT_USD = 1e-3;
|
|
35115
|
-
}
|
|
35116
|
-
});
|
|
35117
|
-
|
|
35118
|
-
// src/router/strategy.ts
|
|
35108
|
+
function filterCandidatesByCapacity(models, estimatedInputTokens, requestedOutputTokens, getCapabilities2) {
|
|
35109
|
+
const filtered = models.filter((modelId) => {
|
|
35110
|
+
const capabilities = getCapabilities2(modelId);
|
|
35111
|
+
if (!capabilities) return true;
|
|
35112
|
+
return capabilities.contextWindow >= (estimatedInputTokens + requestedOutputTokens) * 1.1 && capabilities.maxOutput >= requestedOutputTokens;
|
|
35113
|
+
});
|
|
35114
|
+
return filtered;
|
|
35115
|
+
}
|
|
35119
35116
|
function applyPromotions(tierConfigs, promotions, profile, now2 = /* @__PURE__ */ new Date()) {
|
|
35120
35117
|
if (!promotions || promotions.length === 0) return tierConfigs;
|
|
35121
35118
|
let result = tierConfigs;
|
|
@@ -35145,19 +35142,666 @@ function getStrategy(name) {
|
|
|
35145
35142
|
}
|
|
35146
35143
|
return strategy;
|
|
35147
35144
|
}
|
|
35148
|
-
|
|
35149
|
-
|
|
35150
|
-
|
|
35145
|
+
function registerStrategy(strategy) {
|
|
35146
|
+
registry.set(strategy.name, strategy);
|
|
35147
|
+
}
|
|
35148
|
+
function inferToolRequirement(prompt, _systemPrompt, toolChoice) {
|
|
35149
|
+
if (toolChoice === "none") return false;
|
|
35150
|
+
if (toolChoice === "required") return true;
|
|
35151
|
+
if (typeof toolChoice === "object" && toolChoice !== null && toolChoice.type === "function") {
|
|
35152
|
+
return true;
|
|
35153
|
+
}
|
|
35154
|
+
const text = prompt;
|
|
35155
|
+
const explicitTool = /\b(?:use|call|invoke)\s+(?:the\s+)?[\w.-]+\s+(?:tool|function|api)\b|\btool[_ -]?call\b|使用.{0,20}(?:工具|函数|接口)|调用.{0,20}(?:工具|函数|接口)/i;
|
|
35156
|
+
const codeEnvironment = /\b(?:run|execute)\s+(?:the\s+)?(?:tests?|command|script|build|linter)|\b(?:edit|modify|patch|create|write|save|delete|rename|move|inspect|read)\b.{0,60}\b(?:file|repository|repo|codebase|directory|folder)\b|\b(?:terminal|shell|bash|zsh|pytest|npm test|pnpm test|git\s+(?:status|diff|commit)|docker)\b|(?:运行|执行).{0,20}(?:测试|命令|脚本|构建)|(?:修改|编辑|修复|创建|读取|检查|保存).{0,30}(?:文件|仓库|代码库|目录)/i;
|
|
35157
|
+
const webAction = /\b(?:browse|search|look up|fetch|open)\b.{0,80}\b(?:web|website|url|online|documentation|docs|news|weather|price)\b|(?:浏览|搜索|查询|打开).{0,30}(?:网页|网站|链接|文档|新闻|天气|价格)/i;
|
|
35158
|
+
const statefulAction = /\b(?:refund|cancel|book|reserve|purchase|buy|return|exchange|transfer|update|change)\b.{0,80}\b(?:order|booking|reservation|account|address|payment|subscription|ticket|flight|item)\b|(?:退款|取消|预订|购买|退货|换货|转账|更新|修改).{0,30}(?:订单|预订|账户|地址|付款|订阅|票|航班|商品)/i;
|
|
35159
|
+
return explicitTool.test(text) || codeEnvironment.test(text) || webAction.test(text) || statefulAction.test(text);
|
|
35160
|
+
}
|
|
35161
|
+
function likelyNeedsParallelToolCalls(prompt, needsTools, toolCount, toolNames) {
|
|
35162
|
+
if (!needsTools || toolCount === void 0 || toolCount < 1) return false;
|
|
35163
|
+
const text = prompt.trim();
|
|
35164
|
+
const explicitRepeat = /\b(?:in parallel|simultaneously|concurrently|for each|each of|every one|both|(?:two|three|multiple|several)\s+(?:cities|locations|items|tasks|orders|users|files))\b|并行|同时|分别|每个|各自|(?:两个|三个|多个)(?:城市|地点|项目|任务|订单|用户|文件)|cada uno|para cada|simult[aá]neamente/i.test(
|
|
35165
|
+
text
|
|
35166
|
+
);
|
|
35167
|
+
if (explicitRepeat) return true;
|
|
35168
|
+
const sentenceClauses = text.split(/[.!?。!?]+/).map((part) => part.trim()).filter((part) => part.length >= 8);
|
|
35169
|
+
if (/\b(?:also|additionally|furthermore)\b|另外|此外|그리고/i.test(text) && sentenceClauses.length >= 2 || /\band\s+(?:also|for the)\b/i.test(text))
|
|
35170
|
+
return true;
|
|
35171
|
+
const pairedQuantity = /\b\d+(?:\.\d+)?\s+(?:and|or)\s+\d+(?:\.\d+)?\s*(?:gb|mb|tb|kg|g|ml|oz|cups?|cores?|cpus?)\b/i.test(
|
|
35172
|
+
text
|
|
35173
|
+
);
|
|
35174
|
+
if (pairedQuantity) return true;
|
|
35175
|
+
const operationTokens = /* @__PURE__ */ new Set([
|
|
35176
|
+
"add",
|
|
35177
|
+
"delete",
|
|
35178
|
+
"remove",
|
|
35179
|
+
"cancel",
|
|
35180
|
+
"return",
|
|
35181
|
+
"exchange",
|
|
35182
|
+
"modify",
|
|
35183
|
+
"book",
|
|
35184
|
+
"transfer",
|
|
35185
|
+
"send",
|
|
35186
|
+
"upload",
|
|
35187
|
+
"download",
|
|
35188
|
+
"create",
|
|
35189
|
+
"close"
|
|
35190
|
+
]);
|
|
35191
|
+
const lowered = text.toLowerCase();
|
|
35192
|
+
const matchedOperationTokens = new Set(
|
|
35193
|
+
(toolNames ?? []).flatMap((name) => name.toLowerCase().split(/[^a-z0-9\u3400-\u9fff]+/)).filter((token) => operationTokens.has(token) && lowered.includes(token))
|
|
35194
|
+
);
|
|
35195
|
+
if (matchedOperationTokens.size >= 2) return true;
|
|
35196
|
+
const nonEmptyLines = text.split(/\r?\n/).map((line) => line.trim()).filter(Boolean);
|
|
35197
|
+
const quantityMentions = text.match(
|
|
35198
|
+
/\b(?:\d+(?:\.\d+)?|one|two|three|four|five|six|seven|eight|nine|ten)\s*(?:oz|ounce|ounces|g|gram|grams|kg|ml|cups?|pieces?|tablespoons?)\b/gi
|
|
35199
|
+
) ?? [];
|
|
35200
|
+
if (nonEmptyLines.length >= 2 && quantityMentions.length >= 2) return true;
|
|
35201
|
+
const repeatedLookup = /\b(?:weather|climate|clima|tiempo|temperature|snow|news|report)\b|天气|气象|温度|降雪|新闻|报告/i.test(
|
|
35202
|
+
text
|
|
35203
|
+
);
|
|
35204
|
+
const multiLocationConnector = /\b(?:and also|both|y|e)\b|还有|以及|和|、/i.test(text);
|
|
35205
|
+
const commaSeparatedLocations = (text.match(/[,,]/g) ?? []).length >= 2;
|
|
35206
|
+
if (repeatedLookup && (multiLocationConnector || commaSeparatedLocations)) return true;
|
|
35207
|
+
const distinctOrderParts = /\b(?:food|meal)\b[\s\S]*\bdrink\b|\bdrink\b[\s\S]*\b(?:food|meal)\b/i.test(text);
|
|
35208
|
+
const koreanParallelClauses = (text.match(/,/g) ?? []).length >= 3 && /하고|그리고/.test(text);
|
|
35209
|
+
return distinctOrderParts || koreanParallelClauses;
|
|
35210
|
+
}
|
|
35211
|
+
function classifyTask(prompt, systemPrompt, options) {
|
|
35212
|
+
const fullText = `${systemPrompt ?? ""} ${prompt}`;
|
|
35213
|
+
const estimatedInputTokens = Math.ceil(fullText.length / 4);
|
|
35214
|
+
const scanLimit = Math.max(1, Math.min(8e3, options.config.classifier.promptTruncationChars));
|
|
35215
|
+
const sample = (value) => {
|
|
35216
|
+
if (value.length <= scanLimit) return value;
|
|
35217
|
+
const prefixLength = Math.ceil(scanLimit / 2);
|
|
35218
|
+
return `${value.slice(0, prefixLength)}
|
|
35219
|
+
${value.slice(-(scanLimit - prefixLength))}`;
|
|
35220
|
+
};
|
|
35221
|
+
const scannedPrompt = sample(prompt);
|
|
35222
|
+
const scannedSystemPrompt = sample(systemPrompt ?? "");
|
|
35223
|
+
const scannedFullText = `${scannedSystemPrompt} ${scannedPrompt}`;
|
|
35224
|
+
const text = scannedPrompt.toLowerCase();
|
|
35225
|
+
const explicitCodeSignal = /```|\b(?:typescript|javascript|python|rust|java|sql|stack trace|traceback|exception)\b|\.(?:ts|tsx|js|py|go|rs)\b/i.test(
|
|
35226
|
+
scannedPrompt
|
|
35227
|
+
);
|
|
35228
|
+
const codeConstructSignal = /\b(?:implement|refactor|debug|write|edit|modify|create|define|review|fix)\b[\s\S]{0,48}\b(?:api|function|class|method)\b|\b(?:api|function|class|method)\b[\s\S]{0,48}\b(?:code|implementation|typescript|javascript|python|rust|java)\b/i.test(
|
|
35229
|
+
scannedPrompt
|
|
35230
|
+
);
|
|
35231
|
+
const nativeCodeSignal = /\b(?:programmed|written|implemented?|code)\s+(?:in|using)\s+(?:c\+\+|c|rust|go)\b/i.test(
|
|
35232
|
+
scannedPrompt
|
|
35233
|
+
);
|
|
35234
|
+
const hasCode = explicitCodeSignal || codeConstructSignal || nativeCodeSignal;
|
|
35235
|
+
const toolsAvailable = options.hasTools ?? false;
|
|
35236
|
+
const needsTools = options.requiresTools ?? (toolsAvailable && inferToolRequirement(scannedPrompt, scannedSystemPrompt));
|
|
35237
|
+
const likelyParallelToolCalls = likelyNeedsParallelToolCalls(
|
|
35238
|
+
scannedPrompt,
|
|
35239
|
+
needsTools,
|
|
35240
|
+
options.toolCount,
|
|
35241
|
+
options.toolNames
|
|
35242
|
+
);
|
|
35243
|
+
const normalizedToolNames = (options.toolNames ?? []).map((name) => name.toLowerCase());
|
|
35244
|
+
const airlineToolSignal = normalizedToolNames.some(
|
|
35245
|
+
(name) => /(?:flight|reservation|airport|baggage|passenger)/.test(name)
|
|
35246
|
+
);
|
|
35247
|
+
const retailToolSignal = normalizedToolNames.some(
|
|
35248
|
+
(name) => /(?:order|product|item|return|exchange|address)/.test(name)
|
|
35249
|
+
);
|
|
35250
|
+
const webResearchToolSignal = normalizedToolNames.some(
|
|
35251
|
+
(name) => /^(?:web_?search|web_?fetch)$/.test(name)
|
|
35252
|
+
);
|
|
35253
|
+
const agentDomain = airlineToolSignal && !retailToolSignal ? "airline" : retailToolSignal && !airlineToolSignal ? "retail" : webResearchToolSignal ? "web_research" : "other";
|
|
35254
|
+
const clueConnectors = scannedFullText.match(
|
|
35255
|
+
/\b(?:after|before|while|where|whose|which|in \d{4}|as of|over \d+|another|also|furthermore)\b|(?:之后|之前|其中|截至|超过|另一个|此外)/gi
|
|
35256
|
+
) ?? [];
|
|
35257
|
+
const entityResolutionSignal = /\b(?:identify|who (?:is|was)|what (?:is|was) the name|which (?:person|player|company|country|city)|find the (?:person|player|name|entity))\b|(?:找出|识别|是谁|哪位|名称是什么)/i.test(
|
|
35258
|
+
scannedFullText
|
|
35259
|
+
);
|
|
35260
|
+
const exactAnswerSignal = /\b(?:exact answer|single best-supported answer|following clues|multiple public sources)\b|(?:精确答案|根据.*线索|多个公开来源)/i.test(
|
|
35261
|
+
scannedFullText
|
|
35262
|
+
);
|
|
35263
|
+
const deepWebResearch = agentDomain === "web_research" && (exactAnswerSignal || entityResolutionSignal && (clueConnectors.length >= 3 || prompt.length >= 320));
|
|
35264
|
+
const globalOptimizationSignal = /\b(?:cheapest|lowest[- ]price|least expensive|most expensive|highest(?:[- ]priced)?|largest|smallest|maximum|minimum|best available|closest|not (?:cost|exceed))\b|最便宜|最低价|最贵|最高价|最大|最小/i.test(
|
|
35265
|
+
scannedPrompt
|
|
35266
|
+
);
|
|
35267
|
+
const globalScopeSignal = /\b(?:everything|all (?:(?:my|your|their|the) )?(?:future |upcoming )?(?:items|orders|passengers|flights|reservations|bookings)|every (?:item|order|passenger|flight|reservation|booking))\b|全部|所有|每个/i.test(
|
|
35268
|
+
scannedPrompt
|
|
35269
|
+
);
|
|
35270
|
+
const globalChoiceSignal = globalOptimizationSignal || globalScopeSignal;
|
|
35271
|
+
const crossRecordSignal = /\b(?:another|other|different|previous)\s+(?:order|reservation|booking|account|address)\b|另一(?:个)?(?:订单|预订|账户|地址)|其他(?:订单|预订|账户|地址)/i.test(
|
|
35272
|
+
scannedPrompt
|
|
35273
|
+
);
|
|
35274
|
+
const reservationIds = scannedPrompt.match(/\b[A-Z0-9]{6}\b/g) ?? [];
|
|
35275
|
+
const crossReservationBatchSignal = agentDomain === "airline" && (/\b(?:two|three|multiple|several)(?:\s+of\s+(?:my|our|the))?\s+(?:upcoming\s+)?(?:reservations?|bookings?)\b|\b(?:a\s+)?(?:second|third)\s+(?:reservation|booking)\b/i.test(
|
|
35276
|
+
scannedPrompt
|
|
35277
|
+
) || new Set(reservationIds).size >= 2);
|
|
35278
|
+
const conditionalGlobalWorkflowSignal = agentDomain === "airline" && globalScopeSignal && /\b(?:if|that (?:contain|have)|longer than|shorter than|under|over|at (?:most|least)|wherever possible)\b|如果|超过|少于|不超过|尽可能/i.test(
|
|
35279
|
+
scannedPrompt
|
|
35280
|
+
) && /\b(?:cancel|change|upgrade|move|book)\b[\s\S]*\b(?:cancel|change|upgrade|move|book)\b|取消[\s\S]*(?:升级|更改)|升级[\s\S]*(?:取消|更改)/i.test(
|
|
35281
|
+
scannedPrompt
|
|
35282
|
+
);
|
|
35283
|
+
const policyExceptionSignal = agentDomain === "retail" && /\b(?:return|refund|send back|get (?:my |the )?money back)\b|退货|退款|退回/i.test(
|
|
35284
|
+
scannedPrompt
|
|
35285
|
+
) && /\b(?:amex|american express|visa|mastercard|credit card|debit card|different card|another card|other card)\b|信用卡|借记卡|其他卡|另一张卡/i.test(
|
|
35286
|
+
scannedPrompt
|
|
35287
|
+
);
|
|
35288
|
+
const singleSelectedPolicyException = policyExceptionSignal && /\b(?:return|refund|send back)\b[^.!?。!?]{0,96}\b(?:the )?(?:pricier|cheaper|more expensive|less expensive|costlier|one)\b/i.test(
|
|
35289
|
+
scannedPrompt
|
|
35290
|
+
);
|
|
35291
|
+
const negotiatedWorkflowSignal = agentDomain === "retail" && /\b(?:return|exchange)\b|退货|退回|换货|交换/i.test(scannedPrompt);
|
|
35292
|
+
const numberedSteps = (scannedPrompt.match(/(?:^|\s)\d+(?:\.\d+)*[.)]\s+/g) ?? []).length;
|
|
35293
|
+
const complexMultiToolPlan = likelyParallelToolCalls && ((options.toolCount ?? 0) >= 6 || numberedSteps >= 3 || prompt.length > 1200);
|
|
35294
|
+
let agentRisk = needsTools && singleSelectedPolicyException ? "policy_exception_simple" : needsTools && policyExceptionSignal ? "policy_exception" : (
|
|
35295
|
+
// Airline prompts that require a global optimum (for example the
|
|
35296
|
+
// cheapest itinerary across several candidates) are materially harder
|
|
35297
|
+
// than applying one change to every passenger in a known reservation.
|
|
35298
|
+
// Full-session evidence supports Sonnet for the former, while upgrading
|
|
35299
|
+
// the latter merely because it says "all passengers" caused a large cost
|
|
35300
|
+
// increase without a quality gain.
|
|
35301
|
+
needsTools && agentDomain === "airline" && (globalOptimizationSignal || conditionalGlobalWorkflowSignal) ? "complex_high" : needsTools && (likelyParallelToolCalls || globalChoiceSignal || crossRecordSignal || crossReservationBatchSignal || negotiatedWorkflowSignal) ? "high" : "standard"
|
|
35302
|
+
);
|
|
35303
|
+
const needsVision = options.hasVision ?? false;
|
|
35304
|
+
const needsStructuredOutput = options.requiresStructuredOutput ?? false;
|
|
35305
|
+
const latencySensitive = /\b(?:urgent|asap|fast|quick|low latency|real[- ]time)\b|尽快|马上|快速|低延迟/i.test(
|
|
35306
|
+
scannedFullText
|
|
35307
|
+
);
|
|
35308
|
+
const highStakes = /\b(?:production|security|payment|legal|medical|financial|audit)\b|生产|安全|支付|法律|医疗|财务|审计/i.test(
|
|
35309
|
+
scannedFullText
|
|
35310
|
+
);
|
|
35311
|
+
const terminalToolSignal = normalizedToolNames.some(
|
|
35312
|
+
(name) => /^(?:terminalexec|terminalinspect|terminalsendkeys)$/.test(name)
|
|
35313
|
+
);
|
|
35314
|
+
const simpleTerminalArtifact = /\b(?:create|write|convert|generate|build|implement|run|fix|repair|debug|make)\b[\s\S]{0,120}\b(?:file|script|csv|parquet|json|txt|server|endpoint)\b/i.test(
|
|
35315
|
+
scannedPrompt
|
|
35316
|
+
);
|
|
35317
|
+
const terminalComplexRepair = terminalToolSignal && /\b(?:multiple|several)\s+(?:scripts?|files?|components?)\b|\b(?:pipeline|dependencies)\b[\s\S]{0,100}\b(?:fail|issue|fix|repair|run|execute)\b|\b(?:identify|find|fix|repair)\s+(?:and\s+)?(?:fix\s+)?all\s+(?:the\s+)?issues\b/i.test(
|
|
35318
|
+
scannedPrompt
|
|
35319
|
+
);
|
|
35320
|
+
const mentionedTerminalRuntimes = new Set(
|
|
35321
|
+
(scannedPrompt.match(/\b(?:gcc|clang|rustc|javac|go\s+build|node|python)\b/gi) ?? []).map(
|
|
35322
|
+
(name) => name.toLowerCase().replace(/\s+/g, " ")
|
|
35323
|
+
)
|
|
35324
|
+
);
|
|
35325
|
+
const terminalCrossRuntimeArtifact = terminalToolSignal && (/\bpolyglot\b/i.test(scannedPrompt) || /\b(?:both|each)\b[\s\S]{0,120}\b(?:compilers?|runtimes?|toolchains?)\b/i.test(
|
|
35326
|
+
scannedPrompt
|
|
35327
|
+
) || mentionedTerminalRuntimes.size >= 2 && /\b(?:compile|build|run|execute)\b/i.test(scannedPrompt));
|
|
35328
|
+
const terminalFrameworkToNativeArtifact = terminalToolSignal && /\b(?:pytorch|tensorflow|jax|onnx|state[_ -]?dict|checkpoint|safetensors?)\b|\.(?:pth|pt|onnx)\b/i.test(
|
|
35329
|
+
scannedPrompt
|
|
35330
|
+
) && /\b(?:pure|native|programmed|written|implemented?)\s+(?:in|using)\s+(?:c\+\+|c|rust|go)\b|\b(?:c\+\+|c|rust|go)\s+(?:program|binary|executable|cli|tool|implementation)\b/i.test(
|
|
35331
|
+
scannedPrompt
|
|
35332
|
+
) && /\b(?:inference|model|weights?|tensor|export|convert|load)\b/i.test(scannedPrompt);
|
|
35333
|
+
if (needsTools && (terminalComplexRepair || terminalCrossRuntimeArtifact || terminalFrameworkToNativeArtifact) && (agentRisk === "standard" || agentRisk === "high"))
|
|
35334
|
+
agentRisk = "complex_high";
|
|
35335
|
+
const complexTerminalOperation = /\b(?:git|ssh|nginx|https|certificate|authentication|credential|deploy|production|encrypt|gpg|shred|securely delete|decommission|benchmark|evaluate|embedding|chess|image|search the web|schema|statistical|statistics|aggregate|join|multiple inputs?)\b/i.test(
|
|
35336
|
+
scannedPrompt
|
|
35337
|
+
);
|
|
35338
|
+
const terminalCredentialSignal = /\b(?:ssh|nginx|certificate|authentication|credentials?|passwords?|api keys?|deploy|production|encrypt|gpg|shred|securely delete|decommission)\b/i.test(
|
|
35339
|
+
scannedPrompt
|
|
35340
|
+
) || /\b(?:access|auth|authentication|bearer|secret|api)\s+tokens?\b|\btokens?\s+(?:secret|credential|authentication)\b/i.test(
|
|
35341
|
+
scannedPrompt
|
|
35342
|
+
);
|
|
35343
|
+
const terminalSafetySensitive = terminalToolSignal && (highStakes || terminalCredentialSignal);
|
|
35344
|
+
const implicitTerminalCode = needsTools && terminalToolSignal && agentRisk === "standard" && !highStakes && !complexTerminalOperation && numberedSteps < 3 && prompt.length <= 1e3 && simpleTerminalArtifact;
|
|
35345
|
+
const language = /[\u3400-\u9fff]/.test(scannedFullText) ? "zh" : "other";
|
|
35346
|
+
const multipleChoiceSignals = (scannedPrompt.match(/(?:^|\n)\s*[A-D][.)]\s+/gim) ?? []).length;
|
|
35347
|
+
const numericSignals = (scannedPrompt.match(/-?\d+(?:[.,]\d+)?/g) ?? []).length;
|
|
35348
|
+
const compactMathProblem = !hasCode && prompt.length < 2500 && numericSignals >= 2 && (/[+×÷=%$€£¥]|\b(?:total|each|per|times|half|twice|percent|how many|how much|calculate)\b/i.test(
|
|
35349
|
+
scannedPrompt
|
|
35350
|
+
) || /[??]\s*$/.test(scannedPrompt.trim()) || numericSignals >= 3);
|
|
35351
|
+
let taskType = "chat";
|
|
35352
|
+
if (needsVision) taskType = "vision";
|
|
35353
|
+
else if (estimatedInputTokens > 8e4) taskType = "long_context";
|
|
35354
|
+
else if (needsTools && (hasCode || implicitTerminalCode)) taskType = "code_agent";
|
|
35355
|
+
else if (needsTools && likelyParallelToolCalls && !complexMultiToolPlan)
|
|
35356
|
+
taskType = "tool_agent_parallel";
|
|
35357
|
+
else if (needsTools) taskType = "tool_agent";
|
|
35358
|
+
else if (multipleChoiceSignals >= 3) taskType = "reasoning_mcq";
|
|
35359
|
+
else if (compactMathProblem) taskType = "reasoning_math";
|
|
35360
|
+
else if (/\b(?:bug|debug|error|failure|failing|regression|crash|修复|报错|错误|调试)\b/i.test(text))
|
|
35361
|
+
taskType = "debug";
|
|
35362
|
+
else if (hasCode || /\b(?:refactor|implement|patch|edit|rewrite|重构|实现|修改)\b/i.test(text))
|
|
35363
|
+
taskType = "code_edit";
|
|
35364
|
+
else if (needsStructuredOutput || /\b(?:extract|json|schema|csv|字段|提取)\b/i.test(text))
|
|
35365
|
+
taskType = "extraction";
|
|
35366
|
+
else if (/\b(?:prove|derive|theorem|formal|mathematical|reasoning|证明|推导|定理|数学)\b/i.test(text))
|
|
35367
|
+
taskType = "reasoning";
|
|
35368
|
+
return {
|
|
35369
|
+
taskType,
|
|
35370
|
+
estimatedInputTokens,
|
|
35371
|
+
hasCode,
|
|
35372
|
+
needsTools,
|
|
35373
|
+
toolsAvailable,
|
|
35374
|
+
needsVision,
|
|
35375
|
+
needsStructuredOutput,
|
|
35376
|
+
latencySensitive,
|
|
35377
|
+
highStakes,
|
|
35378
|
+
language,
|
|
35379
|
+
likelyParallelToolCalls,
|
|
35380
|
+
complexMultiToolPlan,
|
|
35381
|
+
agentDomain,
|
|
35382
|
+
deepWebResearch,
|
|
35383
|
+
agentRisk,
|
|
35384
|
+
terminalToolSignal,
|
|
35385
|
+
terminalSafetySensitive,
|
|
35386
|
+
implicitTerminalCode
|
|
35387
|
+
};
|
|
35388
|
+
}
|
|
35389
|
+
function affinity(modelId, task, language = "other", agentDomain = "other", deepWebResearch = false, agentRisk = "standard", terminalToolSignal = false, terminalSafetySensitive = false) {
|
|
35390
|
+
const id2 = modelId.toLowerCase();
|
|
35391
|
+
const modelName = id2.slice(id2.indexOf("/") + 1);
|
|
35392
|
+
const match = (values, score) => values.some((value) => modelName === value) ? score : 0;
|
|
35393
|
+
const base3 = 0.68;
|
|
35394
|
+
switch (task) {
|
|
35395
|
+
case "code_agent":
|
|
35396
|
+
if (terminalToolSignal && agentRisk === "complex_high") {
|
|
35397
|
+
return Math.max(
|
|
35398
|
+
base3,
|
|
35399
|
+
match(["claude-sonnet-5"], 1),
|
|
35400
|
+
match(["gpt-5.3-codex"], 0.87),
|
|
35401
|
+
match(["gpt-5-mini"], 0.78),
|
|
35402
|
+
match(["gemini-3.5-flash"], 0.76)
|
|
35403
|
+
);
|
|
35404
|
+
}
|
|
35405
|
+
return Math.max(
|
|
35406
|
+
base3,
|
|
35407
|
+
match(["gpt-5.3-codex"], 1),
|
|
35408
|
+
match(["claude-sonnet-5"], 0.98),
|
|
35409
|
+
match(["gpt-5-mini"], 0.96),
|
|
35410
|
+
match(["gemini-3.5-flash"], 0.92),
|
|
35411
|
+
match(["kimi-k3"], 0.9),
|
|
35412
|
+
match(["deepseek-v4-pro", "glm-5.2"], 0.88)
|
|
35413
|
+
);
|
|
35414
|
+
case "tool_agent":
|
|
35415
|
+
if (terminalToolSignal && agentRisk === "complex_high") {
|
|
35416
|
+
return Math.max(
|
|
35417
|
+
base3,
|
|
35418
|
+
match(["claude-sonnet-5"], 1),
|
|
35419
|
+
match(["gpt-5.3-codex"], 0.87),
|
|
35420
|
+
match(["gpt-5-mini"], 0.78),
|
|
35421
|
+
match(["gemini-3.5-flash"], 0.76)
|
|
35422
|
+
);
|
|
35423
|
+
}
|
|
35424
|
+
if (terminalToolSignal && !terminalSafetySensitive) {
|
|
35425
|
+
return Math.max(
|
|
35426
|
+
base3,
|
|
35427
|
+
match(["gpt-5-mini"], 1),
|
|
35428
|
+
match(["gpt-5.3-codex"], 0.98),
|
|
35429
|
+
match(["claude-sonnet-5"], 0.9),
|
|
35430
|
+
match(["gemini-3.5-flash"], 0.89)
|
|
35431
|
+
);
|
|
35432
|
+
}
|
|
35433
|
+
if (terminalToolSignal && terminalSafetySensitive) {
|
|
35434
|
+
return Math.max(
|
|
35435
|
+
base3,
|
|
35436
|
+
match(["claude-sonnet-5"], 1),
|
|
35437
|
+
match(["claude-opus-4.8"], 0.9),
|
|
35438
|
+
match(["gpt-5.3-codex"], 0.84)
|
|
35439
|
+
);
|
|
35440
|
+
}
|
|
35441
|
+
if (agentDomain === "web_research") {
|
|
35442
|
+
return deepWebResearch ? Math.max(
|
|
35443
|
+
base3,
|
|
35444
|
+
match(["claude-sonnet-5"], 1),
|
|
35445
|
+
match(["gpt-5-mini"], 0.88),
|
|
35446
|
+
match(["gemini-3.5-flash"], 0.84),
|
|
35447
|
+
match(["claude-opus-5"], 0.8),
|
|
35448
|
+
match(["claude-opus-4.8"], 0.78)
|
|
35449
|
+
) : Math.max(
|
|
35450
|
+
base3,
|
|
35451
|
+
match(["claude-sonnet-5"], 1),
|
|
35452
|
+
match(["gpt-5-mini"], 0.88),
|
|
35453
|
+
match(["gemini-3.5-flash"], 0.86),
|
|
35454
|
+
match(["claude-opus-5"], 0.84),
|
|
35455
|
+
match(["claude-opus-4.8"], 0.82)
|
|
35456
|
+
);
|
|
35457
|
+
}
|
|
35458
|
+
if (agentDomain === "retail") {
|
|
35459
|
+
if (agentRisk === "standard") {
|
|
35460
|
+
return Math.max(
|
|
35461
|
+
base3,
|
|
35462
|
+
match(["gpt-5-mini"], 1),
|
|
35463
|
+
match(["claude-sonnet-5"], 0.88),
|
|
35464
|
+
match(["gemini-3.5-flash"], 0.82),
|
|
35465
|
+
match(["gpt-5.3-codex"], 0.81),
|
|
35466
|
+
match(["kimi-k3"], 0.78),
|
|
35467
|
+
match(["deepseek-v4-pro"], 0.76)
|
|
35468
|
+
);
|
|
35469
|
+
}
|
|
35470
|
+
if (agentRisk === "policy_exception") {
|
|
35471
|
+
return Math.max(
|
|
35472
|
+
base3,
|
|
35473
|
+
match(["gpt-4.1"], 1),
|
|
35474
|
+
match(["claude-sonnet-5"], 0.9),
|
|
35475
|
+
match(["deepseek-v4-pro"], 0.82),
|
|
35476
|
+
match(["gpt-5-mini"], 0.8),
|
|
35477
|
+
match(["gpt-4o-mini"], 0.76)
|
|
35478
|
+
);
|
|
35479
|
+
}
|
|
35480
|
+
if (agentRisk === "policy_exception_simple") {
|
|
35481
|
+
return Math.max(
|
|
35482
|
+
base3,
|
|
35483
|
+
match(["gpt-5-mini"], 1),
|
|
35484
|
+
match(["gpt-4.1"], 0.86),
|
|
35485
|
+
match(["deepseek-v4-pro"], 0.82),
|
|
35486
|
+
match(["gpt-4o-mini"], 0.8)
|
|
35487
|
+
);
|
|
35488
|
+
}
|
|
35489
|
+
return Math.max(
|
|
35490
|
+
base3,
|
|
35491
|
+
match(["deepseek-v4-pro"], 1),
|
|
35492
|
+
match(["claude-sonnet-5"], 0.88),
|
|
35493
|
+
match(["gemini-3.5-flash"], 0.82),
|
|
35494
|
+
match(["gpt-5.3-codex"], 0.81),
|
|
35495
|
+
match(["kimi-k3"], 0.78),
|
|
35496
|
+
match(["gpt-5-mini"], 0.76)
|
|
35497
|
+
);
|
|
35498
|
+
}
|
|
35499
|
+
if (agentDomain === "airline") {
|
|
35500
|
+
if (agentRisk === "complex_high") {
|
|
35501
|
+
return Math.max(
|
|
35502
|
+
base3,
|
|
35503
|
+
match(["claude-sonnet-5"], 1),
|
|
35504
|
+
match(["gpt-5-mini"], 0.78),
|
|
35505
|
+
match(["gemini-3.5-flash"], 0.76),
|
|
35506
|
+
match(["deepseek-v4-pro"], 0.74)
|
|
35507
|
+
);
|
|
35508
|
+
}
|
|
35509
|
+
return Math.max(
|
|
35510
|
+
base3,
|
|
35511
|
+
match(["gpt-5-mini"], 1),
|
|
35512
|
+
match(["claude-sonnet-5"], 0.9),
|
|
35513
|
+
match(["gemini-3.5-flash"], 0.8),
|
|
35514
|
+
match(["deepseek-v4-pro"], 0.76)
|
|
35515
|
+
);
|
|
35516
|
+
}
|
|
35517
|
+
return Math.max(
|
|
35518
|
+
base3,
|
|
35519
|
+
match(["claude-sonnet-5"], 1),
|
|
35520
|
+
match(["gemini-3.5-flash"], 0.88),
|
|
35521
|
+
match(["gpt-5.3-codex"], 0.87),
|
|
35522
|
+
match(["gpt-5-mini"], 0.84),
|
|
35523
|
+
match(["kimi-k3"], 0.85),
|
|
35524
|
+
match(["deepseek-v4-pro"], 0.82)
|
|
35525
|
+
);
|
|
35526
|
+
case "tool_agent_parallel":
|
|
35527
|
+
if (terminalToolSignal) {
|
|
35528
|
+
return terminalSafetySensitive ? Math.max(
|
|
35529
|
+
base3,
|
|
35530
|
+
match(["claude-sonnet-5"], 1),
|
|
35531
|
+
match(["claude-opus-4.8"], 0.9),
|
|
35532
|
+
match(["gpt-5.3-codex"], 0.86)
|
|
35533
|
+
) : Math.max(
|
|
35534
|
+
base3,
|
|
35535
|
+
match(["gpt-5-mini"], 1),
|
|
35536
|
+
match(["gpt-5.3-codex"], 0.98),
|
|
35537
|
+
match(["claude-sonnet-5"], 0.92),
|
|
35538
|
+
match(["gemini-3.5-flash"], 0.88)
|
|
35539
|
+
);
|
|
35540
|
+
}
|
|
35541
|
+
if (agentDomain === "web_research") {
|
|
35542
|
+
return deepWebResearch ? Math.max(
|
|
35543
|
+
base3,
|
|
35544
|
+
match(["claude-sonnet-5"], 1),
|
|
35545
|
+
match(["gpt-5-mini"], 0.88),
|
|
35546
|
+
match(["gemini-3.5-flash"], 0.84),
|
|
35547
|
+
match(["claude-opus-5"], 0.8),
|
|
35548
|
+
match(["claude-opus-4.8"], 0.78)
|
|
35549
|
+
) : Math.max(
|
|
35550
|
+
base3,
|
|
35551
|
+
match(["claude-sonnet-5"], 1),
|
|
35552
|
+
match(["gpt-5-mini"], 0.88),
|
|
35553
|
+
match(["gemini-3.5-flash"], 0.86),
|
|
35554
|
+
match(["claude-opus-5"], 0.84),
|
|
35555
|
+
match(["claude-opus-4.8"], 0.82)
|
|
35556
|
+
);
|
|
35557
|
+
}
|
|
35558
|
+
if (agentDomain === "retail") {
|
|
35559
|
+
if (agentRisk === "policy_exception") {
|
|
35560
|
+
return Math.max(
|
|
35561
|
+
base3,
|
|
35562
|
+
match(["gpt-4.1"], 1),
|
|
35563
|
+
match(["claude-sonnet-5"], 0.9),
|
|
35564
|
+
match(["deepseek-v4-pro"], 0.82),
|
|
35565
|
+
match(["gpt-5-mini"], 0.8),
|
|
35566
|
+
match(["gpt-4o-mini"], 0.76)
|
|
35567
|
+
);
|
|
35568
|
+
}
|
|
35569
|
+
if (agentRisk === "policy_exception_simple") {
|
|
35570
|
+
return Math.max(
|
|
35571
|
+
base3,
|
|
35572
|
+
match(["gpt-5-mini"], 1),
|
|
35573
|
+
match(["gpt-4.1"], 0.86),
|
|
35574
|
+
match(["deepseek-v4-pro"], 0.82),
|
|
35575
|
+
match(["gpt-4o-mini"], 0.8)
|
|
35576
|
+
);
|
|
35577
|
+
}
|
|
35578
|
+
return Math.max(
|
|
35579
|
+
base3,
|
|
35580
|
+
match(["deepseek-v4-pro"], 1),
|
|
35581
|
+
match(["claude-sonnet-5"], 0.88),
|
|
35582
|
+
match(["claude-opus-4.8"], 0.84),
|
|
35583
|
+
match(["gpt-5-mini"], 0.78),
|
|
35584
|
+
match(["gemini-3.5-flash"], 0.76)
|
|
35585
|
+
);
|
|
35586
|
+
}
|
|
35587
|
+
if (agentDomain === "airline") {
|
|
35588
|
+
return agentRisk === "complex_high" ? Math.max(
|
|
35589
|
+
base3,
|
|
35590
|
+
match(["claude-sonnet-5"], 1),
|
|
35591
|
+
match(["gpt-5-mini"], 0.78),
|
|
35592
|
+
match(["claude-opus-4.8"], 0.76),
|
|
35593
|
+
match(["gemini-3.5-flash"], 0.74)
|
|
35594
|
+
) : Math.max(
|
|
35595
|
+
base3,
|
|
35596
|
+
match(["gpt-5-mini"], 1),
|
|
35597
|
+
match(["claude-sonnet-5"], 0.9),
|
|
35598
|
+
match(["gemini-3.5-flash"], 0.8)
|
|
35599
|
+
);
|
|
35600
|
+
}
|
|
35601
|
+
return Math.max(
|
|
35602
|
+
base3,
|
|
35603
|
+
match(["claude-opus-4.8"], 1),
|
|
35604
|
+
match(["claude-sonnet-5"], 0.84),
|
|
35605
|
+
match(["grok-4.5"], 0.82),
|
|
35606
|
+
match(["gemini-3.5-flash"], 0.8),
|
|
35607
|
+
match(["deepseek-v4-pro"], 0.78)
|
|
35608
|
+
);
|
|
35609
|
+
case "code_edit":
|
|
35610
|
+
case "debug":
|
|
35611
|
+
return Math.max(
|
|
35612
|
+
base3,
|
|
35613
|
+
match(["gpt-5.3-codex"], 1),
|
|
35614
|
+
match(["claude-sonnet-4.6"], 0.94),
|
|
35615
|
+
match(["glm-5.2"], 0.9),
|
|
35616
|
+
match(["kimi-k2.7", "deepseek-v4-pro"], 0.86)
|
|
35617
|
+
);
|
|
35618
|
+
case "reasoning":
|
|
35619
|
+
return Math.max(
|
|
35620
|
+
base3,
|
|
35621
|
+
match(["claude-sonnet-5", "claude-sonnet-4.6"], 0.98),
|
|
35622
|
+
match(["deepseek-v4-pro"], 0.95),
|
|
35623
|
+
match(["grok-4.5"], 0.94),
|
|
35624
|
+
match(["gemini-3.1-pro", "gemini-3.5-flash"], 0.92)
|
|
35625
|
+
);
|
|
35626
|
+
case "reasoning_mcq":
|
|
35627
|
+
return Math.max(
|
|
35628
|
+
base3,
|
|
35629
|
+
match(["gemini-3-flash-preview"], 1),
|
|
35630
|
+
match(["gemini-3.5-flash"], 0.91),
|
|
35631
|
+
match(["grok-4.5"], 0.9),
|
|
35632
|
+
match(["claude-sonnet-5"], 0.88),
|
|
35633
|
+
match(["deepseek-v4-pro"], 0.84)
|
|
35634
|
+
);
|
|
35635
|
+
case "reasoning_math":
|
|
35636
|
+
return Math.max(
|
|
35637
|
+
base3,
|
|
35638
|
+
match(["gemini-3.5-flash"], 1),
|
|
35639
|
+
match(["grok-4.5"], 0.93),
|
|
35640
|
+
match(["claude-sonnet-5", "deepseek-v4-pro", "kimi-k3"], 0.9),
|
|
35641
|
+
match(["kimi-k2.7"], 0.84)
|
|
35642
|
+
);
|
|
35643
|
+
case "vision":
|
|
35644
|
+
return Math.max(
|
|
35645
|
+
base3,
|
|
35646
|
+
match(["gemini-3.1-pro"], 0.96),
|
|
35647
|
+
match(["qwen3.7-max", "claude-sonnet-4.6", "kimi-k2.7", "grok-4.3"], 0.9)
|
|
35648
|
+
);
|
|
35649
|
+
case "long_context":
|
|
35650
|
+
return Math.max(
|
|
35651
|
+
base3,
|
|
35652
|
+
match(["gemini-3.1-pro"], 1),
|
|
35653
|
+
match(["qwen3.7-max", "glm-5.2"], 0.89),
|
|
35654
|
+
match(["gemini-3.5-flash"], 0.88),
|
|
35655
|
+
match(["deepseek-v4-pro"], 0.85)
|
|
35656
|
+
);
|
|
35657
|
+
case "extraction": {
|
|
35658
|
+
const kimiExtractionAffinity = language === "zh" ? 1 : 0.9;
|
|
35659
|
+
return Math.max(
|
|
35660
|
+
base3,
|
|
35661
|
+
match(["gemini-3.5-flash", "gemini-2.5-flash", "gpt-4o-mini"], 0.9),
|
|
35662
|
+
match(["claude-sonnet-5", "claude-sonnet-4.6"], 0.9),
|
|
35663
|
+
match(["kimi-k3", "kimi-k2.7"], kimiExtractionAffinity)
|
|
35664
|
+
);
|
|
35665
|
+
}
|
|
35666
|
+
default:
|
|
35667
|
+
return Math.max(
|
|
35668
|
+
base3,
|
|
35669
|
+
match(["gemini-3.5-flash", "gemini-2.5-flash", "kimi-k3", "kimi-k2.7"], 0.86)
|
|
35670
|
+
);
|
|
35671
|
+
}
|
|
35672
|
+
}
|
|
35673
|
+
function evidenceCandidates(task) {
|
|
35674
|
+
if (task === "code_agent") {
|
|
35675
|
+
return [
|
|
35676
|
+
"openai/gpt-5.3-codex",
|
|
35677
|
+
"anthropic/claude-sonnet-5",
|
|
35678
|
+
"openai/gpt-5-mini",
|
|
35679
|
+
"google/gemini-3.5-flash",
|
|
35680
|
+
"moonshot/kimi-k3",
|
|
35681
|
+
"deepseek/deepseek-v4-pro"
|
|
35682
|
+
];
|
|
35683
|
+
}
|
|
35684
|
+
if (task === "tool_agent") {
|
|
35685
|
+
return [
|
|
35686
|
+
"anthropic/claude-sonnet-5",
|
|
35687
|
+
"anthropic/claude-opus-5",
|
|
35688
|
+
"openai/gpt-5-mini",
|
|
35689
|
+
"openai/gpt-4.1",
|
|
35690
|
+
"openai/gpt-4o-mini",
|
|
35691
|
+
"google/gemini-3.5-flash",
|
|
35692
|
+
"openai/gpt-5.3-codex",
|
|
35693
|
+
"moonshot/kimi-k3",
|
|
35694
|
+
"deepseek/deepseek-v4-pro"
|
|
35695
|
+
];
|
|
35696
|
+
}
|
|
35697
|
+
if (task === "tool_agent_parallel") {
|
|
35698
|
+
return [
|
|
35699
|
+
"anthropic/claude-opus-5",
|
|
35700
|
+
"anthropic/claude-opus-4.8",
|
|
35701
|
+
"anthropic/claude-sonnet-5",
|
|
35702
|
+
"openai/gpt-5-mini",
|
|
35703
|
+
"openai/gpt-4.1",
|
|
35704
|
+
"openai/gpt-4o-mini",
|
|
35705
|
+
"xai/grok-4.5",
|
|
35706
|
+
"google/gemini-3.5-flash",
|
|
35707
|
+
"deepseek/deepseek-v4-pro"
|
|
35708
|
+
];
|
|
35709
|
+
}
|
|
35710
|
+
if (task === "long_context") {
|
|
35711
|
+
return [
|
|
35712
|
+
"google/gemini-3.1-pro",
|
|
35713
|
+
"deepseek/deepseek-v4-pro",
|
|
35714
|
+
"qwen/qwen3.7-max",
|
|
35715
|
+
"zai/glm-5.2",
|
|
35716
|
+
"google/gemini-3.5-flash"
|
|
35717
|
+
];
|
|
35718
|
+
}
|
|
35719
|
+
if (task === "reasoning_mcq") {
|
|
35720
|
+
return [
|
|
35721
|
+
"google/gemini-3-flash-preview",
|
|
35722
|
+
"google/gemini-3.5-flash",
|
|
35723
|
+
"xai/grok-4.5",
|
|
35724
|
+
"anthropic/claude-sonnet-5",
|
|
35725
|
+
"deepseek/deepseek-v4-pro"
|
|
35726
|
+
];
|
|
35727
|
+
}
|
|
35728
|
+
if (task === "reasoning_math") {
|
|
35729
|
+
return [
|
|
35730
|
+
"google/gemini-3.5-flash",
|
|
35731
|
+
"xai/grok-4.5",
|
|
35732
|
+
"anthropic/claude-sonnet-5",
|
|
35733
|
+
"deepseek/deepseek-v4-pro",
|
|
35734
|
+
"moonshot/kimi-k3"
|
|
35735
|
+
];
|
|
35736
|
+
}
|
|
35737
|
+
return [];
|
|
35738
|
+
}
|
|
35739
|
+
function isEligible(modelId, features, maxOutputTokens, options) {
|
|
35740
|
+
const model = options.modelCapabilities?.[modelId] ?? DEFAULT_MODEL_CAPABILITIES[modelId];
|
|
35741
|
+
if (!model) return true;
|
|
35742
|
+
if (features.needsTools && !model.supportsTools) return false;
|
|
35743
|
+
if (features.needsVision && !model.supportsVision) return false;
|
|
35744
|
+
if (features.needsStructuredOutput && !model.supportsTools) return false;
|
|
35745
|
+
if (model.maxOutputTokens < maxOutputTokens) return false;
|
|
35746
|
+
return model.contextWindow >= (features.estimatedInputTokens + maxOutputTokens) * 1.1;
|
|
35747
|
+
}
|
|
35748
|
+
function estimatedCost(modelId, options, inputTokens, outputTokens) {
|
|
35749
|
+
const price = options.modelPricing.get(modelId);
|
|
35750
|
+
if (!price) return Number.POSITIVE_INFINITY;
|
|
35751
|
+
if (price.flatPrice !== void 0) return price.flatPrice;
|
|
35752
|
+
return (inputTokens * price.inputPrice + outputTokens * price.outputPrice) / 1e6;
|
|
35753
|
+
}
|
|
35754
|
+
function profileScore(modelId, options, now2) {
|
|
35755
|
+
const profile = options.modelPerformance?.[modelId] ?? LIVE_MODEL_PROFILES[modelId] ?? HISTORICAL_MODEL_PROFILES[modelId];
|
|
35756
|
+
if (!profile) return void 0;
|
|
35757
|
+
const measuredAt = Date.parse(profile.measuredAt);
|
|
35758
|
+
if (!Number.isFinite(measuredAt)) return void 0;
|
|
35759
|
+
const ageDays = Math.max(0, (now2.getTime() - measuredAt) / 864e5);
|
|
35760
|
+
const sampleConfidence = profile.samples === void 0 ? 1 : Math.min(1, Math.max(0, profile.samples) / 10);
|
|
35761
|
+
const freshness = Math.pow(0.5, ageDays / 30) * sampleConfidence;
|
|
35762
|
+
const quality = profile.intelligenceIndex === void 0 ? void 0 : Math.min(1, profile.intelligenceIndex / 50);
|
|
35763
|
+
const speed = Math.min(
|
|
35764
|
+
1,
|
|
35765
|
+
(2e3 / Math.max(500, profile.latencyMs) + profile.outputTokensPerSecond / 250) / 2
|
|
35766
|
+
);
|
|
35767
|
+
const tailSpeed = Math.min(1, 3e3 / Math.max(750, profile.p95LatencyMs ?? profile.latencyMs));
|
|
35768
|
+
const reliability = Math.max(0, 1 - (profile.errorRate ?? 0));
|
|
35769
|
+
return { quality, speed, tailSpeed, reliability, freshness };
|
|
35770
|
+
}
|
|
35771
|
+
function route(prompt, systemPrompt, maxOutputTokens, options) {
|
|
35772
|
+
const strategy = getStrategy(options.config.strategy ?? "portfolio");
|
|
35773
|
+
return strategy.route(prompt, systemPrompt, maxOutputTokens, options);
|
|
35774
|
+
}
|
|
35775
|
+
var BASELINE_MODEL_ID, BASELINE_INPUT_PRICE, BASELINE_OUTPUT_PRICE, SERVER_MARGIN_PERCENT, MIN_PAYMENT_USD, RulesStrategy, registry, DEFAULT_MODEL_CAPABILITIES, model_profiles_generated_default, LIVE_MODEL_PROFILES, HISTORICAL_MODEL_PROFILES, DEFAULT_PORTFOLIO_WEIGHTS, PortfolioStrategy, DEFAULT_ROUTING_CONFIG;
|
|
35776
|
+
var init_dist = __esm({
|
|
35777
|
+
"node_modules/@blockrun/router-core/dist/index.js"() {
|
|
35151
35778
|
"use strict";
|
|
35152
|
-
|
|
35153
|
-
|
|
35779
|
+
BASELINE_MODEL_ID = "anthropic/claude-opus-4.7";
|
|
35780
|
+
BASELINE_INPUT_PRICE = 5;
|
|
35781
|
+
BASELINE_OUTPUT_PRICE = 25;
|
|
35782
|
+
SERVER_MARGIN_PERCENT = 5;
|
|
35783
|
+
MIN_PAYMENT_USD = 1e-3;
|
|
35154
35784
|
RulesStrategy = class {
|
|
35155
35785
|
name = "rules";
|
|
35156
35786
|
route(prompt, systemPrompt, maxOutputTokens, options) {
|
|
35157
35787
|
const { config, modelPricing } = options;
|
|
35158
35788
|
const fullText = `${systemPrompt ?? ""} ${prompt}`;
|
|
35159
35789
|
const estimatedTokens = Math.ceil(fullText.length / 4);
|
|
35160
|
-
const
|
|
35790
|
+
const scanLimit = Math.max(1, Math.min(8e3, config.classifier.promptTruncationChars));
|
|
35791
|
+
const sample = (value) => {
|
|
35792
|
+
if (value.length <= scanLimit) return value;
|
|
35793
|
+
const prefixLength = Math.ceil(scanLimit / 2);
|
|
35794
|
+
return `${value.slice(0, prefixLength)}
|
|
35795
|
+
${value.slice(-(scanLimit - prefixLength))}`;
|
|
35796
|
+
};
|
|
35797
|
+
const scannedPrompt = sample(prompt);
|
|
35798
|
+
const scannedSystemPrompt = systemPrompt ? sample(systemPrompt) : void 0;
|
|
35799
|
+
const ruleResult = classifyByRules(
|
|
35800
|
+
scannedPrompt,
|
|
35801
|
+
scannedSystemPrompt,
|
|
35802
|
+
estimatedTokens,
|
|
35803
|
+
config.scoring
|
|
35804
|
+
);
|
|
35161
35805
|
const { routingProfile } = options;
|
|
35162
35806
|
let tierConfigs;
|
|
35163
35807
|
let profileSuffix;
|
|
@@ -35174,7 +35818,7 @@ var init_strategy = __esm({
|
|
|
35174
35818
|
const agenticScore = ruleResult.agenticScore ?? 0;
|
|
35175
35819
|
const isAutoAgentic = agenticScore >= 0.5;
|
|
35176
35820
|
const agenticModeSetting = config.overrides.agenticMode;
|
|
35177
|
-
const hasToolsInRequest = options.hasTools ?? false;
|
|
35821
|
+
const hasToolsInRequest = options.requiresTools ?? options.hasTools ?? false;
|
|
35178
35822
|
let useAgenticTiers;
|
|
35179
35823
|
if (agenticModeSetting === false) {
|
|
35180
35824
|
useAgenticTiers = false;
|
|
@@ -35204,7 +35848,7 @@ var init_strategy = __esm({
|
|
|
35204
35848
|
);
|
|
35205
35849
|
return { ...decision2, tierConfigs, profile };
|
|
35206
35850
|
}
|
|
35207
|
-
const hasStructuredOutput =
|
|
35851
|
+
const hasStructuredOutput = options.requiresStructuredOutput === true || (scannedSystemPrompt ? /json|structured|schema/i.test(scannedSystemPrompt) : false);
|
|
35208
35852
|
let tier;
|
|
35209
35853
|
let confidence;
|
|
35210
35854
|
const method = "rules";
|
|
@@ -35243,16 +35887,789 @@ var init_strategy = __esm({
|
|
|
35243
35887
|
};
|
|
35244
35888
|
registry = /* @__PURE__ */ new Map();
|
|
35245
35889
|
registry.set("rules", new RulesStrategy());
|
|
35246
|
-
|
|
35247
|
-
|
|
35248
|
-
|
|
35249
|
-
|
|
35250
|
-
|
|
35251
|
-
|
|
35252
|
-
|
|
35253
|
-
|
|
35890
|
+
DEFAULT_MODEL_CAPABILITIES = Object.freeze({
|
|
35891
|
+
"anthropic/claude-fable-5": {
|
|
35892
|
+
contextWindow: 1e6,
|
|
35893
|
+
maxOutputTokens: 128e3,
|
|
35894
|
+
supportsTools: true,
|
|
35895
|
+
supportsVision: true
|
|
35896
|
+
},
|
|
35897
|
+
"anthropic/claude-haiku-4.5": {
|
|
35898
|
+
contextWindow: 2e5,
|
|
35899
|
+
maxOutputTokens: 8192,
|
|
35900
|
+
supportsTools: true,
|
|
35901
|
+
supportsVision: true
|
|
35902
|
+
},
|
|
35903
|
+
"anthropic/claude-opus-4.6": {
|
|
35904
|
+
contextWindow: 1e6,
|
|
35905
|
+
maxOutputTokens: 128e3,
|
|
35906
|
+
supportsTools: true,
|
|
35907
|
+
supportsVision: true
|
|
35908
|
+
},
|
|
35909
|
+
"anthropic/claude-opus-4.7": {
|
|
35910
|
+
contextWindow: 1e6,
|
|
35911
|
+
maxOutputTokens: 128e3,
|
|
35912
|
+
supportsTools: true,
|
|
35913
|
+
supportsVision: true
|
|
35914
|
+
},
|
|
35915
|
+
"anthropic/claude-opus-4.8": {
|
|
35916
|
+
contextWindow: 1e6,
|
|
35917
|
+
maxOutputTokens: 128e3,
|
|
35918
|
+
supportsTools: true,
|
|
35919
|
+
supportsVision: true
|
|
35920
|
+
},
|
|
35921
|
+
"anthropic/claude-opus-5": {
|
|
35922
|
+
contextWindow: 1e6,
|
|
35923
|
+
maxOutputTokens: 128e3,
|
|
35924
|
+
supportsTools: true,
|
|
35925
|
+
supportsVision: true
|
|
35926
|
+
},
|
|
35927
|
+
"anthropic/claude-sonnet-4.6": {
|
|
35928
|
+
contextWindow: 2e5,
|
|
35929
|
+
maxOutputTokens: 64e3,
|
|
35930
|
+
supportsTools: true,
|
|
35931
|
+
supportsVision: true
|
|
35932
|
+
},
|
|
35933
|
+
"anthropic/claude-sonnet-5": {
|
|
35934
|
+
contextWindow: 1e6,
|
|
35935
|
+
maxOutputTokens: 128e3,
|
|
35936
|
+
supportsTools: true,
|
|
35937
|
+
supportsVision: true
|
|
35938
|
+
},
|
|
35939
|
+
"deepseek/deepseek-chat": {
|
|
35940
|
+
contextWindow: 1e6,
|
|
35941
|
+
maxOutputTokens: 8192,
|
|
35942
|
+
supportsTools: true,
|
|
35943
|
+
supportsVision: false
|
|
35944
|
+
},
|
|
35945
|
+
"deepseek/deepseek-reasoner": {
|
|
35946
|
+
contextWindow: 1e6,
|
|
35947
|
+
maxOutputTokens: 8192,
|
|
35948
|
+
supportsTools: true,
|
|
35949
|
+
supportsVision: false
|
|
35950
|
+
},
|
|
35951
|
+
"deepseek/deepseek-v4-pro": {
|
|
35952
|
+
contextWindow: 1048576,
|
|
35953
|
+
maxOutputTokens: 65536,
|
|
35954
|
+
supportsTools: true,
|
|
35955
|
+
supportsVision: false
|
|
35956
|
+
},
|
|
35957
|
+
"free/deepseek-v4-flash": {
|
|
35958
|
+
contextWindow: 1e6,
|
|
35959
|
+
maxOutputTokens: 16384,
|
|
35960
|
+
supportsTools: false,
|
|
35961
|
+
supportsVision: false
|
|
35962
|
+
},
|
|
35963
|
+
"free/gpt-oss-120b": {
|
|
35964
|
+
contextWindow: 128e3,
|
|
35965
|
+
maxOutputTokens: 16384,
|
|
35966
|
+
supportsTools: false,
|
|
35967
|
+
supportsVision: false
|
|
35968
|
+
},
|
|
35969
|
+
"free/gpt-oss-20b": {
|
|
35970
|
+
contextWindow: 128e3,
|
|
35971
|
+
maxOutputTokens: 16384,
|
|
35972
|
+
supportsTools: false,
|
|
35973
|
+
supportsVision: false
|
|
35974
|
+
},
|
|
35975
|
+
"free/seed-oss-36b": {
|
|
35976
|
+
contextWindow: 131072,
|
|
35977
|
+
maxOutputTokens: 16384,
|
|
35978
|
+
supportsTools: false,
|
|
35979
|
+
supportsVision: false
|
|
35980
|
+
},
|
|
35981
|
+
"google/gemini-2.5-flash": {
|
|
35982
|
+
contextWindow: 1e6,
|
|
35983
|
+
maxOutputTokens: 65536,
|
|
35984
|
+
supportsTools: true,
|
|
35985
|
+
supportsVision: true
|
|
35986
|
+
},
|
|
35987
|
+
"google/gemini-2.5-flash-lite": {
|
|
35988
|
+
contextWindow: 1e6,
|
|
35989
|
+
maxOutputTokens: 65536,
|
|
35990
|
+
supportsTools: true,
|
|
35991
|
+
supportsVision: false
|
|
35992
|
+
},
|
|
35993
|
+
"google/gemini-2.5-pro": {
|
|
35994
|
+
contextWindow: 105e4,
|
|
35995
|
+
maxOutputTokens: 65536,
|
|
35996
|
+
supportsTools: true,
|
|
35997
|
+
supportsVision: true
|
|
35998
|
+
},
|
|
35999
|
+
"google/gemini-3-flash-preview": {
|
|
36000
|
+
contextWindow: 1e6,
|
|
36001
|
+
maxOutputTokens: 65536,
|
|
36002
|
+
supportsTools: false,
|
|
36003
|
+
supportsVision: true
|
|
36004
|
+
},
|
|
36005
|
+
"google/gemini-3.1-flash-lite": {
|
|
36006
|
+
contextWindow: 1e6,
|
|
36007
|
+
maxOutputTokens: 8192,
|
|
36008
|
+
supportsTools: true,
|
|
36009
|
+
supportsVision: false
|
|
36010
|
+
},
|
|
36011
|
+
"google/gemini-3.1-pro": {
|
|
36012
|
+
contextWindow: 105e4,
|
|
36013
|
+
maxOutputTokens: 65536,
|
|
36014
|
+
supportsTools: true,
|
|
36015
|
+
supportsVision: true
|
|
36016
|
+
},
|
|
36017
|
+
"google/gemini-3.5-flash": {
|
|
36018
|
+
contextWindow: 1048576,
|
|
36019
|
+
maxOutputTokens: 65536,
|
|
36020
|
+
supportsTools: true,
|
|
36021
|
+
supportsVision: true
|
|
36022
|
+
},
|
|
36023
|
+
"moonshot/kimi-k2.5": {
|
|
36024
|
+
contextWindow: 262144,
|
|
36025
|
+
maxOutputTokens: 16384,
|
|
36026
|
+
supportsTools: true,
|
|
36027
|
+
supportsVision: true
|
|
36028
|
+
},
|
|
36029
|
+
"moonshot/kimi-k2.6": {
|
|
36030
|
+
contextWindow: 262144,
|
|
36031
|
+
maxOutputTokens: 65536,
|
|
36032
|
+
supportsTools: true,
|
|
36033
|
+
supportsVision: true
|
|
36034
|
+
},
|
|
36035
|
+
"moonshot/kimi-k2.7": {
|
|
36036
|
+
contextWindow: 262144,
|
|
36037
|
+
maxOutputTokens: 65536,
|
|
36038
|
+
supportsTools: true,
|
|
36039
|
+
supportsVision: true
|
|
36040
|
+
},
|
|
36041
|
+
"moonshot/kimi-k3": {
|
|
36042
|
+
contextWindow: 1048576,
|
|
36043
|
+
maxOutputTokens: 65536,
|
|
36044
|
+
supportsTools: true,
|
|
36045
|
+
supportsVision: true
|
|
36046
|
+
},
|
|
36047
|
+
"openai/gpt-4.1": {
|
|
36048
|
+
contextWindow: 128e3,
|
|
36049
|
+
maxOutputTokens: 16384,
|
|
36050
|
+
supportsTools: true,
|
|
36051
|
+
supportsVision: true
|
|
36052
|
+
},
|
|
36053
|
+
"openai/gpt-4o-mini": {
|
|
36054
|
+
contextWindow: 128e3,
|
|
36055
|
+
maxOutputTokens: 16384,
|
|
36056
|
+
supportsTools: true,
|
|
36057
|
+
supportsVision: false
|
|
36058
|
+
},
|
|
36059
|
+
"openai/gpt-5-mini": {
|
|
36060
|
+
contextWindow: 2e5,
|
|
36061
|
+
maxOutputTokens: 65536,
|
|
36062
|
+
supportsTools: true,
|
|
36063
|
+
supportsVision: false
|
|
36064
|
+
},
|
|
36065
|
+
"openai/gpt-5.3-codex": {
|
|
36066
|
+
contextWindow: 4e5,
|
|
36067
|
+
maxOutputTokens: 128e3,
|
|
36068
|
+
supportsTools: true,
|
|
36069
|
+
supportsVision: false
|
|
36070
|
+
},
|
|
36071
|
+
"openai/gpt-5.4": {
|
|
36072
|
+
contextWindow: 4e5,
|
|
36073
|
+
maxOutputTokens: 128e3,
|
|
36074
|
+
supportsTools: true,
|
|
36075
|
+
supportsVision: true
|
|
36076
|
+
},
|
|
36077
|
+
"openai/gpt-5.4-nano": {
|
|
36078
|
+
contextWindow: 105e4,
|
|
36079
|
+
maxOutputTokens: 32768,
|
|
36080
|
+
supportsTools: true,
|
|
36081
|
+
supportsVision: false
|
|
36082
|
+
},
|
|
36083
|
+
"openai/gpt-5.5": {
|
|
36084
|
+
contextWindow: 105e4,
|
|
36085
|
+
maxOutputTokens: 128e3,
|
|
36086
|
+
supportsTools: true,
|
|
36087
|
+
supportsVision: true
|
|
36088
|
+
},
|
|
36089
|
+
"openai/gpt-5.6-terra": {
|
|
36090
|
+
contextWindow: 105e4,
|
|
36091
|
+
maxOutputTokens: 128e3,
|
|
36092
|
+
supportsTools: true,
|
|
36093
|
+
supportsVision: true
|
|
36094
|
+
},
|
|
36095
|
+
"openai/o3": {
|
|
36096
|
+
contextWindow: 2e5,
|
|
36097
|
+
maxOutputTokens: 1e5,
|
|
36098
|
+
supportsTools: true,
|
|
36099
|
+
supportsVision: false
|
|
36100
|
+
},
|
|
36101
|
+
"openai/o4-mini": {
|
|
36102
|
+
contextWindow: 128e3,
|
|
36103
|
+
maxOutputTokens: 65536,
|
|
36104
|
+
supportsTools: true,
|
|
36105
|
+
supportsVision: false
|
|
36106
|
+
},
|
|
36107
|
+
"qwen/qwen3.7-max": {
|
|
36108
|
+
contextWindow: 1e6,
|
|
36109
|
+
maxOutputTokens: 65536,
|
|
36110
|
+
supportsTools: true,
|
|
36111
|
+
supportsVision: false
|
|
36112
|
+
},
|
|
36113
|
+
"xai/grok-3-mini": {
|
|
36114
|
+
contextWindow: 131072,
|
|
36115
|
+
maxOutputTokens: 16384,
|
|
36116
|
+
supportsTools: true,
|
|
36117
|
+
supportsVision: false
|
|
36118
|
+
},
|
|
36119
|
+
"xai/grok-4-0709": {
|
|
36120
|
+
contextWindow: 131072,
|
|
36121
|
+
maxOutputTokens: 16384,
|
|
36122
|
+
supportsTools: true,
|
|
36123
|
+
supportsVision: false
|
|
36124
|
+
},
|
|
36125
|
+
"xai/grok-4-1-fast-non-reasoning": {
|
|
36126
|
+
contextWindow: 131072,
|
|
36127
|
+
maxOutputTokens: 16384,
|
|
36128
|
+
supportsTools: true,
|
|
36129
|
+
supportsVision: false
|
|
36130
|
+
},
|
|
36131
|
+
"xai/grok-4-1-fast-reasoning": {
|
|
36132
|
+
contextWindow: 131072,
|
|
36133
|
+
maxOutputTokens: 16384,
|
|
36134
|
+
supportsTools: true,
|
|
36135
|
+
supportsVision: false
|
|
36136
|
+
},
|
|
36137
|
+
"xai/grok-4-fast-non-reasoning": {
|
|
36138
|
+
contextWindow: 131072,
|
|
36139
|
+
maxOutputTokens: 16384,
|
|
36140
|
+
supportsTools: true,
|
|
36141
|
+
supportsVision: false
|
|
36142
|
+
},
|
|
36143
|
+
"xai/grok-4-fast-reasoning": {
|
|
36144
|
+
contextWindow: 131072,
|
|
36145
|
+
maxOutputTokens: 16384,
|
|
36146
|
+
supportsTools: true,
|
|
36147
|
+
supportsVision: false
|
|
36148
|
+
},
|
|
36149
|
+
"xai/grok-4.5": {
|
|
36150
|
+
contextWindow: 5e5,
|
|
36151
|
+
maxOutputTokens: 16384,
|
|
36152
|
+
supportsTools: true,
|
|
36153
|
+
supportsVision: true
|
|
36154
|
+
},
|
|
36155
|
+
"zai/glm-5.1": {
|
|
36156
|
+
contextWindow: 2e5,
|
|
36157
|
+
maxOutputTokens: 128e3,
|
|
36158
|
+
supportsTools: true,
|
|
36159
|
+
supportsVision: false
|
|
36160
|
+
},
|
|
36161
|
+
"zai/glm-5.2": {
|
|
36162
|
+
contextWindow: 1e6,
|
|
36163
|
+
maxOutputTokens: 262144,
|
|
36164
|
+
supportsTools: true,
|
|
36165
|
+
supportsVision: false
|
|
36166
|
+
}
|
|
36167
|
+
});
|
|
36168
|
+
model_profiles_generated_default = {
|
|
36169
|
+
"openai/gpt-5.5": {
|
|
36170
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
36171
|
+
latencyMs: 6243.1,
|
|
36172
|
+
p95LatencyMs: 9865,
|
|
36173
|
+
outputTokensPerSecond: 12.53,
|
|
36174
|
+
errorRate: 0,
|
|
36175
|
+
samples: 3
|
|
36176
|
+
},
|
|
36177
|
+
"openai/gpt-5.4-pro": {
|
|
36178
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
36179
|
+
latencyMs: 13015.5,
|
|
36180
|
+
p95LatencyMs: 23976.4,
|
|
36181
|
+
outputTokensPerSecond: 6.42,
|
|
36182
|
+
errorRate: 0,
|
|
36183
|
+
samples: 3
|
|
36184
|
+
},
|
|
36185
|
+
"openai/gpt-5.4-mini": {
|
|
36186
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
36187
|
+
latencyMs: 5550,
|
|
36188
|
+
p95LatencyMs: 6595.7,
|
|
36189
|
+
outputTokensPerSecond: 11.96,
|
|
36190
|
+
errorRate: 0.3333,
|
|
36191
|
+
samples: 3
|
|
36192
|
+
},
|
|
36193
|
+
"openai/gpt-5.3-codex": {
|
|
36194
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
36195
|
+
latencyMs: 4617.1,
|
|
36196
|
+
p95LatencyMs: 5800.7,
|
|
36197
|
+
outputTokensPerSecond: 12.48,
|
|
36198
|
+
errorRate: 0,
|
|
36199
|
+
samples: 3
|
|
36200
|
+
},
|
|
36201
|
+
"anthropic/claude-opus-4.8": {
|
|
36202
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
36203
|
+
latencyMs: 3915.1,
|
|
36204
|
+
p95LatencyMs: 6130.8,
|
|
36205
|
+
outputTokensPerSecond: 16.33,
|
|
36206
|
+
errorRate: 0,
|
|
36207
|
+
samples: 3
|
|
36208
|
+
},
|
|
36209
|
+
"anthropic/claude-opus-4.6": {
|
|
36210
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
36211
|
+
latencyMs: 3765.5,
|
|
36212
|
+
p95LatencyMs: 4257.2,
|
|
36213
|
+
outputTokensPerSecond: 14.18,
|
|
36214
|
+
errorRate: 0,
|
|
36215
|
+
samples: 3
|
|
36216
|
+
},
|
|
36217
|
+
"anthropic/claude-sonnet-4.6": {
|
|
36218
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
36219
|
+
latencyMs: 3860.6,
|
|
36220
|
+
p95LatencyMs: 5093.5,
|
|
36221
|
+
outputTokensPerSecond: 13.85,
|
|
36222
|
+
errorRate: 0,
|
|
36223
|
+
samples: 3
|
|
36224
|
+
},
|
|
36225
|
+
"anthropic/claude-haiku-4.5": {
|
|
36226
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
36227
|
+
latencyMs: 2734.9,
|
|
36228
|
+
p95LatencyMs: 3181.6,
|
|
36229
|
+
outputTokensPerSecond: 19.58,
|
|
36230
|
+
errorRate: 0,
|
|
36231
|
+
samples: 3
|
|
36232
|
+
},
|
|
36233
|
+
"google/gemini-3.1-pro": {
|
|
36234
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
36235
|
+
latencyMs: 13935.7,
|
|
36236
|
+
p95LatencyMs: 26675.3,
|
|
36237
|
+
outputTokensPerSecond: 77.47,
|
|
36238
|
+
errorRate: 0,
|
|
36239
|
+
samples: 3
|
|
36240
|
+
},
|
|
36241
|
+
"google/gemini-3.5-flash": {
|
|
36242
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
36243
|
+
latencyMs: 4608.7,
|
|
36244
|
+
p95LatencyMs: 8420.9,
|
|
36245
|
+
outputTokensPerSecond: 57.88,
|
|
36246
|
+
errorRate: 0,
|
|
36247
|
+
samples: 3
|
|
36248
|
+
},
|
|
36249
|
+
"google/gemini-3.1-flash-lite": {
|
|
36250
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
36251
|
+
latencyMs: 4619.7,
|
|
36252
|
+
p95LatencyMs: 9927.1,
|
|
36253
|
+
outputTokensPerSecond: 42.01,
|
|
36254
|
+
errorRate: 0,
|
|
36255
|
+
samples: 3
|
|
36256
|
+
},
|
|
36257
|
+
"google/gemini-2.5-flash": {
|
|
36258
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
36259
|
+
latencyMs: 5506.9,
|
|
36260
|
+
p95LatencyMs: 11462.5,
|
|
36261
|
+
outputTokensPerSecond: 65.19,
|
|
36262
|
+
errorRate: 0,
|
|
36263
|
+
samples: 3
|
|
36264
|
+
},
|
|
36265
|
+
"deepseek/deepseek-v4-pro": {
|
|
36266
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
36267
|
+
latencyMs: 6044.8,
|
|
36268
|
+
p95LatencyMs: 10782.3,
|
|
36269
|
+
outputTokensPerSecond: 22.47,
|
|
36270
|
+
errorRate: 0,
|
|
36271
|
+
samples: 3
|
|
36272
|
+
},
|
|
36273
|
+
"deepseek/deepseek-reasoner": {
|
|
36274
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
36275
|
+
latencyMs: 4111.9,
|
|
36276
|
+
p95LatencyMs: 5305.7,
|
|
36277
|
+
outputTokensPerSecond: 16.46,
|
|
36278
|
+
errorRate: 0,
|
|
36279
|
+
samples: 3
|
|
36280
|
+
},
|
|
36281
|
+
"deepseek/deepseek-chat": {
|
|
36282
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
36283
|
+
latencyMs: 2648.6,
|
|
36284
|
+
p95LatencyMs: 3524.1,
|
|
36285
|
+
outputTokensPerSecond: 16.73,
|
|
36286
|
+
errorRate: 0,
|
|
36287
|
+
samples: 3
|
|
36288
|
+
},
|
|
36289
|
+
"moonshot/kimi-k2.7": {
|
|
36290
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
36291
|
+
latencyMs: 4295.4,
|
|
36292
|
+
p95LatencyMs: 6153.8,
|
|
36293
|
+
outputTokensPerSecond: 18.54,
|
|
36294
|
+
errorRate: 0,
|
|
36295
|
+
samples: 3
|
|
36296
|
+
},
|
|
36297
|
+
"qwen/qwen3.7-max": {
|
|
36298
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
36299
|
+
latencyMs: 30729.4,
|
|
36300
|
+
p95LatencyMs: 39622,
|
|
36301
|
+
outputTokensPerSecond: 36.89,
|
|
36302
|
+
errorRate: 0.3333,
|
|
36303
|
+
samples: 3
|
|
36304
|
+
},
|
|
36305
|
+
"xai/grok-4.3": {
|
|
36306
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
36307
|
+
latencyMs: 6946.1,
|
|
36308
|
+
p95LatencyMs: 9495.4,
|
|
36309
|
+
outputTokensPerSecond: 65.3,
|
|
36310
|
+
errorRate: 0,
|
|
36311
|
+
samples: 3
|
|
36312
|
+
},
|
|
36313
|
+
"xai/grok-4.20-reasoning": {
|
|
36314
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
36315
|
+
latencyMs: 3472.4,
|
|
36316
|
+
p95LatencyMs: 5332.4,
|
|
36317
|
+
outputTokensPerSecond: 13.27,
|
|
36318
|
+
errorRate: 0,
|
|
36319
|
+
samples: 3
|
|
36320
|
+
},
|
|
36321
|
+
"xai/grok-4.20-non-reasoning": {
|
|
36322
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
36323
|
+
latencyMs: 5174.4,
|
|
36324
|
+
p95LatencyMs: 6081.7,
|
|
36325
|
+
outputTokensPerSecond: 10.21,
|
|
36326
|
+
errorRate: 0.3333,
|
|
36327
|
+
samples: 3
|
|
36328
|
+
},
|
|
36329
|
+
"xai/grok-4-1-fast-reasoning": {
|
|
36330
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
36331
|
+
latencyMs: 13148.2,
|
|
36332
|
+
p95LatencyMs: 19104.2,
|
|
36333
|
+
outputTokensPerSecond: 4.28,
|
|
36334
|
+
errorRate: 0,
|
|
36335
|
+
samples: 3
|
|
36336
|
+
},
|
|
36337
|
+
"minimax/minimax-m3": {
|
|
36338
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
36339
|
+
latencyMs: 3385,
|
|
36340
|
+
p95LatencyMs: 4247.2,
|
|
36341
|
+
outputTokensPerSecond: 15.16,
|
|
36342
|
+
errorRate: 0,
|
|
36343
|
+
samples: 3
|
|
36344
|
+
},
|
|
36345
|
+
"minimax/minimax-m2.7": {
|
|
36346
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
36347
|
+
latencyMs: 4596.7,
|
|
36348
|
+
p95LatencyMs: 6884.6,
|
|
36349
|
+
outputTokensPerSecond: 17.03,
|
|
36350
|
+
errorRate: 0,
|
|
36351
|
+
samples: 3
|
|
36352
|
+
},
|
|
36353
|
+
"zai/glm-5.2": {
|
|
36354
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
36355
|
+
latencyMs: 4406.3,
|
|
36356
|
+
p95LatencyMs: 6139.7,
|
|
36357
|
+
outputTokensPerSecond: 10.41,
|
|
36358
|
+
errorRate: 0,
|
|
36359
|
+
samples: 3
|
|
36360
|
+
},
|
|
36361
|
+
"zai/glm-5.1": {
|
|
36362
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
36363
|
+
latencyMs: 7775.4,
|
|
36364
|
+
p95LatencyMs: 9182.1,
|
|
36365
|
+
outputTokensPerSecond: 6.08,
|
|
36366
|
+
errorRate: 0,
|
|
36367
|
+
samples: 3
|
|
36368
|
+
},
|
|
36369
|
+
"zai/glm-5": {
|
|
36370
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
36371
|
+
latencyMs: 4159.4,
|
|
36372
|
+
p95LatencyMs: 4992.7,
|
|
36373
|
+
outputTokensPerSecond: 10.28,
|
|
36374
|
+
errorRate: 0,
|
|
36375
|
+
samples: 3
|
|
36376
|
+
},
|
|
36377
|
+
"free/qwen3-coder-480b": {
|
|
36378
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
36379
|
+
latencyMs: 2063.9,
|
|
36380
|
+
p95LatencyMs: 3646.3,
|
|
36381
|
+
outputTokensPerSecond: 39.8,
|
|
36382
|
+
errorRate: 0,
|
|
36383
|
+
samples: 3
|
|
36384
|
+
},
|
|
36385
|
+
"free/mistral-large-3-675b": {
|
|
36386
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
36387
|
+
latencyMs: 3147.5,
|
|
36388
|
+
p95LatencyMs: 5555.3,
|
|
36389
|
+
outputTokensPerSecond: 27.76,
|
|
36390
|
+
errorRate: 0,
|
|
36391
|
+
samples: 3
|
|
36392
|
+
},
|
|
36393
|
+
"free/nemotron-3-nano-omni-30b-a3b-reasoning": {
|
|
36394
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
36395
|
+
latencyMs: 6508.4,
|
|
36396
|
+
p95LatencyMs: 14252.7,
|
|
36397
|
+
outputTokensPerSecond: 68.26,
|
|
36398
|
+
errorRate: 0,
|
|
36399
|
+
samples: 3
|
|
36400
|
+
},
|
|
36401
|
+
"free/glm-4.7": {
|
|
36402
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
36403
|
+
latencyMs: 2014.8,
|
|
36404
|
+
p95LatencyMs: 3039.9,
|
|
36405
|
+
outputTokensPerSecond: 39.92,
|
|
36406
|
+
errorRate: 0,
|
|
36407
|
+
samples: 3
|
|
36408
|
+
}
|
|
36409
|
+
};
|
|
36410
|
+
LIVE_MODEL_PROFILES = Object.freeze(
|
|
36411
|
+
model_profiles_generated_default
|
|
36412
|
+
);
|
|
36413
|
+
HISTORICAL_MODEL_PROFILES = Object.freeze({
|
|
36414
|
+
"anthropic/claude-haiku-4.5": {
|
|
36415
|
+
measuredAt: "2026-03-16T13:50:48Z",
|
|
36416
|
+
latencyMs: 2305,
|
|
36417
|
+
outputTokensPerSecond: 140.6
|
|
36418
|
+
},
|
|
36419
|
+
"anthropic/claude-opus-4.6": {
|
|
36420
|
+
measuredAt: "2026-03-16T13:50:48Z",
|
|
36421
|
+
latencyMs: 2139,
|
|
36422
|
+
outputTokensPerSecond: 119.7
|
|
36423
|
+
},
|
|
36424
|
+
"anthropic/claude-sonnet-4.6": {
|
|
36425
|
+
measuredAt: "2026-03-16T13:50:48Z",
|
|
36426
|
+
latencyMs: 2110,
|
|
36427
|
+
outputTokensPerSecond: 121.3
|
|
36428
|
+
},
|
|
36429
|
+
"deepseek/deepseek-chat": {
|
|
36430
|
+
measuredAt: "2026-03-16T13:50:48Z",
|
|
36431
|
+
latencyMs: 1431,
|
|
36432
|
+
outputTokensPerSecond: 179.2,
|
|
36433
|
+
intelligenceIndex: 32
|
|
36434
|
+
},
|
|
36435
|
+
"google/gemini-2.5-flash": {
|
|
36436
|
+
measuredAt: "2026-03-16T13:50:48Z",
|
|
36437
|
+
latencyMs: 1238,
|
|
36438
|
+
outputTokensPerSecond: 207.6,
|
|
36439
|
+
intelligenceIndex: 20
|
|
36440
|
+
},
|
|
36441
|
+
"google/gemini-2.5-flash-lite": {
|
|
36442
|
+
measuredAt: "2026-03-16T13:50:48Z",
|
|
36443
|
+
latencyMs: 1353,
|
|
36444
|
+
outputTokensPerSecond: 192.5,
|
|
36445
|
+
intelligenceIndex: 20
|
|
36446
|
+
},
|
|
36447
|
+
"google/gemini-2.5-pro": {
|
|
36448
|
+
measuredAt: "2026-03-16T13:50:48Z",
|
|
36449
|
+
latencyMs: 1294,
|
|
36450
|
+
outputTokensPerSecond: 197.8
|
|
36451
|
+
},
|
|
36452
|
+
"google/gemini-3.1-pro": {
|
|
36453
|
+
measuredAt: "2026-03-16T13:50:48Z",
|
|
36454
|
+
latencyMs: 1609,
|
|
36455
|
+
outputTokensPerSecond: 167.2
|
|
36456
|
+
},
|
|
36457
|
+
"moonshot/kimi-k2.5": {
|
|
36458
|
+
measuredAt: "2026-03-16T13:50:48Z",
|
|
36459
|
+
latencyMs: 1646,
|
|
36460
|
+
outputTokensPerSecond: 155.7
|
|
36461
|
+
},
|
|
36462
|
+
"openai/gpt-4o-mini": {
|
|
36463
|
+
measuredAt: "2026-03-16T13:50:48Z",
|
|
36464
|
+
latencyMs: 2764,
|
|
36465
|
+
outputTokensPerSecond: 92.8
|
|
36466
|
+
},
|
|
36467
|
+
"openai/gpt-5.3-codex": {
|
|
36468
|
+
measuredAt: "2026-03-16T13:50:48Z",
|
|
36469
|
+
latencyMs: 7935,
|
|
36470
|
+
outputTokensPerSecond: 32.3
|
|
36471
|
+
},
|
|
36472
|
+
"xai/grok-4-1-fast-non-reasoning": {
|
|
36473
|
+
measuredAt: "2026-03-16T13:50:48Z",
|
|
36474
|
+
latencyMs: 1244,
|
|
36475
|
+
outputTokensPerSecond: 205.8,
|
|
36476
|
+
intelligenceIndex: 41
|
|
36477
|
+
},
|
|
36478
|
+
"xai/grok-4-1-fast-reasoning": {
|
|
36479
|
+
measuredAt: "2026-03-16T13:50:48Z",
|
|
36480
|
+
latencyMs: 1454,
|
|
36481
|
+
outputTokensPerSecond: 176.2,
|
|
36482
|
+
intelligenceIndex: 41
|
|
36483
|
+
}
|
|
36484
|
+
});
|
|
36485
|
+
DEFAULT_PORTFOLIO_WEIGHTS = {
|
|
36486
|
+
auto: {
|
|
36487
|
+
quality: 0.47,
|
|
36488
|
+
capability: 0.2,
|
|
36489
|
+
cost: 0.18,
|
|
36490
|
+
speed: 0.07,
|
|
36491
|
+
reliability: 0.03,
|
|
36492
|
+
legacy: 0.05
|
|
36493
|
+
},
|
|
36494
|
+
eco: { quality: 0.36, capability: 0.2, cost: 0.28, speed: 0.1, reliability: 0.04, legacy: 0.02 },
|
|
36495
|
+
premium: {
|
|
36496
|
+
quality: 0.58,
|
|
36497
|
+
capability: 0.2,
|
|
36498
|
+
cost: 0.08,
|
|
36499
|
+
speed: 0.06,
|
|
36500
|
+
reliability: 0.06,
|
|
36501
|
+
legacy: 0.02
|
|
36502
|
+
},
|
|
36503
|
+
highStakesBoost: { quality: 0.08, reliability: 0.05 },
|
|
36504
|
+
latencySensitiveSpeedBoost: 0.08,
|
|
36505
|
+
affinityFloorGap: { auto: 0.1, eco: 0.22, premium: 0.05 }
|
|
36506
|
+
};
|
|
36507
|
+
PortfolioStrategy = class {
|
|
36508
|
+
name = "portfolio";
|
|
36509
|
+
route(prompt, systemPrompt, maxOutputTokens, options) {
|
|
36510
|
+
const features = classifyTask(prompt, systemPrompt, options);
|
|
36511
|
+
const base3 = new RulesStrategy().route(prompt, systemPrompt, maxOutputTokens, {
|
|
36512
|
+
...options,
|
|
36513
|
+
requiresTools: features.needsTools
|
|
36514
|
+
});
|
|
36515
|
+
const tierConfigs = base3.tierConfigs;
|
|
36516
|
+
if (!tierConfigs) return base3;
|
|
36517
|
+
const targetTier = (features.taskType === "reasoning_mcq" || features.taskType === "reasoning_math") && (base3.tier === "SIMPLE" || base3.tier === "MEDIUM") ? "REASONING" : base3.tier;
|
|
36518
|
+
const tierConfig = tierConfigs[targetTier];
|
|
36519
|
+
const configuredCandidates = tierConfig ? getFallbackChain(targetTier, tierConfigs) : [];
|
|
36520
|
+
const chain3 = [
|
|
36521
|
+
.../* @__PURE__ */ new Set([...configuredCandidates, ...evidenceCandidates(features.taskType)])
|
|
36522
|
+
].filter((model2) => typeof model2 === "string" && model2.length > 0);
|
|
36523
|
+
const eligible = chain3.filter(
|
|
36524
|
+
(model2) => isEligible(model2, features, maxOutputTokens, options)
|
|
36525
|
+
);
|
|
36526
|
+
const eligibleCandidates = eligible.length > 0 ? eligible : chain3;
|
|
36527
|
+
if (eligibleCandidates.length === 0) return base3;
|
|
36528
|
+
const profileName = options.routingProfile === "eco" ? "eco" : options.routingProfile === "premium" ? "premium" : "auto";
|
|
36529
|
+
const portfolio = options.config.portfolio ?? DEFAULT_PORTFOLIO_WEIGHTS;
|
|
36530
|
+
const getAffinity = (model2) => affinity(
|
|
36531
|
+
model2,
|
|
36532
|
+
features.taskType,
|
|
36533
|
+
features.language,
|
|
36534
|
+
features.agentDomain,
|
|
36535
|
+
features.deepWebResearch,
|
|
36536
|
+
features.agentRisk,
|
|
36537
|
+
features.terminalToolSignal,
|
|
36538
|
+
features.terminalSafetySensitive
|
|
36539
|
+
);
|
|
36540
|
+
const bestAffinity = Math.max(...eligibleCandidates.map(getAffinity));
|
|
36541
|
+
const specificAffinity = eligibleCandidates.filter((model2) => getAffinity(model2) > 0.68);
|
|
36542
|
+
const affinityPool = specificAffinity.length > 0 ? specificAffinity : [eligibleCandidates[0]];
|
|
36543
|
+
const affinityFloorGap = features.terminalToolSignal ? Math.max(
|
|
36544
|
+
portfolio.affinityFloorGap[profileName],
|
|
36545
|
+
features.terminalSafetySensitive ? 0.15 : 0.12
|
|
36546
|
+
) : portfolio.affinityFloorGap[profileName];
|
|
36547
|
+
const candidates = affinityPool.filter(
|
|
36548
|
+
(model2) => getAffinity(model2) >= bestAffinity - affinityFloorGap
|
|
36549
|
+
);
|
|
36550
|
+
const costs = candidates.map(
|
|
36551
|
+
(model2) => estimatedCost(model2, options, features.estimatedInputTokens, maxOutputTokens)
|
|
36552
|
+
);
|
|
36553
|
+
const finiteCosts = costs.filter(Number.isFinite);
|
|
36554
|
+
const minCost = finiteCosts.length > 0 ? Math.min(...finiteCosts) : 0;
|
|
36555
|
+
const maxCost = finiteCosts.length > 0 ? Math.max(...finiteCosts) : 1;
|
|
36556
|
+
const now2 = options.now ?? /* @__PURE__ */ new Date();
|
|
36557
|
+
const profileWeights = portfolio[profileName];
|
|
36558
|
+
const rankedEntries = candidates.map((model2, index2) => {
|
|
36559
|
+
const cost = estimatedCost(model2, options, features.estimatedInputTokens, maxOutputTokens);
|
|
36560
|
+
const costScore = Number.isFinite(cost) && maxCost > minCost ? 1 - (cost - minCost) / (maxCost - minCost) : 0.5;
|
|
36561
|
+
const capabilityScore = isEligible(model2, features, maxOutputTokens, options) ? 1 : 0;
|
|
36562
|
+
const profile = profileScore(model2, options, now2);
|
|
36563
|
+
const observedQuality = profile?.quality === void 0 ? getAffinity(model2) : getAffinity(model2) * (1 - profile.freshness) + profile.quality * profile.freshness;
|
|
36564
|
+
const observedSpeed = profile ? profile.speed * profile.freshness : 0.5;
|
|
36565
|
+
const observedTailSpeed = profile ? profile.tailSpeed * profile.freshness : 0.5;
|
|
36566
|
+
const observedReliability = profile ? profile.reliability * profile.freshness + (1 - profile.freshness) : 1;
|
|
36567
|
+
const legacyScore = 1 - index2 / Math.max(1, candidates.length - 1);
|
|
36568
|
+
const qualityWeight = profileWeights.quality + (features.highStakes ? portfolio.highStakesBoost.quality : 0);
|
|
36569
|
+
const speedScore = features.latencySensitive ? observedTailSpeed : observedSpeed;
|
|
36570
|
+
const speedWeight = profileWeights.speed + (features.latencySensitive ? portfolio.latencySensitiveSpeedBoost : 0);
|
|
36571
|
+
const reliabilityWeight = profileWeights.reliability + (features.highStakes ? portfolio.highStakesBoost.reliability : 0);
|
|
36572
|
+
const score = observedQuality * qualityWeight + capabilityScore * profileWeights.capability + costScore * profileWeights.cost + speedScore * speedWeight + observedReliability * reliabilityWeight + legacyScore * profileWeights.legacy;
|
|
36573
|
+
return {
|
|
36574
|
+
model: model2,
|
|
36575
|
+
score,
|
|
36576
|
+
quality: observedQuality,
|
|
36577
|
+
cost: costScore,
|
|
36578
|
+
speed: speedScore,
|
|
36579
|
+
reliability: observedReliability
|
|
36580
|
+
};
|
|
36581
|
+
}).sort((a, b) => b.score - a.score);
|
|
36582
|
+
const scoredModels = rankedEntries.map((item) => item.model);
|
|
36583
|
+
const webResearchFallbackOrder = [
|
|
36584
|
+
"anthropic/claude-sonnet-5",
|
|
36585
|
+
"openai/gpt-5-mini",
|
|
36586
|
+
"google/gemini-3.5-flash",
|
|
36587
|
+
"anthropic/claude-opus-5",
|
|
36588
|
+
"anthropic/claude-opus-4.8",
|
|
36589
|
+
"openai/gpt-5.3-codex"
|
|
36590
|
+
];
|
|
36591
|
+
const ranked = features.agentDomain === "web_research" ? [
|
|
36592
|
+
...scoredModels,
|
|
36593
|
+
...webResearchFallbackOrder.filter(
|
|
36594
|
+
(model2) => eligibleCandidates.includes(model2) && !scoredModels.includes(model2)
|
|
36595
|
+
),
|
|
36596
|
+
...eligibleCandidates.filter(
|
|
36597
|
+
(model2) => !scoredModels.includes(model2) && !webResearchFallbackOrder.includes(model2)
|
|
36598
|
+
)
|
|
36599
|
+
] : features.taskType === "tool_agent" || features.taskType === "tool_agent_parallel" && features.agentDomain !== "other" ? [
|
|
36600
|
+
...scoredModels,
|
|
36601
|
+
...eligibleCandidates.filter((model2) => !scoredModels.includes(model2))
|
|
36602
|
+
] : [
|
|
36603
|
+
...scoredModels,
|
|
36604
|
+
...eligibleCandidates.filter((model2) => !scoredModels.includes(model2))
|
|
36605
|
+
];
|
|
36606
|
+
const model = ranked[0] ?? base3.model;
|
|
36607
|
+
const selectedTierConfigs = {
|
|
36608
|
+
...tierConfigs,
|
|
36609
|
+
[targetTier]: { primary: model, fallback: ranked.slice(1) }
|
|
36610
|
+
};
|
|
36611
|
+
const decision = selectModel(
|
|
36612
|
+
targetTier,
|
|
36613
|
+
base3.confidence,
|
|
36614
|
+
"portfolio",
|
|
36615
|
+
`${base3.reasoning} | v3 task=${features.taskType} agentRisk=${features.agentRisk} deepWebResearch=${features.deepWebResearch} terminalCode=${features.implicitTerminalCode} terminalSafety=${features.terminalSafetySensitive} candidates=${ranked.length}`,
|
|
36616
|
+
selectedTierConfigs,
|
|
36617
|
+
options.modelPricing,
|
|
36618
|
+
features.estimatedInputTokens,
|
|
36619
|
+
maxOutputTokens,
|
|
36620
|
+
options.routingProfile,
|
|
36621
|
+
base3.agenticScore
|
|
36622
|
+
);
|
|
36623
|
+
return {
|
|
36624
|
+
...decision,
|
|
36625
|
+
tierConfigs: selectedTierConfigs,
|
|
36626
|
+
profile: base3.profile,
|
|
36627
|
+
candidates: ranked,
|
|
36628
|
+
candidateScores: rankedEntries.map(({ model: model2, score, quality, cost, speed, reliability }) => ({
|
|
36629
|
+
model: model2,
|
|
36630
|
+
score,
|
|
36631
|
+
quality,
|
|
36632
|
+
cost,
|
|
36633
|
+
speed,
|
|
36634
|
+
reliability
|
|
36635
|
+
})),
|
|
36636
|
+
taskType: features.taskType,
|
|
36637
|
+
routerVersion: "v3-portfolio"
|
|
36638
|
+
};
|
|
36639
|
+
}
|
|
36640
|
+
};
|
|
35254
36641
|
DEFAULT_ROUTING_CONFIG = {
|
|
35255
|
-
version: "
|
|
36642
|
+
version: "3.4",
|
|
36643
|
+
strategy: "portfolio",
|
|
36644
|
+
portfolio: {
|
|
36645
|
+
auto: {
|
|
36646
|
+
quality: 0.47,
|
|
36647
|
+
capability: 0.2,
|
|
36648
|
+
cost: 0.18,
|
|
36649
|
+
speed: 0.07,
|
|
36650
|
+
reliability: 0.03,
|
|
36651
|
+
legacy: 0.05
|
|
36652
|
+
},
|
|
36653
|
+
eco: {
|
|
36654
|
+
quality: 0.36,
|
|
36655
|
+
capability: 0.2,
|
|
36656
|
+
cost: 0.28,
|
|
36657
|
+
speed: 0.1,
|
|
36658
|
+
reliability: 0.04,
|
|
36659
|
+
legacy: 0.02
|
|
36660
|
+
},
|
|
36661
|
+
premium: {
|
|
36662
|
+
quality: 0.58,
|
|
36663
|
+
capability: 0.2,
|
|
36664
|
+
cost: 0.08,
|
|
36665
|
+
speed: 0.06,
|
|
36666
|
+
reliability: 0.06,
|
|
36667
|
+
legacy: 0.02
|
|
36668
|
+
},
|
|
36669
|
+
highStakesBoost: { quality: 0.08, reliability: 0.05 },
|
|
36670
|
+
latencySensitiveSpeedBoost: 0.08,
|
|
36671
|
+
affinityFloorGap: { auto: 0.1, eco: 0.22, premium: 0.05 }
|
|
36672
|
+
},
|
|
35256
36673
|
classifier: {
|
|
35257
36674
|
llmModel: "google/gemini-2.5-flash",
|
|
35258
36675
|
llmMaxTokens: 10,
|
|
@@ -36378,8 +37795,8 @@ var init_config = __esm({
|
|
|
36378
37795
|
// FREE — smaller, faster
|
|
36379
37796
|
"free/deepseek-v4-flash",
|
|
36380
37797
|
// FREE — 1M ctx; slow (~10 tok/s, 07-28 probe) but completes
|
|
36381
|
-
|
|
36382
|
-
//
|
|
37798
|
+
// seed-oss-36b sat here as the free coder until it EOL'd 2026-08-03 (HTTP 410).
|
|
37799
|
+
// gpt-oss-120b/20b already head this chain, so the rung is dropped, not retargeted.
|
|
36383
37800
|
"google/gemini-3.1-flash-lite",
|
|
36384
37801
|
// $0.25/$1.50 — newest flash-lite
|
|
36385
37802
|
"openai/gpt-5.4-nano",
|
|
@@ -36496,8 +37913,8 @@ var init_config = __esm({
|
|
|
36496
37913
|
"openai/gpt-5.3-codex",
|
|
36497
37914
|
"deepseek/deepseek-chat",
|
|
36498
37915
|
// Cheap, reliable
|
|
36499
|
-
"free/
|
|
36500
|
-
// NVIDIA free ultimate backstop (
|
|
37916
|
+
"free/gpt-oss-120b"
|
|
37917
|
+
// NVIDIA free ultimate backstop (was seed-oss-36b; EOL'd 2026-08-03)
|
|
36501
37918
|
]
|
|
36502
37919
|
},
|
|
36503
37920
|
REASONING: {
|
|
@@ -36586,8 +38003,8 @@ var init_config = __esm({
|
|
|
36586
38003
|
// Previous flagship — 6,213ms, reliable
|
|
36587
38004
|
"deepseek/deepseek-chat",
|
|
36588
38005
|
// 1,431ms — cheap, reliable
|
|
36589
|
-
"free/
|
|
36590
|
-
// NVIDIA free ultimate backstop (
|
|
38006
|
+
"free/gpt-oss-120b"
|
|
38007
|
+
// NVIDIA free ultimate backstop (was seed-oss-36b; EOL'd 2026-08-03)
|
|
36591
38008
|
]
|
|
36592
38009
|
},
|
|
36593
38010
|
REASONING: {
|
|
@@ -36632,21 +38049,15 @@ var init_config = __esm({
|
|
|
36632
38049
|
// Set to `true` to force agentic tiers; `false` to disable them entirely.
|
|
36633
38050
|
}
|
|
36634
38051
|
};
|
|
38052
|
+
registerStrategy(new PortfolioStrategy());
|
|
36635
38053
|
}
|
|
36636
38054
|
});
|
|
36637
38055
|
|
|
36638
38056
|
// src/router/index.ts
|
|
36639
|
-
function route(prompt, systemPrompt, maxOutputTokens, options) {
|
|
36640
|
-
const strategy = getStrategy("rules");
|
|
36641
|
-
return strategy.route(prompt, systemPrompt, maxOutputTokens, options);
|
|
36642
|
-
}
|
|
36643
38057
|
var init_router = __esm({
|
|
36644
38058
|
"src/router/index.ts"() {
|
|
36645
38059
|
"use strict";
|
|
36646
|
-
|
|
36647
|
-
init_strategy();
|
|
36648
|
-
init_selector();
|
|
36649
|
-
init_config();
|
|
38060
|
+
init_dist();
|
|
36650
38061
|
}
|
|
36651
38062
|
});
|
|
36652
38063
|
|
|
@@ -56607,7 +58018,7 @@ var init_exclude_models = __esm({
|
|
|
56607
58018
|
|
|
56608
58019
|
// src/config.ts
|
|
56609
58020
|
var DEFAULT_PORT, PROXY_PORT;
|
|
56610
|
-
var
|
|
58021
|
+
var init_config = __esm({
|
|
56611
58022
|
"src/config.ts"() {
|
|
56612
58023
|
"use strict";
|
|
56613
58024
|
DEFAULT_PORT = 8402;
|
|
@@ -73005,27 +74416,27 @@ var require_dns = __commonJS({
|
|
|
73005
74416
|
}
|
|
73006
74417
|
);
|
|
73007
74418
|
}
|
|
73008
|
-
#defaultPick(origin2, hostnameRecords,
|
|
74419
|
+
#defaultPick(origin2, hostnameRecords, affinity2) {
|
|
73009
74420
|
let ip = null;
|
|
73010
74421
|
const { records, offset } = hostnameRecords;
|
|
73011
74422
|
let family;
|
|
73012
74423
|
if (this.dualStack) {
|
|
73013
|
-
if (
|
|
74424
|
+
if (affinity2 == null) {
|
|
73014
74425
|
if (offset == null || offset === maxInt) {
|
|
73015
74426
|
hostnameRecords.offset = 0;
|
|
73016
|
-
|
|
74427
|
+
affinity2 = 4;
|
|
73017
74428
|
} else {
|
|
73018
74429
|
hostnameRecords.offset++;
|
|
73019
|
-
|
|
74430
|
+
affinity2 = (hostnameRecords.offset & 1) === 1 ? 6 : 4;
|
|
73020
74431
|
}
|
|
73021
74432
|
}
|
|
73022
|
-
if (records[
|
|
73023
|
-
family = records[
|
|
74433
|
+
if (records[affinity2] != null && records[affinity2].ips.length > 0) {
|
|
74434
|
+
family = records[affinity2];
|
|
73024
74435
|
} else {
|
|
73025
|
-
family = records[
|
|
74436
|
+
family = records[affinity2 === 4 ? 6 : 4];
|
|
73026
74437
|
}
|
|
73027
74438
|
} else {
|
|
73028
|
-
family = records[
|
|
74439
|
+
family = records[affinity2];
|
|
73029
74440
|
}
|
|
73030
74441
|
if (family == null || family.ips.length === 0) {
|
|
73031
74442
|
return ip;
|
|
@@ -73042,7 +74453,7 @@ var require_dns = __commonJS({
|
|
|
73042
74453
|
}
|
|
73043
74454
|
if (Date.now() - ip.timestamp > ip.ttl) {
|
|
73044
74455
|
family.ips.splice(position, 1);
|
|
73045
|
-
return this.pick(origin2, hostnameRecords,
|
|
74456
|
+
return this.pick(origin2, hostnameRecords, affinity2);
|
|
73046
74457
|
}
|
|
73047
74458
|
return ip;
|
|
73048
74459
|
}
|
|
@@ -73181,11 +74592,11 @@ var require_dns = __commonJS({
|
|
|
73181
74592
|
throw new InvalidArgumentError("Invalid storage. Must be a object with methods: { get, set, full, delete }");
|
|
73182
74593
|
}
|
|
73183
74594
|
const dualStack = interceptorOpts?.dualStack ?? true;
|
|
73184
|
-
let
|
|
74595
|
+
let affinity2;
|
|
73185
74596
|
if (dualStack) {
|
|
73186
|
-
|
|
74597
|
+
affinity2 = interceptorOpts?.affinity ?? null;
|
|
73187
74598
|
} else {
|
|
73188
|
-
|
|
74599
|
+
affinity2 = interceptorOpts?.affinity ?? 4;
|
|
73189
74600
|
}
|
|
73190
74601
|
const opts = {
|
|
73191
74602
|
maxTTL: interceptorOpts?.maxTTL ?? 1e4,
|
|
@@ -73193,7 +74604,7 @@ var require_dns = __commonJS({
|
|
|
73193
74604
|
lookup: interceptorOpts?.lookup ?? null,
|
|
73194
74605
|
pick: interceptorOpts?.pick ?? null,
|
|
73195
74606
|
dualStack,
|
|
73196
|
-
affinity,
|
|
74607
|
+
affinity: affinity2,
|
|
73197
74608
|
maxItems: interceptorOpts?.maxItems ?? Infinity,
|
|
73198
74609
|
storage: interceptorOpts?.storage
|
|
73199
74610
|
};
|
|
@@ -86488,6 +87899,19 @@ function buildModelPricing() {
|
|
|
86488
87899
|
}
|
|
86489
87900
|
return map;
|
|
86490
87901
|
}
|
|
87902
|
+
function buildModelCapabilities() {
|
|
87903
|
+
return Object.fromEntries(
|
|
87904
|
+
BLOCKRUN_MODELS.map((model) => [
|
|
87905
|
+
model.id,
|
|
87906
|
+
{
|
|
87907
|
+
contextWindow: model.contextWindow,
|
|
87908
|
+
maxOutputTokens: model.maxOutput,
|
|
87909
|
+
supportsTools: model.toolCalling === true,
|
|
87910
|
+
supportsVision: model.vision === true
|
|
87911
|
+
}
|
|
87912
|
+
])
|
|
87913
|
+
);
|
|
87914
|
+
}
|
|
86491
87915
|
function buildProxyModelList(createdAt = Math.floor(Date.now() / 1e3)) {
|
|
86492
87916
|
const seen = /* @__PURE__ */ new Set();
|
|
86493
87917
|
return OPENCLAW_MODELS.filter((model) => {
|
|
@@ -86833,7 +88257,8 @@ async function startProxy(options) {
|
|
|
86833
88257
|
const modelPricing = buildModelPricing();
|
|
86834
88258
|
const routerOpts = {
|
|
86835
88259
|
config: routingConfig,
|
|
86836
|
-
modelPricing
|
|
88260
|
+
modelPricing,
|
|
88261
|
+
modelCapabilities: buildModelCapabilities()
|
|
86837
88262
|
};
|
|
86838
88263
|
const deduplicator = new RequestDeduplicator();
|
|
86839
88264
|
const responseCache2 = new ResponseCache(options.cacheConfig);
|
|
@@ -87979,6 +89404,7 @@ async function proxyRequest(req, res, apiBase, payFetch, options, routerOpts, de
|
|
|
87979
89404
|
let maxTokens = DEFAULT_MAX_TOKENS;
|
|
87980
89405
|
let routingProfile = null;
|
|
87981
89406
|
let stickyExplicitModel;
|
|
89407
|
+
let pendingShadowComparison;
|
|
87982
89408
|
let balanceFallbackNotice;
|
|
87983
89409
|
let budgetDowngradeNotice;
|
|
87984
89410
|
let budgetDowngradeHeaderMode;
|
|
@@ -88574,8 +90000,16 @@ async function proxyRequest(req, res, apiBase, payFetch, options, routerOpts, de
|
|
|
88574
90000
|
const systemPrompt = typeof systemMsg?.content === "string" ? systemMsg.content : void 0;
|
|
88575
90001
|
const tools = parsed.tools;
|
|
88576
90002
|
hasTools = Array.isArray(tools) && tools.length > 0;
|
|
90003
|
+
const requiresTools = hasTools && inferToolRequirement(prompt, systemPrompt, parsed.tool_choice);
|
|
90004
|
+
const toolNames = (tools ?? []).map((tool) => {
|
|
90005
|
+
if (typeof tool !== "object" || tool === null) return void 0;
|
|
90006
|
+
const fn = tool.function;
|
|
90007
|
+
if (typeof fn !== "object" || fn === null) return void 0;
|
|
90008
|
+
const name = fn.name;
|
|
90009
|
+
return typeof name === "string" ? name : void 0;
|
|
90010
|
+
}).filter((name) => name !== void 0);
|
|
88577
90011
|
if (hasTools && tools) {
|
|
88578
|
-
console.log(`[ClawRouter] Tools detected (${tools.length}),
|
|
90012
|
+
console.log(`[ClawRouter] Tools detected (${tools.length}), required=${requiresTools}`);
|
|
88579
90013
|
}
|
|
88580
90014
|
hasVision = parsedMessages.some((m) => {
|
|
88581
90015
|
if (Array.isArray(m.content)) {
|
|
@@ -88589,8 +90023,36 @@ async function proxyRequest(req, res, apiBase, payFetch, options, routerOpts, de
|
|
|
88589
90023
|
routingDecision = route(prompt, systemPrompt, maxTokens, {
|
|
88590
90024
|
...routerOpts,
|
|
88591
90025
|
routingProfile: routingProfile ?? void 0,
|
|
88592
|
-
hasTools
|
|
90026
|
+
hasTools,
|
|
90027
|
+
toolCount: tools?.length ?? 0,
|
|
90028
|
+
toolNames,
|
|
90029
|
+
requiresTools,
|
|
90030
|
+
hasVision,
|
|
90031
|
+
requiresStructuredOutput: typeof parsed.response_format === "object" && parsed.response_format !== null
|
|
88593
90032
|
});
|
|
90033
|
+
const shadow = routerOpts.config.shadow;
|
|
90034
|
+
const activeStrategy = routerOpts.config.strategy ?? "portfolio";
|
|
90035
|
+
const shadowRate = Math.max(0, Math.min(1, shadow?.sampleRate ?? 1));
|
|
90036
|
+
if (shadow && shadow.strategy !== activeStrategy && Math.random() < shadowRate) {
|
|
90037
|
+
const requiresStructuredOutput = typeof parsed.response_format === "object" && parsed.response_format !== null;
|
|
90038
|
+
const shadowDecision = route(prompt, systemPrompt, maxTokens, {
|
|
90039
|
+
...routerOpts,
|
|
90040
|
+
config: { ...routerOpts.config, strategy: shadow.strategy },
|
|
90041
|
+
routingProfile: routingProfile ?? void 0,
|
|
90042
|
+
hasTools,
|
|
90043
|
+
toolCount: tools?.length ?? 0,
|
|
90044
|
+
toolNames,
|
|
90045
|
+
requiresTools,
|
|
90046
|
+
hasVision,
|
|
90047
|
+
requiresStructuredOutput
|
|
90048
|
+
});
|
|
90049
|
+
pendingShadowComparison = {
|
|
90050
|
+
shadow: shadowDecision,
|
|
90051
|
+
hasTools,
|
|
90052
|
+
hasVision,
|
|
90053
|
+
requiresStructuredOutput
|
|
90054
|
+
};
|
|
90055
|
+
}
|
|
88594
90056
|
if (hasTools && routingDecision.tier === "SIMPLE") {
|
|
88595
90057
|
console.log(
|
|
88596
90058
|
`[ClawRouter] SIMPLE+tools: keeping agentic model ${routingDecision.model} (tools need reliable function-call support)`
|
|
@@ -88699,6 +90161,21 @@ async function proxyRequest(req, res, apiBase, payFetch, options, routerOpts, de
|
|
|
88699
90161
|
);
|
|
88700
90162
|
}
|
|
88701
90163
|
}
|
|
90164
|
+
if (pendingShadowComparison) {
|
|
90165
|
+
try {
|
|
90166
|
+
options.onShadowRouted?.({
|
|
90167
|
+
executed: routingDecision,
|
|
90168
|
+
shadow: pendingShadowComparison.shadow,
|
|
90169
|
+
sameModel: routingDecision.model === pendingShadowComparison.shadow.model,
|
|
90170
|
+
hasTools: pendingShadowComparison.hasTools,
|
|
90171
|
+
hasVision: pendingShadowComparison.hasVision,
|
|
90172
|
+
requiresStructuredOutput: pendingShadowComparison.requiresStructuredOutput
|
|
90173
|
+
});
|
|
90174
|
+
} catch (err) {
|
|
90175
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
90176
|
+
console.warn(`[ClawRouter] Shadow routing callback failed: ${message}`);
|
|
90177
|
+
}
|
|
90178
|
+
}
|
|
88702
90179
|
options.onRouted?.(routingDecision);
|
|
88703
90180
|
}
|
|
88704
90181
|
}
|
|
@@ -89046,35 +90523,64 @@ async function proxyRequest(req, res, apiBase, payFetch, options, routerOpts, de
|
|
|
89046
90523
|
const estimatedInputTokens = Math.ceil(body.length / 4);
|
|
89047
90524
|
const estimatedTotalTokens = estimatedInputTokens + maxTokens;
|
|
89048
90525
|
const tierConfigs = routingDecision.tierConfigs ?? routerOpts.config.tiers;
|
|
89049
|
-
const
|
|
89050
|
-
|
|
89051
|
-
|
|
89052
|
-
|
|
89053
|
-
|
|
89054
|
-
|
|
89055
|
-
|
|
89056
|
-
|
|
89057
|
-
|
|
89058
|
-
|
|
90526
|
+
const rankedCandidates = routingDecision.candidates ?? getFallbackChain(routingDecision.tier, tierConfigs);
|
|
90527
|
+
const selectedModel = routingDecision.model;
|
|
90528
|
+
const fullChain = prependStickyExplicitModel([
|
|
90529
|
+
selectedModel,
|
|
90530
|
+
...rankedCandidates.filter((model) => model !== selectedModel)
|
|
90531
|
+
]);
|
|
90532
|
+
const contextFiltered = filterCandidatesByCapacity(
|
|
90533
|
+
fullChain,
|
|
90534
|
+
estimatedInputTokens,
|
|
90535
|
+
maxTokens,
|
|
90536
|
+
(modelId2) => {
|
|
90537
|
+
const model = BLOCKRUN_MODEL_BY_ID.get(modelId2);
|
|
90538
|
+
return model ? { contextWindow: model.contextWindow, maxOutput: model.maxOutput } : void 0;
|
|
90539
|
+
}
|
|
89059
90540
|
);
|
|
90541
|
+
if (contextFiltered.length === 0) {
|
|
90542
|
+
const errPayload = JSON.stringify({
|
|
90543
|
+
error: {
|
|
90544
|
+
message: `No routed model can satisfy the requested context and output capacity (~${estimatedTotalTokens} tokens). Reduce the input or max_tokens and retry.`,
|
|
90545
|
+
type: "invalid_request_error",
|
|
90546
|
+
code: "context_capacity_exceeded"
|
|
90547
|
+
}
|
|
90548
|
+
});
|
|
90549
|
+
if (heartbeatInterval) {
|
|
90550
|
+
clearInterval(heartbeatInterval);
|
|
90551
|
+
heartbeatInterval = void 0;
|
|
90552
|
+
}
|
|
90553
|
+
if (headersSentEarly) {
|
|
90554
|
+
safeWrite(res, `data: ${errPayload}
|
|
90555
|
+
|
|
90556
|
+
data: [DONE]
|
|
90557
|
+
|
|
90558
|
+
`);
|
|
90559
|
+
res.end();
|
|
90560
|
+
} else {
|
|
90561
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
90562
|
+
res.end(errPayload);
|
|
90563
|
+
}
|
|
90564
|
+
completed = true;
|
|
90565
|
+
deduplicator.removeInflight(dedupKey);
|
|
90566
|
+
clearTimeout(timeoutId);
|
|
90567
|
+
req.removeListener("close", onClientClose);
|
|
90568
|
+
return;
|
|
90569
|
+
}
|
|
89060
90570
|
const contextExcluded = fullChain.filter((m) => !contextFiltered.includes(m));
|
|
89061
90571
|
if (contextExcluded.length > 0) {
|
|
89062
90572
|
console.log(
|
|
89063
90573
|
`[ClawRouter] Context filter (~${estimatedTotalTokens} tokens): excluded ${contextExcluded.join(", ")}`
|
|
89064
90574
|
);
|
|
89065
90575
|
}
|
|
89066
|
-
const excludeFiltered =
|
|
89067
|
-
filterByExcludeList(contextFiltered, excludeList)
|
|
89068
|
-
);
|
|
90576
|
+
const excludeFiltered = filterByExcludeList(contextFiltered, excludeList);
|
|
89069
90577
|
const excludeExcluded = contextFiltered.filter((m) => !excludeFiltered.includes(m));
|
|
89070
90578
|
if (excludeExcluded.length > 0) {
|
|
89071
90579
|
console.log(
|
|
89072
90580
|
`[ClawRouter] Exclude filter: excluded ${excludeExcluded.join(", ")} (user preference)`
|
|
89073
90581
|
);
|
|
89074
90582
|
}
|
|
89075
|
-
let toolFiltered =
|
|
89076
|
-
filterByToolCalling(excludeFiltered, hasTools, supportsToolCalling)
|
|
89077
|
-
);
|
|
90583
|
+
let toolFiltered = filterByToolCalling(excludeFiltered, hasTools, supportsToolCalling);
|
|
89078
90584
|
const toolExcluded = excludeFiltered.filter((m) => !toolFiltered.includes(m));
|
|
89079
90585
|
if (toolExcluded.length > 0) {
|
|
89080
90586
|
console.log(
|
|
@@ -89093,19 +90599,17 @@ async function proxyRequest(req, res, apiBase, payFetch, options, routerOpts, de
|
|
|
89093
90599
|
console.log(
|
|
89094
90600
|
`[ClawRouter] Tool-compliance filter: excluded ${dropped.join(", ")} (unreliable tool schema handling)`
|
|
89095
90601
|
);
|
|
89096
|
-
toolFiltered =
|
|
90602
|
+
toolFiltered = compliant;
|
|
89097
90603
|
}
|
|
89098
90604
|
}
|
|
89099
|
-
const visionFiltered =
|
|
89100
|
-
filterByVision(toolFiltered, hasVision, supportsVision)
|
|
89101
|
-
);
|
|
90605
|
+
const visionFiltered = filterByVision(toolFiltered, hasVision, supportsVision);
|
|
89102
90606
|
const visionExcluded = toolFiltered.filter((m) => !visionFiltered.includes(m));
|
|
89103
90607
|
if (visionExcluded.length > 0) {
|
|
89104
90608
|
console.log(
|
|
89105
90609
|
`[ClawRouter] Vision filter: excluded ${visionExcluded.join(", ")} (no vision support)`
|
|
89106
90610
|
);
|
|
89107
90611
|
}
|
|
89108
|
-
modelsToTry =
|
|
90612
|
+
modelsToTry = visionFiltered.slice(0, MAX_FALLBACK_ATTEMPTS);
|
|
89109
90613
|
modelsToTry = prioritizeNonRateLimited(modelsToTry);
|
|
89110
90614
|
} else {
|
|
89111
90615
|
modelsToTry = modelId ? [modelId] : [];
|
|
@@ -89995,7 +91499,7 @@ var init_proxy = __esm({
|
|
|
89995
91499
|
init_client2();
|
|
89996
91500
|
init_esm5();
|
|
89997
91501
|
init_router();
|
|
89998
|
-
|
|
91502
|
+
init_router();
|
|
89999
91503
|
init_models();
|
|
90000
91504
|
init_max_tokens();
|
|
90001
91505
|
init_logger();
|
|
@@ -90009,7 +91513,7 @@ var init_proxy = __esm({
|
|
|
90009
91513
|
init_session();
|
|
90010
91514
|
init_updater();
|
|
90011
91515
|
init_exclude_models();
|
|
90012
|
-
|
|
91516
|
+
init_config();
|
|
90013
91517
|
init_journal();
|
|
90014
91518
|
init_upstream_proxy();
|
|
90015
91519
|
init_textual_tool_calls();
|
|
@@ -90036,8 +91540,6 @@ var init_proxy = __esm({
|
|
|
90036
91540
|
"free/gpt-oss-20b",
|
|
90037
91541
|
"free/deepseek-v4-flash",
|
|
90038
91542
|
// 1M ctx; slow (~10 tok/s, 07-28 probe) but completes
|
|
90039
|
-
"free/seed-oss-36b",
|
|
90040
|
-
// live coder (successor to retired qwen3-coder-480b)
|
|
90041
91543
|
"free/mistral-nemotron",
|
|
90042
91544
|
// strong instruction following
|
|
90043
91545
|
"free/step-3.7-flash",
|
|
@@ -91643,7 +93145,7 @@ var init_headers = __esm({
|
|
|
91643
93145
|
|
|
91644
93146
|
// node_modules/@polymarket/clob-client-v2/dist/config.js
|
|
91645
93147
|
var AMOY_CONTRACTS, MATIC_CONTRACTS, COLLATERAL_TOKEN_DECIMALS, getContractConfig;
|
|
91646
|
-
var
|
|
93148
|
+
var init_config2 = __esm({
|
|
91647
93149
|
"node_modules/@polymarket/clob-client-v2/dist/config.js"() {
|
|
91648
93150
|
"use strict";
|
|
91649
93151
|
AMOY_CONTRACTS = {
|
|
@@ -91943,7 +93445,7 @@ var init_buildMarketOrderCreationArgs = __esm({
|
|
|
91943
93445
|
"node_modules/@polymarket/clob-client-v2/dist/order-builder/helpers/buildMarketOrderCreationArgs.js"() {
|
|
91944
93446
|
"use strict";
|
|
91945
93447
|
init_constants2();
|
|
91946
|
-
|
|
93448
|
+
init_config2();
|
|
91947
93449
|
init_getMarketOrderRawAmounts();
|
|
91948
93450
|
init_esm();
|
|
91949
93451
|
}
|
|
@@ -92504,7 +94006,7 @@ var init_createMarketOrder = __esm({
|
|
|
92504
94006
|
"node_modules/@polymarket/clob-client-v2/dist/order-builder/helpers/createMarketOrder.js"() {
|
|
92505
94007
|
"use strict";
|
|
92506
94008
|
init_signer();
|
|
92507
|
-
|
|
94009
|
+
init_config2();
|
|
92508
94010
|
init_buildMarketOrderCreationArgs();
|
|
92509
94011
|
init_signatureTypeV2();
|
|
92510
94012
|
init_buildOrder();
|
|
@@ -92612,7 +94114,7 @@ var init_buildOrderCreationArgs = __esm({
|
|
|
92612
94114
|
"node_modules/@polymarket/clob-client-v2/dist/order-builder/helpers/buildOrderCreationArgs.js"() {
|
|
92613
94115
|
"use strict";
|
|
92614
94116
|
init_constants2();
|
|
92615
|
-
|
|
94117
|
+
init_config2();
|
|
92616
94118
|
init_getOrderRawAmounts();
|
|
92617
94119
|
init_esm();
|
|
92618
94120
|
}
|
|
@@ -92624,7 +94126,7 @@ var init_createOrder = __esm({
|
|
|
92624
94126
|
"node_modules/@polymarket/clob-client-v2/dist/order-builder/helpers/createOrder.js"() {
|
|
92625
94127
|
"use strict";
|
|
92626
94128
|
init_signer();
|
|
92627
|
-
|
|
94129
|
+
init_config2();
|
|
92628
94130
|
init_signatureTypeV2();
|
|
92629
94131
|
init_buildOrder();
|
|
92630
94132
|
init_buildOrderCreationArgs();
|
|
@@ -92662,7 +94164,7 @@ var init_createExchangeV3OrderFromAmounts = __esm({
|
|
|
92662
94164
|
"use strict";
|
|
92663
94165
|
init_constants2();
|
|
92664
94166
|
init_signer();
|
|
92665
|
-
|
|
94167
|
+
init_config2();
|
|
92666
94168
|
init_signatureTypeV2();
|
|
92667
94169
|
init_buildOrder();
|
|
92668
94170
|
createExchangeV3OrderFromAmounts = async (eoaSigner, chainId, signatureType, funderAddress, userOrder) => {
|
|
@@ -110464,7 +111966,7 @@ var init_axios2 = __esm({
|
|
|
110464
111966
|
|
|
110465
111967
|
// node_modules/browser-or-node/dist/index.mjs
|
|
110466
111968
|
var isBrowser, isNode, isWebWorker, isJsDom, isDeno, isBun;
|
|
110467
|
-
var
|
|
111969
|
+
var init_dist2 = __esm({
|
|
110468
111970
|
"node_modules/browser-or-node/dist/index.mjs"() {
|
|
110469
111971
|
"use strict";
|
|
110470
111972
|
isBrowser = typeof window !== "undefined" && typeof window.document !== "undefined";
|
|
@@ -110488,7 +111990,7 @@ var init_http_helpers = __esm({
|
|
|
110488
111990
|
"node_modules/@polymarket/clob-client-v2/dist/http-helpers/index.js"() {
|
|
110489
111991
|
"use strict";
|
|
110490
111992
|
init_axios2();
|
|
110491
|
-
|
|
111993
|
+
init_dist2();
|
|
110492
111994
|
GET = "GET";
|
|
110493
111995
|
POST = "POST";
|
|
110494
111996
|
DELETE = "DELETE";
|
|
@@ -111520,10 +113022,10 @@ var init_client4 = __esm({
|
|
|
111520
113022
|
});
|
|
111521
113023
|
|
|
111522
113024
|
// node_modules/@polymarket/clob-client-v2/dist/index.js
|
|
111523
|
-
var
|
|
113025
|
+
var init_dist3 = __esm({
|
|
111524
113026
|
"node_modules/@polymarket/clob-client-v2/dist/index.js"() {
|
|
111525
113027
|
"use strict";
|
|
111526
|
-
|
|
113028
|
+
init_config2();
|
|
111527
113029
|
init_signatureTypeV2();
|
|
111528
113030
|
init_side();
|
|
111529
113031
|
init_clob();
|
|
@@ -111543,7 +113045,7 @@ import * as net from "net";
|
|
|
111543
113045
|
import * as http4 from "http";
|
|
111544
113046
|
import { Agent as HttpsAgent } from "https";
|
|
111545
113047
|
var INTERNAL, Agent2;
|
|
111546
|
-
var
|
|
113048
|
+
var init_dist4 = __esm({
|
|
111547
113049
|
"node_modules/agent-base/dist/index.js"() {
|
|
111548
113050
|
"use strict";
|
|
111549
113051
|
init_helpers();
|
|
@@ -111782,7 +113284,7 @@ function createNegotiateAuth() {
|
|
|
111782
113284
|
};
|
|
111783
113285
|
};
|
|
111784
113286
|
}
|
|
111785
|
-
var
|
|
113287
|
+
var init_dist5 = __esm({
|
|
111786
113288
|
"node_modules/proxy-agent-negotiate/dist/index.js"() {
|
|
111787
113289
|
"use strict";
|
|
111788
113290
|
}
|
|
@@ -111809,13 +113311,13 @@ function omit(obj, ...keys) {
|
|
|
111809
113311
|
return ret;
|
|
111810
113312
|
}
|
|
111811
113313
|
var import_debug2, debug2, setServernameFromNonIpHost, HttpsProxyAgent2;
|
|
111812
|
-
var
|
|
113314
|
+
var init_dist6 = __esm({
|
|
111813
113315
|
"node_modules/https-proxy-agent/dist/index.js"() {
|
|
111814
113316
|
"use strict";
|
|
111815
113317
|
import_debug2 = __toESM(require_src(), 1);
|
|
111816
|
-
init_dist3();
|
|
111817
|
-
init_parse_proxy_response();
|
|
111818
113318
|
init_dist4();
|
|
113319
|
+
init_parse_proxy_response();
|
|
113320
|
+
init_dist5();
|
|
111819
113321
|
debug2 = (0, import_debug2.default)("https-proxy-agent");
|
|
111820
113322
|
setServernameFromNonIpHost = (options) => {
|
|
111821
113323
|
if (options.servername === void 0 && options.host && !net2.isIP(options.host)) {
|
|
@@ -112028,7 +113530,7 @@ var POLYGON_CHAIN_ID, CTF_EXCHANGE_V2, NEG_RISK_CTF_EXCHANGE_V2, NEG_RISK_ADAPTE
|
|
|
112028
113530
|
var init_constants3 = __esm({
|
|
112029
113531
|
"src/polymarket/constants.ts"() {
|
|
112030
113532
|
"use strict";
|
|
112031
|
-
|
|
113533
|
+
init_dist3();
|
|
112032
113534
|
POLYGON_CHAIN_ID = 137;
|
|
112033
113535
|
CTF_EXCHANGE_V2 = "0xE111180000d2663C0091e4f400237545B87B996B";
|
|
112034
113536
|
NEG_RISK_CTF_EXCHANGE_V2 = "0xe2222d279d744050d28e00520010520000310F59";
|
|
@@ -112565,11 +114067,11 @@ var init_client5 = __esm({
|
|
|
112565
114067
|
"src/polymarket/client.ts"() {
|
|
112566
114068
|
"use strict";
|
|
112567
114069
|
init_axios2();
|
|
112568
|
-
|
|
114070
|
+
init_dist6();
|
|
112569
114071
|
init_esm();
|
|
112570
114072
|
init_accounts();
|
|
112571
114073
|
init_chains();
|
|
112572
|
-
|
|
114074
|
+
init_dist3();
|
|
112573
114075
|
init_wallet_adapter();
|
|
112574
114076
|
init_constants3();
|
|
112575
114077
|
init_creds();
|
|
@@ -112939,7 +114441,7 @@ var ledger;
|
|
|
112939
114441
|
var init_orders = __esm({
|
|
112940
114442
|
"src/polymarket/orders.ts"() {
|
|
112941
114443
|
"use strict";
|
|
112942
|
-
|
|
114444
|
+
init_dist3();
|
|
112943
114445
|
init_client5();
|
|
112944
114446
|
init_constants3();
|
|
112945
114447
|
init_creds();
|
|
@@ -220121,7 +221623,7 @@ var init_relayer = __esm({
|
|
|
220121
221623
|
"use strict";
|
|
220122
221624
|
import_builder_relayer_client = __toESM(require_dist3(), 1);
|
|
220123
221625
|
import_builder_signing_sdk = __toESM(require_dist4(), 1);
|
|
220124
|
-
|
|
221626
|
+
init_dist3();
|
|
220125
221627
|
init_esm();
|
|
220126
221628
|
init_chains();
|
|
220127
221629
|
init_client5();
|
|
@@ -220461,7 +221963,7 @@ var init_setup = __esm({
|
|
|
220461
221963
|
"use strict";
|
|
220462
221964
|
init_esm();
|
|
220463
221965
|
init_chains();
|
|
220464
|
-
|
|
221966
|
+
init_dist3();
|
|
220465
221967
|
init_client5();
|
|
220466
221968
|
init_constants3();
|
|
220467
221969
|
init_creds();
|
|
@@ -220915,7 +222417,7 @@ function sleep2(ms) {
|
|
|
220915
222417
|
return new Promise((r2) => setTimeout(r2, ms));
|
|
220916
222418
|
}
|
|
220917
222419
|
var BlockrunError, PaymentError, APIError, BASE_CHAIN_ID2, USDC_BASE2, USDC_DOMAIN, TRANSFER_TYPES, BLOCKRUN_SERVICE_CODE2, LOCALHOST_DOMAINS, BLOCKRUN_DIR2, COST_LOG_FILE, SDK_VERSION, USER_AGENT2, DEFAULT_TIMEOUT, PHONE_PRICES, DEFAULT_API_URL13, DEFAULT_TIMEOUT13, DEFAULT_POLL_INTERVAL_MS, DEFAULT_POLL_BUDGET_MS, MAX_SIGNED_AUTH_SECONDS, BlockrunClient, WALLET_DIR2, WALLET_FILE3, WALLET_DIR22, SOLANA_WALLET_FILE, CACHE_DIR, DATA_DIR, COST_LOG_FILE2, DEFAULT_TTL;
|
|
220918
|
-
var
|
|
222420
|
+
var init_dist7 = __esm({
|
|
220919
222421
|
"node_modules/@blockrun/llm/dist/index.js"() {
|
|
220920
222422
|
"use strict";
|
|
220921
222423
|
init_accounts();
|
|
@@ -221483,7 +222985,7 @@ var init_fund = __esm({
|
|
|
221483
222985
|
"src/polymarket/fund.ts"() {
|
|
221484
222986
|
"use strict";
|
|
221485
222987
|
init_axios2();
|
|
221486
|
-
|
|
222988
|
+
init_dist7();
|
|
221487
222989
|
init_wallet_adapter();
|
|
221488
222990
|
init_client5();
|
|
221489
222991
|
init_constants3();
|
|
@@ -221962,29 +223464,29 @@ var init_spend_control = __esm({
|
|
|
221962
223464
|
getLimits() {
|
|
221963
223465
|
return { ...this.limits };
|
|
221964
223466
|
}
|
|
221965
|
-
check(
|
|
223467
|
+
check(estimatedCost2) {
|
|
221966
223468
|
const now2 = this.now();
|
|
221967
223469
|
if (this.limits.perRequest !== void 0) {
|
|
221968
|
-
if (
|
|
223470
|
+
if (estimatedCost2 > this.limits.perRequest) {
|
|
221969
223471
|
return {
|
|
221970
223472
|
allowed: false,
|
|
221971
223473
|
blockedBy: "perRequest",
|
|
221972
223474
|
remaining: this.limits.perRequest,
|
|
221973
|
-
reason: `Per-request limit exceeded: $${
|
|
223475
|
+
reason: `Per-request limit exceeded: $${estimatedCost2.toFixed(4)} > $${this.limits.perRequest.toFixed(2)} max`
|
|
221974
223476
|
};
|
|
221975
223477
|
}
|
|
221976
223478
|
}
|
|
221977
223479
|
if (this.limits.hourly !== void 0) {
|
|
221978
223480
|
const hourlySpent = this.getSpendingInWindow(now2 - HOUR_MS, now2);
|
|
221979
223481
|
const remaining = this.limits.hourly - hourlySpent;
|
|
221980
|
-
if (
|
|
223482
|
+
if (estimatedCost2 > remaining) {
|
|
221981
223483
|
const oldestInWindow = this.history.find((r2) => r2.timestamp >= now2 - HOUR_MS);
|
|
221982
223484
|
const resetIn = oldestInWindow ? Math.ceil((oldestInWindow.timestamp + HOUR_MS - now2) / 1e3) : 0;
|
|
221983
223485
|
return {
|
|
221984
223486
|
allowed: false,
|
|
221985
223487
|
blockedBy: "hourly",
|
|
221986
223488
|
remaining,
|
|
221987
|
-
reason: `Hourly limit exceeded: $${(hourlySpent +
|
|
223489
|
+
reason: `Hourly limit exceeded: $${(hourlySpent + estimatedCost2).toFixed(2)} > $${this.limits.hourly.toFixed(2)} max`,
|
|
221988
223490
|
resetIn
|
|
221989
223491
|
};
|
|
221990
223492
|
}
|
|
@@ -221992,26 +223494,26 @@ var init_spend_control = __esm({
|
|
|
221992
223494
|
if (this.limits.daily !== void 0) {
|
|
221993
223495
|
const dailySpent = this.getSpendingInWindow(now2 - DAY_MS, now2);
|
|
221994
223496
|
const remaining = this.limits.daily - dailySpent;
|
|
221995
|
-
if (
|
|
223497
|
+
if (estimatedCost2 > remaining) {
|
|
221996
223498
|
const oldestInWindow = this.history.find((r2) => r2.timestamp >= now2 - DAY_MS);
|
|
221997
223499
|
const resetIn = oldestInWindow ? Math.ceil((oldestInWindow.timestamp + DAY_MS - now2) / 1e3) : 0;
|
|
221998
223500
|
return {
|
|
221999
223501
|
allowed: false,
|
|
222000
223502
|
blockedBy: "daily",
|
|
222001
223503
|
remaining,
|
|
222002
|
-
reason: `Daily limit exceeded: $${(dailySpent +
|
|
223504
|
+
reason: `Daily limit exceeded: $${(dailySpent + estimatedCost2).toFixed(2)} > $${this.limits.daily.toFixed(2)} max`,
|
|
222003
223505
|
resetIn
|
|
222004
223506
|
};
|
|
222005
223507
|
}
|
|
222006
223508
|
}
|
|
222007
223509
|
if (this.limits.session !== void 0) {
|
|
222008
223510
|
const remaining = this.limits.session - this.sessionSpent;
|
|
222009
|
-
if (
|
|
223511
|
+
if (estimatedCost2 > remaining) {
|
|
222010
223512
|
return {
|
|
222011
223513
|
allowed: false,
|
|
222012
223514
|
blockedBy: "session",
|
|
222013
223515
|
remaining,
|
|
222014
|
-
reason: `Session limit exceeded: $${(this.sessionSpent +
|
|
223516
|
+
reason: `Session limit exceeded: $${(this.sessionSpent + estimatedCost2).toFixed(2)} > $${this.limits.session.toFixed(2)} max`
|
|
222015
223517
|
};
|
|
222016
223518
|
}
|
|
222017
223519
|
}
|
|
@@ -222687,6 +224189,11 @@ async function startProxyInBackground(api, startupGeneration) {
|
|
|
222687
224189
|
`[${decision.tier}] ${decision.model} $${cost} (saved ${saved}%) | ${decision.reasoning}`
|
|
222688
224190
|
);
|
|
222689
224191
|
},
|
|
224192
|
+
onShadowRouted: (comparison) => {
|
|
224193
|
+
api.logger.info(
|
|
224194
|
+
`[router-shadow] executed=${comparison.executed.model} (${comparison.executed.method}) candidate=${comparison.shadow.model} (${comparison.shadow.method}) same=${comparison.sameModel} tools=${comparison.hasTools} vision=${comparison.hasVision} structured=${comparison.requiresStructuredOutput}`
|
|
224195
|
+
);
|
|
224196
|
+
},
|
|
222690
224197
|
onLowBalance: (info) => {
|
|
222691
224198
|
api.logger.warn(`[!] Low balance: ${info.balanceUSD}. Fund wallet: ${info.walletAddress}`);
|
|
222692
224199
|
},
|
|
@@ -223884,6 +225391,7 @@ export {
|
|
|
223884
225391
|
deriveEvmKey,
|
|
223885
225392
|
deriveSolanaKeyBytes,
|
|
223886
225393
|
fetchWithRetry,
|
|
225394
|
+
filterCandidatesByCapacity,
|
|
223887
225395
|
formatDuration,
|
|
223888
225396
|
formatStatsAscii,
|
|
223889
225397
|
generateWalletMnemonic,
|
|
@@ -223896,6 +225404,7 @@ export {
|
|
|
223896
225404
|
getSessionId,
|
|
223897
225405
|
getStats,
|
|
223898
225406
|
hashRequestContent,
|
|
225407
|
+
inferToolRequirement,
|
|
223899
225408
|
injectAuthProfile,
|
|
223900
225409
|
injectModelsConfig,
|
|
223901
225410
|
isAgenticModel,
|