@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/cli.js
CHANGED
|
@@ -33163,7 +33163,7 @@ var init_esm5 = __esm({
|
|
|
33163
33163
|
}
|
|
33164
33164
|
});
|
|
33165
33165
|
|
|
33166
|
-
//
|
|
33166
|
+
// node_modules/@blockrun/router-core/dist/index.js
|
|
33167
33167
|
function scoreTokenCount(estimatedTokens, thresholds) {
|
|
33168
33168
|
if (estimatedTokens < thresholds.simple) {
|
|
33169
33169
|
return { name: "tokenCount", score: -1, signal: `short (${estimatedTokens} tokens)` };
|
|
@@ -33403,13 +33403,6 @@ function classifyByRules(prompt, systemPrompt, estimatedTokens, config) {
|
|
|
33403
33403
|
function calibrateConfidence(distance, steepness) {
|
|
33404
33404
|
return 1 / (1 + Math.exp(-steepness * distance));
|
|
33405
33405
|
}
|
|
33406
|
-
var init_rules = __esm({
|
|
33407
|
-
"src/router/rules.ts"() {
|
|
33408
|
-
"use strict";
|
|
33409
|
-
}
|
|
33410
|
-
});
|
|
33411
|
-
|
|
33412
|
-
// src/router/selector.ts
|
|
33413
33406
|
function selectModel(tier, confidence, method, reasoning, tierConfigs, modelPricing, estimatedInputTokens, maxOutputTokens, routingProfile, agenticScore) {
|
|
33414
33407
|
const tierConfig = tierConfigs[tier];
|
|
33415
33408
|
const model = tierConfig.primary;
|
|
@@ -33498,19 +33491,14 @@ function getFallbackChainFiltered(tier, tierConfigs, estimatedTotalTokens, getCo
|
|
|
33498
33491
|
}
|
|
33499
33492
|
return filtered;
|
|
33500
33493
|
}
|
|
33501
|
-
|
|
33502
|
-
|
|
33503
|
-
|
|
33504
|
-
|
|
33505
|
-
|
|
33506
|
-
|
|
33507
|
-
|
|
33508
|
-
|
|
33509
|
-
MIN_PAYMENT_USD = 1e-3;
|
|
33510
|
-
}
|
|
33511
|
-
});
|
|
33512
|
-
|
|
33513
|
-
// src/router/strategy.ts
|
|
33494
|
+
function filterCandidatesByCapacity(models, estimatedInputTokens, requestedOutputTokens, getCapabilities2) {
|
|
33495
|
+
const filtered = models.filter((modelId) => {
|
|
33496
|
+
const capabilities = getCapabilities2(modelId);
|
|
33497
|
+
if (!capabilities) return true;
|
|
33498
|
+
return capabilities.contextWindow >= (estimatedInputTokens + requestedOutputTokens) * 1.1 && capabilities.maxOutput >= requestedOutputTokens;
|
|
33499
|
+
});
|
|
33500
|
+
return filtered;
|
|
33501
|
+
}
|
|
33514
33502
|
function applyPromotions(tierConfigs, promotions, profile, now2 = /* @__PURE__ */ new Date()) {
|
|
33515
33503
|
if (!promotions || promotions.length === 0) return tierConfigs;
|
|
33516
33504
|
let result = tierConfigs;
|
|
@@ -33540,19 +33528,666 @@ function getStrategy(name) {
|
|
|
33540
33528
|
}
|
|
33541
33529
|
return strategy;
|
|
33542
33530
|
}
|
|
33543
|
-
|
|
33544
|
-
|
|
33545
|
-
|
|
33531
|
+
function registerStrategy(strategy) {
|
|
33532
|
+
registry.set(strategy.name, strategy);
|
|
33533
|
+
}
|
|
33534
|
+
function inferToolRequirement(prompt, _systemPrompt, toolChoice) {
|
|
33535
|
+
if (toolChoice === "none") return false;
|
|
33536
|
+
if (toolChoice === "required") return true;
|
|
33537
|
+
if (typeof toolChoice === "object" && toolChoice !== null && toolChoice.type === "function") {
|
|
33538
|
+
return true;
|
|
33539
|
+
}
|
|
33540
|
+
const text = prompt;
|
|
33541
|
+
const explicitTool = /\b(?:use|call|invoke)\s+(?:the\s+)?[\w.-]+\s+(?:tool|function|api)\b|\btool[_ -]?call\b|使用.{0,20}(?:工具|函数|接口)|调用.{0,20}(?:工具|函数|接口)/i;
|
|
33542
|
+
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;
|
|
33543
|
+
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;
|
|
33544
|
+
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;
|
|
33545
|
+
return explicitTool.test(text) || codeEnvironment.test(text) || webAction.test(text) || statefulAction.test(text);
|
|
33546
|
+
}
|
|
33547
|
+
function likelyNeedsParallelToolCalls(prompt, needsTools, toolCount, toolNames) {
|
|
33548
|
+
if (!needsTools || toolCount === void 0 || toolCount < 1) return false;
|
|
33549
|
+
const text = prompt.trim();
|
|
33550
|
+
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(
|
|
33551
|
+
text
|
|
33552
|
+
);
|
|
33553
|
+
if (explicitRepeat) return true;
|
|
33554
|
+
const sentenceClauses = text.split(/[.!?。!?]+/).map((part) => part.trim()).filter((part) => part.length >= 8);
|
|
33555
|
+
if (/\b(?:also|additionally|furthermore)\b|另外|此外|그리고/i.test(text) && sentenceClauses.length >= 2 || /\band\s+(?:also|for the)\b/i.test(text))
|
|
33556
|
+
return true;
|
|
33557
|
+
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(
|
|
33558
|
+
text
|
|
33559
|
+
);
|
|
33560
|
+
if (pairedQuantity) return true;
|
|
33561
|
+
const operationTokens = /* @__PURE__ */ new Set([
|
|
33562
|
+
"add",
|
|
33563
|
+
"delete",
|
|
33564
|
+
"remove",
|
|
33565
|
+
"cancel",
|
|
33566
|
+
"return",
|
|
33567
|
+
"exchange",
|
|
33568
|
+
"modify",
|
|
33569
|
+
"book",
|
|
33570
|
+
"transfer",
|
|
33571
|
+
"send",
|
|
33572
|
+
"upload",
|
|
33573
|
+
"download",
|
|
33574
|
+
"create",
|
|
33575
|
+
"close"
|
|
33576
|
+
]);
|
|
33577
|
+
const lowered = text.toLowerCase();
|
|
33578
|
+
const matchedOperationTokens = new Set(
|
|
33579
|
+
(toolNames ?? []).flatMap((name) => name.toLowerCase().split(/[^a-z0-9\u3400-\u9fff]+/)).filter((token) => operationTokens.has(token) && lowered.includes(token))
|
|
33580
|
+
);
|
|
33581
|
+
if (matchedOperationTokens.size >= 2) return true;
|
|
33582
|
+
const nonEmptyLines = text.split(/\r?\n/).map((line) => line.trim()).filter(Boolean);
|
|
33583
|
+
const quantityMentions = text.match(
|
|
33584
|
+
/\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
|
|
33585
|
+
) ?? [];
|
|
33586
|
+
if (nonEmptyLines.length >= 2 && quantityMentions.length >= 2) return true;
|
|
33587
|
+
const repeatedLookup = /\b(?:weather|climate|clima|tiempo|temperature|snow|news|report)\b|天气|气象|温度|降雪|新闻|报告/i.test(
|
|
33588
|
+
text
|
|
33589
|
+
);
|
|
33590
|
+
const multiLocationConnector = /\b(?:and also|both|y|e)\b|还有|以及|和|、/i.test(text);
|
|
33591
|
+
const commaSeparatedLocations = (text.match(/[,,]/g) ?? []).length >= 2;
|
|
33592
|
+
if (repeatedLookup && (multiLocationConnector || commaSeparatedLocations)) return true;
|
|
33593
|
+
const distinctOrderParts = /\b(?:food|meal)\b[\s\S]*\bdrink\b|\bdrink\b[\s\S]*\b(?:food|meal)\b/i.test(text);
|
|
33594
|
+
const koreanParallelClauses = (text.match(/,/g) ?? []).length >= 3 && /하고|그리고/.test(text);
|
|
33595
|
+
return distinctOrderParts || koreanParallelClauses;
|
|
33596
|
+
}
|
|
33597
|
+
function classifyTask(prompt, systemPrompt, options) {
|
|
33598
|
+
const fullText = `${systemPrompt ?? ""} ${prompt}`;
|
|
33599
|
+
const estimatedInputTokens = Math.ceil(fullText.length / 4);
|
|
33600
|
+
const scanLimit = Math.max(1, Math.min(8e3, options.config.classifier.promptTruncationChars));
|
|
33601
|
+
const sample = (value) => {
|
|
33602
|
+
if (value.length <= scanLimit) return value;
|
|
33603
|
+
const prefixLength = Math.ceil(scanLimit / 2);
|
|
33604
|
+
return `${value.slice(0, prefixLength)}
|
|
33605
|
+
${value.slice(-(scanLimit - prefixLength))}`;
|
|
33606
|
+
};
|
|
33607
|
+
const scannedPrompt = sample(prompt);
|
|
33608
|
+
const scannedSystemPrompt = sample(systemPrompt ?? "");
|
|
33609
|
+
const scannedFullText = `${scannedSystemPrompt} ${scannedPrompt}`;
|
|
33610
|
+
const text = scannedPrompt.toLowerCase();
|
|
33611
|
+
const explicitCodeSignal = /```|\b(?:typescript|javascript|python|rust|java|sql|stack trace|traceback|exception)\b|\.(?:ts|tsx|js|py|go|rs)\b/i.test(
|
|
33612
|
+
scannedPrompt
|
|
33613
|
+
);
|
|
33614
|
+
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(
|
|
33615
|
+
scannedPrompt
|
|
33616
|
+
);
|
|
33617
|
+
const nativeCodeSignal = /\b(?:programmed|written|implemented?|code)\s+(?:in|using)\s+(?:c\+\+|c|rust|go)\b/i.test(
|
|
33618
|
+
scannedPrompt
|
|
33619
|
+
);
|
|
33620
|
+
const hasCode = explicitCodeSignal || codeConstructSignal || nativeCodeSignal;
|
|
33621
|
+
const toolsAvailable = options.hasTools ?? false;
|
|
33622
|
+
const needsTools = options.requiresTools ?? (toolsAvailable && inferToolRequirement(scannedPrompt, scannedSystemPrompt));
|
|
33623
|
+
const likelyParallelToolCalls = likelyNeedsParallelToolCalls(
|
|
33624
|
+
scannedPrompt,
|
|
33625
|
+
needsTools,
|
|
33626
|
+
options.toolCount,
|
|
33627
|
+
options.toolNames
|
|
33628
|
+
);
|
|
33629
|
+
const normalizedToolNames = (options.toolNames ?? []).map((name) => name.toLowerCase());
|
|
33630
|
+
const airlineToolSignal = normalizedToolNames.some(
|
|
33631
|
+
(name) => /(?:flight|reservation|airport|baggage|passenger)/.test(name)
|
|
33632
|
+
);
|
|
33633
|
+
const retailToolSignal = normalizedToolNames.some(
|
|
33634
|
+
(name) => /(?:order|product|item|return|exchange|address)/.test(name)
|
|
33635
|
+
);
|
|
33636
|
+
const webResearchToolSignal = normalizedToolNames.some(
|
|
33637
|
+
(name) => /^(?:web_?search|web_?fetch)$/.test(name)
|
|
33638
|
+
);
|
|
33639
|
+
const agentDomain = airlineToolSignal && !retailToolSignal ? "airline" : retailToolSignal && !airlineToolSignal ? "retail" : webResearchToolSignal ? "web_research" : "other";
|
|
33640
|
+
const clueConnectors = scannedFullText.match(
|
|
33641
|
+
/\b(?:after|before|while|where|whose|which|in \d{4}|as of|over \d+|another|also|furthermore)\b|(?:之后|之前|其中|截至|超过|另一个|此外)/gi
|
|
33642
|
+
) ?? [];
|
|
33643
|
+
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(
|
|
33644
|
+
scannedFullText
|
|
33645
|
+
);
|
|
33646
|
+
const exactAnswerSignal = /\b(?:exact answer|single best-supported answer|following clues|multiple public sources)\b|(?:精确答案|根据.*线索|多个公开来源)/i.test(
|
|
33647
|
+
scannedFullText
|
|
33648
|
+
);
|
|
33649
|
+
const deepWebResearch = agentDomain === "web_research" && (exactAnswerSignal || entityResolutionSignal && (clueConnectors.length >= 3 || prompt.length >= 320));
|
|
33650
|
+
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(
|
|
33651
|
+
scannedPrompt
|
|
33652
|
+
);
|
|
33653
|
+
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(
|
|
33654
|
+
scannedPrompt
|
|
33655
|
+
);
|
|
33656
|
+
const globalChoiceSignal = globalOptimizationSignal || globalScopeSignal;
|
|
33657
|
+
const crossRecordSignal = /\b(?:another|other|different|previous)\s+(?:order|reservation|booking|account|address)\b|另一(?:个)?(?:订单|预订|账户|地址)|其他(?:订单|预订|账户|地址)/i.test(
|
|
33658
|
+
scannedPrompt
|
|
33659
|
+
);
|
|
33660
|
+
const reservationIds = scannedPrompt.match(/\b[A-Z0-9]{6}\b/g) ?? [];
|
|
33661
|
+
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(
|
|
33662
|
+
scannedPrompt
|
|
33663
|
+
) || new Set(reservationIds).size >= 2);
|
|
33664
|
+
const conditionalGlobalWorkflowSignal = agentDomain === "airline" && globalScopeSignal && /\b(?:if|that (?:contain|have)|longer than|shorter than|under|over|at (?:most|least)|wherever possible)\b|如果|超过|少于|不超过|尽可能/i.test(
|
|
33665
|
+
scannedPrompt
|
|
33666
|
+
) && /\b(?:cancel|change|upgrade|move|book)\b[\s\S]*\b(?:cancel|change|upgrade|move|book)\b|取消[\s\S]*(?:升级|更改)|升级[\s\S]*(?:取消|更改)/i.test(
|
|
33667
|
+
scannedPrompt
|
|
33668
|
+
);
|
|
33669
|
+
const policyExceptionSignal = agentDomain === "retail" && /\b(?:return|refund|send back|get (?:my |the )?money back)\b|退货|退款|退回/i.test(
|
|
33670
|
+
scannedPrompt
|
|
33671
|
+
) && /\b(?:amex|american express|visa|mastercard|credit card|debit card|different card|another card|other card)\b|信用卡|借记卡|其他卡|另一张卡/i.test(
|
|
33672
|
+
scannedPrompt
|
|
33673
|
+
);
|
|
33674
|
+
const singleSelectedPolicyException = policyExceptionSignal && /\b(?:return|refund|send back)\b[^.!?。!?]{0,96}\b(?:the )?(?:pricier|cheaper|more expensive|less expensive|costlier|one)\b/i.test(
|
|
33675
|
+
scannedPrompt
|
|
33676
|
+
);
|
|
33677
|
+
const negotiatedWorkflowSignal = agentDomain === "retail" && /\b(?:return|exchange)\b|退货|退回|换货|交换/i.test(scannedPrompt);
|
|
33678
|
+
const numberedSteps = (scannedPrompt.match(/(?:^|\s)\d+(?:\.\d+)*[.)]\s+/g) ?? []).length;
|
|
33679
|
+
const complexMultiToolPlan = likelyParallelToolCalls && ((options.toolCount ?? 0) >= 6 || numberedSteps >= 3 || prompt.length > 1200);
|
|
33680
|
+
let agentRisk = needsTools && singleSelectedPolicyException ? "policy_exception_simple" : needsTools && policyExceptionSignal ? "policy_exception" : (
|
|
33681
|
+
// Airline prompts that require a global optimum (for example the
|
|
33682
|
+
// cheapest itinerary across several candidates) are materially harder
|
|
33683
|
+
// than applying one change to every passenger in a known reservation.
|
|
33684
|
+
// Full-session evidence supports Sonnet for the former, while upgrading
|
|
33685
|
+
// the latter merely because it says "all passengers" caused a large cost
|
|
33686
|
+
// increase without a quality gain.
|
|
33687
|
+
needsTools && agentDomain === "airline" && (globalOptimizationSignal || conditionalGlobalWorkflowSignal) ? "complex_high" : needsTools && (likelyParallelToolCalls || globalChoiceSignal || crossRecordSignal || crossReservationBatchSignal || negotiatedWorkflowSignal) ? "high" : "standard"
|
|
33688
|
+
);
|
|
33689
|
+
const needsVision = options.hasVision ?? false;
|
|
33690
|
+
const needsStructuredOutput = options.requiresStructuredOutput ?? false;
|
|
33691
|
+
const latencySensitive = /\b(?:urgent|asap|fast|quick|low latency|real[- ]time)\b|尽快|马上|快速|低延迟/i.test(
|
|
33692
|
+
scannedFullText
|
|
33693
|
+
);
|
|
33694
|
+
const highStakes = /\b(?:production|security|payment|legal|medical|financial|audit)\b|生产|安全|支付|法律|医疗|财务|审计/i.test(
|
|
33695
|
+
scannedFullText
|
|
33696
|
+
);
|
|
33697
|
+
const terminalToolSignal = normalizedToolNames.some(
|
|
33698
|
+
(name) => /^(?:terminalexec|terminalinspect|terminalsendkeys)$/.test(name)
|
|
33699
|
+
);
|
|
33700
|
+
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(
|
|
33701
|
+
scannedPrompt
|
|
33702
|
+
);
|
|
33703
|
+
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(
|
|
33704
|
+
scannedPrompt
|
|
33705
|
+
);
|
|
33706
|
+
const mentionedTerminalRuntimes = new Set(
|
|
33707
|
+
(scannedPrompt.match(/\b(?:gcc|clang|rustc|javac|go\s+build|node|python)\b/gi) ?? []).map(
|
|
33708
|
+
(name) => name.toLowerCase().replace(/\s+/g, " ")
|
|
33709
|
+
)
|
|
33710
|
+
);
|
|
33711
|
+
const terminalCrossRuntimeArtifact = terminalToolSignal && (/\bpolyglot\b/i.test(scannedPrompt) || /\b(?:both|each)\b[\s\S]{0,120}\b(?:compilers?|runtimes?|toolchains?)\b/i.test(
|
|
33712
|
+
scannedPrompt
|
|
33713
|
+
) || mentionedTerminalRuntimes.size >= 2 && /\b(?:compile|build|run|execute)\b/i.test(scannedPrompt));
|
|
33714
|
+
const terminalFrameworkToNativeArtifact = terminalToolSignal && /\b(?:pytorch|tensorflow|jax|onnx|state[_ -]?dict|checkpoint|safetensors?)\b|\.(?:pth|pt|onnx)\b/i.test(
|
|
33715
|
+
scannedPrompt
|
|
33716
|
+
) && /\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(
|
|
33717
|
+
scannedPrompt
|
|
33718
|
+
) && /\b(?:inference|model|weights?|tensor|export|convert|load)\b/i.test(scannedPrompt);
|
|
33719
|
+
if (needsTools && (terminalComplexRepair || terminalCrossRuntimeArtifact || terminalFrameworkToNativeArtifact) && (agentRisk === "standard" || agentRisk === "high"))
|
|
33720
|
+
agentRisk = "complex_high";
|
|
33721
|
+
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(
|
|
33722
|
+
scannedPrompt
|
|
33723
|
+
);
|
|
33724
|
+
const terminalCredentialSignal = /\b(?:ssh|nginx|certificate|authentication|credentials?|passwords?|api keys?|deploy|production|encrypt|gpg|shred|securely delete|decommission)\b/i.test(
|
|
33725
|
+
scannedPrompt
|
|
33726
|
+
) || /\b(?:access|auth|authentication|bearer|secret|api)\s+tokens?\b|\btokens?\s+(?:secret|credential|authentication)\b/i.test(
|
|
33727
|
+
scannedPrompt
|
|
33728
|
+
);
|
|
33729
|
+
const terminalSafetySensitive = terminalToolSignal && (highStakes || terminalCredentialSignal);
|
|
33730
|
+
const implicitTerminalCode = needsTools && terminalToolSignal && agentRisk === "standard" && !highStakes && !complexTerminalOperation && numberedSteps < 3 && prompt.length <= 1e3 && simpleTerminalArtifact;
|
|
33731
|
+
const language = /[\u3400-\u9fff]/.test(scannedFullText) ? "zh" : "other";
|
|
33732
|
+
const multipleChoiceSignals = (scannedPrompt.match(/(?:^|\n)\s*[A-D][.)]\s+/gim) ?? []).length;
|
|
33733
|
+
const numericSignals = (scannedPrompt.match(/-?\d+(?:[.,]\d+)?/g) ?? []).length;
|
|
33734
|
+
const compactMathProblem = !hasCode && prompt.length < 2500 && numericSignals >= 2 && (/[+×÷=%$€£¥]|\b(?:total|each|per|times|half|twice|percent|how many|how much|calculate)\b/i.test(
|
|
33735
|
+
scannedPrompt
|
|
33736
|
+
) || /[??]\s*$/.test(scannedPrompt.trim()) || numericSignals >= 3);
|
|
33737
|
+
let taskType = "chat";
|
|
33738
|
+
if (needsVision) taskType = "vision";
|
|
33739
|
+
else if (estimatedInputTokens > 8e4) taskType = "long_context";
|
|
33740
|
+
else if (needsTools && (hasCode || implicitTerminalCode)) taskType = "code_agent";
|
|
33741
|
+
else if (needsTools && likelyParallelToolCalls && !complexMultiToolPlan)
|
|
33742
|
+
taskType = "tool_agent_parallel";
|
|
33743
|
+
else if (needsTools) taskType = "tool_agent";
|
|
33744
|
+
else if (multipleChoiceSignals >= 3) taskType = "reasoning_mcq";
|
|
33745
|
+
else if (compactMathProblem) taskType = "reasoning_math";
|
|
33746
|
+
else if (/\b(?:bug|debug|error|failure|failing|regression|crash|修复|报错|错误|调试)\b/i.test(text))
|
|
33747
|
+
taskType = "debug";
|
|
33748
|
+
else if (hasCode || /\b(?:refactor|implement|patch|edit|rewrite|重构|实现|修改)\b/i.test(text))
|
|
33749
|
+
taskType = "code_edit";
|
|
33750
|
+
else if (needsStructuredOutput || /\b(?:extract|json|schema|csv|字段|提取)\b/i.test(text))
|
|
33751
|
+
taskType = "extraction";
|
|
33752
|
+
else if (/\b(?:prove|derive|theorem|formal|mathematical|reasoning|证明|推导|定理|数学)\b/i.test(text))
|
|
33753
|
+
taskType = "reasoning";
|
|
33754
|
+
return {
|
|
33755
|
+
taskType,
|
|
33756
|
+
estimatedInputTokens,
|
|
33757
|
+
hasCode,
|
|
33758
|
+
needsTools,
|
|
33759
|
+
toolsAvailable,
|
|
33760
|
+
needsVision,
|
|
33761
|
+
needsStructuredOutput,
|
|
33762
|
+
latencySensitive,
|
|
33763
|
+
highStakes,
|
|
33764
|
+
language,
|
|
33765
|
+
likelyParallelToolCalls,
|
|
33766
|
+
complexMultiToolPlan,
|
|
33767
|
+
agentDomain,
|
|
33768
|
+
deepWebResearch,
|
|
33769
|
+
agentRisk,
|
|
33770
|
+
terminalToolSignal,
|
|
33771
|
+
terminalSafetySensitive,
|
|
33772
|
+
implicitTerminalCode
|
|
33773
|
+
};
|
|
33774
|
+
}
|
|
33775
|
+
function affinity(modelId, task, language = "other", agentDomain = "other", deepWebResearch = false, agentRisk = "standard", terminalToolSignal = false, terminalSafetySensitive = false) {
|
|
33776
|
+
const id2 = modelId.toLowerCase();
|
|
33777
|
+
const modelName = id2.slice(id2.indexOf("/") + 1);
|
|
33778
|
+
const match = (values, score) => values.some((value) => modelName === value) ? score : 0;
|
|
33779
|
+
const base3 = 0.68;
|
|
33780
|
+
switch (task) {
|
|
33781
|
+
case "code_agent":
|
|
33782
|
+
if (terminalToolSignal && agentRisk === "complex_high") {
|
|
33783
|
+
return Math.max(
|
|
33784
|
+
base3,
|
|
33785
|
+
match(["claude-sonnet-5"], 1),
|
|
33786
|
+
match(["gpt-5.3-codex"], 0.87),
|
|
33787
|
+
match(["gpt-5-mini"], 0.78),
|
|
33788
|
+
match(["gemini-3.5-flash"], 0.76)
|
|
33789
|
+
);
|
|
33790
|
+
}
|
|
33791
|
+
return Math.max(
|
|
33792
|
+
base3,
|
|
33793
|
+
match(["gpt-5.3-codex"], 1),
|
|
33794
|
+
match(["claude-sonnet-5"], 0.98),
|
|
33795
|
+
match(["gpt-5-mini"], 0.96),
|
|
33796
|
+
match(["gemini-3.5-flash"], 0.92),
|
|
33797
|
+
match(["kimi-k3"], 0.9),
|
|
33798
|
+
match(["deepseek-v4-pro", "glm-5.2"], 0.88)
|
|
33799
|
+
);
|
|
33800
|
+
case "tool_agent":
|
|
33801
|
+
if (terminalToolSignal && agentRisk === "complex_high") {
|
|
33802
|
+
return Math.max(
|
|
33803
|
+
base3,
|
|
33804
|
+
match(["claude-sonnet-5"], 1),
|
|
33805
|
+
match(["gpt-5.3-codex"], 0.87),
|
|
33806
|
+
match(["gpt-5-mini"], 0.78),
|
|
33807
|
+
match(["gemini-3.5-flash"], 0.76)
|
|
33808
|
+
);
|
|
33809
|
+
}
|
|
33810
|
+
if (terminalToolSignal && !terminalSafetySensitive) {
|
|
33811
|
+
return Math.max(
|
|
33812
|
+
base3,
|
|
33813
|
+
match(["gpt-5-mini"], 1),
|
|
33814
|
+
match(["gpt-5.3-codex"], 0.98),
|
|
33815
|
+
match(["claude-sonnet-5"], 0.9),
|
|
33816
|
+
match(["gemini-3.5-flash"], 0.89)
|
|
33817
|
+
);
|
|
33818
|
+
}
|
|
33819
|
+
if (terminalToolSignal && terminalSafetySensitive) {
|
|
33820
|
+
return Math.max(
|
|
33821
|
+
base3,
|
|
33822
|
+
match(["claude-sonnet-5"], 1),
|
|
33823
|
+
match(["claude-opus-4.8"], 0.9),
|
|
33824
|
+
match(["gpt-5.3-codex"], 0.84)
|
|
33825
|
+
);
|
|
33826
|
+
}
|
|
33827
|
+
if (agentDomain === "web_research") {
|
|
33828
|
+
return deepWebResearch ? Math.max(
|
|
33829
|
+
base3,
|
|
33830
|
+
match(["claude-sonnet-5"], 1),
|
|
33831
|
+
match(["gpt-5-mini"], 0.88),
|
|
33832
|
+
match(["gemini-3.5-flash"], 0.84),
|
|
33833
|
+
match(["claude-opus-5"], 0.8),
|
|
33834
|
+
match(["claude-opus-4.8"], 0.78)
|
|
33835
|
+
) : Math.max(
|
|
33836
|
+
base3,
|
|
33837
|
+
match(["claude-sonnet-5"], 1),
|
|
33838
|
+
match(["gpt-5-mini"], 0.88),
|
|
33839
|
+
match(["gemini-3.5-flash"], 0.86),
|
|
33840
|
+
match(["claude-opus-5"], 0.84),
|
|
33841
|
+
match(["claude-opus-4.8"], 0.82)
|
|
33842
|
+
);
|
|
33843
|
+
}
|
|
33844
|
+
if (agentDomain === "retail") {
|
|
33845
|
+
if (agentRisk === "standard") {
|
|
33846
|
+
return Math.max(
|
|
33847
|
+
base3,
|
|
33848
|
+
match(["gpt-5-mini"], 1),
|
|
33849
|
+
match(["claude-sonnet-5"], 0.88),
|
|
33850
|
+
match(["gemini-3.5-flash"], 0.82),
|
|
33851
|
+
match(["gpt-5.3-codex"], 0.81),
|
|
33852
|
+
match(["kimi-k3"], 0.78),
|
|
33853
|
+
match(["deepseek-v4-pro"], 0.76)
|
|
33854
|
+
);
|
|
33855
|
+
}
|
|
33856
|
+
if (agentRisk === "policy_exception") {
|
|
33857
|
+
return Math.max(
|
|
33858
|
+
base3,
|
|
33859
|
+
match(["gpt-4.1"], 1),
|
|
33860
|
+
match(["claude-sonnet-5"], 0.9),
|
|
33861
|
+
match(["deepseek-v4-pro"], 0.82),
|
|
33862
|
+
match(["gpt-5-mini"], 0.8),
|
|
33863
|
+
match(["gpt-4o-mini"], 0.76)
|
|
33864
|
+
);
|
|
33865
|
+
}
|
|
33866
|
+
if (agentRisk === "policy_exception_simple") {
|
|
33867
|
+
return Math.max(
|
|
33868
|
+
base3,
|
|
33869
|
+
match(["gpt-5-mini"], 1),
|
|
33870
|
+
match(["gpt-4.1"], 0.86),
|
|
33871
|
+
match(["deepseek-v4-pro"], 0.82),
|
|
33872
|
+
match(["gpt-4o-mini"], 0.8)
|
|
33873
|
+
);
|
|
33874
|
+
}
|
|
33875
|
+
return Math.max(
|
|
33876
|
+
base3,
|
|
33877
|
+
match(["deepseek-v4-pro"], 1),
|
|
33878
|
+
match(["claude-sonnet-5"], 0.88),
|
|
33879
|
+
match(["gemini-3.5-flash"], 0.82),
|
|
33880
|
+
match(["gpt-5.3-codex"], 0.81),
|
|
33881
|
+
match(["kimi-k3"], 0.78),
|
|
33882
|
+
match(["gpt-5-mini"], 0.76)
|
|
33883
|
+
);
|
|
33884
|
+
}
|
|
33885
|
+
if (agentDomain === "airline") {
|
|
33886
|
+
if (agentRisk === "complex_high") {
|
|
33887
|
+
return Math.max(
|
|
33888
|
+
base3,
|
|
33889
|
+
match(["claude-sonnet-5"], 1),
|
|
33890
|
+
match(["gpt-5-mini"], 0.78),
|
|
33891
|
+
match(["gemini-3.5-flash"], 0.76),
|
|
33892
|
+
match(["deepseek-v4-pro"], 0.74)
|
|
33893
|
+
);
|
|
33894
|
+
}
|
|
33895
|
+
return Math.max(
|
|
33896
|
+
base3,
|
|
33897
|
+
match(["gpt-5-mini"], 1),
|
|
33898
|
+
match(["claude-sonnet-5"], 0.9),
|
|
33899
|
+
match(["gemini-3.5-flash"], 0.8),
|
|
33900
|
+
match(["deepseek-v4-pro"], 0.76)
|
|
33901
|
+
);
|
|
33902
|
+
}
|
|
33903
|
+
return Math.max(
|
|
33904
|
+
base3,
|
|
33905
|
+
match(["claude-sonnet-5"], 1),
|
|
33906
|
+
match(["gemini-3.5-flash"], 0.88),
|
|
33907
|
+
match(["gpt-5.3-codex"], 0.87),
|
|
33908
|
+
match(["gpt-5-mini"], 0.84),
|
|
33909
|
+
match(["kimi-k3"], 0.85),
|
|
33910
|
+
match(["deepseek-v4-pro"], 0.82)
|
|
33911
|
+
);
|
|
33912
|
+
case "tool_agent_parallel":
|
|
33913
|
+
if (terminalToolSignal) {
|
|
33914
|
+
return terminalSafetySensitive ? Math.max(
|
|
33915
|
+
base3,
|
|
33916
|
+
match(["claude-sonnet-5"], 1),
|
|
33917
|
+
match(["claude-opus-4.8"], 0.9),
|
|
33918
|
+
match(["gpt-5.3-codex"], 0.86)
|
|
33919
|
+
) : Math.max(
|
|
33920
|
+
base3,
|
|
33921
|
+
match(["gpt-5-mini"], 1),
|
|
33922
|
+
match(["gpt-5.3-codex"], 0.98),
|
|
33923
|
+
match(["claude-sonnet-5"], 0.92),
|
|
33924
|
+
match(["gemini-3.5-flash"], 0.88)
|
|
33925
|
+
);
|
|
33926
|
+
}
|
|
33927
|
+
if (agentDomain === "web_research") {
|
|
33928
|
+
return deepWebResearch ? Math.max(
|
|
33929
|
+
base3,
|
|
33930
|
+
match(["claude-sonnet-5"], 1),
|
|
33931
|
+
match(["gpt-5-mini"], 0.88),
|
|
33932
|
+
match(["gemini-3.5-flash"], 0.84),
|
|
33933
|
+
match(["claude-opus-5"], 0.8),
|
|
33934
|
+
match(["claude-opus-4.8"], 0.78)
|
|
33935
|
+
) : Math.max(
|
|
33936
|
+
base3,
|
|
33937
|
+
match(["claude-sonnet-5"], 1),
|
|
33938
|
+
match(["gpt-5-mini"], 0.88),
|
|
33939
|
+
match(["gemini-3.5-flash"], 0.86),
|
|
33940
|
+
match(["claude-opus-5"], 0.84),
|
|
33941
|
+
match(["claude-opus-4.8"], 0.82)
|
|
33942
|
+
);
|
|
33943
|
+
}
|
|
33944
|
+
if (agentDomain === "retail") {
|
|
33945
|
+
if (agentRisk === "policy_exception") {
|
|
33946
|
+
return Math.max(
|
|
33947
|
+
base3,
|
|
33948
|
+
match(["gpt-4.1"], 1),
|
|
33949
|
+
match(["claude-sonnet-5"], 0.9),
|
|
33950
|
+
match(["deepseek-v4-pro"], 0.82),
|
|
33951
|
+
match(["gpt-5-mini"], 0.8),
|
|
33952
|
+
match(["gpt-4o-mini"], 0.76)
|
|
33953
|
+
);
|
|
33954
|
+
}
|
|
33955
|
+
if (agentRisk === "policy_exception_simple") {
|
|
33956
|
+
return Math.max(
|
|
33957
|
+
base3,
|
|
33958
|
+
match(["gpt-5-mini"], 1),
|
|
33959
|
+
match(["gpt-4.1"], 0.86),
|
|
33960
|
+
match(["deepseek-v4-pro"], 0.82),
|
|
33961
|
+
match(["gpt-4o-mini"], 0.8)
|
|
33962
|
+
);
|
|
33963
|
+
}
|
|
33964
|
+
return Math.max(
|
|
33965
|
+
base3,
|
|
33966
|
+
match(["deepseek-v4-pro"], 1),
|
|
33967
|
+
match(["claude-sonnet-5"], 0.88),
|
|
33968
|
+
match(["claude-opus-4.8"], 0.84),
|
|
33969
|
+
match(["gpt-5-mini"], 0.78),
|
|
33970
|
+
match(["gemini-3.5-flash"], 0.76)
|
|
33971
|
+
);
|
|
33972
|
+
}
|
|
33973
|
+
if (agentDomain === "airline") {
|
|
33974
|
+
return agentRisk === "complex_high" ? Math.max(
|
|
33975
|
+
base3,
|
|
33976
|
+
match(["claude-sonnet-5"], 1),
|
|
33977
|
+
match(["gpt-5-mini"], 0.78),
|
|
33978
|
+
match(["claude-opus-4.8"], 0.76),
|
|
33979
|
+
match(["gemini-3.5-flash"], 0.74)
|
|
33980
|
+
) : Math.max(
|
|
33981
|
+
base3,
|
|
33982
|
+
match(["gpt-5-mini"], 1),
|
|
33983
|
+
match(["claude-sonnet-5"], 0.9),
|
|
33984
|
+
match(["gemini-3.5-flash"], 0.8)
|
|
33985
|
+
);
|
|
33986
|
+
}
|
|
33987
|
+
return Math.max(
|
|
33988
|
+
base3,
|
|
33989
|
+
match(["claude-opus-4.8"], 1),
|
|
33990
|
+
match(["claude-sonnet-5"], 0.84),
|
|
33991
|
+
match(["grok-4.5"], 0.82),
|
|
33992
|
+
match(["gemini-3.5-flash"], 0.8),
|
|
33993
|
+
match(["deepseek-v4-pro"], 0.78)
|
|
33994
|
+
);
|
|
33995
|
+
case "code_edit":
|
|
33996
|
+
case "debug":
|
|
33997
|
+
return Math.max(
|
|
33998
|
+
base3,
|
|
33999
|
+
match(["gpt-5.3-codex"], 1),
|
|
34000
|
+
match(["claude-sonnet-4.6"], 0.94),
|
|
34001
|
+
match(["glm-5.2"], 0.9),
|
|
34002
|
+
match(["kimi-k2.7", "deepseek-v4-pro"], 0.86)
|
|
34003
|
+
);
|
|
34004
|
+
case "reasoning":
|
|
34005
|
+
return Math.max(
|
|
34006
|
+
base3,
|
|
34007
|
+
match(["claude-sonnet-5", "claude-sonnet-4.6"], 0.98),
|
|
34008
|
+
match(["deepseek-v4-pro"], 0.95),
|
|
34009
|
+
match(["grok-4.5"], 0.94),
|
|
34010
|
+
match(["gemini-3.1-pro", "gemini-3.5-flash"], 0.92)
|
|
34011
|
+
);
|
|
34012
|
+
case "reasoning_mcq":
|
|
34013
|
+
return Math.max(
|
|
34014
|
+
base3,
|
|
34015
|
+
match(["gemini-3-flash-preview"], 1),
|
|
34016
|
+
match(["gemini-3.5-flash"], 0.91),
|
|
34017
|
+
match(["grok-4.5"], 0.9),
|
|
34018
|
+
match(["claude-sonnet-5"], 0.88),
|
|
34019
|
+
match(["deepseek-v4-pro"], 0.84)
|
|
34020
|
+
);
|
|
34021
|
+
case "reasoning_math":
|
|
34022
|
+
return Math.max(
|
|
34023
|
+
base3,
|
|
34024
|
+
match(["gemini-3.5-flash"], 1),
|
|
34025
|
+
match(["grok-4.5"], 0.93),
|
|
34026
|
+
match(["claude-sonnet-5", "deepseek-v4-pro", "kimi-k3"], 0.9),
|
|
34027
|
+
match(["kimi-k2.7"], 0.84)
|
|
34028
|
+
);
|
|
34029
|
+
case "vision":
|
|
34030
|
+
return Math.max(
|
|
34031
|
+
base3,
|
|
34032
|
+
match(["gemini-3.1-pro"], 0.96),
|
|
34033
|
+
match(["qwen3.7-max", "claude-sonnet-4.6", "kimi-k2.7", "grok-4.3"], 0.9)
|
|
34034
|
+
);
|
|
34035
|
+
case "long_context":
|
|
34036
|
+
return Math.max(
|
|
34037
|
+
base3,
|
|
34038
|
+
match(["gemini-3.1-pro"], 1),
|
|
34039
|
+
match(["qwen3.7-max", "glm-5.2"], 0.89),
|
|
34040
|
+
match(["gemini-3.5-flash"], 0.88),
|
|
34041
|
+
match(["deepseek-v4-pro"], 0.85)
|
|
34042
|
+
);
|
|
34043
|
+
case "extraction": {
|
|
34044
|
+
const kimiExtractionAffinity = language === "zh" ? 1 : 0.9;
|
|
34045
|
+
return Math.max(
|
|
34046
|
+
base3,
|
|
34047
|
+
match(["gemini-3.5-flash", "gemini-2.5-flash", "gpt-4o-mini"], 0.9),
|
|
34048
|
+
match(["claude-sonnet-5", "claude-sonnet-4.6"], 0.9),
|
|
34049
|
+
match(["kimi-k3", "kimi-k2.7"], kimiExtractionAffinity)
|
|
34050
|
+
);
|
|
34051
|
+
}
|
|
34052
|
+
default:
|
|
34053
|
+
return Math.max(
|
|
34054
|
+
base3,
|
|
34055
|
+
match(["gemini-3.5-flash", "gemini-2.5-flash", "kimi-k3", "kimi-k2.7"], 0.86)
|
|
34056
|
+
);
|
|
34057
|
+
}
|
|
34058
|
+
}
|
|
34059
|
+
function evidenceCandidates(task) {
|
|
34060
|
+
if (task === "code_agent") {
|
|
34061
|
+
return [
|
|
34062
|
+
"openai/gpt-5.3-codex",
|
|
34063
|
+
"anthropic/claude-sonnet-5",
|
|
34064
|
+
"openai/gpt-5-mini",
|
|
34065
|
+
"google/gemini-3.5-flash",
|
|
34066
|
+
"moonshot/kimi-k3",
|
|
34067
|
+
"deepseek/deepseek-v4-pro"
|
|
34068
|
+
];
|
|
34069
|
+
}
|
|
34070
|
+
if (task === "tool_agent") {
|
|
34071
|
+
return [
|
|
34072
|
+
"anthropic/claude-sonnet-5",
|
|
34073
|
+
"anthropic/claude-opus-5",
|
|
34074
|
+
"openai/gpt-5-mini",
|
|
34075
|
+
"openai/gpt-4.1",
|
|
34076
|
+
"openai/gpt-4o-mini",
|
|
34077
|
+
"google/gemini-3.5-flash",
|
|
34078
|
+
"openai/gpt-5.3-codex",
|
|
34079
|
+
"moonshot/kimi-k3",
|
|
34080
|
+
"deepseek/deepseek-v4-pro"
|
|
34081
|
+
];
|
|
34082
|
+
}
|
|
34083
|
+
if (task === "tool_agent_parallel") {
|
|
34084
|
+
return [
|
|
34085
|
+
"anthropic/claude-opus-5",
|
|
34086
|
+
"anthropic/claude-opus-4.8",
|
|
34087
|
+
"anthropic/claude-sonnet-5",
|
|
34088
|
+
"openai/gpt-5-mini",
|
|
34089
|
+
"openai/gpt-4.1",
|
|
34090
|
+
"openai/gpt-4o-mini",
|
|
34091
|
+
"xai/grok-4.5",
|
|
34092
|
+
"google/gemini-3.5-flash",
|
|
34093
|
+
"deepseek/deepseek-v4-pro"
|
|
34094
|
+
];
|
|
34095
|
+
}
|
|
34096
|
+
if (task === "long_context") {
|
|
34097
|
+
return [
|
|
34098
|
+
"google/gemini-3.1-pro",
|
|
34099
|
+
"deepseek/deepseek-v4-pro",
|
|
34100
|
+
"qwen/qwen3.7-max",
|
|
34101
|
+
"zai/glm-5.2",
|
|
34102
|
+
"google/gemini-3.5-flash"
|
|
34103
|
+
];
|
|
34104
|
+
}
|
|
34105
|
+
if (task === "reasoning_mcq") {
|
|
34106
|
+
return [
|
|
34107
|
+
"google/gemini-3-flash-preview",
|
|
34108
|
+
"google/gemini-3.5-flash",
|
|
34109
|
+
"xai/grok-4.5",
|
|
34110
|
+
"anthropic/claude-sonnet-5",
|
|
34111
|
+
"deepseek/deepseek-v4-pro"
|
|
34112
|
+
];
|
|
34113
|
+
}
|
|
34114
|
+
if (task === "reasoning_math") {
|
|
34115
|
+
return [
|
|
34116
|
+
"google/gemini-3.5-flash",
|
|
34117
|
+
"xai/grok-4.5",
|
|
34118
|
+
"anthropic/claude-sonnet-5",
|
|
34119
|
+
"deepseek/deepseek-v4-pro",
|
|
34120
|
+
"moonshot/kimi-k3"
|
|
34121
|
+
];
|
|
34122
|
+
}
|
|
34123
|
+
return [];
|
|
34124
|
+
}
|
|
34125
|
+
function isEligible(modelId, features, maxOutputTokens, options) {
|
|
34126
|
+
const model = options.modelCapabilities?.[modelId] ?? DEFAULT_MODEL_CAPABILITIES[modelId];
|
|
34127
|
+
if (!model) return true;
|
|
34128
|
+
if (features.needsTools && !model.supportsTools) return false;
|
|
34129
|
+
if (features.needsVision && !model.supportsVision) return false;
|
|
34130
|
+
if (features.needsStructuredOutput && !model.supportsTools) return false;
|
|
34131
|
+
if (model.maxOutputTokens < maxOutputTokens) return false;
|
|
34132
|
+
return model.contextWindow >= (features.estimatedInputTokens + maxOutputTokens) * 1.1;
|
|
34133
|
+
}
|
|
34134
|
+
function estimatedCost(modelId, options, inputTokens, outputTokens) {
|
|
34135
|
+
const price = options.modelPricing.get(modelId);
|
|
34136
|
+
if (!price) return Number.POSITIVE_INFINITY;
|
|
34137
|
+
if (price.flatPrice !== void 0) return price.flatPrice;
|
|
34138
|
+
return (inputTokens * price.inputPrice + outputTokens * price.outputPrice) / 1e6;
|
|
34139
|
+
}
|
|
34140
|
+
function profileScore(modelId, options, now2) {
|
|
34141
|
+
const profile = options.modelPerformance?.[modelId] ?? LIVE_MODEL_PROFILES[modelId] ?? HISTORICAL_MODEL_PROFILES[modelId];
|
|
34142
|
+
if (!profile) return void 0;
|
|
34143
|
+
const measuredAt = Date.parse(profile.measuredAt);
|
|
34144
|
+
if (!Number.isFinite(measuredAt)) return void 0;
|
|
34145
|
+
const ageDays = Math.max(0, (now2.getTime() - measuredAt) / 864e5);
|
|
34146
|
+
const sampleConfidence = profile.samples === void 0 ? 1 : Math.min(1, Math.max(0, profile.samples) / 10);
|
|
34147
|
+
const freshness = Math.pow(0.5, ageDays / 30) * sampleConfidence;
|
|
34148
|
+
const quality = profile.intelligenceIndex === void 0 ? void 0 : Math.min(1, profile.intelligenceIndex / 50);
|
|
34149
|
+
const speed = Math.min(
|
|
34150
|
+
1,
|
|
34151
|
+
(2e3 / Math.max(500, profile.latencyMs) + profile.outputTokensPerSecond / 250) / 2
|
|
34152
|
+
);
|
|
34153
|
+
const tailSpeed = Math.min(1, 3e3 / Math.max(750, profile.p95LatencyMs ?? profile.latencyMs));
|
|
34154
|
+
const reliability = Math.max(0, 1 - (profile.errorRate ?? 0));
|
|
34155
|
+
return { quality, speed, tailSpeed, reliability, freshness };
|
|
34156
|
+
}
|
|
34157
|
+
function route(prompt, systemPrompt, maxOutputTokens, options) {
|
|
34158
|
+
const strategy = getStrategy(options.config.strategy ?? "portfolio");
|
|
34159
|
+
return strategy.route(prompt, systemPrompt, maxOutputTokens, options);
|
|
34160
|
+
}
|
|
34161
|
+
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;
|
|
34162
|
+
var init_dist = __esm({
|
|
34163
|
+
"node_modules/@blockrun/router-core/dist/index.js"() {
|
|
33546
34164
|
"use strict";
|
|
33547
|
-
|
|
33548
|
-
|
|
34165
|
+
BASELINE_MODEL_ID = "anthropic/claude-opus-4.7";
|
|
34166
|
+
BASELINE_INPUT_PRICE = 5;
|
|
34167
|
+
BASELINE_OUTPUT_PRICE = 25;
|
|
34168
|
+
SERVER_MARGIN_PERCENT = 5;
|
|
34169
|
+
MIN_PAYMENT_USD = 1e-3;
|
|
33549
34170
|
RulesStrategy = class {
|
|
33550
34171
|
name = "rules";
|
|
33551
34172
|
route(prompt, systemPrompt, maxOutputTokens, options) {
|
|
33552
34173
|
const { config, modelPricing } = options;
|
|
33553
34174
|
const fullText = `${systemPrompt ?? ""} ${prompt}`;
|
|
33554
34175
|
const estimatedTokens = Math.ceil(fullText.length / 4);
|
|
33555
|
-
const
|
|
34176
|
+
const scanLimit = Math.max(1, Math.min(8e3, config.classifier.promptTruncationChars));
|
|
34177
|
+
const sample = (value) => {
|
|
34178
|
+
if (value.length <= scanLimit) return value;
|
|
34179
|
+
const prefixLength = Math.ceil(scanLimit / 2);
|
|
34180
|
+
return `${value.slice(0, prefixLength)}
|
|
34181
|
+
${value.slice(-(scanLimit - prefixLength))}`;
|
|
34182
|
+
};
|
|
34183
|
+
const scannedPrompt = sample(prompt);
|
|
34184
|
+
const scannedSystemPrompt = systemPrompt ? sample(systemPrompt) : void 0;
|
|
34185
|
+
const ruleResult = classifyByRules(
|
|
34186
|
+
scannedPrompt,
|
|
34187
|
+
scannedSystemPrompt,
|
|
34188
|
+
estimatedTokens,
|
|
34189
|
+
config.scoring
|
|
34190
|
+
);
|
|
33556
34191
|
const { routingProfile } = options;
|
|
33557
34192
|
let tierConfigs;
|
|
33558
34193
|
let profileSuffix;
|
|
@@ -33569,7 +34204,7 @@ var init_strategy = __esm({
|
|
|
33569
34204
|
const agenticScore = ruleResult.agenticScore ?? 0;
|
|
33570
34205
|
const isAutoAgentic = agenticScore >= 0.5;
|
|
33571
34206
|
const agenticModeSetting = config.overrides.agenticMode;
|
|
33572
|
-
const hasToolsInRequest = options.hasTools ?? false;
|
|
34207
|
+
const hasToolsInRequest = options.requiresTools ?? options.hasTools ?? false;
|
|
33573
34208
|
let useAgenticTiers;
|
|
33574
34209
|
if (agenticModeSetting === false) {
|
|
33575
34210
|
useAgenticTiers = false;
|
|
@@ -33599,7 +34234,7 @@ var init_strategy = __esm({
|
|
|
33599
34234
|
);
|
|
33600
34235
|
return { ...decision2, tierConfigs, profile };
|
|
33601
34236
|
}
|
|
33602
|
-
const hasStructuredOutput =
|
|
34237
|
+
const hasStructuredOutput = options.requiresStructuredOutput === true || (scannedSystemPrompt ? /json|structured|schema/i.test(scannedSystemPrompt) : false);
|
|
33603
34238
|
let tier;
|
|
33604
34239
|
let confidence;
|
|
33605
34240
|
const method = "rules";
|
|
@@ -33638,16 +34273,789 @@ var init_strategy = __esm({
|
|
|
33638
34273
|
};
|
|
33639
34274
|
registry = /* @__PURE__ */ new Map();
|
|
33640
34275
|
registry.set("rules", new RulesStrategy());
|
|
33641
|
-
|
|
33642
|
-
|
|
33643
|
-
|
|
33644
|
-
|
|
33645
|
-
|
|
33646
|
-
|
|
33647
|
-
|
|
33648
|
-
|
|
34276
|
+
DEFAULT_MODEL_CAPABILITIES = Object.freeze({
|
|
34277
|
+
"anthropic/claude-fable-5": {
|
|
34278
|
+
contextWindow: 1e6,
|
|
34279
|
+
maxOutputTokens: 128e3,
|
|
34280
|
+
supportsTools: true,
|
|
34281
|
+
supportsVision: true
|
|
34282
|
+
},
|
|
34283
|
+
"anthropic/claude-haiku-4.5": {
|
|
34284
|
+
contextWindow: 2e5,
|
|
34285
|
+
maxOutputTokens: 8192,
|
|
34286
|
+
supportsTools: true,
|
|
34287
|
+
supportsVision: true
|
|
34288
|
+
},
|
|
34289
|
+
"anthropic/claude-opus-4.6": {
|
|
34290
|
+
contextWindow: 1e6,
|
|
34291
|
+
maxOutputTokens: 128e3,
|
|
34292
|
+
supportsTools: true,
|
|
34293
|
+
supportsVision: true
|
|
34294
|
+
},
|
|
34295
|
+
"anthropic/claude-opus-4.7": {
|
|
34296
|
+
contextWindow: 1e6,
|
|
34297
|
+
maxOutputTokens: 128e3,
|
|
34298
|
+
supportsTools: true,
|
|
34299
|
+
supportsVision: true
|
|
34300
|
+
},
|
|
34301
|
+
"anthropic/claude-opus-4.8": {
|
|
34302
|
+
contextWindow: 1e6,
|
|
34303
|
+
maxOutputTokens: 128e3,
|
|
34304
|
+
supportsTools: true,
|
|
34305
|
+
supportsVision: true
|
|
34306
|
+
},
|
|
34307
|
+
"anthropic/claude-opus-5": {
|
|
34308
|
+
contextWindow: 1e6,
|
|
34309
|
+
maxOutputTokens: 128e3,
|
|
34310
|
+
supportsTools: true,
|
|
34311
|
+
supportsVision: true
|
|
34312
|
+
},
|
|
34313
|
+
"anthropic/claude-sonnet-4.6": {
|
|
34314
|
+
contextWindow: 2e5,
|
|
34315
|
+
maxOutputTokens: 64e3,
|
|
34316
|
+
supportsTools: true,
|
|
34317
|
+
supportsVision: true
|
|
34318
|
+
},
|
|
34319
|
+
"anthropic/claude-sonnet-5": {
|
|
34320
|
+
contextWindow: 1e6,
|
|
34321
|
+
maxOutputTokens: 128e3,
|
|
34322
|
+
supportsTools: true,
|
|
34323
|
+
supportsVision: true
|
|
34324
|
+
},
|
|
34325
|
+
"deepseek/deepseek-chat": {
|
|
34326
|
+
contextWindow: 1e6,
|
|
34327
|
+
maxOutputTokens: 8192,
|
|
34328
|
+
supportsTools: true,
|
|
34329
|
+
supportsVision: false
|
|
34330
|
+
},
|
|
34331
|
+
"deepseek/deepseek-reasoner": {
|
|
34332
|
+
contextWindow: 1e6,
|
|
34333
|
+
maxOutputTokens: 8192,
|
|
34334
|
+
supportsTools: true,
|
|
34335
|
+
supportsVision: false
|
|
34336
|
+
},
|
|
34337
|
+
"deepseek/deepseek-v4-pro": {
|
|
34338
|
+
contextWindow: 1048576,
|
|
34339
|
+
maxOutputTokens: 65536,
|
|
34340
|
+
supportsTools: true,
|
|
34341
|
+
supportsVision: false
|
|
34342
|
+
},
|
|
34343
|
+
"free/deepseek-v4-flash": {
|
|
34344
|
+
contextWindow: 1e6,
|
|
34345
|
+
maxOutputTokens: 16384,
|
|
34346
|
+
supportsTools: false,
|
|
34347
|
+
supportsVision: false
|
|
34348
|
+
},
|
|
34349
|
+
"free/gpt-oss-120b": {
|
|
34350
|
+
contextWindow: 128e3,
|
|
34351
|
+
maxOutputTokens: 16384,
|
|
34352
|
+
supportsTools: false,
|
|
34353
|
+
supportsVision: false
|
|
34354
|
+
},
|
|
34355
|
+
"free/gpt-oss-20b": {
|
|
34356
|
+
contextWindow: 128e3,
|
|
34357
|
+
maxOutputTokens: 16384,
|
|
34358
|
+
supportsTools: false,
|
|
34359
|
+
supportsVision: false
|
|
34360
|
+
},
|
|
34361
|
+
"free/seed-oss-36b": {
|
|
34362
|
+
contextWindow: 131072,
|
|
34363
|
+
maxOutputTokens: 16384,
|
|
34364
|
+
supportsTools: false,
|
|
34365
|
+
supportsVision: false
|
|
34366
|
+
},
|
|
34367
|
+
"google/gemini-2.5-flash": {
|
|
34368
|
+
contextWindow: 1e6,
|
|
34369
|
+
maxOutputTokens: 65536,
|
|
34370
|
+
supportsTools: true,
|
|
34371
|
+
supportsVision: true
|
|
34372
|
+
},
|
|
34373
|
+
"google/gemini-2.5-flash-lite": {
|
|
34374
|
+
contextWindow: 1e6,
|
|
34375
|
+
maxOutputTokens: 65536,
|
|
34376
|
+
supportsTools: true,
|
|
34377
|
+
supportsVision: false
|
|
34378
|
+
},
|
|
34379
|
+
"google/gemini-2.5-pro": {
|
|
34380
|
+
contextWindow: 105e4,
|
|
34381
|
+
maxOutputTokens: 65536,
|
|
34382
|
+
supportsTools: true,
|
|
34383
|
+
supportsVision: true
|
|
34384
|
+
},
|
|
34385
|
+
"google/gemini-3-flash-preview": {
|
|
34386
|
+
contextWindow: 1e6,
|
|
34387
|
+
maxOutputTokens: 65536,
|
|
34388
|
+
supportsTools: false,
|
|
34389
|
+
supportsVision: true
|
|
34390
|
+
},
|
|
34391
|
+
"google/gemini-3.1-flash-lite": {
|
|
34392
|
+
contextWindow: 1e6,
|
|
34393
|
+
maxOutputTokens: 8192,
|
|
34394
|
+
supportsTools: true,
|
|
34395
|
+
supportsVision: false
|
|
34396
|
+
},
|
|
34397
|
+
"google/gemini-3.1-pro": {
|
|
34398
|
+
contextWindow: 105e4,
|
|
34399
|
+
maxOutputTokens: 65536,
|
|
34400
|
+
supportsTools: true,
|
|
34401
|
+
supportsVision: true
|
|
34402
|
+
},
|
|
34403
|
+
"google/gemini-3.5-flash": {
|
|
34404
|
+
contextWindow: 1048576,
|
|
34405
|
+
maxOutputTokens: 65536,
|
|
34406
|
+
supportsTools: true,
|
|
34407
|
+
supportsVision: true
|
|
34408
|
+
},
|
|
34409
|
+
"moonshot/kimi-k2.5": {
|
|
34410
|
+
contextWindow: 262144,
|
|
34411
|
+
maxOutputTokens: 16384,
|
|
34412
|
+
supportsTools: true,
|
|
34413
|
+
supportsVision: true
|
|
34414
|
+
},
|
|
34415
|
+
"moonshot/kimi-k2.6": {
|
|
34416
|
+
contextWindow: 262144,
|
|
34417
|
+
maxOutputTokens: 65536,
|
|
34418
|
+
supportsTools: true,
|
|
34419
|
+
supportsVision: true
|
|
34420
|
+
},
|
|
34421
|
+
"moonshot/kimi-k2.7": {
|
|
34422
|
+
contextWindow: 262144,
|
|
34423
|
+
maxOutputTokens: 65536,
|
|
34424
|
+
supportsTools: true,
|
|
34425
|
+
supportsVision: true
|
|
34426
|
+
},
|
|
34427
|
+
"moonshot/kimi-k3": {
|
|
34428
|
+
contextWindow: 1048576,
|
|
34429
|
+
maxOutputTokens: 65536,
|
|
34430
|
+
supportsTools: true,
|
|
34431
|
+
supportsVision: true
|
|
34432
|
+
},
|
|
34433
|
+
"openai/gpt-4.1": {
|
|
34434
|
+
contextWindow: 128e3,
|
|
34435
|
+
maxOutputTokens: 16384,
|
|
34436
|
+
supportsTools: true,
|
|
34437
|
+
supportsVision: true
|
|
34438
|
+
},
|
|
34439
|
+
"openai/gpt-4o-mini": {
|
|
34440
|
+
contextWindow: 128e3,
|
|
34441
|
+
maxOutputTokens: 16384,
|
|
34442
|
+
supportsTools: true,
|
|
34443
|
+
supportsVision: false
|
|
34444
|
+
},
|
|
34445
|
+
"openai/gpt-5-mini": {
|
|
34446
|
+
contextWindow: 2e5,
|
|
34447
|
+
maxOutputTokens: 65536,
|
|
34448
|
+
supportsTools: true,
|
|
34449
|
+
supportsVision: false
|
|
34450
|
+
},
|
|
34451
|
+
"openai/gpt-5.3-codex": {
|
|
34452
|
+
contextWindow: 4e5,
|
|
34453
|
+
maxOutputTokens: 128e3,
|
|
34454
|
+
supportsTools: true,
|
|
34455
|
+
supportsVision: false
|
|
34456
|
+
},
|
|
34457
|
+
"openai/gpt-5.4": {
|
|
34458
|
+
contextWindow: 4e5,
|
|
34459
|
+
maxOutputTokens: 128e3,
|
|
34460
|
+
supportsTools: true,
|
|
34461
|
+
supportsVision: true
|
|
34462
|
+
},
|
|
34463
|
+
"openai/gpt-5.4-nano": {
|
|
34464
|
+
contextWindow: 105e4,
|
|
34465
|
+
maxOutputTokens: 32768,
|
|
34466
|
+
supportsTools: true,
|
|
34467
|
+
supportsVision: false
|
|
34468
|
+
},
|
|
34469
|
+
"openai/gpt-5.5": {
|
|
34470
|
+
contextWindow: 105e4,
|
|
34471
|
+
maxOutputTokens: 128e3,
|
|
34472
|
+
supportsTools: true,
|
|
34473
|
+
supportsVision: true
|
|
34474
|
+
},
|
|
34475
|
+
"openai/gpt-5.6-terra": {
|
|
34476
|
+
contextWindow: 105e4,
|
|
34477
|
+
maxOutputTokens: 128e3,
|
|
34478
|
+
supportsTools: true,
|
|
34479
|
+
supportsVision: true
|
|
34480
|
+
},
|
|
34481
|
+
"openai/o3": {
|
|
34482
|
+
contextWindow: 2e5,
|
|
34483
|
+
maxOutputTokens: 1e5,
|
|
34484
|
+
supportsTools: true,
|
|
34485
|
+
supportsVision: false
|
|
34486
|
+
},
|
|
34487
|
+
"openai/o4-mini": {
|
|
34488
|
+
contextWindow: 128e3,
|
|
34489
|
+
maxOutputTokens: 65536,
|
|
34490
|
+
supportsTools: true,
|
|
34491
|
+
supportsVision: false
|
|
34492
|
+
},
|
|
34493
|
+
"qwen/qwen3.7-max": {
|
|
34494
|
+
contextWindow: 1e6,
|
|
34495
|
+
maxOutputTokens: 65536,
|
|
34496
|
+
supportsTools: true,
|
|
34497
|
+
supportsVision: false
|
|
34498
|
+
},
|
|
34499
|
+
"xai/grok-3-mini": {
|
|
34500
|
+
contextWindow: 131072,
|
|
34501
|
+
maxOutputTokens: 16384,
|
|
34502
|
+
supportsTools: true,
|
|
34503
|
+
supportsVision: false
|
|
34504
|
+
},
|
|
34505
|
+
"xai/grok-4-0709": {
|
|
34506
|
+
contextWindow: 131072,
|
|
34507
|
+
maxOutputTokens: 16384,
|
|
34508
|
+
supportsTools: true,
|
|
34509
|
+
supportsVision: false
|
|
34510
|
+
},
|
|
34511
|
+
"xai/grok-4-1-fast-non-reasoning": {
|
|
34512
|
+
contextWindow: 131072,
|
|
34513
|
+
maxOutputTokens: 16384,
|
|
34514
|
+
supportsTools: true,
|
|
34515
|
+
supportsVision: false
|
|
34516
|
+
},
|
|
34517
|
+
"xai/grok-4-1-fast-reasoning": {
|
|
34518
|
+
contextWindow: 131072,
|
|
34519
|
+
maxOutputTokens: 16384,
|
|
34520
|
+
supportsTools: true,
|
|
34521
|
+
supportsVision: false
|
|
34522
|
+
},
|
|
34523
|
+
"xai/grok-4-fast-non-reasoning": {
|
|
34524
|
+
contextWindow: 131072,
|
|
34525
|
+
maxOutputTokens: 16384,
|
|
34526
|
+
supportsTools: true,
|
|
34527
|
+
supportsVision: false
|
|
34528
|
+
},
|
|
34529
|
+
"xai/grok-4-fast-reasoning": {
|
|
34530
|
+
contextWindow: 131072,
|
|
34531
|
+
maxOutputTokens: 16384,
|
|
34532
|
+
supportsTools: true,
|
|
34533
|
+
supportsVision: false
|
|
34534
|
+
},
|
|
34535
|
+
"xai/grok-4.5": {
|
|
34536
|
+
contextWindow: 5e5,
|
|
34537
|
+
maxOutputTokens: 16384,
|
|
34538
|
+
supportsTools: true,
|
|
34539
|
+
supportsVision: true
|
|
34540
|
+
},
|
|
34541
|
+
"zai/glm-5.1": {
|
|
34542
|
+
contextWindow: 2e5,
|
|
34543
|
+
maxOutputTokens: 128e3,
|
|
34544
|
+
supportsTools: true,
|
|
34545
|
+
supportsVision: false
|
|
34546
|
+
},
|
|
34547
|
+
"zai/glm-5.2": {
|
|
34548
|
+
contextWindow: 1e6,
|
|
34549
|
+
maxOutputTokens: 262144,
|
|
34550
|
+
supportsTools: true,
|
|
34551
|
+
supportsVision: false
|
|
34552
|
+
}
|
|
34553
|
+
});
|
|
34554
|
+
model_profiles_generated_default = {
|
|
34555
|
+
"openai/gpt-5.5": {
|
|
34556
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
34557
|
+
latencyMs: 6243.1,
|
|
34558
|
+
p95LatencyMs: 9865,
|
|
34559
|
+
outputTokensPerSecond: 12.53,
|
|
34560
|
+
errorRate: 0,
|
|
34561
|
+
samples: 3
|
|
34562
|
+
},
|
|
34563
|
+
"openai/gpt-5.4-pro": {
|
|
34564
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
34565
|
+
latencyMs: 13015.5,
|
|
34566
|
+
p95LatencyMs: 23976.4,
|
|
34567
|
+
outputTokensPerSecond: 6.42,
|
|
34568
|
+
errorRate: 0,
|
|
34569
|
+
samples: 3
|
|
34570
|
+
},
|
|
34571
|
+
"openai/gpt-5.4-mini": {
|
|
34572
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
34573
|
+
latencyMs: 5550,
|
|
34574
|
+
p95LatencyMs: 6595.7,
|
|
34575
|
+
outputTokensPerSecond: 11.96,
|
|
34576
|
+
errorRate: 0.3333,
|
|
34577
|
+
samples: 3
|
|
34578
|
+
},
|
|
34579
|
+
"openai/gpt-5.3-codex": {
|
|
34580
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
34581
|
+
latencyMs: 4617.1,
|
|
34582
|
+
p95LatencyMs: 5800.7,
|
|
34583
|
+
outputTokensPerSecond: 12.48,
|
|
34584
|
+
errorRate: 0,
|
|
34585
|
+
samples: 3
|
|
34586
|
+
},
|
|
34587
|
+
"anthropic/claude-opus-4.8": {
|
|
34588
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
34589
|
+
latencyMs: 3915.1,
|
|
34590
|
+
p95LatencyMs: 6130.8,
|
|
34591
|
+
outputTokensPerSecond: 16.33,
|
|
34592
|
+
errorRate: 0,
|
|
34593
|
+
samples: 3
|
|
34594
|
+
},
|
|
34595
|
+
"anthropic/claude-opus-4.6": {
|
|
34596
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
34597
|
+
latencyMs: 3765.5,
|
|
34598
|
+
p95LatencyMs: 4257.2,
|
|
34599
|
+
outputTokensPerSecond: 14.18,
|
|
34600
|
+
errorRate: 0,
|
|
34601
|
+
samples: 3
|
|
34602
|
+
},
|
|
34603
|
+
"anthropic/claude-sonnet-4.6": {
|
|
34604
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
34605
|
+
latencyMs: 3860.6,
|
|
34606
|
+
p95LatencyMs: 5093.5,
|
|
34607
|
+
outputTokensPerSecond: 13.85,
|
|
34608
|
+
errorRate: 0,
|
|
34609
|
+
samples: 3
|
|
34610
|
+
},
|
|
34611
|
+
"anthropic/claude-haiku-4.5": {
|
|
34612
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
34613
|
+
latencyMs: 2734.9,
|
|
34614
|
+
p95LatencyMs: 3181.6,
|
|
34615
|
+
outputTokensPerSecond: 19.58,
|
|
34616
|
+
errorRate: 0,
|
|
34617
|
+
samples: 3
|
|
34618
|
+
},
|
|
34619
|
+
"google/gemini-3.1-pro": {
|
|
34620
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
34621
|
+
latencyMs: 13935.7,
|
|
34622
|
+
p95LatencyMs: 26675.3,
|
|
34623
|
+
outputTokensPerSecond: 77.47,
|
|
34624
|
+
errorRate: 0,
|
|
34625
|
+
samples: 3
|
|
34626
|
+
},
|
|
34627
|
+
"google/gemini-3.5-flash": {
|
|
34628
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
34629
|
+
latencyMs: 4608.7,
|
|
34630
|
+
p95LatencyMs: 8420.9,
|
|
34631
|
+
outputTokensPerSecond: 57.88,
|
|
34632
|
+
errorRate: 0,
|
|
34633
|
+
samples: 3
|
|
34634
|
+
},
|
|
34635
|
+
"google/gemini-3.1-flash-lite": {
|
|
34636
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
34637
|
+
latencyMs: 4619.7,
|
|
34638
|
+
p95LatencyMs: 9927.1,
|
|
34639
|
+
outputTokensPerSecond: 42.01,
|
|
34640
|
+
errorRate: 0,
|
|
34641
|
+
samples: 3
|
|
34642
|
+
},
|
|
34643
|
+
"google/gemini-2.5-flash": {
|
|
34644
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
34645
|
+
latencyMs: 5506.9,
|
|
34646
|
+
p95LatencyMs: 11462.5,
|
|
34647
|
+
outputTokensPerSecond: 65.19,
|
|
34648
|
+
errorRate: 0,
|
|
34649
|
+
samples: 3
|
|
34650
|
+
},
|
|
34651
|
+
"deepseek/deepseek-v4-pro": {
|
|
34652
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
34653
|
+
latencyMs: 6044.8,
|
|
34654
|
+
p95LatencyMs: 10782.3,
|
|
34655
|
+
outputTokensPerSecond: 22.47,
|
|
34656
|
+
errorRate: 0,
|
|
34657
|
+
samples: 3
|
|
34658
|
+
},
|
|
34659
|
+
"deepseek/deepseek-reasoner": {
|
|
34660
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
34661
|
+
latencyMs: 4111.9,
|
|
34662
|
+
p95LatencyMs: 5305.7,
|
|
34663
|
+
outputTokensPerSecond: 16.46,
|
|
34664
|
+
errorRate: 0,
|
|
34665
|
+
samples: 3
|
|
34666
|
+
},
|
|
34667
|
+
"deepseek/deepseek-chat": {
|
|
34668
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
34669
|
+
latencyMs: 2648.6,
|
|
34670
|
+
p95LatencyMs: 3524.1,
|
|
34671
|
+
outputTokensPerSecond: 16.73,
|
|
34672
|
+
errorRate: 0,
|
|
34673
|
+
samples: 3
|
|
34674
|
+
},
|
|
34675
|
+
"moonshot/kimi-k2.7": {
|
|
34676
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
34677
|
+
latencyMs: 4295.4,
|
|
34678
|
+
p95LatencyMs: 6153.8,
|
|
34679
|
+
outputTokensPerSecond: 18.54,
|
|
34680
|
+
errorRate: 0,
|
|
34681
|
+
samples: 3
|
|
34682
|
+
},
|
|
34683
|
+
"qwen/qwen3.7-max": {
|
|
34684
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
34685
|
+
latencyMs: 30729.4,
|
|
34686
|
+
p95LatencyMs: 39622,
|
|
34687
|
+
outputTokensPerSecond: 36.89,
|
|
34688
|
+
errorRate: 0.3333,
|
|
34689
|
+
samples: 3
|
|
34690
|
+
},
|
|
34691
|
+
"xai/grok-4.3": {
|
|
34692
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
34693
|
+
latencyMs: 6946.1,
|
|
34694
|
+
p95LatencyMs: 9495.4,
|
|
34695
|
+
outputTokensPerSecond: 65.3,
|
|
34696
|
+
errorRate: 0,
|
|
34697
|
+
samples: 3
|
|
34698
|
+
},
|
|
34699
|
+
"xai/grok-4.20-reasoning": {
|
|
34700
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
34701
|
+
latencyMs: 3472.4,
|
|
34702
|
+
p95LatencyMs: 5332.4,
|
|
34703
|
+
outputTokensPerSecond: 13.27,
|
|
34704
|
+
errorRate: 0,
|
|
34705
|
+
samples: 3
|
|
34706
|
+
},
|
|
34707
|
+
"xai/grok-4.20-non-reasoning": {
|
|
34708
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
34709
|
+
latencyMs: 5174.4,
|
|
34710
|
+
p95LatencyMs: 6081.7,
|
|
34711
|
+
outputTokensPerSecond: 10.21,
|
|
34712
|
+
errorRate: 0.3333,
|
|
34713
|
+
samples: 3
|
|
34714
|
+
},
|
|
34715
|
+
"xai/grok-4-1-fast-reasoning": {
|
|
34716
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
34717
|
+
latencyMs: 13148.2,
|
|
34718
|
+
p95LatencyMs: 19104.2,
|
|
34719
|
+
outputTokensPerSecond: 4.28,
|
|
34720
|
+
errorRate: 0,
|
|
34721
|
+
samples: 3
|
|
34722
|
+
},
|
|
34723
|
+
"minimax/minimax-m3": {
|
|
34724
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
34725
|
+
latencyMs: 3385,
|
|
34726
|
+
p95LatencyMs: 4247.2,
|
|
34727
|
+
outputTokensPerSecond: 15.16,
|
|
34728
|
+
errorRate: 0,
|
|
34729
|
+
samples: 3
|
|
34730
|
+
},
|
|
34731
|
+
"minimax/minimax-m2.7": {
|
|
34732
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
34733
|
+
latencyMs: 4596.7,
|
|
34734
|
+
p95LatencyMs: 6884.6,
|
|
34735
|
+
outputTokensPerSecond: 17.03,
|
|
34736
|
+
errorRate: 0,
|
|
34737
|
+
samples: 3
|
|
34738
|
+
},
|
|
34739
|
+
"zai/glm-5.2": {
|
|
34740
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
34741
|
+
latencyMs: 4406.3,
|
|
34742
|
+
p95LatencyMs: 6139.7,
|
|
34743
|
+
outputTokensPerSecond: 10.41,
|
|
34744
|
+
errorRate: 0,
|
|
34745
|
+
samples: 3
|
|
34746
|
+
},
|
|
34747
|
+
"zai/glm-5.1": {
|
|
34748
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
34749
|
+
latencyMs: 7775.4,
|
|
34750
|
+
p95LatencyMs: 9182.1,
|
|
34751
|
+
outputTokensPerSecond: 6.08,
|
|
34752
|
+
errorRate: 0,
|
|
34753
|
+
samples: 3
|
|
34754
|
+
},
|
|
34755
|
+
"zai/glm-5": {
|
|
34756
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
34757
|
+
latencyMs: 4159.4,
|
|
34758
|
+
p95LatencyMs: 4992.7,
|
|
34759
|
+
outputTokensPerSecond: 10.28,
|
|
34760
|
+
errorRate: 0,
|
|
34761
|
+
samples: 3
|
|
34762
|
+
},
|
|
34763
|
+
"free/qwen3-coder-480b": {
|
|
34764
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
34765
|
+
latencyMs: 2063.9,
|
|
34766
|
+
p95LatencyMs: 3646.3,
|
|
34767
|
+
outputTokensPerSecond: 39.8,
|
|
34768
|
+
errorRate: 0,
|
|
34769
|
+
samples: 3
|
|
34770
|
+
},
|
|
34771
|
+
"free/mistral-large-3-675b": {
|
|
34772
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
34773
|
+
latencyMs: 3147.5,
|
|
34774
|
+
p95LatencyMs: 5555.3,
|
|
34775
|
+
outputTokensPerSecond: 27.76,
|
|
34776
|
+
errorRate: 0,
|
|
34777
|
+
samples: 3
|
|
34778
|
+
},
|
|
34779
|
+
"free/nemotron-3-nano-omni-30b-a3b-reasoning": {
|
|
34780
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
34781
|
+
latencyMs: 6508.4,
|
|
34782
|
+
p95LatencyMs: 14252.7,
|
|
34783
|
+
outputTokensPerSecond: 68.26,
|
|
34784
|
+
errorRate: 0,
|
|
34785
|
+
samples: 3
|
|
34786
|
+
},
|
|
34787
|
+
"free/glm-4.7": {
|
|
34788
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
34789
|
+
latencyMs: 2014.8,
|
|
34790
|
+
p95LatencyMs: 3039.9,
|
|
34791
|
+
outputTokensPerSecond: 39.92,
|
|
34792
|
+
errorRate: 0,
|
|
34793
|
+
samples: 3
|
|
34794
|
+
}
|
|
34795
|
+
};
|
|
34796
|
+
LIVE_MODEL_PROFILES = Object.freeze(
|
|
34797
|
+
model_profiles_generated_default
|
|
34798
|
+
);
|
|
34799
|
+
HISTORICAL_MODEL_PROFILES = Object.freeze({
|
|
34800
|
+
"anthropic/claude-haiku-4.5": {
|
|
34801
|
+
measuredAt: "2026-03-16T13:50:48Z",
|
|
34802
|
+
latencyMs: 2305,
|
|
34803
|
+
outputTokensPerSecond: 140.6
|
|
34804
|
+
},
|
|
34805
|
+
"anthropic/claude-opus-4.6": {
|
|
34806
|
+
measuredAt: "2026-03-16T13:50:48Z",
|
|
34807
|
+
latencyMs: 2139,
|
|
34808
|
+
outputTokensPerSecond: 119.7
|
|
34809
|
+
},
|
|
34810
|
+
"anthropic/claude-sonnet-4.6": {
|
|
34811
|
+
measuredAt: "2026-03-16T13:50:48Z",
|
|
34812
|
+
latencyMs: 2110,
|
|
34813
|
+
outputTokensPerSecond: 121.3
|
|
34814
|
+
},
|
|
34815
|
+
"deepseek/deepseek-chat": {
|
|
34816
|
+
measuredAt: "2026-03-16T13:50:48Z",
|
|
34817
|
+
latencyMs: 1431,
|
|
34818
|
+
outputTokensPerSecond: 179.2,
|
|
34819
|
+
intelligenceIndex: 32
|
|
34820
|
+
},
|
|
34821
|
+
"google/gemini-2.5-flash": {
|
|
34822
|
+
measuredAt: "2026-03-16T13:50:48Z",
|
|
34823
|
+
latencyMs: 1238,
|
|
34824
|
+
outputTokensPerSecond: 207.6,
|
|
34825
|
+
intelligenceIndex: 20
|
|
34826
|
+
},
|
|
34827
|
+
"google/gemini-2.5-flash-lite": {
|
|
34828
|
+
measuredAt: "2026-03-16T13:50:48Z",
|
|
34829
|
+
latencyMs: 1353,
|
|
34830
|
+
outputTokensPerSecond: 192.5,
|
|
34831
|
+
intelligenceIndex: 20
|
|
34832
|
+
},
|
|
34833
|
+
"google/gemini-2.5-pro": {
|
|
34834
|
+
measuredAt: "2026-03-16T13:50:48Z",
|
|
34835
|
+
latencyMs: 1294,
|
|
34836
|
+
outputTokensPerSecond: 197.8
|
|
34837
|
+
},
|
|
34838
|
+
"google/gemini-3.1-pro": {
|
|
34839
|
+
measuredAt: "2026-03-16T13:50:48Z",
|
|
34840
|
+
latencyMs: 1609,
|
|
34841
|
+
outputTokensPerSecond: 167.2
|
|
34842
|
+
},
|
|
34843
|
+
"moonshot/kimi-k2.5": {
|
|
34844
|
+
measuredAt: "2026-03-16T13:50:48Z",
|
|
34845
|
+
latencyMs: 1646,
|
|
34846
|
+
outputTokensPerSecond: 155.7
|
|
34847
|
+
},
|
|
34848
|
+
"openai/gpt-4o-mini": {
|
|
34849
|
+
measuredAt: "2026-03-16T13:50:48Z",
|
|
34850
|
+
latencyMs: 2764,
|
|
34851
|
+
outputTokensPerSecond: 92.8
|
|
34852
|
+
},
|
|
34853
|
+
"openai/gpt-5.3-codex": {
|
|
34854
|
+
measuredAt: "2026-03-16T13:50:48Z",
|
|
34855
|
+
latencyMs: 7935,
|
|
34856
|
+
outputTokensPerSecond: 32.3
|
|
34857
|
+
},
|
|
34858
|
+
"xai/grok-4-1-fast-non-reasoning": {
|
|
34859
|
+
measuredAt: "2026-03-16T13:50:48Z",
|
|
34860
|
+
latencyMs: 1244,
|
|
34861
|
+
outputTokensPerSecond: 205.8,
|
|
34862
|
+
intelligenceIndex: 41
|
|
34863
|
+
},
|
|
34864
|
+
"xai/grok-4-1-fast-reasoning": {
|
|
34865
|
+
measuredAt: "2026-03-16T13:50:48Z",
|
|
34866
|
+
latencyMs: 1454,
|
|
34867
|
+
outputTokensPerSecond: 176.2,
|
|
34868
|
+
intelligenceIndex: 41
|
|
34869
|
+
}
|
|
34870
|
+
});
|
|
34871
|
+
DEFAULT_PORTFOLIO_WEIGHTS = {
|
|
34872
|
+
auto: {
|
|
34873
|
+
quality: 0.47,
|
|
34874
|
+
capability: 0.2,
|
|
34875
|
+
cost: 0.18,
|
|
34876
|
+
speed: 0.07,
|
|
34877
|
+
reliability: 0.03,
|
|
34878
|
+
legacy: 0.05
|
|
34879
|
+
},
|
|
34880
|
+
eco: { quality: 0.36, capability: 0.2, cost: 0.28, speed: 0.1, reliability: 0.04, legacy: 0.02 },
|
|
34881
|
+
premium: {
|
|
34882
|
+
quality: 0.58,
|
|
34883
|
+
capability: 0.2,
|
|
34884
|
+
cost: 0.08,
|
|
34885
|
+
speed: 0.06,
|
|
34886
|
+
reliability: 0.06,
|
|
34887
|
+
legacy: 0.02
|
|
34888
|
+
},
|
|
34889
|
+
highStakesBoost: { quality: 0.08, reliability: 0.05 },
|
|
34890
|
+
latencySensitiveSpeedBoost: 0.08,
|
|
34891
|
+
affinityFloorGap: { auto: 0.1, eco: 0.22, premium: 0.05 }
|
|
34892
|
+
};
|
|
34893
|
+
PortfolioStrategy = class {
|
|
34894
|
+
name = "portfolio";
|
|
34895
|
+
route(prompt, systemPrompt, maxOutputTokens, options) {
|
|
34896
|
+
const features = classifyTask(prompt, systemPrompt, options);
|
|
34897
|
+
const base3 = new RulesStrategy().route(prompt, systemPrompt, maxOutputTokens, {
|
|
34898
|
+
...options,
|
|
34899
|
+
requiresTools: features.needsTools
|
|
34900
|
+
});
|
|
34901
|
+
const tierConfigs = base3.tierConfigs;
|
|
34902
|
+
if (!tierConfigs) return base3;
|
|
34903
|
+
const targetTier = (features.taskType === "reasoning_mcq" || features.taskType === "reasoning_math") && (base3.tier === "SIMPLE" || base3.tier === "MEDIUM") ? "REASONING" : base3.tier;
|
|
34904
|
+
const tierConfig = tierConfigs[targetTier];
|
|
34905
|
+
const configuredCandidates = tierConfig ? getFallbackChain(targetTier, tierConfigs) : [];
|
|
34906
|
+
const chain3 = [
|
|
34907
|
+
.../* @__PURE__ */ new Set([...configuredCandidates, ...evidenceCandidates(features.taskType)])
|
|
34908
|
+
].filter((model2) => typeof model2 === "string" && model2.length > 0);
|
|
34909
|
+
const eligible = chain3.filter(
|
|
34910
|
+
(model2) => isEligible(model2, features, maxOutputTokens, options)
|
|
34911
|
+
);
|
|
34912
|
+
const eligibleCandidates = eligible.length > 0 ? eligible : chain3;
|
|
34913
|
+
if (eligibleCandidates.length === 0) return base3;
|
|
34914
|
+
const profileName = options.routingProfile === "eco" ? "eco" : options.routingProfile === "premium" ? "premium" : "auto";
|
|
34915
|
+
const portfolio = options.config.portfolio ?? DEFAULT_PORTFOLIO_WEIGHTS;
|
|
34916
|
+
const getAffinity = (model2) => affinity(
|
|
34917
|
+
model2,
|
|
34918
|
+
features.taskType,
|
|
34919
|
+
features.language,
|
|
34920
|
+
features.agentDomain,
|
|
34921
|
+
features.deepWebResearch,
|
|
34922
|
+
features.agentRisk,
|
|
34923
|
+
features.terminalToolSignal,
|
|
34924
|
+
features.terminalSafetySensitive
|
|
34925
|
+
);
|
|
34926
|
+
const bestAffinity = Math.max(...eligibleCandidates.map(getAffinity));
|
|
34927
|
+
const specificAffinity = eligibleCandidates.filter((model2) => getAffinity(model2) > 0.68);
|
|
34928
|
+
const affinityPool = specificAffinity.length > 0 ? specificAffinity : [eligibleCandidates[0]];
|
|
34929
|
+
const affinityFloorGap = features.terminalToolSignal ? Math.max(
|
|
34930
|
+
portfolio.affinityFloorGap[profileName],
|
|
34931
|
+
features.terminalSafetySensitive ? 0.15 : 0.12
|
|
34932
|
+
) : portfolio.affinityFloorGap[profileName];
|
|
34933
|
+
const candidates = affinityPool.filter(
|
|
34934
|
+
(model2) => getAffinity(model2) >= bestAffinity - affinityFloorGap
|
|
34935
|
+
);
|
|
34936
|
+
const costs = candidates.map(
|
|
34937
|
+
(model2) => estimatedCost(model2, options, features.estimatedInputTokens, maxOutputTokens)
|
|
34938
|
+
);
|
|
34939
|
+
const finiteCosts = costs.filter(Number.isFinite);
|
|
34940
|
+
const minCost = finiteCosts.length > 0 ? Math.min(...finiteCosts) : 0;
|
|
34941
|
+
const maxCost = finiteCosts.length > 0 ? Math.max(...finiteCosts) : 1;
|
|
34942
|
+
const now2 = options.now ?? /* @__PURE__ */ new Date();
|
|
34943
|
+
const profileWeights = portfolio[profileName];
|
|
34944
|
+
const rankedEntries = candidates.map((model2, index2) => {
|
|
34945
|
+
const cost = estimatedCost(model2, options, features.estimatedInputTokens, maxOutputTokens);
|
|
34946
|
+
const costScore = Number.isFinite(cost) && maxCost > minCost ? 1 - (cost - minCost) / (maxCost - minCost) : 0.5;
|
|
34947
|
+
const capabilityScore = isEligible(model2, features, maxOutputTokens, options) ? 1 : 0;
|
|
34948
|
+
const profile = profileScore(model2, options, now2);
|
|
34949
|
+
const observedQuality = profile?.quality === void 0 ? getAffinity(model2) : getAffinity(model2) * (1 - profile.freshness) + profile.quality * profile.freshness;
|
|
34950
|
+
const observedSpeed = profile ? profile.speed * profile.freshness : 0.5;
|
|
34951
|
+
const observedTailSpeed = profile ? profile.tailSpeed * profile.freshness : 0.5;
|
|
34952
|
+
const observedReliability = profile ? profile.reliability * profile.freshness + (1 - profile.freshness) : 1;
|
|
34953
|
+
const legacyScore = 1 - index2 / Math.max(1, candidates.length - 1);
|
|
34954
|
+
const qualityWeight = profileWeights.quality + (features.highStakes ? portfolio.highStakesBoost.quality : 0);
|
|
34955
|
+
const speedScore = features.latencySensitive ? observedTailSpeed : observedSpeed;
|
|
34956
|
+
const speedWeight = profileWeights.speed + (features.latencySensitive ? portfolio.latencySensitiveSpeedBoost : 0);
|
|
34957
|
+
const reliabilityWeight = profileWeights.reliability + (features.highStakes ? portfolio.highStakesBoost.reliability : 0);
|
|
34958
|
+
const score = observedQuality * qualityWeight + capabilityScore * profileWeights.capability + costScore * profileWeights.cost + speedScore * speedWeight + observedReliability * reliabilityWeight + legacyScore * profileWeights.legacy;
|
|
34959
|
+
return {
|
|
34960
|
+
model: model2,
|
|
34961
|
+
score,
|
|
34962
|
+
quality: observedQuality,
|
|
34963
|
+
cost: costScore,
|
|
34964
|
+
speed: speedScore,
|
|
34965
|
+
reliability: observedReliability
|
|
34966
|
+
};
|
|
34967
|
+
}).sort((a, b) => b.score - a.score);
|
|
34968
|
+
const scoredModels = rankedEntries.map((item) => item.model);
|
|
34969
|
+
const webResearchFallbackOrder = [
|
|
34970
|
+
"anthropic/claude-sonnet-5",
|
|
34971
|
+
"openai/gpt-5-mini",
|
|
34972
|
+
"google/gemini-3.5-flash",
|
|
34973
|
+
"anthropic/claude-opus-5",
|
|
34974
|
+
"anthropic/claude-opus-4.8",
|
|
34975
|
+
"openai/gpt-5.3-codex"
|
|
34976
|
+
];
|
|
34977
|
+
const ranked = features.agentDomain === "web_research" ? [
|
|
34978
|
+
...scoredModels,
|
|
34979
|
+
...webResearchFallbackOrder.filter(
|
|
34980
|
+
(model2) => eligibleCandidates.includes(model2) && !scoredModels.includes(model2)
|
|
34981
|
+
),
|
|
34982
|
+
...eligibleCandidates.filter(
|
|
34983
|
+
(model2) => !scoredModels.includes(model2) && !webResearchFallbackOrder.includes(model2)
|
|
34984
|
+
)
|
|
34985
|
+
] : features.taskType === "tool_agent" || features.taskType === "tool_agent_parallel" && features.agentDomain !== "other" ? [
|
|
34986
|
+
...scoredModels,
|
|
34987
|
+
...eligibleCandidates.filter((model2) => !scoredModels.includes(model2))
|
|
34988
|
+
] : [
|
|
34989
|
+
...scoredModels,
|
|
34990
|
+
...eligibleCandidates.filter((model2) => !scoredModels.includes(model2))
|
|
34991
|
+
];
|
|
34992
|
+
const model = ranked[0] ?? base3.model;
|
|
34993
|
+
const selectedTierConfigs = {
|
|
34994
|
+
...tierConfigs,
|
|
34995
|
+
[targetTier]: { primary: model, fallback: ranked.slice(1) }
|
|
34996
|
+
};
|
|
34997
|
+
const decision = selectModel(
|
|
34998
|
+
targetTier,
|
|
34999
|
+
base3.confidence,
|
|
35000
|
+
"portfolio",
|
|
35001
|
+
`${base3.reasoning} | v3 task=${features.taskType} agentRisk=${features.agentRisk} deepWebResearch=${features.deepWebResearch} terminalCode=${features.implicitTerminalCode} terminalSafety=${features.terminalSafetySensitive} candidates=${ranked.length}`,
|
|
35002
|
+
selectedTierConfigs,
|
|
35003
|
+
options.modelPricing,
|
|
35004
|
+
features.estimatedInputTokens,
|
|
35005
|
+
maxOutputTokens,
|
|
35006
|
+
options.routingProfile,
|
|
35007
|
+
base3.agenticScore
|
|
35008
|
+
);
|
|
35009
|
+
return {
|
|
35010
|
+
...decision,
|
|
35011
|
+
tierConfigs: selectedTierConfigs,
|
|
35012
|
+
profile: base3.profile,
|
|
35013
|
+
candidates: ranked,
|
|
35014
|
+
candidateScores: rankedEntries.map(({ model: model2, score, quality, cost, speed, reliability }) => ({
|
|
35015
|
+
model: model2,
|
|
35016
|
+
score,
|
|
35017
|
+
quality,
|
|
35018
|
+
cost,
|
|
35019
|
+
speed,
|
|
35020
|
+
reliability
|
|
35021
|
+
})),
|
|
35022
|
+
taskType: features.taskType,
|
|
35023
|
+
routerVersion: "v3-portfolio"
|
|
35024
|
+
};
|
|
35025
|
+
}
|
|
35026
|
+
};
|
|
33649
35027
|
DEFAULT_ROUTING_CONFIG = {
|
|
33650
|
-
version: "
|
|
35028
|
+
version: "3.4",
|
|
35029
|
+
strategy: "portfolio",
|
|
35030
|
+
portfolio: {
|
|
35031
|
+
auto: {
|
|
35032
|
+
quality: 0.47,
|
|
35033
|
+
capability: 0.2,
|
|
35034
|
+
cost: 0.18,
|
|
35035
|
+
speed: 0.07,
|
|
35036
|
+
reliability: 0.03,
|
|
35037
|
+
legacy: 0.05
|
|
35038
|
+
},
|
|
35039
|
+
eco: {
|
|
35040
|
+
quality: 0.36,
|
|
35041
|
+
capability: 0.2,
|
|
35042
|
+
cost: 0.28,
|
|
35043
|
+
speed: 0.1,
|
|
35044
|
+
reliability: 0.04,
|
|
35045
|
+
legacy: 0.02
|
|
35046
|
+
},
|
|
35047
|
+
premium: {
|
|
35048
|
+
quality: 0.58,
|
|
35049
|
+
capability: 0.2,
|
|
35050
|
+
cost: 0.08,
|
|
35051
|
+
speed: 0.06,
|
|
35052
|
+
reliability: 0.06,
|
|
35053
|
+
legacy: 0.02
|
|
35054
|
+
},
|
|
35055
|
+
highStakesBoost: { quality: 0.08, reliability: 0.05 },
|
|
35056
|
+
latencySensitiveSpeedBoost: 0.08,
|
|
35057
|
+
affinityFloorGap: { auto: 0.1, eco: 0.22, premium: 0.05 }
|
|
35058
|
+
},
|
|
33651
35059
|
classifier: {
|
|
33652
35060
|
llmModel: "google/gemini-2.5-flash",
|
|
33653
35061
|
llmMaxTokens: 10,
|
|
@@ -34773,8 +36181,8 @@ var init_config = __esm({
|
|
|
34773
36181
|
// FREE — smaller, faster
|
|
34774
36182
|
"free/deepseek-v4-flash",
|
|
34775
36183
|
// FREE — 1M ctx; slow (~10 tok/s, 07-28 probe) but completes
|
|
34776
|
-
|
|
34777
|
-
//
|
|
36184
|
+
// seed-oss-36b sat here as the free coder until it EOL'd 2026-08-03 (HTTP 410).
|
|
36185
|
+
// gpt-oss-120b/20b already head this chain, so the rung is dropped, not retargeted.
|
|
34778
36186
|
"google/gemini-3.1-flash-lite",
|
|
34779
36187
|
// $0.25/$1.50 — newest flash-lite
|
|
34780
36188
|
"openai/gpt-5.4-nano",
|
|
@@ -34891,8 +36299,8 @@ var init_config = __esm({
|
|
|
34891
36299
|
"openai/gpt-5.3-codex",
|
|
34892
36300
|
"deepseek/deepseek-chat",
|
|
34893
36301
|
// Cheap, reliable
|
|
34894
|
-
"free/
|
|
34895
|
-
// NVIDIA free ultimate backstop (
|
|
36302
|
+
"free/gpt-oss-120b"
|
|
36303
|
+
// NVIDIA free ultimate backstop (was seed-oss-36b; EOL'd 2026-08-03)
|
|
34896
36304
|
]
|
|
34897
36305
|
},
|
|
34898
36306
|
REASONING: {
|
|
@@ -34981,8 +36389,8 @@ var init_config = __esm({
|
|
|
34981
36389
|
// Previous flagship — 6,213ms, reliable
|
|
34982
36390
|
"deepseek/deepseek-chat",
|
|
34983
36391
|
// 1,431ms — cheap, reliable
|
|
34984
|
-
"free/
|
|
34985
|
-
// NVIDIA free ultimate backstop (
|
|
36392
|
+
"free/gpt-oss-120b"
|
|
36393
|
+
// NVIDIA free ultimate backstop (was seed-oss-36b; EOL'd 2026-08-03)
|
|
34986
36394
|
]
|
|
34987
36395
|
},
|
|
34988
36396
|
REASONING: {
|
|
@@ -35027,21 +36435,15 @@ var init_config = __esm({
|
|
|
35027
36435
|
// Set to `true` to force agentic tiers; `false` to disable them entirely.
|
|
35028
36436
|
}
|
|
35029
36437
|
};
|
|
36438
|
+
registerStrategy(new PortfolioStrategy());
|
|
35030
36439
|
}
|
|
35031
36440
|
});
|
|
35032
36441
|
|
|
35033
36442
|
// src/router/index.ts
|
|
35034
|
-
function route(prompt, systemPrompt, maxOutputTokens, options) {
|
|
35035
|
-
const strategy = getStrategy("rules");
|
|
35036
|
-
return strategy.route(prompt, systemPrompt, maxOutputTokens, options);
|
|
35037
|
-
}
|
|
35038
36443
|
var init_router = __esm({
|
|
35039
36444
|
"src/router/index.ts"() {
|
|
35040
36445
|
"use strict";
|
|
35041
|
-
|
|
35042
|
-
init_strategy();
|
|
35043
|
-
init_selector();
|
|
35044
|
-
init_config();
|
|
36446
|
+
init_dist();
|
|
35045
36447
|
}
|
|
35046
36448
|
});
|
|
35047
36449
|
|
|
@@ -35090,7 +36492,6 @@ var init_top_models = __esm({
|
|
|
35090
36492
|
"deepseek/deepseek-chat",
|
|
35091
36493
|
"deepseek/deepseek-reasoner",
|
|
35092
36494
|
"free/deepseek-v4-flash",
|
|
35093
|
-
"free/seed-oss-36b",
|
|
35094
36495
|
"free/nemotron-3-nano-omni-30b-a3b-reasoning",
|
|
35095
36496
|
"free/mistral-nemotron",
|
|
35096
36497
|
"free/step-3.7-flash",
|
|
@@ -35400,9 +36801,10 @@ var init_models = __esm({
|
|
|
35400
36801
|
"free/deepseek-v4-pro": "free/deepseek-v4-flash",
|
|
35401
36802
|
"nvidia/deepseek-v4-flash": "free/deepseek-v4-flash",
|
|
35402
36803
|
"nvidia/nemotron-3-nano-omni-30b-a3b-reasoning": "free/nemotron-3-nano-omni-30b-a3b-reasoning",
|
|
35403
|
-
// qwen3-coder-480b retired (NVIDIA EOL 2026-06-14)
|
|
35404
|
-
//
|
|
35405
|
-
//
|
|
36804
|
+
// qwen3-coder-480b retired (NVIDIA EOL 2026-06-14). Its server-side redirect used
|
|
36805
|
+
// to be seed-oss-36b, but that EOL'd too on 2026-08-03, so blockrun re-pointed it
|
|
36806
|
+
// at gpt-oss-120b. Keep the explicit id mappings for pinned callers (BlockRun still
|
|
36807
|
+
// resolves them); the generic coding shorthands follow the gateway to gpt-oss-120b.
|
|
35406
36808
|
"nvidia/qwen3-coder-480b": "free/qwen3-coder-480b",
|
|
35407
36809
|
"qwen/qwen3-coder-480b-a35b-instruct": "free/qwen3-coder-480b",
|
|
35408
36810
|
// glm-4.7 pin keeps the real id — blockrun redirects it server-side (→ gpt-oss-120b).
|
|
@@ -35448,13 +36850,14 @@ var init_models = __esm({
|
|
|
35448
36850
|
"v4-flash": "free/deepseek-v4-flash",
|
|
35449
36851
|
"mistral-free": "free/mistral-nemotron",
|
|
35450
36852
|
// mistral-large-3-675b EOL'd 2026-07-28 → last live free Mistral (blockrun demoted its /free-mistral primary the same way)
|
|
35451
|
-
"glm-free": "free/
|
|
35452
|
-
//
|
|
36853
|
+
"glm-free": "free/gpt-oss-120b",
|
|
36854
|
+
// seed-oss-36b (the prior target) EOL'd 2026-08-03
|
|
35453
36855
|
"llama-free": "free/gpt-oss-120b",
|
|
35454
36856
|
// no live free Llama left (maverick died 2026-07)
|
|
35455
|
-
|
|
35456
|
-
//
|
|
35457
|
-
"qwen-coder
|
|
36857
|
+
// qwen3-coder-480b retired 2026-06-14 → seed-oss-36b, which then EOL'd 2026-08-03.
|
|
36858
|
+
// Follow the gateway's own retarget rather than chaining to a second dead model.
|
|
36859
|
+
"qwen-coder": "free/gpt-oss-120b",
|
|
36860
|
+
"qwen-coder-free": "free/gpt-oss-120b",
|
|
35458
36861
|
"qwen-thinking": "free/gpt-oss-120b",
|
|
35459
36862
|
// qwen3-next died 2026-07-17; no live free Qwen left
|
|
35460
36863
|
"qwen3-next": "free/qwen3-next-80b-a3b-instruct",
|
|
@@ -35463,9 +36866,11 @@ var init_models = __esm({
|
|
|
35463
36866
|
"mistral-small": "free/mistral-nemotron",
|
|
35464
36867
|
// closest live Mistral-family free model
|
|
35465
36868
|
// New live free models (2026-06-14 BlockRun free-tier refresh)
|
|
36869
|
+
// seed-oss pins name the model itself — kept routable, the gateway redirects them.
|
|
35466
36870
|
"seed-oss": "free/seed-oss-36b",
|
|
35467
36871
|
"seed-oss-36b": "free/seed-oss-36b",
|
|
35468
|
-
"coder-free": "free/
|
|
36872
|
+
"coder-free": "free/gpt-oss-120b",
|
|
36873
|
+
// generic "a free coder" → follows the gateway retarget
|
|
35469
36874
|
"mistral-nemotron": "free/mistral-nemotron",
|
|
35470
36875
|
"step-flash": "free/step-3.7-flash",
|
|
35471
36876
|
"step-3.7-flash": "free/step-3.7-flash",
|
|
@@ -35486,8 +36891,9 @@ var init_models = __esm({
|
|
|
35486
36891
|
"nemotron-super": "free/gpt-oss-120b",
|
|
35487
36892
|
"nemotron-49b": "free/gpt-oss-120b",
|
|
35488
36893
|
"nemotron-120b": "free/gpt-oss-120b",
|
|
35489
|
-
devstral: "free/
|
|
35490
|
-
|
|
36894
|
+
devstral: "free/gpt-oss-120b",
|
|
36895
|
+
// seed-oss-36b EOL'd 2026-08-03; matches blockrun's own retarget
|
|
36896
|
+
"devstral-2": "free/gpt-oss-120b",
|
|
35491
36897
|
maverick: "free/llama-4-maverick",
|
|
35492
36898
|
// explicit-ish pin — gateway redirects
|
|
35493
36899
|
free: "free/gpt-oss-120b",
|
|
@@ -36610,8 +38016,13 @@ var init_models = __esm({
|
|
|
36610
38016
|
reasoning: true
|
|
36611
38017
|
},
|
|
36612
38018
|
{
|
|
36613
|
-
// ByteDance Seed-OSS 36B:
|
|
36614
|
-
//
|
|
38019
|
+
// ByteDance Seed-OSS 36B: was the free coder, and the redirect target for the
|
|
38020
|
+
// retired qwen3-coder-480b. EOL'd 2026-08-03 — blockrun's probe got HTTP 410
|
|
38021
|
+
// Gone from NVIDIA on both passes and the prod health gate fired
|
|
38022
|
+
// [ALERT][free-model-dead] kind=gone the same day; upstream now hides it and
|
|
38023
|
+
// re-pointed its own dependents (qwen3-coder-480b, devstral-2) at gpt-oss-120b.
|
|
38024
|
+
// Entry kept so explicit pins stay routable; off the picker, the FREE_MODELS
|
|
38025
|
+
// cascade, and the router fallback chains.
|
|
36615
38026
|
id: "free/seed-oss-36b",
|
|
36616
38027
|
name: "[Free] Seed-OSS 36B",
|
|
36617
38028
|
version: "oss-36b",
|
|
@@ -56787,7 +58198,7 @@ var init_exclude_models = __esm({
|
|
|
56787
58198
|
|
|
56788
58199
|
// src/config.ts
|
|
56789
58200
|
var DEFAULT_PORT, PROXY_PORT;
|
|
56790
|
-
var
|
|
58201
|
+
var init_config = __esm({
|
|
56791
58202
|
"src/config.ts"() {
|
|
56792
58203
|
"use strict";
|
|
56793
58204
|
DEFAULT_PORT = 8402;
|
|
@@ -73185,27 +74596,27 @@ var require_dns = __commonJS({
|
|
|
73185
74596
|
}
|
|
73186
74597
|
);
|
|
73187
74598
|
}
|
|
73188
|
-
#defaultPick(origin2, hostnameRecords,
|
|
74599
|
+
#defaultPick(origin2, hostnameRecords, affinity2) {
|
|
73189
74600
|
let ip = null;
|
|
73190
74601
|
const { records, offset } = hostnameRecords;
|
|
73191
74602
|
let family;
|
|
73192
74603
|
if (this.dualStack) {
|
|
73193
|
-
if (
|
|
74604
|
+
if (affinity2 == null) {
|
|
73194
74605
|
if (offset == null || offset === maxInt) {
|
|
73195
74606
|
hostnameRecords.offset = 0;
|
|
73196
|
-
|
|
74607
|
+
affinity2 = 4;
|
|
73197
74608
|
} else {
|
|
73198
74609
|
hostnameRecords.offset++;
|
|
73199
|
-
|
|
74610
|
+
affinity2 = (hostnameRecords.offset & 1) === 1 ? 6 : 4;
|
|
73200
74611
|
}
|
|
73201
74612
|
}
|
|
73202
|
-
if (records[
|
|
73203
|
-
family = records[
|
|
74613
|
+
if (records[affinity2] != null && records[affinity2].ips.length > 0) {
|
|
74614
|
+
family = records[affinity2];
|
|
73204
74615
|
} else {
|
|
73205
|
-
family = records[
|
|
74616
|
+
family = records[affinity2 === 4 ? 6 : 4];
|
|
73206
74617
|
}
|
|
73207
74618
|
} else {
|
|
73208
|
-
family = records[
|
|
74619
|
+
family = records[affinity2];
|
|
73209
74620
|
}
|
|
73210
74621
|
if (family == null || family.ips.length === 0) {
|
|
73211
74622
|
return ip;
|
|
@@ -73222,7 +74633,7 @@ var require_dns = __commonJS({
|
|
|
73222
74633
|
}
|
|
73223
74634
|
if (Date.now() - ip.timestamp > ip.ttl) {
|
|
73224
74635
|
family.ips.splice(position, 1);
|
|
73225
|
-
return this.pick(origin2, hostnameRecords,
|
|
74636
|
+
return this.pick(origin2, hostnameRecords, affinity2);
|
|
73226
74637
|
}
|
|
73227
74638
|
return ip;
|
|
73228
74639
|
}
|
|
@@ -73361,11 +74772,11 @@ var require_dns = __commonJS({
|
|
|
73361
74772
|
throw new InvalidArgumentError("Invalid storage. Must be a object with methods: { get, set, full, delete }");
|
|
73362
74773
|
}
|
|
73363
74774
|
const dualStack = interceptorOpts?.dualStack ?? true;
|
|
73364
|
-
let
|
|
74775
|
+
let affinity2;
|
|
73365
74776
|
if (dualStack) {
|
|
73366
|
-
|
|
74777
|
+
affinity2 = interceptorOpts?.affinity ?? null;
|
|
73367
74778
|
} else {
|
|
73368
|
-
|
|
74779
|
+
affinity2 = interceptorOpts?.affinity ?? 4;
|
|
73369
74780
|
}
|
|
73370
74781
|
const opts = {
|
|
73371
74782
|
maxTTL: interceptorOpts?.maxTTL ?? 1e4,
|
|
@@ -73373,7 +74784,7 @@ var require_dns = __commonJS({
|
|
|
73373
74784
|
lookup: interceptorOpts?.lookup ?? null,
|
|
73374
74785
|
pick: interceptorOpts?.pick ?? null,
|
|
73375
74786
|
dualStack,
|
|
73376
|
-
affinity,
|
|
74787
|
+
affinity: affinity2,
|
|
73377
74788
|
maxItems: interceptorOpts?.maxItems ?? Infinity,
|
|
73378
74789
|
storage: interceptorOpts?.storage
|
|
73379
74790
|
};
|
|
@@ -86668,6 +88079,19 @@ function buildModelPricing() {
|
|
|
86668
88079
|
}
|
|
86669
88080
|
return map;
|
|
86670
88081
|
}
|
|
88082
|
+
function buildModelCapabilities() {
|
|
88083
|
+
return Object.fromEntries(
|
|
88084
|
+
BLOCKRUN_MODELS.map((model) => [
|
|
88085
|
+
model.id,
|
|
88086
|
+
{
|
|
88087
|
+
contextWindow: model.contextWindow,
|
|
88088
|
+
maxOutputTokens: model.maxOutput,
|
|
88089
|
+
supportsTools: model.toolCalling === true,
|
|
88090
|
+
supportsVision: model.vision === true
|
|
88091
|
+
}
|
|
88092
|
+
])
|
|
88093
|
+
);
|
|
88094
|
+
}
|
|
86671
88095
|
function buildProxyModelList(createdAt = Math.floor(Date.now() / 1e3)) {
|
|
86672
88096
|
const seen = /* @__PURE__ */ new Set();
|
|
86673
88097
|
return OPENCLAW_MODELS.filter((model) => {
|
|
@@ -87013,7 +88437,8 @@ async function startProxy(options) {
|
|
|
87013
88437
|
const modelPricing = buildModelPricing();
|
|
87014
88438
|
const routerOpts = {
|
|
87015
88439
|
config: routingConfig,
|
|
87016
|
-
modelPricing
|
|
88440
|
+
modelPricing,
|
|
88441
|
+
modelCapabilities: buildModelCapabilities()
|
|
87017
88442
|
};
|
|
87018
88443
|
const deduplicator = new RequestDeduplicator();
|
|
87019
88444
|
const responseCache2 = new ResponseCache(options.cacheConfig);
|
|
@@ -88159,6 +89584,7 @@ async function proxyRequest(req, res, apiBase, payFetch, options, routerOpts, de
|
|
|
88159
89584
|
let maxTokens = DEFAULT_MAX_TOKENS;
|
|
88160
89585
|
let routingProfile = null;
|
|
88161
89586
|
let stickyExplicitModel;
|
|
89587
|
+
let pendingShadowComparison;
|
|
88162
89588
|
let balanceFallbackNotice;
|
|
88163
89589
|
let budgetDowngradeNotice;
|
|
88164
89590
|
let budgetDowngradeHeaderMode;
|
|
@@ -88754,8 +90180,16 @@ async function proxyRequest(req, res, apiBase, payFetch, options, routerOpts, de
|
|
|
88754
90180
|
const systemPrompt = typeof systemMsg?.content === "string" ? systemMsg.content : void 0;
|
|
88755
90181
|
const tools = parsed.tools;
|
|
88756
90182
|
hasTools = Array.isArray(tools) && tools.length > 0;
|
|
90183
|
+
const requiresTools = hasTools && inferToolRequirement(prompt, systemPrompt, parsed.tool_choice);
|
|
90184
|
+
const toolNames = (tools ?? []).map((tool) => {
|
|
90185
|
+
if (typeof tool !== "object" || tool === null) return void 0;
|
|
90186
|
+
const fn = tool.function;
|
|
90187
|
+
if (typeof fn !== "object" || fn === null) return void 0;
|
|
90188
|
+
const name = fn.name;
|
|
90189
|
+
return typeof name === "string" ? name : void 0;
|
|
90190
|
+
}).filter((name) => name !== void 0);
|
|
88757
90191
|
if (hasTools && tools) {
|
|
88758
|
-
console.log(`[ClawRouter] Tools detected (${tools.length}),
|
|
90192
|
+
console.log(`[ClawRouter] Tools detected (${tools.length}), required=${requiresTools}`);
|
|
88759
90193
|
}
|
|
88760
90194
|
hasVision = parsedMessages.some((m) => {
|
|
88761
90195
|
if (Array.isArray(m.content)) {
|
|
@@ -88769,8 +90203,36 @@ async function proxyRequest(req, res, apiBase, payFetch, options, routerOpts, de
|
|
|
88769
90203
|
routingDecision = route(prompt, systemPrompt, maxTokens, {
|
|
88770
90204
|
...routerOpts,
|
|
88771
90205
|
routingProfile: routingProfile ?? void 0,
|
|
88772
|
-
hasTools
|
|
90206
|
+
hasTools,
|
|
90207
|
+
toolCount: tools?.length ?? 0,
|
|
90208
|
+
toolNames,
|
|
90209
|
+
requiresTools,
|
|
90210
|
+
hasVision,
|
|
90211
|
+
requiresStructuredOutput: typeof parsed.response_format === "object" && parsed.response_format !== null
|
|
88773
90212
|
});
|
|
90213
|
+
const shadow = routerOpts.config.shadow;
|
|
90214
|
+
const activeStrategy = routerOpts.config.strategy ?? "portfolio";
|
|
90215
|
+
const shadowRate = Math.max(0, Math.min(1, shadow?.sampleRate ?? 1));
|
|
90216
|
+
if (shadow && shadow.strategy !== activeStrategy && Math.random() < shadowRate) {
|
|
90217
|
+
const requiresStructuredOutput = typeof parsed.response_format === "object" && parsed.response_format !== null;
|
|
90218
|
+
const shadowDecision = route(prompt, systemPrompt, maxTokens, {
|
|
90219
|
+
...routerOpts,
|
|
90220
|
+
config: { ...routerOpts.config, strategy: shadow.strategy },
|
|
90221
|
+
routingProfile: routingProfile ?? void 0,
|
|
90222
|
+
hasTools,
|
|
90223
|
+
toolCount: tools?.length ?? 0,
|
|
90224
|
+
toolNames,
|
|
90225
|
+
requiresTools,
|
|
90226
|
+
hasVision,
|
|
90227
|
+
requiresStructuredOutput
|
|
90228
|
+
});
|
|
90229
|
+
pendingShadowComparison = {
|
|
90230
|
+
shadow: shadowDecision,
|
|
90231
|
+
hasTools,
|
|
90232
|
+
hasVision,
|
|
90233
|
+
requiresStructuredOutput
|
|
90234
|
+
};
|
|
90235
|
+
}
|
|
88774
90236
|
if (hasTools && routingDecision.tier === "SIMPLE") {
|
|
88775
90237
|
console.log(
|
|
88776
90238
|
`[ClawRouter] SIMPLE+tools: keeping agentic model ${routingDecision.model} (tools need reliable function-call support)`
|
|
@@ -88879,6 +90341,21 @@ async function proxyRequest(req, res, apiBase, payFetch, options, routerOpts, de
|
|
|
88879
90341
|
);
|
|
88880
90342
|
}
|
|
88881
90343
|
}
|
|
90344
|
+
if (pendingShadowComparison) {
|
|
90345
|
+
try {
|
|
90346
|
+
options.onShadowRouted?.({
|
|
90347
|
+
executed: routingDecision,
|
|
90348
|
+
shadow: pendingShadowComparison.shadow,
|
|
90349
|
+
sameModel: routingDecision.model === pendingShadowComparison.shadow.model,
|
|
90350
|
+
hasTools: pendingShadowComparison.hasTools,
|
|
90351
|
+
hasVision: pendingShadowComparison.hasVision,
|
|
90352
|
+
requiresStructuredOutput: pendingShadowComparison.requiresStructuredOutput
|
|
90353
|
+
});
|
|
90354
|
+
} catch (err) {
|
|
90355
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
90356
|
+
console.warn(`[ClawRouter] Shadow routing callback failed: ${message}`);
|
|
90357
|
+
}
|
|
90358
|
+
}
|
|
88882
90359
|
options.onRouted?.(routingDecision);
|
|
88883
90360
|
}
|
|
88884
90361
|
}
|
|
@@ -89226,35 +90703,64 @@ async function proxyRequest(req, res, apiBase, payFetch, options, routerOpts, de
|
|
|
89226
90703
|
const estimatedInputTokens = Math.ceil(body.length / 4);
|
|
89227
90704
|
const estimatedTotalTokens = estimatedInputTokens + maxTokens;
|
|
89228
90705
|
const tierConfigs = routingDecision.tierConfigs ?? routerOpts.config.tiers;
|
|
89229
|
-
const
|
|
89230
|
-
|
|
89231
|
-
|
|
89232
|
-
|
|
89233
|
-
|
|
89234
|
-
|
|
89235
|
-
|
|
89236
|
-
|
|
89237
|
-
|
|
89238
|
-
|
|
90706
|
+
const rankedCandidates = routingDecision.candidates ?? getFallbackChain(routingDecision.tier, tierConfigs);
|
|
90707
|
+
const selectedModel = routingDecision.model;
|
|
90708
|
+
const fullChain = prependStickyExplicitModel([
|
|
90709
|
+
selectedModel,
|
|
90710
|
+
...rankedCandidates.filter((model) => model !== selectedModel)
|
|
90711
|
+
]);
|
|
90712
|
+
const contextFiltered = filterCandidatesByCapacity(
|
|
90713
|
+
fullChain,
|
|
90714
|
+
estimatedInputTokens,
|
|
90715
|
+
maxTokens,
|
|
90716
|
+
(modelId2) => {
|
|
90717
|
+
const model = BLOCKRUN_MODEL_BY_ID.get(modelId2);
|
|
90718
|
+
return model ? { contextWindow: model.contextWindow, maxOutput: model.maxOutput } : void 0;
|
|
90719
|
+
}
|
|
89239
90720
|
);
|
|
90721
|
+
if (contextFiltered.length === 0) {
|
|
90722
|
+
const errPayload = JSON.stringify({
|
|
90723
|
+
error: {
|
|
90724
|
+
message: `No routed model can satisfy the requested context and output capacity (~${estimatedTotalTokens} tokens). Reduce the input or max_tokens and retry.`,
|
|
90725
|
+
type: "invalid_request_error",
|
|
90726
|
+
code: "context_capacity_exceeded"
|
|
90727
|
+
}
|
|
90728
|
+
});
|
|
90729
|
+
if (heartbeatInterval) {
|
|
90730
|
+
clearInterval(heartbeatInterval);
|
|
90731
|
+
heartbeatInterval = void 0;
|
|
90732
|
+
}
|
|
90733
|
+
if (headersSentEarly) {
|
|
90734
|
+
safeWrite(res, `data: ${errPayload}
|
|
90735
|
+
|
|
90736
|
+
data: [DONE]
|
|
90737
|
+
|
|
90738
|
+
`);
|
|
90739
|
+
res.end();
|
|
90740
|
+
} else {
|
|
90741
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
90742
|
+
res.end(errPayload);
|
|
90743
|
+
}
|
|
90744
|
+
completed = true;
|
|
90745
|
+
deduplicator.removeInflight(dedupKey);
|
|
90746
|
+
clearTimeout(timeoutId);
|
|
90747
|
+
req.removeListener("close", onClientClose);
|
|
90748
|
+
return;
|
|
90749
|
+
}
|
|
89240
90750
|
const contextExcluded = fullChain.filter((m) => !contextFiltered.includes(m));
|
|
89241
90751
|
if (contextExcluded.length > 0) {
|
|
89242
90752
|
console.log(
|
|
89243
90753
|
`[ClawRouter] Context filter (~${estimatedTotalTokens} tokens): excluded ${contextExcluded.join(", ")}`
|
|
89244
90754
|
);
|
|
89245
90755
|
}
|
|
89246
|
-
const excludeFiltered =
|
|
89247
|
-
filterByExcludeList(contextFiltered, excludeList)
|
|
89248
|
-
);
|
|
90756
|
+
const excludeFiltered = filterByExcludeList(contextFiltered, excludeList);
|
|
89249
90757
|
const excludeExcluded = contextFiltered.filter((m) => !excludeFiltered.includes(m));
|
|
89250
90758
|
if (excludeExcluded.length > 0) {
|
|
89251
90759
|
console.log(
|
|
89252
90760
|
`[ClawRouter] Exclude filter: excluded ${excludeExcluded.join(", ")} (user preference)`
|
|
89253
90761
|
);
|
|
89254
90762
|
}
|
|
89255
|
-
let toolFiltered =
|
|
89256
|
-
filterByToolCalling(excludeFiltered, hasTools, supportsToolCalling)
|
|
89257
|
-
);
|
|
90763
|
+
let toolFiltered = filterByToolCalling(excludeFiltered, hasTools, supportsToolCalling);
|
|
89258
90764
|
const toolExcluded = excludeFiltered.filter((m) => !toolFiltered.includes(m));
|
|
89259
90765
|
if (toolExcluded.length > 0) {
|
|
89260
90766
|
console.log(
|
|
@@ -89273,19 +90779,17 @@ async function proxyRequest(req, res, apiBase, payFetch, options, routerOpts, de
|
|
|
89273
90779
|
console.log(
|
|
89274
90780
|
`[ClawRouter] Tool-compliance filter: excluded ${dropped.join(", ")} (unreliable tool schema handling)`
|
|
89275
90781
|
);
|
|
89276
|
-
toolFiltered =
|
|
90782
|
+
toolFiltered = compliant;
|
|
89277
90783
|
}
|
|
89278
90784
|
}
|
|
89279
|
-
const visionFiltered =
|
|
89280
|
-
filterByVision(toolFiltered, hasVision, supportsVision)
|
|
89281
|
-
);
|
|
90785
|
+
const visionFiltered = filterByVision(toolFiltered, hasVision, supportsVision);
|
|
89282
90786
|
const visionExcluded = toolFiltered.filter((m) => !visionFiltered.includes(m));
|
|
89283
90787
|
if (visionExcluded.length > 0) {
|
|
89284
90788
|
console.log(
|
|
89285
90789
|
`[ClawRouter] Vision filter: excluded ${visionExcluded.join(", ")} (no vision support)`
|
|
89286
90790
|
);
|
|
89287
90791
|
}
|
|
89288
|
-
modelsToTry =
|
|
90792
|
+
modelsToTry = visionFiltered.slice(0, MAX_FALLBACK_ATTEMPTS);
|
|
89289
90793
|
modelsToTry = prioritizeNonRateLimited(modelsToTry);
|
|
89290
90794
|
} else {
|
|
89291
90795
|
modelsToTry = modelId ? [modelId] : [];
|
|
@@ -90175,7 +91679,7 @@ var init_proxy = __esm({
|
|
|
90175
91679
|
init_client2();
|
|
90176
91680
|
init_esm5();
|
|
90177
91681
|
init_router();
|
|
90178
|
-
|
|
91682
|
+
init_router();
|
|
90179
91683
|
init_models();
|
|
90180
91684
|
init_max_tokens();
|
|
90181
91685
|
init_logger();
|
|
@@ -90189,7 +91693,7 @@ var init_proxy = __esm({
|
|
|
90189
91693
|
init_session();
|
|
90190
91694
|
init_updater();
|
|
90191
91695
|
init_exclude_models();
|
|
90192
|
-
|
|
91696
|
+
init_config();
|
|
90193
91697
|
init_journal();
|
|
90194
91698
|
init_upstream_proxy();
|
|
90195
91699
|
init_textual_tool_calls();
|
|
@@ -90216,8 +91720,6 @@ var init_proxy = __esm({
|
|
|
90216
91720
|
"free/gpt-oss-20b",
|
|
90217
91721
|
"free/deepseek-v4-flash",
|
|
90218
91722
|
// 1M ctx; slow (~10 tok/s, 07-28 probe) but completes
|
|
90219
|
-
"free/seed-oss-36b",
|
|
90220
|
-
// live coder (successor to retired qwen3-coder-480b)
|
|
90221
91723
|
"free/mistral-nemotron",
|
|
90222
91724
|
// strong instruction following
|
|
90223
91725
|
"free/step-3.7-flash",
|
|
@@ -91823,7 +93325,7 @@ var init_headers = __esm({
|
|
|
91823
93325
|
|
|
91824
93326
|
// node_modules/@polymarket/clob-client-v2/dist/config.js
|
|
91825
93327
|
var AMOY_CONTRACTS, MATIC_CONTRACTS, COLLATERAL_TOKEN_DECIMALS, getContractConfig;
|
|
91826
|
-
var
|
|
93328
|
+
var init_config2 = __esm({
|
|
91827
93329
|
"node_modules/@polymarket/clob-client-v2/dist/config.js"() {
|
|
91828
93330
|
"use strict";
|
|
91829
93331
|
AMOY_CONTRACTS = {
|
|
@@ -92123,7 +93625,7 @@ var init_buildMarketOrderCreationArgs = __esm({
|
|
|
92123
93625
|
"node_modules/@polymarket/clob-client-v2/dist/order-builder/helpers/buildMarketOrderCreationArgs.js"() {
|
|
92124
93626
|
"use strict";
|
|
92125
93627
|
init_constants2();
|
|
92126
|
-
|
|
93628
|
+
init_config2();
|
|
92127
93629
|
init_getMarketOrderRawAmounts();
|
|
92128
93630
|
init_esm();
|
|
92129
93631
|
}
|
|
@@ -92684,7 +94186,7 @@ var init_createMarketOrder = __esm({
|
|
|
92684
94186
|
"node_modules/@polymarket/clob-client-v2/dist/order-builder/helpers/createMarketOrder.js"() {
|
|
92685
94187
|
"use strict";
|
|
92686
94188
|
init_signer();
|
|
92687
|
-
|
|
94189
|
+
init_config2();
|
|
92688
94190
|
init_buildMarketOrderCreationArgs();
|
|
92689
94191
|
init_signatureTypeV2();
|
|
92690
94192
|
init_buildOrder();
|
|
@@ -92792,7 +94294,7 @@ var init_buildOrderCreationArgs = __esm({
|
|
|
92792
94294
|
"node_modules/@polymarket/clob-client-v2/dist/order-builder/helpers/buildOrderCreationArgs.js"() {
|
|
92793
94295
|
"use strict";
|
|
92794
94296
|
init_constants2();
|
|
92795
|
-
|
|
94297
|
+
init_config2();
|
|
92796
94298
|
init_getOrderRawAmounts();
|
|
92797
94299
|
init_esm();
|
|
92798
94300
|
}
|
|
@@ -92804,7 +94306,7 @@ var init_createOrder = __esm({
|
|
|
92804
94306
|
"node_modules/@polymarket/clob-client-v2/dist/order-builder/helpers/createOrder.js"() {
|
|
92805
94307
|
"use strict";
|
|
92806
94308
|
init_signer();
|
|
92807
|
-
|
|
94309
|
+
init_config2();
|
|
92808
94310
|
init_signatureTypeV2();
|
|
92809
94311
|
init_buildOrder();
|
|
92810
94312
|
init_buildOrderCreationArgs();
|
|
@@ -92842,7 +94344,7 @@ var init_createExchangeV3OrderFromAmounts = __esm({
|
|
|
92842
94344
|
"use strict";
|
|
92843
94345
|
init_constants2();
|
|
92844
94346
|
init_signer();
|
|
92845
|
-
|
|
94347
|
+
init_config2();
|
|
92846
94348
|
init_signatureTypeV2();
|
|
92847
94349
|
init_buildOrder();
|
|
92848
94350
|
createExchangeV3OrderFromAmounts = async (eoaSigner, chainId, signatureType, funderAddress, userOrder) => {
|
|
@@ -110644,7 +112146,7 @@ var init_axios2 = __esm({
|
|
|
110644
112146
|
|
|
110645
112147
|
// node_modules/browser-or-node/dist/index.mjs
|
|
110646
112148
|
var isBrowser, isNode, isWebWorker, isJsDom, isDeno, isBun;
|
|
110647
|
-
var
|
|
112149
|
+
var init_dist2 = __esm({
|
|
110648
112150
|
"node_modules/browser-or-node/dist/index.mjs"() {
|
|
110649
112151
|
"use strict";
|
|
110650
112152
|
isBrowser = typeof window !== "undefined" && typeof window.document !== "undefined";
|
|
@@ -110668,7 +112170,7 @@ var init_http_helpers = __esm({
|
|
|
110668
112170
|
"node_modules/@polymarket/clob-client-v2/dist/http-helpers/index.js"() {
|
|
110669
112171
|
"use strict";
|
|
110670
112172
|
init_axios2();
|
|
110671
|
-
|
|
112173
|
+
init_dist2();
|
|
110672
112174
|
GET = "GET";
|
|
110673
112175
|
POST = "POST";
|
|
110674
112176
|
DELETE = "DELETE";
|
|
@@ -111700,10 +113202,10 @@ var init_client4 = __esm({
|
|
|
111700
113202
|
});
|
|
111701
113203
|
|
|
111702
113204
|
// node_modules/@polymarket/clob-client-v2/dist/index.js
|
|
111703
|
-
var
|
|
113205
|
+
var init_dist3 = __esm({
|
|
111704
113206
|
"node_modules/@polymarket/clob-client-v2/dist/index.js"() {
|
|
111705
113207
|
"use strict";
|
|
111706
|
-
|
|
113208
|
+
init_config2();
|
|
111707
113209
|
init_signatureTypeV2();
|
|
111708
113210
|
init_side();
|
|
111709
113211
|
init_clob();
|
|
@@ -111723,7 +113225,7 @@ import * as net from "net";
|
|
|
111723
113225
|
import * as http4 from "http";
|
|
111724
113226
|
import { Agent as HttpsAgent } from "https";
|
|
111725
113227
|
var INTERNAL, Agent2;
|
|
111726
|
-
var
|
|
113228
|
+
var init_dist4 = __esm({
|
|
111727
113229
|
"node_modules/agent-base/dist/index.js"() {
|
|
111728
113230
|
"use strict";
|
|
111729
113231
|
init_helpers();
|
|
@@ -111962,7 +113464,7 @@ function createNegotiateAuth() {
|
|
|
111962
113464
|
};
|
|
111963
113465
|
};
|
|
111964
113466
|
}
|
|
111965
|
-
var
|
|
113467
|
+
var init_dist5 = __esm({
|
|
111966
113468
|
"node_modules/proxy-agent-negotiate/dist/index.js"() {
|
|
111967
113469
|
"use strict";
|
|
111968
113470
|
}
|
|
@@ -111989,13 +113491,13 @@ function omit(obj, ...keys) {
|
|
|
111989
113491
|
return ret;
|
|
111990
113492
|
}
|
|
111991
113493
|
var import_debug2, debug2, setServernameFromNonIpHost, HttpsProxyAgent2;
|
|
111992
|
-
var
|
|
113494
|
+
var init_dist6 = __esm({
|
|
111993
113495
|
"node_modules/https-proxy-agent/dist/index.js"() {
|
|
111994
113496
|
"use strict";
|
|
111995
113497
|
import_debug2 = __toESM(require_src(), 1);
|
|
111996
|
-
init_dist3();
|
|
111997
|
-
init_parse_proxy_response();
|
|
111998
113498
|
init_dist4();
|
|
113499
|
+
init_parse_proxy_response();
|
|
113500
|
+
init_dist5();
|
|
111999
113501
|
debug2 = (0, import_debug2.default)("https-proxy-agent");
|
|
112000
113502
|
setServernameFromNonIpHost = (options) => {
|
|
112001
113503
|
if (options.servername === void 0 && options.host && !net2.isIP(options.host)) {
|
|
@@ -112208,7 +113710,7 @@ var POLYGON_CHAIN_ID, CTF_EXCHANGE_V2, NEG_RISK_CTF_EXCHANGE_V2, NEG_RISK_ADAPTE
|
|
|
112208
113710
|
var init_constants3 = __esm({
|
|
112209
113711
|
"src/polymarket/constants.ts"() {
|
|
112210
113712
|
"use strict";
|
|
112211
|
-
|
|
113713
|
+
init_dist3();
|
|
112212
113714
|
POLYGON_CHAIN_ID = 137;
|
|
112213
113715
|
CTF_EXCHANGE_V2 = "0xE111180000d2663C0091e4f400237545B87B996B";
|
|
112214
113716
|
NEG_RISK_CTF_EXCHANGE_V2 = "0xe2222d279d744050d28e00520010520000310F59";
|
|
@@ -112745,11 +114247,11 @@ var init_client5 = __esm({
|
|
|
112745
114247
|
"src/polymarket/client.ts"() {
|
|
112746
114248
|
"use strict";
|
|
112747
114249
|
init_axios2();
|
|
112748
|
-
|
|
114250
|
+
init_dist6();
|
|
112749
114251
|
init_esm();
|
|
112750
114252
|
init_accounts();
|
|
112751
114253
|
init_chains();
|
|
112752
|
-
|
|
114254
|
+
init_dist3();
|
|
112753
114255
|
init_wallet_adapter();
|
|
112754
114256
|
init_constants3();
|
|
112755
114257
|
init_creds();
|
|
@@ -113119,7 +114621,7 @@ var ledger;
|
|
|
113119
114621
|
var init_orders = __esm({
|
|
113120
114622
|
"src/polymarket/orders.ts"() {
|
|
113121
114623
|
"use strict";
|
|
113122
|
-
|
|
114624
|
+
init_dist3();
|
|
113123
114625
|
init_client5();
|
|
113124
114626
|
init_constants3();
|
|
113125
114627
|
init_creds();
|
|
@@ -220301,7 +221803,7 @@ var init_relayer = __esm({
|
|
|
220301
221803
|
"use strict";
|
|
220302
221804
|
import_builder_relayer_client = __toESM(require_dist3(), 1);
|
|
220303
221805
|
import_builder_signing_sdk = __toESM(require_dist4(), 1);
|
|
220304
|
-
|
|
221806
|
+
init_dist3();
|
|
220305
221807
|
init_esm();
|
|
220306
221808
|
init_chains();
|
|
220307
221809
|
init_client5();
|
|
@@ -220641,7 +222143,7 @@ var init_setup = __esm({
|
|
|
220641
222143
|
"use strict";
|
|
220642
222144
|
init_esm();
|
|
220643
222145
|
init_chains();
|
|
220644
|
-
|
|
222146
|
+
init_dist3();
|
|
220645
222147
|
init_client5();
|
|
220646
222148
|
init_constants3();
|
|
220647
222149
|
init_creds();
|
|
@@ -221095,7 +222597,7 @@ function sleep2(ms) {
|
|
|
221095
222597
|
return new Promise((r2) => setTimeout(r2, ms));
|
|
221096
222598
|
}
|
|
221097
222599
|
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;
|
|
221098
|
-
var
|
|
222600
|
+
var init_dist7 = __esm({
|
|
221099
222601
|
"node_modules/@blockrun/llm/dist/index.js"() {
|
|
221100
222602
|
"use strict";
|
|
221101
222603
|
init_accounts();
|
|
@@ -221663,7 +223165,7 @@ var init_fund = __esm({
|
|
|
221663
223165
|
"src/polymarket/fund.ts"() {
|
|
221664
223166
|
"use strict";
|
|
221665
223167
|
init_axios2();
|
|
221666
|
-
|
|
223168
|
+
init_dist7();
|
|
221667
223169
|
init_wallet_adapter();
|
|
221668
223170
|
init_client5();
|
|
221669
223171
|
init_constants3();
|
|
@@ -222142,29 +223644,29 @@ var init_spend_control = __esm({
|
|
|
222142
223644
|
getLimits() {
|
|
222143
223645
|
return { ...this.limits };
|
|
222144
223646
|
}
|
|
222145
|
-
check(
|
|
223647
|
+
check(estimatedCost2) {
|
|
222146
223648
|
const now2 = this.now();
|
|
222147
223649
|
if (this.limits.perRequest !== void 0) {
|
|
222148
|
-
if (
|
|
223650
|
+
if (estimatedCost2 > this.limits.perRequest) {
|
|
222149
223651
|
return {
|
|
222150
223652
|
allowed: false,
|
|
222151
223653
|
blockedBy: "perRequest",
|
|
222152
223654
|
remaining: this.limits.perRequest,
|
|
222153
|
-
reason: `Per-request limit exceeded: $${
|
|
223655
|
+
reason: `Per-request limit exceeded: $${estimatedCost2.toFixed(4)} > $${this.limits.perRequest.toFixed(2)} max`
|
|
222154
223656
|
};
|
|
222155
223657
|
}
|
|
222156
223658
|
}
|
|
222157
223659
|
if (this.limits.hourly !== void 0) {
|
|
222158
223660
|
const hourlySpent = this.getSpendingInWindow(now2 - HOUR_MS, now2);
|
|
222159
223661
|
const remaining = this.limits.hourly - hourlySpent;
|
|
222160
|
-
if (
|
|
223662
|
+
if (estimatedCost2 > remaining) {
|
|
222161
223663
|
const oldestInWindow = this.history.find((r2) => r2.timestamp >= now2 - HOUR_MS);
|
|
222162
223664
|
const resetIn = oldestInWindow ? Math.ceil((oldestInWindow.timestamp + HOUR_MS - now2) / 1e3) : 0;
|
|
222163
223665
|
return {
|
|
222164
223666
|
allowed: false,
|
|
222165
223667
|
blockedBy: "hourly",
|
|
222166
223668
|
remaining,
|
|
222167
|
-
reason: `Hourly limit exceeded: $${(hourlySpent +
|
|
223669
|
+
reason: `Hourly limit exceeded: $${(hourlySpent + estimatedCost2).toFixed(2)} > $${this.limits.hourly.toFixed(2)} max`,
|
|
222168
223670
|
resetIn
|
|
222169
223671
|
};
|
|
222170
223672
|
}
|
|
@@ -222172,26 +223674,26 @@ var init_spend_control = __esm({
|
|
|
222172
223674
|
if (this.limits.daily !== void 0) {
|
|
222173
223675
|
const dailySpent = this.getSpendingInWindow(now2 - DAY_MS, now2);
|
|
222174
223676
|
const remaining = this.limits.daily - dailySpent;
|
|
222175
|
-
if (
|
|
223677
|
+
if (estimatedCost2 > remaining) {
|
|
222176
223678
|
const oldestInWindow = this.history.find((r2) => r2.timestamp >= now2 - DAY_MS);
|
|
222177
223679
|
const resetIn = oldestInWindow ? Math.ceil((oldestInWindow.timestamp + DAY_MS - now2) / 1e3) : 0;
|
|
222178
223680
|
return {
|
|
222179
223681
|
allowed: false,
|
|
222180
223682
|
blockedBy: "daily",
|
|
222181
223683
|
remaining,
|
|
222182
|
-
reason: `Daily limit exceeded: $${(dailySpent +
|
|
223684
|
+
reason: `Daily limit exceeded: $${(dailySpent + estimatedCost2).toFixed(2)} > $${this.limits.daily.toFixed(2)} max`,
|
|
222183
223685
|
resetIn
|
|
222184
223686
|
};
|
|
222185
223687
|
}
|
|
222186
223688
|
}
|
|
222187
223689
|
if (this.limits.session !== void 0) {
|
|
222188
223690
|
const remaining = this.limits.session - this.sessionSpent;
|
|
222189
|
-
if (
|
|
223691
|
+
if (estimatedCost2 > remaining) {
|
|
222190
223692
|
return {
|
|
222191
223693
|
allowed: false,
|
|
222192
223694
|
blockedBy: "session",
|
|
222193
223695
|
remaining,
|
|
222194
|
-
reason: `Session limit exceeded: $${(this.sessionSpent +
|
|
223696
|
+
reason: `Session limit exceeded: $${(this.sessionSpent + estimatedCost2).toFixed(2)} > $${this.limits.session.toFixed(2)} max`
|
|
222195
223697
|
};
|
|
222196
223698
|
}
|
|
222197
223699
|
}
|
|
@@ -222376,6 +223878,7 @@ __export(index_exports, {
|
|
|
222376
223878
|
deriveEvmKey: () => deriveEvmKey,
|
|
222377
223879
|
deriveSolanaKeyBytes: () => deriveSolanaKeyBytes,
|
|
222378
223880
|
fetchWithRetry: () => fetchWithRetry,
|
|
223881
|
+
filterCandidatesByCapacity: () => filterCandidatesByCapacity,
|
|
222379
223882
|
formatDuration: () => formatDuration,
|
|
222380
223883
|
formatStatsAscii: () => formatStatsAscii,
|
|
222381
223884
|
generateWalletMnemonic: () => generateWalletMnemonic,
|
|
@@ -222388,6 +223891,7 @@ __export(index_exports, {
|
|
|
222388
223891
|
getSessionId: () => getSessionId,
|
|
222389
223892
|
getStats: () => getStats,
|
|
222390
223893
|
hashRequestContent: () => hashRequestContent,
|
|
223894
|
+
inferToolRequirement: () => inferToolRequirement,
|
|
222391
223895
|
injectAuthProfile: () => injectAuthProfile,
|
|
222392
223896
|
injectModelsConfig: () => injectModelsConfig,
|
|
222393
223897
|
isAgenticModel: () => isAgenticModel,
|
|
@@ -222932,6 +224436,11 @@ async function startProxyInBackground(api, startupGeneration) {
|
|
|
222932
224436
|
`[${decision.tier}] ${decision.model} $${cost} (saved ${saved}%) | ${decision.reasoning}`
|
|
222933
224437
|
);
|
|
222934
224438
|
},
|
|
224439
|
+
onShadowRouted: (comparison) => {
|
|
224440
|
+
api.logger.info(
|
|
224441
|
+
`[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}`
|
|
224442
|
+
);
|
|
224443
|
+
},
|
|
222935
224444
|
onLowBalance: (info) => {
|
|
222936
224445
|
api.logger.warn(`[!] Low balance: ${info.balanceUSD}. Fund wallet: ${info.walletAddress}`);
|
|
222937
224446
|
},
|