@blockrun/llm 3.24.1 → 3.24.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +111 -43
- package/dist/index.js +111 -43
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -571,7 +571,69 @@ function withCost(body, response, bookedUsd, scheme) {
|
|
|
571
571
|
// src/client.ts
|
|
572
572
|
var import_accounts2 = require("viem/accounts");
|
|
573
573
|
|
|
574
|
-
// node_modules/.pnpm/@blockrun+router-core@https+++codeload.github.com+BlockRunAI+router-core+tar.gz+
|
|
574
|
+
// node_modules/.pnpm/@blockrun+router-core@https+++codeload.github.com+BlockRunAI+router-core+tar.gz+65a92c85ea1f1_ulf6q3mq2pzpwvcnu73z4krxvy/node_modules/@blockrun/router-core/dist/index.js
|
|
575
|
+
var UNSEGMENTED_SCRIPT = /[-ۿ -ヿ㐀-䶿一-鿿가-豈--]/;
|
|
576
|
+
var WORD_CHAR = /[\p{L}\p{N}]/u;
|
|
577
|
+
var ASCII_PHRASE = /^[a-z0-9' -]+$/;
|
|
578
|
+
var SEGMENTED_WORD_CHAR = "\\p{Script=Latin}\\p{Script=Cyrillic}\\p{Script=Greek}\\p{N}";
|
|
579
|
+
var BOUNDARY_BEFORE = `(?<![${SEGMENTED_WORD_CHAR}])`;
|
|
580
|
+
var BOUNDARY_AFTER = `(?![${SEGMENTED_WORD_CHAR}])`;
|
|
581
|
+
var BOUNDED_LAST_WORD_LENGTH = 6;
|
|
582
|
+
var SHORT_SUFFIXES = "(?:s|ed|ing)?";
|
|
583
|
+
var SIBILANT_PLURAL = "es";
|
|
584
|
+
var MID_SUFFIXES = "(?:s|es|ed|d|ing|er|ers|ly|ment|ments|ation|ations|e|en|n|a|as|o|os|em|et|ung|ungen)?";
|
|
585
|
+
var DROPPED_E_SUFFIXES = "(?:ing|ed|es|er|ers|ation|ations)";
|
|
586
|
+
var DOUBLED_CONSONANT_SUFFIXES = "(?:ing|ed|er|ers)";
|
|
587
|
+
var matcherCache = /* @__PURE__ */ new Map();
|
|
588
|
+
function escapeRegExp(value) {
|
|
589
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
590
|
+
}
|
|
591
|
+
function keywordMatcher(keyword) {
|
|
592
|
+
const cached = matcherCache.get(keyword);
|
|
593
|
+
if (cached) return cached;
|
|
594
|
+
const kw = keyword.toLowerCase();
|
|
595
|
+
let matcher;
|
|
596
|
+
if (UNSEGMENTED_SCRIPT.test(kw) || kw.length === 0) {
|
|
597
|
+
matcher = { needle: kw, pattern: null };
|
|
598
|
+
} else {
|
|
599
|
+
const lead = WORD_CHAR.test(kw[0]) ? BOUNDARY_BEFORE : "";
|
|
600
|
+
const escaped = escapeRegExp(kw);
|
|
601
|
+
let body = escaped;
|
|
602
|
+
let trail = "";
|
|
603
|
+
let needle = kw;
|
|
604
|
+
const lastWord = kw.slice(kw.lastIndexOf(" ") + 1);
|
|
605
|
+
if (WORD_CHAR.test(kw[kw.length - 1]) && ASCII_PHRASE.test(kw) && lastWord.length <= BOUNDED_LAST_WORD_LENGTH) {
|
|
606
|
+
const forms = [];
|
|
607
|
+
if (/\d$/.test(kw)) {
|
|
608
|
+
forms.push(escaped);
|
|
609
|
+
} else if (lastWord.length <= 3) {
|
|
610
|
+
forms.push(`${escaped}${SHORT_SUFFIXES}`);
|
|
611
|
+
if (/(?:x|s|z|ch|sh)$/.test(kw)) forms.push(`${escaped}${SIBILANT_PLURAL}`);
|
|
612
|
+
} else {
|
|
613
|
+
forms.push(`${escaped}${MID_SUFFIXES}`);
|
|
614
|
+
if (kw.endsWith("e")) {
|
|
615
|
+
forms.push(`${escaped.slice(0, -1)}${DROPPED_E_SUFFIXES}`);
|
|
616
|
+
needle = kw.slice(0, -1);
|
|
617
|
+
} else if (kw.endsWith("y")) {
|
|
618
|
+
forms.push(`${escaped.slice(0, -1)}(?:ies|ied)`);
|
|
619
|
+
needle = kw.slice(0, -1);
|
|
620
|
+
} else if (/[aeiou][bdgmnprt]$/.test(kw)) {
|
|
621
|
+
forms.push(`${escaped}${kw[kw.length - 1]}${DOUBLED_CONSONANT_SUFFIXES}`);
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
body = `(?:${forms.join("|")})`;
|
|
625
|
+
trail = BOUNDARY_AFTER;
|
|
626
|
+
}
|
|
627
|
+
matcher = { needle, pattern: new RegExp(`${lead}${body}${trail}`, "u") };
|
|
628
|
+
}
|
|
629
|
+
matcherCache.set(keyword, matcher);
|
|
630
|
+
return matcher;
|
|
631
|
+
}
|
|
632
|
+
function matchesKeyword(text, keyword) {
|
|
633
|
+
const { needle, pattern } = keywordMatcher(keyword);
|
|
634
|
+
if (!text.includes(needle)) return false;
|
|
635
|
+
return pattern === null ? true : pattern.test(text);
|
|
636
|
+
}
|
|
575
637
|
function scoreTokenCount(estimatedTokens, thresholds) {
|
|
576
638
|
if (estimatedTokens < thresholds.simple) {
|
|
577
639
|
return { name: "tokenCount", score: -1, signal: `short (${estimatedTokens} tokens)` };
|
|
@@ -582,7 +644,7 @@ function scoreTokenCount(estimatedTokens, thresholds) {
|
|
|
582
644
|
return { name: "tokenCount", score: 0, signal: null };
|
|
583
645
|
}
|
|
584
646
|
function scoreKeywordMatch(text, keywords, name, signalLabel, thresholds, scores) {
|
|
585
|
-
const matches = keywords.filter((kw) => text
|
|
647
|
+
const matches = keywords.filter((kw) => matchesKeyword(text, kw));
|
|
586
648
|
if (matches.length >= thresholds.high) {
|
|
587
649
|
return {
|
|
588
650
|
name,
|
|
@@ -618,7 +680,7 @@ function scoreAgenticTask(text, keywords) {
|
|
|
618
680
|
let matchCount = 0;
|
|
619
681
|
const signals = [];
|
|
620
682
|
for (const keyword of keywords) {
|
|
621
|
-
if (text
|
|
683
|
+
if (matchesKeyword(text, keyword)) {
|
|
622
684
|
matchCount++;
|
|
623
685
|
if (signals.length < 3) {
|
|
624
686
|
signals.push(keyword);
|
|
@@ -765,9 +827,7 @@ function classifyByRules(prompt, systemPrompt, estimatedTokens, config) {
|
|
|
765
827
|
const w = weights[d.name] ?? 0;
|
|
766
828
|
weightedScore += d.score * w;
|
|
767
829
|
}
|
|
768
|
-
const reasoningMatches = config.reasoningKeywords.filter(
|
|
769
|
-
(kw) => userText.includes(kw.toLowerCase())
|
|
770
|
-
);
|
|
830
|
+
const reasoningMatches = config.reasoningKeywords.filter((kw) => matchesKeyword(userText, kw));
|
|
771
831
|
if (reasoningMatches.length >= 2) {
|
|
772
832
|
const confidence2 = calibrateConfidence(
|
|
773
833
|
Math.max(weightedScore, 0.3),
|
|
@@ -832,7 +892,7 @@ function selectModel(tier, confidence, method, reasoning, tierConfigs, modelPric
|
|
|
832
892
|
const baselineInput = estimatedInputTokens / 1e6 * opusInputPrice;
|
|
833
893
|
const baselineOutput = maxOutputTokens / 1e6 * opusOutputPrice;
|
|
834
894
|
const baselineCost = baselineInput + baselineOutput;
|
|
835
|
-
const savings = routingProfile === "premium" ? 0 : baselineCost > 0 ? Math.max(0, (baselineCost - costEstimate) / baselineCost) : 0;
|
|
895
|
+
const savings = routingProfile === "premium" || pricing === void 0 ? 0 : baselineCost > 0 ? Math.max(0, (baselineCost - costEstimate) / baselineCost) : 0;
|
|
836
896
|
return {
|
|
837
897
|
model,
|
|
838
898
|
tier,
|
|
@@ -883,6 +943,21 @@ function filterCandidatesByCapacity(models, estimatedInputTokens, requestedOutpu
|
|
|
883
943
|
});
|
|
884
944
|
return filtered;
|
|
885
945
|
}
|
|
946
|
+
var CJK_CHARS = /[ -ヿ㐀-䶿一-鿿가-豈--]/g;
|
|
947
|
+
function estimateTokens(text) {
|
|
948
|
+
if (text.length === 0) return 0;
|
|
949
|
+
const cjk = text.match(CJK_CHARS)?.length ?? 0;
|
|
950
|
+
return cjk + Math.ceil((text.length - cjk) / 4);
|
|
951
|
+
}
|
|
952
|
+
function scanLimit(promptTruncationChars) {
|
|
953
|
+
return Math.max(1, Math.min(8e3, promptTruncationChars));
|
|
954
|
+
}
|
|
955
|
+
function sampleForScan(value, limit) {
|
|
956
|
+
if (value.length <= limit) return value;
|
|
957
|
+
const prefixLength = Math.ceil(limit / 2);
|
|
958
|
+
return `${value.slice(0, prefixLength)}
|
|
959
|
+
${value.slice(-(limit - prefixLength))}`;
|
|
960
|
+
}
|
|
886
961
|
function applyPromotions(tierConfigs, promotions, profile, now = /* @__PURE__ */ new Date()) {
|
|
887
962
|
if (!promotions || promotions.length === 0) return tierConfigs;
|
|
888
963
|
let result = tierConfigs;
|
|
@@ -925,16 +1000,10 @@ var RulesStrategy = class {
|
|
|
925
1000
|
route(prompt, systemPrompt, maxOutputTokens, options) {
|
|
926
1001
|
const { config, modelPricing } = options;
|
|
927
1002
|
const fullText = `${systemPrompt ?? ""} ${prompt}`;
|
|
928
|
-
const estimatedTokens =
|
|
929
|
-
const
|
|
930
|
-
const
|
|
931
|
-
|
|
932
|
-
const prefixLength = Math.ceil(scanLimit / 2);
|
|
933
|
-
return `${value.slice(0, prefixLength)}
|
|
934
|
-
${value.slice(-(scanLimit - prefixLength))}`;
|
|
935
|
-
};
|
|
936
|
-
const scannedPrompt = sample(prompt);
|
|
937
|
-
const scannedSystemPrompt = systemPrompt ? sample(systemPrompt) : void 0;
|
|
1003
|
+
const estimatedTokens = estimateTokens(fullText);
|
|
1004
|
+
const limit = scanLimit(config.classifier.promptTruncationChars);
|
|
1005
|
+
const scannedPrompt = sampleForScan(prompt, limit);
|
|
1006
|
+
const scannedSystemPrompt = systemPrompt ? sampleForScan(systemPrompt, limit) : void 0;
|
|
938
1007
|
const ruleResult = classifyByRules(
|
|
939
1008
|
scannedPrompt,
|
|
940
1009
|
scannedSystemPrompt,
|
|
@@ -988,7 +1057,7 @@ ${value.slice(-(scanLimit - prefixLength))}`;
|
|
|
988
1057
|
);
|
|
989
1058
|
return { ...decision2, tierConfigs, profile };
|
|
990
1059
|
}
|
|
991
|
-
const hasStructuredOutput = options.requiresStructuredOutput === true
|
|
1060
|
+
const hasStructuredOutput = options.requiresStructuredOutput === true;
|
|
992
1061
|
let tier;
|
|
993
1062
|
let confidence;
|
|
994
1063
|
const method = "rules";
|
|
@@ -2241,16 +2310,10 @@ function likelyNeedsParallelToolCalls(prompt, needsTools, toolCount, toolNames)
|
|
|
2241
2310
|
}
|
|
2242
2311
|
function classifyTask(prompt, systemPrompt, options) {
|
|
2243
2312
|
const fullText = `${systemPrompt ?? ""} ${prompt}`;
|
|
2244
|
-
const estimatedInputTokens =
|
|
2245
|
-
const
|
|
2246
|
-
const
|
|
2247
|
-
|
|
2248
|
-
const prefixLength = Math.ceil(scanLimit / 2);
|
|
2249
|
-
return `${value.slice(0, prefixLength)}
|
|
2250
|
-
${value.slice(-(scanLimit - prefixLength))}`;
|
|
2251
|
-
};
|
|
2252
|
-
const scannedPrompt = sample(prompt);
|
|
2253
|
-
const scannedSystemPrompt = sample(systemPrompt ?? "");
|
|
2313
|
+
const estimatedInputTokens = estimateTokens(fullText);
|
|
2314
|
+
const limit = scanLimit(options.config.classifier.promptTruncationChars);
|
|
2315
|
+
const scannedPrompt = sampleForScan(prompt, limit);
|
|
2316
|
+
const scannedSystemPrompt = sampleForScan(systemPrompt ?? "", limit);
|
|
2254
2317
|
const scannedFullText = `${scannedSystemPrompt} ${scannedPrompt}`;
|
|
2255
2318
|
const text = scannedPrompt.toLowerCase();
|
|
2256
2319
|
const explicitCodeSignal = /```|\b(?:typescript|javascript|python|rust|java|sql|stack trace|traceback|exception)\b|\.(?:ts|tsx|js|py|go|rs)\b/i.test(
|
|
@@ -2262,7 +2325,9 @@ ${value.slice(-(scanLimit - prefixLength))}`;
|
|
|
2262
2325
|
const nativeCodeSignal = /\b(?:programmed|written|implemented?|code)\s+(?:in|using)\s+(?:c\+\+|c|rust|go)\b/i.test(
|
|
2263
2326
|
scannedPrompt
|
|
2264
2327
|
);
|
|
2265
|
-
const
|
|
2328
|
+
const errorClassSignal = /\b[A-Z][A-Za-z]*(?:Error|Exception)\b/.test(scannedPrompt);
|
|
2329
|
+
const hasCode = explicitCodeSignal || codeConstructSignal || nativeCodeSignal || errorClassSignal;
|
|
2330
|
+
const codeArtifact = /```|\b(?:stack trace|traceback)\b|\.(?:ts|tsx|js|py|go|rs)\b/i.test(scannedPrompt) || codeConstructSignal || nativeCodeSignal || errorClassSignal;
|
|
2266
2331
|
const toolsAvailable = options.hasTools ?? false;
|
|
2267
2332
|
const needsTools = options.requiresTools ?? (toolsAvailable && inferToolRequirement(scannedPrompt, scannedSystemPrompt));
|
|
2268
2333
|
const likelyParallelToolCalls = likelyNeedsParallelToolCalls(
|
|
@@ -2334,10 +2399,10 @@ ${value.slice(-(scanLimit - prefixLength))}`;
|
|
|
2334
2399
|
const needsVision = options.hasVision ?? false;
|
|
2335
2400
|
const needsStructuredOutput = options.requiresStructuredOutput ?? false;
|
|
2336
2401
|
const latencySensitive = /\b(?:urgent|asap|fast|quick|low latency|real[- ]time)\b|尽快|马上|快速|低延迟/i.test(
|
|
2337
|
-
|
|
2402
|
+
scannedPrompt
|
|
2338
2403
|
);
|
|
2339
2404
|
const highStakes = /\b(?:production|security|payment|legal|medical|financial|audit)\b|生产|安全|支付|法律|医疗|财务|审计/i.test(
|
|
2340
|
-
|
|
2405
|
+
scannedPrompt
|
|
2341
2406
|
);
|
|
2342
2407
|
const terminalToolSignal = normalizedToolNames.some(
|
|
2343
2408
|
(name) => /^(?:terminalexec|terminalinspect|terminalsendkeys)$/.test(name)
|
|
@@ -2373,7 +2438,7 @@ ${value.slice(-(scanLimit - prefixLength))}`;
|
|
|
2373
2438
|
);
|
|
2374
2439
|
const terminalSafetySensitive = terminalToolSignal && (highStakes || terminalCredentialSignal);
|
|
2375
2440
|
const implicitTerminalCode = needsTools && terminalToolSignal && agentRisk === "standard" && !highStakes && !complexTerminalOperation && numberedSteps < 3 && prompt.length <= 1e3 && simpleTerminalArtifact;
|
|
2376
|
-
const language = /[\u3400-\u9fff]/.test(
|
|
2441
|
+
const language = /[\u3400-\u9fff]/.test(scannedPrompt) ? "zh" : "other";
|
|
2377
2442
|
const multipleChoiceSignals = (scannedPrompt.match(/(?:^|\n)\s*[A-D][.)]\s+/gim) ?? []).length;
|
|
2378
2443
|
const numericSignals = (scannedPrompt.match(/-?\d+(?:[.,]\d+)?/g) ?? []).length;
|
|
2379
2444
|
const compactMathProblem = !hasCode && prompt.length < 2500 && numericSignals >= 2 && (/[+×÷=%$€£¥]|\b(?:total|each|per|times|half|twice|percent|how many|how much|calculate)\b/i.test(
|
|
@@ -2388,7 +2453,7 @@ ${value.slice(-(scanLimit - prefixLength))}`;
|
|
|
2388
2453
|
else if (needsTools) taskType = "tool_agent";
|
|
2389
2454
|
else if (multipleChoiceSignals >= 3) taskType = "reasoning_mcq";
|
|
2390
2455
|
else if (compactMathProblem) taskType = "reasoning_math";
|
|
2391
|
-
else if (/\b(?:bug|debug|error|failure|failing|regression|crash|修复|报错|错误|调试)\b/i.test(text))
|
|
2456
|
+
else if (errorClassSignal || /\b(?:bug|debug|error|failure|failing|regression|crash|修复|报错|错误|调试)\b/i.test(text))
|
|
2392
2457
|
taskType = "debug";
|
|
2393
2458
|
else if (hasCode || /\b(?:refactor|implement|patch|edit|rewrite|重构|实现|修改)\b/i.test(text))
|
|
2394
2459
|
taskType = "code_edit";
|
|
@@ -2414,7 +2479,8 @@ ${value.slice(-(scanLimit - prefixLength))}`;
|
|
|
2414
2479
|
agentRisk,
|
|
2415
2480
|
terminalToolSignal,
|
|
2416
2481
|
terminalSafetySensitive,
|
|
2417
|
-
implicitTerminalCode
|
|
2482
|
+
implicitTerminalCode,
|
|
2483
|
+
codeArtifact
|
|
2418
2484
|
};
|
|
2419
2485
|
}
|
|
2420
2486
|
function affinity(modelId, task, language = "other", agentDomain = "other", deepWebResearch = false, agentRisk = "standard", terminalToolSignal = false, terminalSafetySensitive = false) {
|
|
@@ -2817,15 +2883,17 @@ function profileScore(modelId, options, now) {
|
|
|
2817
2883
|
}
|
|
2818
2884
|
var PortfolioStrategy = class {
|
|
2819
2885
|
name = "portfolio";
|
|
2886
|
+
// Rules set the capability tier; the strategy is stateless, so one instance serves every request.
|
|
2887
|
+
rules = new RulesStrategy();
|
|
2820
2888
|
route(prompt, systemPrompt, maxOutputTokens, options) {
|
|
2821
2889
|
const features = classifyTask(prompt, systemPrompt, options);
|
|
2822
|
-
const base =
|
|
2890
|
+
const base = this.rules.route(prompt, systemPrompt, maxOutputTokens, {
|
|
2823
2891
|
...options,
|
|
2824
2892
|
requiresTools: features.needsTools
|
|
2825
2893
|
});
|
|
2826
2894
|
const tierConfigs = base.tierConfigs;
|
|
2827
2895
|
if (!tierConfigs) return base;
|
|
2828
|
-
const targetTier = (features.taskType === "reasoning_mcq" || features.taskType === "reasoning_math") && (base.tier === "SIMPLE" || base.tier === "MEDIUM") ? "REASONING" : base.tier;
|
|
2896
|
+
const targetTier = (features.taskType === "reasoning_mcq" || features.taskType === "reasoning_math") && (base.tier === "SIMPLE" || base.tier === "MEDIUM") ? "REASONING" : (features.taskType === "debug" || features.taskType === "code_edit") && features.codeArtifact && base.tier === "SIMPLE" ? "MEDIUM" : base.tier;
|
|
2829
2897
|
const tierConfig = tierConfigs[targetTier];
|
|
2830
2898
|
const configuredCandidates = tierConfig ? getFallbackChain(targetTier, tierConfigs) : [];
|
|
2831
2899
|
const unavailable = new Set(options.unavailableModels ?? []);
|
|
@@ -2843,10 +2911,10 @@ var PortfolioStrategy = class {
|
|
|
2843
2911
|
].filter(
|
|
2844
2912
|
(model2) => typeof model2 === "string" && model2.length > 0 && !unavailable.has(model2)
|
|
2845
2913
|
);
|
|
2846
|
-
const eligible =
|
|
2847
|
-
(model2) => isEligible(model2, features, maxOutputTokens, options)
|
|
2914
|
+
const eligible = new Set(
|
|
2915
|
+
chain.filter((model2) => isEligible(model2, features, maxOutputTokens, options))
|
|
2848
2916
|
);
|
|
2849
|
-
const eligibleCandidates = eligible.
|
|
2917
|
+
const eligibleCandidates = eligible.size > 0 ? [...eligible] : chain;
|
|
2850
2918
|
if (eligibleCandidates.length === 0) return base;
|
|
2851
2919
|
const profileName = options.routingProfile === "eco" ? "eco" : options.routingProfile === "premium" ? "premium" : "auto";
|
|
2852
2920
|
const portfolio = options.config.portfolio ?? DEFAULT_PORTFOLIO_WEIGHTS;
|
|
@@ -2881,11 +2949,11 @@ var PortfolioStrategy = class {
|
|
|
2881
2949
|
const rankedEntries = candidates.map((model2, index) => {
|
|
2882
2950
|
const cost = estimatedCost(model2, options, features.estimatedInputTokens, maxOutputTokens);
|
|
2883
2951
|
const costScore = Number.isFinite(cost) && maxCost > minCost ? 1 - (cost - minCost) / (maxCost - minCost) : 0.5;
|
|
2884
|
-
const capabilityScore =
|
|
2952
|
+
const capabilityScore = eligible.has(model2) ? 1 : 0;
|
|
2885
2953
|
const profile = profileScore(model2, options, now);
|
|
2886
2954
|
const observedQuality = profile?.quality === void 0 ? getAffinity(model2) : getAffinity(model2) * (1 - profile.freshness) + profile.quality * profile.freshness;
|
|
2887
|
-
const observedSpeed = profile ? profile.speed * profile.freshness : 0.5;
|
|
2888
|
-
const observedTailSpeed = profile ? profile.tailSpeed * profile.freshness : 0.5;
|
|
2955
|
+
const observedSpeed = profile ? profile.speed * profile.freshness + 0.5 * (1 - profile.freshness) : 0.5;
|
|
2956
|
+
const observedTailSpeed = profile ? profile.tailSpeed * profile.freshness + 0.5 * (1 - profile.freshness) : 0.5;
|
|
2889
2957
|
const observedReliability = profile ? profile.reliability * profile.freshness + (1 - profile.freshness) : 1;
|
|
2890
2958
|
const legacyScore = 1 - index / Math.max(1, candidates.length - 1);
|
|
2891
2959
|
const qualityWeight = profileWeights.quality + (features.highStakes ? portfolio.highStakesBoost.quality : 0);
|
|
@@ -4977,7 +5045,7 @@ function getCostSummary() {
|
|
|
4977
5045
|
}
|
|
4978
5046
|
|
|
4979
5047
|
// src/version.ts
|
|
4980
|
-
var SDK_VERSION = "3.24.
|
|
5048
|
+
var SDK_VERSION = "3.24.2";
|
|
4981
5049
|
var USER_AGENT = `blockrun-ts/${SDK_VERSION}`;
|
|
4982
5050
|
|
|
4983
5051
|
// src/client.ts
|
package/dist/index.js
CHANGED
|
@@ -440,7 +440,69 @@ function withCost(body, response, bookedUsd, scheme) {
|
|
|
440
440
|
// src/client.ts
|
|
441
441
|
import { privateKeyToAccount } from "viem/accounts";
|
|
442
442
|
|
|
443
|
-
// node_modules/.pnpm/@blockrun+router-core@https+++codeload.github.com+BlockRunAI+router-core+tar.gz+
|
|
443
|
+
// node_modules/.pnpm/@blockrun+router-core@https+++codeload.github.com+BlockRunAI+router-core+tar.gz+65a92c85ea1f1_ulf6q3mq2pzpwvcnu73z4krxvy/node_modules/@blockrun/router-core/dist/index.js
|
|
444
|
+
var UNSEGMENTED_SCRIPT = /[-ۿ -ヿ㐀-䶿一-鿿가-豈--]/;
|
|
445
|
+
var WORD_CHAR = /[\p{L}\p{N}]/u;
|
|
446
|
+
var ASCII_PHRASE = /^[a-z0-9' -]+$/;
|
|
447
|
+
var SEGMENTED_WORD_CHAR = "\\p{Script=Latin}\\p{Script=Cyrillic}\\p{Script=Greek}\\p{N}";
|
|
448
|
+
var BOUNDARY_BEFORE = `(?<![${SEGMENTED_WORD_CHAR}])`;
|
|
449
|
+
var BOUNDARY_AFTER = `(?![${SEGMENTED_WORD_CHAR}])`;
|
|
450
|
+
var BOUNDED_LAST_WORD_LENGTH = 6;
|
|
451
|
+
var SHORT_SUFFIXES = "(?:s|ed|ing)?";
|
|
452
|
+
var SIBILANT_PLURAL = "es";
|
|
453
|
+
var MID_SUFFIXES = "(?:s|es|ed|d|ing|er|ers|ly|ment|ments|ation|ations|e|en|n|a|as|o|os|em|et|ung|ungen)?";
|
|
454
|
+
var DROPPED_E_SUFFIXES = "(?:ing|ed|es|er|ers|ation|ations)";
|
|
455
|
+
var DOUBLED_CONSONANT_SUFFIXES = "(?:ing|ed|er|ers)";
|
|
456
|
+
var matcherCache = /* @__PURE__ */ new Map();
|
|
457
|
+
function escapeRegExp(value) {
|
|
458
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
459
|
+
}
|
|
460
|
+
function keywordMatcher(keyword) {
|
|
461
|
+
const cached = matcherCache.get(keyword);
|
|
462
|
+
if (cached) return cached;
|
|
463
|
+
const kw = keyword.toLowerCase();
|
|
464
|
+
let matcher;
|
|
465
|
+
if (UNSEGMENTED_SCRIPT.test(kw) || kw.length === 0) {
|
|
466
|
+
matcher = { needle: kw, pattern: null };
|
|
467
|
+
} else {
|
|
468
|
+
const lead = WORD_CHAR.test(kw[0]) ? BOUNDARY_BEFORE : "";
|
|
469
|
+
const escaped = escapeRegExp(kw);
|
|
470
|
+
let body = escaped;
|
|
471
|
+
let trail = "";
|
|
472
|
+
let needle = kw;
|
|
473
|
+
const lastWord = kw.slice(kw.lastIndexOf(" ") + 1);
|
|
474
|
+
if (WORD_CHAR.test(kw[kw.length - 1]) && ASCII_PHRASE.test(kw) && lastWord.length <= BOUNDED_LAST_WORD_LENGTH) {
|
|
475
|
+
const forms = [];
|
|
476
|
+
if (/\d$/.test(kw)) {
|
|
477
|
+
forms.push(escaped);
|
|
478
|
+
} else if (lastWord.length <= 3) {
|
|
479
|
+
forms.push(`${escaped}${SHORT_SUFFIXES}`);
|
|
480
|
+
if (/(?:x|s|z|ch|sh)$/.test(kw)) forms.push(`${escaped}${SIBILANT_PLURAL}`);
|
|
481
|
+
} else {
|
|
482
|
+
forms.push(`${escaped}${MID_SUFFIXES}`);
|
|
483
|
+
if (kw.endsWith("e")) {
|
|
484
|
+
forms.push(`${escaped.slice(0, -1)}${DROPPED_E_SUFFIXES}`);
|
|
485
|
+
needle = kw.slice(0, -1);
|
|
486
|
+
} else if (kw.endsWith("y")) {
|
|
487
|
+
forms.push(`${escaped.slice(0, -1)}(?:ies|ied)`);
|
|
488
|
+
needle = kw.slice(0, -1);
|
|
489
|
+
} else if (/[aeiou][bdgmnprt]$/.test(kw)) {
|
|
490
|
+
forms.push(`${escaped}${kw[kw.length - 1]}${DOUBLED_CONSONANT_SUFFIXES}`);
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
body = `(?:${forms.join("|")})`;
|
|
494
|
+
trail = BOUNDARY_AFTER;
|
|
495
|
+
}
|
|
496
|
+
matcher = { needle, pattern: new RegExp(`${lead}${body}${trail}`, "u") };
|
|
497
|
+
}
|
|
498
|
+
matcherCache.set(keyword, matcher);
|
|
499
|
+
return matcher;
|
|
500
|
+
}
|
|
501
|
+
function matchesKeyword(text, keyword) {
|
|
502
|
+
const { needle, pattern } = keywordMatcher(keyword);
|
|
503
|
+
if (!text.includes(needle)) return false;
|
|
504
|
+
return pattern === null ? true : pattern.test(text);
|
|
505
|
+
}
|
|
444
506
|
function scoreTokenCount(estimatedTokens, thresholds) {
|
|
445
507
|
if (estimatedTokens < thresholds.simple) {
|
|
446
508
|
return { name: "tokenCount", score: -1, signal: `short (${estimatedTokens} tokens)` };
|
|
@@ -451,7 +513,7 @@ function scoreTokenCount(estimatedTokens, thresholds) {
|
|
|
451
513
|
return { name: "tokenCount", score: 0, signal: null };
|
|
452
514
|
}
|
|
453
515
|
function scoreKeywordMatch(text, keywords, name, signalLabel, thresholds, scores) {
|
|
454
|
-
const matches = keywords.filter((kw) => text
|
|
516
|
+
const matches = keywords.filter((kw) => matchesKeyword(text, kw));
|
|
455
517
|
if (matches.length >= thresholds.high) {
|
|
456
518
|
return {
|
|
457
519
|
name,
|
|
@@ -487,7 +549,7 @@ function scoreAgenticTask(text, keywords) {
|
|
|
487
549
|
let matchCount = 0;
|
|
488
550
|
const signals = [];
|
|
489
551
|
for (const keyword of keywords) {
|
|
490
|
-
if (text
|
|
552
|
+
if (matchesKeyword(text, keyword)) {
|
|
491
553
|
matchCount++;
|
|
492
554
|
if (signals.length < 3) {
|
|
493
555
|
signals.push(keyword);
|
|
@@ -634,9 +696,7 @@ function classifyByRules(prompt, systemPrompt, estimatedTokens, config) {
|
|
|
634
696
|
const w = weights[d.name] ?? 0;
|
|
635
697
|
weightedScore += d.score * w;
|
|
636
698
|
}
|
|
637
|
-
const reasoningMatches = config.reasoningKeywords.filter(
|
|
638
|
-
(kw) => userText.includes(kw.toLowerCase())
|
|
639
|
-
);
|
|
699
|
+
const reasoningMatches = config.reasoningKeywords.filter((kw) => matchesKeyword(userText, kw));
|
|
640
700
|
if (reasoningMatches.length >= 2) {
|
|
641
701
|
const confidence2 = calibrateConfidence(
|
|
642
702
|
Math.max(weightedScore, 0.3),
|
|
@@ -701,7 +761,7 @@ function selectModel(tier, confidence, method, reasoning, tierConfigs, modelPric
|
|
|
701
761
|
const baselineInput = estimatedInputTokens / 1e6 * opusInputPrice;
|
|
702
762
|
const baselineOutput = maxOutputTokens / 1e6 * opusOutputPrice;
|
|
703
763
|
const baselineCost = baselineInput + baselineOutput;
|
|
704
|
-
const savings = routingProfile === "premium" ? 0 : baselineCost > 0 ? Math.max(0, (baselineCost - costEstimate) / baselineCost) : 0;
|
|
764
|
+
const savings = routingProfile === "premium" || pricing === void 0 ? 0 : baselineCost > 0 ? Math.max(0, (baselineCost - costEstimate) / baselineCost) : 0;
|
|
705
765
|
return {
|
|
706
766
|
model,
|
|
707
767
|
tier,
|
|
@@ -752,6 +812,21 @@ function filterCandidatesByCapacity(models, estimatedInputTokens, requestedOutpu
|
|
|
752
812
|
});
|
|
753
813
|
return filtered;
|
|
754
814
|
}
|
|
815
|
+
var CJK_CHARS = /[ -ヿ㐀-䶿一-鿿가-豈--]/g;
|
|
816
|
+
function estimateTokens(text) {
|
|
817
|
+
if (text.length === 0) return 0;
|
|
818
|
+
const cjk = text.match(CJK_CHARS)?.length ?? 0;
|
|
819
|
+
return cjk + Math.ceil((text.length - cjk) / 4);
|
|
820
|
+
}
|
|
821
|
+
function scanLimit(promptTruncationChars) {
|
|
822
|
+
return Math.max(1, Math.min(8e3, promptTruncationChars));
|
|
823
|
+
}
|
|
824
|
+
function sampleForScan(value, limit) {
|
|
825
|
+
if (value.length <= limit) return value;
|
|
826
|
+
const prefixLength = Math.ceil(limit / 2);
|
|
827
|
+
return `${value.slice(0, prefixLength)}
|
|
828
|
+
${value.slice(-(limit - prefixLength))}`;
|
|
829
|
+
}
|
|
755
830
|
function applyPromotions(tierConfigs, promotions, profile, now = /* @__PURE__ */ new Date()) {
|
|
756
831
|
if (!promotions || promotions.length === 0) return tierConfigs;
|
|
757
832
|
let result = tierConfigs;
|
|
@@ -794,16 +869,10 @@ var RulesStrategy = class {
|
|
|
794
869
|
route(prompt, systemPrompt, maxOutputTokens, options) {
|
|
795
870
|
const { config, modelPricing } = options;
|
|
796
871
|
const fullText = `${systemPrompt ?? ""} ${prompt}`;
|
|
797
|
-
const estimatedTokens =
|
|
798
|
-
const
|
|
799
|
-
const
|
|
800
|
-
|
|
801
|
-
const prefixLength = Math.ceil(scanLimit / 2);
|
|
802
|
-
return `${value.slice(0, prefixLength)}
|
|
803
|
-
${value.slice(-(scanLimit - prefixLength))}`;
|
|
804
|
-
};
|
|
805
|
-
const scannedPrompt = sample(prompt);
|
|
806
|
-
const scannedSystemPrompt = systemPrompt ? sample(systemPrompt) : void 0;
|
|
872
|
+
const estimatedTokens = estimateTokens(fullText);
|
|
873
|
+
const limit = scanLimit(config.classifier.promptTruncationChars);
|
|
874
|
+
const scannedPrompt = sampleForScan(prompt, limit);
|
|
875
|
+
const scannedSystemPrompt = systemPrompt ? sampleForScan(systemPrompt, limit) : void 0;
|
|
807
876
|
const ruleResult = classifyByRules(
|
|
808
877
|
scannedPrompt,
|
|
809
878
|
scannedSystemPrompt,
|
|
@@ -857,7 +926,7 @@ ${value.slice(-(scanLimit - prefixLength))}`;
|
|
|
857
926
|
);
|
|
858
927
|
return { ...decision2, tierConfigs, profile };
|
|
859
928
|
}
|
|
860
|
-
const hasStructuredOutput = options.requiresStructuredOutput === true
|
|
929
|
+
const hasStructuredOutput = options.requiresStructuredOutput === true;
|
|
861
930
|
let tier;
|
|
862
931
|
let confidence;
|
|
863
932
|
const method = "rules";
|
|
@@ -2110,16 +2179,10 @@ function likelyNeedsParallelToolCalls(prompt, needsTools, toolCount, toolNames)
|
|
|
2110
2179
|
}
|
|
2111
2180
|
function classifyTask(prompt, systemPrompt, options) {
|
|
2112
2181
|
const fullText = `${systemPrompt ?? ""} ${prompt}`;
|
|
2113
|
-
const estimatedInputTokens =
|
|
2114
|
-
const
|
|
2115
|
-
const
|
|
2116
|
-
|
|
2117
|
-
const prefixLength = Math.ceil(scanLimit / 2);
|
|
2118
|
-
return `${value.slice(0, prefixLength)}
|
|
2119
|
-
${value.slice(-(scanLimit - prefixLength))}`;
|
|
2120
|
-
};
|
|
2121
|
-
const scannedPrompt = sample(prompt);
|
|
2122
|
-
const scannedSystemPrompt = sample(systemPrompt ?? "");
|
|
2182
|
+
const estimatedInputTokens = estimateTokens(fullText);
|
|
2183
|
+
const limit = scanLimit(options.config.classifier.promptTruncationChars);
|
|
2184
|
+
const scannedPrompt = sampleForScan(prompt, limit);
|
|
2185
|
+
const scannedSystemPrompt = sampleForScan(systemPrompt ?? "", limit);
|
|
2123
2186
|
const scannedFullText = `${scannedSystemPrompt} ${scannedPrompt}`;
|
|
2124
2187
|
const text = scannedPrompt.toLowerCase();
|
|
2125
2188
|
const explicitCodeSignal = /```|\b(?:typescript|javascript|python|rust|java|sql|stack trace|traceback|exception)\b|\.(?:ts|tsx|js|py|go|rs)\b/i.test(
|
|
@@ -2131,7 +2194,9 @@ ${value.slice(-(scanLimit - prefixLength))}`;
|
|
|
2131
2194
|
const nativeCodeSignal = /\b(?:programmed|written|implemented?|code)\s+(?:in|using)\s+(?:c\+\+|c|rust|go)\b/i.test(
|
|
2132
2195
|
scannedPrompt
|
|
2133
2196
|
);
|
|
2134
|
-
const
|
|
2197
|
+
const errorClassSignal = /\b[A-Z][A-Za-z]*(?:Error|Exception)\b/.test(scannedPrompt);
|
|
2198
|
+
const hasCode = explicitCodeSignal || codeConstructSignal || nativeCodeSignal || errorClassSignal;
|
|
2199
|
+
const codeArtifact = /```|\b(?:stack trace|traceback)\b|\.(?:ts|tsx|js|py|go|rs)\b/i.test(scannedPrompt) || codeConstructSignal || nativeCodeSignal || errorClassSignal;
|
|
2135
2200
|
const toolsAvailable = options.hasTools ?? false;
|
|
2136
2201
|
const needsTools = options.requiresTools ?? (toolsAvailable && inferToolRequirement(scannedPrompt, scannedSystemPrompt));
|
|
2137
2202
|
const likelyParallelToolCalls = likelyNeedsParallelToolCalls(
|
|
@@ -2203,10 +2268,10 @@ ${value.slice(-(scanLimit - prefixLength))}`;
|
|
|
2203
2268
|
const needsVision = options.hasVision ?? false;
|
|
2204
2269
|
const needsStructuredOutput = options.requiresStructuredOutput ?? false;
|
|
2205
2270
|
const latencySensitive = /\b(?:urgent|asap|fast|quick|low latency|real[- ]time)\b|尽快|马上|快速|低延迟/i.test(
|
|
2206
|
-
|
|
2271
|
+
scannedPrompt
|
|
2207
2272
|
);
|
|
2208
2273
|
const highStakes = /\b(?:production|security|payment|legal|medical|financial|audit)\b|生产|安全|支付|法律|医疗|财务|审计/i.test(
|
|
2209
|
-
|
|
2274
|
+
scannedPrompt
|
|
2210
2275
|
);
|
|
2211
2276
|
const terminalToolSignal = normalizedToolNames.some(
|
|
2212
2277
|
(name) => /^(?:terminalexec|terminalinspect|terminalsendkeys)$/.test(name)
|
|
@@ -2242,7 +2307,7 @@ ${value.slice(-(scanLimit - prefixLength))}`;
|
|
|
2242
2307
|
);
|
|
2243
2308
|
const terminalSafetySensitive = terminalToolSignal && (highStakes || terminalCredentialSignal);
|
|
2244
2309
|
const implicitTerminalCode = needsTools && terminalToolSignal && agentRisk === "standard" && !highStakes && !complexTerminalOperation && numberedSteps < 3 && prompt.length <= 1e3 && simpleTerminalArtifact;
|
|
2245
|
-
const language = /[\u3400-\u9fff]/.test(
|
|
2310
|
+
const language = /[\u3400-\u9fff]/.test(scannedPrompt) ? "zh" : "other";
|
|
2246
2311
|
const multipleChoiceSignals = (scannedPrompt.match(/(?:^|\n)\s*[A-D][.)]\s+/gim) ?? []).length;
|
|
2247
2312
|
const numericSignals = (scannedPrompt.match(/-?\d+(?:[.,]\d+)?/g) ?? []).length;
|
|
2248
2313
|
const compactMathProblem = !hasCode && prompt.length < 2500 && numericSignals >= 2 && (/[+×÷=%$€£¥]|\b(?:total|each|per|times|half|twice|percent|how many|how much|calculate)\b/i.test(
|
|
@@ -2257,7 +2322,7 @@ ${value.slice(-(scanLimit - prefixLength))}`;
|
|
|
2257
2322
|
else if (needsTools) taskType = "tool_agent";
|
|
2258
2323
|
else if (multipleChoiceSignals >= 3) taskType = "reasoning_mcq";
|
|
2259
2324
|
else if (compactMathProblem) taskType = "reasoning_math";
|
|
2260
|
-
else if (/\b(?:bug|debug|error|failure|failing|regression|crash|修复|报错|错误|调试)\b/i.test(text))
|
|
2325
|
+
else if (errorClassSignal || /\b(?:bug|debug|error|failure|failing|regression|crash|修复|报错|错误|调试)\b/i.test(text))
|
|
2261
2326
|
taskType = "debug";
|
|
2262
2327
|
else if (hasCode || /\b(?:refactor|implement|patch|edit|rewrite|重构|实现|修改)\b/i.test(text))
|
|
2263
2328
|
taskType = "code_edit";
|
|
@@ -2283,7 +2348,8 @@ ${value.slice(-(scanLimit - prefixLength))}`;
|
|
|
2283
2348
|
agentRisk,
|
|
2284
2349
|
terminalToolSignal,
|
|
2285
2350
|
terminalSafetySensitive,
|
|
2286
|
-
implicitTerminalCode
|
|
2351
|
+
implicitTerminalCode,
|
|
2352
|
+
codeArtifact
|
|
2287
2353
|
};
|
|
2288
2354
|
}
|
|
2289
2355
|
function affinity(modelId, task, language = "other", agentDomain = "other", deepWebResearch = false, agentRisk = "standard", terminalToolSignal = false, terminalSafetySensitive = false) {
|
|
@@ -2686,15 +2752,17 @@ function profileScore(modelId, options, now) {
|
|
|
2686
2752
|
}
|
|
2687
2753
|
var PortfolioStrategy = class {
|
|
2688
2754
|
name = "portfolio";
|
|
2755
|
+
// Rules set the capability tier; the strategy is stateless, so one instance serves every request.
|
|
2756
|
+
rules = new RulesStrategy();
|
|
2689
2757
|
route(prompt, systemPrompt, maxOutputTokens, options) {
|
|
2690
2758
|
const features = classifyTask(prompt, systemPrompt, options);
|
|
2691
|
-
const base =
|
|
2759
|
+
const base = this.rules.route(prompt, systemPrompt, maxOutputTokens, {
|
|
2692
2760
|
...options,
|
|
2693
2761
|
requiresTools: features.needsTools
|
|
2694
2762
|
});
|
|
2695
2763
|
const tierConfigs = base.tierConfigs;
|
|
2696
2764
|
if (!tierConfigs) return base;
|
|
2697
|
-
const targetTier = (features.taskType === "reasoning_mcq" || features.taskType === "reasoning_math") && (base.tier === "SIMPLE" || base.tier === "MEDIUM") ? "REASONING" : base.tier;
|
|
2765
|
+
const targetTier = (features.taskType === "reasoning_mcq" || features.taskType === "reasoning_math") && (base.tier === "SIMPLE" || base.tier === "MEDIUM") ? "REASONING" : (features.taskType === "debug" || features.taskType === "code_edit") && features.codeArtifact && base.tier === "SIMPLE" ? "MEDIUM" : base.tier;
|
|
2698
2766
|
const tierConfig = tierConfigs[targetTier];
|
|
2699
2767
|
const configuredCandidates = tierConfig ? getFallbackChain(targetTier, tierConfigs) : [];
|
|
2700
2768
|
const unavailable = new Set(options.unavailableModels ?? []);
|
|
@@ -2712,10 +2780,10 @@ var PortfolioStrategy = class {
|
|
|
2712
2780
|
].filter(
|
|
2713
2781
|
(model2) => typeof model2 === "string" && model2.length > 0 && !unavailable.has(model2)
|
|
2714
2782
|
);
|
|
2715
|
-
const eligible =
|
|
2716
|
-
(model2) => isEligible(model2, features, maxOutputTokens, options)
|
|
2783
|
+
const eligible = new Set(
|
|
2784
|
+
chain.filter((model2) => isEligible(model2, features, maxOutputTokens, options))
|
|
2717
2785
|
);
|
|
2718
|
-
const eligibleCandidates = eligible.
|
|
2786
|
+
const eligibleCandidates = eligible.size > 0 ? [...eligible] : chain;
|
|
2719
2787
|
if (eligibleCandidates.length === 0) return base;
|
|
2720
2788
|
const profileName = options.routingProfile === "eco" ? "eco" : options.routingProfile === "premium" ? "premium" : "auto";
|
|
2721
2789
|
const portfolio = options.config.portfolio ?? DEFAULT_PORTFOLIO_WEIGHTS;
|
|
@@ -2750,11 +2818,11 @@ var PortfolioStrategy = class {
|
|
|
2750
2818
|
const rankedEntries = candidates.map((model2, index) => {
|
|
2751
2819
|
const cost = estimatedCost(model2, options, features.estimatedInputTokens, maxOutputTokens);
|
|
2752
2820
|
const costScore = Number.isFinite(cost) && maxCost > minCost ? 1 - (cost - minCost) / (maxCost - minCost) : 0.5;
|
|
2753
|
-
const capabilityScore =
|
|
2821
|
+
const capabilityScore = eligible.has(model2) ? 1 : 0;
|
|
2754
2822
|
const profile = profileScore(model2, options, now);
|
|
2755
2823
|
const observedQuality = profile?.quality === void 0 ? getAffinity(model2) : getAffinity(model2) * (1 - profile.freshness) + profile.quality * profile.freshness;
|
|
2756
|
-
const observedSpeed = profile ? profile.speed * profile.freshness : 0.5;
|
|
2757
|
-
const observedTailSpeed = profile ? profile.tailSpeed * profile.freshness : 0.5;
|
|
2824
|
+
const observedSpeed = profile ? profile.speed * profile.freshness + 0.5 * (1 - profile.freshness) : 0.5;
|
|
2825
|
+
const observedTailSpeed = profile ? profile.tailSpeed * profile.freshness + 0.5 * (1 - profile.freshness) : 0.5;
|
|
2758
2826
|
const observedReliability = profile ? profile.reliability * profile.freshness + (1 - profile.freshness) : 1;
|
|
2759
2827
|
const legacyScore = 1 - index / Math.max(1, candidates.length - 1);
|
|
2760
2828
|
const qualityWeight = profileWeights.quality + (features.highStakes ? portfolio.highStakesBoost.quality : 0);
|
|
@@ -4846,7 +4914,7 @@ function getCostSummary() {
|
|
|
4846
4914
|
}
|
|
4847
4915
|
|
|
4848
4916
|
// src/version.ts
|
|
4849
|
-
var SDK_VERSION = "3.24.
|
|
4917
|
+
var SDK_VERSION = "3.24.2";
|
|
4850
4918
|
var USER_AGENT = `blockrun-ts/${SDK_VERSION}`;
|
|
4851
4919
|
|
|
4852
4920
|
// src/client.ts
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@blockrun/llm",
|
|
3
|
-
"version": "3.24.
|
|
3
|
+
"version": "3.24.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "TypeScript SDK for BlockRun - every frontier model behind one OpenAI-compatible client. Pay with a BlockRun API key or per-call in USDC. Smart routing picks the cheapest capable model. No rate limits.",
|
|
6
6
|
"main": "dist/index.cjs",
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
},
|
|
59
59
|
"devDependencies": {
|
|
60
60
|
"@blockrun/core": "^0.1.0",
|
|
61
|
-
"@blockrun/router-core": "https://codeload.github.com/BlockRunAI/router-core/tar.gz/
|
|
61
|
+
"@blockrun/router-core": "https://codeload.github.com/BlockRunAI/router-core/tar.gz/65a92c85ea1f187a64e7611302ef6add236b0cba",
|
|
62
62
|
"@eslint/js": "^10.0.1",
|
|
63
63
|
"@solana/kit": "^5.5.1",
|
|
64
64
|
"@types/node": "^26.4.1",
|