@blockrun/clawrouter 0.6.7 → 0.6.8

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 CHANGED
@@ -2457,6 +2457,78 @@ var ROLE_MAPPINGS = {
2457
2457
  model: "assistant"
2458
2458
  // Some APIs use "model" instead of "assistant"
2459
2459
  };
2460
+ var VALID_TOOL_ID_PATTERN = /^[a-zA-Z0-9_-]+$/;
2461
+ function sanitizeToolId(id) {
2462
+ if (!id || typeof id !== "string") return id;
2463
+ if (VALID_TOOL_ID_PATTERN.test(id)) return id;
2464
+ return id.replace(/[^a-zA-Z0-9_-]/g, "_");
2465
+ }
2466
+ function sanitizeToolIds(messages) {
2467
+ if (!messages || messages.length === 0) return messages;
2468
+ let hasChanges = false;
2469
+ const sanitized = messages.map((msg) => {
2470
+ const typedMsg = msg;
2471
+ let msgChanged = false;
2472
+ let newMsg = { ...msg };
2473
+ if (typedMsg.tool_calls && Array.isArray(typedMsg.tool_calls)) {
2474
+ const newToolCalls = typedMsg.tool_calls.map((tc) => {
2475
+ if (tc.id && typeof tc.id === "string") {
2476
+ const sanitized2 = sanitizeToolId(tc.id);
2477
+ if (sanitized2 !== tc.id) {
2478
+ msgChanged = true;
2479
+ return { ...tc, id: sanitized2 };
2480
+ }
2481
+ }
2482
+ return tc;
2483
+ });
2484
+ if (msgChanged) {
2485
+ newMsg = { ...newMsg, tool_calls: newToolCalls };
2486
+ }
2487
+ }
2488
+ if (typedMsg.tool_call_id && typeof typedMsg.tool_call_id === "string") {
2489
+ const sanitized2 = sanitizeToolId(typedMsg.tool_call_id);
2490
+ if (sanitized2 !== typedMsg.tool_call_id) {
2491
+ msgChanged = true;
2492
+ newMsg = { ...newMsg, tool_call_id: sanitized2 };
2493
+ }
2494
+ }
2495
+ if (Array.isArray(typedMsg.content)) {
2496
+ const newContent = typedMsg.content.map((block) => {
2497
+ if (!block || typeof block !== "object") return block;
2498
+ let blockChanged = false;
2499
+ let newBlock = { ...block };
2500
+ if (block.type === "tool_use" && block.id && typeof block.id === "string") {
2501
+ const sanitized2 = sanitizeToolId(block.id);
2502
+ if (sanitized2 !== block.id) {
2503
+ blockChanged = true;
2504
+ newBlock = { ...newBlock, id: sanitized2 };
2505
+ }
2506
+ }
2507
+ if (block.type === "tool_result" && block.tool_use_id && typeof block.tool_use_id === "string") {
2508
+ const sanitized2 = sanitizeToolId(block.tool_use_id);
2509
+ if (sanitized2 !== block.tool_use_id) {
2510
+ blockChanged = true;
2511
+ newBlock = { ...newBlock, tool_use_id: sanitized2 };
2512
+ }
2513
+ }
2514
+ if (blockChanged) {
2515
+ msgChanged = true;
2516
+ return newBlock;
2517
+ }
2518
+ return block;
2519
+ });
2520
+ if (msgChanged) {
2521
+ newMsg = { ...newMsg, content: newContent };
2522
+ }
2523
+ }
2524
+ if (msgChanged) {
2525
+ hasChanges = true;
2526
+ return newMsg;
2527
+ }
2528
+ return msg;
2529
+ });
2530
+ return hasChanges ? sanitized : messages;
2531
+ }
2460
2532
  function normalizeMessageRoles(messages) {
2461
2533
  if (!messages || messages.length === 0) return messages;
2462
2534
  let hasChanges = false;
@@ -2774,6 +2846,9 @@ async function tryModelRequest(upstreamUrl, method, headers, body, modelId, maxT
2774
2846
  if (Array.isArray(parsed.messages)) {
2775
2847
  parsed.messages = normalizeMessageRoles(parsed.messages);
2776
2848
  }
2849
+ if (Array.isArray(parsed.messages)) {
2850
+ parsed.messages = sanitizeToolIds(parsed.messages);
2851
+ }
2777
2852
  if (isGoogleModel(modelId) && Array.isArray(parsed.messages)) {
2778
2853
  parsed.messages = normalizeMessagesForGoogle(parsed.messages);
2779
2854
  }