@blockrun/llm 3.11.0 → 3.13.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 +315 -194
- package/dist/index.cjs +3826 -285
- package/dist/index.d.cts +70 -21
- package/dist/index.d.ts +70 -21
- package/dist/index.js +3826 -285
- package/package.json +3 -7
package/dist/index.cjs
CHANGED
|
@@ -88,7 +88,7 @@ __export(index_exports, {
|
|
|
88
88
|
importSolanaWallet: () => importSolanaWallet,
|
|
89
89
|
importWallet: () => importWallet,
|
|
90
90
|
listDiscoveredSolanaWallets: () => listDiscoveredSolanaWallets,
|
|
91
|
-
listDiscoveredWallets: () =>
|
|
91
|
+
listDiscoveredWallets: () => listDiscoveredWallets2,
|
|
92
92
|
loadSolanaWallet: () => loadSolanaWallet,
|
|
93
93
|
loadWallet: () => loadWallet,
|
|
94
94
|
logCost: () => logCost,
|
|
@@ -97,7 +97,7 @@ __export(index_exports, {
|
|
|
97
97
|
saveToCache: () => saveToCache,
|
|
98
98
|
saveWallet: () => saveWallet,
|
|
99
99
|
scanSolanaWallets: () => scanSolanaWallets,
|
|
100
|
-
scanWallets: () =>
|
|
100
|
+
scanWallets: () => scanWallets2,
|
|
101
101
|
setCache: () => setCache,
|
|
102
102
|
setupAgentSolanaWallet: () => setupAgentSolanaWallet,
|
|
103
103
|
setupAgentWallet: () => setupAgentWallet,
|
|
@@ -145,6 +145,3362 @@ var APIError = class extends BlockrunError {
|
|
|
145
145
|
}
|
|
146
146
|
};
|
|
147
147
|
|
|
148
|
+
// 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
|
|
149
|
+
function scoreTokenCount(estimatedTokens, thresholds) {
|
|
150
|
+
if (estimatedTokens < thresholds.simple) {
|
|
151
|
+
return { name: "tokenCount", score: -1, signal: `short (${estimatedTokens} tokens)` };
|
|
152
|
+
}
|
|
153
|
+
if (estimatedTokens > thresholds.complex) {
|
|
154
|
+
return { name: "tokenCount", score: 1, signal: `long (${estimatedTokens} tokens)` };
|
|
155
|
+
}
|
|
156
|
+
return { name: "tokenCount", score: 0, signal: null };
|
|
157
|
+
}
|
|
158
|
+
function scoreKeywordMatch(text, keywords, name, signalLabel, thresholds, scores) {
|
|
159
|
+
const matches = keywords.filter((kw) => text.includes(kw.toLowerCase()));
|
|
160
|
+
if (matches.length >= thresholds.high) {
|
|
161
|
+
return {
|
|
162
|
+
name,
|
|
163
|
+
score: scores.high,
|
|
164
|
+
signal: `${signalLabel} (${matches.slice(0, 3).join(", ")})`
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
if (matches.length >= thresholds.low) {
|
|
168
|
+
return {
|
|
169
|
+
name,
|
|
170
|
+
score: scores.low,
|
|
171
|
+
signal: `${signalLabel} (${matches.slice(0, 3).join(", ")})`
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
return { name, score: scores.none, signal: null };
|
|
175
|
+
}
|
|
176
|
+
function scoreMultiStep(text) {
|
|
177
|
+
const patterns = [/first.*then/i, /step \d/i, /\d\.\s/];
|
|
178
|
+
const hits = patterns.filter((p) => p.test(text));
|
|
179
|
+
if (hits.length > 0) {
|
|
180
|
+
return { name: "multiStepPatterns", score: 0.5, signal: "multi-step" };
|
|
181
|
+
}
|
|
182
|
+
return { name: "multiStepPatterns", score: 0, signal: null };
|
|
183
|
+
}
|
|
184
|
+
function scoreQuestionComplexity(prompt) {
|
|
185
|
+
const count = (prompt.match(/\?/g) || []).length;
|
|
186
|
+
if (count > 3) {
|
|
187
|
+
return { name: "questionComplexity", score: 0.5, signal: `${count} questions` };
|
|
188
|
+
}
|
|
189
|
+
return { name: "questionComplexity", score: 0, signal: null };
|
|
190
|
+
}
|
|
191
|
+
function scoreAgenticTask(text, keywords) {
|
|
192
|
+
let matchCount = 0;
|
|
193
|
+
const signals = [];
|
|
194
|
+
for (const keyword of keywords) {
|
|
195
|
+
if (text.includes(keyword.toLowerCase())) {
|
|
196
|
+
matchCount++;
|
|
197
|
+
if (signals.length < 3) {
|
|
198
|
+
signals.push(keyword);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
if (matchCount >= 4) {
|
|
203
|
+
return {
|
|
204
|
+
dimensionScore: {
|
|
205
|
+
name: "agenticTask",
|
|
206
|
+
score: 1,
|
|
207
|
+
signal: `agentic (${signals.join(", ")})`
|
|
208
|
+
},
|
|
209
|
+
agenticScore: 1
|
|
210
|
+
};
|
|
211
|
+
} else if (matchCount >= 3) {
|
|
212
|
+
return {
|
|
213
|
+
dimensionScore: {
|
|
214
|
+
name: "agenticTask",
|
|
215
|
+
score: 0.6,
|
|
216
|
+
signal: `agentic (${signals.join(", ")})`
|
|
217
|
+
},
|
|
218
|
+
agenticScore: 0.6
|
|
219
|
+
};
|
|
220
|
+
} else if (matchCount >= 1) {
|
|
221
|
+
return {
|
|
222
|
+
dimensionScore: {
|
|
223
|
+
name: "agenticTask",
|
|
224
|
+
score: 0.2,
|
|
225
|
+
signal: `agentic-light (${signals.join(", ")})`
|
|
226
|
+
},
|
|
227
|
+
agenticScore: 0.2
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
return {
|
|
231
|
+
dimensionScore: { name: "agenticTask", score: 0, signal: null },
|
|
232
|
+
agenticScore: 0
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
function classifyByRules(prompt, systemPrompt, estimatedTokens, config) {
|
|
236
|
+
const userText = prompt.toLowerCase();
|
|
237
|
+
const dimensions = [
|
|
238
|
+
// Token count uses total estimated tokens (system + user) — context size matters for model selection
|
|
239
|
+
scoreTokenCount(estimatedTokens, config.tokenCountThresholds),
|
|
240
|
+
scoreKeywordMatch(
|
|
241
|
+
userText,
|
|
242
|
+
config.codeKeywords,
|
|
243
|
+
"codePresence",
|
|
244
|
+
"code",
|
|
245
|
+
{ low: 1, high: 2 },
|
|
246
|
+
{ none: 0, low: 0.5, high: 1 }
|
|
247
|
+
),
|
|
248
|
+
scoreKeywordMatch(
|
|
249
|
+
userText,
|
|
250
|
+
config.reasoningKeywords,
|
|
251
|
+
"reasoningMarkers",
|
|
252
|
+
"reasoning",
|
|
253
|
+
{ low: 1, high: 2 },
|
|
254
|
+
{ none: 0, low: 0.7, high: 1 }
|
|
255
|
+
),
|
|
256
|
+
scoreKeywordMatch(
|
|
257
|
+
userText,
|
|
258
|
+
config.technicalKeywords,
|
|
259
|
+
"technicalTerms",
|
|
260
|
+
"technical",
|
|
261
|
+
{ low: 2, high: 4 },
|
|
262
|
+
{ none: 0, low: 0.5, high: 1 }
|
|
263
|
+
),
|
|
264
|
+
scoreKeywordMatch(
|
|
265
|
+
userText,
|
|
266
|
+
config.creativeKeywords,
|
|
267
|
+
"creativeMarkers",
|
|
268
|
+
"creative",
|
|
269
|
+
{ low: 1, high: 2 },
|
|
270
|
+
{ none: 0, low: 0.5, high: 0.7 }
|
|
271
|
+
),
|
|
272
|
+
scoreKeywordMatch(
|
|
273
|
+
userText,
|
|
274
|
+
config.simpleKeywords,
|
|
275
|
+
"simpleIndicators",
|
|
276
|
+
"simple",
|
|
277
|
+
{ low: 1, high: 2 },
|
|
278
|
+
{ none: 0, low: -1, high: -1 }
|
|
279
|
+
),
|
|
280
|
+
scoreMultiStep(userText),
|
|
281
|
+
scoreQuestionComplexity(prompt),
|
|
282
|
+
// 6 new dimensions
|
|
283
|
+
scoreKeywordMatch(
|
|
284
|
+
userText,
|
|
285
|
+
config.imperativeVerbs,
|
|
286
|
+
"imperativeVerbs",
|
|
287
|
+
"imperative",
|
|
288
|
+
{ low: 1, high: 2 },
|
|
289
|
+
{ none: 0, low: 0.3, high: 0.5 }
|
|
290
|
+
),
|
|
291
|
+
scoreKeywordMatch(
|
|
292
|
+
userText,
|
|
293
|
+
config.constraintIndicators,
|
|
294
|
+
"constraintCount",
|
|
295
|
+
"constraints",
|
|
296
|
+
{ low: 1, high: 3 },
|
|
297
|
+
{ none: 0, low: 0.3, high: 0.7 }
|
|
298
|
+
),
|
|
299
|
+
scoreKeywordMatch(
|
|
300
|
+
userText,
|
|
301
|
+
config.outputFormatKeywords,
|
|
302
|
+
"outputFormat",
|
|
303
|
+
"format",
|
|
304
|
+
{ low: 1, high: 2 },
|
|
305
|
+
{ none: 0, low: 0.4, high: 0.7 }
|
|
306
|
+
),
|
|
307
|
+
scoreKeywordMatch(
|
|
308
|
+
userText,
|
|
309
|
+
config.referenceKeywords,
|
|
310
|
+
"referenceComplexity",
|
|
311
|
+
"references",
|
|
312
|
+
{ low: 1, high: 2 },
|
|
313
|
+
{ none: 0, low: 0.3, high: 0.5 }
|
|
314
|
+
),
|
|
315
|
+
scoreKeywordMatch(
|
|
316
|
+
userText,
|
|
317
|
+
config.negationKeywords,
|
|
318
|
+
"negationComplexity",
|
|
319
|
+
"negation",
|
|
320
|
+
{ low: 2, high: 3 },
|
|
321
|
+
{ none: 0, low: 0.3, high: 0.5 }
|
|
322
|
+
),
|
|
323
|
+
scoreKeywordMatch(
|
|
324
|
+
userText,
|
|
325
|
+
config.domainSpecificKeywords,
|
|
326
|
+
"domainSpecificity",
|
|
327
|
+
"domain-specific",
|
|
328
|
+
{ low: 1, high: 2 },
|
|
329
|
+
{ none: 0, low: 0.5, high: 0.8 }
|
|
330
|
+
)
|
|
331
|
+
];
|
|
332
|
+
const agenticResult = scoreAgenticTask(userText, config.agenticTaskKeywords);
|
|
333
|
+
dimensions.push(agenticResult.dimensionScore);
|
|
334
|
+
const agenticScore = agenticResult.agenticScore;
|
|
335
|
+
const signals = dimensions.filter((d) => d.signal !== null).map((d) => d.signal);
|
|
336
|
+
const weights = config.dimensionWeights;
|
|
337
|
+
let weightedScore = 0;
|
|
338
|
+
for (const d of dimensions) {
|
|
339
|
+
const w = weights[d.name] ?? 0;
|
|
340
|
+
weightedScore += d.score * w;
|
|
341
|
+
}
|
|
342
|
+
const reasoningMatches = config.reasoningKeywords.filter(
|
|
343
|
+
(kw) => userText.includes(kw.toLowerCase())
|
|
344
|
+
);
|
|
345
|
+
if (reasoningMatches.length >= 2) {
|
|
346
|
+
const confidence2 = calibrateConfidence(
|
|
347
|
+
Math.max(weightedScore, 0.3),
|
|
348
|
+
// ensure positive for confidence calc
|
|
349
|
+
config.confidenceSteepness
|
|
350
|
+
);
|
|
351
|
+
return {
|
|
352
|
+
score: weightedScore,
|
|
353
|
+
tier: "REASONING",
|
|
354
|
+
confidence: Math.max(confidence2, 0.85),
|
|
355
|
+
signals,
|
|
356
|
+
agenticScore,
|
|
357
|
+
dimensions
|
|
358
|
+
};
|
|
359
|
+
}
|
|
360
|
+
const { simpleMedium, mediumComplex, complexReasoning } = config.tierBoundaries;
|
|
361
|
+
let tier;
|
|
362
|
+
let distanceFromBoundary;
|
|
363
|
+
if (weightedScore < simpleMedium) {
|
|
364
|
+
tier = "SIMPLE";
|
|
365
|
+
distanceFromBoundary = simpleMedium - weightedScore;
|
|
366
|
+
} else if (weightedScore < mediumComplex) {
|
|
367
|
+
tier = "MEDIUM";
|
|
368
|
+
distanceFromBoundary = Math.min(weightedScore - simpleMedium, mediumComplex - weightedScore);
|
|
369
|
+
} else if (weightedScore < complexReasoning) {
|
|
370
|
+
tier = "COMPLEX";
|
|
371
|
+
distanceFromBoundary = Math.min(
|
|
372
|
+
weightedScore - mediumComplex,
|
|
373
|
+
complexReasoning - weightedScore
|
|
374
|
+
);
|
|
375
|
+
} else {
|
|
376
|
+
tier = "REASONING";
|
|
377
|
+
distanceFromBoundary = weightedScore - complexReasoning;
|
|
378
|
+
}
|
|
379
|
+
const confidence = calibrateConfidence(distanceFromBoundary, config.confidenceSteepness);
|
|
380
|
+
if (confidence < config.confidenceThreshold) {
|
|
381
|
+
return { score: weightedScore, tier: null, confidence, signals, agenticScore, dimensions };
|
|
382
|
+
}
|
|
383
|
+
return { score: weightedScore, tier, confidence, signals, agenticScore, dimensions };
|
|
384
|
+
}
|
|
385
|
+
function calibrateConfidence(distance, steepness) {
|
|
386
|
+
return 1 / (1 + Math.exp(-steepness * distance));
|
|
387
|
+
}
|
|
388
|
+
var BASELINE_MODEL_ID = "anthropic/claude-opus-4.7";
|
|
389
|
+
var BASELINE_INPUT_PRICE = 5;
|
|
390
|
+
var BASELINE_OUTPUT_PRICE = 25;
|
|
391
|
+
function selectModel(tier, confidence, method, reasoning, tierConfigs, modelPricing, estimatedInputTokens, maxOutputTokens, routingProfile, agenticScore) {
|
|
392
|
+
const tierConfig = tierConfigs[tier];
|
|
393
|
+
const model = tierConfig.primary;
|
|
394
|
+
const pricing = modelPricing.get(model);
|
|
395
|
+
let costEstimate;
|
|
396
|
+
if (pricing?.flatPrice !== void 0) {
|
|
397
|
+
costEstimate = pricing.flatPrice;
|
|
398
|
+
} else {
|
|
399
|
+
const inputPrice = pricing?.inputPrice ?? 0;
|
|
400
|
+
const outputPrice = pricing?.outputPrice ?? 0;
|
|
401
|
+
costEstimate = estimatedInputTokens / 1e6 * inputPrice + maxOutputTokens / 1e6 * outputPrice;
|
|
402
|
+
}
|
|
403
|
+
const opusPricing = modelPricing.get(BASELINE_MODEL_ID);
|
|
404
|
+
const opusInputPrice = opusPricing?.inputPrice ?? BASELINE_INPUT_PRICE;
|
|
405
|
+
const opusOutputPrice = opusPricing?.outputPrice ?? BASELINE_OUTPUT_PRICE;
|
|
406
|
+
const baselineInput = estimatedInputTokens / 1e6 * opusInputPrice;
|
|
407
|
+
const baselineOutput = maxOutputTokens / 1e6 * opusOutputPrice;
|
|
408
|
+
const baselineCost = baselineInput + baselineOutput;
|
|
409
|
+
const savings = routingProfile === "premium" ? 0 : baselineCost > 0 ? Math.max(0, (baselineCost - costEstimate) / baselineCost) : 0;
|
|
410
|
+
return {
|
|
411
|
+
model,
|
|
412
|
+
tier,
|
|
413
|
+
confidence,
|
|
414
|
+
method,
|
|
415
|
+
reasoning,
|
|
416
|
+
costEstimate,
|
|
417
|
+
baselineCost,
|
|
418
|
+
savings,
|
|
419
|
+
...agenticScore !== void 0 && { agenticScore }
|
|
420
|
+
};
|
|
421
|
+
}
|
|
422
|
+
function getFallbackChain(tier, tierConfigs) {
|
|
423
|
+
const config = tierConfigs[tier];
|
|
424
|
+
return [config.primary, ...config.fallback];
|
|
425
|
+
}
|
|
426
|
+
var SERVER_MARGIN_PERCENT = 5;
|
|
427
|
+
var MIN_PAYMENT_USD = 1e-3;
|
|
428
|
+
function calculateModelCost(model, modelPricing, estimatedInputTokens, maxOutputTokens, routingProfile) {
|
|
429
|
+
const pricing = modelPricing.get(model);
|
|
430
|
+
let costEstimate;
|
|
431
|
+
if (pricing?.flatPrice !== void 0) {
|
|
432
|
+
costEstimate = Math.max(pricing.flatPrice * (1 + SERVER_MARGIN_PERCENT / 100), MIN_PAYMENT_USD);
|
|
433
|
+
} else {
|
|
434
|
+
const inputPrice = pricing?.inputPrice ?? 0;
|
|
435
|
+
const outputPrice = pricing?.outputPrice ?? 0;
|
|
436
|
+
const inputCost = estimatedInputTokens / 1e6 * inputPrice;
|
|
437
|
+
const outputCost = maxOutputTokens / 1e6 * outputPrice;
|
|
438
|
+
costEstimate = Math.max(
|
|
439
|
+
(inputCost + outputCost) * (1 + SERVER_MARGIN_PERCENT / 100),
|
|
440
|
+
MIN_PAYMENT_USD
|
|
441
|
+
);
|
|
442
|
+
}
|
|
443
|
+
const opusPricing = modelPricing.get(BASELINE_MODEL_ID);
|
|
444
|
+
const opusInputPrice = opusPricing?.inputPrice ?? BASELINE_INPUT_PRICE;
|
|
445
|
+
const opusOutputPrice = opusPricing?.outputPrice ?? BASELINE_OUTPUT_PRICE;
|
|
446
|
+
const baselineInput = estimatedInputTokens / 1e6 * opusInputPrice;
|
|
447
|
+
const baselineOutput = maxOutputTokens / 1e6 * opusOutputPrice;
|
|
448
|
+
const baselineCost = baselineInput + baselineOutput;
|
|
449
|
+
const savings = routingProfile === "premium" ? 0 : baselineCost > 0 ? Math.max(0, (baselineCost - costEstimate) / baselineCost) : 0;
|
|
450
|
+
return { costEstimate, baselineCost, savings };
|
|
451
|
+
}
|
|
452
|
+
function filterCandidatesByCapacity(models, estimatedInputTokens, requestedOutputTokens, getCapabilities) {
|
|
453
|
+
const filtered = models.filter((modelId) => {
|
|
454
|
+
const capabilities = getCapabilities(modelId);
|
|
455
|
+
if (!capabilities) return true;
|
|
456
|
+
return capabilities.contextWindow >= (estimatedInputTokens + requestedOutputTokens) * 1.1 && capabilities.maxOutput >= requestedOutputTokens;
|
|
457
|
+
});
|
|
458
|
+
return filtered;
|
|
459
|
+
}
|
|
460
|
+
function applyPromotions(tierConfigs, promotions, profile, now = /* @__PURE__ */ new Date()) {
|
|
461
|
+
if (!promotions || promotions.length === 0) return tierConfigs;
|
|
462
|
+
let result = tierConfigs;
|
|
463
|
+
for (const promo of promotions) {
|
|
464
|
+
const start = new Date(promo.startDate);
|
|
465
|
+
const end = new Date(promo.endDate);
|
|
466
|
+
if (now < start || now >= end) continue;
|
|
467
|
+
if (promo.profiles && !promo.profiles.includes(profile)) continue;
|
|
468
|
+
if (result === tierConfigs) {
|
|
469
|
+
result = { ...tierConfigs };
|
|
470
|
+
for (const t of Object.keys(result)) {
|
|
471
|
+
result[t] = { ...result[t] };
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
for (const [tier, override] of Object.entries(promo.tierOverrides)) {
|
|
475
|
+
if (!result[tier]) continue;
|
|
476
|
+
if (override.primary) result[tier].primary = override.primary;
|
|
477
|
+
if (override.fallback) result[tier].fallback = override.fallback;
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
return result;
|
|
481
|
+
}
|
|
482
|
+
var RulesStrategy = class {
|
|
483
|
+
name = "rules";
|
|
484
|
+
route(prompt, systemPrompt, maxOutputTokens, options) {
|
|
485
|
+
const { config, modelPricing } = options;
|
|
486
|
+
const fullText = `${systemPrompt ?? ""} ${prompt}`;
|
|
487
|
+
const estimatedTokens = Math.ceil(fullText.length / 4);
|
|
488
|
+
const scanLimit = Math.max(1, Math.min(8e3, config.classifier.promptTruncationChars));
|
|
489
|
+
const sample = (value) => {
|
|
490
|
+
if (value.length <= scanLimit) return value;
|
|
491
|
+
const prefixLength = Math.ceil(scanLimit / 2);
|
|
492
|
+
return `${value.slice(0, prefixLength)}
|
|
493
|
+
${value.slice(-(scanLimit - prefixLength))}`;
|
|
494
|
+
};
|
|
495
|
+
const scannedPrompt = sample(prompt);
|
|
496
|
+
const scannedSystemPrompt = systemPrompt ? sample(systemPrompt) : void 0;
|
|
497
|
+
const ruleResult = classifyByRules(
|
|
498
|
+
scannedPrompt,
|
|
499
|
+
scannedSystemPrompt,
|
|
500
|
+
estimatedTokens,
|
|
501
|
+
config.scoring
|
|
502
|
+
);
|
|
503
|
+
const { routingProfile } = options;
|
|
504
|
+
let tierConfigs;
|
|
505
|
+
let profileSuffix;
|
|
506
|
+
let profile;
|
|
507
|
+
if (routingProfile === "eco") {
|
|
508
|
+
tierConfigs = config.ecoTiers ?? config.tiers;
|
|
509
|
+
profileSuffix = config.ecoTiers ? " | eco" : " | eco (default tiers)";
|
|
510
|
+
profile = "eco";
|
|
511
|
+
} else if (routingProfile === "premium") {
|
|
512
|
+
tierConfigs = config.premiumTiers ?? config.tiers;
|
|
513
|
+
profileSuffix = config.premiumTiers ? " | premium" : " | premium (default tiers)";
|
|
514
|
+
profile = "premium";
|
|
515
|
+
} else {
|
|
516
|
+
const agenticScore = ruleResult.agenticScore ?? 0;
|
|
517
|
+
const isAutoAgentic = agenticScore >= 0.5;
|
|
518
|
+
const agenticModeSetting = config.overrides.agenticMode;
|
|
519
|
+
const hasToolsInRequest = options.requiresTools ?? options.hasTools ?? false;
|
|
520
|
+
let useAgenticTiers;
|
|
521
|
+
if (agenticModeSetting === false) {
|
|
522
|
+
useAgenticTiers = false;
|
|
523
|
+
} else if (agenticModeSetting === true) {
|
|
524
|
+
useAgenticTiers = config.agenticTiers != null;
|
|
525
|
+
} else {
|
|
526
|
+
useAgenticTiers = (hasToolsInRequest || isAutoAgentic) && config.agenticTiers != null;
|
|
527
|
+
}
|
|
528
|
+
tierConfigs = useAgenticTiers ? config.agenticTiers : config.tiers;
|
|
529
|
+
profileSuffix = useAgenticTiers ? ` | agentic${hasToolsInRequest ? " (tools)" : ""}` : "";
|
|
530
|
+
profile = useAgenticTiers ? "agentic" : "auto";
|
|
531
|
+
}
|
|
532
|
+
tierConfigs = applyPromotions(tierConfigs, config.promotions, profile, options.now);
|
|
533
|
+
const agenticScoreValue = ruleResult.agenticScore;
|
|
534
|
+
if (estimatedTokens > config.overrides.maxTokensForceComplex) {
|
|
535
|
+
const decision2 = selectModel(
|
|
536
|
+
"COMPLEX",
|
|
537
|
+
0.95,
|
|
538
|
+
"rules",
|
|
539
|
+
`Input exceeds ${config.overrides.maxTokensForceComplex} tokens${profileSuffix}`,
|
|
540
|
+
tierConfigs,
|
|
541
|
+
modelPricing,
|
|
542
|
+
estimatedTokens,
|
|
543
|
+
maxOutputTokens,
|
|
544
|
+
routingProfile,
|
|
545
|
+
agenticScoreValue
|
|
546
|
+
);
|
|
547
|
+
return { ...decision2, tierConfigs, profile };
|
|
548
|
+
}
|
|
549
|
+
const hasStructuredOutput = options.requiresStructuredOutput === true || (scannedSystemPrompt ? /json|structured|schema/i.test(scannedSystemPrompt) : false);
|
|
550
|
+
let tier;
|
|
551
|
+
let confidence;
|
|
552
|
+
const method = "rules";
|
|
553
|
+
let reasoning = `score=${ruleResult.score.toFixed(2)} | ${ruleResult.signals.join(", ")}`;
|
|
554
|
+
if (ruleResult.tier !== null) {
|
|
555
|
+
tier = ruleResult.tier;
|
|
556
|
+
confidence = ruleResult.confidence;
|
|
557
|
+
} else {
|
|
558
|
+
tier = config.overrides.ambiguousDefaultTier;
|
|
559
|
+
confidence = 0.5;
|
|
560
|
+
reasoning += ` | ambiguous -> default: ${tier}`;
|
|
561
|
+
}
|
|
562
|
+
if (hasStructuredOutput) {
|
|
563
|
+
const tierRank = { SIMPLE: 0, MEDIUM: 1, COMPLEX: 2, REASONING: 3 };
|
|
564
|
+
const minTier = config.overrides.structuredOutputMinTier;
|
|
565
|
+
if (tierRank[tier] < tierRank[minTier]) {
|
|
566
|
+
reasoning += ` | upgraded to ${minTier} (structured output)`;
|
|
567
|
+
tier = minTier;
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
reasoning += profileSuffix;
|
|
571
|
+
const decision = selectModel(
|
|
572
|
+
tier,
|
|
573
|
+
confidence,
|
|
574
|
+
method,
|
|
575
|
+
reasoning,
|
|
576
|
+
tierConfigs,
|
|
577
|
+
modelPricing,
|
|
578
|
+
estimatedTokens,
|
|
579
|
+
maxOutputTokens,
|
|
580
|
+
routingProfile,
|
|
581
|
+
agenticScoreValue
|
|
582
|
+
);
|
|
583
|
+
return { ...decision, tierConfigs, profile };
|
|
584
|
+
}
|
|
585
|
+
};
|
|
586
|
+
var registry = /* @__PURE__ */ new Map();
|
|
587
|
+
registry.set("rules", new RulesStrategy());
|
|
588
|
+
function getStrategy(name) {
|
|
589
|
+
const strategy = registry.get(name);
|
|
590
|
+
if (!strategy) {
|
|
591
|
+
throw new Error(`Unknown routing strategy: ${name}`);
|
|
592
|
+
}
|
|
593
|
+
return strategy;
|
|
594
|
+
}
|
|
595
|
+
function registerStrategy(strategy) {
|
|
596
|
+
registry.set(strategy.name, strategy);
|
|
597
|
+
}
|
|
598
|
+
var DEFAULT_MODEL_CAPABILITIES = Object.freeze({
|
|
599
|
+
"anthropic/claude-fable-5": {
|
|
600
|
+
contextWindow: 1e6,
|
|
601
|
+
maxOutputTokens: 128e3,
|
|
602
|
+
supportsTools: true,
|
|
603
|
+
supportsVision: true
|
|
604
|
+
},
|
|
605
|
+
"anthropic/claude-haiku-4.5": {
|
|
606
|
+
contextWindow: 2e5,
|
|
607
|
+
maxOutputTokens: 8192,
|
|
608
|
+
supportsTools: true,
|
|
609
|
+
supportsVision: true
|
|
610
|
+
},
|
|
611
|
+
"anthropic/claude-opus-4.6": {
|
|
612
|
+
contextWindow: 1e6,
|
|
613
|
+
maxOutputTokens: 128e3,
|
|
614
|
+
supportsTools: true,
|
|
615
|
+
supportsVision: true
|
|
616
|
+
},
|
|
617
|
+
"anthropic/claude-opus-4.7": {
|
|
618
|
+
contextWindow: 1e6,
|
|
619
|
+
maxOutputTokens: 128e3,
|
|
620
|
+
supportsTools: true,
|
|
621
|
+
supportsVision: true
|
|
622
|
+
},
|
|
623
|
+
"anthropic/claude-opus-4.8": {
|
|
624
|
+
contextWindow: 1e6,
|
|
625
|
+
maxOutputTokens: 128e3,
|
|
626
|
+
supportsTools: true,
|
|
627
|
+
supportsVision: true
|
|
628
|
+
},
|
|
629
|
+
"anthropic/claude-opus-5": {
|
|
630
|
+
contextWindow: 1e6,
|
|
631
|
+
maxOutputTokens: 128e3,
|
|
632
|
+
supportsTools: true,
|
|
633
|
+
supportsVision: true
|
|
634
|
+
},
|
|
635
|
+
"anthropic/claude-sonnet-4.6": {
|
|
636
|
+
contextWindow: 2e5,
|
|
637
|
+
maxOutputTokens: 64e3,
|
|
638
|
+
supportsTools: true,
|
|
639
|
+
supportsVision: true
|
|
640
|
+
},
|
|
641
|
+
"anthropic/claude-sonnet-5": {
|
|
642
|
+
contextWindow: 1e6,
|
|
643
|
+
maxOutputTokens: 128e3,
|
|
644
|
+
supportsTools: true,
|
|
645
|
+
supportsVision: true
|
|
646
|
+
},
|
|
647
|
+
"deepseek/deepseek-chat": {
|
|
648
|
+
contextWindow: 1e6,
|
|
649
|
+
maxOutputTokens: 8192,
|
|
650
|
+
supportsTools: true,
|
|
651
|
+
supportsVision: false
|
|
652
|
+
},
|
|
653
|
+
"deepseek/deepseek-reasoner": {
|
|
654
|
+
contextWindow: 1e6,
|
|
655
|
+
maxOutputTokens: 8192,
|
|
656
|
+
supportsTools: true,
|
|
657
|
+
supportsVision: false
|
|
658
|
+
},
|
|
659
|
+
"deepseek/deepseek-v4-pro": {
|
|
660
|
+
contextWindow: 1048576,
|
|
661
|
+
maxOutputTokens: 65536,
|
|
662
|
+
supportsTools: true,
|
|
663
|
+
supportsVision: false
|
|
664
|
+
},
|
|
665
|
+
"free/deepseek-v4-flash": {
|
|
666
|
+
contextWindow: 1e6,
|
|
667
|
+
maxOutputTokens: 16384,
|
|
668
|
+
supportsTools: false,
|
|
669
|
+
supportsVision: false
|
|
670
|
+
},
|
|
671
|
+
"free/gpt-oss-120b": {
|
|
672
|
+
contextWindow: 128e3,
|
|
673
|
+
maxOutputTokens: 16384,
|
|
674
|
+
supportsTools: false,
|
|
675
|
+
supportsVision: false
|
|
676
|
+
},
|
|
677
|
+
"free/gpt-oss-20b": {
|
|
678
|
+
contextWindow: 128e3,
|
|
679
|
+
maxOutputTokens: 16384,
|
|
680
|
+
supportsTools: false,
|
|
681
|
+
supportsVision: false
|
|
682
|
+
},
|
|
683
|
+
"free/seed-oss-36b": {
|
|
684
|
+
contextWindow: 131072,
|
|
685
|
+
maxOutputTokens: 16384,
|
|
686
|
+
supportsTools: false,
|
|
687
|
+
supportsVision: false
|
|
688
|
+
},
|
|
689
|
+
"google/gemini-2.5-flash": {
|
|
690
|
+
contextWindow: 1e6,
|
|
691
|
+
maxOutputTokens: 65536,
|
|
692
|
+
supportsTools: true,
|
|
693
|
+
supportsVision: true
|
|
694
|
+
},
|
|
695
|
+
"google/gemini-2.5-flash-lite": {
|
|
696
|
+
contextWindow: 1e6,
|
|
697
|
+
maxOutputTokens: 65536,
|
|
698
|
+
supportsTools: true,
|
|
699
|
+
supportsVision: false
|
|
700
|
+
},
|
|
701
|
+
"google/gemini-2.5-pro": {
|
|
702
|
+
contextWindow: 105e4,
|
|
703
|
+
maxOutputTokens: 65536,
|
|
704
|
+
supportsTools: true,
|
|
705
|
+
supportsVision: true
|
|
706
|
+
},
|
|
707
|
+
"google/gemini-3-flash-preview": {
|
|
708
|
+
contextWindow: 1e6,
|
|
709
|
+
maxOutputTokens: 65536,
|
|
710
|
+
supportsTools: false,
|
|
711
|
+
supportsVision: true
|
|
712
|
+
},
|
|
713
|
+
"google/gemini-3.1-flash-lite": {
|
|
714
|
+
contextWindow: 1e6,
|
|
715
|
+
maxOutputTokens: 8192,
|
|
716
|
+
supportsTools: true,
|
|
717
|
+
supportsVision: false
|
|
718
|
+
},
|
|
719
|
+
"google/gemini-3.1-pro": {
|
|
720
|
+
contextWindow: 105e4,
|
|
721
|
+
maxOutputTokens: 65536,
|
|
722
|
+
supportsTools: true,
|
|
723
|
+
supportsVision: true
|
|
724
|
+
},
|
|
725
|
+
"google/gemini-3.5-flash": {
|
|
726
|
+
contextWindow: 1048576,
|
|
727
|
+
maxOutputTokens: 65536,
|
|
728
|
+
supportsTools: true,
|
|
729
|
+
supportsVision: true
|
|
730
|
+
},
|
|
731
|
+
"moonshot/kimi-k2.5": {
|
|
732
|
+
contextWindow: 262144,
|
|
733
|
+
maxOutputTokens: 16384,
|
|
734
|
+
supportsTools: true,
|
|
735
|
+
supportsVision: true
|
|
736
|
+
},
|
|
737
|
+
"moonshot/kimi-k2.6": {
|
|
738
|
+
contextWindow: 262144,
|
|
739
|
+
maxOutputTokens: 65536,
|
|
740
|
+
supportsTools: true,
|
|
741
|
+
supportsVision: true
|
|
742
|
+
},
|
|
743
|
+
"moonshot/kimi-k2.7": {
|
|
744
|
+
contextWindow: 262144,
|
|
745
|
+
maxOutputTokens: 65536,
|
|
746
|
+
supportsTools: true,
|
|
747
|
+
supportsVision: true
|
|
748
|
+
},
|
|
749
|
+
"moonshot/kimi-k3": {
|
|
750
|
+
contextWindow: 1048576,
|
|
751
|
+
maxOutputTokens: 65536,
|
|
752
|
+
supportsTools: true,
|
|
753
|
+
supportsVision: true
|
|
754
|
+
},
|
|
755
|
+
"openai/gpt-4.1": {
|
|
756
|
+
contextWindow: 128e3,
|
|
757
|
+
maxOutputTokens: 16384,
|
|
758
|
+
supportsTools: true,
|
|
759
|
+
supportsVision: true
|
|
760
|
+
},
|
|
761
|
+
"openai/gpt-4o-mini": {
|
|
762
|
+
contextWindow: 128e3,
|
|
763
|
+
maxOutputTokens: 16384,
|
|
764
|
+
supportsTools: true,
|
|
765
|
+
supportsVision: false
|
|
766
|
+
},
|
|
767
|
+
"openai/gpt-5-mini": {
|
|
768
|
+
contextWindow: 2e5,
|
|
769
|
+
maxOutputTokens: 65536,
|
|
770
|
+
supportsTools: true,
|
|
771
|
+
supportsVision: false
|
|
772
|
+
},
|
|
773
|
+
"openai/gpt-5.3-codex": {
|
|
774
|
+
contextWindow: 4e5,
|
|
775
|
+
maxOutputTokens: 128e3,
|
|
776
|
+
supportsTools: true,
|
|
777
|
+
supportsVision: false
|
|
778
|
+
},
|
|
779
|
+
"openai/gpt-5.4": {
|
|
780
|
+
contextWindow: 4e5,
|
|
781
|
+
maxOutputTokens: 128e3,
|
|
782
|
+
supportsTools: true,
|
|
783
|
+
supportsVision: true
|
|
784
|
+
},
|
|
785
|
+
"openai/gpt-5.4-nano": {
|
|
786
|
+
contextWindow: 105e4,
|
|
787
|
+
maxOutputTokens: 32768,
|
|
788
|
+
supportsTools: true,
|
|
789
|
+
supportsVision: false
|
|
790
|
+
},
|
|
791
|
+
"openai/gpt-5.5": {
|
|
792
|
+
contextWindow: 105e4,
|
|
793
|
+
maxOutputTokens: 128e3,
|
|
794
|
+
supportsTools: true,
|
|
795
|
+
supportsVision: true
|
|
796
|
+
},
|
|
797
|
+
"openai/gpt-5.6-terra": {
|
|
798
|
+
contextWindow: 105e4,
|
|
799
|
+
maxOutputTokens: 128e3,
|
|
800
|
+
supportsTools: true,
|
|
801
|
+
supportsVision: true
|
|
802
|
+
},
|
|
803
|
+
"openai/o3": {
|
|
804
|
+
contextWindow: 2e5,
|
|
805
|
+
maxOutputTokens: 1e5,
|
|
806
|
+
supportsTools: true,
|
|
807
|
+
supportsVision: false
|
|
808
|
+
},
|
|
809
|
+
"openai/o4-mini": {
|
|
810
|
+
contextWindow: 128e3,
|
|
811
|
+
maxOutputTokens: 65536,
|
|
812
|
+
supportsTools: true,
|
|
813
|
+
supportsVision: false
|
|
814
|
+
},
|
|
815
|
+
"qwen/qwen3.7-max": {
|
|
816
|
+
contextWindow: 1e6,
|
|
817
|
+
maxOutputTokens: 65536,
|
|
818
|
+
supportsTools: true,
|
|
819
|
+
supportsVision: false
|
|
820
|
+
},
|
|
821
|
+
"xai/grok-3-mini": {
|
|
822
|
+
contextWindow: 131072,
|
|
823
|
+
maxOutputTokens: 16384,
|
|
824
|
+
supportsTools: true,
|
|
825
|
+
supportsVision: false
|
|
826
|
+
},
|
|
827
|
+
"xai/grok-4-0709": {
|
|
828
|
+
contextWindow: 131072,
|
|
829
|
+
maxOutputTokens: 16384,
|
|
830
|
+
supportsTools: true,
|
|
831
|
+
supportsVision: false
|
|
832
|
+
},
|
|
833
|
+
"xai/grok-4-1-fast-non-reasoning": {
|
|
834
|
+
contextWindow: 131072,
|
|
835
|
+
maxOutputTokens: 16384,
|
|
836
|
+
supportsTools: true,
|
|
837
|
+
supportsVision: false
|
|
838
|
+
},
|
|
839
|
+
"xai/grok-4-1-fast-reasoning": {
|
|
840
|
+
contextWindow: 131072,
|
|
841
|
+
maxOutputTokens: 16384,
|
|
842
|
+
supportsTools: true,
|
|
843
|
+
supportsVision: false
|
|
844
|
+
},
|
|
845
|
+
"xai/grok-4-fast-non-reasoning": {
|
|
846
|
+
contextWindow: 131072,
|
|
847
|
+
maxOutputTokens: 16384,
|
|
848
|
+
supportsTools: true,
|
|
849
|
+
supportsVision: false
|
|
850
|
+
},
|
|
851
|
+
"xai/grok-4-fast-reasoning": {
|
|
852
|
+
contextWindow: 131072,
|
|
853
|
+
maxOutputTokens: 16384,
|
|
854
|
+
supportsTools: true,
|
|
855
|
+
supportsVision: false
|
|
856
|
+
},
|
|
857
|
+
"xai/grok-4.5": {
|
|
858
|
+
contextWindow: 5e5,
|
|
859
|
+
maxOutputTokens: 16384,
|
|
860
|
+
supportsTools: true,
|
|
861
|
+
supportsVision: true
|
|
862
|
+
},
|
|
863
|
+
"zai/glm-5.1": {
|
|
864
|
+
contextWindow: 2e5,
|
|
865
|
+
maxOutputTokens: 128e3,
|
|
866
|
+
supportsTools: true,
|
|
867
|
+
supportsVision: false
|
|
868
|
+
},
|
|
869
|
+
"zai/glm-5.2": {
|
|
870
|
+
contextWindow: 1e6,
|
|
871
|
+
maxOutputTokens: 262144,
|
|
872
|
+
supportsTools: true,
|
|
873
|
+
supportsVision: false
|
|
874
|
+
}
|
|
875
|
+
});
|
|
876
|
+
var model_profiles_generated_default = {
|
|
877
|
+
"openai/gpt-5.5": {
|
|
878
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
879
|
+
latencyMs: 6243.1,
|
|
880
|
+
p95LatencyMs: 9865,
|
|
881
|
+
outputTokensPerSecond: 12.53,
|
|
882
|
+
errorRate: 0,
|
|
883
|
+
samples: 3
|
|
884
|
+
},
|
|
885
|
+
"openai/gpt-5.4-pro": {
|
|
886
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
887
|
+
latencyMs: 13015.5,
|
|
888
|
+
p95LatencyMs: 23976.4,
|
|
889
|
+
outputTokensPerSecond: 6.42,
|
|
890
|
+
errorRate: 0,
|
|
891
|
+
samples: 3
|
|
892
|
+
},
|
|
893
|
+
"openai/gpt-5.4-mini": {
|
|
894
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
895
|
+
latencyMs: 5550,
|
|
896
|
+
p95LatencyMs: 6595.7,
|
|
897
|
+
outputTokensPerSecond: 11.96,
|
|
898
|
+
errorRate: 0.3333,
|
|
899
|
+
samples: 3
|
|
900
|
+
},
|
|
901
|
+
"openai/gpt-5.3-codex": {
|
|
902
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
903
|
+
latencyMs: 4617.1,
|
|
904
|
+
p95LatencyMs: 5800.7,
|
|
905
|
+
outputTokensPerSecond: 12.48,
|
|
906
|
+
errorRate: 0,
|
|
907
|
+
samples: 3
|
|
908
|
+
},
|
|
909
|
+
"anthropic/claude-opus-4.8": {
|
|
910
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
911
|
+
latencyMs: 3915.1,
|
|
912
|
+
p95LatencyMs: 6130.8,
|
|
913
|
+
outputTokensPerSecond: 16.33,
|
|
914
|
+
errorRate: 0,
|
|
915
|
+
samples: 3
|
|
916
|
+
},
|
|
917
|
+
"anthropic/claude-opus-4.6": {
|
|
918
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
919
|
+
latencyMs: 3765.5,
|
|
920
|
+
p95LatencyMs: 4257.2,
|
|
921
|
+
outputTokensPerSecond: 14.18,
|
|
922
|
+
errorRate: 0,
|
|
923
|
+
samples: 3
|
|
924
|
+
},
|
|
925
|
+
"anthropic/claude-sonnet-4.6": {
|
|
926
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
927
|
+
latencyMs: 3860.6,
|
|
928
|
+
p95LatencyMs: 5093.5,
|
|
929
|
+
outputTokensPerSecond: 13.85,
|
|
930
|
+
errorRate: 0,
|
|
931
|
+
samples: 3
|
|
932
|
+
},
|
|
933
|
+
"anthropic/claude-haiku-4.5": {
|
|
934
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
935
|
+
latencyMs: 2734.9,
|
|
936
|
+
p95LatencyMs: 3181.6,
|
|
937
|
+
outputTokensPerSecond: 19.58,
|
|
938
|
+
errorRate: 0,
|
|
939
|
+
samples: 3
|
|
940
|
+
},
|
|
941
|
+
"google/gemini-3.1-pro": {
|
|
942
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
943
|
+
latencyMs: 13935.7,
|
|
944
|
+
p95LatencyMs: 26675.3,
|
|
945
|
+
outputTokensPerSecond: 77.47,
|
|
946
|
+
errorRate: 0,
|
|
947
|
+
samples: 3
|
|
948
|
+
},
|
|
949
|
+
"google/gemini-3.5-flash": {
|
|
950
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
951
|
+
latencyMs: 4608.7,
|
|
952
|
+
p95LatencyMs: 8420.9,
|
|
953
|
+
outputTokensPerSecond: 57.88,
|
|
954
|
+
errorRate: 0,
|
|
955
|
+
samples: 3
|
|
956
|
+
},
|
|
957
|
+
"google/gemini-3.1-flash-lite": {
|
|
958
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
959
|
+
latencyMs: 4619.7,
|
|
960
|
+
p95LatencyMs: 9927.1,
|
|
961
|
+
outputTokensPerSecond: 42.01,
|
|
962
|
+
errorRate: 0,
|
|
963
|
+
samples: 3
|
|
964
|
+
},
|
|
965
|
+
"google/gemini-2.5-flash": {
|
|
966
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
967
|
+
latencyMs: 5506.9,
|
|
968
|
+
p95LatencyMs: 11462.5,
|
|
969
|
+
outputTokensPerSecond: 65.19,
|
|
970
|
+
errorRate: 0,
|
|
971
|
+
samples: 3
|
|
972
|
+
},
|
|
973
|
+
"deepseek/deepseek-v4-pro": {
|
|
974
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
975
|
+
latencyMs: 6044.8,
|
|
976
|
+
p95LatencyMs: 10782.3,
|
|
977
|
+
outputTokensPerSecond: 22.47,
|
|
978
|
+
errorRate: 0,
|
|
979
|
+
samples: 3
|
|
980
|
+
},
|
|
981
|
+
"deepseek/deepseek-reasoner": {
|
|
982
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
983
|
+
latencyMs: 4111.9,
|
|
984
|
+
p95LatencyMs: 5305.7,
|
|
985
|
+
outputTokensPerSecond: 16.46,
|
|
986
|
+
errorRate: 0,
|
|
987
|
+
samples: 3
|
|
988
|
+
},
|
|
989
|
+
"deepseek/deepseek-chat": {
|
|
990
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
991
|
+
latencyMs: 2648.6,
|
|
992
|
+
p95LatencyMs: 3524.1,
|
|
993
|
+
outputTokensPerSecond: 16.73,
|
|
994
|
+
errorRate: 0,
|
|
995
|
+
samples: 3
|
|
996
|
+
},
|
|
997
|
+
"moonshot/kimi-k2.7": {
|
|
998
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
999
|
+
latencyMs: 4295.4,
|
|
1000
|
+
p95LatencyMs: 6153.8,
|
|
1001
|
+
outputTokensPerSecond: 18.54,
|
|
1002
|
+
errorRate: 0,
|
|
1003
|
+
samples: 3
|
|
1004
|
+
},
|
|
1005
|
+
"qwen/qwen3.7-max": {
|
|
1006
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
1007
|
+
latencyMs: 30729.4,
|
|
1008
|
+
p95LatencyMs: 39622,
|
|
1009
|
+
outputTokensPerSecond: 36.89,
|
|
1010
|
+
errorRate: 0.3333,
|
|
1011
|
+
samples: 3
|
|
1012
|
+
},
|
|
1013
|
+
"xai/grok-4.3": {
|
|
1014
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
1015
|
+
latencyMs: 6946.1,
|
|
1016
|
+
p95LatencyMs: 9495.4,
|
|
1017
|
+
outputTokensPerSecond: 65.3,
|
|
1018
|
+
errorRate: 0,
|
|
1019
|
+
samples: 3
|
|
1020
|
+
},
|
|
1021
|
+
"xai/grok-4.20-reasoning": {
|
|
1022
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
1023
|
+
latencyMs: 3472.4,
|
|
1024
|
+
p95LatencyMs: 5332.4,
|
|
1025
|
+
outputTokensPerSecond: 13.27,
|
|
1026
|
+
errorRate: 0,
|
|
1027
|
+
samples: 3
|
|
1028
|
+
},
|
|
1029
|
+
"xai/grok-4.20-non-reasoning": {
|
|
1030
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
1031
|
+
latencyMs: 5174.4,
|
|
1032
|
+
p95LatencyMs: 6081.7,
|
|
1033
|
+
outputTokensPerSecond: 10.21,
|
|
1034
|
+
errorRate: 0.3333,
|
|
1035
|
+
samples: 3
|
|
1036
|
+
},
|
|
1037
|
+
"xai/grok-4-1-fast-reasoning": {
|
|
1038
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
1039
|
+
latencyMs: 13148.2,
|
|
1040
|
+
p95LatencyMs: 19104.2,
|
|
1041
|
+
outputTokensPerSecond: 4.28,
|
|
1042
|
+
errorRate: 0,
|
|
1043
|
+
samples: 3
|
|
1044
|
+
},
|
|
1045
|
+
"minimax/minimax-m3": {
|
|
1046
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
1047
|
+
latencyMs: 3385,
|
|
1048
|
+
p95LatencyMs: 4247.2,
|
|
1049
|
+
outputTokensPerSecond: 15.16,
|
|
1050
|
+
errorRate: 0,
|
|
1051
|
+
samples: 3
|
|
1052
|
+
},
|
|
1053
|
+
"minimax/minimax-m2.7": {
|
|
1054
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
1055
|
+
latencyMs: 4596.7,
|
|
1056
|
+
p95LatencyMs: 6884.6,
|
|
1057
|
+
outputTokensPerSecond: 17.03,
|
|
1058
|
+
errorRate: 0,
|
|
1059
|
+
samples: 3
|
|
1060
|
+
},
|
|
1061
|
+
"zai/glm-5.2": {
|
|
1062
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
1063
|
+
latencyMs: 4406.3,
|
|
1064
|
+
p95LatencyMs: 6139.7,
|
|
1065
|
+
outputTokensPerSecond: 10.41,
|
|
1066
|
+
errorRate: 0,
|
|
1067
|
+
samples: 3
|
|
1068
|
+
},
|
|
1069
|
+
"zai/glm-5.1": {
|
|
1070
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
1071
|
+
latencyMs: 7775.4,
|
|
1072
|
+
p95LatencyMs: 9182.1,
|
|
1073
|
+
outputTokensPerSecond: 6.08,
|
|
1074
|
+
errorRate: 0,
|
|
1075
|
+
samples: 3
|
|
1076
|
+
},
|
|
1077
|
+
"zai/glm-5": {
|
|
1078
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
1079
|
+
latencyMs: 4159.4,
|
|
1080
|
+
p95LatencyMs: 4992.7,
|
|
1081
|
+
outputTokensPerSecond: 10.28,
|
|
1082
|
+
errorRate: 0,
|
|
1083
|
+
samples: 3
|
|
1084
|
+
},
|
|
1085
|
+
"free/qwen3-coder-480b": {
|
|
1086
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
1087
|
+
latencyMs: 2063.9,
|
|
1088
|
+
p95LatencyMs: 3646.3,
|
|
1089
|
+
outputTokensPerSecond: 39.8,
|
|
1090
|
+
errorRate: 0,
|
|
1091
|
+
samples: 3
|
|
1092
|
+
},
|
|
1093
|
+
"free/mistral-large-3-675b": {
|
|
1094
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
1095
|
+
latencyMs: 3147.5,
|
|
1096
|
+
p95LatencyMs: 5555.3,
|
|
1097
|
+
outputTokensPerSecond: 27.76,
|
|
1098
|
+
errorRate: 0,
|
|
1099
|
+
samples: 3
|
|
1100
|
+
},
|
|
1101
|
+
"free/nemotron-3-nano-omni-30b-a3b-reasoning": {
|
|
1102
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
1103
|
+
latencyMs: 6508.4,
|
|
1104
|
+
p95LatencyMs: 14252.7,
|
|
1105
|
+
outputTokensPerSecond: 68.26,
|
|
1106
|
+
errorRate: 0,
|
|
1107
|
+
samples: 3
|
|
1108
|
+
},
|
|
1109
|
+
"free/glm-4.7": {
|
|
1110
|
+
measuredAt: "2026-07-21T10:21:31Z",
|
|
1111
|
+
latencyMs: 2014.8,
|
|
1112
|
+
p95LatencyMs: 3039.9,
|
|
1113
|
+
outputTokensPerSecond: 39.92,
|
|
1114
|
+
errorRate: 0,
|
|
1115
|
+
samples: 3
|
|
1116
|
+
}
|
|
1117
|
+
};
|
|
1118
|
+
var LIVE_MODEL_PROFILES = Object.freeze(
|
|
1119
|
+
model_profiles_generated_default
|
|
1120
|
+
);
|
|
1121
|
+
var HISTORICAL_MODEL_PROFILES = Object.freeze({
|
|
1122
|
+
"anthropic/claude-haiku-4.5": {
|
|
1123
|
+
measuredAt: "2026-03-16T13:50:48Z",
|
|
1124
|
+
latencyMs: 2305,
|
|
1125
|
+
outputTokensPerSecond: 140.6
|
|
1126
|
+
},
|
|
1127
|
+
"anthropic/claude-opus-4.6": {
|
|
1128
|
+
measuredAt: "2026-03-16T13:50:48Z",
|
|
1129
|
+
latencyMs: 2139,
|
|
1130
|
+
outputTokensPerSecond: 119.7
|
|
1131
|
+
},
|
|
1132
|
+
"anthropic/claude-sonnet-4.6": {
|
|
1133
|
+
measuredAt: "2026-03-16T13:50:48Z",
|
|
1134
|
+
latencyMs: 2110,
|
|
1135
|
+
outputTokensPerSecond: 121.3
|
|
1136
|
+
},
|
|
1137
|
+
"deepseek/deepseek-chat": {
|
|
1138
|
+
measuredAt: "2026-03-16T13:50:48Z",
|
|
1139
|
+
latencyMs: 1431,
|
|
1140
|
+
outputTokensPerSecond: 179.2,
|
|
1141
|
+
intelligenceIndex: 32
|
|
1142
|
+
},
|
|
1143
|
+
"google/gemini-2.5-flash": {
|
|
1144
|
+
measuredAt: "2026-03-16T13:50:48Z",
|
|
1145
|
+
latencyMs: 1238,
|
|
1146
|
+
outputTokensPerSecond: 207.6,
|
|
1147
|
+
intelligenceIndex: 20
|
|
1148
|
+
},
|
|
1149
|
+
"google/gemini-2.5-flash-lite": {
|
|
1150
|
+
measuredAt: "2026-03-16T13:50:48Z",
|
|
1151
|
+
latencyMs: 1353,
|
|
1152
|
+
outputTokensPerSecond: 192.5,
|
|
1153
|
+
intelligenceIndex: 20
|
|
1154
|
+
},
|
|
1155
|
+
"google/gemini-2.5-pro": {
|
|
1156
|
+
measuredAt: "2026-03-16T13:50:48Z",
|
|
1157
|
+
latencyMs: 1294,
|
|
1158
|
+
outputTokensPerSecond: 197.8
|
|
1159
|
+
},
|
|
1160
|
+
"google/gemini-3.1-pro": {
|
|
1161
|
+
measuredAt: "2026-03-16T13:50:48Z",
|
|
1162
|
+
latencyMs: 1609,
|
|
1163
|
+
outputTokensPerSecond: 167.2
|
|
1164
|
+
},
|
|
1165
|
+
"moonshot/kimi-k2.5": {
|
|
1166
|
+
measuredAt: "2026-03-16T13:50:48Z",
|
|
1167
|
+
latencyMs: 1646,
|
|
1168
|
+
outputTokensPerSecond: 155.7
|
|
1169
|
+
},
|
|
1170
|
+
"openai/gpt-4o-mini": {
|
|
1171
|
+
measuredAt: "2026-03-16T13:50:48Z",
|
|
1172
|
+
latencyMs: 2764,
|
|
1173
|
+
outputTokensPerSecond: 92.8
|
|
1174
|
+
},
|
|
1175
|
+
"openai/gpt-5.3-codex": {
|
|
1176
|
+
measuredAt: "2026-03-16T13:50:48Z",
|
|
1177
|
+
latencyMs: 7935,
|
|
1178
|
+
outputTokensPerSecond: 32.3
|
|
1179
|
+
},
|
|
1180
|
+
"xai/grok-4-1-fast-non-reasoning": {
|
|
1181
|
+
measuredAt: "2026-03-16T13:50:48Z",
|
|
1182
|
+
latencyMs: 1244,
|
|
1183
|
+
outputTokensPerSecond: 205.8,
|
|
1184
|
+
intelligenceIndex: 41
|
|
1185
|
+
},
|
|
1186
|
+
"xai/grok-4-1-fast-reasoning": {
|
|
1187
|
+
measuredAt: "2026-03-16T13:50:48Z",
|
|
1188
|
+
latencyMs: 1454,
|
|
1189
|
+
outputTokensPerSecond: 176.2,
|
|
1190
|
+
intelligenceIndex: 41
|
|
1191
|
+
}
|
|
1192
|
+
});
|
|
1193
|
+
function inferToolRequirement(prompt, _systemPrompt, toolChoice) {
|
|
1194
|
+
if (toolChoice === "none") return false;
|
|
1195
|
+
if (toolChoice === "required") return true;
|
|
1196
|
+
if (typeof toolChoice === "object" && toolChoice !== null && toolChoice.type === "function") {
|
|
1197
|
+
return true;
|
|
1198
|
+
}
|
|
1199
|
+
const text = prompt;
|
|
1200
|
+
const explicitTool = /\b(?:use|call|invoke)\s+(?:the\s+)?[\w.-]+\s+(?:tool|function|api)\b|\btool[_ -]?call\b|使用.{0,20}(?:工具|函数|接口)|调用.{0,20}(?:工具|函数|接口)/i;
|
|
1201
|
+
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;
|
|
1202
|
+
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;
|
|
1203
|
+
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;
|
|
1204
|
+
return explicitTool.test(text) || codeEnvironment.test(text) || webAction.test(text) || statefulAction.test(text);
|
|
1205
|
+
}
|
|
1206
|
+
var DEFAULT_PORTFOLIO_WEIGHTS = {
|
|
1207
|
+
auto: {
|
|
1208
|
+
quality: 0.47,
|
|
1209
|
+
capability: 0.2,
|
|
1210
|
+
cost: 0.18,
|
|
1211
|
+
speed: 0.07,
|
|
1212
|
+
reliability: 0.03,
|
|
1213
|
+
legacy: 0.05
|
|
1214
|
+
},
|
|
1215
|
+
eco: { quality: 0.36, capability: 0.2, cost: 0.28, speed: 0.1, reliability: 0.04, legacy: 0.02 },
|
|
1216
|
+
premium: {
|
|
1217
|
+
quality: 0.58,
|
|
1218
|
+
capability: 0.2,
|
|
1219
|
+
cost: 0.08,
|
|
1220
|
+
speed: 0.06,
|
|
1221
|
+
reliability: 0.06,
|
|
1222
|
+
legacy: 0.02
|
|
1223
|
+
},
|
|
1224
|
+
highStakesBoost: { quality: 0.08, reliability: 0.05 },
|
|
1225
|
+
latencySensitiveSpeedBoost: 0.08,
|
|
1226
|
+
affinityFloorGap: { auto: 0.1, eco: 0.22, premium: 0.05 }
|
|
1227
|
+
};
|
|
1228
|
+
function likelyNeedsParallelToolCalls(prompt, needsTools, toolCount, toolNames) {
|
|
1229
|
+
if (!needsTools || toolCount === void 0 || toolCount < 1) return false;
|
|
1230
|
+
const text = prompt.trim();
|
|
1231
|
+
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(
|
|
1232
|
+
text
|
|
1233
|
+
);
|
|
1234
|
+
if (explicitRepeat) return true;
|
|
1235
|
+
const sentenceClauses = text.split(/[.!?。!?]+/).map((part) => part.trim()).filter((part) => part.length >= 8);
|
|
1236
|
+
if (/\b(?:also|additionally|furthermore)\b|另外|此外|그리고/i.test(text) && sentenceClauses.length >= 2 || /\band\s+(?:also|for the)\b/i.test(text))
|
|
1237
|
+
return true;
|
|
1238
|
+
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(
|
|
1239
|
+
text
|
|
1240
|
+
);
|
|
1241
|
+
if (pairedQuantity) return true;
|
|
1242
|
+
const operationTokens = /* @__PURE__ */ new Set([
|
|
1243
|
+
"add",
|
|
1244
|
+
"delete",
|
|
1245
|
+
"remove",
|
|
1246
|
+
"cancel",
|
|
1247
|
+
"return",
|
|
1248
|
+
"exchange",
|
|
1249
|
+
"modify",
|
|
1250
|
+
"book",
|
|
1251
|
+
"transfer",
|
|
1252
|
+
"send",
|
|
1253
|
+
"upload",
|
|
1254
|
+
"download",
|
|
1255
|
+
"create",
|
|
1256
|
+
"close"
|
|
1257
|
+
]);
|
|
1258
|
+
const lowered = text.toLowerCase();
|
|
1259
|
+
const matchedOperationTokens = new Set(
|
|
1260
|
+
(toolNames ?? []).flatMap((name) => name.toLowerCase().split(/[^a-z0-9\u3400-\u9fff]+/)).filter((token) => operationTokens.has(token) && lowered.includes(token))
|
|
1261
|
+
);
|
|
1262
|
+
if (matchedOperationTokens.size >= 2) return true;
|
|
1263
|
+
const nonEmptyLines = text.split(/\r?\n/).map((line) => line.trim()).filter(Boolean);
|
|
1264
|
+
const quantityMentions = text.match(
|
|
1265
|
+
/\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
|
|
1266
|
+
) ?? [];
|
|
1267
|
+
if (nonEmptyLines.length >= 2 && quantityMentions.length >= 2) return true;
|
|
1268
|
+
const repeatedLookup = /\b(?:weather|climate|clima|tiempo|temperature|snow|news|report)\b|天气|气象|温度|降雪|新闻|报告/i.test(
|
|
1269
|
+
text
|
|
1270
|
+
);
|
|
1271
|
+
const multiLocationConnector = /\b(?:and also|both|y|e)\b|还有|以及|和|、/i.test(text);
|
|
1272
|
+
const commaSeparatedLocations = (text.match(/[,,]/g) ?? []).length >= 2;
|
|
1273
|
+
if (repeatedLookup && (multiLocationConnector || commaSeparatedLocations)) return true;
|
|
1274
|
+
const distinctOrderParts = /\b(?:food|meal)\b[\s\S]*\bdrink\b|\bdrink\b[\s\S]*\b(?:food|meal)\b/i.test(text);
|
|
1275
|
+
const koreanParallelClauses = (text.match(/,/g) ?? []).length >= 3 && /하고|그리고/.test(text);
|
|
1276
|
+
return distinctOrderParts || koreanParallelClauses;
|
|
1277
|
+
}
|
|
1278
|
+
function classifyTask(prompt, systemPrompt, options) {
|
|
1279
|
+
const fullText = `${systemPrompt ?? ""} ${prompt}`;
|
|
1280
|
+
const estimatedInputTokens = Math.ceil(fullText.length / 4);
|
|
1281
|
+
const scanLimit = Math.max(1, Math.min(8e3, options.config.classifier.promptTruncationChars));
|
|
1282
|
+
const sample = (value) => {
|
|
1283
|
+
if (value.length <= scanLimit) return value;
|
|
1284
|
+
const prefixLength = Math.ceil(scanLimit / 2);
|
|
1285
|
+
return `${value.slice(0, prefixLength)}
|
|
1286
|
+
${value.slice(-(scanLimit - prefixLength))}`;
|
|
1287
|
+
};
|
|
1288
|
+
const scannedPrompt = sample(prompt);
|
|
1289
|
+
const scannedSystemPrompt = sample(systemPrompt ?? "");
|
|
1290
|
+
const scannedFullText = `${scannedSystemPrompt} ${scannedPrompt}`;
|
|
1291
|
+
const text = scannedPrompt.toLowerCase();
|
|
1292
|
+
const explicitCodeSignal = /```|\b(?:typescript|javascript|python|rust|java|sql|stack trace|traceback|exception)\b|\.(?:ts|tsx|js|py|go|rs)\b/i.test(
|
|
1293
|
+
scannedPrompt
|
|
1294
|
+
);
|
|
1295
|
+
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(
|
|
1296
|
+
scannedPrompt
|
|
1297
|
+
);
|
|
1298
|
+
const nativeCodeSignal = /\b(?:programmed|written|implemented?|code)\s+(?:in|using)\s+(?:c\+\+|c|rust|go)\b/i.test(
|
|
1299
|
+
scannedPrompt
|
|
1300
|
+
);
|
|
1301
|
+
const hasCode = explicitCodeSignal || codeConstructSignal || nativeCodeSignal;
|
|
1302
|
+
const toolsAvailable = options.hasTools ?? false;
|
|
1303
|
+
const needsTools = options.requiresTools ?? (toolsAvailable && inferToolRequirement(scannedPrompt, scannedSystemPrompt));
|
|
1304
|
+
const likelyParallelToolCalls = likelyNeedsParallelToolCalls(
|
|
1305
|
+
scannedPrompt,
|
|
1306
|
+
needsTools,
|
|
1307
|
+
options.toolCount,
|
|
1308
|
+
options.toolNames
|
|
1309
|
+
);
|
|
1310
|
+
const normalizedToolNames = (options.toolNames ?? []).map((name) => name.toLowerCase());
|
|
1311
|
+
const airlineToolSignal = normalizedToolNames.some(
|
|
1312
|
+
(name) => /(?:flight|reservation|airport|baggage|passenger)/.test(name)
|
|
1313
|
+
);
|
|
1314
|
+
const retailToolSignal = normalizedToolNames.some(
|
|
1315
|
+
(name) => /(?:order|product|item|return|exchange|address)/.test(name)
|
|
1316
|
+
);
|
|
1317
|
+
const webResearchToolSignal = normalizedToolNames.some(
|
|
1318
|
+
(name) => /^(?:web_?search|web_?fetch)$/.test(name)
|
|
1319
|
+
);
|
|
1320
|
+
const agentDomain = airlineToolSignal && !retailToolSignal ? "airline" : retailToolSignal && !airlineToolSignal ? "retail" : webResearchToolSignal ? "web_research" : "other";
|
|
1321
|
+
const clueConnectors = scannedFullText.match(
|
|
1322
|
+
/\b(?:after|before|while|where|whose|which|in \d{4}|as of|over \d+|another|also|furthermore)\b|(?:之后|之前|其中|截至|超过|另一个|此外)/gi
|
|
1323
|
+
) ?? [];
|
|
1324
|
+
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(
|
|
1325
|
+
scannedFullText
|
|
1326
|
+
);
|
|
1327
|
+
const exactAnswerSignal = /\b(?:exact answer|single best-supported answer|following clues|multiple public sources)\b|(?:精确答案|根据.*线索|多个公开来源)/i.test(
|
|
1328
|
+
scannedFullText
|
|
1329
|
+
);
|
|
1330
|
+
const deepWebResearch = agentDomain === "web_research" && (exactAnswerSignal || entityResolutionSignal && (clueConnectors.length >= 3 || prompt.length >= 320));
|
|
1331
|
+
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(
|
|
1332
|
+
scannedPrompt
|
|
1333
|
+
);
|
|
1334
|
+
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(
|
|
1335
|
+
scannedPrompt
|
|
1336
|
+
);
|
|
1337
|
+
const globalChoiceSignal = globalOptimizationSignal || globalScopeSignal;
|
|
1338
|
+
const crossRecordSignal = /\b(?:another|other|different|previous)\s+(?:order|reservation|booking|account|address)\b|另一(?:个)?(?:订单|预订|账户|地址)|其他(?:订单|预订|账户|地址)/i.test(
|
|
1339
|
+
scannedPrompt
|
|
1340
|
+
);
|
|
1341
|
+
const reservationIds = scannedPrompt.match(/\b[A-Z0-9]{6}\b/g) ?? [];
|
|
1342
|
+
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(
|
|
1343
|
+
scannedPrompt
|
|
1344
|
+
) || new Set(reservationIds).size >= 2);
|
|
1345
|
+
const conditionalGlobalWorkflowSignal = agentDomain === "airline" && globalScopeSignal && /\b(?:if|that (?:contain|have)|longer than|shorter than|under|over|at (?:most|least)|wherever possible)\b|如果|超过|少于|不超过|尽可能/i.test(
|
|
1346
|
+
scannedPrompt
|
|
1347
|
+
) && /\b(?:cancel|change|upgrade|move|book)\b[\s\S]*\b(?:cancel|change|upgrade|move|book)\b|取消[\s\S]*(?:升级|更改)|升级[\s\S]*(?:取消|更改)/i.test(
|
|
1348
|
+
scannedPrompt
|
|
1349
|
+
);
|
|
1350
|
+
const policyExceptionSignal = agentDomain === "retail" && /\b(?:return|refund|send back|get (?:my |the )?money back)\b|退货|退款|退回/i.test(
|
|
1351
|
+
scannedPrompt
|
|
1352
|
+
) && /\b(?:amex|american express|visa|mastercard|credit card|debit card|different card|another card|other card)\b|信用卡|借记卡|其他卡|另一张卡/i.test(
|
|
1353
|
+
scannedPrompt
|
|
1354
|
+
);
|
|
1355
|
+
const singleSelectedPolicyException = policyExceptionSignal && /\b(?:return|refund|send back)\b[^.!?。!?]{0,96}\b(?:the )?(?:pricier|cheaper|more expensive|less expensive|costlier|one)\b/i.test(
|
|
1356
|
+
scannedPrompt
|
|
1357
|
+
);
|
|
1358
|
+
const negotiatedWorkflowSignal = agentDomain === "retail" && /\b(?:return|exchange)\b|退货|退回|换货|交换/i.test(scannedPrompt);
|
|
1359
|
+
const numberedSteps = (scannedPrompt.match(/(?:^|\s)\d+(?:\.\d+)*[.)]\s+/g) ?? []).length;
|
|
1360
|
+
const complexMultiToolPlan = likelyParallelToolCalls && ((options.toolCount ?? 0) >= 6 || numberedSteps >= 3 || prompt.length > 1200);
|
|
1361
|
+
let agentRisk = needsTools && singleSelectedPolicyException ? "policy_exception_simple" : needsTools && policyExceptionSignal ? "policy_exception" : (
|
|
1362
|
+
// Airline prompts that require a global optimum (for example the
|
|
1363
|
+
// cheapest itinerary across several candidates) are materially harder
|
|
1364
|
+
// than applying one change to every passenger in a known reservation.
|
|
1365
|
+
// Full-session evidence supports Sonnet for the former, while upgrading
|
|
1366
|
+
// the latter merely because it says "all passengers" caused a large cost
|
|
1367
|
+
// increase without a quality gain.
|
|
1368
|
+
needsTools && agentDomain === "airline" && (globalOptimizationSignal || conditionalGlobalWorkflowSignal) ? "complex_high" : needsTools && (likelyParallelToolCalls || globalChoiceSignal || crossRecordSignal || crossReservationBatchSignal || negotiatedWorkflowSignal) ? "high" : "standard"
|
|
1369
|
+
);
|
|
1370
|
+
const needsVision = options.hasVision ?? false;
|
|
1371
|
+
const needsStructuredOutput = options.requiresStructuredOutput ?? false;
|
|
1372
|
+
const latencySensitive = /\b(?:urgent|asap|fast|quick|low latency|real[- ]time)\b|尽快|马上|快速|低延迟/i.test(
|
|
1373
|
+
scannedFullText
|
|
1374
|
+
);
|
|
1375
|
+
const highStakes = /\b(?:production|security|payment|legal|medical|financial|audit)\b|生产|安全|支付|法律|医疗|财务|审计/i.test(
|
|
1376
|
+
scannedFullText
|
|
1377
|
+
);
|
|
1378
|
+
const terminalToolSignal = normalizedToolNames.some(
|
|
1379
|
+
(name) => /^(?:terminalexec|terminalinspect|terminalsendkeys)$/.test(name)
|
|
1380
|
+
);
|
|
1381
|
+
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(
|
|
1382
|
+
scannedPrompt
|
|
1383
|
+
);
|
|
1384
|
+
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(
|
|
1385
|
+
scannedPrompt
|
|
1386
|
+
);
|
|
1387
|
+
const mentionedTerminalRuntimes = new Set(
|
|
1388
|
+
(scannedPrompt.match(/\b(?:gcc|clang|rustc|javac|go\s+build|node|python)\b/gi) ?? []).map(
|
|
1389
|
+
(name) => name.toLowerCase().replace(/\s+/g, " ")
|
|
1390
|
+
)
|
|
1391
|
+
);
|
|
1392
|
+
const terminalCrossRuntimeArtifact = terminalToolSignal && (/\bpolyglot\b/i.test(scannedPrompt) || /\b(?:both|each)\b[\s\S]{0,120}\b(?:compilers?|runtimes?|toolchains?)\b/i.test(
|
|
1393
|
+
scannedPrompt
|
|
1394
|
+
) || mentionedTerminalRuntimes.size >= 2 && /\b(?:compile|build|run|execute)\b/i.test(scannedPrompt));
|
|
1395
|
+
const terminalFrameworkToNativeArtifact = terminalToolSignal && /\b(?:pytorch|tensorflow|jax|onnx|state[_ -]?dict|checkpoint|safetensors?)\b|\.(?:pth|pt|onnx)\b/i.test(
|
|
1396
|
+
scannedPrompt
|
|
1397
|
+
) && /\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(
|
|
1398
|
+
scannedPrompt
|
|
1399
|
+
) && /\b(?:inference|model|weights?|tensor|export|convert|load)\b/i.test(scannedPrompt);
|
|
1400
|
+
if (needsTools && (terminalComplexRepair || terminalCrossRuntimeArtifact || terminalFrameworkToNativeArtifact) && (agentRisk === "standard" || agentRisk === "high"))
|
|
1401
|
+
agentRisk = "complex_high";
|
|
1402
|
+
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(
|
|
1403
|
+
scannedPrompt
|
|
1404
|
+
);
|
|
1405
|
+
const terminalCredentialSignal = /\b(?:ssh|nginx|certificate|authentication|credentials?|passwords?|api keys?|deploy|production|encrypt|gpg|shred|securely delete|decommission)\b/i.test(
|
|
1406
|
+
scannedPrompt
|
|
1407
|
+
) || /\b(?:access|auth|authentication|bearer|secret|api)\s+tokens?\b|\btokens?\s+(?:secret|credential|authentication)\b/i.test(
|
|
1408
|
+
scannedPrompt
|
|
1409
|
+
);
|
|
1410
|
+
const terminalSafetySensitive = terminalToolSignal && (highStakes || terminalCredentialSignal);
|
|
1411
|
+
const implicitTerminalCode = needsTools && terminalToolSignal && agentRisk === "standard" && !highStakes && !complexTerminalOperation && numberedSteps < 3 && prompt.length <= 1e3 && simpleTerminalArtifact;
|
|
1412
|
+
const language = /[\u3400-\u9fff]/.test(scannedFullText) ? "zh" : "other";
|
|
1413
|
+
const multipleChoiceSignals = (scannedPrompt.match(/(?:^|\n)\s*[A-D][.)]\s+/gim) ?? []).length;
|
|
1414
|
+
const numericSignals = (scannedPrompt.match(/-?\d+(?:[.,]\d+)?/g) ?? []).length;
|
|
1415
|
+
const compactMathProblem = !hasCode && prompt.length < 2500 && numericSignals >= 2 && (/[+×÷=%$€£¥]|\b(?:total|each|per|times|half|twice|percent|how many|how much|calculate)\b/i.test(
|
|
1416
|
+
scannedPrompt
|
|
1417
|
+
) || /[??]\s*$/.test(scannedPrompt.trim()) || numericSignals >= 3);
|
|
1418
|
+
let taskType = "chat";
|
|
1419
|
+
if (needsVision) taskType = "vision";
|
|
1420
|
+
else if (estimatedInputTokens > 8e4) taskType = "long_context";
|
|
1421
|
+
else if (needsTools && (hasCode || implicitTerminalCode)) taskType = "code_agent";
|
|
1422
|
+
else if (needsTools && likelyParallelToolCalls && !complexMultiToolPlan)
|
|
1423
|
+
taskType = "tool_agent_parallel";
|
|
1424
|
+
else if (needsTools) taskType = "tool_agent";
|
|
1425
|
+
else if (multipleChoiceSignals >= 3) taskType = "reasoning_mcq";
|
|
1426
|
+
else if (compactMathProblem) taskType = "reasoning_math";
|
|
1427
|
+
else if (/\b(?:bug|debug|error|failure|failing|regression|crash|修复|报错|错误|调试)\b/i.test(text))
|
|
1428
|
+
taskType = "debug";
|
|
1429
|
+
else if (hasCode || /\b(?:refactor|implement|patch|edit|rewrite|重构|实现|修改)\b/i.test(text))
|
|
1430
|
+
taskType = "code_edit";
|
|
1431
|
+
else if (needsStructuredOutput || /\b(?:extract|json|schema|csv|字段|提取)\b/i.test(text))
|
|
1432
|
+
taskType = "extraction";
|
|
1433
|
+
else if (/\b(?:prove|derive|theorem|formal|mathematical|reasoning|证明|推导|定理|数学)\b/i.test(text))
|
|
1434
|
+
taskType = "reasoning";
|
|
1435
|
+
return {
|
|
1436
|
+
taskType,
|
|
1437
|
+
estimatedInputTokens,
|
|
1438
|
+
hasCode,
|
|
1439
|
+
needsTools,
|
|
1440
|
+
toolsAvailable,
|
|
1441
|
+
needsVision,
|
|
1442
|
+
needsStructuredOutput,
|
|
1443
|
+
latencySensitive,
|
|
1444
|
+
highStakes,
|
|
1445
|
+
language,
|
|
1446
|
+
likelyParallelToolCalls,
|
|
1447
|
+
complexMultiToolPlan,
|
|
1448
|
+
agentDomain,
|
|
1449
|
+
deepWebResearch,
|
|
1450
|
+
agentRisk,
|
|
1451
|
+
terminalToolSignal,
|
|
1452
|
+
terminalSafetySensitive,
|
|
1453
|
+
implicitTerminalCode
|
|
1454
|
+
};
|
|
1455
|
+
}
|
|
1456
|
+
function affinity(modelId, task, language = "other", agentDomain = "other", deepWebResearch = false, agentRisk = "standard", terminalToolSignal = false, terminalSafetySensitive = false) {
|
|
1457
|
+
const id = modelId.toLowerCase();
|
|
1458
|
+
const modelName = id.slice(id.indexOf("/") + 1);
|
|
1459
|
+
const match = (values, score) => values.some((value) => modelName === value) ? score : 0;
|
|
1460
|
+
const base = 0.68;
|
|
1461
|
+
switch (task) {
|
|
1462
|
+
case "code_agent":
|
|
1463
|
+
if (terminalToolSignal && agentRisk === "complex_high") {
|
|
1464
|
+
return Math.max(
|
|
1465
|
+
base,
|
|
1466
|
+
match(["claude-sonnet-5"], 1),
|
|
1467
|
+
match(["gpt-5.3-codex"], 0.87),
|
|
1468
|
+
match(["gpt-5-mini"], 0.78),
|
|
1469
|
+
match(["gemini-3.5-flash"], 0.76)
|
|
1470
|
+
);
|
|
1471
|
+
}
|
|
1472
|
+
return Math.max(
|
|
1473
|
+
base,
|
|
1474
|
+
match(["gpt-5.3-codex"], 1),
|
|
1475
|
+
match(["claude-sonnet-5"], 0.98),
|
|
1476
|
+
match(["gpt-5-mini"], 0.96),
|
|
1477
|
+
match(["gemini-3.5-flash"], 0.92),
|
|
1478
|
+
match(["kimi-k3"], 0.9),
|
|
1479
|
+
match(["deepseek-v4-pro", "glm-5.2"], 0.88)
|
|
1480
|
+
);
|
|
1481
|
+
case "tool_agent":
|
|
1482
|
+
if (terminalToolSignal && agentRisk === "complex_high") {
|
|
1483
|
+
return Math.max(
|
|
1484
|
+
base,
|
|
1485
|
+
match(["claude-sonnet-5"], 1),
|
|
1486
|
+
match(["gpt-5.3-codex"], 0.87),
|
|
1487
|
+
match(["gpt-5-mini"], 0.78),
|
|
1488
|
+
match(["gemini-3.5-flash"], 0.76)
|
|
1489
|
+
);
|
|
1490
|
+
}
|
|
1491
|
+
if (terminalToolSignal && !terminalSafetySensitive) {
|
|
1492
|
+
return Math.max(
|
|
1493
|
+
base,
|
|
1494
|
+
match(["gpt-5-mini"], 1),
|
|
1495
|
+
match(["gpt-5.3-codex"], 0.98),
|
|
1496
|
+
match(["claude-sonnet-5"], 0.9),
|
|
1497
|
+
match(["gemini-3.5-flash"], 0.89)
|
|
1498
|
+
);
|
|
1499
|
+
}
|
|
1500
|
+
if (terminalToolSignal && terminalSafetySensitive) {
|
|
1501
|
+
return Math.max(
|
|
1502
|
+
base,
|
|
1503
|
+
match(["claude-sonnet-5"], 1),
|
|
1504
|
+
match(["claude-opus-4.8"], 0.9),
|
|
1505
|
+
match(["gpt-5.3-codex"], 0.84)
|
|
1506
|
+
);
|
|
1507
|
+
}
|
|
1508
|
+
if (agentDomain === "web_research") {
|
|
1509
|
+
return deepWebResearch ? Math.max(
|
|
1510
|
+
base,
|
|
1511
|
+
match(["claude-sonnet-5"], 1),
|
|
1512
|
+
match(["gpt-5-mini"], 0.88),
|
|
1513
|
+
match(["gemini-3.5-flash"], 0.84),
|
|
1514
|
+
match(["claude-opus-5"], 0.8),
|
|
1515
|
+
match(["claude-opus-4.8"], 0.78)
|
|
1516
|
+
) : Math.max(
|
|
1517
|
+
base,
|
|
1518
|
+
match(["claude-sonnet-5"], 1),
|
|
1519
|
+
match(["gpt-5-mini"], 0.88),
|
|
1520
|
+
match(["gemini-3.5-flash"], 0.86),
|
|
1521
|
+
match(["claude-opus-5"], 0.84),
|
|
1522
|
+
match(["claude-opus-4.8"], 0.82)
|
|
1523
|
+
);
|
|
1524
|
+
}
|
|
1525
|
+
if (agentDomain === "retail") {
|
|
1526
|
+
if (agentRisk === "standard") {
|
|
1527
|
+
return Math.max(
|
|
1528
|
+
base,
|
|
1529
|
+
match(["gpt-5-mini"], 1),
|
|
1530
|
+
match(["claude-sonnet-5"], 0.88),
|
|
1531
|
+
match(["gemini-3.5-flash"], 0.82),
|
|
1532
|
+
match(["gpt-5.3-codex"], 0.81),
|
|
1533
|
+
match(["kimi-k3"], 0.78),
|
|
1534
|
+
match(["deepseek-v4-pro"], 0.76)
|
|
1535
|
+
);
|
|
1536
|
+
}
|
|
1537
|
+
if (agentRisk === "policy_exception") {
|
|
1538
|
+
return Math.max(
|
|
1539
|
+
base,
|
|
1540
|
+
match(["gpt-4.1"], 1),
|
|
1541
|
+
match(["claude-sonnet-5"], 0.9),
|
|
1542
|
+
match(["deepseek-v4-pro"], 0.82),
|
|
1543
|
+
match(["gpt-5-mini"], 0.8),
|
|
1544
|
+
match(["gpt-4o-mini"], 0.76)
|
|
1545
|
+
);
|
|
1546
|
+
}
|
|
1547
|
+
if (agentRisk === "policy_exception_simple") {
|
|
1548
|
+
return Math.max(
|
|
1549
|
+
base,
|
|
1550
|
+
match(["gpt-5-mini"], 1),
|
|
1551
|
+
match(["gpt-4.1"], 0.86),
|
|
1552
|
+
match(["deepseek-v4-pro"], 0.82),
|
|
1553
|
+
match(["gpt-4o-mini"], 0.8)
|
|
1554
|
+
);
|
|
1555
|
+
}
|
|
1556
|
+
return Math.max(
|
|
1557
|
+
base,
|
|
1558
|
+
match(["deepseek-v4-pro"], 1),
|
|
1559
|
+
match(["claude-sonnet-5"], 0.88),
|
|
1560
|
+
match(["gemini-3.5-flash"], 0.82),
|
|
1561
|
+
match(["gpt-5.3-codex"], 0.81),
|
|
1562
|
+
match(["kimi-k3"], 0.78),
|
|
1563
|
+
match(["gpt-5-mini"], 0.76)
|
|
1564
|
+
);
|
|
1565
|
+
}
|
|
1566
|
+
if (agentDomain === "airline") {
|
|
1567
|
+
if (agentRisk === "complex_high") {
|
|
1568
|
+
return Math.max(
|
|
1569
|
+
base,
|
|
1570
|
+
match(["claude-sonnet-5"], 1),
|
|
1571
|
+
match(["gpt-5-mini"], 0.78),
|
|
1572
|
+
match(["gemini-3.5-flash"], 0.76),
|
|
1573
|
+
match(["deepseek-v4-pro"], 0.74)
|
|
1574
|
+
);
|
|
1575
|
+
}
|
|
1576
|
+
return Math.max(
|
|
1577
|
+
base,
|
|
1578
|
+
match(["gpt-5-mini"], 1),
|
|
1579
|
+
match(["claude-sonnet-5"], 0.9),
|
|
1580
|
+
match(["gemini-3.5-flash"], 0.8),
|
|
1581
|
+
match(["deepseek-v4-pro"], 0.76)
|
|
1582
|
+
);
|
|
1583
|
+
}
|
|
1584
|
+
return Math.max(
|
|
1585
|
+
base,
|
|
1586
|
+
match(["claude-sonnet-5"], 1),
|
|
1587
|
+
match(["gemini-3.5-flash"], 0.88),
|
|
1588
|
+
match(["gpt-5.3-codex"], 0.87),
|
|
1589
|
+
match(["gpt-5-mini"], 0.84),
|
|
1590
|
+
match(["kimi-k3"], 0.85),
|
|
1591
|
+
match(["deepseek-v4-pro"], 0.82)
|
|
1592
|
+
);
|
|
1593
|
+
case "tool_agent_parallel":
|
|
1594
|
+
if (terminalToolSignal) {
|
|
1595
|
+
return terminalSafetySensitive ? Math.max(
|
|
1596
|
+
base,
|
|
1597
|
+
match(["claude-sonnet-5"], 1),
|
|
1598
|
+
match(["claude-opus-4.8"], 0.9),
|
|
1599
|
+
match(["gpt-5.3-codex"], 0.86)
|
|
1600
|
+
) : Math.max(
|
|
1601
|
+
base,
|
|
1602
|
+
match(["gpt-5-mini"], 1),
|
|
1603
|
+
match(["gpt-5.3-codex"], 0.98),
|
|
1604
|
+
match(["claude-sonnet-5"], 0.92),
|
|
1605
|
+
match(["gemini-3.5-flash"], 0.88)
|
|
1606
|
+
);
|
|
1607
|
+
}
|
|
1608
|
+
if (agentDomain === "web_research") {
|
|
1609
|
+
return deepWebResearch ? Math.max(
|
|
1610
|
+
base,
|
|
1611
|
+
match(["claude-sonnet-5"], 1),
|
|
1612
|
+
match(["gpt-5-mini"], 0.88),
|
|
1613
|
+
match(["gemini-3.5-flash"], 0.84),
|
|
1614
|
+
match(["claude-opus-5"], 0.8),
|
|
1615
|
+
match(["claude-opus-4.8"], 0.78)
|
|
1616
|
+
) : Math.max(
|
|
1617
|
+
base,
|
|
1618
|
+
match(["claude-sonnet-5"], 1),
|
|
1619
|
+
match(["gpt-5-mini"], 0.88),
|
|
1620
|
+
match(["gemini-3.5-flash"], 0.86),
|
|
1621
|
+
match(["claude-opus-5"], 0.84),
|
|
1622
|
+
match(["claude-opus-4.8"], 0.82)
|
|
1623
|
+
);
|
|
1624
|
+
}
|
|
1625
|
+
if (agentDomain === "retail") {
|
|
1626
|
+
if (agentRisk === "policy_exception") {
|
|
1627
|
+
return Math.max(
|
|
1628
|
+
base,
|
|
1629
|
+
match(["gpt-4.1"], 1),
|
|
1630
|
+
match(["claude-sonnet-5"], 0.9),
|
|
1631
|
+
match(["deepseek-v4-pro"], 0.82),
|
|
1632
|
+
match(["gpt-5-mini"], 0.8),
|
|
1633
|
+
match(["gpt-4o-mini"], 0.76)
|
|
1634
|
+
);
|
|
1635
|
+
}
|
|
1636
|
+
if (agentRisk === "policy_exception_simple") {
|
|
1637
|
+
return Math.max(
|
|
1638
|
+
base,
|
|
1639
|
+
match(["gpt-5-mini"], 1),
|
|
1640
|
+
match(["gpt-4.1"], 0.86),
|
|
1641
|
+
match(["deepseek-v4-pro"], 0.82),
|
|
1642
|
+
match(["gpt-4o-mini"], 0.8)
|
|
1643
|
+
);
|
|
1644
|
+
}
|
|
1645
|
+
return Math.max(
|
|
1646
|
+
base,
|
|
1647
|
+
match(["deepseek-v4-pro"], 1),
|
|
1648
|
+
match(["claude-sonnet-5"], 0.88),
|
|
1649
|
+
match(["claude-opus-4.8"], 0.84),
|
|
1650
|
+
match(["gpt-5-mini"], 0.78),
|
|
1651
|
+
match(["gemini-3.5-flash"], 0.76)
|
|
1652
|
+
);
|
|
1653
|
+
}
|
|
1654
|
+
if (agentDomain === "airline") {
|
|
1655
|
+
return agentRisk === "complex_high" ? Math.max(
|
|
1656
|
+
base,
|
|
1657
|
+
match(["claude-sonnet-5"], 1),
|
|
1658
|
+
match(["gpt-5-mini"], 0.78),
|
|
1659
|
+
match(["claude-opus-4.8"], 0.76),
|
|
1660
|
+
match(["gemini-3.5-flash"], 0.74)
|
|
1661
|
+
) : Math.max(
|
|
1662
|
+
base,
|
|
1663
|
+
match(["gpt-5-mini"], 1),
|
|
1664
|
+
match(["claude-sonnet-5"], 0.9),
|
|
1665
|
+
match(["gemini-3.5-flash"], 0.8)
|
|
1666
|
+
);
|
|
1667
|
+
}
|
|
1668
|
+
return Math.max(
|
|
1669
|
+
base,
|
|
1670
|
+
match(["claude-opus-4.8"], 1),
|
|
1671
|
+
match(["claude-sonnet-5"], 0.84),
|
|
1672
|
+
match(["grok-4.5"], 0.82),
|
|
1673
|
+
match(["gemini-3.5-flash"], 0.8),
|
|
1674
|
+
match(["deepseek-v4-pro"], 0.78)
|
|
1675
|
+
);
|
|
1676
|
+
case "code_edit":
|
|
1677
|
+
case "debug":
|
|
1678
|
+
return Math.max(
|
|
1679
|
+
base,
|
|
1680
|
+
match(["gpt-5.3-codex"], 1),
|
|
1681
|
+
match(["claude-sonnet-4.6"], 0.94),
|
|
1682
|
+
match(["glm-5.2"], 0.9),
|
|
1683
|
+
match(["kimi-k2.7", "deepseek-v4-pro"], 0.86)
|
|
1684
|
+
);
|
|
1685
|
+
case "reasoning":
|
|
1686
|
+
return Math.max(
|
|
1687
|
+
base,
|
|
1688
|
+
match(["claude-sonnet-5", "claude-sonnet-4.6"], 0.98),
|
|
1689
|
+
match(["deepseek-v4-pro"], 0.95),
|
|
1690
|
+
match(["grok-4.5"], 0.94),
|
|
1691
|
+
match(["gemini-3.1-pro", "gemini-3.5-flash"], 0.92)
|
|
1692
|
+
);
|
|
1693
|
+
case "reasoning_mcq":
|
|
1694
|
+
return Math.max(
|
|
1695
|
+
base,
|
|
1696
|
+
match(["gemini-3-flash-preview"], 1),
|
|
1697
|
+
match(["gemini-3.5-flash"], 0.91),
|
|
1698
|
+
match(["grok-4.5"], 0.9),
|
|
1699
|
+
match(["claude-sonnet-5"], 0.88),
|
|
1700
|
+
match(["deepseek-v4-pro"], 0.84)
|
|
1701
|
+
);
|
|
1702
|
+
case "reasoning_math":
|
|
1703
|
+
return Math.max(
|
|
1704
|
+
base,
|
|
1705
|
+
match(["gemini-3.5-flash"], 1),
|
|
1706
|
+
match(["grok-4.5"], 0.93),
|
|
1707
|
+
match(["claude-sonnet-5", "deepseek-v4-pro", "kimi-k3"], 0.9),
|
|
1708
|
+
match(["kimi-k2.7"], 0.84)
|
|
1709
|
+
);
|
|
1710
|
+
case "vision":
|
|
1711
|
+
return Math.max(
|
|
1712
|
+
base,
|
|
1713
|
+
match(["gemini-3.1-pro"], 0.96),
|
|
1714
|
+
match(["qwen3.7-max", "claude-sonnet-4.6", "kimi-k2.7", "grok-4.3"], 0.9)
|
|
1715
|
+
);
|
|
1716
|
+
case "long_context":
|
|
1717
|
+
return Math.max(
|
|
1718
|
+
base,
|
|
1719
|
+
match(["gemini-3.1-pro"], 1),
|
|
1720
|
+
match(["qwen3.7-max", "glm-5.2"], 0.89),
|
|
1721
|
+
match(["gemini-3.5-flash"], 0.88),
|
|
1722
|
+
match(["deepseek-v4-pro"], 0.85)
|
|
1723
|
+
);
|
|
1724
|
+
case "extraction": {
|
|
1725
|
+
const kimiExtractionAffinity = language === "zh" ? 1 : 0.9;
|
|
1726
|
+
return Math.max(
|
|
1727
|
+
base,
|
|
1728
|
+
match(["gemini-3.5-flash", "gemini-2.5-flash", "gpt-4o-mini"], 0.9),
|
|
1729
|
+
match(["claude-sonnet-5", "claude-sonnet-4.6"], 0.9),
|
|
1730
|
+
match(["kimi-k3", "kimi-k2.7"], kimiExtractionAffinity)
|
|
1731
|
+
);
|
|
1732
|
+
}
|
|
1733
|
+
default:
|
|
1734
|
+
return Math.max(
|
|
1735
|
+
base,
|
|
1736
|
+
match(["gemini-3.5-flash", "gemini-2.5-flash", "kimi-k3", "kimi-k2.7"], 0.86)
|
|
1737
|
+
);
|
|
1738
|
+
}
|
|
1739
|
+
}
|
|
1740
|
+
function evidenceCandidates(task) {
|
|
1741
|
+
if (task === "code_agent") {
|
|
1742
|
+
return [
|
|
1743
|
+
"openai/gpt-5.3-codex",
|
|
1744
|
+
"anthropic/claude-sonnet-5",
|
|
1745
|
+
"openai/gpt-5-mini",
|
|
1746
|
+
"google/gemini-3.5-flash",
|
|
1747
|
+
"moonshot/kimi-k3",
|
|
1748
|
+
"deepseek/deepseek-v4-pro"
|
|
1749
|
+
];
|
|
1750
|
+
}
|
|
1751
|
+
if (task === "tool_agent") {
|
|
1752
|
+
return [
|
|
1753
|
+
"anthropic/claude-sonnet-5",
|
|
1754
|
+
"anthropic/claude-opus-5",
|
|
1755
|
+
"openai/gpt-5-mini",
|
|
1756
|
+
"openai/gpt-4.1",
|
|
1757
|
+
"openai/gpt-4o-mini",
|
|
1758
|
+
"google/gemini-3.5-flash",
|
|
1759
|
+
"openai/gpt-5.3-codex",
|
|
1760
|
+
"moonshot/kimi-k3",
|
|
1761
|
+
"deepseek/deepseek-v4-pro"
|
|
1762
|
+
];
|
|
1763
|
+
}
|
|
1764
|
+
if (task === "tool_agent_parallel") {
|
|
1765
|
+
return [
|
|
1766
|
+
"anthropic/claude-opus-5",
|
|
1767
|
+
"anthropic/claude-opus-4.8",
|
|
1768
|
+
"anthropic/claude-sonnet-5",
|
|
1769
|
+
"openai/gpt-5-mini",
|
|
1770
|
+
"openai/gpt-4.1",
|
|
1771
|
+
"openai/gpt-4o-mini",
|
|
1772
|
+
"xai/grok-4.5",
|
|
1773
|
+
"google/gemini-3.5-flash",
|
|
1774
|
+
"deepseek/deepseek-v4-pro"
|
|
1775
|
+
];
|
|
1776
|
+
}
|
|
1777
|
+
if (task === "long_context") {
|
|
1778
|
+
return [
|
|
1779
|
+
"google/gemini-3.1-pro",
|
|
1780
|
+
"deepseek/deepseek-v4-pro",
|
|
1781
|
+
"qwen/qwen3.7-max",
|
|
1782
|
+
"zai/glm-5.2",
|
|
1783
|
+
"google/gemini-3.5-flash"
|
|
1784
|
+
];
|
|
1785
|
+
}
|
|
1786
|
+
if (task === "reasoning_mcq") {
|
|
1787
|
+
return [
|
|
1788
|
+
"google/gemini-3-flash-preview",
|
|
1789
|
+
"google/gemini-3.5-flash",
|
|
1790
|
+
"xai/grok-4.5",
|
|
1791
|
+
"anthropic/claude-sonnet-5",
|
|
1792
|
+
"deepseek/deepseek-v4-pro"
|
|
1793
|
+
];
|
|
1794
|
+
}
|
|
1795
|
+
if (task === "reasoning_math") {
|
|
1796
|
+
return [
|
|
1797
|
+
"google/gemini-3.5-flash",
|
|
1798
|
+
"xai/grok-4.5",
|
|
1799
|
+
"anthropic/claude-sonnet-5",
|
|
1800
|
+
"deepseek/deepseek-v4-pro",
|
|
1801
|
+
"moonshot/kimi-k3"
|
|
1802
|
+
];
|
|
1803
|
+
}
|
|
1804
|
+
return [];
|
|
1805
|
+
}
|
|
1806
|
+
function isEligible(modelId, features, maxOutputTokens, options) {
|
|
1807
|
+
const model = options.modelCapabilities?.[modelId] ?? DEFAULT_MODEL_CAPABILITIES[modelId];
|
|
1808
|
+
if (!model) return true;
|
|
1809
|
+
if (features.needsTools && !model.supportsTools) return false;
|
|
1810
|
+
if (features.needsVision && !model.supportsVision) return false;
|
|
1811
|
+
if (features.needsStructuredOutput && !model.supportsTools) return false;
|
|
1812
|
+
if (model.maxOutputTokens < maxOutputTokens) return false;
|
|
1813
|
+
return model.contextWindow >= (features.estimatedInputTokens + maxOutputTokens) * 1.1;
|
|
1814
|
+
}
|
|
1815
|
+
function estimatedCost(modelId, options, inputTokens, outputTokens) {
|
|
1816
|
+
const price = options.modelPricing.get(modelId);
|
|
1817
|
+
if (!price) return Number.POSITIVE_INFINITY;
|
|
1818
|
+
if (price.flatPrice !== void 0) return price.flatPrice;
|
|
1819
|
+
return (inputTokens * price.inputPrice + outputTokens * price.outputPrice) / 1e6;
|
|
1820
|
+
}
|
|
1821
|
+
function profileScore(modelId, options, now) {
|
|
1822
|
+
const profile = options.modelPerformance?.[modelId] ?? LIVE_MODEL_PROFILES[modelId] ?? HISTORICAL_MODEL_PROFILES[modelId];
|
|
1823
|
+
if (!profile) return void 0;
|
|
1824
|
+
const measuredAt = Date.parse(profile.measuredAt);
|
|
1825
|
+
if (!Number.isFinite(measuredAt)) return void 0;
|
|
1826
|
+
const ageDays = Math.max(0, (now.getTime() - measuredAt) / 864e5);
|
|
1827
|
+
const sampleConfidence = profile.samples === void 0 ? 1 : Math.min(1, Math.max(0, profile.samples) / 10);
|
|
1828
|
+
const freshness = Math.pow(0.5, ageDays / 30) * sampleConfidence;
|
|
1829
|
+
const quality = profile.intelligenceIndex === void 0 ? void 0 : Math.min(1, profile.intelligenceIndex / 50);
|
|
1830
|
+
const speed = Math.min(
|
|
1831
|
+
1,
|
|
1832
|
+
(2e3 / Math.max(500, profile.latencyMs) + profile.outputTokensPerSecond / 250) / 2
|
|
1833
|
+
);
|
|
1834
|
+
const tailSpeed = Math.min(1, 3e3 / Math.max(750, profile.p95LatencyMs ?? profile.latencyMs));
|
|
1835
|
+
const reliability = Math.max(0, 1 - (profile.errorRate ?? 0));
|
|
1836
|
+
return { quality, speed, tailSpeed, reliability, freshness };
|
|
1837
|
+
}
|
|
1838
|
+
var PortfolioStrategy = class {
|
|
1839
|
+
name = "portfolio";
|
|
1840
|
+
route(prompt, systemPrompt, maxOutputTokens, options) {
|
|
1841
|
+
const features = classifyTask(prompt, systemPrompt, options);
|
|
1842
|
+
const base = new RulesStrategy().route(prompt, systemPrompt, maxOutputTokens, {
|
|
1843
|
+
...options,
|
|
1844
|
+
requiresTools: features.needsTools
|
|
1845
|
+
});
|
|
1846
|
+
const tierConfigs = base.tierConfigs;
|
|
1847
|
+
if (!tierConfigs) return base;
|
|
1848
|
+
const targetTier = (features.taskType === "reasoning_mcq" || features.taskType === "reasoning_math") && (base.tier === "SIMPLE" || base.tier === "MEDIUM") ? "REASONING" : base.tier;
|
|
1849
|
+
const tierConfig = tierConfigs[targetTier];
|
|
1850
|
+
const configuredCandidates = tierConfig ? getFallbackChain(targetTier, tierConfigs) : [];
|
|
1851
|
+
const chain = [
|
|
1852
|
+
.../* @__PURE__ */ new Set([...configuredCandidates, ...evidenceCandidates(features.taskType)])
|
|
1853
|
+
].filter((model2) => typeof model2 === "string" && model2.length > 0);
|
|
1854
|
+
const eligible = chain.filter(
|
|
1855
|
+
(model2) => isEligible(model2, features, maxOutputTokens, options)
|
|
1856
|
+
);
|
|
1857
|
+
const eligibleCandidates = eligible.length > 0 ? eligible : chain;
|
|
1858
|
+
if (eligibleCandidates.length === 0) return base;
|
|
1859
|
+
const profileName = options.routingProfile === "eco" ? "eco" : options.routingProfile === "premium" ? "premium" : "auto";
|
|
1860
|
+
const portfolio = options.config.portfolio ?? DEFAULT_PORTFOLIO_WEIGHTS;
|
|
1861
|
+
const getAffinity = (model2) => affinity(
|
|
1862
|
+
model2,
|
|
1863
|
+
features.taskType,
|
|
1864
|
+
features.language,
|
|
1865
|
+
features.agentDomain,
|
|
1866
|
+
features.deepWebResearch,
|
|
1867
|
+
features.agentRisk,
|
|
1868
|
+
features.terminalToolSignal,
|
|
1869
|
+
features.terminalSafetySensitive
|
|
1870
|
+
);
|
|
1871
|
+
const bestAffinity = Math.max(...eligibleCandidates.map(getAffinity));
|
|
1872
|
+
const specificAffinity = eligibleCandidates.filter((model2) => getAffinity(model2) > 0.68);
|
|
1873
|
+
const affinityPool = specificAffinity.length > 0 ? specificAffinity : [eligibleCandidates[0]];
|
|
1874
|
+
const affinityFloorGap = features.terminalToolSignal ? Math.max(
|
|
1875
|
+
portfolio.affinityFloorGap[profileName],
|
|
1876
|
+
features.terminalSafetySensitive ? 0.15 : 0.12
|
|
1877
|
+
) : portfolio.affinityFloorGap[profileName];
|
|
1878
|
+
const candidates = affinityPool.filter(
|
|
1879
|
+
(model2) => getAffinity(model2) >= bestAffinity - affinityFloorGap
|
|
1880
|
+
);
|
|
1881
|
+
const costs = candidates.map(
|
|
1882
|
+
(model2) => estimatedCost(model2, options, features.estimatedInputTokens, maxOutputTokens)
|
|
1883
|
+
);
|
|
1884
|
+
const finiteCosts = costs.filter(Number.isFinite);
|
|
1885
|
+
const minCost = finiteCosts.length > 0 ? Math.min(...finiteCosts) : 0;
|
|
1886
|
+
const maxCost = finiteCosts.length > 0 ? Math.max(...finiteCosts) : 1;
|
|
1887
|
+
const now = options.now ?? /* @__PURE__ */ new Date();
|
|
1888
|
+
const profileWeights = portfolio[profileName];
|
|
1889
|
+
const rankedEntries = candidates.map((model2, index) => {
|
|
1890
|
+
const cost = estimatedCost(model2, options, features.estimatedInputTokens, maxOutputTokens);
|
|
1891
|
+
const costScore = Number.isFinite(cost) && maxCost > minCost ? 1 - (cost - minCost) / (maxCost - minCost) : 0.5;
|
|
1892
|
+
const capabilityScore = isEligible(model2, features, maxOutputTokens, options) ? 1 : 0;
|
|
1893
|
+
const profile = profileScore(model2, options, now);
|
|
1894
|
+
const observedQuality = profile?.quality === void 0 ? getAffinity(model2) : getAffinity(model2) * (1 - profile.freshness) + profile.quality * profile.freshness;
|
|
1895
|
+
const observedSpeed = profile ? profile.speed * profile.freshness : 0.5;
|
|
1896
|
+
const observedTailSpeed = profile ? profile.tailSpeed * profile.freshness : 0.5;
|
|
1897
|
+
const observedReliability = profile ? profile.reliability * profile.freshness + (1 - profile.freshness) : 1;
|
|
1898
|
+
const legacyScore = 1 - index / Math.max(1, candidates.length - 1);
|
|
1899
|
+
const qualityWeight = profileWeights.quality + (features.highStakes ? portfolio.highStakesBoost.quality : 0);
|
|
1900
|
+
const speedScore = features.latencySensitive ? observedTailSpeed : observedSpeed;
|
|
1901
|
+
const speedWeight = profileWeights.speed + (features.latencySensitive ? portfolio.latencySensitiveSpeedBoost : 0);
|
|
1902
|
+
const reliabilityWeight = profileWeights.reliability + (features.highStakes ? portfolio.highStakesBoost.reliability : 0);
|
|
1903
|
+
const score = observedQuality * qualityWeight + capabilityScore * profileWeights.capability + costScore * profileWeights.cost + speedScore * speedWeight + observedReliability * reliabilityWeight + legacyScore * profileWeights.legacy;
|
|
1904
|
+
return {
|
|
1905
|
+
model: model2,
|
|
1906
|
+
score,
|
|
1907
|
+
quality: observedQuality,
|
|
1908
|
+
cost: costScore,
|
|
1909
|
+
speed: speedScore,
|
|
1910
|
+
reliability: observedReliability
|
|
1911
|
+
};
|
|
1912
|
+
}).sort((a, b) => b.score - a.score);
|
|
1913
|
+
const scoredModels = rankedEntries.map((item) => item.model);
|
|
1914
|
+
const webResearchFallbackOrder = [
|
|
1915
|
+
"anthropic/claude-sonnet-5",
|
|
1916
|
+
"openai/gpt-5-mini",
|
|
1917
|
+
"google/gemini-3.5-flash",
|
|
1918
|
+
"anthropic/claude-opus-5",
|
|
1919
|
+
"anthropic/claude-opus-4.8",
|
|
1920
|
+
"openai/gpt-5.3-codex"
|
|
1921
|
+
];
|
|
1922
|
+
const ranked = features.agentDomain === "web_research" ? [
|
|
1923
|
+
...scoredModels,
|
|
1924
|
+
...webResearchFallbackOrder.filter(
|
|
1925
|
+
(model2) => eligibleCandidates.includes(model2) && !scoredModels.includes(model2)
|
|
1926
|
+
),
|
|
1927
|
+
...eligibleCandidates.filter(
|
|
1928
|
+
(model2) => !scoredModels.includes(model2) && !webResearchFallbackOrder.includes(model2)
|
|
1929
|
+
)
|
|
1930
|
+
] : features.taskType === "tool_agent" || features.taskType === "tool_agent_parallel" && features.agentDomain !== "other" ? [
|
|
1931
|
+
...scoredModels,
|
|
1932
|
+
...eligibleCandidates.filter((model2) => !scoredModels.includes(model2))
|
|
1933
|
+
] : [
|
|
1934
|
+
...scoredModels,
|
|
1935
|
+
...eligibleCandidates.filter((model2) => !scoredModels.includes(model2))
|
|
1936
|
+
];
|
|
1937
|
+
const model = ranked[0] ?? base.model;
|
|
1938
|
+
const selectedTierConfigs = {
|
|
1939
|
+
...tierConfigs,
|
|
1940
|
+
[targetTier]: { primary: model, fallback: ranked.slice(1) }
|
|
1941
|
+
};
|
|
1942
|
+
const decision = selectModel(
|
|
1943
|
+
targetTier,
|
|
1944
|
+
base.confidence,
|
|
1945
|
+
"portfolio",
|
|
1946
|
+
`${base.reasoning} | v3 task=${features.taskType} agentRisk=${features.agentRisk} deepWebResearch=${features.deepWebResearch} terminalCode=${features.implicitTerminalCode} terminalSafety=${features.terminalSafetySensitive} candidates=${ranked.length}`,
|
|
1947
|
+
selectedTierConfigs,
|
|
1948
|
+
options.modelPricing,
|
|
1949
|
+
features.estimatedInputTokens,
|
|
1950
|
+
maxOutputTokens,
|
|
1951
|
+
options.routingProfile,
|
|
1952
|
+
base.agenticScore
|
|
1953
|
+
);
|
|
1954
|
+
return {
|
|
1955
|
+
...decision,
|
|
1956
|
+
tierConfigs: selectedTierConfigs,
|
|
1957
|
+
profile: base.profile,
|
|
1958
|
+
candidates: ranked,
|
|
1959
|
+
candidateScores: rankedEntries.map(({ model: model2, score, quality, cost, speed, reliability }) => ({
|
|
1960
|
+
model: model2,
|
|
1961
|
+
score,
|
|
1962
|
+
quality,
|
|
1963
|
+
cost,
|
|
1964
|
+
speed,
|
|
1965
|
+
reliability
|
|
1966
|
+
})),
|
|
1967
|
+
taskType: features.taskType,
|
|
1968
|
+
routerVersion: "v3-portfolio"
|
|
1969
|
+
};
|
|
1970
|
+
}
|
|
1971
|
+
};
|
|
1972
|
+
var DEFAULT_ROUTING_CONFIG = {
|
|
1973
|
+
version: "3.4",
|
|
1974
|
+
strategy: "portfolio",
|
|
1975
|
+
portfolio: {
|
|
1976
|
+
auto: {
|
|
1977
|
+
quality: 0.47,
|
|
1978
|
+
capability: 0.2,
|
|
1979
|
+
cost: 0.18,
|
|
1980
|
+
speed: 0.07,
|
|
1981
|
+
reliability: 0.03,
|
|
1982
|
+
legacy: 0.05
|
|
1983
|
+
},
|
|
1984
|
+
eco: {
|
|
1985
|
+
quality: 0.36,
|
|
1986
|
+
capability: 0.2,
|
|
1987
|
+
cost: 0.28,
|
|
1988
|
+
speed: 0.1,
|
|
1989
|
+
reliability: 0.04,
|
|
1990
|
+
legacy: 0.02
|
|
1991
|
+
},
|
|
1992
|
+
premium: {
|
|
1993
|
+
quality: 0.58,
|
|
1994
|
+
capability: 0.2,
|
|
1995
|
+
cost: 0.08,
|
|
1996
|
+
speed: 0.06,
|
|
1997
|
+
reliability: 0.06,
|
|
1998
|
+
legacy: 0.02
|
|
1999
|
+
},
|
|
2000
|
+
highStakesBoost: { quality: 0.08, reliability: 0.05 },
|
|
2001
|
+
latencySensitiveSpeedBoost: 0.08,
|
|
2002
|
+
affinityFloorGap: { auto: 0.1, eco: 0.22, premium: 0.05 }
|
|
2003
|
+
},
|
|
2004
|
+
classifier: {
|
|
2005
|
+
llmModel: "google/gemini-2.5-flash",
|
|
2006
|
+
llmMaxTokens: 10,
|
|
2007
|
+
llmTemperature: 0,
|
|
2008
|
+
promptTruncationChars: 500,
|
|
2009
|
+
cacheTtlMs: 36e5
|
|
2010
|
+
// 1 hour
|
|
2011
|
+
},
|
|
2012
|
+
scoring: {
|
|
2013
|
+
tokenCountThresholds: { simple: 50, complex: 500 },
|
|
2014
|
+
// Multilingual keywords: EN + ZH + JA + RU + DE + ES + PT + KO + AR
|
|
2015
|
+
codeKeywords: [
|
|
2016
|
+
// English
|
|
2017
|
+
"function",
|
|
2018
|
+
"class",
|
|
2019
|
+
"import",
|
|
2020
|
+
"def",
|
|
2021
|
+
"SELECT",
|
|
2022
|
+
"async",
|
|
2023
|
+
"await",
|
|
2024
|
+
"const",
|
|
2025
|
+
"let",
|
|
2026
|
+
"var",
|
|
2027
|
+
"return",
|
|
2028
|
+
"```",
|
|
2029
|
+
// Chinese
|
|
2030
|
+
"\u51FD\u6570",
|
|
2031
|
+
"\u7C7B",
|
|
2032
|
+
"\u5BFC\u5165",
|
|
2033
|
+
"\u5B9A\u4E49",
|
|
2034
|
+
"\u67E5\u8BE2",
|
|
2035
|
+
"\u5F02\u6B65",
|
|
2036
|
+
"\u7B49\u5F85",
|
|
2037
|
+
"\u5E38\u91CF",
|
|
2038
|
+
"\u53D8\u91CF",
|
|
2039
|
+
"\u8FD4\u56DE",
|
|
2040
|
+
// Japanese
|
|
2041
|
+
"\u95A2\u6570",
|
|
2042
|
+
"\u30AF\u30E9\u30B9",
|
|
2043
|
+
"\u30A4\u30F3\u30DD\u30FC\u30C8",
|
|
2044
|
+
"\u975E\u540C\u671F",
|
|
2045
|
+
"\u5B9A\u6570",
|
|
2046
|
+
"\u5909\u6570",
|
|
2047
|
+
// Russian
|
|
2048
|
+
"\u0444\u0443\u043D\u043A\u0446\u0438\u044F",
|
|
2049
|
+
"\u043A\u043B\u0430\u0441\u0441",
|
|
2050
|
+
"\u0438\u043C\u043F\u043E\u0440\u0442",
|
|
2051
|
+
"\u043E\u043F\u0440\u0435\u0434\u0435\u043B",
|
|
2052
|
+
"\u0437\u0430\u043F\u0440\u043E\u0441",
|
|
2053
|
+
"\u0430\u0441\u0438\u043D\u0445\u0440\u043E\u043D\u043D\u044B\u0439",
|
|
2054
|
+
"\u043E\u0436\u0438\u0434\u0430\u0442\u044C",
|
|
2055
|
+
"\u043A\u043E\u043D\u0441\u0442\u0430\u043D\u0442\u0430",
|
|
2056
|
+
"\u043F\u0435\u0440\u0435\u043C\u0435\u043D\u043D\u0430\u044F",
|
|
2057
|
+
"\u0432\u0435\u0440\u043D\u0443\u0442\u044C",
|
|
2058
|
+
// German
|
|
2059
|
+
"funktion",
|
|
2060
|
+
"klasse",
|
|
2061
|
+
"importieren",
|
|
2062
|
+
"definieren",
|
|
2063
|
+
"abfrage",
|
|
2064
|
+
"asynchron",
|
|
2065
|
+
"erwarten",
|
|
2066
|
+
"konstante",
|
|
2067
|
+
"variable",
|
|
2068
|
+
"zur\xFCckgeben",
|
|
2069
|
+
// Spanish
|
|
2070
|
+
"funci\xF3n",
|
|
2071
|
+
"clase",
|
|
2072
|
+
"importar",
|
|
2073
|
+
"definir",
|
|
2074
|
+
"consulta",
|
|
2075
|
+
"as\xEDncrono",
|
|
2076
|
+
"esperar",
|
|
2077
|
+
"constante",
|
|
2078
|
+
"variable",
|
|
2079
|
+
"retornar",
|
|
2080
|
+
// Portuguese
|
|
2081
|
+
"fun\xE7\xE3o",
|
|
2082
|
+
"classe",
|
|
2083
|
+
"importar",
|
|
2084
|
+
"definir",
|
|
2085
|
+
"consulta",
|
|
2086
|
+
"ass\xEDncrono",
|
|
2087
|
+
"aguardar",
|
|
2088
|
+
"constante",
|
|
2089
|
+
"vari\xE1vel",
|
|
2090
|
+
"retornar",
|
|
2091
|
+
// Korean
|
|
2092
|
+
"\uD568\uC218",
|
|
2093
|
+
"\uD074\uB798\uC2A4",
|
|
2094
|
+
"\uAC00\uC838\uC624\uAE30",
|
|
2095
|
+
"\uC815\uC758",
|
|
2096
|
+
"\uCFFC\uB9AC",
|
|
2097
|
+
"\uBE44\uB3D9\uAE30",
|
|
2098
|
+
"\uB300\uAE30",
|
|
2099
|
+
"\uC0C1\uC218",
|
|
2100
|
+
"\uBCC0\uC218",
|
|
2101
|
+
"\uBC18\uD658",
|
|
2102
|
+
// Arabic
|
|
2103
|
+
"\u062F\u0627\u0644\u0629",
|
|
2104
|
+
"\u0641\u0626\u0629",
|
|
2105
|
+
"\u0627\u0633\u062A\u064A\u0631\u0627\u062F",
|
|
2106
|
+
"\u062A\u0639\u0631\u064A\u0641",
|
|
2107
|
+
"\u0627\u0633\u062A\u0639\u0644\u0627\u0645",
|
|
2108
|
+
"\u063A\u064A\u0631 \u0645\u062A\u0632\u0627\u0645\u0646",
|
|
2109
|
+
"\u0627\u0646\u062A\u0638\u0627\u0631",
|
|
2110
|
+
"\u062B\u0627\u0628\u062A",
|
|
2111
|
+
"\u0645\u062A\u063A\u064A\u0631",
|
|
2112
|
+
"\u0625\u0631\u062C\u0627\u0639"
|
|
2113
|
+
],
|
|
2114
|
+
reasoningKeywords: [
|
|
2115
|
+
// English
|
|
2116
|
+
"prove",
|
|
2117
|
+
"theorem",
|
|
2118
|
+
"derive",
|
|
2119
|
+
"step by step",
|
|
2120
|
+
"chain of thought",
|
|
2121
|
+
"formally",
|
|
2122
|
+
"mathematical",
|
|
2123
|
+
"proof",
|
|
2124
|
+
"logically",
|
|
2125
|
+
// Chinese
|
|
2126
|
+
"\u8BC1\u660E",
|
|
2127
|
+
"\u5B9A\u7406",
|
|
2128
|
+
"\u63A8\u5BFC",
|
|
2129
|
+
"\u9010\u6B65",
|
|
2130
|
+
"\u601D\u7EF4\u94FE",
|
|
2131
|
+
"\u5F62\u5F0F\u5316",
|
|
2132
|
+
"\u6570\u5B66",
|
|
2133
|
+
"\u903B\u8F91",
|
|
2134
|
+
// Japanese
|
|
2135
|
+
"\u8A3C\u660E",
|
|
2136
|
+
"\u5B9A\u7406",
|
|
2137
|
+
"\u5C0E\u51FA",
|
|
2138
|
+
"\u30B9\u30C6\u30C3\u30D7\u30D0\u30A4\u30B9\u30C6\u30C3\u30D7",
|
|
2139
|
+
"\u8AD6\u7406\u7684",
|
|
2140
|
+
// Russian
|
|
2141
|
+
"\u0434\u043E\u043A\u0430\u0437\u0430\u0442\u044C",
|
|
2142
|
+
"\u0434\u043E\u043A\u0430\u0436\u0438",
|
|
2143
|
+
"\u0434\u043E\u043A\u0430\u0437\u0430\u0442\u0435\u043B\u044C\u0441\u0442\u0432",
|
|
2144
|
+
"\u0442\u0435\u043E\u0440\u0435\u043C\u0430",
|
|
2145
|
+
"\u0432\u044B\u0432\u0435\u0441\u0442\u0438",
|
|
2146
|
+
"\u0448\u0430\u0433 \u0437\u0430 \u0448\u0430\u0433\u043E\u043C",
|
|
2147
|
+
"\u043F\u043E\u0448\u0430\u0433\u043E\u0432\u043E",
|
|
2148
|
+
"\u043F\u043E\u044D\u0442\u0430\u043F\u043D\u043E",
|
|
2149
|
+
"\u0446\u0435\u043F\u043E\u0447\u043A\u0430 \u0440\u0430\u0441\u0441\u0443\u0436\u0434\u0435\u043D\u0438\u0439",
|
|
2150
|
+
"\u0440\u0430\u0441\u0441\u0443\u0436\u0434\u0435\u043D\u0438",
|
|
2151
|
+
"\u0444\u043E\u0440\u043C\u0430\u043B\u044C\u043D\u043E",
|
|
2152
|
+
"\u043C\u0430\u0442\u0435\u043C\u0430\u0442\u0438\u0447\u0435\u0441\u043A\u0438",
|
|
2153
|
+
"\u043B\u043E\u0433\u0438\u0447\u0435\u0441\u043A\u0438",
|
|
2154
|
+
// German
|
|
2155
|
+
"beweisen",
|
|
2156
|
+
"beweis",
|
|
2157
|
+
"theorem",
|
|
2158
|
+
"ableiten",
|
|
2159
|
+
"schritt f\xFCr schritt",
|
|
2160
|
+
"gedankenkette",
|
|
2161
|
+
"formal",
|
|
2162
|
+
"mathematisch",
|
|
2163
|
+
"logisch",
|
|
2164
|
+
// Spanish
|
|
2165
|
+
"demostrar",
|
|
2166
|
+
"teorema",
|
|
2167
|
+
"derivar",
|
|
2168
|
+
"paso a paso",
|
|
2169
|
+
"cadena de pensamiento",
|
|
2170
|
+
"formalmente",
|
|
2171
|
+
"matem\xE1tico",
|
|
2172
|
+
"prueba",
|
|
2173
|
+
"l\xF3gicamente",
|
|
2174
|
+
// Portuguese
|
|
2175
|
+
"provar",
|
|
2176
|
+
"teorema",
|
|
2177
|
+
"derivar",
|
|
2178
|
+
"passo a passo",
|
|
2179
|
+
"cadeia de pensamento",
|
|
2180
|
+
"formalmente",
|
|
2181
|
+
"matem\xE1tico",
|
|
2182
|
+
"prova",
|
|
2183
|
+
"logicamente",
|
|
2184
|
+
// Korean
|
|
2185
|
+
"\uC99D\uBA85",
|
|
2186
|
+
"\uC815\uB9AC",
|
|
2187
|
+
"\uB3C4\uCD9C",
|
|
2188
|
+
"\uB2E8\uACC4\uBCC4",
|
|
2189
|
+
"\uC0AC\uACE0\uC758 \uC5F0\uC1C4",
|
|
2190
|
+
"\uD615\uC2DD\uC801",
|
|
2191
|
+
"\uC218\uD559\uC801",
|
|
2192
|
+
"\uB17C\uB9AC\uC801",
|
|
2193
|
+
// Arabic
|
|
2194
|
+
"\u0625\u062B\u0628\u0627\u062A",
|
|
2195
|
+
"\u0646\u0638\u0631\u064A\u0629",
|
|
2196
|
+
"\u0627\u0634\u062A\u0642\u0627\u0642",
|
|
2197
|
+
"\u062E\u0637\u0648\u0629 \u0628\u062E\u0637\u0648\u0629",
|
|
2198
|
+
"\u0633\u0644\u0633\u0644\u0629 \u0627\u0644\u062A\u0641\u0643\u064A\u0631",
|
|
2199
|
+
"\u0631\u0633\u0645\u064A\u0627\u064B",
|
|
2200
|
+
"\u0631\u064A\u0627\u0636\u064A",
|
|
2201
|
+
"\u0628\u0631\u0647\u0627\u0646",
|
|
2202
|
+
"\u0645\u0646\u0637\u0642\u064A\u0627\u064B"
|
|
2203
|
+
],
|
|
2204
|
+
simpleKeywords: [
|
|
2205
|
+
// English
|
|
2206
|
+
"what is",
|
|
2207
|
+
"define",
|
|
2208
|
+
"translate",
|
|
2209
|
+
"hello",
|
|
2210
|
+
"yes or no",
|
|
2211
|
+
"capital of",
|
|
2212
|
+
"how old",
|
|
2213
|
+
"who is",
|
|
2214
|
+
"when was",
|
|
2215
|
+
// Chinese
|
|
2216
|
+
"\u4EC0\u4E48\u662F",
|
|
2217
|
+
"\u5B9A\u4E49",
|
|
2218
|
+
"\u7FFB\u8BD1",
|
|
2219
|
+
"\u4F60\u597D",
|
|
2220
|
+
"\u662F\u5426",
|
|
2221
|
+
"\u9996\u90FD",
|
|
2222
|
+
"\u591A\u5927",
|
|
2223
|
+
"\u8C01\u662F",
|
|
2224
|
+
"\u4F55\u65F6",
|
|
2225
|
+
// Japanese
|
|
2226
|
+
"\u3068\u306F",
|
|
2227
|
+
"\u5B9A\u7FA9",
|
|
2228
|
+
"\u7FFB\u8A33",
|
|
2229
|
+
"\u3053\u3093\u306B\u3061\u306F",
|
|
2230
|
+
"\u306F\u3044\u304B\u3044\u3044\u3048",
|
|
2231
|
+
"\u9996\u90FD",
|
|
2232
|
+
"\u8AB0",
|
|
2233
|
+
// Russian
|
|
2234
|
+
"\u0447\u0442\u043E \u0442\u0430\u043A\u043E\u0435",
|
|
2235
|
+
"\u043E\u043F\u0440\u0435\u0434\u0435\u043B\u0435\u043D\u0438\u0435",
|
|
2236
|
+
"\u043F\u0435\u0440\u0435\u0432\u0435\u0441\u0442\u0438",
|
|
2237
|
+
"\u043F\u0435\u0440\u0435\u0432\u0435\u0434\u0438",
|
|
2238
|
+
"\u043F\u0440\u0438\u0432\u0435\u0442",
|
|
2239
|
+
"\u0434\u0430 \u0438\u043B\u0438 \u043D\u0435\u0442",
|
|
2240
|
+
"\u0441\u0442\u043E\u043B\u0438\u0446\u0430",
|
|
2241
|
+
"\u0441\u043A\u043E\u043B\u044C\u043A\u043E \u043B\u0435\u0442",
|
|
2242
|
+
"\u043A\u0442\u043E \u0442\u0430\u043A\u043E\u0439",
|
|
2243
|
+
"\u043A\u043E\u0433\u0434\u0430",
|
|
2244
|
+
"\u043E\u0431\u044A\u044F\u0441\u043D\u0438",
|
|
2245
|
+
// German
|
|
2246
|
+
"was ist",
|
|
2247
|
+
"definiere",
|
|
2248
|
+
"\xFCbersetze",
|
|
2249
|
+
"hallo",
|
|
2250
|
+
"ja oder nein",
|
|
2251
|
+
"hauptstadt",
|
|
2252
|
+
"wie alt",
|
|
2253
|
+
"wer ist",
|
|
2254
|
+
"wann",
|
|
2255
|
+
"erkl\xE4re",
|
|
2256
|
+
// Spanish
|
|
2257
|
+
"qu\xE9 es",
|
|
2258
|
+
"definir",
|
|
2259
|
+
"traducir",
|
|
2260
|
+
"hola",
|
|
2261
|
+
"s\xED o no",
|
|
2262
|
+
"capital de",
|
|
2263
|
+
"cu\xE1ntos a\xF1os",
|
|
2264
|
+
"qui\xE9n es",
|
|
2265
|
+
"cu\xE1ndo",
|
|
2266
|
+
// Portuguese
|
|
2267
|
+
"o que \xE9",
|
|
2268
|
+
"definir",
|
|
2269
|
+
"traduzir",
|
|
2270
|
+
"ol\xE1",
|
|
2271
|
+
"sim ou n\xE3o",
|
|
2272
|
+
"capital de",
|
|
2273
|
+
"quantos anos",
|
|
2274
|
+
"quem \xE9",
|
|
2275
|
+
"quando",
|
|
2276
|
+
// Korean
|
|
2277
|
+
"\uBB34\uC5C7",
|
|
2278
|
+
"\uC815\uC758",
|
|
2279
|
+
"\uBC88\uC5ED",
|
|
2280
|
+
"\uC548\uB155\uD558\uC138\uC694",
|
|
2281
|
+
"\uC608 \uB610\uB294 \uC544\uB2C8\uC624",
|
|
2282
|
+
"\uC218\uB3C4",
|
|
2283
|
+
"\uB204\uAD6C",
|
|
2284
|
+
"\uC5B8\uC81C",
|
|
2285
|
+
// Arabic
|
|
2286
|
+
"\u0645\u0627 \u0647\u0648",
|
|
2287
|
+
"\u062A\u0639\u0631\u064A\u0641",
|
|
2288
|
+
"\u062A\u0631\u062C\u0645",
|
|
2289
|
+
"\u0645\u0631\u062D\u0628\u0627",
|
|
2290
|
+
"\u0646\u0639\u0645 \u0623\u0648 \u0644\u0627",
|
|
2291
|
+
"\u0639\u0627\u0635\u0645\u0629",
|
|
2292
|
+
"\u0645\u0646 \u0647\u0648",
|
|
2293
|
+
"\u0645\u062A\u0649"
|
|
2294
|
+
],
|
|
2295
|
+
technicalKeywords: [
|
|
2296
|
+
// English
|
|
2297
|
+
"algorithm",
|
|
2298
|
+
"optimize",
|
|
2299
|
+
"architecture",
|
|
2300
|
+
"distributed",
|
|
2301
|
+
"kubernetes",
|
|
2302
|
+
"microservice",
|
|
2303
|
+
"database",
|
|
2304
|
+
"infrastructure",
|
|
2305
|
+
// Chinese
|
|
2306
|
+
"\u7B97\u6CD5",
|
|
2307
|
+
"\u4F18\u5316",
|
|
2308
|
+
"\u67B6\u6784",
|
|
2309
|
+
"\u5206\u5E03\u5F0F",
|
|
2310
|
+
"\u5FAE\u670D\u52A1",
|
|
2311
|
+
"\u6570\u636E\u5E93",
|
|
2312
|
+
"\u57FA\u7840\u8BBE\u65BD",
|
|
2313
|
+
// Japanese
|
|
2314
|
+
"\u30A2\u30EB\u30B4\u30EA\u30BA\u30E0",
|
|
2315
|
+
"\u6700\u9069\u5316",
|
|
2316
|
+
"\u30A2\u30FC\u30AD\u30C6\u30AF\u30C1\u30E3",
|
|
2317
|
+
"\u5206\u6563",
|
|
2318
|
+
"\u30DE\u30A4\u30AF\u30ED\u30B5\u30FC\u30D3\u30B9",
|
|
2319
|
+
"\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9",
|
|
2320
|
+
// Russian
|
|
2321
|
+
"\u0430\u043B\u0433\u043E\u0440\u0438\u0442\u043C",
|
|
2322
|
+
"\u043E\u043F\u0442\u0438\u043C\u0438\u0437\u0438\u0440\u043E\u0432\u0430\u0442\u044C",
|
|
2323
|
+
"\u043E\u043F\u0442\u0438\u043C\u0438\u0437\u0430\u0446\u0438",
|
|
2324
|
+
"\u043E\u043F\u0442\u0438\u043C\u0438\u0437\u0438\u0440\u0443\u0439",
|
|
2325
|
+
"\u0430\u0440\u0445\u0438\u0442\u0435\u043A\u0442\u0443\u0440\u0430",
|
|
2326
|
+
"\u0440\u0430\u0441\u043F\u0440\u0435\u0434\u0435\u043B\u0451\u043D\u043D\u044B\u0439",
|
|
2327
|
+
"\u043C\u0438\u043A\u0440\u043E\u0441\u0435\u0440\u0432\u0438\u0441",
|
|
2328
|
+
"\u0431\u0430\u0437\u0430 \u0434\u0430\u043D\u043D\u044B\u0445",
|
|
2329
|
+
"\u0438\u043D\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043A\u0442\u0443\u0440\u0430",
|
|
2330
|
+
// German
|
|
2331
|
+
"algorithmus",
|
|
2332
|
+
"optimieren",
|
|
2333
|
+
"architektur",
|
|
2334
|
+
"verteilt",
|
|
2335
|
+
"kubernetes",
|
|
2336
|
+
"mikroservice",
|
|
2337
|
+
"datenbank",
|
|
2338
|
+
"infrastruktur",
|
|
2339
|
+
// Spanish
|
|
2340
|
+
"algoritmo",
|
|
2341
|
+
"optimizar",
|
|
2342
|
+
"arquitectura",
|
|
2343
|
+
"distribuido",
|
|
2344
|
+
"microservicio",
|
|
2345
|
+
"base de datos",
|
|
2346
|
+
"infraestructura",
|
|
2347
|
+
// Portuguese
|
|
2348
|
+
"algoritmo",
|
|
2349
|
+
"otimizar",
|
|
2350
|
+
"arquitetura",
|
|
2351
|
+
"distribu\xEDdo",
|
|
2352
|
+
"microsservi\xE7o",
|
|
2353
|
+
"banco de dados",
|
|
2354
|
+
"infraestrutura",
|
|
2355
|
+
// Korean
|
|
2356
|
+
"\uC54C\uACE0\uB9AC\uC998",
|
|
2357
|
+
"\uCD5C\uC801\uD654",
|
|
2358
|
+
"\uC544\uD0A4\uD14D\uCC98",
|
|
2359
|
+
"\uBD84\uC0B0",
|
|
2360
|
+
"\uB9C8\uC774\uD06C\uB85C\uC11C\uBE44\uC2A4",
|
|
2361
|
+
"\uB370\uC774\uD130\uBCA0\uC774\uC2A4",
|
|
2362
|
+
"\uC778\uD504\uB77C",
|
|
2363
|
+
// Arabic
|
|
2364
|
+
"\u062E\u0648\u0627\u0631\u0632\u0645\u064A\u0629",
|
|
2365
|
+
"\u062A\u062D\u0633\u064A\u0646",
|
|
2366
|
+
"\u0628\u0646\u064A\u0629",
|
|
2367
|
+
"\u0645\u0648\u0632\u0639",
|
|
2368
|
+
"\u062E\u062F\u0645\u0629 \u0645\u0635\u063A\u0631\u0629",
|
|
2369
|
+
"\u0642\u0627\u0639\u062F\u0629 \u0628\u064A\u0627\u0646\u0627\u062A",
|
|
2370
|
+
"\u0628\u0646\u064A\u0629 \u062A\u062D\u062A\u064A\u0629"
|
|
2371
|
+
],
|
|
2372
|
+
creativeKeywords: [
|
|
2373
|
+
// English
|
|
2374
|
+
"story",
|
|
2375
|
+
"poem",
|
|
2376
|
+
"compose",
|
|
2377
|
+
"brainstorm",
|
|
2378
|
+
"creative",
|
|
2379
|
+
"imagine",
|
|
2380
|
+
"write a",
|
|
2381
|
+
// Chinese
|
|
2382
|
+
"\u6545\u4E8B",
|
|
2383
|
+
"\u8BD7",
|
|
2384
|
+
"\u521B\u4F5C",
|
|
2385
|
+
"\u5934\u8111\u98CE\u66B4",
|
|
2386
|
+
"\u521B\u610F",
|
|
2387
|
+
"\u60F3\u8C61",
|
|
2388
|
+
"\u5199\u4E00\u4E2A",
|
|
2389
|
+
// Japanese
|
|
2390
|
+
"\u7269\u8A9E",
|
|
2391
|
+
"\u8A69",
|
|
2392
|
+
"\u4F5C\u66F2",
|
|
2393
|
+
"\u30D6\u30EC\u30A4\u30F3\u30B9\u30C8\u30FC\u30E0",
|
|
2394
|
+
"\u5275\u9020\u7684",
|
|
2395
|
+
"\u60F3\u50CF",
|
|
2396
|
+
// Russian
|
|
2397
|
+
"\u0438\u0441\u0442\u043E\u0440\u0438\u044F",
|
|
2398
|
+
"\u0440\u0430\u0441\u0441\u043A\u0430\u0437",
|
|
2399
|
+
"\u0441\u0442\u0438\u0445\u043E\u0442\u0432\u043E\u0440\u0435\u043D\u0438\u0435",
|
|
2400
|
+
"\u0441\u043E\u0447\u0438\u043D\u0438\u0442\u044C",
|
|
2401
|
+
"\u0441\u043E\u0447\u0438\u043D\u0438",
|
|
2402
|
+
"\u043C\u043E\u0437\u0433\u043E\u0432\u043E\u0439 \u0448\u0442\u0443\u0440\u043C",
|
|
2403
|
+
"\u0442\u0432\u043E\u0440\u0447\u0435\u0441\u043A\u0438\u0439",
|
|
2404
|
+
"\u043F\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u0442\u044C",
|
|
2405
|
+
"\u043F\u0440\u0438\u0434\u0443\u043C\u0430\u0439",
|
|
2406
|
+
"\u043D\u0430\u043F\u0438\u0448\u0438",
|
|
2407
|
+
// German
|
|
2408
|
+
"geschichte",
|
|
2409
|
+
"gedicht",
|
|
2410
|
+
"komponieren",
|
|
2411
|
+
"brainstorming",
|
|
2412
|
+
"kreativ",
|
|
2413
|
+
"vorstellen",
|
|
2414
|
+
"schreibe",
|
|
2415
|
+
"erz\xE4hlung",
|
|
2416
|
+
// Spanish
|
|
2417
|
+
"historia",
|
|
2418
|
+
"poema",
|
|
2419
|
+
"componer",
|
|
2420
|
+
"lluvia de ideas",
|
|
2421
|
+
"creativo",
|
|
2422
|
+
"imaginar",
|
|
2423
|
+
"escribe",
|
|
2424
|
+
// Portuguese
|
|
2425
|
+
"hist\xF3ria",
|
|
2426
|
+
"poema",
|
|
2427
|
+
"compor",
|
|
2428
|
+
"criativo",
|
|
2429
|
+
"imaginar",
|
|
2430
|
+
"escreva",
|
|
2431
|
+
// Korean
|
|
2432
|
+
"\uC774\uC57C\uAE30",
|
|
2433
|
+
"\uC2DC",
|
|
2434
|
+
"\uC791\uACE1",
|
|
2435
|
+
"\uBE0C\uB808\uC778\uC2A4\uD1A0\uBC0D",
|
|
2436
|
+
"\uCC3D\uC758\uC801",
|
|
2437
|
+
"\uC0C1\uC0C1",
|
|
2438
|
+
"\uC791\uC131",
|
|
2439
|
+
// Arabic
|
|
2440
|
+
"\u0642\u0635\u0629",
|
|
2441
|
+
"\u0642\u0635\u064A\u062F\u0629",
|
|
2442
|
+
"\u062A\u0623\u0644\u064A\u0641",
|
|
2443
|
+
"\u0639\u0635\u0641 \u0630\u0647\u0646\u064A",
|
|
2444
|
+
"\u0625\u0628\u062F\u0627\u0639\u064A",
|
|
2445
|
+
"\u062A\u062E\u064A\u0644",
|
|
2446
|
+
"\u0627\u0643\u062A\u0628"
|
|
2447
|
+
],
|
|
2448
|
+
// New dimension keyword lists (multilingual)
|
|
2449
|
+
imperativeVerbs: [
|
|
2450
|
+
// English
|
|
2451
|
+
"build",
|
|
2452
|
+
"create",
|
|
2453
|
+
"implement",
|
|
2454
|
+
"design",
|
|
2455
|
+
"develop",
|
|
2456
|
+
"construct",
|
|
2457
|
+
"generate",
|
|
2458
|
+
"deploy",
|
|
2459
|
+
"configure",
|
|
2460
|
+
"set up",
|
|
2461
|
+
// Chinese
|
|
2462
|
+
"\u6784\u5EFA",
|
|
2463
|
+
"\u521B\u5EFA",
|
|
2464
|
+
"\u5B9E\u73B0",
|
|
2465
|
+
"\u8BBE\u8BA1",
|
|
2466
|
+
"\u5F00\u53D1",
|
|
2467
|
+
"\u751F\u6210",
|
|
2468
|
+
"\u90E8\u7F72",
|
|
2469
|
+
"\u914D\u7F6E",
|
|
2470
|
+
"\u8BBE\u7F6E",
|
|
2471
|
+
// Japanese
|
|
2472
|
+
"\u69CB\u7BC9",
|
|
2473
|
+
"\u4F5C\u6210",
|
|
2474
|
+
"\u5B9F\u88C5",
|
|
2475
|
+
"\u8A2D\u8A08",
|
|
2476
|
+
"\u958B\u767A",
|
|
2477
|
+
"\u751F\u6210",
|
|
2478
|
+
"\u30C7\u30D7\u30ED\u30A4",
|
|
2479
|
+
"\u8A2D\u5B9A",
|
|
2480
|
+
// Russian
|
|
2481
|
+
"\u043F\u043E\u0441\u0442\u0440\u043E\u0438\u0442\u044C",
|
|
2482
|
+
"\u043F\u043E\u0441\u0442\u0440\u043E\u0439",
|
|
2483
|
+
"\u0441\u043E\u0437\u0434\u0430\u0442\u044C",
|
|
2484
|
+
"\u0441\u043E\u0437\u0434\u0430\u0439",
|
|
2485
|
+
"\u0440\u0435\u0430\u043B\u0438\u0437\u043E\u0432\u0430\u0442\u044C",
|
|
2486
|
+
"\u0440\u0435\u0430\u043B\u0438\u0437\u0443\u0439",
|
|
2487
|
+
"\u0441\u043F\u0440\u043E\u0435\u043A\u0442\u0438\u0440\u043E\u0432\u0430\u0442\u044C",
|
|
2488
|
+
"\u0440\u0430\u0437\u0440\u0430\u0431\u043E\u0442\u0430\u0442\u044C",
|
|
2489
|
+
"\u0440\u0430\u0437\u0440\u0430\u0431\u043E\u0442\u0430\u0439",
|
|
2490
|
+
"\u0441\u043A\u043E\u043D\u0441\u0442\u0440\u0443\u0438\u0440\u043E\u0432\u0430\u0442\u044C",
|
|
2491
|
+
"\u0441\u0433\u0435\u043D\u0435\u0440\u0438\u0440\u043E\u0432\u0430\u0442\u044C",
|
|
2492
|
+
"\u0441\u0433\u0435\u043D\u0435\u0440\u0438\u0440\u0443\u0439",
|
|
2493
|
+
"\u0440\u0430\u0437\u0432\u0435\u0440\u043D\u0443\u0442\u044C",
|
|
2494
|
+
"\u0440\u0430\u0437\u0432\u0435\u0440\u043D\u0438",
|
|
2495
|
+
"\u043D\u0430\u0441\u0442\u0440\u043E\u0438\u0442\u044C",
|
|
2496
|
+
"\u043D\u0430\u0441\u0442\u0440\u043E\u0439",
|
|
2497
|
+
// German
|
|
2498
|
+
"erstellen",
|
|
2499
|
+
"bauen",
|
|
2500
|
+
"implementieren",
|
|
2501
|
+
"entwerfen",
|
|
2502
|
+
"entwickeln",
|
|
2503
|
+
"konstruieren",
|
|
2504
|
+
"generieren",
|
|
2505
|
+
"bereitstellen",
|
|
2506
|
+
"konfigurieren",
|
|
2507
|
+
"einrichten",
|
|
2508
|
+
// Spanish
|
|
2509
|
+
"construir",
|
|
2510
|
+
"crear",
|
|
2511
|
+
"implementar",
|
|
2512
|
+
"dise\xF1ar",
|
|
2513
|
+
"desarrollar",
|
|
2514
|
+
"generar",
|
|
2515
|
+
"desplegar",
|
|
2516
|
+
"configurar",
|
|
2517
|
+
// Portuguese
|
|
2518
|
+
"construir",
|
|
2519
|
+
"criar",
|
|
2520
|
+
"implementar",
|
|
2521
|
+
"projetar",
|
|
2522
|
+
"desenvolver",
|
|
2523
|
+
"gerar",
|
|
2524
|
+
"implantar",
|
|
2525
|
+
"configurar",
|
|
2526
|
+
// Korean
|
|
2527
|
+
"\uAD6C\uCD95",
|
|
2528
|
+
"\uC0DD\uC131",
|
|
2529
|
+
"\uAD6C\uD604",
|
|
2530
|
+
"\uC124\uACC4",
|
|
2531
|
+
"\uAC1C\uBC1C",
|
|
2532
|
+
"\uBC30\uD3EC",
|
|
2533
|
+
"\uC124\uC815",
|
|
2534
|
+
// Arabic
|
|
2535
|
+
"\u0628\u0646\u0627\u0621",
|
|
2536
|
+
"\u0625\u0646\u0634\u0627\u0621",
|
|
2537
|
+
"\u062A\u0646\u0641\u064A\u0630",
|
|
2538
|
+
"\u062A\u0635\u0645\u064A\u0645",
|
|
2539
|
+
"\u062A\u0637\u0648\u064A\u0631",
|
|
2540
|
+
"\u062A\u0648\u0644\u064A\u062F",
|
|
2541
|
+
"\u0646\u0634\u0631",
|
|
2542
|
+
"\u0625\u0639\u062F\u0627\u062F"
|
|
2543
|
+
],
|
|
2544
|
+
constraintIndicators: [
|
|
2545
|
+
// English
|
|
2546
|
+
"under",
|
|
2547
|
+
"at most",
|
|
2548
|
+
"at least",
|
|
2549
|
+
"within",
|
|
2550
|
+
"no more than",
|
|
2551
|
+
"o(",
|
|
2552
|
+
"maximum",
|
|
2553
|
+
"minimum",
|
|
2554
|
+
"limit",
|
|
2555
|
+
"budget",
|
|
2556
|
+
// Chinese
|
|
2557
|
+
"\u4E0D\u8D85\u8FC7",
|
|
2558
|
+
"\u81F3\u5C11",
|
|
2559
|
+
"\u6700\u591A",
|
|
2560
|
+
"\u5728\u5185",
|
|
2561
|
+
"\u6700\u5927",
|
|
2562
|
+
"\u6700\u5C0F",
|
|
2563
|
+
"\u9650\u5236",
|
|
2564
|
+
"\u9884\u7B97",
|
|
2565
|
+
// Japanese
|
|
2566
|
+
"\u4EE5\u4E0B",
|
|
2567
|
+
"\u6700\u5927",
|
|
2568
|
+
"\u6700\u5C0F",
|
|
2569
|
+
"\u5236\u9650",
|
|
2570
|
+
"\u4E88\u7B97",
|
|
2571
|
+
// Russian
|
|
2572
|
+
"\u043D\u0435 \u0431\u043E\u043B\u0435\u0435",
|
|
2573
|
+
"\u043D\u0435 \u043C\u0435\u043D\u0435\u0435",
|
|
2574
|
+
"\u043A\u0430\u043A \u043C\u0438\u043D\u0438\u043C\u0443\u043C",
|
|
2575
|
+
"\u0432 \u043F\u0440\u0435\u0434\u0435\u043B\u0430\u0445",
|
|
2576
|
+
"\u043C\u0430\u043A\u0441\u0438\u043C\u0443\u043C",
|
|
2577
|
+
"\u043C\u0438\u043D\u0438\u043C\u0443\u043C",
|
|
2578
|
+
"\u043E\u0433\u0440\u0430\u043D\u0438\u0447\u0435\u043D\u0438\u0435",
|
|
2579
|
+
"\u0431\u044E\u0434\u0436\u0435\u0442",
|
|
2580
|
+
// German
|
|
2581
|
+
"h\xF6chstens",
|
|
2582
|
+
"mindestens",
|
|
2583
|
+
"innerhalb",
|
|
2584
|
+
"nicht mehr als",
|
|
2585
|
+
"maximal",
|
|
2586
|
+
"minimal",
|
|
2587
|
+
"grenze",
|
|
2588
|
+
"budget",
|
|
2589
|
+
// Spanish
|
|
2590
|
+
"como m\xE1ximo",
|
|
2591
|
+
"al menos",
|
|
2592
|
+
"dentro de",
|
|
2593
|
+
"no m\xE1s de",
|
|
2594
|
+
"m\xE1ximo",
|
|
2595
|
+
"m\xEDnimo",
|
|
2596
|
+
"l\xEDmite",
|
|
2597
|
+
"presupuesto",
|
|
2598
|
+
// Portuguese
|
|
2599
|
+
"no m\xE1ximo",
|
|
2600
|
+
"pelo menos",
|
|
2601
|
+
"dentro de",
|
|
2602
|
+
"n\xE3o mais que",
|
|
2603
|
+
"m\xE1ximo",
|
|
2604
|
+
"m\xEDnimo",
|
|
2605
|
+
"limite",
|
|
2606
|
+
"or\xE7amento",
|
|
2607
|
+
// Korean
|
|
2608
|
+
"\uC774\uD558",
|
|
2609
|
+
"\uC774\uC0C1",
|
|
2610
|
+
"\uCD5C\uB300",
|
|
2611
|
+
"\uCD5C\uC18C",
|
|
2612
|
+
"\uC81C\uD55C",
|
|
2613
|
+
"\uC608\uC0B0",
|
|
2614
|
+
// Arabic
|
|
2615
|
+
"\u0639\u0644\u0649 \u0627\u0644\u0623\u0643\u062B\u0631",
|
|
2616
|
+
"\u0639\u0644\u0649 \u0627\u0644\u0623\u0642\u0644",
|
|
2617
|
+
"\u0636\u0645\u0646",
|
|
2618
|
+
"\u0644\u0627 \u064A\u0632\u064A\u062F \u0639\u0646",
|
|
2619
|
+
"\u0623\u0642\u0635\u0649",
|
|
2620
|
+
"\u0623\u062F\u0646\u0649",
|
|
2621
|
+
"\u062D\u062F",
|
|
2622
|
+
"\u0645\u064A\u0632\u0627\u0646\u064A\u0629"
|
|
2623
|
+
],
|
|
2624
|
+
outputFormatKeywords: [
|
|
2625
|
+
// English
|
|
2626
|
+
"json",
|
|
2627
|
+
"yaml",
|
|
2628
|
+
"xml",
|
|
2629
|
+
"table",
|
|
2630
|
+
"csv",
|
|
2631
|
+
"markdown",
|
|
2632
|
+
"schema",
|
|
2633
|
+
"format as",
|
|
2634
|
+
"structured",
|
|
2635
|
+
// Chinese
|
|
2636
|
+
"\u8868\u683C",
|
|
2637
|
+
"\u683C\u5F0F\u5316\u4E3A",
|
|
2638
|
+
"\u7ED3\u6784\u5316",
|
|
2639
|
+
// Japanese
|
|
2640
|
+
"\u30C6\u30FC\u30D6\u30EB",
|
|
2641
|
+
"\u30D5\u30A9\u30FC\u30DE\u30C3\u30C8",
|
|
2642
|
+
"\u69CB\u9020\u5316",
|
|
2643
|
+
// Russian
|
|
2644
|
+
"\u0442\u0430\u0431\u043B\u0438\u0446\u0430",
|
|
2645
|
+
"\u0444\u043E\u0440\u043C\u0430\u0442\u0438\u0440\u043E\u0432\u0430\u0442\u044C \u043A\u0430\u043A",
|
|
2646
|
+
"\u0441\u0442\u0440\u0443\u043A\u0442\u0443\u0440\u0438\u0440\u043E\u0432\u0430\u043D\u043D\u044B\u0439",
|
|
2647
|
+
// German
|
|
2648
|
+
"tabelle",
|
|
2649
|
+
"formatieren als",
|
|
2650
|
+
"strukturiert",
|
|
2651
|
+
// Spanish
|
|
2652
|
+
"tabla",
|
|
2653
|
+
"formatear como",
|
|
2654
|
+
"estructurado",
|
|
2655
|
+
// Portuguese
|
|
2656
|
+
"tabela",
|
|
2657
|
+
"formatar como",
|
|
2658
|
+
"estruturado",
|
|
2659
|
+
// Korean
|
|
2660
|
+
"\uD14C\uC774\uBE14",
|
|
2661
|
+
"\uD615\uC2DD",
|
|
2662
|
+
"\uAD6C\uC870\uD654",
|
|
2663
|
+
// Arabic
|
|
2664
|
+
"\u062C\u062F\u0648\u0644",
|
|
2665
|
+
"\u062A\u0646\u0633\u064A\u0642",
|
|
2666
|
+
"\u0645\u0646\u0638\u0645"
|
|
2667
|
+
],
|
|
2668
|
+
referenceKeywords: [
|
|
2669
|
+
// English
|
|
2670
|
+
"above",
|
|
2671
|
+
"below",
|
|
2672
|
+
"previous",
|
|
2673
|
+
"following",
|
|
2674
|
+
"the docs",
|
|
2675
|
+
"the api",
|
|
2676
|
+
"the code",
|
|
2677
|
+
"earlier",
|
|
2678
|
+
"attached",
|
|
2679
|
+
// Chinese
|
|
2680
|
+
"\u4E0A\u9762",
|
|
2681
|
+
"\u4E0B\u9762",
|
|
2682
|
+
"\u4E4B\u524D",
|
|
2683
|
+
"\u63A5\u4E0B\u6765",
|
|
2684
|
+
"\u6587\u6863",
|
|
2685
|
+
"\u4EE3\u7801",
|
|
2686
|
+
"\u9644\u4EF6",
|
|
2687
|
+
// Japanese
|
|
2688
|
+
"\u4E0A\u8A18",
|
|
2689
|
+
"\u4E0B\u8A18",
|
|
2690
|
+
"\u524D\u306E",
|
|
2691
|
+
"\u6B21\u306E",
|
|
2692
|
+
"\u30C9\u30AD\u30E5\u30E1\u30F3\u30C8",
|
|
2693
|
+
"\u30B3\u30FC\u30C9",
|
|
2694
|
+
// Russian
|
|
2695
|
+
"\u0432\u044B\u0448\u0435",
|
|
2696
|
+
"\u043D\u0438\u0436\u0435",
|
|
2697
|
+
"\u043F\u0440\u0435\u0434\u044B\u0434\u0443\u0449\u0438\u0439",
|
|
2698
|
+
"\u0441\u043B\u0435\u0434\u0443\u044E\u0449\u0438\u0439",
|
|
2699
|
+
"\u0434\u043E\u043A\u0443\u043C\u0435\u043D\u0442\u0430\u0446\u0438\u044F",
|
|
2700
|
+
"\u043A\u043E\u0434",
|
|
2701
|
+
"\u0440\u0430\u043D\u0435\u0435",
|
|
2702
|
+
"\u0432\u043B\u043E\u0436\u0435\u043D\u0438\u0435",
|
|
2703
|
+
// German
|
|
2704
|
+
"oben",
|
|
2705
|
+
"unten",
|
|
2706
|
+
"vorherige",
|
|
2707
|
+
"folgende",
|
|
2708
|
+
"dokumentation",
|
|
2709
|
+
"der code",
|
|
2710
|
+
"fr\xFCher",
|
|
2711
|
+
"anhang",
|
|
2712
|
+
// Spanish
|
|
2713
|
+
"arriba",
|
|
2714
|
+
"abajo",
|
|
2715
|
+
"anterior",
|
|
2716
|
+
"siguiente",
|
|
2717
|
+
"documentaci\xF3n",
|
|
2718
|
+
"el c\xF3digo",
|
|
2719
|
+
"adjunto",
|
|
2720
|
+
// Portuguese
|
|
2721
|
+
"acima",
|
|
2722
|
+
"abaixo",
|
|
2723
|
+
"anterior",
|
|
2724
|
+
"seguinte",
|
|
2725
|
+
"documenta\xE7\xE3o",
|
|
2726
|
+
"o c\xF3digo",
|
|
2727
|
+
"anexo",
|
|
2728
|
+
// Korean
|
|
2729
|
+
"\uC704",
|
|
2730
|
+
"\uC544\uB798",
|
|
2731
|
+
"\uC774\uC804",
|
|
2732
|
+
"\uB2E4\uC74C",
|
|
2733
|
+
"\uBB38\uC11C",
|
|
2734
|
+
"\uCF54\uB4DC",
|
|
2735
|
+
"\uCCA8\uBD80",
|
|
2736
|
+
// Arabic
|
|
2737
|
+
"\u0623\u0639\u0644\u0627\u0647",
|
|
2738
|
+
"\u0623\u062F\u0646\u0627\u0647",
|
|
2739
|
+
"\u0627\u0644\u0633\u0627\u0628\u0642",
|
|
2740
|
+
"\u0627\u0644\u062A\u0627\u0644\u064A",
|
|
2741
|
+
"\u0627\u0644\u0648\u062B\u0627\u0626\u0642",
|
|
2742
|
+
"\u0627\u0644\u0643\u0648\u062F",
|
|
2743
|
+
"\u0645\u0631\u0641\u0642"
|
|
2744
|
+
],
|
|
2745
|
+
negationKeywords: [
|
|
2746
|
+
// English
|
|
2747
|
+
"don't",
|
|
2748
|
+
"do not",
|
|
2749
|
+
"avoid",
|
|
2750
|
+
"never",
|
|
2751
|
+
"without",
|
|
2752
|
+
"except",
|
|
2753
|
+
"exclude",
|
|
2754
|
+
"no longer",
|
|
2755
|
+
// Chinese
|
|
2756
|
+
"\u4E0D\u8981",
|
|
2757
|
+
"\u907F\u514D",
|
|
2758
|
+
"\u4ECE\u4E0D",
|
|
2759
|
+
"\u6CA1\u6709",
|
|
2760
|
+
"\u9664\u4E86",
|
|
2761
|
+
"\u6392\u9664",
|
|
2762
|
+
// Japanese
|
|
2763
|
+
"\u3057\u306A\u3044\u3067",
|
|
2764
|
+
"\u907F\u3051\u308B",
|
|
2765
|
+
"\u6C7A\u3057\u3066",
|
|
2766
|
+
"\u306A\u3057\u3067",
|
|
2767
|
+
"\u9664\u304F",
|
|
2768
|
+
// Russian
|
|
2769
|
+
"\u043D\u0435 \u0434\u0435\u043B\u0430\u0439",
|
|
2770
|
+
"\u043D\u0435 \u043D\u0430\u0434\u043E",
|
|
2771
|
+
"\u043D\u0435\u043B\u044C\u0437\u044F",
|
|
2772
|
+
"\u0438\u0437\u0431\u0435\u0433\u0430\u0442\u044C",
|
|
2773
|
+
"\u043D\u0438\u043A\u043E\u0433\u0434\u0430",
|
|
2774
|
+
"\u0431\u0435\u0437",
|
|
2775
|
+
"\u043A\u0440\u043E\u043C\u0435",
|
|
2776
|
+
"\u0438\u0441\u043A\u043B\u044E\u0447\u0438\u0442\u044C",
|
|
2777
|
+
"\u0431\u043E\u043B\u044C\u0448\u0435 \u043D\u0435",
|
|
2778
|
+
// German
|
|
2779
|
+
"nicht",
|
|
2780
|
+
"vermeide",
|
|
2781
|
+
"niemals",
|
|
2782
|
+
"ohne",
|
|
2783
|
+
"au\xDFer",
|
|
2784
|
+
"ausschlie\xDFen",
|
|
2785
|
+
"nicht mehr",
|
|
2786
|
+
// Spanish
|
|
2787
|
+
"no hagas",
|
|
2788
|
+
"evitar",
|
|
2789
|
+
"nunca",
|
|
2790
|
+
"sin",
|
|
2791
|
+
"excepto",
|
|
2792
|
+
"excluir",
|
|
2793
|
+
// Portuguese
|
|
2794
|
+
"n\xE3o fa\xE7a",
|
|
2795
|
+
"evitar",
|
|
2796
|
+
"nunca",
|
|
2797
|
+
"sem",
|
|
2798
|
+
"exceto",
|
|
2799
|
+
"excluir",
|
|
2800
|
+
// Korean
|
|
2801
|
+
"\uD558\uC9C0 \uB9C8",
|
|
2802
|
+
"\uD53C\uD558\uB2E4",
|
|
2803
|
+
"\uC808\uB300",
|
|
2804
|
+
"\uC5C6\uC774",
|
|
2805
|
+
"\uC81C\uC678",
|
|
2806
|
+
// Arabic
|
|
2807
|
+
"\u0644\u0627 \u062A\u0641\u0639\u0644",
|
|
2808
|
+
"\u062A\u062C\u0646\u0628",
|
|
2809
|
+
"\u0623\u0628\u062F\u0627\u064B",
|
|
2810
|
+
"\u0628\u062F\u0648\u0646",
|
|
2811
|
+
"\u0628\u0627\u0633\u062A\u062B\u0646\u0627\u0621",
|
|
2812
|
+
"\u0627\u0633\u062A\u0628\u0639\u0627\u062F"
|
|
2813
|
+
],
|
|
2814
|
+
domainSpecificKeywords: [
|
|
2815
|
+
// English
|
|
2816
|
+
"quantum",
|
|
2817
|
+
"fpga",
|
|
2818
|
+
"vlsi",
|
|
2819
|
+
"risc-v",
|
|
2820
|
+
"asic",
|
|
2821
|
+
"photonics",
|
|
2822
|
+
"genomics",
|
|
2823
|
+
"proteomics",
|
|
2824
|
+
"topological",
|
|
2825
|
+
"homomorphic",
|
|
2826
|
+
"zero-knowledge",
|
|
2827
|
+
"lattice-based",
|
|
2828
|
+
// Chinese
|
|
2829
|
+
"\u91CF\u5B50",
|
|
2830
|
+
"\u5149\u5B50\u5B66",
|
|
2831
|
+
"\u57FA\u56E0\u7EC4\u5B66",
|
|
2832
|
+
"\u86CB\u767D\u8D28\u7EC4\u5B66",
|
|
2833
|
+
"\u62D3\u6251",
|
|
2834
|
+
"\u540C\u6001",
|
|
2835
|
+
"\u96F6\u77E5\u8BC6",
|
|
2836
|
+
"\u683C\u5BC6\u7801",
|
|
2837
|
+
// Japanese
|
|
2838
|
+
"\u91CF\u5B50",
|
|
2839
|
+
"\u30D5\u30A9\u30C8\u30CB\u30AF\u30B9",
|
|
2840
|
+
"\u30B2\u30CE\u30DF\u30AF\u30B9",
|
|
2841
|
+
"\u30C8\u30DD\u30ED\u30B8\u30AB\u30EB",
|
|
2842
|
+
// Russian
|
|
2843
|
+
"\u043A\u0432\u0430\u043D\u0442\u043E\u0432\u044B\u0439",
|
|
2844
|
+
"\u0444\u043E\u0442\u043E\u043D\u0438\u043A\u0430",
|
|
2845
|
+
"\u0433\u0435\u043D\u043E\u043C\u0438\u043A\u0430",
|
|
2846
|
+
"\u043F\u0440\u043E\u0442\u0435\u043E\u043C\u0438\u043A\u0430",
|
|
2847
|
+
"\u0442\u043E\u043F\u043E\u043B\u043E\u0433\u0438\u0447\u0435\u0441\u043A\u0438\u0439",
|
|
2848
|
+
"\u0433\u043E\u043C\u043E\u043C\u043E\u0440\u0444\u043D\u044B\u0439",
|
|
2849
|
+
"\u0441 \u043D\u0443\u043B\u0435\u0432\u044B\u043C \u0440\u0430\u0437\u0433\u043B\u0430\u0448\u0435\u043D\u0438\u0435\u043C",
|
|
2850
|
+
"\u043D\u0430 \u043E\u0441\u043D\u043E\u0432\u0435 \u0440\u0435\u0448\u0451\u0442\u043E\u043A",
|
|
2851
|
+
// German
|
|
2852
|
+
"quanten",
|
|
2853
|
+
"photonik",
|
|
2854
|
+
"genomik",
|
|
2855
|
+
"proteomik",
|
|
2856
|
+
"topologisch",
|
|
2857
|
+
"homomorph",
|
|
2858
|
+
"zero-knowledge",
|
|
2859
|
+
"gitterbasiert",
|
|
2860
|
+
// Spanish
|
|
2861
|
+
"cu\xE1ntico",
|
|
2862
|
+
"fot\xF3nica",
|
|
2863
|
+
"gen\xF3mica",
|
|
2864
|
+
"prote\xF3mica",
|
|
2865
|
+
"topol\xF3gico",
|
|
2866
|
+
"homom\xF3rfico",
|
|
2867
|
+
// Portuguese
|
|
2868
|
+
"qu\xE2ntico",
|
|
2869
|
+
"fot\xF4nica",
|
|
2870
|
+
"gen\xF4mica",
|
|
2871
|
+
"prote\xF4mica",
|
|
2872
|
+
"topol\xF3gico",
|
|
2873
|
+
"homom\xF3rfico",
|
|
2874
|
+
// Korean
|
|
2875
|
+
"\uC591\uC790",
|
|
2876
|
+
"\uD3EC\uD1A0\uB2C9\uC2A4",
|
|
2877
|
+
"\uC720\uC804\uCCB4\uD559",
|
|
2878
|
+
"\uC704\uC0C1",
|
|
2879
|
+
"\uB3D9\uD615",
|
|
2880
|
+
// Arabic
|
|
2881
|
+
"\u0643\u0645\u064A",
|
|
2882
|
+
"\u0636\u0648\u0626\u064A\u0627\u062A",
|
|
2883
|
+
"\u062C\u064A\u0646\u0648\u0645\u064A\u0627\u062A",
|
|
2884
|
+
"\u0637\u0648\u0628\u0648\u0644\u0648\u062C\u064A",
|
|
2885
|
+
"\u062A\u0645\u0627\u062B\u0644\u064A"
|
|
2886
|
+
],
|
|
2887
|
+
// Agentic task keywords - file ops, execution, multi-step, iterative work
|
|
2888
|
+
// Pruned: removed overly common words like "then", "first", "run", "test", "build"
|
|
2889
|
+
agenticTaskKeywords: [
|
|
2890
|
+
// English - File operations (clearly agentic)
|
|
2891
|
+
"read file",
|
|
2892
|
+
"read the file",
|
|
2893
|
+
"look at",
|
|
2894
|
+
"check the",
|
|
2895
|
+
"open the",
|
|
2896
|
+
"edit",
|
|
2897
|
+
"modify",
|
|
2898
|
+
"update the",
|
|
2899
|
+
"change the",
|
|
2900
|
+
"write to",
|
|
2901
|
+
"create file",
|
|
2902
|
+
// English - Execution (specific commands only)
|
|
2903
|
+
"execute",
|
|
2904
|
+
"deploy",
|
|
2905
|
+
"install",
|
|
2906
|
+
"npm",
|
|
2907
|
+
"pip",
|
|
2908
|
+
"compile",
|
|
2909
|
+
// English - Multi-step patterns (specific only)
|
|
2910
|
+
"after that",
|
|
2911
|
+
"and also",
|
|
2912
|
+
"once done",
|
|
2913
|
+
"step 1",
|
|
2914
|
+
"step 2",
|
|
2915
|
+
// English - Iterative work
|
|
2916
|
+
"fix",
|
|
2917
|
+
"debug",
|
|
2918
|
+
"until it works",
|
|
2919
|
+
"keep trying",
|
|
2920
|
+
"iterate",
|
|
2921
|
+
"make sure",
|
|
2922
|
+
"verify",
|
|
2923
|
+
"confirm",
|
|
2924
|
+
// Chinese (keep specific ones)
|
|
2925
|
+
"\u8BFB\u53D6\u6587\u4EF6",
|
|
2926
|
+
"\u67E5\u770B",
|
|
2927
|
+
"\u6253\u5F00",
|
|
2928
|
+
"\u7F16\u8F91",
|
|
2929
|
+
"\u4FEE\u6539",
|
|
2930
|
+
"\u66F4\u65B0",
|
|
2931
|
+
"\u521B\u5EFA",
|
|
2932
|
+
"\u6267\u884C",
|
|
2933
|
+
"\u90E8\u7F72",
|
|
2934
|
+
"\u5B89\u88C5",
|
|
2935
|
+
"\u7B2C\u4E00\u6B65",
|
|
2936
|
+
"\u7B2C\u4E8C\u6B65",
|
|
2937
|
+
"\u4FEE\u590D",
|
|
2938
|
+
"\u8C03\u8BD5",
|
|
2939
|
+
"\u76F4\u5230",
|
|
2940
|
+
"\u786E\u8BA4",
|
|
2941
|
+
"\u9A8C\u8BC1",
|
|
2942
|
+
// Spanish
|
|
2943
|
+
"leer archivo",
|
|
2944
|
+
"editar",
|
|
2945
|
+
"modificar",
|
|
2946
|
+
"actualizar",
|
|
2947
|
+
"ejecutar",
|
|
2948
|
+
"desplegar",
|
|
2949
|
+
"instalar",
|
|
2950
|
+
"paso 1",
|
|
2951
|
+
"paso 2",
|
|
2952
|
+
"arreglar",
|
|
2953
|
+
"depurar",
|
|
2954
|
+
"verificar",
|
|
2955
|
+
// Portuguese
|
|
2956
|
+
"ler arquivo",
|
|
2957
|
+
"editar",
|
|
2958
|
+
"modificar",
|
|
2959
|
+
"atualizar",
|
|
2960
|
+
"executar",
|
|
2961
|
+
"implantar",
|
|
2962
|
+
"instalar",
|
|
2963
|
+
"passo 1",
|
|
2964
|
+
"passo 2",
|
|
2965
|
+
"corrigir",
|
|
2966
|
+
"depurar",
|
|
2967
|
+
"verificar",
|
|
2968
|
+
// Korean
|
|
2969
|
+
"\uD30C\uC77C \uC77D\uAE30",
|
|
2970
|
+
"\uD3B8\uC9D1",
|
|
2971
|
+
"\uC218\uC815",
|
|
2972
|
+
"\uC5C5\uB370\uC774\uD2B8",
|
|
2973
|
+
"\uC2E4\uD589",
|
|
2974
|
+
"\uBC30\uD3EC",
|
|
2975
|
+
"\uC124\uCE58",
|
|
2976
|
+
"\uB2E8\uACC4 1",
|
|
2977
|
+
"\uB2E8\uACC4 2",
|
|
2978
|
+
"\uB514\uBC84\uADF8",
|
|
2979
|
+
"\uD655\uC778",
|
|
2980
|
+
// Arabic
|
|
2981
|
+
"\u0642\u0631\u0627\u0621\u0629 \u0645\u0644\u0641",
|
|
2982
|
+
"\u062A\u062D\u0631\u064A\u0631",
|
|
2983
|
+
"\u062A\u0639\u062F\u064A\u0644",
|
|
2984
|
+
"\u062A\u062D\u062F\u064A\u062B",
|
|
2985
|
+
"\u062A\u0646\u0641\u064A\u0630",
|
|
2986
|
+
"\u0646\u0634\u0631",
|
|
2987
|
+
"\u062A\u062B\u0628\u064A\u062A",
|
|
2988
|
+
"\u0627\u0644\u062E\u0637\u0648\u0629 1",
|
|
2989
|
+
"\u0627\u0644\u062E\u0637\u0648\u0629 2",
|
|
2990
|
+
"\u0625\u0635\u0644\u0627\u062D",
|
|
2991
|
+
"\u062A\u0635\u062D\u064A\u062D",
|
|
2992
|
+
"\u062A\u062D\u0642\u0642"
|
|
2993
|
+
],
|
|
2994
|
+
// Dimension weights (sum to 1.0)
|
|
2995
|
+
dimensionWeights: {
|
|
2996
|
+
tokenCount: 0.08,
|
|
2997
|
+
codePresence: 0.15,
|
|
2998
|
+
reasoningMarkers: 0.18,
|
|
2999
|
+
technicalTerms: 0.1,
|
|
3000
|
+
creativeMarkers: 0.05,
|
|
3001
|
+
simpleIndicators: 0.02,
|
|
3002
|
+
// Reduced from 0.12 to make room for agenticTask
|
|
3003
|
+
multiStepPatterns: 0.12,
|
|
3004
|
+
questionComplexity: 0.05,
|
|
3005
|
+
imperativeVerbs: 0.03,
|
|
3006
|
+
constraintCount: 0.04,
|
|
3007
|
+
outputFormat: 0.03,
|
|
3008
|
+
referenceComplexity: 0.02,
|
|
3009
|
+
negationComplexity: 0.01,
|
|
3010
|
+
domainSpecificity: 0.02,
|
|
3011
|
+
agenticTask: 0.04
|
|
3012
|
+
// Reduced - agentic signals influence tier selection, not dominate it
|
|
3013
|
+
},
|
|
3014
|
+
// Tier boundaries on weighted score axis
|
|
3015
|
+
tierBoundaries: {
|
|
3016
|
+
simpleMedium: 0,
|
|
3017
|
+
mediumComplex: 0.3,
|
|
3018
|
+
// Raised from 0.18 - prevent simple tasks from reaching expensive COMPLEX tier
|
|
3019
|
+
complexReasoning: 0.5
|
|
3020
|
+
// Raised from 0.4 - reserve for true reasoning tasks
|
|
3021
|
+
},
|
|
3022
|
+
// Sigmoid steepness for confidence calibration
|
|
3023
|
+
confidenceSteepness: 12,
|
|
3024
|
+
// Below this confidence → ambiguous (null tier)
|
|
3025
|
+
confidenceThreshold: 0.7
|
|
3026
|
+
},
|
|
3027
|
+
// Auto (balanced) tier configs - current default smart routing
|
|
3028
|
+
// Benchmark-tuned 2026-03-16: balancing quality (retention) + latency
|
|
3029
|
+
tiers: {
|
|
3030
|
+
SIMPLE: {
|
|
3031
|
+
primary: "google/gemini-2.5-flash",
|
|
3032
|
+
// 1,238ms, IQ 20, 60% retention (best) — fast AND quality
|
|
3033
|
+
fallback: [
|
|
3034
|
+
"google/gemini-3-flash-preview",
|
|
3035
|
+
// 1,398ms, IQ 46 — smarter fallback
|
|
3036
|
+
"deepseek/deepseek-chat",
|
|
3037
|
+
// V4 Flash chat ($0.20/$0.40, 1M ctx) — repriced 2026-04-24
|
|
3038
|
+
"moonshot/kimi-k2.5",
|
|
3039
|
+
// 1,646ms, IQ 47, strong quality
|
|
3040
|
+
"google/gemini-3.1-flash-lite",
|
|
3041
|
+
// $0.25/$1.50, 1M context — newest flash-lite
|
|
3042
|
+
"google/gemini-2.5-flash-lite",
|
|
3043
|
+
// 1,353ms, $0.10/$0.40
|
|
3044
|
+
"openai/gpt-5.4-nano",
|
|
3045
|
+
// $0.20/$1.25, 1M context
|
|
3046
|
+
"xai/grok-4-fast-non-reasoning",
|
|
3047
|
+
// 1,143ms, $0.20/$0.50 — fast fallback
|
|
3048
|
+
"free/gpt-oss-120b"
|
|
3049
|
+
// 1,252ms, FREE fallback (hidden from /v1/models but direct calls work)
|
|
3050
|
+
]
|
|
3051
|
+
},
|
|
3052
|
+
MEDIUM: {
|
|
3053
|
+
primary: "moonshot/kimi-k2.7",
|
|
3054
|
+
// $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.
|
|
3055
|
+
fallback: [
|
|
3056
|
+
"moonshot/kimi-k2.6",
|
|
3057
|
+
// identical-cost in-family hot swap (K2.6 still routable)
|
|
3058
|
+
"moonshot/kimi-k2.5",
|
|
3059
|
+
// $0.60/$3.00 — graceful-degradation backstop
|
|
3060
|
+
"google/gemini-3-flash-preview",
|
|
3061
|
+
// 1,398ms, IQ 46 — nearly same IQ, faster + cheaper
|
|
3062
|
+
"deepseek/deepseek-chat",
|
|
3063
|
+
// 1,431ms, IQ 32, 41% retention
|
|
3064
|
+
"google/gemini-2.5-flash",
|
|
3065
|
+
// 1,238ms, 60% retention
|
|
3066
|
+
"google/gemini-3.1-flash-lite",
|
|
3067
|
+
// $0.25/$1.50, 1M context
|
|
3068
|
+
"google/gemini-2.5-flash-lite",
|
|
3069
|
+
// 1,353ms, $0.10/$0.40
|
|
3070
|
+
"xai/grok-4-1-fast-non-reasoning",
|
|
3071
|
+
// 1,244ms, fast fallback
|
|
3072
|
+
"xai/grok-3-mini"
|
|
3073
|
+
// 1,202ms, $0.30/$0.50
|
|
3074
|
+
]
|
|
3075
|
+
},
|
|
3076
|
+
COMPLEX: {
|
|
3077
|
+
primary: "google/gemini-3.1-pro",
|
|
3078
|
+
// 1,609ms, IQ 57 — fast flagship quality
|
|
3079
|
+
fallback: [
|
|
3080
|
+
"google/gemini-3-flash-preview",
|
|
3081
|
+
// 1,398ms, IQ 46 — fast + smart
|
|
3082
|
+
"xai/grok-4-0709",
|
|
3083
|
+
// 1,348ms, IQ 41
|
|
3084
|
+
"google/gemini-2.5-pro",
|
|
3085
|
+
// 1,294ms
|
|
3086
|
+
"anthropic/claude-sonnet-5",
|
|
3087
|
+
// near-Opus quality at Sonnet cost, 1M ctx
|
|
3088
|
+
"anthropic/claude-sonnet-4.6",
|
|
3089
|
+
// 2,110ms, IQ 52 — quality fallback
|
|
3090
|
+
"deepseek/deepseek-chat",
|
|
3091
|
+
// 1,431ms, IQ 32
|
|
3092
|
+
"google/gemini-2.5-flash",
|
|
3093
|
+
// 1,238ms, IQ 20 — cheap last resort
|
|
3094
|
+
"openai/gpt-5.6-terra",
|
|
3095
|
+
// GPT-5.6 balanced tier — newest generation, stable (Sol excluded: #202)
|
|
3096
|
+
"openai/gpt-5.5",
|
|
3097
|
+
// Prior OpenAI flagship — 1M+ ctx, native agent + computer use; benchmark TBD
|
|
3098
|
+
"openai/gpt-5.4"
|
|
3099
|
+
// 6,213ms, IQ 57 — previous flagship, benchmarked
|
|
3100
|
+
]
|
|
3101
|
+
},
|
|
3102
|
+
REASONING: {
|
|
3103
|
+
primary: "xai/grok-4-1-fast-reasoning",
|
|
3104
|
+
// 1,454ms, $0.20/$0.50
|
|
3105
|
+
fallback: [
|
|
3106
|
+
"xai/grok-4-fast-reasoning",
|
|
3107
|
+
// 1,298ms, $0.20/$0.50
|
|
3108
|
+
"deepseek/deepseek-reasoner",
|
|
3109
|
+
// V4 Flash thinking ($0.20/$0.40, 1M ctx)
|
|
3110
|
+
"deepseek/deepseek-v4-pro",
|
|
3111
|
+
// V4 Pro flagship ($0.50/$1.00 promo through 2026-05-31, list $2/$4) — strongest open-weight reasoner
|
|
3112
|
+
"openai/o4-mini",
|
|
3113
|
+
// 2,328ms ($1.10/$4.40)
|
|
3114
|
+
"openai/o3"
|
|
3115
|
+
// 2,862ms
|
|
3116
|
+
]
|
|
3117
|
+
}
|
|
3118
|
+
},
|
|
3119
|
+
// Eco tier configs - absolute cheapest (blockrun/eco)
|
|
3120
|
+
ecoTiers: {
|
|
3121
|
+
SIMPLE: {
|
|
3122
|
+
primary: "free/gpt-oss-120b",
|
|
3123
|
+
// FREE! $0.00/$0.00 — heavy user default
|
|
3124
|
+
fallback: [
|
|
3125
|
+
"free/gpt-oss-20b",
|
|
3126
|
+
// FREE — smaller, faster
|
|
3127
|
+
"free/deepseek-v4-flash",
|
|
3128
|
+
// FREE — 1M ctx; slow (~10 tok/s, 07-28 probe) but completes
|
|
3129
|
+
// seed-oss-36b sat here as the free coder until it EOL'd 2026-08-03 (HTTP 410).
|
|
3130
|
+
// gpt-oss-120b/20b already head this chain, so the rung is dropped, not retargeted.
|
|
3131
|
+
"google/gemini-3.1-flash-lite",
|
|
3132
|
+
// $0.25/$1.50 — newest flash-lite
|
|
3133
|
+
"openai/gpt-5.4-nano",
|
|
3134
|
+
// $0.20/$1.25 — fast nano
|
|
3135
|
+
"google/gemini-2.5-flash-lite",
|
|
3136
|
+
// $0.10/$0.40
|
|
3137
|
+
"xai/grok-4-fast-non-reasoning"
|
|
3138
|
+
// $0.20/$0.50
|
|
3139
|
+
]
|
|
3140
|
+
},
|
|
3141
|
+
MEDIUM: {
|
|
3142
|
+
primary: "google/gemini-3.1-flash-lite",
|
|
3143
|
+
// $0.25/$1.50 — newest flash-lite
|
|
3144
|
+
fallback: [
|
|
3145
|
+
"openai/gpt-5.4-nano",
|
|
3146
|
+
// $0.20/$1.25
|
|
3147
|
+
"google/gemini-2.5-flash-lite",
|
|
3148
|
+
// $0.10/$0.40
|
|
3149
|
+
"xai/grok-4-fast-non-reasoning",
|
|
3150
|
+
"google/gemini-2.5-flash"
|
|
3151
|
+
]
|
|
3152
|
+
},
|
|
3153
|
+
COMPLEX: {
|
|
3154
|
+
primary: "google/gemini-3.1-flash-lite",
|
|
3155
|
+
// $0.25/$1.50
|
|
3156
|
+
fallback: [
|
|
3157
|
+
"google/gemini-2.5-flash-lite",
|
|
3158
|
+
"xai/grok-4-0709",
|
|
3159
|
+
"google/gemini-2.5-flash",
|
|
3160
|
+
"deepseek/deepseek-chat"
|
|
3161
|
+
]
|
|
3162
|
+
},
|
|
3163
|
+
REASONING: {
|
|
3164
|
+
primary: "xai/grok-4-1-fast-reasoning",
|
|
3165
|
+
// $0.20/$0.50
|
|
3166
|
+
fallback: [
|
|
3167
|
+
"xai/grok-4-fast-reasoning",
|
|
3168
|
+
"deepseek/deepseek-reasoner",
|
|
3169
|
+
// V4 Flash thinking — $0.20/$0.40
|
|
3170
|
+
"deepseek/deepseek-v4-pro"
|
|
3171
|
+
// V4 Pro flagship — $0.50/$1.00 promo, post-promo $2/$4
|
|
3172
|
+
]
|
|
3173
|
+
}
|
|
3174
|
+
},
|
|
3175
|
+
// Premium tier configs - best quality (blockrun/premium)
|
|
3176
|
+
// codex=complex coding, kimi=simple coding, sonnet=reasoning/instructions, opus=architecture/PM/audits
|
|
3177
|
+
premiumTiers: {
|
|
3178
|
+
SIMPLE: {
|
|
3179
|
+
primary: "moonshot/kimi-k2.7",
|
|
3180
|
+
// $0.95/$4.00 - Moonshot flagship (256K ctx, multi-modal + reasoning); promoted from K2.6 (2026-06-14), same price
|
|
3181
|
+
fallback: [
|
|
3182
|
+
"moonshot/kimi-k2.6",
|
|
3183
|
+
// identical-cost in-family hot swap (K2.6 still routable)
|
|
3184
|
+
"moonshot/kimi-k2.5",
|
|
3185
|
+
// $0.60/$3.00 - proven reliable backstop when Moonshot direct API falters
|
|
3186
|
+
"google/gemini-2.5-flash",
|
|
3187
|
+
// 60% retention, fast growth
|
|
3188
|
+
"anthropic/claude-haiku-4.5",
|
|
3189
|
+
"google/gemini-2.5-flash-lite",
|
|
3190
|
+
"deepseek/deepseek-chat"
|
|
3191
|
+
]
|
|
3192
|
+
},
|
|
3193
|
+
MEDIUM: {
|
|
3194
|
+
primary: "openai/gpt-5.3-codex",
|
|
3195
|
+
// $1.75/$14 - 400K context, 128K output, replaces 5.2
|
|
3196
|
+
fallback: [
|
|
3197
|
+
"moonshot/kimi-k2.7",
|
|
3198
|
+
// Moonshot flagship
|
|
3199
|
+
"moonshot/kimi-k2.6",
|
|
3200
|
+
"moonshot/kimi-k2.5",
|
|
3201
|
+
"google/gemini-2.5-flash",
|
|
3202
|
+
// 60% retention, good coding capability
|
|
3203
|
+
"google/gemini-2.5-pro",
|
|
3204
|
+
"xai/grok-4-0709",
|
|
3205
|
+
"anthropic/claude-sonnet-5",
|
|
3206
|
+
"anthropic/claude-sonnet-4.6"
|
|
3207
|
+
]
|
|
3208
|
+
},
|
|
3209
|
+
COMPLEX: {
|
|
3210
|
+
// fable-5 was promoted here 2026-06-11, force-reverted 2026-06-13 when Anthropic
|
|
3211
|
+
// withdrew the offer, and restored 2026-07-14 now that BlockRun has relisted it.
|
|
3212
|
+
primary: "anthropic/claude-fable-5",
|
|
3213
|
+
// Best quality for complex tasks — Mythos-class flagship above Opus ($10/$50, 1M ctx, always-on thinking)
|
|
3214
|
+
// Fallback chain de-Gemini'd 2026-04-22: when Anthropic 503s, Gemini is
|
|
3215
|
+
// also prone to "high demand" 503s (correlated failure — everyone falls
|
|
3216
|
+
// back to Google at the same time). Prefer xAI Grok → Moonshot → OpenAI
|
|
3217
|
+
// flagship → DeepSeek → NVIDIA free instead.
|
|
3218
|
+
fallback: [
|
|
3219
|
+
"anthropic/claude-opus-5",
|
|
3220
|
+
// in-family hot swap first (half the price, 1M ctx + adaptive thinking)
|
|
3221
|
+
"anthropic/claude-opus-4.8",
|
|
3222
|
+
// in-family hot swap (identical cost to 5)
|
|
3223
|
+
"anthropic/claude-opus-4.7",
|
|
3224
|
+
// in-family hot swap (identical cost to 4.8)
|
|
3225
|
+
"anthropic/claude-opus-4.6",
|
|
3226
|
+
// in-family hot swap
|
|
3227
|
+
"anthropic/claude-sonnet-5",
|
|
3228
|
+
// Sonnet-tier drop-down, near-Opus quality
|
|
3229
|
+
"anthropic/claude-sonnet-4.6",
|
|
3230
|
+
"xai/grok-4.5",
|
|
3231
|
+
// xAI flagship — 503-resistant, direct-xAI SKU (added 2026-07-14)
|
|
3232
|
+
"xai/grok-4-0709",
|
|
3233
|
+
// 503-resistant flagship
|
|
3234
|
+
"moonshot/kimi-k2.7",
|
|
3235
|
+
// Moonshot flagship, independent infra
|
|
3236
|
+
"moonshot/kimi-k2.6",
|
|
3237
|
+
"moonshot/kimi-k2.5",
|
|
3238
|
+
"openai/gpt-5.6-terra",
|
|
3239
|
+
// GPT-5.6 balanced tier — newest generation, stable (Sol excluded: #202)
|
|
3240
|
+
"openai/gpt-5.5",
|
|
3241
|
+
// Prior OpenAI flagship — 1M+ ctx, native agent + computer use
|
|
3242
|
+
"openai/gpt-5.4",
|
|
3243
|
+
// Previous flagship (slow but stable, benchmarked at 6,213ms)
|
|
3244
|
+
"openai/gpt-5.3-codex",
|
|
3245
|
+
"deepseek/deepseek-chat",
|
|
3246
|
+
// Cheap, reliable
|
|
3247
|
+
"free/gpt-oss-120b"
|
|
3248
|
+
// NVIDIA free ultimate backstop (was seed-oss-36b; EOL'd 2026-08-03)
|
|
3249
|
+
]
|
|
3250
|
+
},
|
|
3251
|
+
REASONING: {
|
|
3252
|
+
primary: "anthropic/claude-sonnet-4.6",
|
|
3253
|
+
// 2,110ms, $3/$15 - best for reasoning/instructions
|
|
3254
|
+
fallback: [
|
|
3255
|
+
"anthropic/claude-sonnet-5",
|
|
3256
|
+
// in-family hot swap — same cost, adaptive thinking, 1M ctx
|
|
3257
|
+
"anthropic/claude-opus-5",
|
|
3258
|
+
// Newest flagship Opus w/ adaptive thinking
|
|
3259
|
+
"anthropic/claude-opus-4.8",
|
|
3260
|
+
// Prior flagship Opus — identical cost to 5
|
|
3261
|
+
"anthropic/claude-opus-4.7",
|
|
3262
|
+
// Flagship Opus w/ adaptive thinking
|
|
3263
|
+
"anthropic/claude-opus-4.6",
|
|
3264
|
+
// 2,139ms
|
|
3265
|
+
"xai/grok-4-1-fast-reasoning",
|
|
3266
|
+
// 1,454ms, cheap fast reasoning
|
|
3267
|
+
"openai/o4-mini",
|
|
3268
|
+
// 2,328ms ($1.10/$4.40)
|
|
3269
|
+
"openai/o3"
|
|
3270
|
+
// 2,862ms
|
|
3271
|
+
]
|
|
3272
|
+
}
|
|
3273
|
+
},
|
|
3274
|
+
// Agentic tier configs - models that excel at multi-step autonomous tasks
|
|
3275
|
+
agenticTiers: {
|
|
3276
|
+
SIMPLE: {
|
|
3277
|
+
primary: "openai/gpt-4o-mini",
|
|
3278
|
+
// $0.15/$0.60 - best tool compliance at lowest cost
|
|
3279
|
+
fallback: [
|
|
3280
|
+
"moonshot/kimi-k2.5",
|
|
3281
|
+
// 1,646ms, strong tool use quality
|
|
3282
|
+
"anthropic/claude-haiku-4.5",
|
|
3283
|
+
// 2,305ms
|
|
3284
|
+
"xai/grok-4-1-fast-non-reasoning"
|
|
3285
|
+
// 1,244ms, fast fallback
|
|
3286
|
+
]
|
|
3287
|
+
},
|
|
3288
|
+
MEDIUM: {
|
|
3289
|
+
primary: "moonshot/kimi-k2.7",
|
|
3290
|
+
// $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.
|
|
3291
|
+
fallback: [
|
|
3292
|
+
"moonshot/kimi-k2.6",
|
|
3293
|
+
// identical-cost in-family hot swap (K2.6 still routable)
|
|
3294
|
+
"moonshot/kimi-k2.5",
|
|
3295
|
+
// $0.60/$3.00 — graceful-degradation backstop
|
|
3296
|
+
"xai/grok-4-1-fast-non-reasoning",
|
|
3297
|
+
// 1,244ms, fast fallback
|
|
3298
|
+
"openai/gpt-4o-mini",
|
|
3299
|
+
// 2,764ms, reliable tool calling
|
|
3300
|
+
"anthropic/claude-haiku-4.5",
|
|
3301
|
+
// 2,305ms
|
|
3302
|
+
"deepseek/deepseek-chat"
|
|
3303
|
+
// 1,431ms
|
|
3304
|
+
]
|
|
3305
|
+
},
|
|
3306
|
+
COMPLEX: {
|
|
3307
|
+
primary: "anthropic/claude-sonnet-4.6",
|
|
3308
|
+
// 2,110ms — best agentic quality
|
|
3309
|
+
// Fallback chain de-Gemini'd 2026-04-22: Gemini's "high demand" 503s
|
|
3310
|
+
// correlate with Anthropic outages (everyone falls back together).
|
|
3311
|
+
// Prefer 503-resistant providers first.
|
|
3312
|
+
fallback: [
|
|
3313
|
+
"anthropic/claude-sonnet-5",
|
|
3314
|
+
// in-family hot swap — same cost, near-Opus agentic quality
|
|
3315
|
+
"anthropic/claude-opus-5",
|
|
3316
|
+
// Newest flagship Opus — in-family hot swap
|
|
3317
|
+
"anthropic/claude-opus-4.8",
|
|
3318
|
+
// Prior flagship Opus — identical cost to 5
|
|
3319
|
+
"anthropic/claude-opus-4.7",
|
|
3320
|
+
// Flagship Opus — in-family hot swap
|
|
3321
|
+
"anthropic/claude-opus-4.6",
|
|
3322
|
+
// 2,139ms
|
|
3323
|
+
"xai/grok-4-0709",
|
|
3324
|
+
// 1,348ms — strong tool use, independent infra
|
|
3325
|
+
"moonshot/kimi-k2.7",
|
|
3326
|
+
// Moonshot flagship — strong tool use, independent infra
|
|
3327
|
+
"moonshot/kimi-k2.5",
|
|
3328
|
+
// cost-stability backstop
|
|
3329
|
+
"openai/gpt-5.6-terra",
|
|
3330
|
+
// GPT-5.6 balanced tier — newest generation, stable (Sol excluded: #202)
|
|
3331
|
+
"openai/gpt-5.5",
|
|
3332
|
+
// Prior flagship — native agent + computer use (exactly the agentic-tier use case)
|
|
3333
|
+
"openai/gpt-5.4",
|
|
3334
|
+
// Previous flagship — 6,213ms, reliable
|
|
3335
|
+
"deepseek/deepseek-chat",
|
|
3336
|
+
// 1,431ms — cheap, reliable
|
|
3337
|
+
"free/gpt-oss-120b"
|
|
3338
|
+
// NVIDIA free ultimate backstop (was seed-oss-36b; EOL'd 2026-08-03)
|
|
3339
|
+
]
|
|
3340
|
+
},
|
|
3341
|
+
REASONING: {
|
|
3342
|
+
primary: "anthropic/claude-sonnet-4.6",
|
|
3343
|
+
// 2,110ms — strong tool use + reasoning
|
|
3344
|
+
fallback: [
|
|
3345
|
+
"anthropic/claude-sonnet-5",
|
|
3346
|
+
// in-family hot swap — same cost, adaptive thinking
|
|
3347
|
+
"anthropic/claude-opus-5",
|
|
3348
|
+
// Newest flagship Opus w/ adaptive thinking
|
|
3349
|
+
"anthropic/claude-opus-4.8",
|
|
3350
|
+
// Prior flagship Opus — identical cost to 5
|
|
3351
|
+
"anthropic/claude-opus-4.7",
|
|
3352
|
+
// Flagship Opus w/ adaptive thinking
|
|
3353
|
+
"anthropic/claude-opus-4.6",
|
|
3354
|
+
// 2,139ms
|
|
3355
|
+
"xai/grok-4-1-fast-reasoning",
|
|
3356
|
+
// 1,454ms
|
|
3357
|
+
"deepseek/deepseek-reasoner"
|
|
3358
|
+
// 1,454ms
|
|
3359
|
+
]
|
|
3360
|
+
}
|
|
3361
|
+
},
|
|
3362
|
+
// Time-windowed promotions — auto-applied when active, ignored when expired
|
|
3363
|
+
promotions: [
|
|
3364
|
+
{
|
|
3365
|
+
name: "GLM-5.1 Launch Promo ($0.001 flat)",
|
|
3366
|
+
startDate: "2026-04-01",
|
|
3367
|
+
endDate: "2026-05-01",
|
|
3368
|
+
tierOverrides: {
|
|
3369
|
+
SIMPLE: { primary: "zai/glm-5.1" }
|
|
3370
|
+
},
|
|
3371
|
+
profiles: ["auto"]
|
|
3372
|
+
// only auto profile — eco stays free, premium stays premium
|
|
3373
|
+
}
|
|
3374
|
+
],
|
|
3375
|
+
overrides: {
|
|
3376
|
+
maxTokensForceComplex: 1e5,
|
|
3377
|
+
structuredOutputMinTier: "MEDIUM",
|
|
3378
|
+
ambiguousDefaultTier: "MEDIUM"
|
|
3379
|
+
// agenticMode left undefined → auto-detect via tools/agenticScore.
|
|
3380
|
+
// Set to `true` to force agentic tiers; `false` to disable them entirely.
|
|
3381
|
+
}
|
|
3382
|
+
};
|
|
3383
|
+
registerStrategy(new PortfolioStrategy());
|
|
3384
|
+
function route(prompt, systemPrompt, maxOutputTokens, options) {
|
|
3385
|
+
const strategy = getStrategy(options.config.strategy ?? "portfolio");
|
|
3386
|
+
return strategy.route(prompt, systemPrompt, maxOutputTokens, options);
|
|
3387
|
+
}
|
|
3388
|
+
|
|
3389
|
+
// src/router-adapter.ts
|
|
3390
|
+
var AUTO_ROUTING_PROFILES = {
|
|
3391
|
+
"blockrun/auto": "auto",
|
|
3392
|
+
"blockrun/eco": "eco",
|
|
3393
|
+
"blockrun/premium": "premium"
|
|
3394
|
+
};
|
|
3395
|
+
var BASE_MINIMUM_PAYMENT_USD = 2e-3;
|
|
3396
|
+
var SOLANA_MINIMUM_PAYMENT_USD = 1e-3;
|
|
3397
|
+
function isTransientError(err) {
|
|
3398
|
+
if (err instanceof PaymentError) return false;
|
|
3399
|
+
if (err instanceof APIError) {
|
|
3400
|
+
return [429, 502, 503, 504, 522, 524].includes(err.statusCode);
|
|
3401
|
+
}
|
|
3402
|
+
if (err instanceof Error) {
|
|
3403
|
+
if (err.name === "AbortError") return true;
|
|
3404
|
+
if (err.name === "TypeError" && /fetch|network/i.test(err.message)) return true;
|
|
3405
|
+
}
|
|
3406
|
+
return false;
|
|
3407
|
+
}
|
|
3408
|
+
function errSummary(err) {
|
|
3409
|
+
if (err instanceof APIError) return `APIError ${err.statusCode}`;
|
|
3410
|
+
if (err instanceof Error) {
|
|
3411
|
+
const msg = err.message.length > 80 ? err.message.slice(0, 80) : err.message;
|
|
3412
|
+
return `${err.name}: ${msg}`;
|
|
3413
|
+
}
|
|
3414
|
+
return String(err).slice(0, 100);
|
|
3415
|
+
}
|
|
3416
|
+
function routingProfileForModel(model) {
|
|
3417
|
+
return AUTO_ROUTING_PROFILES[model.toLowerCase()];
|
|
3418
|
+
}
|
|
3419
|
+
function routingText(messages) {
|
|
3420
|
+
const systemPrompt = messages.filter((message) => message.role === "system" && typeof message.content === "string").map((message) => message.content).join("\n") || void 0;
|
|
3421
|
+
const lastUser = [...messages].reverse().find((message) => message.role === "user" && typeof message.content === "string");
|
|
3422
|
+
const lastText = [...messages].reverse().find((message) => typeof message.content === "string");
|
|
3423
|
+
let conversationChars = 0;
|
|
3424
|
+
let hasVision = false;
|
|
3425
|
+
for (const message of messages) {
|
|
3426
|
+
if (typeof message.content === "string") {
|
|
3427
|
+
conversationChars += message.content.length;
|
|
3428
|
+
} else if (Array.isArray(message.content)) {
|
|
3429
|
+
for (const part of message.content) {
|
|
3430
|
+
if (part?.type === "image_url" || part?.type === "image") hasVision = true;
|
|
3431
|
+
if (typeof part?.text === "string") conversationChars += part.text.length;
|
|
3432
|
+
}
|
|
3433
|
+
}
|
|
3434
|
+
}
|
|
3435
|
+
return {
|
|
3436
|
+
prompt: lastUser?.content ?? lastText?.content ?? "",
|
|
3437
|
+
systemPrompt,
|
|
3438
|
+
conversationChars,
|
|
3439
|
+
hasVision
|
|
3440
|
+
};
|
|
3441
|
+
}
|
|
3442
|
+
function routeWithCatalog(prompt, systemPrompt, maxOutputTokens, modelPricing, options = {}) {
|
|
3443
|
+
const tools = options.tools ?? [];
|
|
3444
|
+
const requiresTools = options.toolChoice === "none" ? false : options.toolChoice === "required" || typeof options.toolChoice === "object" ? true : void 0;
|
|
3445
|
+
const decision = route(prompt, systemPrompt, maxOutputTokens, {
|
|
3446
|
+
config: DEFAULT_ROUTING_CONFIG,
|
|
3447
|
+
modelPricing,
|
|
3448
|
+
routingProfile: options.routingProfile,
|
|
3449
|
+
hasTools: tools.length > 0,
|
|
3450
|
+
toolCount: tools.length,
|
|
3451
|
+
toolNames: tools.map((tool) => tool.function.name),
|
|
3452
|
+
requiresTools,
|
|
3453
|
+
hasVision: options.hasVision,
|
|
3454
|
+
requiresStructuredOutput: options.requiresStructuredOutput
|
|
3455
|
+
});
|
|
3456
|
+
const tierConfigs = decision.tierConfigs ?? DEFAULT_ROUTING_CONFIG.tiers;
|
|
3457
|
+
const ranked = decision.candidates?.length ? decision.candidates : [decision.model, ...getFallbackChain(decision.tier, tierConfigs)];
|
|
3458
|
+
const callable = [];
|
|
3459
|
+
for (const id of ranked) {
|
|
3460
|
+
const resolved = !id.startsWith("free/") ? id : modelPricing.has(`nvidia/${id.slice(5)}`) ? `nvidia/${id.slice(5)}` : null;
|
|
3461
|
+
if (resolved && !callable.includes(resolved)) callable.push(resolved);
|
|
3462
|
+
}
|
|
3463
|
+
const estimatedInputTokens = Math.ceil(
|
|
3464
|
+
Math.max(options.conversationChars ?? 0, `${systemPrompt ?? ""} ${prompt}`.length) / 4
|
|
3465
|
+
);
|
|
3466
|
+
const fitting = filterCandidatesByCapacity(
|
|
3467
|
+
callable,
|
|
3468
|
+
estimatedInputTokens,
|
|
3469
|
+
maxOutputTokens,
|
|
3470
|
+
(id) => {
|
|
3471
|
+
const caps = DEFAULT_MODEL_CAPABILITIES[id];
|
|
3472
|
+
return caps ? { contextWindow: caps.contextWindow, maxOutput: caps.maxOutputTokens } : void 0;
|
|
3473
|
+
}
|
|
3474
|
+
);
|
|
3475
|
+
const availableCandidates = fitting.length > 0 ? fitting : callable;
|
|
3476
|
+
const model = availableCandidates[0] ?? decision.model;
|
|
3477
|
+
const costs = calculateModelCost(
|
|
3478
|
+
model,
|
|
3479
|
+
modelPricing,
|
|
3480
|
+
estimatedInputTokens,
|
|
3481
|
+
maxOutputTokens,
|
|
3482
|
+
options.routingProfile
|
|
3483
|
+
);
|
|
3484
|
+
const minimumPaymentUsd = options.minimumPaymentUsd ?? SOLANA_MINIMUM_PAYMENT_USD;
|
|
3485
|
+
const entry = modelPricing.get(model);
|
|
3486
|
+
const isFree = entry !== void 0 && entry.inputPrice === 0 && entry.outputPrice === 0 && !entry.flatPrice;
|
|
3487
|
+
const costEstimate = isFree ? 0 : Math.max(costs.costEstimate, minimumPaymentUsd);
|
|
3488
|
+
const savings = options.routingProfile === "premium" || costs.baselineCost <= 0 ? 0 : entry !== void 0 ? Math.max(0, (costs.baselineCost - costEstimate) / costs.baselineCost) : decision.savings;
|
|
3489
|
+
return {
|
|
3490
|
+
...decision,
|
|
3491
|
+
...costs,
|
|
3492
|
+
costEstimate,
|
|
3493
|
+
savings,
|
|
3494
|
+
model,
|
|
3495
|
+
reasoning: model === decision.model ? decision.reasoning : `${decision.reasoning} | catalog fallback: ${model}`,
|
|
3496
|
+
candidates: availableCandidates,
|
|
3497
|
+
candidateScores: decision.candidateScores?.filter(
|
|
3498
|
+
(score) => availableCandidates.includes(score.model)
|
|
3499
|
+
),
|
|
3500
|
+
fallbacks: availableCandidates.slice(1)
|
|
3501
|
+
};
|
|
3502
|
+
}
|
|
3503
|
+
|
|
148
3504
|
// src/x402.ts
|
|
149
3505
|
var import_accounts = require("viem/accounts");
|
|
150
3506
|
|
|
@@ -608,29 +3964,10 @@ function getCostSummary() {
|
|
|
608
3964
|
}
|
|
609
3965
|
|
|
610
3966
|
// src/version.ts
|
|
611
|
-
var SDK_VERSION = "3.
|
|
3967
|
+
var SDK_VERSION = "3.13.0";
|
|
612
3968
|
var USER_AGENT = `blockrun-ts/${SDK_VERSION}`;
|
|
613
3969
|
|
|
614
3970
|
// src/client.ts
|
|
615
|
-
function isTransientError(err) {
|
|
616
|
-
if (err instanceof PaymentError) return false;
|
|
617
|
-
if (err instanceof APIError) {
|
|
618
|
-
return [429, 502, 503, 504, 522, 524].includes(err.statusCode);
|
|
619
|
-
}
|
|
620
|
-
if (err instanceof Error) {
|
|
621
|
-
if (err.name === "AbortError") return true;
|
|
622
|
-
if (err.name === "TypeError" && /fetch|network/i.test(err.message)) return true;
|
|
623
|
-
}
|
|
624
|
-
return false;
|
|
625
|
-
}
|
|
626
|
-
function errSummary(err) {
|
|
627
|
-
if (err instanceof APIError) return `APIError ${err.statusCode}`;
|
|
628
|
-
if (err instanceof Error) {
|
|
629
|
-
const msg = err.message.length > 80 ? err.message.slice(0, 80) : err.message;
|
|
630
|
-
return `${err.name}: ${msg}`;
|
|
631
|
-
}
|
|
632
|
-
return String(err).slice(0, 100);
|
|
633
|
-
}
|
|
634
3971
|
function mapRawToModel(m) {
|
|
635
3972
|
return {
|
|
636
3973
|
id: m.id,
|
|
@@ -685,7 +4022,7 @@ var LLMClient = class _LLMClient {
|
|
|
685
4022
|
modelPricingPromise = null;
|
|
686
4023
|
// Pre-auth cache: avoids the 402 round-trip on repeat requests to the same model.
|
|
687
4024
|
// Key = "endpoint:model", value = cached payment header + timestamp.
|
|
688
|
-
// TTL: 1 hour
|
|
4025
|
+
// TTL: 1 hour — pre-auth quotes are stable server-side on that horizon.
|
|
689
4026
|
preAuthCache = /* @__PURE__ */ new Map();
|
|
690
4027
|
static PRE_AUTH_TTL_MS = 36e5;
|
|
691
4028
|
/**
|
|
@@ -739,11 +4076,35 @@ var LLMClient = class _LLMClient {
|
|
|
739
4076
|
});
|
|
740
4077
|
return result.choices[0].message.content || "";
|
|
741
4078
|
}
|
|
4079
|
+
async makeRoutingDecision(prompt, systemPrompt, maxOutputTokens, options = {}) {
|
|
4080
|
+
return routeWithCatalog(
|
|
4081
|
+
prompt,
|
|
4082
|
+
systemPrompt,
|
|
4083
|
+
maxOutputTokens,
|
|
4084
|
+
await this.getModelPricing(),
|
|
4085
|
+
{ ...options, minimumPaymentUsd: BASE_MINIMUM_PAYMENT_USD }
|
|
4086
|
+
);
|
|
4087
|
+
}
|
|
4088
|
+
/**
|
|
4089
|
+
* Inspect a local routing decision without making or paying for a model call.
|
|
4090
|
+
* The first invocation may fetch the public model catalog for current prices.
|
|
4091
|
+
*/
|
|
4092
|
+
async route(prompt, options) {
|
|
4093
|
+
return this.makeRoutingDecision(
|
|
4094
|
+
prompt,
|
|
4095
|
+
options?.system,
|
|
4096
|
+
options?.maxOutputTokens ?? options?.maxTokens ?? DEFAULT_MAX_TOKENS,
|
|
4097
|
+
{
|
|
4098
|
+
routingProfile: options?.routingProfile,
|
|
4099
|
+
requiresStructuredOutput: options?.responseFormat !== void 0
|
|
4100
|
+
}
|
|
4101
|
+
);
|
|
4102
|
+
}
|
|
742
4103
|
/**
|
|
743
4104
|
* Smart chat with automatic model routing.
|
|
744
4105
|
*
|
|
745
|
-
* Uses
|
|
746
|
-
*
|
|
4106
|
+
* Uses BlockRun's product-neutral Router Core portfolio strategy: it
|
|
4107
|
+
* classifies the task shape locally (no
|
|
747
4108
|
* extra model call), enforces capability constraints as hard filters, and
|
|
748
4109
|
* ranks an ordered candidate portfolio — the cheapest model that can handle
|
|
749
4110
|
* the request wins, and the rest become the transient-error fallback chain.
|
|
@@ -771,33 +4132,8 @@ var LLMClient = class _LLMClient {
|
|
|
771
4132
|
* ```
|
|
772
4133
|
*/
|
|
773
4134
|
async smartChat(prompt, options) {
|
|
774
|
-
const
|
|
775
|
-
const
|
|
776
|
-
let route;
|
|
777
|
-
let DEFAULT_ROUTING_CONFIG;
|
|
778
|
-
let getFallbackChain;
|
|
779
|
-
try {
|
|
780
|
-
({ route, DEFAULT_ROUTING_CONFIG, getFallbackChain } = await import("@blockrun/clawrouter"));
|
|
781
|
-
} catch (err) {
|
|
782
|
-
throw new Error(
|
|
783
|
-
`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}`
|
|
784
|
-
);
|
|
785
|
-
}
|
|
786
|
-
const decision = route(prompt, options?.system, maxOutputTokens, {
|
|
787
|
-
config: DEFAULT_ROUTING_CONFIG,
|
|
788
|
-
modelPricing,
|
|
789
|
-
routingProfile: options?.routingProfile
|
|
790
|
-
});
|
|
791
|
-
const tierConfigs = decision.tierConfigs ?? DEFAULT_ROUTING_CONFIG.tiers;
|
|
792
|
-
const ranked = decision.candidates?.length ? decision.candidates : [decision.model, ...getFallbackChain(decision.tier, tierConfigs)];
|
|
793
|
-
const callable = [];
|
|
794
|
-
for (const id of ranked) {
|
|
795
|
-
const resolved = !id.startsWith("free/") ? id : modelPricing.has(`nvidia/${id.slice(5)}`) ? `nvidia/${id.slice(5)}` : null;
|
|
796
|
-
if (resolved && !callable.includes(resolved)) callable.push(resolved);
|
|
797
|
-
}
|
|
798
|
-
const primary = callable[0] ?? decision.model;
|
|
799
|
-
const fallbacks = callable.slice(1);
|
|
800
|
-
const response = await this.chat(primary, prompt, {
|
|
4135
|
+
const decision = await this.route(prompt, options);
|
|
4136
|
+
const response = await this.chat(decision.model, prompt, {
|
|
801
4137
|
system: options?.system,
|
|
802
4138
|
maxTokens: options?.maxTokens,
|
|
803
4139
|
temperature: options?.temperature,
|
|
@@ -806,14 +4142,47 @@ var LLMClient = class _LLMClient {
|
|
|
806
4142
|
searchParameters: options?.searchParameters,
|
|
807
4143
|
responseFormat: options?.responseFormat,
|
|
808
4144
|
stop: options?.stop,
|
|
809
|
-
|
|
4145
|
+
// An explicit caller-supplied chain wins over the routed one.
|
|
4146
|
+
fallbackModels: options?.fallbackModels ?? decision.fallbacks
|
|
810
4147
|
});
|
|
811
4148
|
return {
|
|
812
4149
|
response,
|
|
813
|
-
model:
|
|
814
|
-
routing:
|
|
4150
|
+
model: decision.model,
|
|
4151
|
+
routing: decision
|
|
815
4152
|
};
|
|
816
4153
|
}
|
|
4154
|
+
/** Route a full Agent/tool conversation while preserving its complete response. */
|
|
4155
|
+
async smartChatCompletion(messages, options = {}) {
|
|
4156
|
+
const { prompt, systemPrompt, conversationChars, hasVision } = routingText(messages);
|
|
4157
|
+
const decision = await this.makeRoutingDecision(
|
|
4158
|
+
prompt,
|
|
4159
|
+
systemPrompt,
|
|
4160
|
+
options.maxOutputTokens ?? options.maxTokens ?? DEFAULT_MAX_TOKENS,
|
|
4161
|
+
{
|
|
4162
|
+
routingProfile: options.routingProfile,
|
|
4163
|
+
requiresStructuredOutput: options.responseFormat !== void 0,
|
|
4164
|
+
tools: options.tools,
|
|
4165
|
+
toolChoice: options.toolChoice,
|
|
4166
|
+
conversationChars,
|
|
4167
|
+
hasVision
|
|
4168
|
+
}
|
|
4169
|
+
);
|
|
4170
|
+
const response = await this.chatCompletion(decision.model, messages, {
|
|
4171
|
+
maxTokens: options.maxTokens,
|
|
4172
|
+
temperature: options.temperature,
|
|
4173
|
+
topP: options.topP,
|
|
4174
|
+
search: options.search,
|
|
4175
|
+
searchParameters: options.searchParameters,
|
|
4176
|
+
tools: options.tools,
|
|
4177
|
+
toolChoice: options.toolChoice,
|
|
4178
|
+
responseFormat: options.responseFormat,
|
|
4179
|
+
stop: options.stop,
|
|
4180
|
+
// An explicit caller-supplied chain wins over the routed one.
|
|
4181
|
+
fallbackModels: options.fallbackModels ?? decision.fallbacks
|
|
4182
|
+
});
|
|
4183
|
+
response.routing = decision;
|
|
4184
|
+
return { response, model: decision.model, routing: decision };
|
|
4185
|
+
}
|
|
817
4186
|
/**
|
|
818
4187
|
* Get model pricing map (cached).
|
|
819
4188
|
* Fetches from API on first call, then returns cached result.
|
|
@@ -833,31 +4202,18 @@ var LLMClient = class _LLMClient {
|
|
|
833
4202
|
this.modelPricingPromise = null;
|
|
834
4203
|
}
|
|
835
4204
|
}
|
|
836
|
-
/**
|
|
837
|
-
* Fetch model pricing from API.
|
|
838
|
-
*
|
|
839
|
-
* For flat-billed models (e.g. ZAI GLM-5 family at $0.001/call) the
|
|
840
|
-
* router still expects per-token rates, so we synthesise an equivalent
|
|
841
|
-
* per-token price assuming ~1500 total tokens per call. Without this,
|
|
842
|
-
* flat models would resolve to inputPrice=outputPrice=0 and the router
|
|
843
|
-
* would treat them as free, biasing routing decisions and reporting
|
|
844
|
-
* inflated savings %.
|
|
845
|
-
*/
|
|
4205
|
+
/** Fetch model pricing from the live catalog, preserving flat billing. */
|
|
846
4206
|
async fetchModelPricing() {
|
|
847
4207
|
const models = await this.listModels();
|
|
848
4208
|
const pricing = /* @__PURE__ */ new Map();
|
|
849
4209
|
for (const model of models) {
|
|
850
|
-
if (model.
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
});
|
|
4210
|
+
if (model.available === false) continue;
|
|
4211
|
+
const inputPrice = Number.isFinite(model.inputPrice) ? model.inputPrice : 0;
|
|
4212
|
+
const outputPrice = Number.isFinite(model.outputPrice) ? model.outputPrice : 0;
|
|
4213
|
+
if (model.billingMode === "flat" && Number.isFinite(model.flatPrice) && model.flatPrice > 0) {
|
|
4214
|
+
pricing.set(model.id, { inputPrice, outputPrice, flatPrice: model.flatPrice });
|
|
856
4215
|
} else {
|
|
857
|
-
pricing.set(model.id, {
|
|
858
|
-
inputPrice: model.inputPrice,
|
|
859
|
-
outputPrice: model.outputPrice
|
|
860
|
-
});
|
|
4216
|
+
pricing.set(model.id, { inputPrice, outputPrice });
|
|
861
4217
|
}
|
|
862
4218
|
}
|
|
863
4219
|
return pricing;
|
|
@@ -877,6 +4233,13 @@ var LLMClient = class _LLMClient {
|
|
|
877
4233
|
* @returns ChatResponse object with choices and usage
|
|
878
4234
|
*/
|
|
879
4235
|
async chatCompletion(model, messages, options) {
|
|
4236
|
+
const routingProfile = routingProfileForModel(model);
|
|
4237
|
+
if (routingProfile) {
|
|
4238
|
+
return (await this.smartChatCompletion(messages, {
|
|
4239
|
+
...options,
|
|
4240
|
+
routingProfile
|
|
4241
|
+
})).response;
|
|
4242
|
+
}
|
|
880
4243
|
validateMaxTokens(options?.maxTokens);
|
|
881
4244
|
const buildBody = (m) => {
|
|
882
4245
|
const body = {
|
|
@@ -1149,9 +4512,28 @@ var LLMClient = class _LLMClient {
|
|
|
1149
4512
|
*/
|
|
1150
4513
|
async chatCompletionStream(model, messages, options) {
|
|
1151
4514
|
validateMaxTokens(options?.maxTokens);
|
|
4515
|
+
let requestModel = model;
|
|
4516
|
+
const routingProfile = routingProfileForModel(model);
|
|
4517
|
+
if (routingProfile) {
|
|
4518
|
+
const { prompt, systemPrompt, conversationChars, hasVision } = routingText(messages);
|
|
4519
|
+
const decision = await this.makeRoutingDecision(
|
|
4520
|
+
prompt,
|
|
4521
|
+
systemPrompt,
|
|
4522
|
+
options?.maxTokens ?? DEFAULT_MAX_TOKENS,
|
|
4523
|
+
{
|
|
4524
|
+
routingProfile,
|
|
4525
|
+
requiresStructuredOutput: options?.responseFormat !== void 0,
|
|
4526
|
+
tools: options?.tools,
|
|
4527
|
+
toolChoice: options?.toolChoice,
|
|
4528
|
+
conversationChars,
|
|
4529
|
+
hasVision
|
|
4530
|
+
}
|
|
4531
|
+
);
|
|
4532
|
+
requestModel = decision.model;
|
|
4533
|
+
}
|
|
1152
4534
|
const url = `${this.apiUrl}/v1/chat/completions`;
|
|
1153
4535
|
const body = {
|
|
1154
|
-
model,
|
|
4536
|
+
model: requestModel,
|
|
1155
4537
|
messages,
|
|
1156
4538
|
max_tokens: options?.maxTokens ?? DEFAULT_MAX_TOKENS,
|
|
1157
4539
|
stream: true
|
|
@@ -1162,7 +4544,7 @@ var LLMClient = class _LLMClient {
|
|
|
1162
4544
|
if (options?.toolChoice !== void 0) body.tool_choice = options.toolChoice;
|
|
1163
4545
|
if (options?.responseFormat !== void 0) body.response_format = options.responseFormat;
|
|
1164
4546
|
if (options?.stop !== void 0) body.stop = options.stop;
|
|
1165
|
-
const cacheKey2 = `/v1/chat/completions:${
|
|
4547
|
+
const cacheKey2 = `/v1/chat/completions:${requestModel}`;
|
|
1166
4548
|
const cached = this.preAuthCache.get(cacheKey2);
|
|
1167
4549
|
const now = Date.now();
|
|
1168
4550
|
if (cached && now - cached.cachedAt < _LLMClient.PRE_AUTH_TTL_MS) {
|
|
@@ -1672,8 +5054,8 @@ var LLMClient = class _LLMClient {
|
|
|
1672
5054
|
* @example
|
|
1673
5055
|
* const results = await client.exa("search", { query: "latest AI research", numResults: 5 });
|
|
1674
5056
|
*/
|
|
1675
|
-
async exa(
|
|
1676
|
-
return this.requestWithPaymentRaw(`/v1/exa/${
|
|
5057
|
+
async exa(path6, body) {
|
|
5058
|
+
return this.requestWithPaymentRaw(`/v1/exa/${path6}`, body);
|
|
1677
5059
|
}
|
|
1678
5060
|
/**
|
|
1679
5061
|
* Neural web search via Exa. Returns semantically relevant URLs and metadata.
|
|
@@ -1772,7 +5154,13 @@ var LLMClient = class _LLMClient {
|
|
|
1772
5154
|
*/
|
|
1773
5155
|
async getBalance() {
|
|
1774
5156
|
const usdcContract = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913";
|
|
1775
|
-
const
|
|
5157
|
+
const configuredRpc = typeof process !== "undefined" && process.env ? process.env.BASE_RPC_URL : void 0;
|
|
5158
|
+
const rpcs = [
|
|
5159
|
+
configuredRpc,
|
|
5160
|
+
"https://base-rpc.publicnode.com",
|
|
5161
|
+
"https://mainnet.base.org",
|
|
5162
|
+
"https://base.llamarpc.com"
|
|
5163
|
+
].filter((rpc) => Boolean(rpc));
|
|
1776
5164
|
const selector = "0x70a08231";
|
|
1777
5165
|
const paddedAddress = this.account.address.slice(2).toLowerCase().padStart(64, "0");
|
|
1778
5166
|
const data = selector + paddedAddress;
|
|
@@ -1790,7 +5178,9 @@ var LLMClient = class _LLMClient {
|
|
|
1790
5178
|
headers: { "Content-Type": "application/json" },
|
|
1791
5179
|
body: JSON.stringify(payload)
|
|
1792
5180
|
});
|
|
5181
|
+
if (!response.ok) throw new Error(`Base RPC returned ${response.status}`);
|
|
1793
5182
|
const result = await response.json();
|
|
5183
|
+
if (!result.result || result.error) throw new Error("Base RPC returned no balance result");
|
|
1794
5184
|
const balanceRaw = parseInt(result.result || "0x0", 16);
|
|
1795
5185
|
return balanceRaw / 1e6;
|
|
1796
5186
|
} catch (e) {
|
|
@@ -1813,8 +5203,8 @@ var LLMClient = class _LLMClient {
|
|
|
1813
5203
|
* const market = await client.pm("kalshi/markets/KXBTC-25MAR14");
|
|
1814
5204
|
* const results = await client.pm("polymarket/search", { q: "bitcoin" });
|
|
1815
5205
|
*/
|
|
1816
|
-
async pm(
|
|
1817
|
-
return this.getWithPaymentRaw(`/v1/pm/${
|
|
5206
|
+
async pm(path6, params) {
|
|
5207
|
+
return this.getWithPaymentRaw(`/v1/pm/${path6}`, params);
|
|
1818
5208
|
}
|
|
1819
5209
|
/**
|
|
1820
5210
|
* Structured query for Predexon prediction market data (POST endpoints).
|
|
@@ -1830,8 +5220,8 @@ var LLMClient = class _LLMClient {
|
|
|
1830
5220
|
* addresses: ["0xabc...", "0xdef..."],
|
|
1831
5221
|
* });
|
|
1832
5222
|
*/
|
|
1833
|
-
async pmQuery(
|
|
1834
|
-
return this.requestWithPaymentRaw(`/v1/pm/${
|
|
5223
|
+
async pmQuery(path6, query) {
|
|
5224
|
+
return this.requestWithPaymentRaw(`/v1/pm/${path6}`, query);
|
|
1835
5225
|
}
|
|
1836
5226
|
// ── PM convenience helpers (Predexon v2) ─────────────────────────────────
|
|
1837
5227
|
// Thin wrappers over pm() / pmQuery() for the most common v2 endpoints.
|
|
@@ -1919,8 +5309,8 @@ var LLMClient = class _LLMClient {
|
|
|
1919
5309
|
* "prices/coingecko:bitcoin,base:0x..."
|
|
1920
5310
|
* @param params - Query parameters passed through to DefiLlama
|
|
1921
5311
|
*/
|
|
1922
|
-
async defi(
|
|
1923
|
-
return this.getWithPaymentRaw(`/v1/defillama/${
|
|
5312
|
+
async defi(path6, params) {
|
|
5313
|
+
return this.getWithPaymentRaw(`/v1/defillama/${path6}`, params);
|
|
1924
5314
|
}
|
|
1925
5315
|
/** All DeFi protocols with TVL ($0.005/call). */
|
|
1926
5316
|
async defiProtocols() {
|
|
@@ -1956,9 +5346,9 @@ var LLMClient = class _LLMClient {
|
|
|
1956
5346
|
* @param params - Query params (chainId, sellToken, buyToken, sellAmount, taker, ...)
|
|
1957
5347
|
* @param body - JSON body — pass to switch to POST (gasless/submit only)
|
|
1958
5348
|
*/
|
|
1959
|
-
async dex(
|
|
1960
|
-
if (body) return this.requestWithPaymentRaw(`/v1/zerox/${
|
|
1961
|
-
return this.getWithPaymentRaw(`/v1/zerox/${
|
|
5349
|
+
async dex(path6, params, body) {
|
|
5350
|
+
if (body) return this.requestWithPaymentRaw(`/v1/zerox/${path6}`, body);
|
|
5351
|
+
return this.getWithPaymentRaw(`/v1/zerox/${path6}`, params);
|
|
1962
5352
|
}
|
|
1963
5353
|
/** Indicative Permit2 swap price — no commitment (free). */
|
|
1964
5354
|
async dexPrice(params) {
|
|
@@ -2002,8 +5392,8 @@ var LLMClient = class _LLMClient {
|
|
|
2002
5392
|
* "sandbox/status", "sandbox/terminate" ($0.001 each)
|
|
2003
5393
|
* @param body - JSON body for the endpoint
|
|
2004
5394
|
*/
|
|
2005
|
-
async modal(
|
|
2006
|
-
return this.requestWithPaymentRaw(`/v1/modal/${
|
|
5395
|
+
async modal(path6, body) {
|
|
5396
|
+
return this.requestWithPaymentRaw(`/v1/modal/${path6}`, body ?? {});
|
|
2007
5397
|
}
|
|
2008
5398
|
/** Create a sandboxed compute environment ($0.01 CPU / $0.05 GPU). */
|
|
2009
5399
|
async modalSandboxCreate(body) {
|
|
@@ -3365,8 +6755,8 @@ var PhoneClient = class {
|
|
|
3365
6755
|
return data;
|
|
3366
6756
|
}
|
|
3367
6757
|
// ─── Internals ─────────────────────────────────────────────────────────
|
|
3368
|
-
async request(
|
|
3369
|
-
const url = `${this.apiUrl}/v1/phone/${
|
|
6758
|
+
async request(path6, body) {
|
|
6759
|
+
const url = `${this.apiUrl}/v1/phone/${path6}`;
|
|
3370
6760
|
const response = await this.fetchWithTimeout(url, {
|
|
3371
6761
|
method: "POST",
|
|
3372
6762
|
headers: { "Content-Type": "application/json" },
|
|
@@ -3773,10 +7163,10 @@ var PriceClient = class {
|
|
|
3773
7163
|
}
|
|
3774
7164
|
async price(category, symbol, options) {
|
|
3775
7165
|
if (!symbol) throw new Error("symbol is required");
|
|
3776
|
-
const
|
|
7166
|
+
const path6 = categoryPath(category, options?.market, "price", symbol);
|
|
3777
7167
|
const query = {};
|
|
3778
7168
|
if (options?.session) query.session = options.session;
|
|
3779
|
-
const data = await this.getWithPayment(
|
|
7169
|
+
const data = await this.getWithPayment(path6, query);
|
|
3780
7170
|
return {
|
|
3781
7171
|
symbol: data.symbol ?? symbol.toUpperCase(),
|
|
3782
7172
|
price: data.price,
|
|
@@ -3795,14 +7185,14 @@ var PriceClient = class {
|
|
|
3795
7185
|
if (!options.from || options.from <= 0) {
|
|
3796
7186
|
throw new Error("history requires options.from (unix seconds)");
|
|
3797
7187
|
}
|
|
3798
|
-
const
|
|
7188
|
+
const path6 = categoryPath(category, options.market, "history", symbol);
|
|
3799
7189
|
const query = {
|
|
3800
7190
|
resolution: options.resolution ?? "D",
|
|
3801
7191
|
from: String(options.from)
|
|
3802
7192
|
};
|
|
3803
7193
|
if (options.to) query.to = String(options.to);
|
|
3804
7194
|
if (options.session) query.session = options.session;
|
|
3805
|
-
const data = await this.getWithPayment(
|
|
7195
|
+
const data = await this.getWithPayment(path6, query);
|
|
3806
7196
|
return {
|
|
3807
7197
|
symbol: data.symbol ?? symbol.toUpperCase(),
|
|
3808
7198
|
resolution: data.resolution ?? (options.resolution ?? "D"),
|
|
@@ -3814,12 +7204,12 @@ var PriceClient = class {
|
|
|
3814
7204
|
};
|
|
3815
7205
|
}
|
|
3816
7206
|
async listSymbols(category, options) {
|
|
3817
|
-
const
|
|
7207
|
+
const path6 = categoryPath(category, options?.market, "list");
|
|
3818
7208
|
const query = {
|
|
3819
7209
|
limit: String(options?.limit && options.limit > 0 ? options.limit : 100)
|
|
3820
7210
|
};
|
|
3821
7211
|
if (options?.query) query.q = options.query;
|
|
3822
|
-
const data = await this.getWithPayment(
|
|
7212
|
+
const data = await this.getWithPayment(path6, query);
|
|
3823
7213
|
if (Array.isArray(data)) {
|
|
3824
7214
|
return { symbols: data, count: data.length };
|
|
3825
7215
|
}
|
|
@@ -3978,19 +7368,19 @@ var SurfClient = class {
|
|
|
3978
7368
|
* `/v1/surf` is tolerated and stripped). Query params are URL-encoded;
|
|
3979
7369
|
* arrays become repeated keys (`?a=1&a=2`).
|
|
3980
7370
|
*/
|
|
3981
|
-
async get(
|
|
3982
|
-
const url = this.buildUrl(
|
|
7371
|
+
async get(path6, params) {
|
|
7372
|
+
const url = this.buildUrl(path6, params);
|
|
3983
7373
|
return this.requestWithPayment(url, "GET");
|
|
3984
7374
|
}
|
|
3985
7375
|
/**
|
|
3986
7376
|
* POST a Surf endpoint with a JSON body. Same path normalization as `get`.
|
|
3987
7377
|
*/
|
|
3988
|
-
async post(
|
|
3989
|
-
const url = this.buildUrl(
|
|
7378
|
+
async post(path6, body) {
|
|
7379
|
+
const url = this.buildUrl(path6);
|
|
3990
7380
|
return this.requestWithPayment(url, "POST", body);
|
|
3991
7381
|
}
|
|
3992
|
-
buildUrl(
|
|
3993
|
-
let normalized =
|
|
7382
|
+
buildUrl(path6, params) {
|
|
7383
|
+
let normalized = path6.startsWith("/") ? path6 : `/${path6}`;
|
|
3994
7384
|
if (!normalized.startsWith(SURF_PREFIX)) {
|
|
3995
7385
|
normalized = `${SURF_PREFIX}${normalized}`;
|
|
3996
7386
|
}
|
|
@@ -4390,15 +7780,15 @@ var BlockrunClient = class {
|
|
|
4390
7780
|
* `/api` is tolerated and stripped). Query params are URL-encoded; arrays
|
|
4391
7781
|
* become repeated keys (`?a=1&a=2`); undefined/null are dropped.
|
|
4392
7782
|
*/
|
|
4393
|
-
async get(
|
|
4394
|
-
const url = this.buildUrl(
|
|
7783
|
+
async get(path6, params) {
|
|
7784
|
+
const url = this.buildUrl(path6, params);
|
|
4395
7785
|
return this.requestWithPayment(url, "GET");
|
|
4396
7786
|
}
|
|
4397
7787
|
/**
|
|
4398
7788
|
* POST a BlockRun endpoint with a JSON body.
|
|
4399
7789
|
*/
|
|
4400
|
-
async post(
|
|
4401
|
-
const url = this.buildUrl(
|
|
7790
|
+
async post(path6, body) {
|
|
7791
|
+
const url = this.buildUrl(path6);
|
|
4402
7792
|
return this.requestWithPayment(url, "POST", body);
|
|
4403
7793
|
}
|
|
4404
7794
|
/**
|
|
@@ -4413,8 +7803,8 @@ var BlockrunClient = class {
|
|
|
4413
7803
|
* short-circuits and returns the body. Most long-running endpoints (image,
|
|
4414
7804
|
* video, music, voice) return 202 with a poll_url.
|
|
4415
7805
|
*/
|
|
4416
|
-
async poll(
|
|
4417
|
-
const submitUrl = this.buildUrl(
|
|
7806
|
+
async poll(path6, body, options) {
|
|
7807
|
+
const submitUrl = this.buildUrl(path6);
|
|
4418
7808
|
const budgetMs = options?.budgetMs ?? DEFAULT_POLL_BUDGET_MS;
|
|
4419
7809
|
const intervalMs = options?.intervalMs ?? DEFAULT_POLL_INTERVAL_MS;
|
|
4420
7810
|
const resp402 = await this.fetchWithTimeout(submitUrl, {
|
|
@@ -4513,8 +7903,8 @@ var BlockrunClient = class {
|
|
|
4513
7903
|
* process.stdout.write(chunk.choices?.[0]?.delta?.content ?? "");
|
|
4514
7904
|
* }
|
|
4515
7905
|
*/
|
|
4516
|
-
async *stream(
|
|
4517
|
-
const url = this.buildUrl(
|
|
7906
|
+
async *stream(path6, body) {
|
|
7907
|
+
const url = this.buildUrl(path6);
|
|
4518
7908
|
const requestBody = JSON.stringify(body ?? {});
|
|
4519
7909
|
const resp402 = await this.fetchWithTimeout(url, {
|
|
4520
7910
|
method: "POST",
|
|
@@ -4580,8 +7970,8 @@ var BlockrunClient = class {
|
|
|
4580
7970
|
// --------------------------------------------------------------------
|
|
4581
7971
|
// Internal: shared infrastructure
|
|
4582
7972
|
// --------------------------------------------------------------------
|
|
4583
|
-
buildUrl(
|
|
4584
|
-
let normalized =
|
|
7973
|
+
buildUrl(path6, params) {
|
|
7974
|
+
let normalized = path6.startsWith("/") ? path6 : `/${path6}`;
|
|
4585
7975
|
if (normalized.startsWith("/api/")) {
|
|
4586
7976
|
normalized = normalized.slice(4);
|
|
4587
7977
|
}
|
|
@@ -4734,46 +8124,64 @@ function sleep(ms) {
|
|
|
4734
8124
|
}
|
|
4735
8125
|
|
|
4736
8126
|
// src/wallet.ts
|
|
4737
|
-
var
|
|
8127
|
+
var import_accounts16 = require("viem/accounts");
|
|
8128
|
+
|
|
8129
|
+
// node_modules/.pnpm/@blockrun+core@0.1.1_bufferutil@4.1.0_typescript@5.9.3_utf-8-validate@6.0.6_zod@3.25.76/node_modules/@blockrun/core/dist/config.js
|
|
4738
8130
|
var fs2 = __toESM(require("fs"), 1);
|
|
4739
|
-
var path2 = __toESM(require("path"), 1);
|
|
4740
8131
|
var os2 = __toESM(require("os"), 1);
|
|
4741
|
-
var
|
|
4742
|
-
|
|
4743
|
-
|
|
4744
|
-
|
|
4745
|
-
function
|
|
4746
|
-
|
|
4747
|
-
|
|
8132
|
+
var path2 = __toESM(require("path"), 1);
|
|
8133
|
+
function homeDir() {
|
|
8134
|
+
return process.env.BLOCKRUN_HOME || os2.homedir();
|
|
8135
|
+
}
|
|
8136
|
+
function blockrunDir() {
|
|
8137
|
+
return path2.join(homeDir(), ".blockrun");
|
|
8138
|
+
}
|
|
8139
|
+
function paths() {
|
|
8140
|
+
const dir = blockrunDir();
|
|
4748
8141
|
return {
|
|
4749
|
-
|
|
4750
|
-
|
|
8142
|
+
dir,
|
|
8143
|
+
session: path2.join(dir, ".session"),
|
|
8144
|
+
legacy: path2.join(dir, "wallet.key"),
|
|
8145
|
+
solana: path2.join(dir, ".solana"),
|
|
8146
|
+
config: path2.join(dir, "config.json"),
|
|
8147
|
+
costLog: path2.join(dir, "cost_log.jsonl")
|
|
4751
8148
|
};
|
|
4752
8149
|
}
|
|
4753
|
-
|
|
4754
|
-
|
|
4755
|
-
|
|
8150
|
+
|
|
8151
|
+
// node_modules/.pnpm/@blockrun+core@0.1.1_bufferutil@4.1.0_typescript@5.9.3_utf-8-validate@6.0.6_zod@3.25.76/node_modules/@blockrun/core/dist/wallet.js
|
|
8152
|
+
var fs3 = __toESM(require("fs"), 1);
|
|
8153
|
+
var path3 = __toESM(require("path"), 1);
|
|
8154
|
+
var import_accounts15 = require("viem/accounts");
|
|
8155
|
+
function normalize(raw) {
|
|
8156
|
+
const k = raw.trim();
|
|
8157
|
+
return k.startsWith("0x") ? k : `0x${k}`;
|
|
8158
|
+
}
|
|
8159
|
+
function addressFromKey(raw) {
|
|
8160
|
+
try {
|
|
8161
|
+
return (0, import_accounts15.privateKeyToAccount)(normalize(raw)).address;
|
|
8162
|
+
} catch {
|
|
8163
|
+
return null;
|
|
4756
8164
|
}
|
|
4757
|
-
fs2.writeFileSync(WALLET_FILE, privateKey, { mode: 384 });
|
|
4758
|
-
return WALLET_FILE;
|
|
4759
8165
|
}
|
|
4760
8166
|
function scanWallets() {
|
|
4761
|
-
const home =
|
|
8167
|
+
const home = homeDir();
|
|
4762
8168
|
const results = [];
|
|
4763
8169
|
try {
|
|
4764
|
-
const
|
|
4765
|
-
|
|
4766
|
-
|
|
4767
|
-
const
|
|
4768
|
-
if (!
|
|
8170
|
+
for (const entry of fs3.readdirSync(home, { withFileTypes: true })) {
|
|
8171
|
+
if (!entry.name.startsWith(".") || !entry.isDirectory())
|
|
8172
|
+
continue;
|
|
8173
|
+
const walletFile2 = path3.join(home, entry.name, "wallet.json");
|
|
8174
|
+
if (!fs3.existsSync(walletFile2))
|
|
8175
|
+
continue;
|
|
4769
8176
|
try {
|
|
4770
|
-
const data = JSON.parse(
|
|
8177
|
+
const data = JSON.parse(fs3.readFileSync(walletFile2, "utf-8"));
|
|
4771
8178
|
const pk = data.privateKey || "";
|
|
4772
|
-
|
|
4773
|
-
|
|
4774
|
-
|
|
4775
|
-
|
|
4776
|
-
|
|
8179
|
+
if (!pk)
|
|
8180
|
+
continue;
|
|
8181
|
+
const derived = addressFromKey(pk);
|
|
8182
|
+
if (!derived)
|
|
8183
|
+
continue;
|
|
8184
|
+
results.push({ mtime: fs3.statSync(walletFile2).mtimeMs, privateKey: pk, address: derived, source: walletFile2 });
|
|
4777
8185
|
} catch {
|
|
4778
8186
|
continue;
|
|
4779
8187
|
}
|
|
@@ -4784,71 +8192,97 @@ function scanWallets() {
|
|
|
4784
8192
|
return results.map(({ privateKey, address, source }) => ({ privateKey, address, source }));
|
|
4785
8193
|
}
|
|
4786
8194
|
function listDiscoveredWallets() {
|
|
4787
|
-
|
|
4788
|
-
for (const entry of scanWallets()) {
|
|
4789
|
-
try {
|
|
4790
|
-
listed.push({
|
|
4791
|
-
address: (0, import_accounts15.privateKeyToAccount)(entry.privateKey).address,
|
|
4792
|
-
source: entry.source
|
|
4793
|
-
});
|
|
4794
|
-
} catch {
|
|
4795
|
-
continue;
|
|
4796
|
-
}
|
|
4797
|
-
}
|
|
4798
|
-
return listed;
|
|
8195
|
+
return scanWallets().map(({ address, source }) => ({ address, source }));
|
|
4799
8196
|
}
|
|
4800
|
-
function
|
|
8197
|
+
function adoptWallet(address) {
|
|
4801
8198
|
const wanted = address.trim().toLowerCase();
|
|
8199
|
+
const p = paths();
|
|
4802
8200
|
for (const entry of scanWallets()) {
|
|
4803
|
-
|
|
4804
|
-
try {
|
|
4805
|
-
derived = (0, import_accounts15.privateKeyToAccount)(entry.privateKey).address;
|
|
4806
|
-
} catch {
|
|
8201
|
+
if (entry.address.toLowerCase() !== wanted)
|
|
4807
8202
|
continue;
|
|
4808
|
-
|
|
4809
|
-
if (
|
|
4810
|
-
|
|
4811
|
-
|
|
4812
|
-
|
|
4813
|
-
|
|
4814
|
-
fs2.writeFileSync(backup, current, { mode: 384 });
|
|
8203
|
+
const privateKey = normalize(entry.privateKey);
|
|
8204
|
+
if (fs3.existsSync(p.session)) {
|
|
8205
|
+
const current = fs3.readFileSync(p.session, "utf8").trim();
|
|
8206
|
+
if (current && normalize(current) !== privateKey) {
|
|
8207
|
+
const backup = path3.join(p.dir, `.session.backup-${Math.floor(Date.now() / 1e3)}`);
|
|
8208
|
+
fs3.writeFileSync(backup, current, { mode: 384 });
|
|
4815
8209
|
}
|
|
4816
8210
|
}
|
|
4817
|
-
|
|
4818
|
-
|
|
8211
|
+
fs3.mkdirSync(p.dir, { recursive: true });
|
|
8212
|
+
fs3.writeFileSync(p.session, privateKey, { mode: 384 });
|
|
8213
|
+
return { address: entry.address, privateKey, source: "session" };
|
|
4819
8214
|
}
|
|
4820
8215
|
const available = listDiscoveredWallets().map((w) => w.address);
|
|
4821
|
-
throw new Error(
|
|
4822
|
-
`No discovered wallet controls ${address}. Available: ${available.length ? available.join(", ") : "none"}`
|
|
4823
|
-
);
|
|
8216
|
+
throw new Error(`No discovered wallet controls ${address}. Available: ${available.length ? available.join(", ") : "none"}`);
|
|
4824
8217
|
}
|
|
4825
|
-
function
|
|
4826
|
-
|
|
4827
|
-
|
|
4828
|
-
|
|
4829
|
-
|
|
4830
|
-
|
|
4831
|
-
|
|
4832
|
-
|
|
4833
|
-
|
|
8218
|
+
function resolveFromFiles() {
|
|
8219
|
+
const p = paths();
|
|
8220
|
+
if (fs3.existsSync(p.session)) {
|
|
8221
|
+
const raw = fs3.readFileSync(p.session, "utf8").trim();
|
|
8222
|
+
if (raw)
|
|
8223
|
+
return { privateKey: normalize(raw), source: "session" };
|
|
8224
|
+
}
|
|
8225
|
+
if (fs3.existsSync(p.legacy)) {
|
|
8226
|
+
const raw = fs3.readFileSync(p.legacy, "utf8").trim();
|
|
8227
|
+
if (raw)
|
|
8228
|
+
return { privateKey: normalize(raw), source: "legacy" };
|
|
4834
8229
|
}
|
|
4835
8230
|
return null;
|
|
4836
8231
|
}
|
|
8232
|
+
function resolvePrivateKey(env = process.env) {
|
|
8233
|
+
const fromEnv = env.BLOCKRUN_WALLET_KEY || env.BASE_CHAIN_WALLET_KEY;
|
|
8234
|
+
if (fromEnv && fromEnv.trim()) {
|
|
8235
|
+
return { privateKey: normalize(fromEnv), source: "env" };
|
|
8236
|
+
}
|
|
8237
|
+
return resolveFromFiles();
|
|
8238
|
+
}
|
|
8239
|
+
|
|
8240
|
+
// src/wallet.ts
|
|
8241
|
+
var fs4 = __toESM(require("fs"), 1);
|
|
8242
|
+
var USDC_BASE_CONTRACT = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913";
|
|
8243
|
+
var BASE_CHAIN_ID2 = "8453";
|
|
8244
|
+
function walletDir() {
|
|
8245
|
+
return paths().dir;
|
|
8246
|
+
}
|
|
8247
|
+
function walletFile() {
|
|
8248
|
+
return paths().session;
|
|
8249
|
+
}
|
|
8250
|
+
function createWallet() {
|
|
8251
|
+
const privateKey = (0, import_accounts16.generatePrivateKey)();
|
|
8252
|
+
const account = (0, import_accounts16.privateKeyToAccount)(privateKey);
|
|
8253
|
+
return {
|
|
8254
|
+
address: account.address,
|
|
8255
|
+
privateKey
|
|
8256
|
+
};
|
|
8257
|
+
}
|
|
8258
|
+
function saveWallet(privateKey) {
|
|
8259
|
+
const dir = walletDir();
|
|
8260
|
+
const file = walletFile();
|
|
8261
|
+
if (!fs4.existsSync(dir)) {
|
|
8262
|
+
fs4.mkdirSync(dir, { recursive: true });
|
|
8263
|
+
}
|
|
8264
|
+
fs4.writeFileSync(file, privateKey, { mode: 384 });
|
|
8265
|
+
return file;
|
|
8266
|
+
}
|
|
8267
|
+
function scanWallets2() {
|
|
8268
|
+
return scanWallets();
|
|
8269
|
+
}
|
|
8270
|
+
function listDiscoveredWallets2() {
|
|
8271
|
+
return listDiscoveredWallets();
|
|
8272
|
+
}
|
|
8273
|
+
function importWallet(address) {
|
|
8274
|
+
return adoptWallet(address).address;
|
|
8275
|
+
}
|
|
8276
|
+
function loadWallet() {
|
|
8277
|
+
return resolveFromFiles()?.privateKey ?? null;
|
|
8278
|
+
}
|
|
4837
8279
|
function formatWalletMigrationNotice(newAddress) {
|
|
4838
|
-
let
|
|
8280
|
+
let addresses;
|
|
4839
8281
|
try {
|
|
4840
|
-
|
|
8282
|
+
addresses = listDiscoveredWallets().map((w) => w.address);
|
|
4841
8283
|
} catch {
|
|
4842
8284
|
return null;
|
|
4843
8285
|
}
|
|
4844
|
-
const addresses = [];
|
|
4845
|
-
for (const entry of discovered) {
|
|
4846
|
-
try {
|
|
4847
|
-
addresses.push((0, import_accounts15.privateKeyToAccount)(entry.privateKey).address);
|
|
4848
|
-
} catch {
|
|
4849
|
-
continue;
|
|
4850
|
-
}
|
|
4851
|
-
}
|
|
4852
8286
|
if (addresses.length === 0) return null;
|
|
4853
8287
|
const found = addresses.map((addr) => ` ${addr}`).join("\n");
|
|
4854
8288
|
return `
|
|
@@ -4875,30 +8309,18 @@ BLOCKRUN_WALLET_KEY=<private-key> for a single run without changing anything.
|
|
|
4875
8309
|
`;
|
|
4876
8310
|
}
|
|
4877
8311
|
function getOrCreateWallet() {
|
|
4878
|
-
const
|
|
4879
|
-
if (
|
|
4880
|
-
const account = (0,
|
|
4881
|
-
return { address: account.address, privateKey:
|
|
4882
|
-
}
|
|
4883
|
-
const fileKey = loadWallet();
|
|
4884
|
-
if (fileKey) {
|
|
4885
|
-
const account = (0, import_accounts15.privateKeyToAccount)(fileKey);
|
|
4886
|
-
return { address: account.address, privateKey: fileKey, isNew: false };
|
|
8312
|
+
const resolved = resolvePrivateKey();
|
|
8313
|
+
if (resolved) {
|
|
8314
|
+
const account = (0, import_accounts16.privateKeyToAccount)(resolved.privateKey);
|
|
8315
|
+
return { address: account.address, privateKey: resolved.privateKey, isNew: false };
|
|
4887
8316
|
}
|
|
4888
8317
|
const { address, privateKey } = createWallet();
|
|
4889
8318
|
saveWallet(privateKey);
|
|
4890
8319
|
return { address, privateKey, isNew: true };
|
|
4891
8320
|
}
|
|
4892
8321
|
function getWalletAddress() {
|
|
4893
|
-
const
|
|
4894
|
-
|
|
4895
|
-
return (0, import_accounts15.privateKeyToAccount)(envKey).address;
|
|
4896
|
-
}
|
|
4897
|
-
const fileKey = loadWallet();
|
|
4898
|
-
if (fileKey) {
|
|
4899
|
-
return (0, import_accounts15.privateKeyToAccount)(fileKey).address;
|
|
4900
|
-
}
|
|
4901
|
-
return null;
|
|
8322
|
+
const resolved = resolvePrivateKey();
|
|
8323
|
+
return resolved ? (0, import_accounts16.privateKeyToAccount)(resolved.privateKey).address : null;
|
|
4902
8324
|
}
|
|
4903
8325
|
function getEip681Uri(address, amountUsdc = 1) {
|
|
4904
8326
|
const amountWei = Math.floor(amountUsdc * 1e6);
|
|
@@ -4960,15 +8382,15 @@ function formatFundingMessageCompact(address) {
|
|
|
4960
8382
|
return `I need a little top-up to keep helping you! Send USDC on Base to: ${address}
|
|
4961
8383
|
Check my balance: ${links.basescan}`;
|
|
4962
8384
|
}
|
|
4963
|
-
var WALLET_FILE_PATH =
|
|
4964
|
-
var WALLET_DIR_PATH =
|
|
8385
|
+
var WALLET_FILE_PATH = walletFile();
|
|
8386
|
+
var WALLET_DIR_PATH = walletDir();
|
|
4965
8387
|
|
|
4966
8388
|
// src/solana-wallet.ts
|
|
4967
|
-
var
|
|
4968
|
-
var
|
|
8389
|
+
var fs5 = __toESM(require("fs"), 1);
|
|
8390
|
+
var path4 = __toESM(require("path"), 1);
|
|
4969
8391
|
var os3 = __toESM(require("os"), 1);
|
|
4970
|
-
var
|
|
4971
|
-
var SOLANA_WALLET_FILE =
|
|
8392
|
+
var WALLET_DIR = path4.join(os3.homedir(), ".blockrun");
|
|
8393
|
+
var SOLANA_WALLET_FILE = path4.join(WALLET_DIR, ".solana-session");
|
|
4972
8394
|
async function createSolanaWallet() {
|
|
4973
8395
|
const { Keypair } = await loadSolanaWeb3("Solana wallet operations");
|
|
4974
8396
|
const bs58 = await import("bs58");
|
|
@@ -5032,39 +8454,39 @@ async function solanaPublicKey(privateKey) {
|
|
|
5032
8454
|
return Keypair.fromSecretKey(bytes).publicKey.toBase58();
|
|
5033
8455
|
}
|
|
5034
8456
|
function saveSolanaWallet(privateKey) {
|
|
5035
|
-
if (!
|
|
5036
|
-
|
|
8457
|
+
if (!fs5.existsSync(WALLET_DIR)) fs5.mkdirSync(WALLET_DIR, { recursive: true });
|
|
8458
|
+
fs5.writeFileSync(SOLANA_WALLET_FILE, privateKey, { mode: 384 });
|
|
5037
8459
|
return SOLANA_WALLET_FILE;
|
|
5038
8460
|
}
|
|
5039
8461
|
function scanSolanaWallets() {
|
|
5040
8462
|
const home = os3.homedir();
|
|
5041
8463
|
const results = [];
|
|
5042
8464
|
try {
|
|
5043
|
-
const entries =
|
|
8465
|
+
const entries = fs5.readdirSync(home, { withFileTypes: true });
|
|
5044
8466
|
for (const entry of entries) {
|
|
5045
8467
|
if (!entry.name.startsWith(".") || !entry.isDirectory()) continue;
|
|
5046
|
-
const solanaWalletFile =
|
|
5047
|
-
if (
|
|
8468
|
+
const solanaWalletFile = path4.join(home, entry.name, "solana-wallet.json");
|
|
8469
|
+
if (fs5.existsSync(solanaWalletFile)) {
|
|
5048
8470
|
try {
|
|
5049
|
-
const data = JSON.parse(
|
|
8471
|
+
const data = JSON.parse(fs5.readFileSync(solanaWalletFile, "utf-8"));
|
|
5050
8472
|
const pk = data.privateKey || "";
|
|
5051
8473
|
const addr = data.address || "";
|
|
5052
8474
|
if (pk && addr) {
|
|
5053
|
-
const mtime =
|
|
8475
|
+
const mtime = fs5.statSync(solanaWalletFile).mtimeMs;
|
|
5054
8476
|
results.push({ mtime, secretKey: pk, publicKey: addr, source: solanaWalletFile });
|
|
5055
8477
|
}
|
|
5056
8478
|
} catch {
|
|
5057
8479
|
}
|
|
5058
8480
|
}
|
|
5059
8481
|
if (entry.name === ".brcc") {
|
|
5060
|
-
const brccWalletFile =
|
|
5061
|
-
if (
|
|
8482
|
+
const brccWalletFile = path4.join(home, entry.name, "wallet.json");
|
|
8483
|
+
if (fs5.existsSync(brccWalletFile)) {
|
|
5062
8484
|
try {
|
|
5063
|
-
const data = JSON.parse(
|
|
8485
|
+
const data = JSON.parse(fs5.readFileSync(brccWalletFile, "utf-8"));
|
|
5064
8486
|
const pk = data.privateKey || "";
|
|
5065
8487
|
const addr = data.address || "";
|
|
5066
8488
|
if (pk && addr) {
|
|
5067
|
-
const mtime =
|
|
8489
|
+
const mtime = fs5.statSync(brccWalletFile).mtimeMs;
|
|
5068
8490
|
results.push({ mtime, secretKey: pk, publicKey: addr, source: brccWalletFile });
|
|
5069
8491
|
}
|
|
5070
8492
|
} catch {
|
|
@@ -5078,8 +8500,8 @@ function scanSolanaWallets() {
|
|
|
5078
8500
|
return results.map(({ secretKey, publicKey, source }) => ({ secretKey, publicKey, source }));
|
|
5079
8501
|
}
|
|
5080
8502
|
function loadSolanaWallet() {
|
|
5081
|
-
if (
|
|
5082
|
-
const key =
|
|
8503
|
+
if (fs5.existsSync(SOLANA_WALLET_FILE)) {
|
|
8504
|
+
const key = fs5.readFileSync(SOLANA_WALLET_FILE, "utf-8").trim();
|
|
5083
8505
|
if (key) return key;
|
|
5084
8506
|
}
|
|
5085
8507
|
return null;
|
|
@@ -5105,14 +8527,14 @@ async function importSolanaWallet(address) {
|
|
|
5105
8527
|
continue;
|
|
5106
8528
|
}
|
|
5107
8529
|
if (derived !== wanted) continue;
|
|
5108
|
-
if (
|
|
5109
|
-
const current =
|
|
8530
|
+
if (fs5.existsSync(SOLANA_WALLET_FILE)) {
|
|
8531
|
+
const current = fs5.readFileSync(SOLANA_WALLET_FILE, "utf-8").trim();
|
|
5110
8532
|
if (current && current !== entry.secretKey) {
|
|
5111
|
-
const backup =
|
|
5112
|
-
|
|
8533
|
+
const backup = path4.join(
|
|
8534
|
+
WALLET_DIR,
|
|
5113
8535
|
`.solana-session.backup-${Math.floor(Date.now() / 1e3)}`
|
|
5114
8536
|
);
|
|
5115
|
-
|
|
8537
|
+
fs5.writeFileSync(backup, current, { mode: 384 });
|
|
5116
8538
|
}
|
|
5117
8539
|
}
|
|
5118
8540
|
saveSolanaWallet(entry.secretKey);
|
|
@@ -5180,8 +8602,8 @@ async function getOrCreateSolanaWallet() {
|
|
|
5180
8602
|
);
|
|
5181
8603
|
return { privateKey: envKey, address: address2, isNew: false };
|
|
5182
8604
|
}
|
|
5183
|
-
if (
|
|
5184
|
-
const fileKey =
|
|
8605
|
+
if (fs5.existsSync(SOLANA_WALLET_FILE)) {
|
|
8606
|
+
const fileKey = fs5.readFileSync(SOLANA_WALLET_FILE, "utf-8").trim();
|
|
5185
8607
|
if (fileKey) {
|
|
5186
8608
|
const address2 = await solanaPublicKeyFrom(fileKey, SOLANA_WALLET_FILE);
|
|
5187
8609
|
return { privateKey: fileKey, address: address2, isNew: false };
|
|
@@ -5228,6 +8650,8 @@ var SolanaLLMClient = class {
|
|
|
5228
8650
|
sessionTotalUsd = 0;
|
|
5229
8651
|
sessionCalls = 0;
|
|
5230
8652
|
addressCache = null;
|
|
8653
|
+
modelPricingCache = null;
|
|
8654
|
+
modelPricingPromise = null;
|
|
5231
8655
|
constructor(options = {}) {
|
|
5232
8656
|
const envKey = typeof process !== "undefined" && process.env ? process.env.SOLANA_WALLET_KEY : void 0;
|
|
5233
8657
|
const privateKey = options.privateKey || envKey;
|
|
@@ -5262,25 +8686,141 @@ var SolanaLLMClient = class {
|
|
|
5262
8686
|
temperature: options?.temperature,
|
|
5263
8687
|
topP: options?.topP,
|
|
5264
8688
|
search: options?.search,
|
|
5265
|
-
searchParameters: options?.searchParameters
|
|
8689
|
+
searchParameters: options?.searchParameters,
|
|
8690
|
+
responseFormat: options?.responseFormat,
|
|
8691
|
+
stop: options?.stop,
|
|
8692
|
+
fallbackModels: options?.fallbackModels
|
|
5266
8693
|
});
|
|
5267
8694
|
return result.choices[0].message.content || "";
|
|
5268
8695
|
}
|
|
5269
8696
|
/** Full chat completion (OpenAI-compatible). */
|
|
5270
8697
|
async chatCompletion(model, messages, options) {
|
|
8698
|
+
const routingProfile = routingProfileForModel(model);
|
|
8699
|
+
if (routingProfile) {
|
|
8700
|
+
return (await this.smartChatCompletion(messages, {
|
|
8701
|
+
...options,
|
|
8702
|
+
routingProfile
|
|
8703
|
+
})).response;
|
|
8704
|
+
}
|
|
5271
8705
|
validateMaxTokens(options?.maxTokens);
|
|
5272
|
-
const
|
|
5273
|
-
|
|
5274
|
-
|
|
5275
|
-
|
|
8706
|
+
const buildBody = (candidate) => {
|
|
8707
|
+
const body = {
|
|
8708
|
+
model: candidate,
|
|
8709
|
+
messages,
|
|
8710
|
+
max_tokens: options?.maxTokens || DEFAULT_MAX_TOKENS2
|
|
8711
|
+
};
|
|
8712
|
+
if (options?.temperature !== void 0) body.temperature = options.temperature;
|
|
8713
|
+
if (options?.topP !== void 0) body.top_p = options.topP;
|
|
8714
|
+
if (options?.searchParameters !== void 0) body.search_parameters = options.searchParameters;
|
|
8715
|
+
else if (options?.search === true) body.search_parameters = { mode: "on" };
|
|
8716
|
+
if (options?.tools !== void 0) body.tools = options.tools;
|
|
8717
|
+
if (options?.toolChoice !== void 0) body.tool_choice = options.toolChoice;
|
|
8718
|
+
if (options?.responseFormat !== void 0) body.response_format = options.responseFormat;
|
|
8719
|
+
if (options?.stop !== void 0) body.stop = options.stop;
|
|
8720
|
+
return body;
|
|
5276
8721
|
};
|
|
5277
|
-
|
|
5278
|
-
|
|
5279
|
-
|
|
5280
|
-
|
|
5281
|
-
|
|
5282
|
-
|
|
5283
|
-
|
|
8722
|
+
const chain = [model, ...options?.fallbackModels ?? []];
|
|
8723
|
+
let lastError;
|
|
8724
|
+
for (let index = 0; index < chain.length; index += 1) {
|
|
8725
|
+
const candidate = chain[index];
|
|
8726
|
+
try {
|
|
8727
|
+
return await this.requestWithPayment("/v1/chat/completions", buildBody(candidate));
|
|
8728
|
+
} catch (error) {
|
|
8729
|
+
lastError = error;
|
|
8730
|
+
if (!isTransientError(error) || index === chain.length - 1) throw error;
|
|
8731
|
+
console.error(`[@blockrun/llm] ${candidate} -> ${chain[index + 1]} (${errSummary(error)})`);
|
|
8732
|
+
}
|
|
8733
|
+
}
|
|
8734
|
+
throw lastError;
|
|
8735
|
+
}
|
|
8736
|
+
async getModelPricing() {
|
|
8737
|
+
if (this.modelPricingCache) return this.modelPricingCache;
|
|
8738
|
+
if (this.modelPricingPromise) return this.modelPricingPromise;
|
|
8739
|
+
this.modelPricingPromise = (async () => {
|
|
8740
|
+
const models = await this.listModels();
|
|
8741
|
+
const pricing = /* @__PURE__ */ new Map();
|
|
8742
|
+
for (const model of models) {
|
|
8743
|
+
const raw = model;
|
|
8744
|
+
if (model.available === false) continue;
|
|
8745
|
+
const num = (value) => {
|
|
8746
|
+
const n = Number(value ?? 0);
|
|
8747
|
+
return Number.isFinite(n) ? n : 0;
|
|
8748
|
+
};
|
|
8749
|
+
const inputPrice = num(model.inputPrice ?? raw.input_price ?? raw.pricing?.input);
|
|
8750
|
+
const outputPrice = num(model.outputPrice ?? raw.output_price ?? raw.pricing?.output);
|
|
8751
|
+
const flatPrice = num(model.flatPrice ?? raw.flat_price ?? raw.pricing?.flat);
|
|
8752
|
+
pricing.set(model.id, {
|
|
8753
|
+
inputPrice,
|
|
8754
|
+
outputPrice,
|
|
8755
|
+
...(model.billingMode ?? raw.billing_mode) === "flat" && flatPrice > 0 ? { flatPrice } : {}
|
|
8756
|
+
});
|
|
8757
|
+
}
|
|
8758
|
+
return pricing;
|
|
8759
|
+
})();
|
|
8760
|
+
try {
|
|
8761
|
+
this.modelPricingCache = await this.modelPricingPromise;
|
|
8762
|
+
return this.modelPricingCache;
|
|
8763
|
+
} finally {
|
|
8764
|
+
this.modelPricingPromise = null;
|
|
8765
|
+
}
|
|
8766
|
+
}
|
|
8767
|
+
/** Inspect a Solana route without making or paying for a model call. */
|
|
8768
|
+
async route(prompt, options) {
|
|
8769
|
+
return routeWithCatalog(
|
|
8770
|
+
prompt,
|
|
8771
|
+
options?.system,
|
|
8772
|
+
options?.maxOutputTokens ?? options?.maxTokens ?? DEFAULT_MAX_TOKENS2,
|
|
8773
|
+
await this.getModelPricing(),
|
|
8774
|
+
{
|
|
8775
|
+
routingProfile: options?.routingProfile,
|
|
8776
|
+
requiresStructuredOutput: options?.responseFormat !== void 0,
|
|
8777
|
+
minimumPaymentUsd: SOLANA_MINIMUM_PAYMENT_USD
|
|
8778
|
+
}
|
|
8779
|
+
);
|
|
8780
|
+
}
|
|
8781
|
+
/** Smart one-line chat paid on Solana. */
|
|
8782
|
+
async smartChat(prompt, options) {
|
|
8783
|
+
const decision = await this.route(prompt, options);
|
|
8784
|
+
const response = await this.chat(decision.model, prompt, {
|
|
8785
|
+
...options,
|
|
8786
|
+
// An explicit caller-supplied chain wins over the routed one.
|
|
8787
|
+
fallbackModels: options?.fallbackModels ?? decision.fallbacks
|
|
8788
|
+
});
|
|
8789
|
+
return { response, model: decision.model, routing: decision };
|
|
8790
|
+
}
|
|
8791
|
+
/** Smart full message/tool completion paid on Solana. */
|
|
8792
|
+
async smartChatCompletion(messages, options = {}) {
|
|
8793
|
+
const { prompt, systemPrompt, conversationChars, hasVision } = routingText(messages);
|
|
8794
|
+
const decision = routeWithCatalog(
|
|
8795
|
+
prompt,
|
|
8796
|
+
systemPrompt,
|
|
8797
|
+
options.maxOutputTokens ?? options.maxTokens ?? DEFAULT_MAX_TOKENS2,
|
|
8798
|
+
await this.getModelPricing(),
|
|
8799
|
+
{
|
|
8800
|
+
routingProfile: options.routingProfile,
|
|
8801
|
+
requiresStructuredOutput: options.responseFormat !== void 0,
|
|
8802
|
+
tools: options.tools,
|
|
8803
|
+
toolChoice: options.toolChoice,
|
|
8804
|
+
conversationChars,
|
|
8805
|
+
hasVision,
|
|
8806
|
+
minimumPaymentUsd: SOLANA_MINIMUM_PAYMENT_USD
|
|
8807
|
+
}
|
|
8808
|
+
);
|
|
8809
|
+
const response = await this.chatCompletion(decision.model, messages, {
|
|
8810
|
+
maxTokens: options.maxTokens,
|
|
8811
|
+
temperature: options.temperature,
|
|
8812
|
+
topP: options.topP,
|
|
8813
|
+
search: options.search,
|
|
8814
|
+
searchParameters: options.searchParameters,
|
|
8815
|
+
tools: options.tools,
|
|
8816
|
+
toolChoice: options.toolChoice,
|
|
8817
|
+
responseFormat: options.responseFormat,
|
|
8818
|
+
stop: options.stop,
|
|
8819
|
+
// An explicit caller-supplied chain wins over the routed one.
|
|
8820
|
+
fallbackModels: options.fallbackModels ?? decision.fallbacks
|
|
8821
|
+
});
|
|
8822
|
+
response.routing = decision;
|
|
8823
|
+
return { response, model: decision.model, routing: decision };
|
|
5284
8824
|
}
|
|
5285
8825
|
/** List available models. */
|
|
5286
8826
|
async listModels() {
|
|
@@ -5345,11 +8885,11 @@ var SolanaLLMClient = class {
|
|
|
5345
8885
|
return data;
|
|
5346
8886
|
}
|
|
5347
8887
|
// ── Prediction Markets (Powered by Predexon) ────────────────────────────
|
|
5348
|
-
async pm(
|
|
5349
|
-
return this.getWithPaymentRaw(`/v1/pm/${
|
|
8888
|
+
async pm(path6, params) {
|
|
8889
|
+
return this.getWithPaymentRaw(`/v1/pm/${path6}`, params);
|
|
5350
8890
|
}
|
|
5351
|
-
async pmQuery(
|
|
5352
|
-
return this.requestWithPaymentRaw(`/v1/pm/${
|
|
8891
|
+
async pmQuery(path6, query) {
|
|
8892
|
+
return this.requestWithPaymentRaw(`/v1/pm/${path6}`, query);
|
|
5353
8893
|
}
|
|
5354
8894
|
// ── Exa Web Search (Powered by Exa) ──────────────────────────────────────
|
|
5355
8895
|
/**
|
|
@@ -5361,8 +8901,8 @@ var SolanaLLMClient = class {
|
|
|
5361
8901
|
* @example
|
|
5362
8902
|
* const results = await client.exa("search", { query: "latest AI research", numResults: 5 });
|
|
5363
8903
|
*/
|
|
5364
|
-
async exa(
|
|
5365
|
-
return this.requestWithPaymentRaw(`/v1/exa/${
|
|
8904
|
+
async exa(path6, body) {
|
|
8905
|
+
return this.requestWithPaymentRaw(`/v1/exa/${path6}`, body);
|
|
5366
8906
|
}
|
|
5367
8907
|
/**
|
|
5368
8908
|
* Neural and keyword web search via Exa (Solana payment, $0.01/request).
|
|
@@ -5412,8 +8952,8 @@ var SolanaLLMClient = class {
|
|
|
5412
8952
|
* "prices/coingecko:bitcoin,base:0x..."
|
|
5413
8953
|
* @param params - Query parameters passed through to DefiLlama
|
|
5414
8954
|
*/
|
|
5415
|
-
async defi(
|
|
5416
|
-
return this.getWithPaymentRaw(`/v1/defillama/${
|
|
8955
|
+
async defi(path6, params) {
|
|
8956
|
+
return this.getWithPaymentRaw(`/v1/defillama/${path6}`, params);
|
|
5417
8957
|
}
|
|
5418
8958
|
/** All DeFi protocols with TVL ($0.005/call). */
|
|
5419
8959
|
async defiProtocols() {
|
|
@@ -5449,9 +8989,9 @@ var SolanaLLMClient = class {
|
|
|
5449
8989
|
* @param params - Query params (chainId, sellToken, buyToken, sellAmount, taker, ...)
|
|
5450
8990
|
* @param body - JSON body — pass to switch to POST (gasless/submit only)
|
|
5451
8991
|
*/
|
|
5452
|
-
async dex(
|
|
5453
|
-
if (body) return this.requestWithPaymentRaw(`/v1/zerox/${
|
|
5454
|
-
return this.getWithPaymentRaw(`/v1/zerox/${
|
|
8992
|
+
async dex(path6, params, body) {
|
|
8993
|
+
if (body) return this.requestWithPaymentRaw(`/v1/zerox/${path6}`, body);
|
|
8994
|
+
return this.getWithPaymentRaw(`/v1/zerox/${path6}`, params);
|
|
5455
8995
|
}
|
|
5456
8996
|
/** Indicative Permit2 swap price — no commitment (free). */
|
|
5457
8997
|
async dexPrice(params) {
|
|
@@ -5495,8 +9035,8 @@ var SolanaLLMClient = class {
|
|
|
5495
9035
|
* "sandbox/status", "sandbox/terminate" ($0.001 each)
|
|
5496
9036
|
* @param body - JSON body for the endpoint
|
|
5497
9037
|
*/
|
|
5498
|
-
async modal(
|
|
5499
|
-
return this.requestWithPaymentRaw(`/v1/modal/${
|
|
9038
|
+
async modal(path6, body) {
|
|
9039
|
+
return this.requestWithPaymentRaw(`/v1/modal/${path6}`, body ?? {});
|
|
5500
9040
|
}
|
|
5501
9041
|
/** Create a sandboxed compute environment ($0.01 CPU / $0.05 GPU). */
|
|
5502
9042
|
async modalSandboxCreate(body) {
|
|
@@ -5813,13 +9353,13 @@ function solanaClient(options = {}) {
|
|
|
5813
9353
|
}
|
|
5814
9354
|
|
|
5815
9355
|
// src/cache.ts
|
|
5816
|
-
var
|
|
5817
|
-
var
|
|
9356
|
+
var fs6 = __toESM(require("fs"), 1);
|
|
9357
|
+
var path5 = __toESM(require("path"), 1);
|
|
5818
9358
|
var os4 = __toESM(require("os"), 1);
|
|
5819
9359
|
var crypto2 = __toESM(require("crypto"), 1);
|
|
5820
|
-
var CACHE_DIR =
|
|
5821
|
-
var DATA_DIR =
|
|
5822
|
-
var COST_LOG_FILE2 =
|
|
9360
|
+
var CACHE_DIR = path5.join(os4.homedir(), ".blockrun", "cache");
|
|
9361
|
+
var DATA_DIR = path5.join(os4.homedir(), ".blockrun", "data");
|
|
9362
|
+
var COST_LOG_FILE2 = path5.join(os4.homedir(), ".blockrun", "cost_log.jsonl");
|
|
5823
9363
|
var DEFAULT_TTL = {
|
|
5824
9364
|
"/v1/partner/": 3600 * 1e3,
|
|
5825
9365
|
"/v1/pm/": 1800 * 1e3,
|
|
@@ -5839,19 +9379,19 @@ function cacheKey(endpoint, body) {
|
|
|
5839
9379
|
return crypto2.createHash("sha256").update(keyData).digest("hex").slice(0, 16);
|
|
5840
9380
|
}
|
|
5841
9381
|
function cachePath(key) {
|
|
5842
|
-
return
|
|
9382
|
+
return path5.join(CACHE_DIR, `${key}.json`);
|
|
5843
9383
|
}
|
|
5844
9384
|
function getCached(key) {
|
|
5845
9385
|
const filePath = cachePath(key);
|
|
5846
|
-
if (!
|
|
9386
|
+
if (!fs6.existsSync(filePath)) return null;
|
|
5847
9387
|
try {
|
|
5848
|
-
const raw =
|
|
9388
|
+
const raw = fs6.readFileSync(filePath, "utf-8");
|
|
5849
9389
|
const entry = JSON.parse(raw);
|
|
5850
9390
|
const ttl = entry.ttlMs ?? getTtl(entry.endpoint ?? "");
|
|
5851
9391
|
if (ttl <= 0) return null;
|
|
5852
9392
|
if (Date.now() - entry.cachedAt > ttl) {
|
|
5853
9393
|
try {
|
|
5854
|
-
|
|
9394
|
+
fs6.unlinkSync(filePath);
|
|
5855
9395
|
} catch {
|
|
5856
9396
|
}
|
|
5857
9397
|
return null;
|
|
@@ -5870,7 +9410,7 @@ function getCachedByRequest(endpoint, body) {
|
|
|
5870
9410
|
function setCache(key, data, ttlMs) {
|
|
5871
9411
|
if (ttlMs <= 0) return;
|
|
5872
9412
|
try {
|
|
5873
|
-
|
|
9413
|
+
fs6.mkdirSync(CACHE_DIR, { recursive: true });
|
|
5874
9414
|
} catch {
|
|
5875
9415
|
}
|
|
5876
9416
|
const entry = {
|
|
@@ -5879,7 +9419,7 @@ function setCache(key, data, ttlMs) {
|
|
|
5879
9419
|
ttlMs
|
|
5880
9420
|
};
|
|
5881
9421
|
try {
|
|
5882
|
-
|
|
9422
|
+
fs6.writeFileSync(cachePath(key), JSON.stringify(entry));
|
|
5883
9423
|
} catch {
|
|
5884
9424
|
}
|
|
5885
9425
|
}
|
|
@@ -5900,7 +9440,7 @@ function readableFilename(endpoint, body) {
|
|
|
5900
9440
|
}
|
|
5901
9441
|
function saveReadable(endpoint, body, response, costUsd) {
|
|
5902
9442
|
try {
|
|
5903
|
-
|
|
9443
|
+
fs6.mkdirSync(DATA_DIR, { recursive: true });
|
|
5904
9444
|
} catch {
|
|
5905
9445
|
}
|
|
5906
9446
|
const filename = readableFilename(endpoint, body);
|
|
@@ -5912,14 +9452,14 @@ function saveReadable(endpoint, body, response, costUsd) {
|
|
|
5912
9452
|
response
|
|
5913
9453
|
};
|
|
5914
9454
|
try {
|
|
5915
|
-
|
|
9455
|
+
fs6.writeFileSync(path5.join(DATA_DIR, filename), JSON.stringify(entry, null, 2));
|
|
5916
9456
|
} catch {
|
|
5917
9457
|
}
|
|
5918
9458
|
}
|
|
5919
9459
|
function appendCostLog(endpoint, costUsd) {
|
|
5920
9460
|
if (costUsd <= 0) return;
|
|
5921
9461
|
try {
|
|
5922
|
-
|
|
9462
|
+
fs6.mkdirSync(path5.dirname(COST_LOG_FILE2), { recursive: true });
|
|
5923
9463
|
} catch {
|
|
5924
9464
|
}
|
|
5925
9465
|
const entry = {
|
|
@@ -5928,7 +9468,7 @@ function appendCostLog(endpoint, costUsd) {
|
|
|
5928
9468
|
cost_usd: costUsd
|
|
5929
9469
|
};
|
|
5930
9470
|
try {
|
|
5931
|
-
|
|
9471
|
+
fs6.appendFileSync(COST_LOG_FILE2, JSON.stringify(entry) + "\n");
|
|
5932
9472
|
} catch {
|
|
5933
9473
|
}
|
|
5934
9474
|
}
|
|
@@ -5936,7 +9476,7 @@ function saveToCache(endpoint, body, response, costUsd = 0) {
|
|
|
5936
9476
|
const ttl = getTtl(endpoint);
|
|
5937
9477
|
if (ttl > 0) {
|
|
5938
9478
|
try {
|
|
5939
|
-
|
|
9479
|
+
fs6.mkdirSync(CACHE_DIR, { recursive: true });
|
|
5940
9480
|
} catch {
|
|
5941
9481
|
}
|
|
5942
9482
|
const key = cacheKey(endpoint, body);
|
|
@@ -5948,7 +9488,7 @@ function saveToCache(endpoint, body, response, costUsd = 0) {
|
|
|
5948
9488
|
costUsd
|
|
5949
9489
|
};
|
|
5950
9490
|
try {
|
|
5951
|
-
|
|
9491
|
+
fs6.writeFileSync(cachePath(key), JSON.stringify(entry));
|
|
5952
9492
|
} catch {
|
|
5953
9493
|
}
|
|
5954
9494
|
}
|
|
@@ -5956,14 +9496,14 @@ function saveToCache(endpoint, body, response, costUsd = 0) {
|
|
|
5956
9496
|
appendCostLog(endpoint, costUsd);
|
|
5957
9497
|
}
|
|
5958
9498
|
function clearCache() {
|
|
5959
|
-
if (!
|
|
9499
|
+
if (!fs6.existsSync(CACHE_DIR)) return 0;
|
|
5960
9500
|
let count = 0;
|
|
5961
9501
|
try {
|
|
5962
|
-
const files =
|
|
9502
|
+
const files = fs6.readdirSync(CACHE_DIR);
|
|
5963
9503
|
for (const file of files) {
|
|
5964
9504
|
if (file.endsWith(".json")) {
|
|
5965
9505
|
try {
|
|
5966
|
-
|
|
9506
|
+
fs6.unlinkSync(path5.join(CACHE_DIR, file));
|
|
5967
9507
|
count++;
|
|
5968
9508
|
} catch {
|
|
5969
9509
|
}
|
|
@@ -5974,14 +9514,14 @@ function clearCache() {
|
|
|
5974
9514
|
return count;
|
|
5975
9515
|
}
|
|
5976
9516
|
function getCostLogSummary() {
|
|
5977
|
-
if (!
|
|
9517
|
+
if (!fs6.existsSync(COST_LOG_FILE2)) {
|
|
5978
9518
|
return { totalUsd: 0, calls: 0, byEndpoint: {} };
|
|
5979
9519
|
}
|
|
5980
9520
|
let totalUsd = 0;
|
|
5981
9521
|
let calls = 0;
|
|
5982
9522
|
const byEndpoint = {};
|
|
5983
9523
|
try {
|
|
5984
|
-
const content =
|
|
9524
|
+
const content = fs6.readFileSync(COST_LOG_FILE2, "utf-8").trim();
|
|
5985
9525
|
if (!content) return { totalUsd: 0, calls: 0, byEndpoint: {} };
|
|
5986
9526
|
for (const line of content.split("\n")) {
|
|
5987
9527
|
if (!line) continue;
|
|
@@ -6161,7 +9701,8 @@ var ChatCompletions = class {
|
|
|
6161
9701
|
},
|
|
6162
9702
|
finish_reason: choice.finish_reason || "stop"
|
|
6163
9703
|
})),
|
|
6164
|
-
usage: response.usage
|
|
9704
|
+
usage: response.usage,
|
|
9705
|
+
routing: response.routing
|
|
6165
9706
|
};
|
|
6166
9707
|
}
|
|
6167
9708
|
};
|
|
@@ -6194,7 +9735,7 @@ var OpenAI = class {
|
|
|
6194
9735
|
};
|
|
6195
9736
|
|
|
6196
9737
|
// src/anthropic-compat.ts
|
|
6197
|
-
var
|
|
9738
|
+
var import_accounts17 = require("viem/accounts");
|
|
6198
9739
|
var AnthropicClient = class {
|
|
6199
9740
|
_client = null;
|
|
6200
9741
|
_clientPromise = null;
|
|
@@ -6207,7 +9748,7 @@ var AnthropicClient = class {
|
|
|
6207
9748
|
const key = options.privateKey ?? wallet.privateKey;
|
|
6208
9749
|
validatePrivateKey(key);
|
|
6209
9750
|
this._privateKey = key;
|
|
6210
|
-
this._account = (0,
|
|
9751
|
+
this._account = (0, import_accounts17.privateKeyToAccount)(this._privateKey);
|
|
6211
9752
|
const apiUrl = options.apiUrl ?? "https://blockrun.ai/api";
|
|
6212
9753
|
validateApiUrl(apiUrl);
|
|
6213
9754
|
this._apiUrl = apiUrl.replace(/\/$/, "");
|