@blockrun/llm 3.10.0 → 3.12.0
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 +336 -157
- package/dist/index.cjs +3601 -84
- package/dist/index.d.cts +233 -31
- package/dist/index.d.ts +233 -31
- package/dist/index.js +3601 -84
- package/package.json +4 -7
package/dist/index.js
CHANGED
|
@@ -31,6 +31,3362 @@ var APIError = class extends BlockrunError {
|
|
|
31
31
|
}
|
|
32
32
|
};
|
|
33
33
|
|
|
34
|
+
// node_modules/.pnpm/@blockrun+router-core@https+++codeload.github.com+BlockRunAI+router-core+tar.gz+d4308049348e1_gni7wlazdyzf7iqax5nhqdpoqi/node_modules/@blockrun/router-core/dist/index.js
|
|
35
|
+
function scoreTokenCount(estimatedTokens, thresholds) {
|
|
36
|
+
if (estimatedTokens < thresholds.simple) {
|
|
37
|
+
return { name: "tokenCount", score: -1, signal: `short (${estimatedTokens} tokens)` };
|
|
38
|
+
}
|
|
39
|
+
if (estimatedTokens > thresholds.complex) {
|
|
40
|
+
return { name: "tokenCount", score: 1, signal: `long (${estimatedTokens} tokens)` };
|
|
41
|
+
}
|
|
42
|
+
return { name: "tokenCount", score: 0, signal: null };
|
|
43
|
+
}
|
|
44
|
+
function scoreKeywordMatch(text, keywords, name, signalLabel, thresholds, scores) {
|
|
45
|
+
const matches = keywords.filter((kw) => text.includes(kw.toLowerCase()));
|
|
46
|
+
if (matches.length >= thresholds.high) {
|
|
47
|
+
return {
|
|
48
|
+
name,
|
|
49
|
+
score: scores.high,
|
|
50
|
+
signal: `${signalLabel} (${matches.slice(0, 3).join(", ")})`
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
if (matches.length >= thresholds.low) {
|
|
54
|
+
return {
|
|
55
|
+
name,
|
|
56
|
+
score: scores.low,
|
|
57
|
+
signal: `${signalLabel} (${matches.slice(0, 3).join(", ")})`
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
return { name, score: scores.none, signal: null };
|
|
61
|
+
}
|
|
62
|
+
function scoreMultiStep(text) {
|
|
63
|
+
const patterns = [/first.*then/i, /step \d/i, /\d\.\s/];
|
|
64
|
+
const hits = patterns.filter((p) => p.test(text));
|
|
65
|
+
if (hits.length > 0) {
|
|
66
|
+
return { name: "multiStepPatterns", score: 0.5, signal: "multi-step" };
|
|
67
|
+
}
|
|
68
|
+
return { name: "multiStepPatterns", score: 0, signal: null };
|
|
69
|
+
}
|
|
70
|
+
function scoreQuestionComplexity(prompt) {
|
|
71
|
+
const count = (prompt.match(/\?/g) || []).length;
|
|
72
|
+
if (count > 3) {
|
|
73
|
+
return { name: "questionComplexity", score: 0.5, signal: `${count} questions` };
|
|
74
|
+
}
|
|
75
|
+
return { name: "questionComplexity", score: 0, signal: null };
|
|
76
|
+
}
|
|
77
|
+
function scoreAgenticTask(text, keywords) {
|
|
78
|
+
let matchCount = 0;
|
|
79
|
+
const signals = [];
|
|
80
|
+
for (const keyword of keywords) {
|
|
81
|
+
if (text.includes(keyword.toLowerCase())) {
|
|
82
|
+
matchCount++;
|
|
83
|
+
if (signals.length < 3) {
|
|
84
|
+
signals.push(keyword);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
if (matchCount >= 4) {
|
|
89
|
+
return {
|
|
90
|
+
dimensionScore: {
|
|
91
|
+
name: "agenticTask",
|
|
92
|
+
score: 1,
|
|
93
|
+
signal: `agentic (${signals.join(", ")})`
|
|
94
|
+
},
|
|
95
|
+
agenticScore: 1
|
|
96
|
+
};
|
|
97
|
+
} else if (matchCount >= 3) {
|
|
98
|
+
return {
|
|
99
|
+
dimensionScore: {
|
|
100
|
+
name: "agenticTask",
|
|
101
|
+
score: 0.6,
|
|
102
|
+
signal: `agentic (${signals.join(", ")})`
|
|
103
|
+
},
|
|
104
|
+
agenticScore: 0.6
|
|
105
|
+
};
|
|
106
|
+
} else if (matchCount >= 1) {
|
|
107
|
+
return {
|
|
108
|
+
dimensionScore: {
|
|
109
|
+
name: "agenticTask",
|
|
110
|
+
score: 0.2,
|
|
111
|
+
signal: `agentic-light (${signals.join(", ")})`
|
|
112
|
+
},
|
|
113
|
+
agenticScore: 0.2
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
return {
|
|
117
|
+
dimensionScore: { name: "agenticTask", score: 0, signal: null },
|
|
118
|
+
agenticScore: 0
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
function classifyByRules(prompt, systemPrompt, estimatedTokens, config) {
|
|
122
|
+
const userText = prompt.toLowerCase();
|
|
123
|
+
const dimensions = [
|
|
124
|
+
// Token count uses total estimated tokens (system + user) — context size matters for model selection
|
|
125
|
+
scoreTokenCount(estimatedTokens, config.tokenCountThresholds),
|
|
126
|
+
scoreKeywordMatch(
|
|
127
|
+
userText,
|
|
128
|
+
config.codeKeywords,
|
|
129
|
+
"codePresence",
|
|
130
|
+
"code",
|
|
131
|
+
{ low: 1, high: 2 },
|
|
132
|
+
{ none: 0, low: 0.5, high: 1 }
|
|
133
|
+
),
|
|
134
|
+
scoreKeywordMatch(
|
|
135
|
+
userText,
|
|
136
|
+
config.reasoningKeywords,
|
|
137
|
+
"reasoningMarkers",
|
|
138
|
+
"reasoning",
|
|
139
|
+
{ low: 1, high: 2 },
|
|
140
|
+
{ none: 0, low: 0.7, high: 1 }
|
|
141
|
+
),
|
|
142
|
+
scoreKeywordMatch(
|
|
143
|
+
userText,
|
|
144
|
+
config.technicalKeywords,
|
|
145
|
+
"technicalTerms",
|
|
146
|
+
"technical",
|
|
147
|
+
{ low: 2, high: 4 },
|
|
148
|
+
{ none: 0, low: 0.5, high: 1 }
|
|
149
|
+
),
|
|
150
|
+
scoreKeywordMatch(
|
|
151
|
+
userText,
|
|
152
|
+
config.creativeKeywords,
|
|
153
|
+
"creativeMarkers",
|
|
154
|
+
"creative",
|
|
155
|
+
{ low: 1, high: 2 },
|
|
156
|
+
{ none: 0, low: 0.5, high: 0.7 }
|
|
157
|
+
),
|
|
158
|
+
scoreKeywordMatch(
|
|
159
|
+
userText,
|
|
160
|
+
config.simpleKeywords,
|
|
161
|
+
"simpleIndicators",
|
|
162
|
+
"simple",
|
|
163
|
+
{ low: 1, high: 2 },
|
|
164
|
+
{ none: 0, low: -1, high: -1 }
|
|
165
|
+
),
|
|
166
|
+
scoreMultiStep(userText),
|
|
167
|
+
scoreQuestionComplexity(prompt),
|
|
168
|
+
// 6 new dimensions
|
|
169
|
+
scoreKeywordMatch(
|
|
170
|
+
userText,
|
|
171
|
+
config.imperativeVerbs,
|
|
172
|
+
"imperativeVerbs",
|
|
173
|
+
"imperative",
|
|
174
|
+
{ low: 1, high: 2 },
|
|
175
|
+
{ none: 0, low: 0.3, high: 0.5 }
|
|
176
|
+
),
|
|
177
|
+
scoreKeywordMatch(
|
|
178
|
+
userText,
|
|
179
|
+
config.constraintIndicators,
|
|
180
|
+
"constraintCount",
|
|
181
|
+
"constraints",
|
|
182
|
+
{ low: 1, high: 3 },
|
|
183
|
+
{ none: 0, low: 0.3, high: 0.7 }
|
|
184
|
+
),
|
|
185
|
+
scoreKeywordMatch(
|
|
186
|
+
userText,
|
|
187
|
+
config.outputFormatKeywords,
|
|
188
|
+
"outputFormat",
|
|
189
|
+
"format",
|
|
190
|
+
{ low: 1, high: 2 },
|
|
191
|
+
{ none: 0, low: 0.4, high: 0.7 }
|
|
192
|
+
),
|
|
193
|
+
scoreKeywordMatch(
|
|
194
|
+
userText,
|
|
195
|
+
config.referenceKeywords,
|
|
196
|
+
"referenceComplexity",
|
|
197
|
+
"references",
|
|
198
|
+
{ low: 1, high: 2 },
|
|
199
|
+
{ none: 0, low: 0.3, high: 0.5 }
|
|
200
|
+
),
|
|
201
|
+
scoreKeywordMatch(
|
|
202
|
+
userText,
|
|
203
|
+
config.negationKeywords,
|
|
204
|
+
"negationComplexity",
|
|
205
|
+
"negation",
|
|
206
|
+
{ low: 2, high: 3 },
|
|
207
|
+
{ none: 0, low: 0.3, high: 0.5 }
|
|
208
|
+
),
|
|
209
|
+
scoreKeywordMatch(
|
|
210
|
+
userText,
|
|
211
|
+
config.domainSpecificKeywords,
|
|
212
|
+
"domainSpecificity",
|
|
213
|
+
"domain-specific",
|
|
214
|
+
{ low: 1, high: 2 },
|
|
215
|
+
{ none: 0, low: 0.5, high: 0.8 }
|
|
216
|
+
)
|
|
217
|
+
];
|
|
218
|
+
const agenticResult = scoreAgenticTask(userText, config.agenticTaskKeywords);
|
|
219
|
+
dimensions.push(agenticResult.dimensionScore);
|
|
220
|
+
const agenticScore = agenticResult.agenticScore;
|
|
221
|
+
const signals = dimensions.filter((d) => d.signal !== null).map((d) => d.signal);
|
|
222
|
+
const weights = config.dimensionWeights;
|
|
223
|
+
let weightedScore = 0;
|
|
224
|
+
for (const d of dimensions) {
|
|
225
|
+
const w = weights[d.name] ?? 0;
|
|
226
|
+
weightedScore += d.score * w;
|
|
227
|
+
}
|
|
228
|
+
const reasoningMatches = config.reasoningKeywords.filter(
|
|
229
|
+
(kw) => userText.includes(kw.toLowerCase())
|
|
230
|
+
);
|
|
231
|
+
if (reasoningMatches.length >= 2) {
|
|
232
|
+
const confidence2 = calibrateConfidence(
|
|
233
|
+
Math.max(weightedScore, 0.3),
|
|
234
|
+
// ensure positive for confidence calc
|
|
235
|
+
config.confidenceSteepness
|
|
236
|
+
);
|
|
237
|
+
return {
|
|
238
|
+
score: weightedScore,
|
|
239
|
+
tier: "REASONING",
|
|
240
|
+
confidence: Math.max(confidence2, 0.85),
|
|
241
|
+
signals,
|
|
242
|
+
agenticScore,
|
|
243
|
+
dimensions
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
const { simpleMedium, mediumComplex, complexReasoning } = config.tierBoundaries;
|
|
247
|
+
let tier;
|
|
248
|
+
let distanceFromBoundary;
|
|
249
|
+
if (weightedScore < simpleMedium) {
|
|
250
|
+
tier = "SIMPLE";
|
|
251
|
+
distanceFromBoundary = simpleMedium - weightedScore;
|
|
252
|
+
} else if (weightedScore < mediumComplex) {
|
|
253
|
+
tier = "MEDIUM";
|
|
254
|
+
distanceFromBoundary = Math.min(weightedScore - simpleMedium, mediumComplex - weightedScore);
|
|
255
|
+
} else if (weightedScore < complexReasoning) {
|
|
256
|
+
tier = "COMPLEX";
|
|
257
|
+
distanceFromBoundary = Math.min(
|
|
258
|
+
weightedScore - mediumComplex,
|
|
259
|
+
complexReasoning - weightedScore
|
|
260
|
+
);
|
|
261
|
+
} else {
|
|
262
|
+
tier = "REASONING";
|
|
263
|
+
distanceFromBoundary = weightedScore - complexReasoning;
|
|
264
|
+
}
|
|
265
|
+
const confidence = calibrateConfidence(distanceFromBoundary, config.confidenceSteepness);
|
|
266
|
+
if (confidence < config.confidenceThreshold) {
|
|
267
|
+
return { score: weightedScore, tier: null, confidence, signals, agenticScore, dimensions };
|
|
268
|
+
}
|
|
269
|
+
return { score: weightedScore, tier, confidence, signals, agenticScore, dimensions };
|
|
270
|
+
}
|
|
271
|
+
function calibrateConfidence(distance, steepness) {
|
|
272
|
+
return 1 / (1 + Math.exp(-steepness * distance));
|
|
273
|
+
}
|
|
274
|
+
var BASELINE_MODEL_ID = "anthropic/claude-opus-4.7";
|
|
275
|
+
var BASELINE_INPUT_PRICE = 5;
|
|
276
|
+
var BASELINE_OUTPUT_PRICE = 25;
|
|
277
|
+
function selectModel(tier, confidence, method, reasoning, tierConfigs, modelPricing, estimatedInputTokens, maxOutputTokens, routingProfile, agenticScore) {
|
|
278
|
+
const tierConfig = tierConfigs[tier];
|
|
279
|
+
const model = tierConfig.primary;
|
|
280
|
+
const pricing = modelPricing.get(model);
|
|
281
|
+
let costEstimate;
|
|
282
|
+
if (pricing?.flatPrice !== void 0) {
|
|
283
|
+
costEstimate = pricing.flatPrice;
|
|
284
|
+
} else {
|
|
285
|
+
const inputPrice = pricing?.inputPrice ?? 0;
|
|
286
|
+
const outputPrice = pricing?.outputPrice ?? 0;
|
|
287
|
+
costEstimate = estimatedInputTokens / 1e6 * inputPrice + maxOutputTokens / 1e6 * outputPrice;
|
|
288
|
+
}
|
|
289
|
+
const opusPricing = modelPricing.get(BASELINE_MODEL_ID);
|
|
290
|
+
const opusInputPrice = opusPricing?.inputPrice ?? BASELINE_INPUT_PRICE;
|
|
291
|
+
const opusOutputPrice = opusPricing?.outputPrice ?? BASELINE_OUTPUT_PRICE;
|
|
292
|
+
const baselineInput = estimatedInputTokens / 1e6 * opusInputPrice;
|
|
293
|
+
const baselineOutput = maxOutputTokens / 1e6 * opusOutputPrice;
|
|
294
|
+
const baselineCost = baselineInput + baselineOutput;
|
|
295
|
+
const savings = routingProfile === "premium" ? 0 : baselineCost > 0 ? Math.max(0, (baselineCost - costEstimate) / baselineCost) : 0;
|
|
296
|
+
return {
|
|
297
|
+
model,
|
|
298
|
+
tier,
|
|
299
|
+
confidence,
|
|
300
|
+
method,
|
|
301
|
+
reasoning,
|
|
302
|
+
costEstimate,
|
|
303
|
+
baselineCost,
|
|
304
|
+
savings,
|
|
305
|
+
...agenticScore !== void 0 && { agenticScore }
|
|
306
|
+
};
|
|
307
|
+
}
|
|
308
|
+
function getFallbackChain(tier, tierConfigs) {
|
|
309
|
+
const config = tierConfigs[tier];
|
|
310
|
+
return [config.primary, ...config.fallback];
|
|
311
|
+
}
|
|
312
|
+
var SERVER_MARGIN_PERCENT = 5;
|
|
313
|
+
var MIN_PAYMENT_USD = 1e-3;
|
|
314
|
+
function calculateModelCost(model, modelPricing, estimatedInputTokens, maxOutputTokens, routingProfile) {
|
|
315
|
+
const pricing = modelPricing.get(model);
|
|
316
|
+
let costEstimate;
|
|
317
|
+
if (pricing?.flatPrice !== void 0) {
|
|
318
|
+
costEstimate = Math.max(pricing.flatPrice * (1 + SERVER_MARGIN_PERCENT / 100), MIN_PAYMENT_USD);
|
|
319
|
+
} else {
|
|
320
|
+
const inputPrice = pricing?.inputPrice ?? 0;
|
|
321
|
+
const outputPrice = pricing?.outputPrice ?? 0;
|
|
322
|
+
const inputCost = estimatedInputTokens / 1e6 * inputPrice;
|
|
323
|
+
const outputCost = maxOutputTokens / 1e6 * outputPrice;
|
|
324
|
+
costEstimate = Math.max(
|
|
325
|
+
(inputCost + outputCost) * (1 + SERVER_MARGIN_PERCENT / 100),
|
|
326
|
+
MIN_PAYMENT_USD
|
|
327
|
+
);
|
|
328
|
+
}
|
|
329
|
+
const opusPricing = modelPricing.get(BASELINE_MODEL_ID);
|
|
330
|
+
const opusInputPrice = opusPricing?.inputPrice ?? BASELINE_INPUT_PRICE;
|
|
331
|
+
const opusOutputPrice = opusPricing?.outputPrice ?? BASELINE_OUTPUT_PRICE;
|
|
332
|
+
const baselineInput = estimatedInputTokens / 1e6 * opusInputPrice;
|
|
333
|
+
const baselineOutput = maxOutputTokens / 1e6 * opusOutputPrice;
|
|
334
|
+
const baselineCost = baselineInput + baselineOutput;
|
|
335
|
+
const savings = routingProfile === "premium" ? 0 : baselineCost > 0 ? Math.max(0, (baselineCost - costEstimate) / baselineCost) : 0;
|
|
336
|
+
return { costEstimate, baselineCost, savings };
|
|
337
|
+
}
|
|
338
|
+
function filterCandidatesByCapacity(models, estimatedInputTokens, requestedOutputTokens, getCapabilities) {
|
|
339
|
+
const filtered = models.filter((modelId) => {
|
|
340
|
+
const capabilities = getCapabilities(modelId);
|
|
341
|
+
if (!capabilities) return true;
|
|
342
|
+
return capabilities.contextWindow >= (estimatedInputTokens + requestedOutputTokens) * 1.1 && capabilities.maxOutput >= requestedOutputTokens;
|
|
343
|
+
});
|
|
344
|
+
return filtered;
|
|
345
|
+
}
|
|
346
|
+
function applyPromotions(tierConfigs, promotions, profile, now = /* @__PURE__ */ new Date()) {
|
|
347
|
+
if (!promotions || promotions.length === 0) return tierConfigs;
|
|
348
|
+
let result = tierConfigs;
|
|
349
|
+
for (const promo of promotions) {
|
|
350
|
+
const start = new Date(promo.startDate);
|
|
351
|
+
const end = new Date(promo.endDate);
|
|
352
|
+
if (now < start || now >= end) continue;
|
|
353
|
+
if (promo.profiles && !promo.profiles.includes(profile)) continue;
|
|
354
|
+
if (result === tierConfigs) {
|
|
355
|
+
result = { ...tierConfigs };
|
|
356
|
+
for (const t of Object.keys(result)) {
|
|
357
|
+
result[t] = { ...result[t] };
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
for (const [tier, override] of Object.entries(promo.tierOverrides)) {
|
|
361
|
+
if (!result[tier]) continue;
|
|
362
|
+
if (override.primary) result[tier].primary = override.primary;
|
|
363
|
+
if (override.fallback) result[tier].fallback = override.fallback;
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
return result;
|
|
367
|
+
}
|
|
368
|
+
var RulesStrategy = class {
|
|
369
|
+
name = "rules";
|
|
370
|
+
route(prompt, systemPrompt, maxOutputTokens, options) {
|
|
371
|
+
const { config, modelPricing } = options;
|
|
372
|
+
const fullText = `${systemPrompt ?? ""} ${prompt}`;
|
|
373
|
+
const estimatedTokens = Math.ceil(fullText.length / 4);
|
|
374
|
+
const scanLimit = Math.max(1, Math.min(8e3, config.classifier.promptTruncationChars));
|
|
375
|
+
const sample = (value) => {
|
|
376
|
+
if (value.length <= scanLimit) return value;
|
|
377
|
+
const prefixLength = Math.ceil(scanLimit / 2);
|
|
378
|
+
return `${value.slice(0, prefixLength)}
|
|
379
|
+
${value.slice(-(scanLimit - prefixLength))}`;
|
|
380
|
+
};
|
|
381
|
+
const scannedPrompt = sample(prompt);
|
|
382
|
+
const scannedSystemPrompt = systemPrompt ? sample(systemPrompt) : void 0;
|
|
383
|
+
const ruleResult = classifyByRules(
|
|
384
|
+
scannedPrompt,
|
|
385
|
+
scannedSystemPrompt,
|
|
386
|
+
estimatedTokens,
|
|
387
|
+
config.scoring
|
|
388
|
+
);
|
|
389
|
+
const { routingProfile } = options;
|
|
390
|
+
let tierConfigs;
|
|
391
|
+
let profileSuffix;
|
|
392
|
+
let profile;
|
|
393
|
+
if (routingProfile === "eco") {
|
|
394
|
+
tierConfigs = config.ecoTiers ?? config.tiers;
|
|
395
|
+
profileSuffix = config.ecoTiers ? " | eco" : " | eco (default tiers)";
|
|
396
|
+
profile = "eco";
|
|
397
|
+
} else if (routingProfile === "premium") {
|
|
398
|
+
tierConfigs = config.premiumTiers ?? config.tiers;
|
|
399
|
+
profileSuffix = config.premiumTiers ? " | premium" : " | premium (default tiers)";
|
|
400
|
+
profile = "premium";
|
|
401
|
+
} else {
|
|
402
|
+
const agenticScore = ruleResult.agenticScore ?? 0;
|
|
403
|
+
const isAutoAgentic = agenticScore >= 0.5;
|
|
404
|
+
const agenticModeSetting = config.overrides.agenticMode;
|
|
405
|
+
const hasToolsInRequest = options.requiresTools ?? options.hasTools ?? false;
|
|
406
|
+
let useAgenticTiers;
|
|
407
|
+
if (agenticModeSetting === false) {
|
|
408
|
+
useAgenticTiers = false;
|
|
409
|
+
} else if (agenticModeSetting === true) {
|
|
410
|
+
useAgenticTiers = config.agenticTiers != null;
|
|
411
|
+
} else {
|
|
412
|
+
useAgenticTiers = (hasToolsInRequest || isAutoAgentic) && config.agenticTiers != null;
|
|
413
|
+
}
|
|
414
|
+
tierConfigs = useAgenticTiers ? config.agenticTiers : config.tiers;
|
|
415
|
+
profileSuffix = useAgenticTiers ? ` | agentic${hasToolsInRequest ? " (tools)" : ""}` : "";
|
|
416
|
+
profile = useAgenticTiers ? "agentic" : "auto";
|
|
417
|
+
}
|
|
418
|
+
tierConfigs = applyPromotions(tierConfigs, config.promotions, profile, options.now);
|
|
419
|
+
const agenticScoreValue = ruleResult.agenticScore;
|
|
420
|
+
if (estimatedTokens > config.overrides.maxTokensForceComplex) {
|
|
421
|
+
const decision2 = selectModel(
|
|
422
|
+
"COMPLEX",
|
|
423
|
+
0.95,
|
|
424
|
+
"rules",
|
|
425
|
+
`Input exceeds ${config.overrides.maxTokensForceComplex} tokens${profileSuffix}`,
|
|
426
|
+
tierConfigs,
|
|
427
|
+
modelPricing,
|
|
428
|
+
estimatedTokens,
|
|
429
|
+
maxOutputTokens,
|
|
430
|
+
routingProfile,
|
|
431
|
+
agenticScoreValue
|
|
432
|
+
);
|
|
433
|
+
return { ...decision2, tierConfigs, profile };
|
|
434
|
+
}
|
|
435
|
+
const hasStructuredOutput = options.requiresStructuredOutput === true || (scannedSystemPrompt ? /json|structured|schema/i.test(scannedSystemPrompt) : false);
|
|
436
|
+
let tier;
|
|
437
|
+
let confidence;
|
|
438
|
+
const method = "rules";
|
|
439
|
+
let reasoning = `score=${ruleResult.score.toFixed(2)} | ${ruleResult.signals.join(", ")}`;
|
|
440
|
+
if (ruleResult.tier !== null) {
|
|
441
|
+
tier = ruleResult.tier;
|
|
442
|
+
confidence = ruleResult.confidence;
|
|
443
|
+
} else {
|
|
444
|
+
tier = config.overrides.ambiguousDefaultTier;
|
|
445
|
+
confidence = 0.5;
|
|
446
|
+
reasoning += ` | ambiguous -> default: ${tier}`;
|
|
447
|
+
}
|
|
448
|
+
if (hasStructuredOutput) {
|
|
449
|
+
const tierRank = { SIMPLE: 0, MEDIUM: 1, COMPLEX: 2, REASONING: 3 };
|
|
450
|
+
const minTier = config.overrides.structuredOutputMinTier;
|
|
451
|
+
if (tierRank[tier] < tierRank[minTier]) {
|
|
452
|
+
reasoning += ` | upgraded to ${minTier} (structured output)`;
|
|
453
|
+
tier = minTier;
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
reasoning += profileSuffix;
|
|
457
|
+
const decision = selectModel(
|
|
458
|
+
tier,
|
|
459
|
+
confidence,
|
|
460
|
+
method,
|
|
461
|
+
reasoning,
|
|
462
|
+
tierConfigs,
|
|
463
|
+
modelPricing,
|
|
464
|
+
estimatedTokens,
|
|
465
|
+
maxOutputTokens,
|
|
466
|
+
routingProfile,
|
|
467
|
+
agenticScoreValue
|
|
468
|
+
);
|
|
469
|
+
return { ...decision, tierConfigs, profile };
|
|
470
|
+
}
|
|
471
|
+
};
|
|
472
|
+
var registry = /* @__PURE__ */ new Map();
|
|
473
|
+
registry.set("rules", new RulesStrategy());
|
|
474
|
+
function getStrategy(name) {
|
|
475
|
+
const strategy = registry.get(name);
|
|
476
|
+
if (!strategy) {
|
|
477
|
+
throw new Error(`Unknown routing strategy: ${name}`);
|
|
478
|
+
}
|
|
479
|
+
return strategy;
|
|
480
|
+
}
|
|
481
|
+
function registerStrategy(strategy) {
|
|
482
|
+
registry.set(strategy.name, strategy);
|
|
483
|
+
}
|
|
484
|
+
var DEFAULT_MODEL_CAPABILITIES = Object.freeze({
|
|
485
|
+
"anthropic/claude-fable-5": {
|
|
486
|
+
contextWindow: 1e6,
|
|
487
|
+
maxOutputTokens: 128e3,
|
|
488
|
+
supportsTools: true,
|
|
489
|
+
supportsVision: true
|
|
490
|
+
},
|
|
491
|
+
"anthropic/claude-haiku-4.5": {
|
|
492
|
+
contextWindow: 2e5,
|
|
493
|
+
maxOutputTokens: 8192,
|
|
494
|
+
supportsTools: true,
|
|
495
|
+
supportsVision: true
|
|
496
|
+
},
|
|
497
|
+
"anthropic/claude-opus-4.6": {
|
|
498
|
+
contextWindow: 1e6,
|
|
499
|
+
maxOutputTokens: 128e3,
|
|
500
|
+
supportsTools: true,
|
|
501
|
+
supportsVision: true
|
|
502
|
+
},
|
|
503
|
+
"anthropic/claude-opus-4.7": {
|
|
504
|
+
contextWindow: 1e6,
|
|
505
|
+
maxOutputTokens: 128e3,
|
|
506
|
+
supportsTools: true,
|
|
507
|
+
supportsVision: true
|
|
508
|
+
},
|
|
509
|
+
"anthropic/claude-opus-4.8": {
|
|
510
|
+
contextWindow: 1e6,
|
|
511
|
+
maxOutputTokens: 128e3,
|
|
512
|
+
supportsTools: true,
|
|
513
|
+
supportsVision: true
|
|
514
|
+
},
|
|
515
|
+
"anthropic/claude-opus-5": {
|
|
516
|
+
contextWindow: 1e6,
|
|
517
|
+
maxOutputTokens: 128e3,
|
|
518
|
+
supportsTools: true,
|
|
519
|
+
supportsVision: true
|
|
520
|
+
},
|
|
521
|
+
"anthropic/claude-sonnet-4.6": {
|
|
522
|
+
contextWindow: 2e5,
|
|
523
|
+
maxOutputTokens: 64e3,
|
|
524
|
+
supportsTools: true,
|
|
525
|
+
supportsVision: true
|
|
526
|
+
},
|
|
527
|
+
"anthropic/claude-sonnet-5": {
|
|
528
|
+
contextWindow: 1e6,
|
|
529
|
+
maxOutputTokens: 128e3,
|
|
530
|
+
supportsTools: true,
|
|
531
|
+
supportsVision: true
|
|
532
|
+
},
|
|
533
|
+
"deepseek/deepseek-chat": {
|
|
534
|
+
contextWindow: 1e6,
|
|
535
|
+
maxOutputTokens: 8192,
|
|
536
|
+
supportsTools: true,
|
|
537
|
+
supportsVision: false
|
|
538
|
+
},
|
|
539
|
+
"deepseek/deepseek-reasoner": {
|
|
540
|
+
contextWindow: 1e6,
|
|
541
|
+
maxOutputTokens: 8192,
|
|
542
|
+
supportsTools: true,
|
|
543
|
+
supportsVision: false
|
|
544
|
+
},
|
|
545
|
+
"deepseek/deepseek-v4-pro": {
|
|
546
|
+
contextWindow: 1048576,
|
|
547
|
+
maxOutputTokens: 65536,
|
|
548
|
+
supportsTools: true,
|
|
549
|
+
supportsVision: false
|
|
550
|
+
},
|
|
551
|
+
"free/deepseek-v4-flash": {
|
|
552
|
+
contextWindow: 1e6,
|
|
553
|
+
maxOutputTokens: 16384,
|
|
554
|
+
supportsTools: false,
|
|
555
|
+
supportsVision: false
|
|
556
|
+
},
|
|
557
|
+
"free/gpt-oss-120b": {
|
|
558
|
+
contextWindow: 128e3,
|
|
559
|
+
maxOutputTokens: 16384,
|
|
560
|
+
supportsTools: false,
|
|
561
|
+
supportsVision: false
|
|
562
|
+
},
|
|
563
|
+
"free/gpt-oss-20b": {
|
|
564
|
+
contextWindow: 128e3,
|
|
565
|
+
maxOutputTokens: 16384,
|
|
566
|
+
supportsTools: false,
|
|
567
|
+
supportsVision: false
|
|
568
|
+
},
|
|
569
|
+
"free/seed-oss-36b": {
|
|
570
|
+
contextWindow: 131072,
|
|
571
|
+
maxOutputTokens: 16384,
|
|
572
|
+
supportsTools: false,
|
|
573
|
+
supportsVision: false
|
|
574
|
+
},
|
|
575
|
+
"google/gemini-2.5-flash": {
|
|
576
|
+
contextWindow: 1e6,
|
|
577
|
+
maxOutputTokens: 65536,
|
|
578
|
+
supportsTools: true,
|
|
579
|
+
supportsVision: true
|
|
580
|
+
},
|
|
581
|
+
"google/gemini-2.5-flash-lite": {
|
|
582
|
+
contextWindow: 1e6,
|
|
583
|
+
maxOutputTokens: 65536,
|
|
584
|
+
supportsTools: true,
|
|
585
|
+
supportsVision: false
|
|
586
|
+
},
|
|
587
|
+
"google/gemini-2.5-pro": {
|
|
588
|
+
contextWindow: 105e4,
|
|
589
|
+
maxOutputTokens: 65536,
|
|
590
|
+
supportsTools: true,
|
|
591
|
+
supportsVision: true
|
|
592
|
+
},
|
|
593
|
+
"google/gemini-3-flash-preview": {
|
|
594
|
+
contextWindow: 1e6,
|
|
595
|
+
maxOutputTokens: 65536,
|
|
596
|
+
supportsTools: false,
|
|
597
|
+
supportsVision: true
|
|
598
|
+
},
|
|
599
|
+
"google/gemini-3.1-flash-lite": {
|
|
600
|
+
contextWindow: 1e6,
|
|
601
|
+
maxOutputTokens: 8192,
|
|
602
|
+
supportsTools: true,
|
|
603
|
+
supportsVision: false
|
|
604
|
+
},
|
|
605
|
+
"google/gemini-3.1-pro": {
|
|
606
|
+
contextWindow: 105e4,
|
|
607
|
+
maxOutputTokens: 65536,
|
|
608
|
+
supportsTools: true,
|
|
609
|
+
supportsVision: true
|
|
610
|
+
},
|
|
611
|
+
"google/gemini-3.5-flash": {
|
|
612
|
+
contextWindow: 1048576,
|
|
613
|
+
maxOutputTokens: 65536,
|
|
614
|
+
supportsTools: true,
|
|
615
|
+
supportsVision: true
|
|
616
|
+
},
|
|
617
|
+
"moonshot/kimi-k2.5": {
|
|
618
|
+
contextWindow: 262144,
|
|
619
|
+
maxOutputTokens: 16384,
|
|
620
|
+
supportsTools: true,
|
|
621
|
+
supportsVision: true
|
|
622
|
+
},
|
|
623
|
+
"moonshot/kimi-k2.6": {
|
|
624
|
+
contextWindow: 262144,
|
|
625
|
+
maxOutputTokens: 65536,
|
|
626
|
+
supportsTools: true,
|
|
627
|
+
supportsVision: true
|
|
628
|
+
},
|
|
629
|
+
"moonshot/kimi-k2.7": {
|
|
630
|
+
contextWindow: 262144,
|
|
631
|
+
maxOutputTokens: 65536,
|
|
632
|
+
supportsTools: true,
|
|
633
|
+
supportsVision: true
|
|
634
|
+
},
|
|
635
|
+
"moonshot/kimi-k3": {
|
|
636
|
+
contextWindow: 1048576,
|
|
637
|
+
maxOutputTokens: 65536,
|
|
638
|
+
supportsTools: true,
|
|
639
|
+
supportsVision: true
|
|
640
|
+
},
|
|
641
|
+
"openai/gpt-4.1": {
|
|
642
|
+
contextWindow: 128e3,
|
|
643
|
+
maxOutputTokens: 16384,
|
|
644
|
+
supportsTools: true,
|
|
645
|
+
supportsVision: true
|
|
646
|
+
},
|
|
647
|
+
"openai/gpt-4o-mini": {
|
|
648
|
+
contextWindow: 128e3,
|
|
649
|
+
maxOutputTokens: 16384,
|
|
650
|
+
supportsTools: true,
|
|
651
|
+
supportsVision: false
|
|
652
|
+
},
|
|
653
|
+
"openai/gpt-5-mini": {
|
|
654
|
+
contextWindow: 2e5,
|
|
655
|
+
maxOutputTokens: 65536,
|
|
656
|
+
supportsTools: true,
|
|
657
|
+
supportsVision: false
|
|
658
|
+
},
|
|
659
|
+
"openai/gpt-5.3-codex": {
|
|
660
|
+
contextWindow: 4e5,
|
|
661
|
+
maxOutputTokens: 128e3,
|
|
662
|
+
supportsTools: true,
|
|
663
|
+
supportsVision: false
|
|
664
|
+
},
|
|
665
|
+
"openai/gpt-5.4": {
|
|
666
|
+
contextWindow: 4e5,
|
|
667
|
+
maxOutputTokens: 128e3,
|
|
668
|
+
supportsTools: true,
|
|
669
|
+
supportsVision: true
|
|
670
|
+
},
|
|
671
|
+
"openai/gpt-5.4-nano": {
|
|
672
|
+
contextWindow: 105e4,
|
|
673
|
+
maxOutputTokens: 32768,
|
|
674
|
+
supportsTools: true,
|
|
675
|
+
supportsVision: false
|
|
676
|
+
},
|
|
677
|
+
"openai/gpt-5.5": {
|
|
678
|
+
contextWindow: 105e4,
|
|
679
|
+
maxOutputTokens: 128e3,
|
|
680
|
+
supportsTools: true,
|
|
681
|
+
supportsVision: true
|
|
682
|
+
},
|
|
683
|
+
"openai/gpt-5.6-terra": {
|
|
684
|
+
contextWindow: 105e4,
|
|
685
|
+
maxOutputTokens: 128e3,
|
|
686
|
+
supportsTools: true,
|
|
687
|
+
supportsVision: true
|
|
688
|
+
},
|
|
689
|
+
"openai/o3": {
|
|
690
|
+
contextWindow: 2e5,
|
|
691
|
+
maxOutputTokens: 1e5,
|
|
692
|
+
supportsTools: true,
|
|
693
|
+
supportsVision: false
|
|
694
|
+
},
|
|
695
|
+
"openai/o4-mini": {
|
|
696
|
+
contextWindow: 128e3,
|
|
697
|
+
maxOutputTokens: 65536,
|
|
698
|
+
supportsTools: true,
|
|
699
|
+
supportsVision: false
|
|
700
|
+
},
|
|
701
|
+
"qwen/qwen3.7-max": {
|
|
702
|
+
contextWindow: 1e6,
|
|
703
|
+
maxOutputTokens: 65536,
|
|
704
|
+
supportsTools: true,
|
|
705
|
+
supportsVision: false
|
|
706
|
+
},
|
|
707
|
+
"xai/grok-3-mini": {
|
|
708
|
+
contextWindow: 131072,
|
|
709
|
+
maxOutputTokens: 16384,
|
|
710
|
+
supportsTools: true,
|
|
711
|
+
supportsVision: false
|
|
712
|
+
},
|
|
713
|
+
"xai/grok-4-0709": {
|
|
714
|
+
contextWindow: 131072,
|
|
715
|
+
maxOutputTokens: 16384,
|
|
716
|
+
supportsTools: true,
|
|
717
|
+
supportsVision: false
|
|
718
|
+
},
|
|
719
|
+
"xai/grok-4-1-fast-non-reasoning": {
|
|
720
|
+
contextWindow: 131072,
|
|
721
|
+
maxOutputTokens: 16384,
|
|
722
|
+
supportsTools: true,
|
|
723
|
+
supportsVision: false
|
|
724
|
+
},
|
|
725
|
+
"xai/grok-4-1-fast-reasoning": {
|
|
726
|
+
contextWindow: 131072,
|
|
727
|
+
maxOutputTokens: 16384,
|
|
728
|
+
supportsTools: true,
|
|
729
|
+
supportsVision: false
|
|
730
|
+
},
|
|
731
|
+
"xai/grok-4-fast-non-reasoning": {
|
|
732
|
+
contextWindow: 131072,
|
|
733
|
+
maxOutputTokens: 16384,
|
|
734
|
+
supportsTools: true,
|
|
735
|
+
supportsVision: false
|
|
736
|
+
},
|
|
737
|
+
"xai/grok-4-fast-reasoning": {
|
|
738
|
+
contextWindow: 131072,
|
|
739
|
+
maxOutputTokens: 16384,
|
|
740
|
+
supportsTools: true,
|
|
741
|
+
supportsVision: false
|
|
742
|
+
},
|
|
743
|
+
"xai/grok-4.5": {
|
|
744
|
+
contextWindow: 5e5,
|
|
745
|
+
maxOutputTokens: 16384,
|
|
746
|
+
supportsTools: true,
|
|
747
|
+
supportsVision: true
|
|
748
|
+
},
|
|
749
|
+
"zai/glm-5.1": {
|
|
750
|
+
contextWindow: 2e5,
|
|
751
|
+
maxOutputTokens: 128e3,
|
|
752
|
+
supportsTools: true,
|
|
753
|
+
supportsVision: false
|
|
754
|
+
},
|
|
755
|
+
"zai/glm-5.2": {
|
|
756
|
+
contextWindow: 1e6,
|
|
757
|
+
maxOutputTokens: 262144,
|
|
758
|
+
supportsTools: true,
|
|
759
|
+
supportsVision: false
|
|
760
|
+
}
|
|
761
|
+
});
|
|
762
|
+
var model_profiles_generated_default = {
|
|
763
|
+
"openai/gpt-5.5": {
|
|
764
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
765
|
+
latencyMs: 6243.1,
|
|
766
|
+
p95LatencyMs: 9865,
|
|
767
|
+
outputTokensPerSecond: 12.53,
|
|
768
|
+
errorRate: 0,
|
|
769
|
+
samples: 3
|
|
770
|
+
},
|
|
771
|
+
"openai/gpt-5.4-pro": {
|
|
772
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
773
|
+
latencyMs: 13015.5,
|
|
774
|
+
p95LatencyMs: 23976.4,
|
|
775
|
+
outputTokensPerSecond: 6.42,
|
|
776
|
+
errorRate: 0,
|
|
777
|
+
samples: 3
|
|
778
|
+
},
|
|
779
|
+
"openai/gpt-5.4-mini": {
|
|
780
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
781
|
+
latencyMs: 5550,
|
|
782
|
+
p95LatencyMs: 6595.7,
|
|
783
|
+
outputTokensPerSecond: 11.96,
|
|
784
|
+
errorRate: 0.3333,
|
|
785
|
+
samples: 3
|
|
786
|
+
},
|
|
787
|
+
"openai/gpt-5.3-codex": {
|
|
788
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
789
|
+
latencyMs: 4617.1,
|
|
790
|
+
p95LatencyMs: 5800.7,
|
|
791
|
+
outputTokensPerSecond: 12.48,
|
|
792
|
+
errorRate: 0,
|
|
793
|
+
samples: 3
|
|
794
|
+
},
|
|
795
|
+
"anthropic/claude-opus-4.8": {
|
|
796
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
797
|
+
latencyMs: 3915.1,
|
|
798
|
+
p95LatencyMs: 6130.8,
|
|
799
|
+
outputTokensPerSecond: 16.33,
|
|
800
|
+
errorRate: 0,
|
|
801
|
+
samples: 3
|
|
802
|
+
},
|
|
803
|
+
"anthropic/claude-opus-4.6": {
|
|
804
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
805
|
+
latencyMs: 3765.5,
|
|
806
|
+
p95LatencyMs: 4257.2,
|
|
807
|
+
outputTokensPerSecond: 14.18,
|
|
808
|
+
errorRate: 0,
|
|
809
|
+
samples: 3
|
|
810
|
+
},
|
|
811
|
+
"anthropic/claude-sonnet-4.6": {
|
|
812
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
813
|
+
latencyMs: 3860.6,
|
|
814
|
+
p95LatencyMs: 5093.5,
|
|
815
|
+
outputTokensPerSecond: 13.85,
|
|
816
|
+
errorRate: 0,
|
|
817
|
+
samples: 3
|
|
818
|
+
},
|
|
819
|
+
"anthropic/claude-haiku-4.5": {
|
|
820
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
821
|
+
latencyMs: 2734.9,
|
|
822
|
+
p95LatencyMs: 3181.6,
|
|
823
|
+
outputTokensPerSecond: 19.58,
|
|
824
|
+
errorRate: 0,
|
|
825
|
+
samples: 3
|
|
826
|
+
},
|
|
827
|
+
"google/gemini-3.1-pro": {
|
|
828
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
829
|
+
latencyMs: 13935.7,
|
|
830
|
+
p95LatencyMs: 26675.3,
|
|
831
|
+
outputTokensPerSecond: 77.47,
|
|
832
|
+
errorRate: 0,
|
|
833
|
+
samples: 3
|
|
834
|
+
},
|
|
835
|
+
"google/gemini-3.5-flash": {
|
|
836
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
837
|
+
latencyMs: 4608.7,
|
|
838
|
+
p95LatencyMs: 8420.9,
|
|
839
|
+
outputTokensPerSecond: 57.88,
|
|
840
|
+
errorRate: 0,
|
|
841
|
+
samples: 3
|
|
842
|
+
},
|
|
843
|
+
"google/gemini-3.1-flash-lite": {
|
|
844
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
845
|
+
latencyMs: 4619.7,
|
|
846
|
+
p95LatencyMs: 9927.1,
|
|
847
|
+
outputTokensPerSecond: 42.01,
|
|
848
|
+
errorRate: 0,
|
|
849
|
+
samples: 3
|
|
850
|
+
},
|
|
851
|
+
"google/gemini-2.5-flash": {
|
|
852
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
853
|
+
latencyMs: 5506.9,
|
|
854
|
+
p95LatencyMs: 11462.5,
|
|
855
|
+
outputTokensPerSecond: 65.19,
|
|
856
|
+
errorRate: 0,
|
|
857
|
+
samples: 3
|
|
858
|
+
},
|
|
859
|
+
"deepseek/deepseek-v4-pro": {
|
|
860
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
861
|
+
latencyMs: 6044.8,
|
|
862
|
+
p95LatencyMs: 10782.3,
|
|
863
|
+
outputTokensPerSecond: 22.47,
|
|
864
|
+
errorRate: 0,
|
|
865
|
+
samples: 3
|
|
866
|
+
},
|
|
867
|
+
"deepseek/deepseek-reasoner": {
|
|
868
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
869
|
+
latencyMs: 4111.9,
|
|
870
|
+
p95LatencyMs: 5305.7,
|
|
871
|
+
outputTokensPerSecond: 16.46,
|
|
872
|
+
errorRate: 0,
|
|
873
|
+
samples: 3
|
|
874
|
+
},
|
|
875
|
+
"deepseek/deepseek-chat": {
|
|
876
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
877
|
+
latencyMs: 2648.6,
|
|
878
|
+
p95LatencyMs: 3524.1,
|
|
879
|
+
outputTokensPerSecond: 16.73,
|
|
880
|
+
errorRate: 0,
|
|
881
|
+
samples: 3
|
|
882
|
+
},
|
|
883
|
+
"moonshot/kimi-k2.7": {
|
|
884
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
885
|
+
latencyMs: 4295.4,
|
|
886
|
+
p95LatencyMs: 6153.8,
|
|
887
|
+
outputTokensPerSecond: 18.54,
|
|
888
|
+
errorRate: 0,
|
|
889
|
+
samples: 3
|
|
890
|
+
},
|
|
891
|
+
"qwen/qwen3.7-max": {
|
|
892
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
893
|
+
latencyMs: 30729.4,
|
|
894
|
+
p95LatencyMs: 39622,
|
|
895
|
+
outputTokensPerSecond: 36.89,
|
|
896
|
+
errorRate: 0.3333,
|
|
897
|
+
samples: 3
|
|
898
|
+
},
|
|
899
|
+
"xai/grok-4.3": {
|
|
900
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
901
|
+
latencyMs: 6946.1,
|
|
902
|
+
p95LatencyMs: 9495.4,
|
|
903
|
+
outputTokensPerSecond: 65.3,
|
|
904
|
+
errorRate: 0,
|
|
905
|
+
samples: 3
|
|
906
|
+
},
|
|
907
|
+
"xai/grok-4.20-reasoning": {
|
|
908
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
909
|
+
latencyMs: 3472.4,
|
|
910
|
+
p95LatencyMs: 5332.4,
|
|
911
|
+
outputTokensPerSecond: 13.27,
|
|
912
|
+
errorRate: 0,
|
|
913
|
+
samples: 3
|
|
914
|
+
},
|
|
915
|
+
"xai/grok-4.20-non-reasoning": {
|
|
916
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
917
|
+
latencyMs: 5174.4,
|
|
918
|
+
p95LatencyMs: 6081.7,
|
|
919
|
+
outputTokensPerSecond: 10.21,
|
|
920
|
+
errorRate: 0.3333,
|
|
921
|
+
samples: 3
|
|
922
|
+
},
|
|
923
|
+
"xai/grok-4-1-fast-reasoning": {
|
|
924
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
925
|
+
latencyMs: 13148.2,
|
|
926
|
+
p95LatencyMs: 19104.2,
|
|
927
|
+
outputTokensPerSecond: 4.28,
|
|
928
|
+
errorRate: 0,
|
|
929
|
+
samples: 3
|
|
930
|
+
},
|
|
931
|
+
"minimax/minimax-m3": {
|
|
932
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
933
|
+
latencyMs: 3385,
|
|
934
|
+
p95LatencyMs: 4247.2,
|
|
935
|
+
outputTokensPerSecond: 15.16,
|
|
936
|
+
errorRate: 0,
|
|
937
|
+
samples: 3
|
|
938
|
+
},
|
|
939
|
+
"minimax/minimax-m2.7": {
|
|
940
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
941
|
+
latencyMs: 4596.7,
|
|
942
|
+
p95LatencyMs: 6884.6,
|
|
943
|
+
outputTokensPerSecond: 17.03,
|
|
944
|
+
errorRate: 0,
|
|
945
|
+
samples: 3
|
|
946
|
+
},
|
|
947
|
+
"zai/glm-5.2": {
|
|
948
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
949
|
+
latencyMs: 4406.3,
|
|
950
|
+
p95LatencyMs: 6139.7,
|
|
951
|
+
outputTokensPerSecond: 10.41,
|
|
952
|
+
errorRate: 0,
|
|
953
|
+
samples: 3
|
|
954
|
+
},
|
|
955
|
+
"zai/glm-5.1": {
|
|
956
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
957
|
+
latencyMs: 7775.4,
|
|
958
|
+
p95LatencyMs: 9182.1,
|
|
959
|
+
outputTokensPerSecond: 6.08,
|
|
960
|
+
errorRate: 0,
|
|
961
|
+
samples: 3
|
|
962
|
+
},
|
|
963
|
+
"zai/glm-5": {
|
|
964
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
965
|
+
latencyMs: 4159.4,
|
|
966
|
+
p95LatencyMs: 4992.7,
|
|
967
|
+
outputTokensPerSecond: 10.28,
|
|
968
|
+
errorRate: 0,
|
|
969
|
+
samples: 3
|
|
970
|
+
},
|
|
971
|
+
"free/qwen3-coder-480b": {
|
|
972
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
973
|
+
latencyMs: 2063.9,
|
|
974
|
+
p95LatencyMs: 3646.3,
|
|
975
|
+
outputTokensPerSecond: 39.8,
|
|
976
|
+
errorRate: 0,
|
|
977
|
+
samples: 3
|
|
978
|
+
},
|
|
979
|
+
"free/mistral-large-3-675b": {
|
|
980
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
981
|
+
latencyMs: 3147.5,
|
|
982
|
+
p95LatencyMs: 5555.3,
|
|
983
|
+
outputTokensPerSecond: 27.76,
|
|
984
|
+
errorRate: 0,
|
|
985
|
+
samples: 3
|
|
986
|
+
},
|
|
987
|
+
"free/nemotron-3-nano-omni-30b-a3b-reasoning": {
|
|
988
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
989
|
+
latencyMs: 6508.4,
|
|
990
|
+
p95LatencyMs: 14252.7,
|
|
991
|
+
outputTokensPerSecond: 68.26,
|
|
992
|
+
errorRate: 0,
|
|
993
|
+
samples: 3
|
|
994
|
+
},
|
|
995
|
+
"free/glm-4.7": {
|
|
996
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
997
|
+
latencyMs: 2014.8,
|
|
998
|
+
p95LatencyMs: 3039.9,
|
|
999
|
+
outputTokensPerSecond: 39.92,
|
|
1000
|
+
errorRate: 0,
|
|
1001
|
+
samples: 3
|
|
1002
|
+
}
|
|
1003
|
+
};
|
|
1004
|
+
var LIVE_MODEL_PROFILES = Object.freeze(
|
|
1005
|
+
model_profiles_generated_default
|
|
1006
|
+
);
|
|
1007
|
+
var HISTORICAL_MODEL_PROFILES = Object.freeze({
|
|
1008
|
+
"anthropic/claude-haiku-4.5": {
|
|
1009
|
+
measuredAt: "2026-03-16T13:50:48Z",
|
|
1010
|
+
latencyMs: 2305,
|
|
1011
|
+
outputTokensPerSecond: 140.6
|
|
1012
|
+
},
|
|
1013
|
+
"anthropic/claude-opus-4.6": {
|
|
1014
|
+
measuredAt: "2026-03-16T13:50:48Z",
|
|
1015
|
+
latencyMs: 2139,
|
|
1016
|
+
outputTokensPerSecond: 119.7
|
|
1017
|
+
},
|
|
1018
|
+
"anthropic/claude-sonnet-4.6": {
|
|
1019
|
+
measuredAt: "2026-03-16T13:50:48Z",
|
|
1020
|
+
latencyMs: 2110,
|
|
1021
|
+
outputTokensPerSecond: 121.3
|
|
1022
|
+
},
|
|
1023
|
+
"deepseek/deepseek-chat": {
|
|
1024
|
+
measuredAt: "2026-03-16T13:50:48Z",
|
|
1025
|
+
latencyMs: 1431,
|
|
1026
|
+
outputTokensPerSecond: 179.2,
|
|
1027
|
+
intelligenceIndex: 32
|
|
1028
|
+
},
|
|
1029
|
+
"google/gemini-2.5-flash": {
|
|
1030
|
+
measuredAt: "2026-03-16T13:50:48Z",
|
|
1031
|
+
latencyMs: 1238,
|
|
1032
|
+
outputTokensPerSecond: 207.6,
|
|
1033
|
+
intelligenceIndex: 20
|
|
1034
|
+
},
|
|
1035
|
+
"google/gemini-2.5-flash-lite": {
|
|
1036
|
+
measuredAt: "2026-03-16T13:50:48Z",
|
|
1037
|
+
latencyMs: 1353,
|
|
1038
|
+
outputTokensPerSecond: 192.5,
|
|
1039
|
+
intelligenceIndex: 20
|
|
1040
|
+
},
|
|
1041
|
+
"google/gemini-2.5-pro": {
|
|
1042
|
+
measuredAt: "2026-03-16T13:50:48Z",
|
|
1043
|
+
latencyMs: 1294,
|
|
1044
|
+
outputTokensPerSecond: 197.8
|
|
1045
|
+
},
|
|
1046
|
+
"google/gemini-3.1-pro": {
|
|
1047
|
+
measuredAt: "2026-03-16T13:50:48Z",
|
|
1048
|
+
latencyMs: 1609,
|
|
1049
|
+
outputTokensPerSecond: 167.2
|
|
1050
|
+
},
|
|
1051
|
+
"moonshot/kimi-k2.5": {
|
|
1052
|
+
measuredAt: "2026-03-16T13:50:48Z",
|
|
1053
|
+
latencyMs: 1646,
|
|
1054
|
+
outputTokensPerSecond: 155.7
|
|
1055
|
+
},
|
|
1056
|
+
"openai/gpt-4o-mini": {
|
|
1057
|
+
measuredAt: "2026-03-16T13:50:48Z",
|
|
1058
|
+
latencyMs: 2764,
|
|
1059
|
+
outputTokensPerSecond: 92.8
|
|
1060
|
+
},
|
|
1061
|
+
"openai/gpt-5.3-codex": {
|
|
1062
|
+
measuredAt: "2026-03-16T13:50:48Z",
|
|
1063
|
+
latencyMs: 7935,
|
|
1064
|
+
outputTokensPerSecond: 32.3
|
|
1065
|
+
},
|
|
1066
|
+
"xai/grok-4-1-fast-non-reasoning": {
|
|
1067
|
+
measuredAt: "2026-03-16T13:50:48Z",
|
|
1068
|
+
latencyMs: 1244,
|
|
1069
|
+
outputTokensPerSecond: 205.8,
|
|
1070
|
+
intelligenceIndex: 41
|
|
1071
|
+
},
|
|
1072
|
+
"xai/grok-4-1-fast-reasoning": {
|
|
1073
|
+
measuredAt: "2026-03-16T13:50:48Z",
|
|
1074
|
+
latencyMs: 1454,
|
|
1075
|
+
outputTokensPerSecond: 176.2,
|
|
1076
|
+
intelligenceIndex: 41
|
|
1077
|
+
}
|
|
1078
|
+
});
|
|
1079
|
+
function inferToolRequirement(prompt, _systemPrompt, toolChoice) {
|
|
1080
|
+
if (toolChoice === "none") return false;
|
|
1081
|
+
if (toolChoice === "required") return true;
|
|
1082
|
+
if (typeof toolChoice === "object" && toolChoice !== null && toolChoice.type === "function") {
|
|
1083
|
+
return true;
|
|
1084
|
+
}
|
|
1085
|
+
const text = prompt;
|
|
1086
|
+
const explicitTool = /\b(?:use|call|invoke)\s+(?:the\s+)?[\w.-]+\s+(?:tool|function|api)\b|\btool[_ -]?call\b|使用.{0,20}(?:工具|函数|接口)|调用.{0,20}(?:工具|函数|接口)/i;
|
|
1087
|
+
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;
|
|
1088
|
+
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;
|
|
1089
|
+
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;
|
|
1090
|
+
return explicitTool.test(text) || codeEnvironment.test(text) || webAction.test(text) || statefulAction.test(text);
|
|
1091
|
+
}
|
|
1092
|
+
var DEFAULT_PORTFOLIO_WEIGHTS = {
|
|
1093
|
+
auto: {
|
|
1094
|
+
quality: 0.47,
|
|
1095
|
+
capability: 0.2,
|
|
1096
|
+
cost: 0.18,
|
|
1097
|
+
speed: 0.07,
|
|
1098
|
+
reliability: 0.03,
|
|
1099
|
+
legacy: 0.05
|
|
1100
|
+
},
|
|
1101
|
+
eco: { quality: 0.36, capability: 0.2, cost: 0.28, speed: 0.1, reliability: 0.04, legacy: 0.02 },
|
|
1102
|
+
premium: {
|
|
1103
|
+
quality: 0.58,
|
|
1104
|
+
capability: 0.2,
|
|
1105
|
+
cost: 0.08,
|
|
1106
|
+
speed: 0.06,
|
|
1107
|
+
reliability: 0.06,
|
|
1108
|
+
legacy: 0.02
|
|
1109
|
+
},
|
|
1110
|
+
highStakesBoost: { quality: 0.08, reliability: 0.05 },
|
|
1111
|
+
latencySensitiveSpeedBoost: 0.08,
|
|
1112
|
+
affinityFloorGap: { auto: 0.1, eco: 0.22, premium: 0.05 }
|
|
1113
|
+
};
|
|
1114
|
+
function likelyNeedsParallelToolCalls(prompt, needsTools, toolCount, toolNames) {
|
|
1115
|
+
if (!needsTools || toolCount === void 0 || toolCount < 1) return false;
|
|
1116
|
+
const text = prompt.trim();
|
|
1117
|
+
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(
|
|
1118
|
+
text
|
|
1119
|
+
);
|
|
1120
|
+
if (explicitRepeat) return true;
|
|
1121
|
+
const sentenceClauses = text.split(/[.!?。!?]+/).map((part) => part.trim()).filter((part) => part.length >= 8);
|
|
1122
|
+
if (/\b(?:also|additionally|furthermore)\b|另外|此外|그리고/i.test(text) && sentenceClauses.length >= 2 || /\band\s+(?:also|for the)\b/i.test(text))
|
|
1123
|
+
return true;
|
|
1124
|
+
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(
|
|
1125
|
+
text
|
|
1126
|
+
);
|
|
1127
|
+
if (pairedQuantity) return true;
|
|
1128
|
+
const operationTokens = /* @__PURE__ */ new Set([
|
|
1129
|
+
"add",
|
|
1130
|
+
"delete",
|
|
1131
|
+
"remove",
|
|
1132
|
+
"cancel",
|
|
1133
|
+
"return",
|
|
1134
|
+
"exchange",
|
|
1135
|
+
"modify",
|
|
1136
|
+
"book",
|
|
1137
|
+
"transfer",
|
|
1138
|
+
"send",
|
|
1139
|
+
"upload",
|
|
1140
|
+
"download",
|
|
1141
|
+
"create",
|
|
1142
|
+
"close"
|
|
1143
|
+
]);
|
|
1144
|
+
const lowered = text.toLowerCase();
|
|
1145
|
+
const matchedOperationTokens = new Set(
|
|
1146
|
+
(toolNames ?? []).flatMap((name) => name.toLowerCase().split(/[^a-z0-9\u3400-\u9fff]+/)).filter((token) => operationTokens.has(token) && lowered.includes(token))
|
|
1147
|
+
);
|
|
1148
|
+
if (matchedOperationTokens.size >= 2) return true;
|
|
1149
|
+
const nonEmptyLines = text.split(/\r?\n/).map((line) => line.trim()).filter(Boolean);
|
|
1150
|
+
const quantityMentions = text.match(
|
|
1151
|
+
/\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
|
|
1152
|
+
) ?? [];
|
|
1153
|
+
if (nonEmptyLines.length >= 2 && quantityMentions.length >= 2) return true;
|
|
1154
|
+
const repeatedLookup = /\b(?:weather|climate|clima|tiempo|temperature|snow|news|report)\b|天气|气象|温度|降雪|新闻|报告/i.test(
|
|
1155
|
+
text
|
|
1156
|
+
);
|
|
1157
|
+
const multiLocationConnector = /\b(?:and also|both|y|e)\b|还有|以及|和|、/i.test(text);
|
|
1158
|
+
const commaSeparatedLocations = (text.match(/[,,]/g) ?? []).length >= 2;
|
|
1159
|
+
if (repeatedLookup && (multiLocationConnector || commaSeparatedLocations)) return true;
|
|
1160
|
+
const distinctOrderParts = /\b(?:food|meal)\b[\s\S]*\bdrink\b|\bdrink\b[\s\S]*\b(?:food|meal)\b/i.test(text);
|
|
1161
|
+
const koreanParallelClauses = (text.match(/,/g) ?? []).length >= 3 && /하고|그리고/.test(text);
|
|
1162
|
+
return distinctOrderParts || koreanParallelClauses;
|
|
1163
|
+
}
|
|
1164
|
+
function classifyTask(prompt, systemPrompt, options) {
|
|
1165
|
+
const fullText = `${systemPrompt ?? ""} ${prompt}`;
|
|
1166
|
+
const estimatedInputTokens = Math.ceil(fullText.length / 4);
|
|
1167
|
+
const scanLimit = Math.max(1, Math.min(8e3, options.config.classifier.promptTruncationChars));
|
|
1168
|
+
const sample = (value) => {
|
|
1169
|
+
if (value.length <= scanLimit) return value;
|
|
1170
|
+
const prefixLength = Math.ceil(scanLimit / 2);
|
|
1171
|
+
return `${value.slice(0, prefixLength)}
|
|
1172
|
+
${value.slice(-(scanLimit - prefixLength))}`;
|
|
1173
|
+
};
|
|
1174
|
+
const scannedPrompt = sample(prompt);
|
|
1175
|
+
const scannedSystemPrompt = sample(systemPrompt ?? "");
|
|
1176
|
+
const scannedFullText = `${scannedSystemPrompt} ${scannedPrompt}`;
|
|
1177
|
+
const text = scannedPrompt.toLowerCase();
|
|
1178
|
+
const explicitCodeSignal = /```|\b(?:typescript|javascript|python|rust|java|sql|stack trace|traceback|exception)\b|\.(?:ts|tsx|js|py|go|rs)\b/i.test(
|
|
1179
|
+
scannedPrompt
|
|
1180
|
+
);
|
|
1181
|
+
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(
|
|
1182
|
+
scannedPrompt
|
|
1183
|
+
);
|
|
1184
|
+
const nativeCodeSignal = /\b(?:programmed|written|implemented?|code)\s+(?:in|using)\s+(?:c\+\+|c|rust|go)\b/i.test(
|
|
1185
|
+
scannedPrompt
|
|
1186
|
+
);
|
|
1187
|
+
const hasCode = explicitCodeSignal || codeConstructSignal || nativeCodeSignal;
|
|
1188
|
+
const toolsAvailable = options.hasTools ?? false;
|
|
1189
|
+
const needsTools = options.requiresTools ?? (toolsAvailable && inferToolRequirement(scannedPrompt, scannedSystemPrompt));
|
|
1190
|
+
const likelyParallelToolCalls = likelyNeedsParallelToolCalls(
|
|
1191
|
+
scannedPrompt,
|
|
1192
|
+
needsTools,
|
|
1193
|
+
options.toolCount,
|
|
1194
|
+
options.toolNames
|
|
1195
|
+
);
|
|
1196
|
+
const normalizedToolNames = (options.toolNames ?? []).map((name) => name.toLowerCase());
|
|
1197
|
+
const airlineToolSignal = normalizedToolNames.some(
|
|
1198
|
+
(name) => /(?:flight|reservation|airport|baggage|passenger)/.test(name)
|
|
1199
|
+
);
|
|
1200
|
+
const retailToolSignal = normalizedToolNames.some(
|
|
1201
|
+
(name) => /(?:order|product|item|return|exchange|address)/.test(name)
|
|
1202
|
+
);
|
|
1203
|
+
const webResearchToolSignal = normalizedToolNames.some(
|
|
1204
|
+
(name) => /^(?:web_?search|web_?fetch)$/.test(name)
|
|
1205
|
+
);
|
|
1206
|
+
const agentDomain = airlineToolSignal && !retailToolSignal ? "airline" : retailToolSignal && !airlineToolSignal ? "retail" : webResearchToolSignal ? "web_research" : "other";
|
|
1207
|
+
const clueConnectors = scannedFullText.match(
|
|
1208
|
+
/\b(?:after|before|while|where|whose|which|in \d{4}|as of|over \d+|another|also|furthermore)\b|(?:之后|之前|其中|截至|超过|另一个|此外)/gi
|
|
1209
|
+
) ?? [];
|
|
1210
|
+
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(
|
|
1211
|
+
scannedFullText
|
|
1212
|
+
);
|
|
1213
|
+
const exactAnswerSignal = /\b(?:exact answer|single best-supported answer|following clues|multiple public sources)\b|(?:精确答案|根据.*线索|多个公开来源)/i.test(
|
|
1214
|
+
scannedFullText
|
|
1215
|
+
);
|
|
1216
|
+
const deepWebResearch = agentDomain === "web_research" && (exactAnswerSignal || entityResolutionSignal && (clueConnectors.length >= 3 || prompt.length >= 320));
|
|
1217
|
+
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(
|
|
1218
|
+
scannedPrompt
|
|
1219
|
+
);
|
|
1220
|
+
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(
|
|
1221
|
+
scannedPrompt
|
|
1222
|
+
);
|
|
1223
|
+
const globalChoiceSignal = globalOptimizationSignal || globalScopeSignal;
|
|
1224
|
+
const crossRecordSignal = /\b(?:another|other|different|previous)\s+(?:order|reservation|booking|account|address)\b|另一(?:个)?(?:订单|预订|账户|地址)|其他(?:订单|预订|账户|地址)/i.test(
|
|
1225
|
+
scannedPrompt
|
|
1226
|
+
);
|
|
1227
|
+
const reservationIds = scannedPrompt.match(/\b[A-Z0-9]{6}\b/g) ?? [];
|
|
1228
|
+
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(
|
|
1229
|
+
scannedPrompt
|
|
1230
|
+
) || new Set(reservationIds).size >= 2);
|
|
1231
|
+
const conditionalGlobalWorkflowSignal = agentDomain === "airline" && globalScopeSignal && /\b(?:if|that (?:contain|have)|longer than|shorter than|under|over|at (?:most|least)|wherever possible)\b|如果|超过|少于|不超过|尽可能/i.test(
|
|
1232
|
+
scannedPrompt
|
|
1233
|
+
) && /\b(?:cancel|change|upgrade|move|book)\b[\s\S]*\b(?:cancel|change|upgrade|move|book)\b|取消[\s\S]*(?:升级|更改)|升级[\s\S]*(?:取消|更改)/i.test(
|
|
1234
|
+
scannedPrompt
|
|
1235
|
+
);
|
|
1236
|
+
const policyExceptionSignal = agentDomain === "retail" && /\b(?:return|refund|send back|get (?:my |the )?money back)\b|退货|退款|退回/i.test(
|
|
1237
|
+
scannedPrompt
|
|
1238
|
+
) && /\b(?:amex|american express|visa|mastercard|credit card|debit card|different card|another card|other card)\b|信用卡|借记卡|其他卡|另一张卡/i.test(
|
|
1239
|
+
scannedPrompt
|
|
1240
|
+
);
|
|
1241
|
+
const singleSelectedPolicyException = policyExceptionSignal && /\b(?:return|refund|send back)\b[^.!?。!?]{0,96}\b(?:the )?(?:pricier|cheaper|more expensive|less expensive|costlier|one)\b/i.test(
|
|
1242
|
+
scannedPrompt
|
|
1243
|
+
);
|
|
1244
|
+
const negotiatedWorkflowSignal = agentDomain === "retail" && /\b(?:return|exchange)\b|退货|退回|换货|交换/i.test(scannedPrompt);
|
|
1245
|
+
const numberedSteps = (scannedPrompt.match(/(?:^|\s)\d+(?:\.\d+)*[.)]\s+/g) ?? []).length;
|
|
1246
|
+
const complexMultiToolPlan = likelyParallelToolCalls && ((options.toolCount ?? 0) >= 6 || numberedSteps >= 3 || prompt.length > 1200);
|
|
1247
|
+
let agentRisk = needsTools && singleSelectedPolicyException ? "policy_exception_simple" : needsTools && policyExceptionSignal ? "policy_exception" : (
|
|
1248
|
+
// Airline prompts that require a global optimum (for example the
|
|
1249
|
+
// cheapest itinerary across several candidates) are materially harder
|
|
1250
|
+
// than applying one change to every passenger in a known reservation.
|
|
1251
|
+
// Full-session evidence supports Sonnet for the former, while upgrading
|
|
1252
|
+
// the latter merely because it says "all passengers" caused a large cost
|
|
1253
|
+
// increase without a quality gain.
|
|
1254
|
+
needsTools && agentDomain === "airline" && (globalOptimizationSignal || conditionalGlobalWorkflowSignal) ? "complex_high" : needsTools && (likelyParallelToolCalls || globalChoiceSignal || crossRecordSignal || crossReservationBatchSignal || negotiatedWorkflowSignal) ? "high" : "standard"
|
|
1255
|
+
);
|
|
1256
|
+
const needsVision = options.hasVision ?? false;
|
|
1257
|
+
const needsStructuredOutput = options.requiresStructuredOutput ?? false;
|
|
1258
|
+
const latencySensitive = /\b(?:urgent|asap|fast|quick|low latency|real[- ]time)\b|尽快|马上|快速|低延迟/i.test(
|
|
1259
|
+
scannedFullText
|
|
1260
|
+
);
|
|
1261
|
+
const highStakes = /\b(?:production|security|payment|legal|medical|financial|audit)\b|生产|安全|支付|法律|医疗|财务|审计/i.test(
|
|
1262
|
+
scannedFullText
|
|
1263
|
+
);
|
|
1264
|
+
const terminalToolSignal = normalizedToolNames.some(
|
|
1265
|
+
(name) => /^(?:terminalexec|terminalinspect|terminalsendkeys)$/.test(name)
|
|
1266
|
+
);
|
|
1267
|
+
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(
|
|
1268
|
+
scannedPrompt
|
|
1269
|
+
);
|
|
1270
|
+
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(
|
|
1271
|
+
scannedPrompt
|
|
1272
|
+
);
|
|
1273
|
+
const mentionedTerminalRuntimes = new Set(
|
|
1274
|
+
(scannedPrompt.match(/\b(?:gcc|clang|rustc|javac|go\s+build|node|python)\b/gi) ?? []).map(
|
|
1275
|
+
(name) => name.toLowerCase().replace(/\s+/g, " ")
|
|
1276
|
+
)
|
|
1277
|
+
);
|
|
1278
|
+
const terminalCrossRuntimeArtifact = terminalToolSignal && (/\bpolyglot\b/i.test(scannedPrompt) || /\b(?:both|each)\b[\s\S]{0,120}\b(?:compilers?|runtimes?|toolchains?)\b/i.test(
|
|
1279
|
+
scannedPrompt
|
|
1280
|
+
) || mentionedTerminalRuntimes.size >= 2 && /\b(?:compile|build|run|execute)\b/i.test(scannedPrompt));
|
|
1281
|
+
const terminalFrameworkToNativeArtifact = terminalToolSignal && /\b(?:pytorch|tensorflow|jax|onnx|state[_ -]?dict|checkpoint|safetensors?)\b|\.(?:pth|pt|onnx)\b/i.test(
|
|
1282
|
+
scannedPrompt
|
|
1283
|
+
) && /\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(
|
|
1284
|
+
scannedPrompt
|
|
1285
|
+
) && /\b(?:inference|model|weights?|tensor|export|convert|load)\b/i.test(scannedPrompt);
|
|
1286
|
+
if (needsTools && (terminalComplexRepair || terminalCrossRuntimeArtifact || terminalFrameworkToNativeArtifact) && (agentRisk === "standard" || agentRisk === "high"))
|
|
1287
|
+
agentRisk = "complex_high";
|
|
1288
|
+
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(
|
|
1289
|
+
scannedPrompt
|
|
1290
|
+
);
|
|
1291
|
+
const terminalCredentialSignal = /\b(?:ssh|nginx|certificate|authentication|credentials?|passwords?|api keys?|deploy|production|encrypt|gpg|shred|securely delete|decommission)\b/i.test(
|
|
1292
|
+
scannedPrompt
|
|
1293
|
+
) || /\b(?:access|auth|authentication|bearer|secret|api)\s+tokens?\b|\btokens?\s+(?:secret|credential|authentication)\b/i.test(
|
|
1294
|
+
scannedPrompt
|
|
1295
|
+
);
|
|
1296
|
+
const terminalSafetySensitive = terminalToolSignal && (highStakes || terminalCredentialSignal);
|
|
1297
|
+
const implicitTerminalCode = needsTools && terminalToolSignal && agentRisk === "standard" && !highStakes && !complexTerminalOperation && numberedSteps < 3 && prompt.length <= 1e3 && simpleTerminalArtifact;
|
|
1298
|
+
const language = /[\u3400-\u9fff]/.test(scannedFullText) ? "zh" : "other";
|
|
1299
|
+
const multipleChoiceSignals = (scannedPrompt.match(/(?:^|\n)\s*[A-D][.)]\s+/gim) ?? []).length;
|
|
1300
|
+
const numericSignals = (scannedPrompt.match(/-?\d+(?:[.,]\d+)?/g) ?? []).length;
|
|
1301
|
+
const compactMathProblem = !hasCode && prompt.length < 2500 && numericSignals >= 2 && (/[+×÷=%$€£¥]|\b(?:total|each|per|times|half|twice|percent|how many|how much|calculate)\b/i.test(
|
|
1302
|
+
scannedPrompt
|
|
1303
|
+
) || /[??]\s*$/.test(scannedPrompt.trim()) || numericSignals >= 3);
|
|
1304
|
+
let taskType = "chat";
|
|
1305
|
+
if (needsVision) taskType = "vision";
|
|
1306
|
+
else if (estimatedInputTokens > 8e4) taskType = "long_context";
|
|
1307
|
+
else if (needsTools && (hasCode || implicitTerminalCode)) taskType = "code_agent";
|
|
1308
|
+
else if (needsTools && likelyParallelToolCalls && !complexMultiToolPlan)
|
|
1309
|
+
taskType = "tool_agent_parallel";
|
|
1310
|
+
else if (needsTools) taskType = "tool_agent";
|
|
1311
|
+
else if (multipleChoiceSignals >= 3) taskType = "reasoning_mcq";
|
|
1312
|
+
else if (compactMathProblem) taskType = "reasoning_math";
|
|
1313
|
+
else if (/\b(?:bug|debug|error|failure|failing|regression|crash|修复|报错|错误|调试)\b/i.test(text))
|
|
1314
|
+
taskType = "debug";
|
|
1315
|
+
else if (hasCode || /\b(?:refactor|implement|patch|edit|rewrite|重构|实现|修改)\b/i.test(text))
|
|
1316
|
+
taskType = "code_edit";
|
|
1317
|
+
else if (needsStructuredOutput || /\b(?:extract|json|schema|csv|字段|提取)\b/i.test(text))
|
|
1318
|
+
taskType = "extraction";
|
|
1319
|
+
else if (/\b(?:prove|derive|theorem|formal|mathematical|reasoning|证明|推导|定理|数学)\b/i.test(text))
|
|
1320
|
+
taskType = "reasoning";
|
|
1321
|
+
return {
|
|
1322
|
+
taskType,
|
|
1323
|
+
estimatedInputTokens,
|
|
1324
|
+
hasCode,
|
|
1325
|
+
needsTools,
|
|
1326
|
+
toolsAvailable,
|
|
1327
|
+
needsVision,
|
|
1328
|
+
needsStructuredOutput,
|
|
1329
|
+
latencySensitive,
|
|
1330
|
+
highStakes,
|
|
1331
|
+
language,
|
|
1332
|
+
likelyParallelToolCalls,
|
|
1333
|
+
complexMultiToolPlan,
|
|
1334
|
+
agentDomain,
|
|
1335
|
+
deepWebResearch,
|
|
1336
|
+
agentRisk,
|
|
1337
|
+
terminalToolSignal,
|
|
1338
|
+
terminalSafetySensitive,
|
|
1339
|
+
implicitTerminalCode
|
|
1340
|
+
};
|
|
1341
|
+
}
|
|
1342
|
+
function affinity(modelId, task, language = "other", agentDomain = "other", deepWebResearch = false, agentRisk = "standard", terminalToolSignal = false, terminalSafetySensitive = false) {
|
|
1343
|
+
const id = modelId.toLowerCase();
|
|
1344
|
+
const modelName = id.slice(id.indexOf("/") + 1);
|
|
1345
|
+
const match = (values, score) => values.some((value) => modelName === value) ? score : 0;
|
|
1346
|
+
const base = 0.68;
|
|
1347
|
+
switch (task) {
|
|
1348
|
+
case "code_agent":
|
|
1349
|
+
if (terminalToolSignal && agentRisk === "complex_high") {
|
|
1350
|
+
return Math.max(
|
|
1351
|
+
base,
|
|
1352
|
+
match(["claude-sonnet-5"], 1),
|
|
1353
|
+
match(["gpt-5.3-codex"], 0.87),
|
|
1354
|
+
match(["gpt-5-mini"], 0.78),
|
|
1355
|
+
match(["gemini-3.5-flash"], 0.76)
|
|
1356
|
+
);
|
|
1357
|
+
}
|
|
1358
|
+
return Math.max(
|
|
1359
|
+
base,
|
|
1360
|
+
match(["gpt-5.3-codex"], 1),
|
|
1361
|
+
match(["claude-sonnet-5"], 0.98),
|
|
1362
|
+
match(["gpt-5-mini"], 0.96),
|
|
1363
|
+
match(["gemini-3.5-flash"], 0.92),
|
|
1364
|
+
match(["kimi-k3"], 0.9),
|
|
1365
|
+
match(["deepseek-v4-pro", "glm-5.2"], 0.88)
|
|
1366
|
+
);
|
|
1367
|
+
case "tool_agent":
|
|
1368
|
+
if (terminalToolSignal && agentRisk === "complex_high") {
|
|
1369
|
+
return Math.max(
|
|
1370
|
+
base,
|
|
1371
|
+
match(["claude-sonnet-5"], 1),
|
|
1372
|
+
match(["gpt-5.3-codex"], 0.87),
|
|
1373
|
+
match(["gpt-5-mini"], 0.78),
|
|
1374
|
+
match(["gemini-3.5-flash"], 0.76)
|
|
1375
|
+
);
|
|
1376
|
+
}
|
|
1377
|
+
if (terminalToolSignal && !terminalSafetySensitive) {
|
|
1378
|
+
return Math.max(
|
|
1379
|
+
base,
|
|
1380
|
+
match(["gpt-5-mini"], 1),
|
|
1381
|
+
match(["gpt-5.3-codex"], 0.98),
|
|
1382
|
+
match(["claude-sonnet-5"], 0.9),
|
|
1383
|
+
match(["gemini-3.5-flash"], 0.89)
|
|
1384
|
+
);
|
|
1385
|
+
}
|
|
1386
|
+
if (terminalToolSignal && terminalSafetySensitive) {
|
|
1387
|
+
return Math.max(
|
|
1388
|
+
base,
|
|
1389
|
+
match(["claude-sonnet-5"], 1),
|
|
1390
|
+
match(["claude-opus-4.8"], 0.9),
|
|
1391
|
+
match(["gpt-5.3-codex"], 0.84)
|
|
1392
|
+
);
|
|
1393
|
+
}
|
|
1394
|
+
if (agentDomain === "web_research") {
|
|
1395
|
+
return deepWebResearch ? Math.max(
|
|
1396
|
+
base,
|
|
1397
|
+
match(["claude-sonnet-5"], 1),
|
|
1398
|
+
match(["gpt-5-mini"], 0.88),
|
|
1399
|
+
match(["gemini-3.5-flash"], 0.84),
|
|
1400
|
+
match(["claude-opus-5"], 0.8),
|
|
1401
|
+
match(["claude-opus-4.8"], 0.78)
|
|
1402
|
+
) : Math.max(
|
|
1403
|
+
base,
|
|
1404
|
+
match(["claude-sonnet-5"], 1),
|
|
1405
|
+
match(["gpt-5-mini"], 0.88),
|
|
1406
|
+
match(["gemini-3.5-flash"], 0.86),
|
|
1407
|
+
match(["claude-opus-5"], 0.84),
|
|
1408
|
+
match(["claude-opus-4.8"], 0.82)
|
|
1409
|
+
);
|
|
1410
|
+
}
|
|
1411
|
+
if (agentDomain === "retail") {
|
|
1412
|
+
if (agentRisk === "standard") {
|
|
1413
|
+
return Math.max(
|
|
1414
|
+
base,
|
|
1415
|
+
match(["gpt-5-mini"], 1),
|
|
1416
|
+
match(["claude-sonnet-5"], 0.88),
|
|
1417
|
+
match(["gemini-3.5-flash"], 0.82),
|
|
1418
|
+
match(["gpt-5.3-codex"], 0.81),
|
|
1419
|
+
match(["kimi-k3"], 0.78),
|
|
1420
|
+
match(["deepseek-v4-pro"], 0.76)
|
|
1421
|
+
);
|
|
1422
|
+
}
|
|
1423
|
+
if (agentRisk === "policy_exception") {
|
|
1424
|
+
return Math.max(
|
|
1425
|
+
base,
|
|
1426
|
+
match(["gpt-4.1"], 1),
|
|
1427
|
+
match(["claude-sonnet-5"], 0.9),
|
|
1428
|
+
match(["deepseek-v4-pro"], 0.82),
|
|
1429
|
+
match(["gpt-5-mini"], 0.8),
|
|
1430
|
+
match(["gpt-4o-mini"], 0.76)
|
|
1431
|
+
);
|
|
1432
|
+
}
|
|
1433
|
+
if (agentRisk === "policy_exception_simple") {
|
|
1434
|
+
return Math.max(
|
|
1435
|
+
base,
|
|
1436
|
+
match(["gpt-5-mini"], 1),
|
|
1437
|
+
match(["gpt-4.1"], 0.86),
|
|
1438
|
+
match(["deepseek-v4-pro"], 0.82),
|
|
1439
|
+
match(["gpt-4o-mini"], 0.8)
|
|
1440
|
+
);
|
|
1441
|
+
}
|
|
1442
|
+
return Math.max(
|
|
1443
|
+
base,
|
|
1444
|
+
match(["deepseek-v4-pro"], 1),
|
|
1445
|
+
match(["claude-sonnet-5"], 0.88),
|
|
1446
|
+
match(["gemini-3.5-flash"], 0.82),
|
|
1447
|
+
match(["gpt-5.3-codex"], 0.81),
|
|
1448
|
+
match(["kimi-k3"], 0.78),
|
|
1449
|
+
match(["gpt-5-mini"], 0.76)
|
|
1450
|
+
);
|
|
1451
|
+
}
|
|
1452
|
+
if (agentDomain === "airline") {
|
|
1453
|
+
if (agentRisk === "complex_high") {
|
|
1454
|
+
return Math.max(
|
|
1455
|
+
base,
|
|
1456
|
+
match(["claude-sonnet-5"], 1),
|
|
1457
|
+
match(["gpt-5-mini"], 0.78),
|
|
1458
|
+
match(["gemini-3.5-flash"], 0.76),
|
|
1459
|
+
match(["deepseek-v4-pro"], 0.74)
|
|
1460
|
+
);
|
|
1461
|
+
}
|
|
1462
|
+
return Math.max(
|
|
1463
|
+
base,
|
|
1464
|
+
match(["gpt-5-mini"], 1),
|
|
1465
|
+
match(["claude-sonnet-5"], 0.9),
|
|
1466
|
+
match(["gemini-3.5-flash"], 0.8),
|
|
1467
|
+
match(["deepseek-v4-pro"], 0.76)
|
|
1468
|
+
);
|
|
1469
|
+
}
|
|
1470
|
+
return Math.max(
|
|
1471
|
+
base,
|
|
1472
|
+
match(["claude-sonnet-5"], 1),
|
|
1473
|
+
match(["gemini-3.5-flash"], 0.88),
|
|
1474
|
+
match(["gpt-5.3-codex"], 0.87),
|
|
1475
|
+
match(["gpt-5-mini"], 0.84),
|
|
1476
|
+
match(["kimi-k3"], 0.85),
|
|
1477
|
+
match(["deepseek-v4-pro"], 0.82)
|
|
1478
|
+
);
|
|
1479
|
+
case "tool_agent_parallel":
|
|
1480
|
+
if (terminalToolSignal) {
|
|
1481
|
+
return terminalSafetySensitive ? Math.max(
|
|
1482
|
+
base,
|
|
1483
|
+
match(["claude-sonnet-5"], 1),
|
|
1484
|
+
match(["claude-opus-4.8"], 0.9),
|
|
1485
|
+
match(["gpt-5.3-codex"], 0.86)
|
|
1486
|
+
) : Math.max(
|
|
1487
|
+
base,
|
|
1488
|
+
match(["gpt-5-mini"], 1),
|
|
1489
|
+
match(["gpt-5.3-codex"], 0.98),
|
|
1490
|
+
match(["claude-sonnet-5"], 0.92),
|
|
1491
|
+
match(["gemini-3.5-flash"], 0.88)
|
|
1492
|
+
);
|
|
1493
|
+
}
|
|
1494
|
+
if (agentDomain === "web_research") {
|
|
1495
|
+
return deepWebResearch ? Math.max(
|
|
1496
|
+
base,
|
|
1497
|
+
match(["claude-sonnet-5"], 1),
|
|
1498
|
+
match(["gpt-5-mini"], 0.88),
|
|
1499
|
+
match(["gemini-3.5-flash"], 0.84),
|
|
1500
|
+
match(["claude-opus-5"], 0.8),
|
|
1501
|
+
match(["claude-opus-4.8"], 0.78)
|
|
1502
|
+
) : Math.max(
|
|
1503
|
+
base,
|
|
1504
|
+
match(["claude-sonnet-5"], 1),
|
|
1505
|
+
match(["gpt-5-mini"], 0.88),
|
|
1506
|
+
match(["gemini-3.5-flash"], 0.86),
|
|
1507
|
+
match(["claude-opus-5"], 0.84),
|
|
1508
|
+
match(["claude-opus-4.8"], 0.82)
|
|
1509
|
+
);
|
|
1510
|
+
}
|
|
1511
|
+
if (agentDomain === "retail") {
|
|
1512
|
+
if (agentRisk === "policy_exception") {
|
|
1513
|
+
return Math.max(
|
|
1514
|
+
base,
|
|
1515
|
+
match(["gpt-4.1"], 1),
|
|
1516
|
+
match(["claude-sonnet-5"], 0.9),
|
|
1517
|
+
match(["deepseek-v4-pro"], 0.82),
|
|
1518
|
+
match(["gpt-5-mini"], 0.8),
|
|
1519
|
+
match(["gpt-4o-mini"], 0.76)
|
|
1520
|
+
);
|
|
1521
|
+
}
|
|
1522
|
+
if (agentRisk === "policy_exception_simple") {
|
|
1523
|
+
return Math.max(
|
|
1524
|
+
base,
|
|
1525
|
+
match(["gpt-5-mini"], 1),
|
|
1526
|
+
match(["gpt-4.1"], 0.86),
|
|
1527
|
+
match(["deepseek-v4-pro"], 0.82),
|
|
1528
|
+
match(["gpt-4o-mini"], 0.8)
|
|
1529
|
+
);
|
|
1530
|
+
}
|
|
1531
|
+
return Math.max(
|
|
1532
|
+
base,
|
|
1533
|
+
match(["deepseek-v4-pro"], 1),
|
|
1534
|
+
match(["claude-sonnet-5"], 0.88),
|
|
1535
|
+
match(["claude-opus-4.8"], 0.84),
|
|
1536
|
+
match(["gpt-5-mini"], 0.78),
|
|
1537
|
+
match(["gemini-3.5-flash"], 0.76)
|
|
1538
|
+
);
|
|
1539
|
+
}
|
|
1540
|
+
if (agentDomain === "airline") {
|
|
1541
|
+
return agentRisk === "complex_high" ? Math.max(
|
|
1542
|
+
base,
|
|
1543
|
+
match(["claude-sonnet-5"], 1),
|
|
1544
|
+
match(["gpt-5-mini"], 0.78),
|
|
1545
|
+
match(["claude-opus-4.8"], 0.76),
|
|
1546
|
+
match(["gemini-3.5-flash"], 0.74)
|
|
1547
|
+
) : Math.max(
|
|
1548
|
+
base,
|
|
1549
|
+
match(["gpt-5-mini"], 1),
|
|
1550
|
+
match(["claude-sonnet-5"], 0.9),
|
|
1551
|
+
match(["gemini-3.5-flash"], 0.8)
|
|
1552
|
+
);
|
|
1553
|
+
}
|
|
1554
|
+
return Math.max(
|
|
1555
|
+
base,
|
|
1556
|
+
match(["claude-opus-4.8"], 1),
|
|
1557
|
+
match(["claude-sonnet-5"], 0.84),
|
|
1558
|
+
match(["grok-4.5"], 0.82),
|
|
1559
|
+
match(["gemini-3.5-flash"], 0.8),
|
|
1560
|
+
match(["deepseek-v4-pro"], 0.78)
|
|
1561
|
+
);
|
|
1562
|
+
case "code_edit":
|
|
1563
|
+
case "debug":
|
|
1564
|
+
return Math.max(
|
|
1565
|
+
base,
|
|
1566
|
+
match(["gpt-5.3-codex"], 1),
|
|
1567
|
+
match(["claude-sonnet-4.6"], 0.94),
|
|
1568
|
+
match(["glm-5.2"], 0.9),
|
|
1569
|
+
match(["kimi-k2.7", "deepseek-v4-pro"], 0.86)
|
|
1570
|
+
);
|
|
1571
|
+
case "reasoning":
|
|
1572
|
+
return Math.max(
|
|
1573
|
+
base,
|
|
1574
|
+
match(["claude-sonnet-5", "claude-sonnet-4.6"], 0.98),
|
|
1575
|
+
match(["deepseek-v4-pro"], 0.95),
|
|
1576
|
+
match(["grok-4.5"], 0.94),
|
|
1577
|
+
match(["gemini-3.1-pro", "gemini-3.5-flash"], 0.92)
|
|
1578
|
+
);
|
|
1579
|
+
case "reasoning_mcq":
|
|
1580
|
+
return Math.max(
|
|
1581
|
+
base,
|
|
1582
|
+
match(["gemini-3-flash-preview"], 1),
|
|
1583
|
+
match(["gemini-3.5-flash"], 0.91),
|
|
1584
|
+
match(["grok-4.5"], 0.9),
|
|
1585
|
+
match(["claude-sonnet-5"], 0.88),
|
|
1586
|
+
match(["deepseek-v4-pro"], 0.84)
|
|
1587
|
+
);
|
|
1588
|
+
case "reasoning_math":
|
|
1589
|
+
return Math.max(
|
|
1590
|
+
base,
|
|
1591
|
+
match(["gemini-3.5-flash"], 1),
|
|
1592
|
+
match(["grok-4.5"], 0.93),
|
|
1593
|
+
match(["claude-sonnet-5", "deepseek-v4-pro", "kimi-k3"], 0.9),
|
|
1594
|
+
match(["kimi-k2.7"], 0.84)
|
|
1595
|
+
);
|
|
1596
|
+
case "vision":
|
|
1597
|
+
return Math.max(
|
|
1598
|
+
base,
|
|
1599
|
+
match(["gemini-3.1-pro"], 0.96),
|
|
1600
|
+
match(["qwen3.7-max", "claude-sonnet-4.6", "kimi-k2.7", "grok-4.3"], 0.9)
|
|
1601
|
+
);
|
|
1602
|
+
case "long_context":
|
|
1603
|
+
return Math.max(
|
|
1604
|
+
base,
|
|
1605
|
+
match(["gemini-3.1-pro"], 1),
|
|
1606
|
+
match(["qwen3.7-max", "glm-5.2"], 0.89),
|
|
1607
|
+
match(["gemini-3.5-flash"], 0.88),
|
|
1608
|
+
match(["deepseek-v4-pro"], 0.85)
|
|
1609
|
+
);
|
|
1610
|
+
case "extraction": {
|
|
1611
|
+
const kimiExtractionAffinity = language === "zh" ? 1 : 0.9;
|
|
1612
|
+
return Math.max(
|
|
1613
|
+
base,
|
|
1614
|
+
match(["gemini-3.5-flash", "gemini-2.5-flash", "gpt-4o-mini"], 0.9),
|
|
1615
|
+
match(["claude-sonnet-5", "claude-sonnet-4.6"], 0.9),
|
|
1616
|
+
match(["kimi-k3", "kimi-k2.7"], kimiExtractionAffinity)
|
|
1617
|
+
);
|
|
1618
|
+
}
|
|
1619
|
+
default:
|
|
1620
|
+
return Math.max(
|
|
1621
|
+
base,
|
|
1622
|
+
match(["gemini-3.5-flash", "gemini-2.5-flash", "kimi-k3", "kimi-k2.7"], 0.86)
|
|
1623
|
+
);
|
|
1624
|
+
}
|
|
1625
|
+
}
|
|
1626
|
+
function evidenceCandidates(task) {
|
|
1627
|
+
if (task === "code_agent") {
|
|
1628
|
+
return [
|
|
1629
|
+
"openai/gpt-5.3-codex",
|
|
1630
|
+
"anthropic/claude-sonnet-5",
|
|
1631
|
+
"openai/gpt-5-mini",
|
|
1632
|
+
"google/gemini-3.5-flash",
|
|
1633
|
+
"moonshot/kimi-k3",
|
|
1634
|
+
"deepseek/deepseek-v4-pro"
|
|
1635
|
+
];
|
|
1636
|
+
}
|
|
1637
|
+
if (task === "tool_agent") {
|
|
1638
|
+
return [
|
|
1639
|
+
"anthropic/claude-sonnet-5",
|
|
1640
|
+
"anthropic/claude-opus-5",
|
|
1641
|
+
"openai/gpt-5-mini",
|
|
1642
|
+
"openai/gpt-4.1",
|
|
1643
|
+
"openai/gpt-4o-mini",
|
|
1644
|
+
"google/gemini-3.5-flash",
|
|
1645
|
+
"openai/gpt-5.3-codex",
|
|
1646
|
+
"moonshot/kimi-k3",
|
|
1647
|
+
"deepseek/deepseek-v4-pro"
|
|
1648
|
+
];
|
|
1649
|
+
}
|
|
1650
|
+
if (task === "tool_agent_parallel") {
|
|
1651
|
+
return [
|
|
1652
|
+
"anthropic/claude-opus-5",
|
|
1653
|
+
"anthropic/claude-opus-4.8",
|
|
1654
|
+
"anthropic/claude-sonnet-5",
|
|
1655
|
+
"openai/gpt-5-mini",
|
|
1656
|
+
"openai/gpt-4.1",
|
|
1657
|
+
"openai/gpt-4o-mini",
|
|
1658
|
+
"xai/grok-4.5",
|
|
1659
|
+
"google/gemini-3.5-flash",
|
|
1660
|
+
"deepseek/deepseek-v4-pro"
|
|
1661
|
+
];
|
|
1662
|
+
}
|
|
1663
|
+
if (task === "long_context") {
|
|
1664
|
+
return [
|
|
1665
|
+
"google/gemini-3.1-pro",
|
|
1666
|
+
"deepseek/deepseek-v4-pro",
|
|
1667
|
+
"qwen/qwen3.7-max",
|
|
1668
|
+
"zai/glm-5.2",
|
|
1669
|
+
"google/gemini-3.5-flash"
|
|
1670
|
+
];
|
|
1671
|
+
}
|
|
1672
|
+
if (task === "reasoning_mcq") {
|
|
1673
|
+
return [
|
|
1674
|
+
"google/gemini-3-flash-preview",
|
|
1675
|
+
"google/gemini-3.5-flash",
|
|
1676
|
+
"xai/grok-4.5",
|
|
1677
|
+
"anthropic/claude-sonnet-5",
|
|
1678
|
+
"deepseek/deepseek-v4-pro"
|
|
1679
|
+
];
|
|
1680
|
+
}
|
|
1681
|
+
if (task === "reasoning_math") {
|
|
1682
|
+
return [
|
|
1683
|
+
"google/gemini-3.5-flash",
|
|
1684
|
+
"xai/grok-4.5",
|
|
1685
|
+
"anthropic/claude-sonnet-5",
|
|
1686
|
+
"deepseek/deepseek-v4-pro",
|
|
1687
|
+
"moonshot/kimi-k3"
|
|
1688
|
+
];
|
|
1689
|
+
}
|
|
1690
|
+
return [];
|
|
1691
|
+
}
|
|
1692
|
+
function isEligible(modelId, features, maxOutputTokens, options) {
|
|
1693
|
+
const model = options.modelCapabilities?.[modelId] ?? DEFAULT_MODEL_CAPABILITIES[modelId];
|
|
1694
|
+
if (!model) return true;
|
|
1695
|
+
if (features.needsTools && !model.supportsTools) return false;
|
|
1696
|
+
if (features.needsVision && !model.supportsVision) return false;
|
|
1697
|
+
if (features.needsStructuredOutput && !model.supportsTools) return false;
|
|
1698
|
+
if (model.maxOutputTokens < maxOutputTokens) return false;
|
|
1699
|
+
return model.contextWindow >= (features.estimatedInputTokens + maxOutputTokens) * 1.1;
|
|
1700
|
+
}
|
|
1701
|
+
function estimatedCost(modelId, options, inputTokens, outputTokens) {
|
|
1702
|
+
const price = options.modelPricing.get(modelId);
|
|
1703
|
+
if (!price) return Number.POSITIVE_INFINITY;
|
|
1704
|
+
if (price.flatPrice !== void 0) return price.flatPrice;
|
|
1705
|
+
return (inputTokens * price.inputPrice + outputTokens * price.outputPrice) / 1e6;
|
|
1706
|
+
}
|
|
1707
|
+
function profileScore(modelId, options, now) {
|
|
1708
|
+
const profile = options.modelPerformance?.[modelId] ?? LIVE_MODEL_PROFILES[modelId] ?? HISTORICAL_MODEL_PROFILES[modelId];
|
|
1709
|
+
if (!profile) return void 0;
|
|
1710
|
+
const measuredAt = Date.parse(profile.measuredAt);
|
|
1711
|
+
if (!Number.isFinite(measuredAt)) return void 0;
|
|
1712
|
+
const ageDays = Math.max(0, (now.getTime() - measuredAt) / 864e5);
|
|
1713
|
+
const sampleConfidence = profile.samples === void 0 ? 1 : Math.min(1, Math.max(0, profile.samples) / 10);
|
|
1714
|
+
const freshness = Math.pow(0.5, ageDays / 30) * sampleConfidence;
|
|
1715
|
+
const quality = profile.intelligenceIndex === void 0 ? void 0 : Math.min(1, profile.intelligenceIndex / 50);
|
|
1716
|
+
const speed = Math.min(
|
|
1717
|
+
1,
|
|
1718
|
+
(2e3 / Math.max(500, profile.latencyMs) + profile.outputTokensPerSecond / 250) / 2
|
|
1719
|
+
);
|
|
1720
|
+
const tailSpeed = Math.min(1, 3e3 / Math.max(750, profile.p95LatencyMs ?? profile.latencyMs));
|
|
1721
|
+
const reliability = Math.max(0, 1 - (profile.errorRate ?? 0));
|
|
1722
|
+
return { quality, speed, tailSpeed, reliability, freshness };
|
|
1723
|
+
}
|
|
1724
|
+
var PortfolioStrategy = class {
|
|
1725
|
+
name = "portfolio";
|
|
1726
|
+
route(prompt, systemPrompt, maxOutputTokens, options) {
|
|
1727
|
+
const features = classifyTask(prompt, systemPrompt, options);
|
|
1728
|
+
const base = new RulesStrategy().route(prompt, systemPrompt, maxOutputTokens, {
|
|
1729
|
+
...options,
|
|
1730
|
+
requiresTools: features.needsTools
|
|
1731
|
+
});
|
|
1732
|
+
const tierConfigs = base.tierConfigs;
|
|
1733
|
+
if (!tierConfigs) return base;
|
|
1734
|
+
const targetTier = (features.taskType === "reasoning_mcq" || features.taskType === "reasoning_math") && (base.tier === "SIMPLE" || base.tier === "MEDIUM") ? "REASONING" : base.tier;
|
|
1735
|
+
const tierConfig = tierConfigs[targetTier];
|
|
1736
|
+
const configuredCandidates = tierConfig ? getFallbackChain(targetTier, tierConfigs) : [];
|
|
1737
|
+
const chain = [
|
|
1738
|
+
.../* @__PURE__ */ new Set([...configuredCandidates, ...evidenceCandidates(features.taskType)])
|
|
1739
|
+
].filter((model2) => typeof model2 === "string" && model2.length > 0);
|
|
1740
|
+
const eligible = chain.filter(
|
|
1741
|
+
(model2) => isEligible(model2, features, maxOutputTokens, options)
|
|
1742
|
+
);
|
|
1743
|
+
const eligibleCandidates = eligible.length > 0 ? eligible : chain;
|
|
1744
|
+
if (eligibleCandidates.length === 0) return base;
|
|
1745
|
+
const profileName = options.routingProfile === "eco" ? "eco" : options.routingProfile === "premium" ? "premium" : "auto";
|
|
1746
|
+
const portfolio = options.config.portfolio ?? DEFAULT_PORTFOLIO_WEIGHTS;
|
|
1747
|
+
const getAffinity = (model2) => affinity(
|
|
1748
|
+
model2,
|
|
1749
|
+
features.taskType,
|
|
1750
|
+
features.language,
|
|
1751
|
+
features.agentDomain,
|
|
1752
|
+
features.deepWebResearch,
|
|
1753
|
+
features.agentRisk,
|
|
1754
|
+
features.terminalToolSignal,
|
|
1755
|
+
features.terminalSafetySensitive
|
|
1756
|
+
);
|
|
1757
|
+
const bestAffinity = Math.max(...eligibleCandidates.map(getAffinity));
|
|
1758
|
+
const specificAffinity = eligibleCandidates.filter((model2) => getAffinity(model2) > 0.68);
|
|
1759
|
+
const affinityPool = specificAffinity.length > 0 ? specificAffinity : [eligibleCandidates[0]];
|
|
1760
|
+
const affinityFloorGap = features.terminalToolSignal ? Math.max(
|
|
1761
|
+
portfolio.affinityFloorGap[profileName],
|
|
1762
|
+
features.terminalSafetySensitive ? 0.15 : 0.12
|
|
1763
|
+
) : portfolio.affinityFloorGap[profileName];
|
|
1764
|
+
const candidates = affinityPool.filter(
|
|
1765
|
+
(model2) => getAffinity(model2) >= bestAffinity - affinityFloorGap
|
|
1766
|
+
);
|
|
1767
|
+
const costs = candidates.map(
|
|
1768
|
+
(model2) => estimatedCost(model2, options, features.estimatedInputTokens, maxOutputTokens)
|
|
1769
|
+
);
|
|
1770
|
+
const finiteCosts = costs.filter(Number.isFinite);
|
|
1771
|
+
const minCost = finiteCosts.length > 0 ? Math.min(...finiteCosts) : 0;
|
|
1772
|
+
const maxCost = finiteCosts.length > 0 ? Math.max(...finiteCosts) : 1;
|
|
1773
|
+
const now = options.now ?? /* @__PURE__ */ new Date();
|
|
1774
|
+
const profileWeights = portfolio[profileName];
|
|
1775
|
+
const rankedEntries = candidates.map((model2, index) => {
|
|
1776
|
+
const cost = estimatedCost(model2, options, features.estimatedInputTokens, maxOutputTokens);
|
|
1777
|
+
const costScore = Number.isFinite(cost) && maxCost > minCost ? 1 - (cost - minCost) / (maxCost - minCost) : 0.5;
|
|
1778
|
+
const capabilityScore = isEligible(model2, features, maxOutputTokens, options) ? 1 : 0;
|
|
1779
|
+
const profile = profileScore(model2, options, now);
|
|
1780
|
+
const observedQuality = profile?.quality === void 0 ? getAffinity(model2) : getAffinity(model2) * (1 - profile.freshness) + profile.quality * profile.freshness;
|
|
1781
|
+
const observedSpeed = profile ? profile.speed * profile.freshness : 0.5;
|
|
1782
|
+
const observedTailSpeed = profile ? profile.tailSpeed * profile.freshness : 0.5;
|
|
1783
|
+
const observedReliability = profile ? profile.reliability * profile.freshness + (1 - profile.freshness) : 1;
|
|
1784
|
+
const legacyScore = 1 - index / Math.max(1, candidates.length - 1);
|
|
1785
|
+
const qualityWeight = profileWeights.quality + (features.highStakes ? portfolio.highStakesBoost.quality : 0);
|
|
1786
|
+
const speedScore = features.latencySensitive ? observedTailSpeed : observedSpeed;
|
|
1787
|
+
const speedWeight = profileWeights.speed + (features.latencySensitive ? portfolio.latencySensitiveSpeedBoost : 0);
|
|
1788
|
+
const reliabilityWeight = profileWeights.reliability + (features.highStakes ? portfolio.highStakesBoost.reliability : 0);
|
|
1789
|
+
const score = observedQuality * qualityWeight + capabilityScore * profileWeights.capability + costScore * profileWeights.cost + speedScore * speedWeight + observedReliability * reliabilityWeight + legacyScore * profileWeights.legacy;
|
|
1790
|
+
return {
|
|
1791
|
+
model: model2,
|
|
1792
|
+
score,
|
|
1793
|
+
quality: observedQuality,
|
|
1794
|
+
cost: costScore,
|
|
1795
|
+
speed: speedScore,
|
|
1796
|
+
reliability: observedReliability
|
|
1797
|
+
};
|
|
1798
|
+
}).sort((a, b) => b.score - a.score);
|
|
1799
|
+
const scoredModels = rankedEntries.map((item) => item.model);
|
|
1800
|
+
const webResearchFallbackOrder = [
|
|
1801
|
+
"anthropic/claude-sonnet-5",
|
|
1802
|
+
"openai/gpt-5-mini",
|
|
1803
|
+
"google/gemini-3.5-flash",
|
|
1804
|
+
"anthropic/claude-opus-5",
|
|
1805
|
+
"anthropic/claude-opus-4.8",
|
|
1806
|
+
"openai/gpt-5.3-codex"
|
|
1807
|
+
];
|
|
1808
|
+
const ranked = features.agentDomain === "web_research" ? [
|
|
1809
|
+
...scoredModels,
|
|
1810
|
+
...webResearchFallbackOrder.filter(
|
|
1811
|
+
(model2) => eligibleCandidates.includes(model2) && !scoredModels.includes(model2)
|
|
1812
|
+
),
|
|
1813
|
+
...eligibleCandidates.filter(
|
|
1814
|
+
(model2) => !scoredModels.includes(model2) && !webResearchFallbackOrder.includes(model2)
|
|
1815
|
+
)
|
|
1816
|
+
] : features.taskType === "tool_agent" || features.taskType === "tool_agent_parallel" && features.agentDomain !== "other" ? [
|
|
1817
|
+
...scoredModels,
|
|
1818
|
+
...eligibleCandidates.filter((model2) => !scoredModels.includes(model2))
|
|
1819
|
+
] : [
|
|
1820
|
+
...scoredModels,
|
|
1821
|
+
...eligibleCandidates.filter((model2) => !scoredModels.includes(model2))
|
|
1822
|
+
];
|
|
1823
|
+
const model = ranked[0] ?? base.model;
|
|
1824
|
+
const selectedTierConfigs = {
|
|
1825
|
+
...tierConfigs,
|
|
1826
|
+
[targetTier]: { primary: model, fallback: ranked.slice(1) }
|
|
1827
|
+
};
|
|
1828
|
+
const decision = selectModel(
|
|
1829
|
+
targetTier,
|
|
1830
|
+
base.confidence,
|
|
1831
|
+
"portfolio",
|
|
1832
|
+
`${base.reasoning} | v3 task=${features.taskType} agentRisk=${features.agentRisk} deepWebResearch=${features.deepWebResearch} terminalCode=${features.implicitTerminalCode} terminalSafety=${features.terminalSafetySensitive} candidates=${ranked.length}`,
|
|
1833
|
+
selectedTierConfigs,
|
|
1834
|
+
options.modelPricing,
|
|
1835
|
+
features.estimatedInputTokens,
|
|
1836
|
+
maxOutputTokens,
|
|
1837
|
+
options.routingProfile,
|
|
1838
|
+
base.agenticScore
|
|
1839
|
+
);
|
|
1840
|
+
return {
|
|
1841
|
+
...decision,
|
|
1842
|
+
tierConfigs: selectedTierConfigs,
|
|
1843
|
+
profile: base.profile,
|
|
1844
|
+
candidates: ranked,
|
|
1845
|
+
candidateScores: rankedEntries.map(({ model: model2, score, quality, cost, speed, reliability }) => ({
|
|
1846
|
+
model: model2,
|
|
1847
|
+
score,
|
|
1848
|
+
quality,
|
|
1849
|
+
cost,
|
|
1850
|
+
speed,
|
|
1851
|
+
reliability
|
|
1852
|
+
})),
|
|
1853
|
+
taskType: features.taskType,
|
|
1854
|
+
routerVersion: "v3-portfolio"
|
|
1855
|
+
};
|
|
1856
|
+
}
|
|
1857
|
+
};
|
|
1858
|
+
var DEFAULT_ROUTING_CONFIG = {
|
|
1859
|
+
version: "3.4",
|
|
1860
|
+
strategy: "portfolio",
|
|
1861
|
+
portfolio: {
|
|
1862
|
+
auto: {
|
|
1863
|
+
quality: 0.47,
|
|
1864
|
+
capability: 0.2,
|
|
1865
|
+
cost: 0.18,
|
|
1866
|
+
speed: 0.07,
|
|
1867
|
+
reliability: 0.03,
|
|
1868
|
+
legacy: 0.05
|
|
1869
|
+
},
|
|
1870
|
+
eco: {
|
|
1871
|
+
quality: 0.36,
|
|
1872
|
+
capability: 0.2,
|
|
1873
|
+
cost: 0.28,
|
|
1874
|
+
speed: 0.1,
|
|
1875
|
+
reliability: 0.04,
|
|
1876
|
+
legacy: 0.02
|
|
1877
|
+
},
|
|
1878
|
+
premium: {
|
|
1879
|
+
quality: 0.58,
|
|
1880
|
+
capability: 0.2,
|
|
1881
|
+
cost: 0.08,
|
|
1882
|
+
speed: 0.06,
|
|
1883
|
+
reliability: 0.06,
|
|
1884
|
+
legacy: 0.02
|
|
1885
|
+
},
|
|
1886
|
+
highStakesBoost: { quality: 0.08, reliability: 0.05 },
|
|
1887
|
+
latencySensitiveSpeedBoost: 0.08,
|
|
1888
|
+
affinityFloorGap: { auto: 0.1, eco: 0.22, premium: 0.05 }
|
|
1889
|
+
},
|
|
1890
|
+
classifier: {
|
|
1891
|
+
llmModel: "google/gemini-2.5-flash",
|
|
1892
|
+
llmMaxTokens: 10,
|
|
1893
|
+
llmTemperature: 0,
|
|
1894
|
+
promptTruncationChars: 500,
|
|
1895
|
+
cacheTtlMs: 36e5
|
|
1896
|
+
// 1 hour
|
|
1897
|
+
},
|
|
1898
|
+
scoring: {
|
|
1899
|
+
tokenCountThresholds: { simple: 50, complex: 500 },
|
|
1900
|
+
// Multilingual keywords: EN + ZH + JA + RU + DE + ES + PT + KO + AR
|
|
1901
|
+
codeKeywords: [
|
|
1902
|
+
// English
|
|
1903
|
+
"function",
|
|
1904
|
+
"class",
|
|
1905
|
+
"import",
|
|
1906
|
+
"def",
|
|
1907
|
+
"SELECT",
|
|
1908
|
+
"async",
|
|
1909
|
+
"await",
|
|
1910
|
+
"const",
|
|
1911
|
+
"let",
|
|
1912
|
+
"var",
|
|
1913
|
+
"return",
|
|
1914
|
+
"```",
|
|
1915
|
+
// Chinese
|
|
1916
|
+
"\u51FD\u6570",
|
|
1917
|
+
"\u7C7B",
|
|
1918
|
+
"\u5BFC\u5165",
|
|
1919
|
+
"\u5B9A\u4E49",
|
|
1920
|
+
"\u67E5\u8BE2",
|
|
1921
|
+
"\u5F02\u6B65",
|
|
1922
|
+
"\u7B49\u5F85",
|
|
1923
|
+
"\u5E38\u91CF",
|
|
1924
|
+
"\u53D8\u91CF",
|
|
1925
|
+
"\u8FD4\u56DE",
|
|
1926
|
+
// Japanese
|
|
1927
|
+
"\u95A2\u6570",
|
|
1928
|
+
"\u30AF\u30E9\u30B9",
|
|
1929
|
+
"\u30A4\u30F3\u30DD\u30FC\u30C8",
|
|
1930
|
+
"\u975E\u540C\u671F",
|
|
1931
|
+
"\u5B9A\u6570",
|
|
1932
|
+
"\u5909\u6570",
|
|
1933
|
+
// Russian
|
|
1934
|
+
"\u0444\u0443\u043D\u043A\u0446\u0438\u044F",
|
|
1935
|
+
"\u043A\u043B\u0430\u0441\u0441",
|
|
1936
|
+
"\u0438\u043C\u043F\u043E\u0440\u0442",
|
|
1937
|
+
"\u043E\u043F\u0440\u0435\u0434\u0435\u043B",
|
|
1938
|
+
"\u0437\u0430\u043F\u0440\u043E\u0441",
|
|
1939
|
+
"\u0430\u0441\u0438\u043D\u0445\u0440\u043E\u043D\u043D\u044B\u0439",
|
|
1940
|
+
"\u043E\u0436\u0438\u0434\u0430\u0442\u044C",
|
|
1941
|
+
"\u043A\u043E\u043D\u0441\u0442\u0430\u043D\u0442\u0430",
|
|
1942
|
+
"\u043F\u0435\u0440\u0435\u043C\u0435\u043D\u043D\u0430\u044F",
|
|
1943
|
+
"\u0432\u0435\u0440\u043D\u0443\u0442\u044C",
|
|
1944
|
+
// German
|
|
1945
|
+
"funktion",
|
|
1946
|
+
"klasse",
|
|
1947
|
+
"importieren",
|
|
1948
|
+
"definieren",
|
|
1949
|
+
"abfrage",
|
|
1950
|
+
"asynchron",
|
|
1951
|
+
"erwarten",
|
|
1952
|
+
"konstante",
|
|
1953
|
+
"variable",
|
|
1954
|
+
"zur\xFCckgeben",
|
|
1955
|
+
// Spanish
|
|
1956
|
+
"funci\xF3n",
|
|
1957
|
+
"clase",
|
|
1958
|
+
"importar",
|
|
1959
|
+
"definir",
|
|
1960
|
+
"consulta",
|
|
1961
|
+
"as\xEDncrono",
|
|
1962
|
+
"esperar",
|
|
1963
|
+
"constante",
|
|
1964
|
+
"variable",
|
|
1965
|
+
"retornar",
|
|
1966
|
+
// Portuguese
|
|
1967
|
+
"fun\xE7\xE3o",
|
|
1968
|
+
"classe",
|
|
1969
|
+
"importar",
|
|
1970
|
+
"definir",
|
|
1971
|
+
"consulta",
|
|
1972
|
+
"ass\xEDncrono",
|
|
1973
|
+
"aguardar",
|
|
1974
|
+
"constante",
|
|
1975
|
+
"vari\xE1vel",
|
|
1976
|
+
"retornar",
|
|
1977
|
+
// Korean
|
|
1978
|
+
"\uD568\uC218",
|
|
1979
|
+
"\uD074\uB798\uC2A4",
|
|
1980
|
+
"\uAC00\uC838\uC624\uAE30",
|
|
1981
|
+
"\uC815\uC758",
|
|
1982
|
+
"\uCFFC\uB9AC",
|
|
1983
|
+
"\uBE44\uB3D9\uAE30",
|
|
1984
|
+
"\uB300\uAE30",
|
|
1985
|
+
"\uC0C1\uC218",
|
|
1986
|
+
"\uBCC0\uC218",
|
|
1987
|
+
"\uBC18\uD658",
|
|
1988
|
+
// Arabic
|
|
1989
|
+
"\u062F\u0627\u0644\u0629",
|
|
1990
|
+
"\u0641\u0626\u0629",
|
|
1991
|
+
"\u0627\u0633\u062A\u064A\u0631\u0627\u062F",
|
|
1992
|
+
"\u062A\u0639\u0631\u064A\u0641",
|
|
1993
|
+
"\u0627\u0633\u062A\u0639\u0644\u0627\u0645",
|
|
1994
|
+
"\u063A\u064A\u0631 \u0645\u062A\u0632\u0627\u0645\u0646",
|
|
1995
|
+
"\u0627\u0646\u062A\u0638\u0627\u0631",
|
|
1996
|
+
"\u062B\u0627\u0628\u062A",
|
|
1997
|
+
"\u0645\u062A\u063A\u064A\u0631",
|
|
1998
|
+
"\u0625\u0631\u062C\u0627\u0639"
|
|
1999
|
+
],
|
|
2000
|
+
reasoningKeywords: [
|
|
2001
|
+
// English
|
|
2002
|
+
"prove",
|
|
2003
|
+
"theorem",
|
|
2004
|
+
"derive",
|
|
2005
|
+
"step by step",
|
|
2006
|
+
"chain of thought",
|
|
2007
|
+
"formally",
|
|
2008
|
+
"mathematical",
|
|
2009
|
+
"proof",
|
|
2010
|
+
"logically",
|
|
2011
|
+
// Chinese
|
|
2012
|
+
"\u8BC1\u660E",
|
|
2013
|
+
"\u5B9A\u7406",
|
|
2014
|
+
"\u63A8\u5BFC",
|
|
2015
|
+
"\u9010\u6B65",
|
|
2016
|
+
"\u601D\u7EF4\u94FE",
|
|
2017
|
+
"\u5F62\u5F0F\u5316",
|
|
2018
|
+
"\u6570\u5B66",
|
|
2019
|
+
"\u903B\u8F91",
|
|
2020
|
+
// Japanese
|
|
2021
|
+
"\u8A3C\u660E",
|
|
2022
|
+
"\u5B9A\u7406",
|
|
2023
|
+
"\u5C0E\u51FA",
|
|
2024
|
+
"\u30B9\u30C6\u30C3\u30D7\u30D0\u30A4\u30B9\u30C6\u30C3\u30D7",
|
|
2025
|
+
"\u8AD6\u7406\u7684",
|
|
2026
|
+
// Russian
|
|
2027
|
+
"\u0434\u043E\u043A\u0430\u0437\u0430\u0442\u044C",
|
|
2028
|
+
"\u0434\u043E\u043A\u0430\u0436\u0438",
|
|
2029
|
+
"\u0434\u043E\u043A\u0430\u0437\u0430\u0442\u0435\u043B\u044C\u0441\u0442\u0432",
|
|
2030
|
+
"\u0442\u0435\u043E\u0440\u0435\u043C\u0430",
|
|
2031
|
+
"\u0432\u044B\u0432\u0435\u0441\u0442\u0438",
|
|
2032
|
+
"\u0448\u0430\u0433 \u0437\u0430 \u0448\u0430\u0433\u043E\u043C",
|
|
2033
|
+
"\u043F\u043E\u0448\u0430\u0433\u043E\u0432\u043E",
|
|
2034
|
+
"\u043F\u043E\u044D\u0442\u0430\u043F\u043D\u043E",
|
|
2035
|
+
"\u0446\u0435\u043F\u043E\u0447\u043A\u0430 \u0440\u0430\u0441\u0441\u0443\u0436\u0434\u0435\u043D\u0438\u0439",
|
|
2036
|
+
"\u0440\u0430\u0441\u0441\u0443\u0436\u0434\u0435\u043D\u0438",
|
|
2037
|
+
"\u0444\u043E\u0440\u043C\u0430\u043B\u044C\u043D\u043E",
|
|
2038
|
+
"\u043C\u0430\u0442\u0435\u043C\u0430\u0442\u0438\u0447\u0435\u0441\u043A\u0438",
|
|
2039
|
+
"\u043B\u043E\u0433\u0438\u0447\u0435\u0441\u043A\u0438",
|
|
2040
|
+
// German
|
|
2041
|
+
"beweisen",
|
|
2042
|
+
"beweis",
|
|
2043
|
+
"theorem",
|
|
2044
|
+
"ableiten",
|
|
2045
|
+
"schritt f\xFCr schritt",
|
|
2046
|
+
"gedankenkette",
|
|
2047
|
+
"formal",
|
|
2048
|
+
"mathematisch",
|
|
2049
|
+
"logisch",
|
|
2050
|
+
// Spanish
|
|
2051
|
+
"demostrar",
|
|
2052
|
+
"teorema",
|
|
2053
|
+
"derivar",
|
|
2054
|
+
"paso a paso",
|
|
2055
|
+
"cadena de pensamiento",
|
|
2056
|
+
"formalmente",
|
|
2057
|
+
"matem\xE1tico",
|
|
2058
|
+
"prueba",
|
|
2059
|
+
"l\xF3gicamente",
|
|
2060
|
+
// Portuguese
|
|
2061
|
+
"provar",
|
|
2062
|
+
"teorema",
|
|
2063
|
+
"derivar",
|
|
2064
|
+
"passo a passo",
|
|
2065
|
+
"cadeia de pensamento",
|
|
2066
|
+
"formalmente",
|
|
2067
|
+
"matem\xE1tico",
|
|
2068
|
+
"prova",
|
|
2069
|
+
"logicamente",
|
|
2070
|
+
// Korean
|
|
2071
|
+
"\uC99D\uBA85",
|
|
2072
|
+
"\uC815\uB9AC",
|
|
2073
|
+
"\uB3C4\uCD9C",
|
|
2074
|
+
"\uB2E8\uACC4\uBCC4",
|
|
2075
|
+
"\uC0AC\uACE0\uC758 \uC5F0\uC1C4",
|
|
2076
|
+
"\uD615\uC2DD\uC801",
|
|
2077
|
+
"\uC218\uD559\uC801",
|
|
2078
|
+
"\uB17C\uB9AC\uC801",
|
|
2079
|
+
// Arabic
|
|
2080
|
+
"\u0625\u062B\u0628\u0627\u062A",
|
|
2081
|
+
"\u0646\u0638\u0631\u064A\u0629",
|
|
2082
|
+
"\u0627\u0634\u062A\u0642\u0627\u0642",
|
|
2083
|
+
"\u062E\u0637\u0648\u0629 \u0628\u062E\u0637\u0648\u0629",
|
|
2084
|
+
"\u0633\u0644\u0633\u0644\u0629 \u0627\u0644\u062A\u0641\u0643\u064A\u0631",
|
|
2085
|
+
"\u0631\u0633\u0645\u064A\u0627\u064B",
|
|
2086
|
+
"\u0631\u064A\u0627\u0636\u064A",
|
|
2087
|
+
"\u0628\u0631\u0647\u0627\u0646",
|
|
2088
|
+
"\u0645\u0646\u0637\u0642\u064A\u0627\u064B"
|
|
2089
|
+
],
|
|
2090
|
+
simpleKeywords: [
|
|
2091
|
+
// English
|
|
2092
|
+
"what is",
|
|
2093
|
+
"define",
|
|
2094
|
+
"translate",
|
|
2095
|
+
"hello",
|
|
2096
|
+
"yes or no",
|
|
2097
|
+
"capital of",
|
|
2098
|
+
"how old",
|
|
2099
|
+
"who is",
|
|
2100
|
+
"when was",
|
|
2101
|
+
// Chinese
|
|
2102
|
+
"\u4EC0\u4E48\u662F",
|
|
2103
|
+
"\u5B9A\u4E49",
|
|
2104
|
+
"\u7FFB\u8BD1",
|
|
2105
|
+
"\u4F60\u597D",
|
|
2106
|
+
"\u662F\u5426",
|
|
2107
|
+
"\u9996\u90FD",
|
|
2108
|
+
"\u591A\u5927",
|
|
2109
|
+
"\u8C01\u662F",
|
|
2110
|
+
"\u4F55\u65F6",
|
|
2111
|
+
// Japanese
|
|
2112
|
+
"\u3068\u306F",
|
|
2113
|
+
"\u5B9A\u7FA9",
|
|
2114
|
+
"\u7FFB\u8A33",
|
|
2115
|
+
"\u3053\u3093\u306B\u3061\u306F",
|
|
2116
|
+
"\u306F\u3044\u304B\u3044\u3044\u3048",
|
|
2117
|
+
"\u9996\u90FD",
|
|
2118
|
+
"\u8AB0",
|
|
2119
|
+
// Russian
|
|
2120
|
+
"\u0447\u0442\u043E \u0442\u0430\u043A\u043E\u0435",
|
|
2121
|
+
"\u043E\u043F\u0440\u0435\u0434\u0435\u043B\u0435\u043D\u0438\u0435",
|
|
2122
|
+
"\u043F\u0435\u0440\u0435\u0432\u0435\u0441\u0442\u0438",
|
|
2123
|
+
"\u043F\u0435\u0440\u0435\u0432\u0435\u0434\u0438",
|
|
2124
|
+
"\u043F\u0440\u0438\u0432\u0435\u0442",
|
|
2125
|
+
"\u0434\u0430 \u0438\u043B\u0438 \u043D\u0435\u0442",
|
|
2126
|
+
"\u0441\u0442\u043E\u043B\u0438\u0446\u0430",
|
|
2127
|
+
"\u0441\u043A\u043E\u043B\u044C\u043A\u043E \u043B\u0435\u0442",
|
|
2128
|
+
"\u043A\u0442\u043E \u0442\u0430\u043A\u043E\u0439",
|
|
2129
|
+
"\u043A\u043E\u0433\u0434\u0430",
|
|
2130
|
+
"\u043E\u0431\u044A\u044F\u0441\u043D\u0438",
|
|
2131
|
+
// German
|
|
2132
|
+
"was ist",
|
|
2133
|
+
"definiere",
|
|
2134
|
+
"\xFCbersetze",
|
|
2135
|
+
"hallo",
|
|
2136
|
+
"ja oder nein",
|
|
2137
|
+
"hauptstadt",
|
|
2138
|
+
"wie alt",
|
|
2139
|
+
"wer ist",
|
|
2140
|
+
"wann",
|
|
2141
|
+
"erkl\xE4re",
|
|
2142
|
+
// Spanish
|
|
2143
|
+
"qu\xE9 es",
|
|
2144
|
+
"definir",
|
|
2145
|
+
"traducir",
|
|
2146
|
+
"hola",
|
|
2147
|
+
"s\xED o no",
|
|
2148
|
+
"capital de",
|
|
2149
|
+
"cu\xE1ntos a\xF1os",
|
|
2150
|
+
"qui\xE9n es",
|
|
2151
|
+
"cu\xE1ndo",
|
|
2152
|
+
// Portuguese
|
|
2153
|
+
"o que \xE9",
|
|
2154
|
+
"definir",
|
|
2155
|
+
"traduzir",
|
|
2156
|
+
"ol\xE1",
|
|
2157
|
+
"sim ou n\xE3o",
|
|
2158
|
+
"capital de",
|
|
2159
|
+
"quantos anos",
|
|
2160
|
+
"quem \xE9",
|
|
2161
|
+
"quando",
|
|
2162
|
+
// Korean
|
|
2163
|
+
"\uBB34\uC5C7",
|
|
2164
|
+
"\uC815\uC758",
|
|
2165
|
+
"\uBC88\uC5ED",
|
|
2166
|
+
"\uC548\uB155\uD558\uC138\uC694",
|
|
2167
|
+
"\uC608 \uB610\uB294 \uC544\uB2C8\uC624",
|
|
2168
|
+
"\uC218\uB3C4",
|
|
2169
|
+
"\uB204\uAD6C",
|
|
2170
|
+
"\uC5B8\uC81C",
|
|
2171
|
+
// Arabic
|
|
2172
|
+
"\u0645\u0627 \u0647\u0648",
|
|
2173
|
+
"\u062A\u0639\u0631\u064A\u0641",
|
|
2174
|
+
"\u062A\u0631\u062C\u0645",
|
|
2175
|
+
"\u0645\u0631\u062D\u0628\u0627",
|
|
2176
|
+
"\u0646\u0639\u0645 \u0623\u0648 \u0644\u0627",
|
|
2177
|
+
"\u0639\u0627\u0635\u0645\u0629",
|
|
2178
|
+
"\u0645\u0646 \u0647\u0648",
|
|
2179
|
+
"\u0645\u062A\u0649"
|
|
2180
|
+
],
|
|
2181
|
+
technicalKeywords: [
|
|
2182
|
+
// English
|
|
2183
|
+
"algorithm",
|
|
2184
|
+
"optimize",
|
|
2185
|
+
"architecture",
|
|
2186
|
+
"distributed",
|
|
2187
|
+
"kubernetes",
|
|
2188
|
+
"microservice",
|
|
2189
|
+
"database",
|
|
2190
|
+
"infrastructure",
|
|
2191
|
+
// Chinese
|
|
2192
|
+
"\u7B97\u6CD5",
|
|
2193
|
+
"\u4F18\u5316",
|
|
2194
|
+
"\u67B6\u6784",
|
|
2195
|
+
"\u5206\u5E03\u5F0F",
|
|
2196
|
+
"\u5FAE\u670D\u52A1",
|
|
2197
|
+
"\u6570\u636E\u5E93",
|
|
2198
|
+
"\u57FA\u7840\u8BBE\u65BD",
|
|
2199
|
+
// Japanese
|
|
2200
|
+
"\u30A2\u30EB\u30B4\u30EA\u30BA\u30E0",
|
|
2201
|
+
"\u6700\u9069\u5316",
|
|
2202
|
+
"\u30A2\u30FC\u30AD\u30C6\u30AF\u30C1\u30E3",
|
|
2203
|
+
"\u5206\u6563",
|
|
2204
|
+
"\u30DE\u30A4\u30AF\u30ED\u30B5\u30FC\u30D3\u30B9",
|
|
2205
|
+
"\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9",
|
|
2206
|
+
// Russian
|
|
2207
|
+
"\u0430\u043B\u0433\u043E\u0440\u0438\u0442\u043C",
|
|
2208
|
+
"\u043E\u043F\u0442\u0438\u043C\u0438\u0437\u0438\u0440\u043E\u0432\u0430\u0442\u044C",
|
|
2209
|
+
"\u043E\u043F\u0442\u0438\u043C\u0438\u0437\u0430\u0446\u0438",
|
|
2210
|
+
"\u043E\u043F\u0442\u0438\u043C\u0438\u0437\u0438\u0440\u0443\u0439",
|
|
2211
|
+
"\u0430\u0440\u0445\u0438\u0442\u0435\u043A\u0442\u0443\u0440\u0430",
|
|
2212
|
+
"\u0440\u0430\u0441\u043F\u0440\u0435\u0434\u0435\u043B\u0451\u043D\u043D\u044B\u0439",
|
|
2213
|
+
"\u043C\u0438\u043A\u0440\u043E\u0441\u0435\u0440\u0432\u0438\u0441",
|
|
2214
|
+
"\u0431\u0430\u0437\u0430 \u0434\u0430\u043D\u043D\u044B\u0445",
|
|
2215
|
+
"\u0438\u043D\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043A\u0442\u0443\u0440\u0430",
|
|
2216
|
+
// German
|
|
2217
|
+
"algorithmus",
|
|
2218
|
+
"optimieren",
|
|
2219
|
+
"architektur",
|
|
2220
|
+
"verteilt",
|
|
2221
|
+
"kubernetes",
|
|
2222
|
+
"mikroservice",
|
|
2223
|
+
"datenbank",
|
|
2224
|
+
"infrastruktur",
|
|
2225
|
+
// Spanish
|
|
2226
|
+
"algoritmo",
|
|
2227
|
+
"optimizar",
|
|
2228
|
+
"arquitectura",
|
|
2229
|
+
"distribuido",
|
|
2230
|
+
"microservicio",
|
|
2231
|
+
"base de datos",
|
|
2232
|
+
"infraestructura",
|
|
2233
|
+
// Portuguese
|
|
2234
|
+
"algoritmo",
|
|
2235
|
+
"otimizar",
|
|
2236
|
+
"arquitetura",
|
|
2237
|
+
"distribu\xEDdo",
|
|
2238
|
+
"microsservi\xE7o",
|
|
2239
|
+
"banco de dados",
|
|
2240
|
+
"infraestrutura",
|
|
2241
|
+
// Korean
|
|
2242
|
+
"\uC54C\uACE0\uB9AC\uC998",
|
|
2243
|
+
"\uCD5C\uC801\uD654",
|
|
2244
|
+
"\uC544\uD0A4\uD14D\uCC98",
|
|
2245
|
+
"\uBD84\uC0B0",
|
|
2246
|
+
"\uB9C8\uC774\uD06C\uB85C\uC11C\uBE44\uC2A4",
|
|
2247
|
+
"\uB370\uC774\uD130\uBCA0\uC774\uC2A4",
|
|
2248
|
+
"\uC778\uD504\uB77C",
|
|
2249
|
+
// Arabic
|
|
2250
|
+
"\u062E\u0648\u0627\u0631\u0632\u0645\u064A\u0629",
|
|
2251
|
+
"\u062A\u062D\u0633\u064A\u0646",
|
|
2252
|
+
"\u0628\u0646\u064A\u0629",
|
|
2253
|
+
"\u0645\u0648\u0632\u0639",
|
|
2254
|
+
"\u062E\u062F\u0645\u0629 \u0645\u0635\u063A\u0631\u0629",
|
|
2255
|
+
"\u0642\u0627\u0639\u062F\u0629 \u0628\u064A\u0627\u0646\u0627\u062A",
|
|
2256
|
+
"\u0628\u0646\u064A\u0629 \u062A\u062D\u062A\u064A\u0629"
|
|
2257
|
+
],
|
|
2258
|
+
creativeKeywords: [
|
|
2259
|
+
// English
|
|
2260
|
+
"story",
|
|
2261
|
+
"poem",
|
|
2262
|
+
"compose",
|
|
2263
|
+
"brainstorm",
|
|
2264
|
+
"creative",
|
|
2265
|
+
"imagine",
|
|
2266
|
+
"write a",
|
|
2267
|
+
// Chinese
|
|
2268
|
+
"\u6545\u4E8B",
|
|
2269
|
+
"\u8BD7",
|
|
2270
|
+
"\u521B\u4F5C",
|
|
2271
|
+
"\u5934\u8111\u98CE\u66B4",
|
|
2272
|
+
"\u521B\u610F",
|
|
2273
|
+
"\u60F3\u8C61",
|
|
2274
|
+
"\u5199\u4E00\u4E2A",
|
|
2275
|
+
// Japanese
|
|
2276
|
+
"\u7269\u8A9E",
|
|
2277
|
+
"\u8A69",
|
|
2278
|
+
"\u4F5C\u66F2",
|
|
2279
|
+
"\u30D6\u30EC\u30A4\u30F3\u30B9\u30C8\u30FC\u30E0",
|
|
2280
|
+
"\u5275\u9020\u7684",
|
|
2281
|
+
"\u60F3\u50CF",
|
|
2282
|
+
// Russian
|
|
2283
|
+
"\u0438\u0441\u0442\u043E\u0440\u0438\u044F",
|
|
2284
|
+
"\u0440\u0430\u0441\u0441\u043A\u0430\u0437",
|
|
2285
|
+
"\u0441\u0442\u0438\u0445\u043E\u0442\u0432\u043E\u0440\u0435\u043D\u0438\u0435",
|
|
2286
|
+
"\u0441\u043E\u0447\u0438\u043D\u0438\u0442\u044C",
|
|
2287
|
+
"\u0441\u043E\u0447\u0438\u043D\u0438",
|
|
2288
|
+
"\u043C\u043E\u0437\u0433\u043E\u0432\u043E\u0439 \u0448\u0442\u0443\u0440\u043C",
|
|
2289
|
+
"\u0442\u0432\u043E\u0440\u0447\u0435\u0441\u043A\u0438\u0439",
|
|
2290
|
+
"\u043F\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u0442\u044C",
|
|
2291
|
+
"\u043F\u0440\u0438\u0434\u0443\u043C\u0430\u0439",
|
|
2292
|
+
"\u043D\u0430\u043F\u0438\u0448\u0438",
|
|
2293
|
+
// German
|
|
2294
|
+
"geschichte",
|
|
2295
|
+
"gedicht",
|
|
2296
|
+
"komponieren",
|
|
2297
|
+
"brainstorming",
|
|
2298
|
+
"kreativ",
|
|
2299
|
+
"vorstellen",
|
|
2300
|
+
"schreibe",
|
|
2301
|
+
"erz\xE4hlung",
|
|
2302
|
+
// Spanish
|
|
2303
|
+
"historia",
|
|
2304
|
+
"poema",
|
|
2305
|
+
"componer",
|
|
2306
|
+
"lluvia de ideas",
|
|
2307
|
+
"creativo",
|
|
2308
|
+
"imaginar",
|
|
2309
|
+
"escribe",
|
|
2310
|
+
// Portuguese
|
|
2311
|
+
"hist\xF3ria",
|
|
2312
|
+
"poema",
|
|
2313
|
+
"compor",
|
|
2314
|
+
"criativo",
|
|
2315
|
+
"imaginar",
|
|
2316
|
+
"escreva",
|
|
2317
|
+
// Korean
|
|
2318
|
+
"\uC774\uC57C\uAE30",
|
|
2319
|
+
"\uC2DC",
|
|
2320
|
+
"\uC791\uACE1",
|
|
2321
|
+
"\uBE0C\uB808\uC778\uC2A4\uD1A0\uBC0D",
|
|
2322
|
+
"\uCC3D\uC758\uC801",
|
|
2323
|
+
"\uC0C1\uC0C1",
|
|
2324
|
+
"\uC791\uC131",
|
|
2325
|
+
// Arabic
|
|
2326
|
+
"\u0642\u0635\u0629",
|
|
2327
|
+
"\u0642\u0635\u064A\u062F\u0629",
|
|
2328
|
+
"\u062A\u0623\u0644\u064A\u0641",
|
|
2329
|
+
"\u0639\u0635\u0641 \u0630\u0647\u0646\u064A",
|
|
2330
|
+
"\u0625\u0628\u062F\u0627\u0639\u064A",
|
|
2331
|
+
"\u062A\u062E\u064A\u0644",
|
|
2332
|
+
"\u0627\u0643\u062A\u0628"
|
|
2333
|
+
],
|
|
2334
|
+
// New dimension keyword lists (multilingual)
|
|
2335
|
+
imperativeVerbs: [
|
|
2336
|
+
// English
|
|
2337
|
+
"build",
|
|
2338
|
+
"create",
|
|
2339
|
+
"implement",
|
|
2340
|
+
"design",
|
|
2341
|
+
"develop",
|
|
2342
|
+
"construct",
|
|
2343
|
+
"generate",
|
|
2344
|
+
"deploy",
|
|
2345
|
+
"configure",
|
|
2346
|
+
"set up",
|
|
2347
|
+
// Chinese
|
|
2348
|
+
"\u6784\u5EFA",
|
|
2349
|
+
"\u521B\u5EFA",
|
|
2350
|
+
"\u5B9E\u73B0",
|
|
2351
|
+
"\u8BBE\u8BA1",
|
|
2352
|
+
"\u5F00\u53D1",
|
|
2353
|
+
"\u751F\u6210",
|
|
2354
|
+
"\u90E8\u7F72",
|
|
2355
|
+
"\u914D\u7F6E",
|
|
2356
|
+
"\u8BBE\u7F6E",
|
|
2357
|
+
// Japanese
|
|
2358
|
+
"\u69CB\u7BC9",
|
|
2359
|
+
"\u4F5C\u6210",
|
|
2360
|
+
"\u5B9F\u88C5",
|
|
2361
|
+
"\u8A2D\u8A08",
|
|
2362
|
+
"\u958B\u767A",
|
|
2363
|
+
"\u751F\u6210",
|
|
2364
|
+
"\u30C7\u30D7\u30ED\u30A4",
|
|
2365
|
+
"\u8A2D\u5B9A",
|
|
2366
|
+
// Russian
|
|
2367
|
+
"\u043F\u043E\u0441\u0442\u0440\u043E\u0438\u0442\u044C",
|
|
2368
|
+
"\u043F\u043E\u0441\u0442\u0440\u043E\u0439",
|
|
2369
|
+
"\u0441\u043E\u0437\u0434\u0430\u0442\u044C",
|
|
2370
|
+
"\u0441\u043E\u0437\u0434\u0430\u0439",
|
|
2371
|
+
"\u0440\u0435\u0430\u043B\u0438\u0437\u043E\u0432\u0430\u0442\u044C",
|
|
2372
|
+
"\u0440\u0435\u0430\u043B\u0438\u0437\u0443\u0439",
|
|
2373
|
+
"\u0441\u043F\u0440\u043E\u0435\u043A\u0442\u0438\u0440\u043E\u0432\u0430\u0442\u044C",
|
|
2374
|
+
"\u0440\u0430\u0437\u0440\u0430\u0431\u043E\u0442\u0430\u0442\u044C",
|
|
2375
|
+
"\u0440\u0430\u0437\u0440\u0430\u0431\u043E\u0442\u0430\u0439",
|
|
2376
|
+
"\u0441\u043A\u043E\u043D\u0441\u0442\u0440\u0443\u0438\u0440\u043E\u0432\u0430\u0442\u044C",
|
|
2377
|
+
"\u0441\u0433\u0435\u043D\u0435\u0440\u0438\u0440\u043E\u0432\u0430\u0442\u044C",
|
|
2378
|
+
"\u0441\u0433\u0435\u043D\u0435\u0440\u0438\u0440\u0443\u0439",
|
|
2379
|
+
"\u0440\u0430\u0437\u0432\u0435\u0440\u043D\u0443\u0442\u044C",
|
|
2380
|
+
"\u0440\u0430\u0437\u0432\u0435\u0440\u043D\u0438",
|
|
2381
|
+
"\u043D\u0430\u0441\u0442\u0440\u043E\u0438\u0442\u044C",
|
|
2382
|
+
"\u043D\u0430\u0441\u0442\u0440\u043E\u0439",
|
|
2383
|
+
// German
|
|
2384
|
+
"erstellen",
|
|
2385
|
+
"bauen",
|
|
2386
|
+
"implementieren",
|
|
2387
|
+
"entwerfen",
|
|
2388
|
+
"entwickeln",
|
|
2389
|
+
"konstruieren",
|
|
2390
|
+
"generieren",
|
|
2391
|
+
"bereitstellen",
|
|
2392
|
+
"konfigurieren",
|
|
2393
|
+
"einrichten",
|
|
2394
|
+
// Spanish
|
|
2395
|
+
"construir",
|
|
2396
|
+
"crear",
|
|
2397
|
+
"implementar",
|
|
2398
|
+
"dise\xF1ar",
|
|
2399
|
+
"desarrollar",
|
|
2400
|
+
"generar",
|
|
2401
|
+
"desplegar",
|
|
2402
|
+
"configurar",
|
|
2403
|
+
// Portuguese
|
|
2404
|
+
"construir",
|
|
2405
|
+
"criar",
|
|
2406
|
+
"implementar",
|
|
2407
|
+
"projetar",
|
|
2408
|
+
"desenvolver",
|
|
2409
|
+
"gerar",
|
|
2410
|
+
"implantar",
|
|
2411
|
+
"configurar",
|
|
2412
|
+
// Korean
|
|
2413
|
+
"\uAD6C\uCD95",
|
|
2414
|
+
"\uC0DD\uC131",
|
|
2415
|
+
"\uAD6C\uD604",
|
|
2416
|
+
"\uC124\uACC4",
|
|
2417
|
+
"\uAC1C\uBC1C",
|
|
2418
|
+
"\uBC30\uD3EC",
|
|
2419
|
+
"\uC124\uC815",
|
|
2420
|
+
// Arabic
|
|
2421
|
+
"\u0628\u0646\u0627\u0621",
|
|
2422
|
+
"\u0625\u0646\u0634\u0627\u0621",
|
|
2423
|
+
"\u062A\u0646\u0641\u064A\u0630",
|
|
2424
|
+
"\u062A\u0635\u0645\u064A\u0645",
|
|
2425
|
+
"\u062A\u0637\u0648\u064A\u0631",
|
|
2426
|
+
"\u062A\u0648\u0644\u064A\u062F",
|
|
2427
|
+
"\u0646\u0634\u0631",
|
|
2428
|
+
"\u0625\u0639\u062F\u0627\u062F"
|
|
2429
|
+
],
|
|
2430
|
+
constraintIndicators: [
|
|
2431
|
+
// English
|
|
2432
|
+
"under",
|
|
2433
|
+
"at most",
|
|
2434
|
+
"at least",
|
|
2435
|
+
"within",
|
|
2436
|
+
"no more than",
|
|
2437
|
+
"o(",
|
|
2438
|
+
"maximum",
|
|
2439
|
+
"minimum",
|
|
2440
|
+
"limit",
|
|
2441
|
+
"budget",
|
|
2442
|
+
// Chinese
|
|
2443
|
+
"\u4E0D\u8D85\u8FC7",
|
|
2444
|
+
"\u81F3\u5C11",
|
|
2445
|
+
"\u6700\u591A",
|
|
2446
|
+
"\u5728\u5185",
|
|
2447
|
+
"\u6700\u5927",
|
|
2448
|
+
"\u6700\u5C0F",
|
|
2449
|
+
"\u9650\u5236",
|
|
2450
|
+
"\u9884\u7B97",
|
|
2451
|
+
// Japanese
|
|
2452
|
+
"\u4EE5\u4E0B",
|
|
2453
|
+
"\u6700\u5927",
|
|
2454
|
+
"\u6700\u5C0F",
|
|
2455
|
+
"\u5236\u9650",
|
|
2456
|
+
"\u4E88\u7B97",
|
|
2457
|
+
// Russian
|
|
2458
|
+
"\u043D\u0435 \u0431\u043E\u043B\u0435\u0435",
|
|
2459
|
+
"\u043D\u0435 \u043C\u0435\u043D\u0435\u0435",
|
|
2460
|
+
"\u043A\u0430\u043A \u043C\u0438\u043D\u0438\u043C\u0443\u043C",
|
|
2461
|
+
"\u0432 \u043F\u0440\u0435\u0434\u0435\u043B\u0430\u0445",
|
|
2462
|
+
"\u043C\u0430\u043A\u0441\u0438\u043C\u0443\u043C",
|
|
2463
|
+
"\u043C\u0438\u043D\u0438\u043C\u0443\u043C",
|
|
2464
|
+
"\u043E\u0433\u0440\u0430\u043D\u0438\u0447\u0435\u043D\u0438\u0435",
|
|
2465
|
+
"\u0431\u044E\u0434\u0436\u0435\u0442",
|
|
2466
|
+
// German
|
|
2467
|
+
"h\xF6chstens",
|
|
2468
|
+
"mindestens",
|
|
2469
|
+
"innerhalb",
|
|
2470
|
+
"nicht mehr als",
|
|
2471
|
+
"maximal",
|
|
2472
|
+
"minimal",
|
|
2473
|
+
"grenze",
|
|
2474
|
+
"budget",
|
|
2475
|
+
// Spanish
|
|
2476
|
+
"como m\xE1ximo",
|
|
2477
|
+
"al menos",
|
|
2478
|
+
"dentro de",
|
|
2479
|
+
"no m\xE1s de",
|
|
2480
|
+
"m\xE1ximo",
|
|
2481
|
+
"m\xEDnimo",
|
|
2482
|
+
"l\xEDmite",
|
|
2483
|
+
"presupuesto",
|
|
2484
|
+
// Portuguese
|
|
2485
|
+
"no m\xE1ximo",
|
|
2486
|
+
"pelo menos",
|
|
2487
|
+
"dentro de",
|
|
2488
|
+
"n\xE3o mais que",
|
|
2489
|
+
"m\xE1ximo",
|
|
2490
|
+
"m\xEDnimo",
|
|
2491
|
+
"limite",
|
|
2492
|
+
"or\xE7amento",
|
|
2493
|
+
// Korean
|
|
2494
|
+
"\uC774\uD558",
|
|
2495
|
+
"\uC774\uC0C1",
|
|
2496
|
+
"\uCD5C\uB300",
|
|
2497
|
+
"\uCD5C\uC18C",
|
|
2498
|
+
"\uC81C\uD55C",
|
|
2499
|
+
"\uC608\uC0B0",
|
|
2500
|
+
// Arabic
|
|
2501
|
+
"\u0639\u0644\u0649 \u0627\u0644\u0623\u0643\u062B\u0631",
|
|
2502
|
+
"\u0639\u0644\u0649 \u0627\u0644\u0623\u0642\u0644",
|
|
2503
|
+
"\u0636\u0645\u0646",
|
|
2504
|
+
"\u0644\u0627 \u064A\u0632\u064A\u062F \u0639\u0646",
|
|
2505
|
+
"\u0623\u0642\u0635\u0649",
|
|
2506
|
+
"\u0623\u062F\u0646\u0649",
|
|
2507
|
+
"\u062D\u062F",
|
|
2508
|
+
"\u0645\u064A\u0632\u0627\u0646\u064A\u0629"
|
|
2509
|
+
],
|
|
2510
|
+
outputFormatKeywords: [
|
|
2511
|
+
// English
|
|
2512
|
+
"json",
|
|
2513
|
+
"yaml",
|
|
2514
|
+
"xml",
|
|
2515
|
+
"table",
|
|
2516
|
+
"csv",
|
|
2517
|
+
"markdown",
|
|
2518
|
+
"schema",
|
|
2519
|
+
"format as",
|
|
2520
|
+
"structured",
|
|
2521
|
+
// Chinese
|
|
2522
|
+
"\u8868\u683C",
|
|
2523
|
+
"\u683C\u5F0F\u5316\u4E3A",
|
|
2524
|
+
"\u7ED3\u6784\u5316",
|
|
2525
|
+
// Japanese
|
|
2526
|
+
"\u30C6\u30FC\u30D6\u30EB",
|
|
2527
|
+
"\u30D5\u30A9\u30FC\u30DE\u30C3\u30C8",
|
|
2528
|
+
"\u69CB\u9020\u5316",
|
|
2529
|
+
// Russian
|
|
2530
|
+
"\u0442\u0430\u0431\u043B\u0438\u0446\u0430",
|
|
2531
|
+
"\u0444\u043E\u0440\u043C\u0430\u0442\u0438\u0440\u043E\u0432\u0430\u0442\u044C \u043A\u0430\u043A",
|
|
2532
|
+
"\u0441\u0442\u0440\u0443\u043A\u0442\u0443\u0440\u0438\u0440\u043E\u0432\u0430\u043D\u043D\u044B\u0439",
|
|
2533
|
+
// German
|
|
2534
|
+
"tabelle",
|
|
2535
|
+
"formatieren als",
|
|
2536
|
+
"strukturiert",
|
|
2537
|
+
// Spanish
|
|
2538
|
+
"tabla",
|
|
2539
|
+
"formatear como",
|
|
2540
|
+
"estructurado",
|
|
2541
|
+
// Portuguese
|
|
2542
|
+
"tabela",
|
|
2543
|
+
"formatar como",
|
|
2544
|
+
"estruturado",
|
|
2545
|
+
// Korean
|
|
2546
|
+
"\uD14C\uC774\uBE14",
|
|
2547
|
+
"\uD615\uC2DD",
|
|
2548
|
+
"\uAD6C\uC870\uD654",
|
|
2549
|
+
// Arabic
|
|
2550
|
+
"\u062C\u062F\u0648\u0644",
|
|
2551
|
+
"\u062A\u0646\u0633\u064A\u0642",
|
|
2552
|
+
"\u0645\u0646\u0638\u0645"
|
|
2553
|
+
],
|
|
2554
|
+
referenceKeywords: [
|
|
2555
|
+
// English
|
|
2556
|
+
"above",
|
|
2557
|
+
"below",
|
|
2558
|
+
"previous",
|
|
2559
|
+
"following",
|
|
2560
|
+
"the docs",
|
|
2561
|
+
"the api",
|
|
2562
|
+
"the code",
|
|
2563
|
+
"earlier",
|
|
2564
|
+
"attached",
|
|
2565
|
+
// Chinese
|
|
2566
|
+
"\u4E0A\u9762",
|
|
2567
|
+
"\u4E0B\u9762",
|
|
2568
|
+
"\u4E4B\u524D",
|
|
2569
|
+
"\u63A5\u4E0B\u6765",
|
|
2570
|
+
"\u6587\u6863",
|
|
2571
|
+
"\u4EE3\u7801",
|
|
2572
|
+
"\u9644\u4EF6",
|
|
2573
|
+
// Japanese
|
|
2574
|
+
"\u4E0A\u8A18",
|
|
2575
|
+
"\u4E0B\u8A18",
|
|
2576
|
+
"\u524D\u306E",
|
|
2577
|
+
"\u6B21\u306E",
|
|
2578
|
+
"\u30C9\u30AD\u30E5\u30E1\u30F3\u30C8",
|
|
2579
|
+
"\u30B3\u30FC\u30C9",
|
|
2580
|
+
// Russian
|
|
2581
|
+
"\u0432\u044B\u0448\u0435",
|
|
2582
|
+
"\u043D\u0438\u0436\u0435",
|
|
2583
|
+
"\u043F\u0440\u0435\u0434\u044B\u0434\u0443\u0449\u0438\u0439",
|
|
2584
|
+
"\u0441\u043B\u0435\u0434\u0443\u044E\u0449\u0438\u0439",
|
|
2585
|
+
"\u0434\u043E\u043A\u0443\u043C\u0435\u043D\u0442\u0430\u0446\u0438\u044F",
|
|
2586
|
+
"\u043A\u043E\u0434",
|
|
2587
|
+
"\u0440\u0430\u043D\u0435\u0435",
|
|
2588
|
+
"\u0432\u043B\u043E\u0436\u0435\u043D\u0438\u0435",
|
|
2589
|
+
// German
|
|
2590
|
+
"oben",
|
|
2591
|
+
"unten",
|
|
2592
|
+
"vorherige",
|
|
2593
|
+
"folgende",
|
|
2594
|
+
"dokumentation",
|
|
2595
|
+
"der code",
|
|
2596
|
+
"fr\xFCher",
|
|
2597
|
+
"anhang",
|
|
2598
|
+
// Spanish
|
|
2599
|
+
"arriba",
|
|
2600
|
+
"abajo",
|
|
2601
|
+
"anterior",
|
|
2602
|
+
"siguiente",
|
|
2603
|
+
"documentaci\xF3n",
|
|
2604
|
+
"el c\xF3digo",
|
|
2605
|
+
"adjunto",
|
|
2606
|
+
// Portuguese
|
|
2607
|
+
"acima",
|
|
2608
|
+
"abaixo",
|
|
2609
|
+
"anterior",
|
|
2610
|
+
"seguinte",
|
|
2611
|
+
"documenta\xE7\xE3o",
|
|
2612
|
+
"o c\xF3digo",
|
|
2613
|
+
"anexo",
|
|
2614
|
+
// Korean
|
|
2615
|
+
"\uC704",
|
|
2616
|
+
"\uC544\uB798",
|
|
2617
|
+
"\uC774\uC804",
|
|
2618
|
+
"\uB2E4\uC74C",
|
|
2619
|
+
"\uBB38\uC11C",
|
|
2620
|
+
"\uCF54\uB4DC",
|
|
2621
|
+
"\uCCA8\uBD80",
|
|
2622
|
+
// Arabic
|
|
2623
|
+
"\u0623\u0639\u0644\u0627\u0647",
|
|
2624
|
+
"\u0623\u062F\u0646\u0627\u0647",
|
|
2625
|
+
"\u0627\u0644\u0633\u0627\u0628\u0642",
|
|
2626
|
+
"\u0627\u0644\u062A\u0627\u0644\u064A",
|
|
2627
|
+
"\u0627\u0644\u0648\u062B\u0627\u0626\u0642",
|
|
2628
|
+
"\u0627\u0644\u0643\u0648\u062F",
|
|
2629
|
+
"\u0645\u0631\u0641\u0642"
|
|
2630
|
+
],
|
|
2631
|
+
negationKeywords: [
|
|
2632
|
+
// English
|
|
2633
|
+
"don't",
|
|
2634
|
+
"do not",
|
|
2635
|
+
"avoid",
|
|
2636
|
+
"never",
|
|
2637
|
+
"without",
|
|
2638
|
+
"except",
|
|
2639
|
+
"exclude",
|
|
2640
|
+
"no longer",
|
|
2641
|
+
// Chinese
|
|
2642
|
+
"\u4E0D\u8981",
|
|
2643
|
+
"\u907F\u514D",
|
|
2644
|
+
"\u4ECE\u4E0D",
|
|
2645
|
+
"\u6CA1\u6709",
|
|
2646
|
+
"\u9664\u4E86",
|
|
2647
|
+
"\u6392\u9664",
|
|
2648
|
+
// Japanese
|
|
2649
|
+
"\u3057\u306A\u3044\u3067",
|
|
2650
|
+
"\u907F\u3051\u308B",
|
|
2651
|
+
"\u6C7A\u3057\u3066",
|
|
2652
|
+
"\u306A\u3057\u3067",
|
|
2653
|
+
"\u9664\u304F",
|
|
2654
|
+
// Russian
|
|
2655
|
+
"\u043D\u0435 \u0434\u0435\u043B\u0430\u0439",
|
|
2656
|
+
"\u043D\u0435 \u043D\u0430\u0434\u043E",
|
|
2657
|
+
"\u043D\u0435\u043B\u044C\u0437\u044F",
|
|
2658
|
+
"\u0438\u0437\u0431\u0435\u0433\u0430\u0442\u044C",
|
|
2659
|
+
"\u043D\u0438\u043A\u043E\u0433\u0434\u0430",
|
|
2660
|
+
"\u0431\u0435\u0437",
|
|
2661
|
+
"\u043A\u0440\u043E\u043C\u0435",
|
|
2662
|
+
"\u0438\u0441\u043A\u043B\u044E\u0447\u0438\u0442\u044C",
|
|
2663
|
+
"\u0431\u043E\u043B\u044C\u0448\u0435 \u043D\u0435",
|
|
2664
|
+
// German
|
|
2665
|
+
"nicht",
|
|
2666
|
+
"vermeide",
|
|
2667
|
+
"niemals",
|
|
2668
|
+
"ohne",
|
|
2669
|
+
"au\xDFer",
|
|
2670
|
+
"ausschlie\xDFen",
|
|
2671
|
+
"nicht mehr",
|
|
2672
|
+
// Spanish
|
|
2673
|
+
"no hagas",
|
|
2674
|
+
"evitar",
|
|
2675
|
+
"nunca",
|
|
2676
|
+
"sin",
|
|
2677
|
+
"excepto",
|
|
2678
|
+
"excluir",
|
|
2679
|
+
// Portuguese
|
|
2680
|
+
"n\xE3o fa\xE7a",
|
|
2681
|
+
"evitar",
|
|
2682
|
+
"nunca",
|
|
2683
|
+
"sem",
|
|
2684
|
+
"exceto",
|
|
2685
|
+
"excluir",
|
|
2686
|
+
// Korean
|
|
2687
|
+
"\uD558\uC9C0 \uB9C8",
|
|
2688
|
+
"\uD53C\uD558\uB2E4",
|
|
2689
|
+
"\uC808\uB300",
|
|
2690
|
+
"\uC5C6\uC774",
|
|
2691
|
+
"\uC81C\uC678",
|
|
2692
|
+
// Arabic
|
|
2693
|
+
"\u0644\u0627 \u062A\u0641\u0639\u0644",
|
|
2694
|
+
"\u062A\u062C\u0646\u0628",
|
|
2695
|
+
"\u0623\u0628\u062F\u0627\u064B",
|
|
2696
|
+
"\u0628\u062F\u0648\u0646",
|
|
2697
|
+
"\u0628\u0627\u0633\u062A\u062B\u0646\u0627\u0621",
|
|
2698
|
+
"\u0627\u0633\u062A\u0628\u0639\u0627\u062F"
|
|
2699
|
+
],
|
|
2700
|
+
domainSpecificKeywords: [
|
|
2701
|
+
// English
|
|
2702
|
+
"quantum",
|
|
2703
|
+
"fpga",
|
|
2704
|
+
"vlsi",
|
|
2705
|
+
"risc-v",
|
|
2706
|
+
"asic",
|
|
2707
|
+
"photonics",
|
|
2708
|
+
"genomics",
|
|
2709
|
+
"proteomics",
|
|
2710
|
+
"topological",
|
|
2711
|
+
"homomorphic",
|
|
2712
|
+
"zero-knowledge",
|
|
2713
|
+
"lattice-based",
|
|
2714
|
+
// Chinese
|
|
2715
|
+
"\u91CF\u5B50",
|
|
2716
|
+
"\u5149\u5B50\u5B66",
|
|
2717
|
+
"\u57FA\u56E0\u7EC4\u5B66",
|
|
2718
|
+
"\u86CB\u767D\u8D28\u7EC4\u5B66",
|
|
2719
|
+
"\u62D3\u6251",
|
|
2720
|
+
"\u540C\u6001",
|
|
2721
|
+
"\u96F6\u77E5\u8BC6",
|
|
2722
|
+
"\u683C\u5BC6\u7801",
|
|
2723
|
+
// Japanese
|
|
2724
|
+
"\u91CF\u5B50",
|
|
2725
|
+
"\u30D5\u30A9\u30C8\u30CB\u30AF\u30B9",
|
|
2726
|
+
"\u30B2\u30CE\u30DF\u30AF\u30B9",
|
|
2727
|
+
"\u30C8\u30DD\u30ED\u30B8\u30AB\u30EB",
|
|
2728
|
+
// Russian
|
|
2729
|
+
"\u043A\u0432\u0430\u043D\u0442\u043E\u0432\u044B\u0439",
|
|
2730
|
+
"\u0444\u043E\u0442\u043E\u043D\u0438\u043A\u0430",
|
|
2731
|
+
"\u0433\u0435\u043D\u043E\u043C\u0438\u043A\u0430",
|
|
2732
|
+
"\u043F\u0440\u043E\u0442\u0435\u043E\u043C\u0438\u043A\u0430",
|
|
2733
|
+
"\u0442\u043E\u043F\u043E\u043B\u043E\u0433\u0438\u0447\u0435\u0441\u043A\u0438\u0439",
|
|
2734
|
+
"\u0433\u043E\u043C\u043E\u043C\u043E\u0440\u0444\u043D\u044B\u0439",
|
|
2735
|
+
"\u0441 \u043D\u0443\u043B\u0435\u0432\u044B\u043C \u0440\u0430\u0437\u0433\u043B\u0430\u0448\u0435\u043D\u0438\u0435\u043C",
|
|
2736
|
+
"\u043D\u0430 \u043E\u0441\u043D\u043E\u0432\u0435 \u0440\u0435\u0448\u0451\u0442\u043E\u043A",
|
|
2737
|
+
// German
|
|
2738
|
+
"quanten",
|
|
2739
|
+
"photonik",
|
|
2740
|
+
"genomik",
|
|
2741
|
+
"proteomik",
|
|
2742
|
+
"topologisch",
|
|
2743
|
+
"homomorph",
|
|
2744
|
+
"zero-knowledge",
|
|
2745
|
+
"gitterbasiert",
|
|
2746
|
+
// Spanish
|
|
2747
|
+
"cu\xE1ntico",
|
|
2748
|
+
"fot\xF3nica",
|
|
2749
|
+
"gen\xF3mica",
|
|
2750
|
+
"prote\xF3mica",
|
|
2751
|
+
"topol\xF3gico",
|
|
2752
|
+
"homom\xF3rfico",
|
|
2753
|
+
// Portuguese
|
|
2754
|
+
"qu\xE2ntico",
|
|
2755
|
+
"fot\xF4nica",
|
|
2756
|
+
"gen\xF4mica",
|
|
2757
|
+
"prote\xF4mica",
|
|
2758
|
+
"topol\xF3gico",
|
|
2759
|
+
"homom\xF3rfico",
|
|
2760
|
+
// Korean
|
|
2761
|
+
"\uC591\uC790",
|
|
2762
|
+
"\uD3EC\uD1A0\uB2C9\uC2A4",
|
|
2763
|
+
"\uC720\uC804\uCCB4\uD559",
|
|
2764
|
+
"\uC704\uC0C1",
|
|
2765
|
+
"\uB3D9\uD615",
|
|
2766
|
+
// Arabic
|
|
2767
|
+
"\u0643\u0645\u064A",
|
|
2768
|
+
"\u0636\u0648\u0626\u064A\u0627\u062A",
|
|
2769
|
+
"\u062C\u064A\u0646\u0648\u0645\u064A\u0627\u062A",
|
|
2770
|
+
"\u0637\u0648\u0628\u0648\u0644\u0648\u062C\u064A",
|
|
2771
|
+
"\u062A\u0645\u0627\u062B\u0644\u064A"
|
|
2772
|
+
],
|
|
2773
|
+
// Agentic task keywords - file ops, execution, multi-step, iterative work
|
|
2774
|
+
// Pruned: removed overly common words like "then", "first", "run", "test", "build"
|
|
2775
|
+
agenticTaskKeywords: [
|
|
2776
|
+
// English - File operations (clearly agentic)
|
|
2777
|
+
"read file",
|
|
2778
|
+
"read the file",
|
|
2779
|
+
"look at",
|
|
2780
|
+
"check the",
|
|
2781
|
+
"open the",
|
|
2782
|
+
"edit",
|
|
2783
|
+
"modify",
|
|
2784
|
+
"update the",
|
|
2785
|
+
"change the",
|
|
2786
|
+
"write to",
|
|
2787
|
+
"create file",
|
|
2788
|
+
// English - Execution (specific commands only)
|
|
2789
|
+
"execute",
|
|
2790
|
+
"deploy",
|
|
2791
|
+
"install",
|
|
2792
|
+
"npm",
|
|
2793
|
+
"pip",
|
|
2794
|
+
"compile",
|
|
2795
|
+
// English - Multi-step patterns (specific only)
|
|
2796
|
+
"after that",
|
|
2797
|
+
"and also",
|
|
2798
|
+
"once done",
|
|
2799
|
+
"step 1",
|
|
2800
|
+
"step 2",
|
|
2801
|
+
// English - Iterative work
|
|
2802
|
+
"fix",
|
|
2803
|
+
"debug",
|
|
2804
|
+
"until it works",
|
|
2805
|
+
"keep trying",
|
|
2806
|
+
"iterate",
|
|
2807
|
+
"make sure",
|
|
2808
|
+
"verify",
|
|
2809
|
+
"confirm",
|
|
2810
|
+
// Chinese (keep specific ones)
|
|
2811
|
+
"\u8BFB\u53D6\u6587\u4EF6",
|
|
2812
|
+
"\u67E5\u770B",
|
|
2813
|
+
"\u6253\u5F00",
|
|
2814
|
+
"\u7F16\u8F91",
|
|
2815
|
+
"\u4FEE\u6539",
|
|
2816
|
+
"\u66F4\u65B0",
|
|
2817
|
+
"\u521B\u5EFA",
|
|
2818
|
+
"\u6267\u884C",
|
|
2819
|
+
"\u90E8\u7F72",
|
|
2820
|
+
"\u5B89\u88C5",
|
|
2821
|
+
"\u7B2C\u4E00\u6B65",
|
|
2822
|
+
"\u7B2C\u4E8C\u6B65",
|
|
2823
|
+
"\u4FEE\u590D",
|
|
2824
|
+
"\u8C03\u8BD5",
|
|
2825
|
+
"\u76F4\u5230",
|
|
2826
|
+
"\u786E\u8BA4",
|
|
2827
|
+
"\u9A8C\u8BC1",
|
|
2828
|
+
// Spanish
|
|
2829
|
+
"leer archivo",
|
|
2830
|
+
"editar",
|
|
2831
|
+
"modificar",
|
|
2832
|
+
"actualizar",
|
|
2833
|
+
"ejecutar",
|
|
2834
|
+
"desplegar",
|
|
2835
|
+
"instalar",
|
|
2836
|
+
"paso 1",
|
|
2837
|
+
"paso 2",
|
|
2838
|
+
"arreglar",
|
|
2839
|
+
"depurar",
|
|
2840
|
+
"verificar",
|
|
2841
|
+
// Portuguese
|
|
2842
|
+
"ler arquivo",
|
|
2843
|
+
"editar",
|
|
2844
|
+
"modificar",
|
|
2845
|
+
"atualizar",
|
|
2846
|
+
"executar",
|
|
2847
|
+
"implantar",
|
|
2848
|
+
"instalar",
|
|
2849
|
+
"passo 1",
|
|
2850
|
+
"passo 2",
|
|
2851
|
+
"corrigir",
|
|
2852
|
+
"depurar",
|
|
2853
|
+
"verificar",
|
|
2854
|
+
// Korean
|
|
2855
|
+
"\uD30C\uC77C \uC77D\uAE30",
|
|
2856
|
+
"\uD3B8\uC9D1",
|
|
2857
|
+
"\uC218\uC815",
|
|
2858
|
+
"\uC5C5\uB370\uC774\uD2B8",
|
|
2859
|
+
"\uC2E4\uD589",
|
|
2860
|
+
"\uBC30\uD3EC",
|
|
2861
|
+
"\uC124\uCE58",
|
|
2862
|
+
"\uB2E8\uACC4 1",
|
|
2863
|
+
"\uB2E8\uACC4 2",
|
|
2864
|
+
"\uB514\uBC84\uADF8",
|
|
2865
|
+
"\uD655\uC778",
|
|
2866
|
+
// Arabic
|
|
2867
|
+
"\u0642\u0631\u0627\u0621\u0629 \u0645\u0644\u0641",
|
|
2868
|
+
"\u062A\u062D\u0631\u064A\u0631",
|
|
2869
|
+
"\u062A\u0639\u062F\u064A\u0644",
|
|
2870
|
+
"\u062A\u062D\u062F\u064A\u062B",
|
|
2871
|
+
"\u062A\u0646\u0641\u064A\u0630",
|
|
2872
|
+
"\u0646\u0634\u0631",
|
|
2873
|
+
"\u062A\u062B\u0628\u064A\u062A",
|
|
2874
|
+
"\u0627\u0644\u062E\u0637\u0648\u0629 1",
|
|
2875
|
+
"\u0627\u0644\u062E\u0637\u0648\u0629 2",
|
|
2876
|
+
"\u0625\u0635\u0644\u0627\u062D",
|
|
2877
|
+
"\u062A\u0635\u062D\u064A\u062D",
|
|
2878
|
+
"\u062A\u062D\u0642\u0642"
|
|
2879
|
+
],
|
|
2880
|
+
// Dimension weights (sum to 1.0)
|
|
2881
|
+
dimensionWeights: {
|
|
2882
|
+
tokenCount: 0.08,
|
|
2883
|
+
codePresence: 0.15,
|
|
2884
|
+
reasoningMarkers: 0.18,
|
|
2885
|
+
technicalTerms: 0.1,
|
|
2886
|
+
creativeMarkers: 0.05,
|
|
2887
|
+
simpleIndicators: 0.02,
|
|
2888
|
+
// Reduced from 0.12 to make room for agenticTask
|
|
2889
|
+
multiStepPatterns: 0.12,
|
|
2890
|
+
questionComplexity: 0.05,
|
|
2891
|
+
imperativeVerbs: 0.03,
|
|
2892
|
+
constraintCount: 0.04,
|
|
2893
|
+
outputFormat: 0.03,
|
|
2894
|
+
referenceComplexity: 0.02,
|
|
2895
|
+
negationComplexity: 0.01,
|
|
2896
|
+
domainSpecificity: 0.02,
|
|
2897
|
+
agenticTask: 0.04
|
|
2898
|
+
// Reduced - agentic signals influence tier selection, not dominate it
|
|
2899
|
+
},
|
|
2900
|
+
// Tier boundaries on weighted score axis
|
|
2901
|
+
tierBoundaries: {
|
|
2902
|
+
simpleMedium: 0,
|
|
2903
|
+
mediumComplex: 0.3,
|
|
2904
|
+
// Raised from 0.18 - prevent simple tasks from reaching expensive COMPLEX tier
|
|
2905
|
+
complexReasoning: 0.5
|
|
2906
|
+
// Raised from 0.4 - reserve for true reasoning tasks
|
|
2907
|
+
},
|
|
2908
|
+
// Sigmoid steepness for confidence calibration
|
|
2909
|
+
confidenceSteepness: 12,
|
|
2910
|
+
// Below this confidence → ambiguous (null tier)
|
|
2911
|
+
confidenceThreshold: 0.7
|
|
2912
|
+
},
|
|
2913
|
+
// Auto (balanced) tier configs - current default smart routing
|
|
2914
|
+
// Benchmark-tuned 2026-03-16: balancing quality (retention) + latency
|
|
2915
|
+
tiers: {
|
|
2916
|
+
SIMPLE: {
|
|
2917
|
+
primary: "google/gemini-2.5-flash",
|
|
2918
|
+
// 1,238ms, IQ 20, 60% retention (best) — fast AND quality
|
|
2919
|
+
fallback: [
|
|
2920
|
+
"google/gemini-3-flash-preview",
|
|
2921
|
+
// 1,398ms, IQ 46 — smarter fallback
|
|
2922
|
+
"deepseek/deepseek-chat",
|
|
2923
|
+
// V4 Flash chat ($0.20/$0.40, 1M ctx) — repriced 2026-04-24
|
|
2924
|
+
"moonshot/kimi-k2.5",
|
|
2925
|
+
// 1,646ms, IQ 47, strong quality
|
|
2926
|
+
"google/gemini-3.1-flash-lite",
|
|
2927
|
+
// $0.25/$1.50, 1M context — newest flash-lite
|
|
2928
|
+
"google/gemini-2.5-flash-lite",
|
|
2929
|
+
// 1,353ms, $0.10/$0.40
|
|
2930
|
+
"openai/gpt-5.4-nano",
|
|
2931
|
+
// $0.20/$1.25, 1M context
|
|
2932
|
+
"xai/grok-4-fast-non-reasoning",
|
|
2933
|
+
// 1,143ms, $0.20/$0.50 — fast fallback
|
|
2934
|
+
"free/gpt-oss-120b"
|
|
2935
|
+
// 1,252ms, FREE fallback (hidden from /v1/models but direct calls work)
|
|
2936
|
+
]
|
|
2937
|
+
},
|
|
2938
|
+
MEDIUM: {
|
|
2939
|
+
primary: "moonshot/kimi-k2.7",
|
|
2940
|
+
// $0.95/$4.00, 256K ctx, multi-modal + reasoning — Moonshot flagship; promoted from K2.6 (2026-06-14) after BlockRun added K2.7 + hid K2.6. Same price as K2.6.
|
|
2941
|
+
fallback: [
|
|
2942
|
+
"moonshot/kimi-k2.6",
|
|
2943
|
+
// identical-cost in-family hot swap (K2.6 still routable)
|
|
2944
|
+
"moonshot/kimi-k2.5",
|
|
2945
|
+
// $0.60/$3.00 — graceful-degradation backstop
|
|
2946
|
+
"google/gemini-3-flash-preview",
|
|
2947
|
+
// 1,398ms, IQ 46 — nearly same IQ, faster + cheaper
|
|
2948
|
+
"deepseek/deepseek-chat",
|
|
2949
|
+
// 1,431ms, IQ 32, 41% retention
|
|
2950
|
+
"google/gemini-2.5-flash",
|
|
2951
|
+
// 1,238ms, 60% retention
|
|
2952
|
+
"google/gemini-3.1-flash-lite",
|
|
2953
|
+
// $0.25/$1.50, 1M context
|
|
2954
|
+
"google/gemini-2.5-flash-lite",
|
|
2955
|
+
// 1,353ms, $0.10/$0.40
|
|
2956
|
+
"xai/grok-4-1-fast-non-reasoning",
|
|
2957
|
+
// 1,244ms, fast fallback
|
|
2958
|
+
"xai/grok-3-mini"
|
|
2959
|
+
// 1,202ms, $0.30/$0.50
|
|
2960
|
+
]
|
|
2961
|
+
},
|
|
2962
|
+
COMPLEX: {
|
|
2963
|
+
primary: "google/gemini-3.1-pro",
|
|
2964
|
+
// 1,609ms, IQ 57 — fast flagship quality
|
|
2965
|
+
fallback: [
|
|
2966
|
+
"google/gemini-3-flash-preview",
|
|
2967
|
+
// 1,398ms, IQ 46 — fast + smart
|
|
2968
|
+
"xai/grok-4-0709",
|
|
2969
|
+
// 1,348ms, IQ 41
|
|
2970
|
+
"google/gemini-2.5-pro",
|
|
2971
|
+
// 1,294ms
|
|
2972
|
+
"anthropic/claude-sonnet-5",
|
|
2973
|
+
// near-Opus quality at Sonnet cost, 1M ctx
|
|
2974
|
+
"anthropic/claude-sonnet-4.6",
|
|
2975
|
+
// 2,110ms, IQ 52 — quality fallback
|
|
2976
|
+
"deepseek/deepseek-chat",
|
|
2977
|
+
// 1,431ms, IQ 32
|
|
2978
|
+
"google/gemini-2.5-flash",
|
|
2979
|
+
// 1,238ms, IQ 20 — cheap last resort
|
|
2980
|
+
"openai/gpt-5.6-terra",
|
|
2981
|
+
// GPT-5.6 balanced tier — newest generation, stable (Sol excluded: #202)
|
|
2982
|
+
"openai/gpt-5.5",
|
|
2983
|
+
// Prior OpenAI flagship — 1M+ ctx, native agent + computer use; benchmark TBD
|
|
2984
|
+
"openai/gpt-5.4"
|
|
2985
|
+
// 6,213ms, IQ 57 — previous flagship, benchmarked
|
|
2986
|
+
]
|
|
2987
|
+
},
|
|
2988
|
+
REASONING: {
|
|
2989
|
+
primary: "xai/grok-4-1-fast-reasoning",
|
|
2990
|
+
// 1,454ms, $0.20/$0.50
|
|
2991
|
+
fallback: [
|
|
2992
|
+
"xai/grok-4-fast-reasoning",
|
|
2993
|
+
// 1,298ms, $0.20/$0.50
|
|
2994
|
+
"deepseek/deepseek-reasoner",
|
|
2995
|
+
// V4 Flash thinking ($0.20/$0.40, 1M ctx)
|
|
2996
|
+
"deepseek/deepseek-v4-pro",
|
|
2997
|
+
// V4 Pro flagship ($0.50/$1.00 promo through 2026-05-31, list $2/$4) — strongest open-weight reasoner
|
|
2998
|
+
"openai/o4-mini",
|
|
2999
|
+
// 2,328ms ($1.10/$4.40)
|
|
3000
|
+
"openai/o3"
|
|
3001
|
+
// 2,862ms
|
|
3002
|
+
]
|
|
3003
|
+
}
|
|
3004
|
+
},
|
|
3005
|
+
// Eco tier configs - absolute cheapest (blockrun/eco)
|
|
3006
|
+
ecoTiers: {
|
|
3007
|
+
SIMPLE: {
|
|
3008
|
+
primary: "free/gpt-oss-120b",
|
|
3009
|
+
// FREE! $0.00/$0.00 — heavy user default
|
|
3010
|
+
fallback: [
|
|
3011
|
+
"free/gpt-oss-20b",
|
|
3012
|
+
// FREE — smaller, faster
|
|
3013
|
+
"free/deepseek-v4-flash",
|
|
3014
|
+
// FREE — 1M ctx; slow (~10 tok/s, 07-28 probe) but completes
|
|
3015
|
+
// seed-oss-36b sat here as the free coder until it EOL'd 2026-08-03 (HTTP 410).
|
|
3016
|
+
// gpt-oss-120b/20b already head this chain, so the rung is dropped, not retargeted.
|
|
3017
|
+
"google/gemini-3.1-flash-lite",
|
|
3018
|
+
// $0.25/$1.50 — newest flash-lite
|
|
3019
|
+
"openai/gpt-5.4-nano",
|
|
3020
|
+
// $0.20/$1.25 — fast nano
|
|
3021
|
+
"google/gemini-2.5-flash-lite",
|
|
3022
|
+
// $0.10/$0.40
|
|
3023
|
+
"xai/grok-4-fast-non-reasoning"
|
|
3024
|
+
// $0.20/$0.50
|
|
3025
|
+
]
|
|
3026
|
+
},
|
|
3027
|
+
MEDIUM: {
|
|
3028
|
+
primary: "google/gemini-3.1-flash-lite",
|
|
3029
|
+
// $0.25/$1.50 — newest flash-lite
|
|
3030
|
+
fallback: [
|
|
3031
|
+
"openai/gpt-5.4-nano",
|
|
3032
|
+
// $0.20/$1.25
|
|
3033
|
+
"google/gemini-2.5-flash-lite",
|
|
3034
|
+
// $0.10/$0.40
|
|
3035
|
+
"xai/grok-4-fast-non-reasoning",
|
|
3036
|
+
"google/gemini-2.5-flash"
|
|
3037
|
+
]
|
|
3038
|
+
},
|
|
3039
|
+
COMPLEX: {
|
|
3040
|
+
primary: "google/gemini-3.1-flash-lite",
|
|
3041
|
+
// $0.25/$1.50
|
|
3042
|
+
fallback: [
|
|
3043
|
+
"google/gemini-2.5-flash-lite",
|
|
3044
|
+
"xai/grok-4-0709",
|
|
3045
|
+
"google/gemini-2.5-flash",
|
|
3046
|
+
"deepseek/deepseek-chat"
|
|
3047
|
+
]
|
|
3048
|
+
},
|
|
3049
|
+
REASONING: {
|
|
3050
|
+
primary: "xai/grok-4-1-fast-reasoning",
|
|
3051
|
+
// $0.20/$0.50
|
|
3052
|
+
fallback: [
|
|
3053
|
+
"xai/grok-4-fast-reasoning",
|
|
3054
|
+
"deepseek/deepseek-reasoner",
|
|
3055
|
+
// V4 Flash thinking — $0.20/$0.40
|
|
3056
|
+
"deepseek/deepseek-v4-pro"
|
|
3057
|
+
// V4 Pro flagship — $0.50/$1.00 promo, post-promo $2/$4
|
|
3058
|
+
]
|
|
3059
|
+
}
|
|
3060
|
+
},
|
|
3061
|
+
// Premium tier configs - best quality (blockrun/premium)
|
|
3062
|
+
// codex=complex coding, kimi=simple coding, sonnet=reasoning/instructions, opus=architecture/PM/audits
|
|
3063
|
+
premiumTiers: {
|
|
3064
|
+
SIMPLE: {
|
|
3065
|
+
primary: "moonshot/kimi-k2.7",
|
|
3066
|
+
// $0.95/$4.00 - Moonshot flagship (256K ctx, multi-modal + reasoning); promoted from K2.6 (2026-06-14), same price
|
|
3067
|
+
fallback: [
|
|
3068
|
+
"moonshot/kimi-k2.6",
|
|
3069
|
+
// identical-cost in-family hot swap (K2.6 still routable)
|
|
3070
|
+
"moonshot/kimi-k2.5",
|
|
3071
|
+
// $0.60/$3.00 - proven reliable backstop when Moonshot direct API falters
|
|
3072
|
+
"google/gemini-2.5-flash",
|
|
3073
|
+
// 60% retention, fast growth
|
|
3074
|
+
"anthropic/claude-haiku-4.5",
|
|
3075
|
+
"google/gemini-2.5-flash-lite",
|
|
3076
|
+
"deepseek/deepseek-chat"
|
|
3077
|
+
]
|
|
3078
|
+
},
|
|
3079
|
+
MEDIUM: {
|
|
3080
|
+
primary: "openai/gpt-5.3-codex",
|
|
3081
|
+
// $1.75/$14 - 400K context, 128K output, replaces 5.2
|
|
3082
|
+
fallback: [
|
|
3083
|
+
"moonshot/kimi-k2.7",
|
|
3084
|
+
// Moonshot flagship
|
|
3085
|
+
"moonshot/kimi-k2.6",
|
|
3086
|
+
"moonshot/kimi-k2.5",
|
|
3087
|
+
"google/gemini-2.5-flash",
|
|
3088
|
+
// 60% retention, good coding capability
|
|
3089
|
+
"google/gemini-2.5-pro",
|
|
3090
|
+
"xai/grok-4-0709",
|
|
3091
|
+
"anthropic/claude-sonnet-5",
|
|
3092
|
+
"anthropic/claude-sonnet-4.6"
|
|
3093
|
+
]
|
|
3094
|
+
},
|
|
3095
|
+
COMPLEX: {
|
|
3096
|
+
// fable-5 was promoted here 2026-06-11, force-reverted 2026-06-13 when Anthropic
|
|
3097
|
+
// withdrew the offer, and restored 2026-07-14 now that BlockRun has relisted it.
|
|
3098
|
+
primary: "anthropic/claude-fable-5",
|
|
3099
|
+
// Best quality for complex tasks — Mythos-class flagship above Opus ($10/$50, 1M ctx, always-on thinking)
|
|
3100
|
+
// Fallback chain de-Gemini'd 2026-04-22: when Anthropic 503s, Gemini is
|
|
3101
|
+
// also prone to "high demand" 503s (correlated failure — everyone falls
|
|
3102
|
+
// back to Google at the same time). Prefer xAI Grok → Moonshot → OpenAI
|
|
3103
|
+
// flagship → DeepSeek → NVIDIA free instead.
|
|
3104
|
+
fallback: [
|
|
3105
|
+
"anthropic/claude-opus-5",
|
|
3106
|
+
// in-family hot swap first (half the price, 1M ctx + adaptive thinking)
|
|
3107
|
+
"anthropic/claude-opus-4.8",
|
|
3108
|
+
// in-family hot swap (identical cost to 5)
|
|
3109
|
+
"anthropic/claude-opus-4.7",
|
|
3110
|
+
// in-family hot swap (identical cost to 4.8)
|
|
3111
|
+
"anthropic/claude-opus-4.6",
|
|
3112
|
+
// in-family hot swap
|
|
3113
|
+
"anthropic/claude-sonnet-5",
|
|
3114
|
+
// Sonnet-tier drop-down, near-Opus quality
|
|
3115
|
+
"anthropic/claude-sonnet-4.6",
|
|
3116
|
+
"xai/grok-4.5",
|
|
3117
|
+
// xAI flagship — 503-resistant, direct-xAI SKU (added 2026-07-14)
|
|
3118
|
+
"xai/grok-4-0709",
|
|
3119
|
+
// 503-resistant flagship
|
|
3120
|
+
"moonshot/kimi-k2.7",
|
|
3121
|
+
// Moonshot flagship, independent infra
|
|
3122
|
+
"moonshot/kimi-k2.6",
|
|
3123
|
+
"moonshot/kimi-k2.5",
|
|
3124
|
+
"openai/gpt-5.6-terra",
|
|
3125
|
+
// GPT-5.6 balanced tier — newest generation, stable (Sol excluded: #202)
|
|
3126
|
+
"openai/gpt-5.5",
|
|
3127
|
+
// Prior OpenAI flagship — 1M+ ctx, native agent + computer use
|
|
3128
|
+
"openai/gpt-5.4",
|
|
3129
|
+
// Previous flagship (slow but stable, benchmarked at 6,213ms)
|
|
3130
|
+
"openai/gpt-5.3-codex",
|
|
3131
|
+
"deepseek/deepseek-chat",
|
|
3132
|
+
// Cheap, reliable
|
|
3133
|
+
"free/gpt-oss-120b"
|
|
3134
|
+
// NVIDIA free ultimate backstop (was seed-oss-36b; EOL'd 2026-08-03)
|
|
3135
|
+
]
|
|
3136
|
+
},
|
|
3137
|
+
REASONING: {
|
|
3138
|
+
primary: "anthropic/claude-sonnet-4.6",
|
|
3139
|
+
// 2,110ms, $3/$15 - best for reasoning/instructions
|
|
3140
|
+
fallback: [
|
|
3141
|
+
"anthropic/claude-sonnet-5",
|
|
3142
|
+
// in-family hot swap — same cost, adaptive thinking, 1M ctx
|
|
3143
|
+
"anthropic/claude-opus-5",
|
|
3144
|
+
// Newest flagship Opus w/ adaptive thinking
|
|
3145
|
+
"anthropic/claude-opus-4.8",
|
|
3146
|
+
// Prior flagship Opus — identical cost to 5
|
|
3147
|
+
"anthropic/claude-opus-4.7",
|
|
3148
|
+
// Flagship Opus w/ adaptive thinking
|
|
3149
|
+
"anthropic/claude-opus-4.6",
|
|
3150
|
+
// 2,139ms
|
|
3151
|
+
"xai/grok-4-1-fast-reasoning",
|
|
3152
|
+
// 1,454ms, cheap fast reasoning
|
|
3153
|
+
"openai/o4-mini",
|
|
3154
|
+
// 2,328ms ($1.10/$4.40)
|
|
3155
|
+
"openai/o3"
|
|
3156
|
+
// 2,862ms
|
|
3157
|
+
]
|
|
3158
|
+
}
|
|
3159
|
+
},
|
|
3160
|
+
// Agentic tier configs - models that excel at multi-step autonomous tasks
|
|
3161
|
+
agenticTiers: {
|
|
3162
|
+
SIMPLE: {
|
|
3163
|
+
primary: "openai/gpt-4o-mini",
|
|
3164
|
+
// $0.15/$0.60 - best tool compliance at lowest cost
|
|
3165
|
+
fallback: [
|
|
3166
|
+
"moonshot/kimi-k2.5",
|
|
3167
|
+
// 1,646ms, strong tool use quality
|
|
3168
|
+
"anthropic/claude-haiku-4.5",
|
|
3169
|
+
// 2,305ms
|
|
3170
|
+
"xai/grok-4-1-fast-non-reasoning"
|
|
3171
|
+
// 1,244ms, fast fallback
|
|
3172
|
+
]
|
|
3173
|
+
},
|
|
3174
|
+
MEDIUM: {
|
|
3175
|
+
primary: "moonshot/kimi-k2.7",
|
|
3176
|
+
// $0.95/$4.00 — Moonshot flagship, strong tool use; promoted from K2.6 (2026-06-14) after BlockRun added K2.7 + hid K2.6. Same price.
|
|
3177
|
+
fallback: [
|
|
3178
|
+
"moonshot/kimi-k2.6",
|
|
3179
|
+
// identical-cost in-family hot swap (K2.6 still routable)
|
|
3180
|
+
"moonshot/kimi-k2.5",
|
|
3181
|
+
// $0.60/$3.00 — graceful-degradation backstop
|
|
3182
|
+
"xai/grok-4-1-fast-non-reasoning",
|
|
3183
|
+
// 1,244ms, fast fallback
|
|
3184
|
+
"openai/gpt-4o-mini",
|
|
3185
|
+
// 2,764ms, reliable tool calling
|
|
3186
|
+
"anthropic/claude-haiku-4.5",
|
|
3187
|
+
// 2,305ms
|
|
3188
|
+
"deepseek/deepseek-chat"
|
|
3189
|
+
// 1,431ms
|
|
3190
|
+
]
|
|
3191
|
+
},
|
|
3192
|
+
COMPLEX: {
|
|
3193
|
+
primary: "anthropic/claude-sonnet-4.6",
|
|
3194
|
+
// 2,110ms — best agentic quality
|
|
3195
|
+
// Fallback chain de-Gemini'd 2026-04-22: Gemini's "high demand" 503s
|
|
3196
|
+
// correlate with Anthropic outages (everyone falls back together).
|
|
3197
|
+
// Prefer 503-resistant providers first.
|
|
3198
|
+
fallback: [
|
|
3199
|
+
"anthropic/claude-sonnet-5",
|
|
3200
|
+
// in-family hot swap — same cost, near-Opus agentic quality
|
|
3201
|
+
"anthropic/claude-opus-5",
|
|
3202
|
+
// Newest flagship Opus — in-family hot swap
|
|
3203
|
+
"anthropic/claude-opus-4.8",
|
|
3204
|
+
// Prior flagship Opus — identical cost to 5
|
|
3205
|
+
"anthropic/claude-opus-4.7",
|
|
3206
|
+
// Flagship Opus — in-family hot swap
|
|
3207
|
+
"anthropic/claude-opus-4.6",
|
|
3208
|
+
// 2,139ms
|
|
3209
|
+
"xai/grok-4-0709",
|
|
3210
|
+
// 1,348ms — strong tool use, independent infra
|
|
3211
|
+
"moonshot/kimi-k2.7",
|
|
3212
|
+
// Moonshot flagship — strong tool use, independent infra
|
|
3213
|
+
"moonshot/kimi-k2.5",
|
|
3214
|
+
// cost-stability backstop
|
|
3215
|
+
"openai/gpt-5.6-terra",
|
|
3216
|
+
// GPT-5.6 balanced tier — newest generation, stable (Sol excluded: #202)
|
|
3217
|
+
"openai/gpt-5.5",
|
|
3218
|
+
// Prior flagship — native agent + computer use (exactly the agentic-tier use case)
|
|
3219
|
+
"openai/gpt-5.4",
|
|
3220
|
+
// Previous flagship — 6,213ms, reliable
|
|
3221
|
+
"deepseek/deepseek-chat",
|
|
3222
|
+
// 1,431ms — cheap, reliable
|
|
3223
|
+
"free/gpt-oss-120b"
|
|
3224
|
+
// NVIDIA free ultimate backstop (was seed-oss-36b; EOL'd 2026-08-03)
|
|
3225
|
+
]
|
|
3226
|
+
},
|
|
3227
|
+
REASONING: {
|
|
3228
|
+
primary: "anthropic/claude-sonnet-4.6",
|
|
3229
|
+
// 2,110ms — strong tool use + reasoning
|
|
3230
|
+
fallback: [
|
|
3231
|
+
"anthropic/claude-sonnet-5",
|
|
3232
|
+
// in-family hot swap — same cost, adaptive thinking
|
|
3233
|
+
"anthropic/claude-opus-5",
|
|
3234
|
+
// Newest flagship Opus w/ adaptive thinking
|
|
3235
|
+
"anthropic/claude-opus-4.8",
|
|
3236
|
+
// Prior flagship Opus — identical cost to 5
|
|
3237
|
+
"anthropic/claude-opus-4.7",
|
|
3238
|
+
// Flagship Opus w/ adaptive thinking
|
|
3239
|
+
"anthropic/claude-opus-4.6",
|
|
3240
|
+
// 2,139ms
|
|
3241
|
+
"xai/grok-4-1-fast-reasoning",
|
|
3242
|
+
// 1,454ms
|
|
3243
|
+
"deepseek/deepseek-reasoner"
|
|
3244
|
+
// 1,454ms
|
|
3245
|
+
]
|
|
3246
|
+
}
|
|
3247
|
+
},
|
|
3248
|
+
// Time-windowed promotions — auto-applied when active, ignored when expired
|
|
3249
|
+
promotions: [
|
|
3250
|
+
{
|
|
3251
|
+
name: "GLM-5.1 Launch Promo ($0.001 flat)",
|
|
3252
|
+
startDate: "2026-04-01",
|
|
3253
|
+
endDate: "2026-05-01",
|
|
3254
|
+
tierOverrides: {
|
|
3255
|
+
SIMPLE: { primary: "zai/glm-5.1" }
|
|
3256
|
+
},
|
|
3257
|
+
profiles: ["auto"]
|
|
3258
|
+
// only auto profile — eco stays free, premium stays premium
|
|
3259
|
+
}
|
|
3260
|
+
],
|
|
3261
|
+
overrides: {
|
|
3262
|
+
maxTokensForceComplex: 1e5,
|
|
3263
|
+
structuredOutputMinTier: "MEDIUM",
|
|
3264
|
+
ambiguousDefaultTier: "MEDIUM"
|
|
3265
|
+
// agenticMode left undefined → auto-detect via tools/agenticScore.
|
|
3266
|
+
// Set to `true` to force agentic tiers; `false` to disable them entirely.
|
|
3267
|
+
}
|
|
3268
|
+
};
|
|
3269
|
+
registerStrategy(new PortfolioStrategy());
|
|
3270
|
+
function route(prompt, systemPrompt, maxOutputTokens, options) {
|
|
3271
|
+
const strategy = getStrategy(options.config.strategy ?? "portfolio");
|
|
3272
|
+
return strategy.route(prompt, systemPrompt, maxOutputTokens, options);
|
|
3273
|
+
}
|
|
3274
|
+
|
|
3275
|
+
// src/router-adapter.ts
|
|
3276
|
+
var AUTO_ROUTING_PROFILES = {
|
|
3277
|
+
"blockrun/auto": "auto",
|
|
3278
|
+
"blockrun/eco": "eco",
|
|
3279
|
+
"blockrun/premium": "premium"
|
|
3280
|
+
};
|
|
3281
|
+
var BASE_MINIMUM_PAYMENT_USD = 2e-3;
|
|
3282
|
+
var SOLANA_MINIMUM_PAYMENT_USD = 1e-3;
|
|
3283
|
+
function isTransientError(err) {
|
|
3284
|
+
if (err instanceof PaymentError) return false;
|
|
3285
|
+
if (err instanceof APIError) {
|
|
3286
|
+
return [429, 502, 503, 504, 522, 524].includes(err.statusCode);
|
|
3287
|
+
}
|
|
3288
|
+
if (err instanceof Error) {
|
|
3289
|
+
if (err.name === "AbortError") return true;
|
|
3290
|
+
if (err.name === "TypeError" && /fetch|network/i.test(err.message)) return true;
|
|
3291
|
+
}
|
|
3292
|
+
return false;
|
|
3293
|
+
}
|
|
3294
|
+
function errSummary(err) {
|
|
3295
|
+
if (err instanceof APIError) return `APIError ${err.statusCode}`;
|
|
3296
|
+
if (err instanceof Error) {
|
|
3297
|
+
const msg = err.message.length > 80 ? err.message.slice(0, 80) : err.message;
|
|
3298
|
+
return `${err.name}: ${msg}`;
|
|
3299
|
+
}
|
|
3300
|
+
return String(err).slice(0, 100);
|
|
3301
|
+
}
|
|
3302
|
+
function routingProfileForModel(model) {
|
|
3303
|
+
return AUTO_ROUTING_PROFILES[model.toLowerCase()];
|
|
3304
|
+
}
|
|
3305
|
+
function routingText(messages) {
|
|
3306
|
+
const systemPrompt = messages.filter((message) => message.role === "system" && typeof message.content === "string").map((message) => message.content).join("\n") || void 0;
|
|
3307
|
+
const lastUser = [...messages].reverse().find((message) => message.role === "user" && typeof message.content === "string");
|
|
3308
|
+
const lastText = [...messages].reverse().find((message) => typeof message.content === "string");
|
|
3309
|
+
let conversationChars = 0;
|
|
3310
|
+
let hasVision = false;
|
|
3311
|
+
for (const message of messages) {
|
|
3312
|
+
if (typeof message.content === "string") {
|
|
3313
|
+
conversationChars += message.content.length;
|
|
3314
|
+
} else if (Array.isArray(message.content)) {
|
|
3315
|
+
for (const part of message.content) {
|
|
3316
|
+
if (part?.type === "image_url" || part?.type === "image") hasVision = true;
|
|
3317
|
+
if (typeof part?.text === "string") conversationChars += part.text.length;
|
|
3318
|
+
}
|
|
3319
|
+
}
|
|
3320
|
+
}
|
|
3321
|
+
return {
|
|
3322
|
+
prompt: lastUser?.content ?? lastText?.content ?? "",
|
|
3323
|
+
systemPrompt,
|
|
3324
|
+
conversationChars,
|
|
3325
|
+
hasVision
|
|
3326
|
+
};
|
|
3327
|
+
}
|
|
3328
|
+
function routeWithCatalog(prompt, systemPrompt, maxOutputTokens, modelPricing, options = {}) {
|
|
3329
|
+
const tools = options.tools ?? [];
|
|
3330
|
+
const requiresTools = options.toolChoice === "none" ? false : options.toolChoice === "required" || typeof options.toolChoice === "object" ? true : void 0;
|
|
3331
|
+
const decision = route(prompt, systemPrompt, maxOutputTokens, {
|
|
3332
|
+
config: DEFAULT_ROUTING_CONFIG,
|
|
3333
|
+
modelPricing,
|
|
3334
|
+
routingProfile: options.routingProfile,
|
|
3335
|
+
hasTools: tools.length > 0,
|
|
3336
|
+
toolCount: tools.length,
|
|
3337
|
+
toolNames: tools.map((tool) => tool.function.name),
|
|
3338
|
+
requiresTools,
|
|
3339
|
+
hasVision: options.hasVision,
|
|
3340
|
+
requiresStructuredOutput: options.requiresStructuredOutput
|
|
3341
|
+
});
|
|
3342
|
+
const tierConfigs = decision.tierConfigs ?? DEFAULT_ROUTING_CONFIG.tiers;
|
|
3343
|
+
const ranked = decision.candidates?.length ? decision.candidates : [decision.model, ...getFallbackChain(decision.tier, tierConfigs)];
|
|
3344
|
+
const callable = [];
|
|
3345
|
+
for (const id of ranked) {
|
|
3346
|
+
const resolved = !id.startsWith("free/") ? id : modelPricing.has(`nvidia/${id.slice(5)}`) ? `nvidia/${id.slice(5)}` : null;
|
|
3347
|
+
if (resolved && !callable.includes(resolved)) callable.push(resolved);
|
|
3348
|
+
}
|
|
3349
|
+
const estimatedInputTokens = Math.ceil(
|
|
3350
|
+
Math.max(options.conversationChars ?? 0, `${systemPrompt ?? ""} ${prompt}`.length) / 4
|
|
3351
|
+
);
|
|
3352
|
+
const fitting = filterCandidatesByCapacity(
|
|
3353
|
+
callable,
|
|
3354
|
+
estimatedInputTokens,
|
|
3355
|
+
maxOutputTokens,
|
|
3356
|
+
(id) => {
|
|
3357
|
+
const caps = DEFAULT_MODEL_CAPABILITIES[id];
|
|
3358
|
+
return caps ? { contextWindow: caps.contextWindow, maxOutput: caps.maxOutputTokens } : void 0;
|
|
3359
|
+
}
|
|
3360
|
+
);
|
|
3361
|
+
const availableCandidates = fitting.length > 0 ? fitting : callable;
|
|
3362
|
+
const model = availableCandidates[0] ?? decision.model;
|
|
3363
|
+
const costs = calculateModelCost(
|
|
3364
|
+
model,
|
|
3365
|
+
modelPricing,
|
|
3366
|
+
estimatedInputTokens,
|
|
3367
|
+
maxOutputTokens,
|
|
3368
|
+
options.routingProfile
|
|
3369
|
+
);
|
|
3370
|
+
const minimumPaymentUsd = options.minimumPaymentUsd ?? SOLANA_MINIMUM_PAYMENT_USD;
|
|
3371
|
+
const entry = modelPricing.get(model);
|
|
3372
|
+
const isFree = entry !== void 0 && entry.inputPrice === 0 && entry.outputPrice === 0 && !entry.flatPrice;
|
|
3373
|
+
const costEstimate = isFree ? 0 : Math.max(costs.costEstimate, minimumPaymentUsd);
|
|
3374
|
+
const savings = options.routingProfile === "premium" || costs.baselineCost <= 0 ? 0 : entry !== void 0 ? Math.max(0, (costs.baselineCost - costEstimate) / costs.baselineCost) : decision.savings;
|
|
3375
|
+
return {
|
|
3376
|
+
...decision,
|
|
3377
|
+
...costs,
|
|
3378
|
+
costEstimate,
|
|
3379
|
+
savings,
|
|
3380
|
+
model,
|
|
3381
|
+
reasoning: model === decision.model ? decision.reasoning : `${decision.reasoning} | catalog fallback: ${model}`,
|
|
3382
|
+
candidates: availableCandidates,
|
|
3383
|
+
candidateScores: decision.candidateScores?.filter(
|
|
3384
|
+
(score) => availableCandidates.includes(score.model)
|
|
3385
|
+
),
|
|
3386
|
+
fallbacks: availableCandidates.slice(1)
|
|
3387
|
+
};
|
|
3388
|
+
}
|
|
3389
|
+
|
|
34
3390
|
// src/x402.ts
|
|
35
3391
|
import { signTypedData } from "viem/accounts";
|
|
36
3392
|
|
|
@@ -494,29 +3850,10 @@ function getCostSummary() {
|
|
|
494
3850
|
}
|
|
495
3851
|
|
|
496
3852
|
// src/version.ts
|
|
497
|
-
var SDK_VERSION = "3.
|
|
3853
|
+
var SDK_VERSION = "3.12.0";
|
|
498
3854
|
var USER_AGENT = `blockrun-ts/${SDK_VERSION}`;
|
|
499
3855
|
|
|
500
3856
|
// src/client.ts
|
|
501
|
-
function isTransientError(err) {
|
|
502
|
-
if (err instanceof PaymentError) return false;
|
|
503
|
-
if (err instanceof APIError) {
|
|
504
|
-
return [502, 503, 504, 522, 524].includes(err.statusCode);
|
|
505
|
-
}
|
|
506
|
-
if (err instanceof Error) {
|
|
507
|
-
if (err.name === "AbortError") return true;
|
|
508
|
-
if (err.name === "TypeError" && /fetch|network/i.test(err.message)) return true;
|
|
509
|
-
}
|
|
510
|
-
return false;
|
|
511
|
-
}
|
|
512
|
-
function errSummary(err) {
|
|
513
|
-
if (err instanceof APIError) return `APIError ${err.statusCode}`;
|
|
514
|
-
if (err instanceof Error) {
|
|
515
|
-
const msg = err.message.length > 80 ? err.message.slice(0, 80) : err.message;
|
|
516
|
-
return `${err.name}: ${msg}`;
|
|
517
|
-
}
|
|
518
|
-
return String(err).slice(0, 100);
|
|
519
|
-
}
|
|
520
3857
|
function mapRawToModel(m) {
|
|
521
3858
|
return {
|
|
522
3859
|
id: m.id,
|
|
@@ -571,7 +3908,7 @@ var LLMClient = class _LLMClient {
|
|
|
571
3908
|
modelPricingPromise = null;
|
|
572
3909
|
// Pre-auth cache: avoids the 402 round-trip on repeat requests to the same model.
|
|
573
3910
|
// Key = "endpoint:model", value = cached payment header + timestamp.
|
|
574
|
-
// TTL: 1 hour
|
|
3911
|
+
// TTL: 1 hour — pre-auth quotes are stable server-side on that horizon.
|
|
575
3912
|
preAuthCache = /* @__PURE__ */ new Map();
|
|
576
3913
|
static PRE_AUTH_TTL_MS = 36e5;
|
|
577
3914
|
/**
|
|
@@ -625,11 +3962,38 @@ var LLMClient = class _LLMClient {
|
|
|
625
3962
|
});
|
|
626
3963
|
return result.choices[0].message.content || "";
|
|
627
3964
|
}
|
|
3965
|
+
async makeRoutingDecision(prompt, systemPrompt, maxOutputTokens, options = {}) {
|
|
3966
|
+
return routeWithCatalog(
|
|
3967
|
+
prompt,
|
|
3968
|
+
systemPrompt,
|
|
3969
|
+
maxOutputTokens,
|
|
3970
|
+
await this.getModelPricing(),
|
|
3971
|
+
{ ...options, minimumPaymentUsd: BASE_MINIMUM_PAYMENT_USD }
|
|
3972
|
+
);
|
|
3973
|
+
}
|
|
3974
|
+
/**
|
|
3975
|
+
* Inspect a local routing decision without making or paying for a model call.
|
|
3976
|
+
* The first invocation may fetch the public model catalog for current prices.
|
|
3977
|
+
*/
|
|
3978
|
+
async route(prompt, options) {
|
|
3979
|
+
return this.makeRoutingDecision(
|
|
3980
|
+
prompt,
|
|
3981
|
+
options?.system,
|
|
3982
|
+
options?.maxOutputTokens ?? options?.maxTokens ?? DEFAULT_MAX_TOKENS,
|
|
3983
|
+
{
|
|
3984
|
+
routingProfile: options?.routingProfile,
|
|
3985
|
+
requiresStructuredOutput: options?.responseFormat !== void 0
|
|
3986
|
+
}
|
|
3987
|
+
);
|
|
3988
|
+
}
|
|
628
3989
|
/**
|
|
629
3990
|
* Smart chat with automatic model routing.
|
|
630
3991
|
*
|
|
631
|
-
* Uses
|
|
632
|
-
*
|
|
3992
|
+
* Uses BlockRun's product-neutral Router Core portfolio strategy: it
|
|
3993
|
+
* classifies the task shape locally (no
|
|
3994
|
+
* extra model call), enforces capability constraints as hard filters, and
|
|
3995
|
+
* ranks an ordered candidate portfolio — the cheapest model that can handle
|
|
3996
|
+
* the request wins, and the rest become the transient-error fallback chain.
|
|
633
3997
|
*
|
|
634
3998
|
* @param prompt - User message
|
|
635
3999
|
* @param options - Optional chat and routing parameters
|
|
@@ -639,7 +4003,8 @@ var LLMClient = class _LLMClient {
|
|
|
639
4003
|
* ```ts
|
|
640
4004
|
* const result = await client.smartChat('What is 2+2?');
|
|
641
4005
|
* console.log(result.response); // '4'
|
|
642
|
-
* console.log(result.model); // 'google/gemini-
|
|
4006
|
+
* console.log(result.model); // 'google/gemini-3.5-flash'
|
|
4007
|
+
* console.log(result.routing.method); // 'portfolio'
|
|
643
4008
|
* console.log(result.routing.savings); // 0.78 (78% savings)
|
|
644
4009
|
* ```
|
|
645
4010
|
*
|
|
@@ -653,28 +4018,7 @@ var LLMClient = class _LLMClient {
|
|
|
653
4018
|
* ```
|
|
654
4019
|
*/
|
|
655
4020
|
async smartChat(prompt, options) {
|
|
656
|
-
const
|
|
657
|
-
const maxOutputTokens = options?.maxOutputTokens || options?.maxTokens || 1024;
|
|
658
|
-
let route;
|
|
659
|
-
let DEFAULT_ROUTING_CONFIG;
|
|
660
|
-
let getFallbackChain;
|
|
661
|
-
try {
|
|
662
|
-
({ route, DEFAULT_ROUTING_CONFIG, getFallbackChain } = await import("@blockrun/clawrouter"));
|
|
663
|
-
} catch (err) {
|
|
664
|
-
throw new Error(
|
|
665
|
-
`smartChat() requires the optional '@blockrun/clawrouter' routing engine, which is not installed or failed to load. Install it, or call chat() with an explicit model instead. Cause: ${err.message}`
|
|
666
|
-
);
|
|
667
|
-
}
|
|
668
|
-
const decision = route(prompt, options?.system, maxOutputTokens, {
|
|
669
|
-
config: DEFAULT_ROUTING_CONFIG,
|
|
670
|
-
modelPricing,
|
|
671
|
-
routingProfile: options?.routingProfile
|
|
672
|
-
});
|
|
673
|
-
const tierConfigs = decision.tierConfigs ?? DEFAULT_ROUTING_CONFIG.tiers;
|
|
674
|
-
const fullChain = getFallbackChain(decision.tier, tierConfigs);
|
|
675
|
-
const fallbacks = fullChain.filter(
|
|
676
|
-
(id) => id !== decision.model && modelPricing.has(id)
|
|
677
|
-
);
|
|
4021
|
+
const decision = await this.route(prompt, options);
|
|
678
4022
|
const response = await this.chat(decision.model, prompt, {
|
|
679
4023
|
system: options?.system,
|
|
680
4024
|
maxTokens: options?.maxTokens,
|
|
@@ -684,14 +4028,47 @@ var LLMClient = class _LLMClient {
|
|
|
684
4028
|
searchParameters: options?.searchParameters,
|
|
685
4029
|
responseFormat: options?.responseFormat,
|
|
686
4030
|
stop: options?.stop,
|
|
687
|
-
|
|
4031
|
+
// An explicit caller-supplied chain wins over the routed one.
|
|
4032
|
+
fallbackModels: options?.fallbackModels ?? decision.fallbacks
|
|
688
4033
|
});
|
|
689
4034
|
return {
|
|
690
4035
|
response,
|
|
691
4036
|
model: decision.model,
|
|
692
|
-
routing:
|
|
4037
|
+
routing: decision
|
|
693
4038
|
};
|
|
694
4039
|
}
|
|
4040
|
+
/** Route a full Agent/tool conversation while preserving its complete response. */
|
|
4041
|
+
async smartChatCompletion(messages, options = {}) {
|
|
4042
|
+
const { prompt, systemPrompt, conversationChars, hasVision } = routingText(messages);
|
|
4043
|
+
const decision = await this.makeRoutingDecision(
|
|
4044
|
+
prompt,
|
|
4045
|
+
systemPrompt,
|
|
4046
|
+
options.maxOutputTokens ?? options.maxTokens ?? DEFAULT_MAX_TOKENS,
|
|
4047
|
+
{
|
|
4048
|
+
routingProfile: options.routingProfile,
|
|
4049
|
+
requiresStructuredOutput: options.responseFormat !== void 0,
|
|
4050
|
+
tools: options.tools,
|
|
4051
|
+
toolChoice: options.toolChoice,
|
|
4052
|
+
conversationChars,
|
|
4053
|
+
hasVision
|
|
4054
|
+
}
|
|
4055
|
+
);
|
|
4056
|
+
const response = await this.chatCompletion(decision.model, messages, {
|
|
4057
|
+
maxTokens: options.maxTokens,
|
|
4058
|
+
temperature: options.temperature,
|
|
4059
|
+
topP: options.topP,
|
|
4060
|
+
search: options.search,
|
|
4061
|
+
searchParameters: options.searchParameters,
|
|
4062
|
+
tools: options.tools,
|
|
4063
|
+
toolChoice: options.toolChoice,
|
|
4064
|
+
responseFormat: options.responseFormat,
|
|
4065
|
+
stop: options.stop,
|
|
4066
|
+
// An explicit caller-supplied chain wins over the routed one.
|
|
4067
|
+
fallbackModels: options.fallbackModels ?? decision.fallbacks
|
|
4068
|
+
});
|
|
4069
|
+
response.routing = decision;
|
|
4070
|
+
return { response, model: decision.model, routing: decision };
|
|
4071
|
+
}
|
|
695
4072
|
/**
|
|
696
4073
|
* Get model pricing map (cached).
|
|
697
4074
|
* Fetches from API on first call, then returns cached result.
|
|
@@ -711,31 +4088,18 @@ var LLMClient = class _LLMClient {
|
|
|
711
4088
|
this.modelPricingPromise = null;
|
|
712
4089
|
}
|
|
713
4090
|
}
|
|
714
|
-
/**
|
|
715
|
-
* Fetch model pricing from API.
|
|
716
|
-
*
|
|
717
|
-
* For flat-billed models (e.g. ZAI GLM-5 family at $0.001/call) the
|
|
718
|
-
* router still expects per-token rates, so we synthesise an equivalent
|
|
719
|
-
* per-token price assuming ~1500 total tokens per call. Without this,
|
|
720
|
-
* flat models would resolve to inputPrice=outputPrice=0 and the router
|
|
721
|
-
* would treat them as free, biasing routing decisions and reporting
|
|
722
|
-
* inflated savings %.
|
|
723
|
-
*/
|
|
4091
|
+
/** Fetch model pricing from the live catalog, preserving flat billing. */
|
|
724
4092
|
async fetchModelPricing() {
|
|
725
4093
|
const models = await this.listModels();
|
|
726
4094
|
const pricing = /* @__PURE__ */ new Map();
|
|
727
4095
|
for (const model of models) {
|
|
728
|
-
if (model.
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
});
|
|
4096
|
+
if (model.available === false) continue;
|
|
4097
|
+
const inputPrice = Number.isFinite(model.inputPrice) ? model.inputPrice : 0;
|
|
4098
|
+
const outputPrice = Number.isFinite(model.outputPrice) ? model.outputPrice : 0;
|
|
4099
|
+
if (model.billingMode === "flat" && Number.isFinite(model.flatPrice) && model.flatPrice > 0) {
|
|
4100
|
+
pricing.set(model.id, { inputPrice, outputPrice, flatPrice: model.flatPrice });
|
|
734
4101
|
} else {
|
|
735
|
-
pricing.set(model.id, {
|
|
736
|
-
inputPrice: model.inputPrice,
|
|
737
|
-
outputPrice: model.outputPrice
|
|
738
|
-
});
|
|
4102
|
+
pricing.set(model.id, { inputPrice, outputPrice });
|
|
739
4103
|
}
|
|
740
4104
|
}
|
|
741
4105
|
return pricing;
|
|
@@ -755,6 +4119,13 @@ var LLMClient = class _LLMClient {
|
|
|
755
4119
|
* @returns ChatResponse object with choices and usage
|
|
756
4120
|
*/
|
|
757
4121
|
async chatCompletion(model, messages, options) {
|
|
4122
|
+
const routingProfile = routingProfileForModel(model);
|
|
4123
|
+
if (routingProfile) {
|
|
4124
|
+
return (await this.smartChatCompletion(messages, {
|
|
4125
|
+
...options,
|
|
4126
|
+
routingProfile
|
|
4127
|
+
})).response;
|
|
4128
|
+
}
|
|
758
4129
|
validateMaxTokens(options?.maxTokens);
|
|
759
4130
|
const buildBody = (m) => {
|
|
760
4131
|
const body = {
|
|
@@ -1027,9 +4398,28 @@ var LLMClient = class _LLMClient {
|
|
|
1027
4398
|
*/
|
|
1028
4399
|
async chatCompletionStream(model, messages, options) {
|
|
1029
4400
|
validateMaxTokens(options?.maxTokens);
|
|
4401
|
+
let requestModel = model;
|
|
4402
|
+
const routingProfile = routingProfileForModel(model);
|
|
4403
|
+
if (routingProfile) {
|
|
4404
|
+
const { prompt, systemPrompt, conversationChars, hasVision } = routingText(messages);
|
|
4405
|
+
const decision = await this.makeRoutingDecision(
|
|
4406
|
+
prompt,
|
|
4407
|
+
systemPrompt,
|
|
4408
|
+
options?.maxTokens ?? DEFAULT_MAX_TOKENS,
|
|
4409
|
+
{
|
|
4410
|
+
routingProfile,
|
|
4411
|
+
requiresStructuredOutput: options?.responseFormat !== void 0,
|
|
4412
|
+
tools: options?.tools,
|
|
4413
|
+
toolChoice: options?.toolChoice,
|
|
4414
|
+
conversationChars,
|
|
4415
|
+
hasVision
|
|
4416
|
+
}
|
|
4417
|
+
);
|
|
4418
|
+
requestModel = decision.model;
|
|
4419
|
+
}
|
|
1030
4420
|
const url = `${this.apiUrl}/v1/chat/completions`;
|
|
1031
4421
|
const body = {
|
|
1032
|
-
model,
|
|
4422
|
+
model: requestModel,
|
|
1033
4423
|
messages,
|
|
1034
4424
|
max_tokens: options?.maxTokens ?? DEFAULT_MAX_TOKENS,
|
|
1035
4425
|
stream: true
|
|
@@ -1040,7 +4430,7 @@ var LLMClient = class _LLMClient {
|
|
|
1040
4430
|
if (options?.toolChoice !== void 0) body.tool_choice = options.toolChoice;
|
|
1041
4431
|
if (options?.responseFormat !== void 0) body.response_format = options.responseFormat;
|
|
1042
4432
|
if (options?.stop !== void 0) body.stop = options.stop;
|
|
1043
|
-
const cacheKey2 = `/v1/chat/completions:${
|
|
4433
|
+
const cacheKey2 = `/v1/chat/completions:${requestModel}`;
|
|
1044
4434
|
const cached = this.preAuthCache.get(cacheKey2);
|
|
1045
4435
|
const now = Date.now();
|
|
1046
4436
|
if (cached && now - cached.cachedAt < _LLMClient.PRE_AUTH_TTL_MS) {
|
|
@@ -1650,7 +5040,13 @@ var LLMClient = class _LLMClient {
|
|
|
1650
5040
|
*/
|
|
1651
5041
|
async getBalance() {
|
|
1652
5042
|
const usdcContract = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913";
|
|
1653
|
-
const
|
|
5043
|
+
const configuredRpc = typeof process !== "undefined" && process.env ? process.env.BASE_RPC_URL : void 0;
|
|
5044
|
+
const rpcs = [
|
|
5045
|
+
configuredRpc,
|
|
5046
|
+
"https://base-rpc.publicnode.com",
|
|
5047
|
+
"https://mainnet.base.org",
|
|
5048
|
+
"https://base.llamarpc.com"
|
|
5049
|
+
].filter((rpc) => Boolean(rpc));
|
|
1654
5050
|
const selector = "0x70a08231";
|
|
1655
5051
|
const paddedAddress = this.account.address.slice(2).toLowerCase().padStart(64, "0");
|
|
1656
5052
|
const data = selector + paddedAddress;
|
|
@@ -1668,7 +5064,9 @@ var LLMClient = class _LLMClient {
|
|
|
1668
5064
|
headers: { "Content-Type": "application/json" },
|
|
1669
5065
|
body: JSON.stringify(payload)
|
|
1670
5066
|
});
|
|
5067
|
+
if (!response.ok) throw new Error(`Base RPC returned ${response.status}`);
|
|
1671
5068
|
const result = await response.json();
|
|
5069
|
+
if (!result.result || result.error) throw new Error("Base RPC returned no balance result");
|
|
1672
5070
|
const balanceRaw = parseInt(result.result || "0x0", 16);
|
|
1673
5071
|
return balanceRaw / 1e6;
|
|
1674
5072
|
} catch (e) {
|
|
@@ -5106,6 +8504,8 @@ var SolanaLLMClient = class {
|
|
|
5106
8504
|
sessionTotalUsd = 0;
|
|
5107
8505
|
sessionCalls = 0;
|
|
5108
8506
|
addressCache = null;
|
|
8507
|
+
modelPricingCache = null;
|
|
8508
|
+
modelPricingPromise = null;
|
|
5109
8509
|
constructor(options = {}) {
|
|
5110
8510
|
const envKey = typeof process !== "undefined" && process.env ? process.env.SOLANA_WALLET_KEY : void 0;
|
|
5111
8511
|
const privateKey = options.privateKey || envKey;
|
|
@@ -5140,25 +8540,141 @@ var SolanaLLMClient = class {
|
|
|
5140
8540
|
temperature: options?.temperature,
|
|
5141
8541
|
topP: options?.topP,
|
|
5142
8542
|
search: options?.search,
|
|
5143
|
-
searchParameters: options?.searchParameters
|
|
8543
|
+
searchParameters: options?.searchParameters,
|
|
8544
|
+
responseFormat: options?.responseFormat,
|
|
8545
|
+
stop: options?.stop,
|
|
8546
|
+
fallbackModels: options?.fallbackModels
|
|
5144
8547
|
});
|
|
5145
8548
|
return result.choices[0].message.content || "";
|
|
5146
8549
|
}
|
|
5147
8550
|
/** Full chat completion (OpenAI-compatible). */
|
|
5148
8551
|
async chatCompletion(model, messages, options) {
|
|
8552
|
+
const routingProfile = routingProfileForModel(model);
|
|
8553
|
+
if (routingProfile) {
|
|
8554
|
+
return (await this.smartChatCompletion(messages, {
|
|
8555
|
+
...options,
|
|
8556
|
+
routingProfile
|
|
8557
|
+
})).response;
|
|
8558
|
+
}
|
|
5149
8559
|
validateMaxTokens(options?.maxTokens);
|
|
5150
|
-
const
|
|
5151
|
-
|
|
5152
|
-
|
|
5153
|
-
|
|
8560
|
+
const buildBody = (candidate) => {
|
|
8561
|
+
const body = {
|
|
8562
|
+
model: candidate,
|
|
8563
|
+
messages,
|
|
8564
|
+
max_tokens: options?.maxTokens || DEFAULT_MAX_TOKENS2
|
|
8565
|
+
};
|
|
8566
|
+
if (options?.temperature !== void 0) body.temperature = options.temperature;
|
|
8567
|
+
if (options?.topP !== void 0) body.top_p = options.topP;
|
|
8568
|
+
if (options?.searchParameters !== void 0) body.search_parameters = options.searchParameters;
|
|
8569
|
+
else if (options?.search === true) body.search_parameters = { mode: "on" };
|
|
8570
|
+
if (options?.tools !== void 0) body.tools = options.tools;
|
|
8571
|
+
if (options?.toolChoice !== void 0) body.tool_choice = options.toolChoice;
|
|
8572
|
+
if (options?.responseFormat !== void 0) body.response_format = options.responseFormat;
|
|
8573
|
+
if (options?.stop !== void 0) body.stop = options.stop;
|
|
8574
|
+
return body;
|
|
5154
8575
|
};
|
|
5155
|
-
|
|
5156
|
-
|
|
5157
|
-
|
|
5158
|
-
|
|
5159
|
-
|
|
5160
|
-
|
|
5161
|
-
|
|
8576
|
+
const chain = [model, ...options?.fallbackModels ?? []];
|
|
8577
|
+
let lastError;
|
|
8578
|
+
for (let index = 0; index < chain.length; index += 1) {
|
|
8579
|
+
const candidate = chain[index];
|
|
8580
|
+
try {
|
|
8581
|
+
return await this.requestWithPayment("/v1/chat/completions", buildBody(candidate));
|
|
8582
|
+
} catch (error) {
|
|
8583
|
+
lastError = error;
|
|
8584
|
+
if (!isTransientError(error) || index === chain.length - 1) throw error;
|
|
8585
|
+
console.error(`[@blockrun/llm] ${candidate} -> ${chain[index + 1]} (${errSummary(error)})`);
|
|
8586
|
+
}
|
|
8587
|
+
}
|
|
8588
|
+
throw lastError;
|
|
8589
|
+
}
|
|
8590
|
+
async getModelPricing() {
|
|
8591
|
+
if (this.modelPricingCache) return this.modelPricingCache;
|
|
8592
|
+
if (this.modelPricingPromise) return this.modelPricingPromise;
|
|
8593
|
+
this.modelPricingPromise = (async () => {
|
|
8594
|
+
const models = await this.listModels();
|
|
8595
|
+
const pricing = /* @__PURE__ */ new Map();
|
|
8596
|
+
for (const model of models) {
|
|
8597
|
+
const raw = model;
|
|
8598
|
+
if (model.available === false) continue;
|
|
8599
|
+
const num = (value) => {
|
|
8600
|
+
const n = Number(value ?? 0);
|
|
8601
|
+
return Number.isFinite(n) ? n : 0;
|
|
8602
|
+
};
|
|
8603
|
+
const inputPrice = num(model.inputPrice ?? raw.input_price ?? raw.pricing?.input);
|
|
8604
|
+
const outputPrice = num(model.outputPrice ?? raw.output_price ?? raw.pricing?.output);
|
|
8605
|
+
const flatPrice = num(model.flatPrice ?? raw.flat_price ?? raw.pricing?.flat);
|
|
8606
|
+
pricing.set(model.id, {
|
|
8607
|
+
inputPrice,
|
|
8608
|
+
outputPrice,
|
|
8609
|
+
...(model.billingMode ?? raw.billing_mode) === "flat" && flatPrice > 0 ? { flatPrice } : {}
|
|
8610
|
+
});
|
|
8611
|
+
}
|
|
8612
|
+
return pricing;
|
|
8613
|
+
})();
|
|
8614
|
+
try {
|
|
8615
|
+
this.modelPricingCache = await this.modelPricingPromise;
|
|
8616
|
+
return this.modelPricingCache;
|
|
8617
|
+
} finally {
|
|
8618
|
+
this.modelPricingPromise = null;
|
|
8619
|
+
}
|
|
8620
|
+
}
|
|
8621
|
+
/** Inspect a Solana route without making or paying for a model call. */
|
|
8622
|
+
async route(prompt, options) {
|
|
8623
|
+
return routeWithCatalog(
|
|
8624
|
+
prompt,
|
|
8625
|
+
options?.system,
|
|
8626
|
+
options?.maxOutputTokens ?? options?.maxTokens ?? DEFAULT_MAX_TOKENS2,
|
|
8627
|
+
await this.getModelPricing(),
|
|
8628
|
+
{
|
|
8629
|
+
routingProfile: options?.routingProfile,
|
|
8630
|
+
requiresStructuredOutput: options?.responseFormat !== void 0,
|
|
8631
|
+
minimumPaymentUsd: SOLANA_MINIMUM_PAYMENT_USD
|
|
8632
|
+
}
|
|
8633
|
+
);
|
|
8634
|
+
}
|
|
8635
|
+
/** Smart one-line chat paid on Solana. */
|
|
8636
|
+
async smartChat(prompt, options) {
|
|
8637
|
+
const decision = await this.route(prompt, options);
|
|
8638
|
+
const response = await this.chat(decision.model, prompt, {
|
|
8639
|
+
...options,
|
|
8640
|
+
// An explicit caller-supplied chain wins over the routed one.
|
|
8641
|
+
fallbackModels: options?.fallbackModels ?? decision.fallbacks
|
|
8642
|
+
});
|
|
8643
|
+
return { response, model: decision.model, routing: decision };
|
|
8644
|
+
}
|
|
8645
|
+
/** Smart full message/tool completion paid on Solana. */
|
|
8646
|
+
async smartChatCompletion(messages, options = {}) {
|
|
8647
|
+
const { prompt, systemPrompt, conversationChars, hasVision } = routingText(messages);
|
|
8648
|
+
const decision = routeWithCatalog(
|
|
8649
|
+
prompt,
|
|
8650
|
+
systemPrompt,
|
|
8651
|
+
options.maxOutputTokens ?? options.maxTokens ?? DEFAULT_MAX_TOKENS2,
|
|
8652
|
+
await this.getModelPricing(),
|
|
8653
|
+
{
|
|
8654
|
+
routingProfile: options.routingProfile,
|
|
8655
|
+
requiresStructuredOutput: options.responseFormat !== void 0,
|
|
8656
|
+
tools: options.tools,
|
|
8657
|
+
toolChoice: options.toolChoice,
|
|
8658
|
+
conversationChars,
|
|
8659
|
+
hasVision,
|
|
8660
|
+
minimumPaymentUsd: SOLANA_MINIMUM_PAYMENT_USD
|
|
8661
|
+
}
|
|
8662
|
+
);
|
|
8663
|
+
const response = await this.chatCompletion(decision.model, messages, {
|
|
8664
|
+
maxTokens: options.maxTokens,
|
|
8665
|
+
temperature: options.temperature,
|
|
8666
|
+
topP: options.topP,
|
|
8667
|
+
search: options.search,
|
|
8668
|
+
searchParameters: options.searchParameters,
|
|
8669
|
+
tools: options.tools,
|
|
8670
|
+
toolChoice: options.toolChoice,
|
|
8671
|
+
responseFormat: options.responseFormat,
|
|
8672
|
+
stop: options.stop,
|
|
8673
|
+
// An explicit caller-supplied chain wins over the routed one.
|
|
8674
|
+
fallbackModels: options.fallbackModels ?? decision.fallbacks
|
|
8675
|
+
});
|
|
8676
|
+
response.routing = decision;
|
|
8677
|
+
return { response, model: decision.model, routing: decision };
|
|
5162
8678
|
}
|
|
5163
8679
|
/** List available models. */
|
|
5164
8680
|
async listModels() {
|
|
@@ -6039,7 +9555,8 @@ var ChatCompletions = class {
|
|
|
6039
9555
|
},
|
|
6040
9556
|
finish_reason: choice.finish_reason || "stop"
|
|
6041
9557
|
})),
|
|
6042
|
-
usage: response.usage
|
|
9558
|
+
usage: response.usage,
|
|
9559
|
+
routing: response.routing
|
|
6043
9560
|
};
|
|
6044
9561
|
}
|
|
6045
9562
|
};
|