@blockrun/clawrouter 0.6.7 → 0.6.9
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.js +95 -42
- package/dist/index.js.map +1 -1
- package/package.json +3 -2
package/dist/index.js
CHANGED
|
@@ -715,7 +715,7 @@ function scoreAgenticTask(text, keywords) {
|
|
|
715
715
|
}
|
|
716
716
|
}
|
|
717
717
|
}
|
|
718
|
-
if (matchCount >=
|
|
718
|
+
if (matchCount >= 4) {
|
|
719
719
|
return {
|
|
720
720
|
dimensionScore: {
|
|
721
721
|
name: "agenticTask",
|
|
@@ -724,7 +724,7 @@ function scoreAgenticTask(text, keywords) {
|
|
|
724
724
|
},
|
|
725
725
|
agenticScore: 1
|
|
726
726
|
};
|
|
727
|
-
} else if (matchCount >=
|
|
727
|
+
} else if (matchCount >= 3) {
|
|
728
728
|
return {
|
|
729
729
|
dimensionScore: {
|
|
730
730
|
name: "agenticTask",
|
|
@@ -737,10 +737,10 @@ function scoreAgenticTask(text, keywords) {
|
|
|
737
737
|
return {
|
|
738
738
|
dimensionScore: {
|
|
739
739
|
name: "agenticTask",
|
|
740
|
-
score: 0.
|
|
741
|
-
signal: `agentic (${signals.join(", ")})`
|
|
740
|
+
score: 0.2,
|
|
741
|
+
signal: `agentic-light (${signals.join(", ")})`
|
|
742
742
|
},
|
|
743
|
-
agenticScore: 0.
|
|
743
|
+
agenticScore: 0.2
|
|
744
744
|
};
|
|
745
745
|
}
|
|
746
746
|
return {
|
|
@@ -1479,8 +1479,9 @@ var DEFAULT_ROUTING_CONFIG = {
|
|
|
1479
1479
|
"gitterbasiert"
|
|
1480
1480
|
],
|
|
1481
1481
|
// Agentic task keywords - file ops, execution, multi-step, iterative work
|
|
1482
|
+
// Pruned: removed overly common words like "then", "first", "run", "test", "build"
|
|
1482
1483
|
agenticTaskKeywords: [
|
|
1483
|
-
// English - File operations
|
|
1484
|
+
// English - File operations (clearly agentic)
|
|
1484
1485
|
"read file",
|
|
1485
1486
|
"read the file",
|
|
1486
1487
|
"look at",
|
|
@@ -1492,30 +1493,19 @@ var DEFAULT_ROUTING_CONFIG = {
|
|
|
1492
1493
|
"change the",
|
|
1493
1494
|
"write to",
|
|
1494
1495
|
"create file",
|
|
1495
|
-
// English - Execution
|
|
1496
|
-
"run",
|
|
1496
|
+
// English - Execution (specific commands only)
|
|
1497
1497
|
"execute",
|
|
1498
|
-
"test",
|
|
1499
|
-
"build",
|
|
1500
1498
|
"deploy",
|
|
1501
1499
|
"install",
|
|
1502
1500
|
"npm",
|
|
1503
1501
|
"pip",
|
|
1504
1502
|
"compile",
|
|
1505
|
-
|
|
1506
|
-
"launch",
|
|
1507
|
-
// English - Multi-step patterns
|
|
1508
|
-
"then",
|
|
1503
|
+
// English - Multi-step patterns (specific only)
|
|
1509
1504
|
"after that",
|
|
1510
|
-
"next",
|
|
1511
1505
|
"and also",
|
|
1512
|
-
"finally",
|
|
1513
1506
|
"once done",
|
|
1514
1507
|
"step 1",
|
|
1515
1508
|
"step 2",
|
|
1516
|
-
"first",
|
|
1517
|
-
"second",
|
|
1518
|
-
"lastly",
|
|
1519
1509
|
// English - Iterative work
|
|
1520
1510
|
"fix",
|
|
1521
1511
|
"debug",
|
|
@@ -1525,7 +1515,7 @@ var DEFAULT_ROUTING_CONFIG = {
|
|
|
1525
1515
|
"make sure",
|
|
1526
1516
|
"verify",
|
|
1527
1517
|
"confirm",
|
|
1528
|
-
// Chinese
|
|
1518
|
+
// Chinese (keep specific ones)
|
|
1529
1519
|
"\u8BFB\u53D6\u6587\u4EF6",
|
|
1530
1520
|
"\u67E5\u770B",
|
|
1531
1521
|
"\u6253\u5F00",
|
|
@@ -1533,15 +1523,9 @@ var DEFAULT_ROUTING_CONFIG = {
|
|
|
1533
1523
|
"\u4FEE\u6539",
|
|
1534
1524
|
"\u66F4\u65B0",
|
|
1535
1525
|
"\u521B\u5EFA",
|
|
1536
|
-
"\u8FD0\u884C",
|
|
1537
1526
|
"\u6267\u884C",
|
|
1538
|
-
"\u6D4B\u8BD5",
|
|
1539
|
-
"\u6784\u5EFA",
|
|
1540
1527
|
"\u90E8\u7F72",
|
|
1541
1528
|
"\u5B89\u88C5",
|
|
1542
|
-
"\u7136\u540E",
|
|
1543
|
-
"\u63A5\u4E0B\u6765",
|
|
1544
|
-
"\u6700\u540E",
|
|
1545
1529
|
"\u7B2C\u4E00\u6B65",
|
|
1546
1530
|
"\u7B2C\u4E8C\u6B65",
|
|
1547
1531
|
"\u4FEE\u590D",
|
|
@@ -1567,14 +1551,15 @@ var DEFAULT_ROUTING_CONFIG = {
|
|
|
1567
1551
|
referenceComplexity: 0.02,
|
|
1568
1552
|
negationComplexity: 0.01,
|
|
1569
1553
|
domainSpecificity: 0.02,
|
|
1570
|
-
agenticTask: 0.
|
|
1571
|
-
//
|
|
1554
|
+
agenticTask: 0.04
|
|
1555
|
+
// Reduced - agentic signals influence tier selection, not dominate it
|
|
1572
1556
|
},
|
|
1573
1557
|
// Tier boundaries on weighted score axis
|
|
1574
1558
|
tierBoundaries: {
|
|
1575
1559
|
simpleMedium: 0,
|
|
1576
|
-
mediumComplex: 0.
|
|
1577
|
-
complexReasoning: 0.
|
|
1560
|
+
mediumComplex: 0.18,
|
|
1561
|
+
complexReasoning: 0.4
|
|
1562
|
+
// Raised from 0.25 - requires strong reasoning signals
|
|
1578
1563
|
},
|
|
1579
1564
|
// Sigmoid steepness for confidence calibration
|
|
1580
1565
|
confidenceSteepness: 12,
|
|
@@ -1621,9 +1606,9 @@ var DEFAULT_ROUTING_CONFIG = {
|
|
|
1621
1606
|
fallback: ["anthropic/claude-opus-4", "xai/grok-4-0709", "openai/gpt-4o"]
|
|
1622
1607
|
},
|
|
1623
1608
|
REASONING: {
|
|
1624
|
-
primary: "
|
|
1625
|
-
//
|
|
1626
|
-
fallback: ["
|
|
1609
|
+
primary: "anthropic/claude-sonnet-4",
|
|
1610
|
+
// Strong tool use + reasoning for agentic tasks
|
|
1611
|
+
fallback: ["xai/grok-4-fast-reasoning", "moonshot/kimi-k2.5", "deepseek/deepseek-reasoner"]
|
|
1627
1612
|
}
|
|
1628
1613
|
},
|
|
1629
1614
|
overrides: {
|
|
@@ -2457,6 +2442,78 @@ var ROLE_MAPPINGS = {
|
|
|
2457
2442
|
model: "assistant"
|
|
2458
2443
|
// Some APIs use "model" instead of "assistant"
|
|
2459
2444
|
};
|
|
2445
|
+
var VALID_TOOL_ID_PATTERN = /^[a-zA-Z0-9_-]+$/;
|
|
2446
|
+
function sanitizeToolId(id) {
|
|
2447
|
+
if (!id || typeof id !== "string") return id;
|
|
2448
|
+
if (VALID_TOOL_ID_PATTERN.test(id)) return id;
|
|
2449
|
+
return id.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
2450
|
+
}
|
|
2451
|
+
function sanitizeToolIds(messages) {
|
|
2452
|
+
if (!messages || messages.length === 0) return messages;
|
|
2453
|
+
let hasChanges = false;
|
|
2454
|
+
const sanitized = messages.map((msg) => {
|
|
2455
|
+
const typedMsg = msg;
|
|
2456
|
+
let msgChanged = false;
|
|
2457
|
+
let newMsg = { ...msg };
|
|
2458
|
+
if (typedMsg.tool_calls && Array.isArray(typedMsg.tool_calls)) {
|
|
2459
|
+
const newToolCalls = typedMsg.tool_calls.map((tc) => {
|
|
2460
|
+
if (tc.id && typeof tc.id === "string") {
|
|
2461
|
+
const sanitized2 = sanitizeToolId(tc.id);
|
|
2462
|
+
if (sanitized2 !== tc.id) {
|
|
2463
|
+
msgChanged = true;
|
|
2464
|
+
return { ...tc, id: sanitized2 };
|
|
2465
|
+
}
|
|
2466
|
+
}
|
|
2467
|
+
return tc;
|
|
2468
|
+
});
|
|
2469
|
+
if (msgChanged) {
|
|
2470
|
+
newMsg = { ...newMsg, tool_calls: newToolCalls };
|
|
2471
|
+
}
|
|
2472
|
+
}
|
|
2473
|
+
if (typedMsg.tool_call_id && typeof typedMsg.tool_call_id === "string") {
|
|
2474
|
+
const sanitized2 = sanitizeToolId(typedMsg.tool_call_id);
|
|
2475
|
+
if (sanitized2 !== typedMsg.tool_call_id) {
|
|
2476
|
+
msgChanged = true;
|
|
2477
|
+
newMsg = { ...newMsg, tool_call_id: sanitized2 };
|
|
2478
|
+
}
|
|
2479
|
+
}
|
|
2480
|
+
if (Array.isArray(typedMsg.content)) {
|
|
2481
|
+
const newContent = typedMsg.content.map((block) => {
|
|
2482
|
+
if (!block || typeof block !== "object") return block;
|
|
2483
|
+
let blockChanged = false;
|
|
2484
|
+
let newBlock = { ...block };
|
|
2485
|
+
if (block.type === "tool_use" && block.id && typeof block.id === "string") {
|
|
2486
|
+
const sanitized2 = sanitizeToolId(block.id);
|
|
2487
|
+
if (sanitized2 !== block.id) {
|
|
2488
|
+
blockChanged = true;
|
|
2489
|
+
newBlock = { ...newBlock, id: sanitized2 };
|
|
2490
|
+
}
|
|
2491
|
+
}
|
|
2492
|
+
if (block.type === "tool_result" && block.tool_use_id && typeof block.tool_use_id === "string") {
|
|
2493
|
+
const sanitized2 = sanitizeToolId(block.tool_use_id);
|
|
2494
|
+
if (sanitized2 !== block.tool_use_id) {
|
|
2495
|
+
blockChanged = true;
|
|
2496
|
+
newBlock = { ...newBlock, tool_use_id: sanitized2 };
|
|
2497
|
+
}
|
|
2498
|
+
}
|
|
2499
|
+
if (blockChanged) {
|
|
2500
|
+
msgChanged = true;
|
|
2501
|
+
return newBlock;
|
|
2502
|
+
}
|
|
2503
|
+
return block;
|
|
2504
|
+
});
|
|
2505
|
+
if (msgChanged) {
|
|
2506
|
+
newMsg = { ...newMsg, content: newContent };
|
|
2507
|
+
}
|
|
2508
|
+
}
|
|
2509
|
+
if (msgChanged) {
|
|
2510
|
+
hasChanges = true;
|
|
2511
|
+
return newMsg;
|
|
2512
|
+
}
|
|
2513
|
+
return msg;
|
|
2514
|
+
});
|
|
2515
|
+
return hasChanges ? sanitized : messages;
|
|
2516
|
+
}
|
|
2460
2517
|
function normalizeMessageRoles(messages) {
|
|
2461
2518
|
if (!messages || messages.length === 0) return messages;
|
|
2462
2519
|
let hasChanges = false;
|
|
@@ -2774,6 +2831,9 @@ async function tryModelRequest(upstreamUrl, method, headers, body, modelId, maxT
|
|
|
2774
2831
|
if (Array.isArray(parsed.messages)) {
|
|
2775
2832
|
parsed.messages = normalizeMessageRoles(parsed.messages);
|
|
2776
2833
|
}
|
|
2834
|
+
if (Array.isArray(parsed.messages)) {
|
|
2835
|
+
parsed.messages = sanitizeToolIds(parsed.messages);
|
|
2836
|
+
}
|
|
2777
2837
|
if (isGoogleModel(modelId) && Array.isArray(parsed.messages)) {
|
|
2778
2838
|
parsed.messages = normalizeMessagesForGoogle(parsed.messages);
|
|
2779
2839
|
}
|
|
@@ -2883,17 +2943,10 @@ async function proxyRequest(req, res, apiBase, payFetch, options, routerOpts, de
|
|
|
2883
2943
|
const systemPrompt = typeof systemMsg?.content === "string" ? systemMsg.content : void 0;
|
|
2884
2944
|
const tools = parsed.tools;
|
|
2885
2945
|
const hasTools = Array.isArray(tools) && tools.length > 0;
|
|
2886
|
-
const effectiveRouterOpts = hasTools ? {
|
|
2887
|
-
...routerOpts,
|
|
2888
|
-
config: {
|
|
2889
|
-
...routerOpts.config,
|
|
2890
|
-
overrides: { ...routerOpts.config.overrides, agenticMode: true }
|
|
2891
|
-
}
|
|
2892
|
-
} : routerOpts;
|
|
2893
2946
|
if (hasTools) {
|
|
2894
|
-
console.log(`[ClawRouter] Tools detected (${tools.length}),
|
|
2947
|
+
console.log(`[ClawRouter] Tools detected (${tools.length}), agentic mode via keywords`);
|
|
2895
2948
|
}
|
|
2896
|
-
routingDecision = route(prompt, systemPrompt, maxTokens,
|
|
2949
|
+
routingDecision = route(prompt, systemPrompt, maxTokens, routerOpts);
|
|
2897
2950
|
parsed.model = routingDecision.model;
|
|
2898
2951
|
modelId = routingDecision.model;
|
|
2899
2952
|
bodyModified = true;
|