@blockrun/clawrouter 0.9.0 → 0.9.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.js CHANGED
@@ -2438,66 +2438,66 @@ function normalizeMessagesWhitespace(messages) {
2438
2438
  // src/compression/codebook.ts
2439
2439
  var STATIC_CODEBOOK = {
2440
2440
  // High-impact: OpenClaw/Agent system prompt patterns (very common)
2441
- "$OC01": "unbrowse_",
2441
+ $OC01: "unbrowse_",
2442
2442
  // Common prefix in tool names
2443
- "$OC02": "<location>",
2444
- "$OC03": "</location>",
2445
- "$OC04": "<name>",
2446
- "$OC05": "</name>",
2447
- "$OC06": "<description>",
2448
- "$OC07": "</description>",
2449
- "$OC08": "(may need login)",
2450
- "$OC09": "API skill for OpenClaw",
2451
- "$OC10": "endpoints",
2443
+ $OC02: "<location>",
2444
+ $OC03: "</location>",
2445
+ $OC04: "<name>",
2446
+ $OC05: "</name>",
2447
+ $OC06: "<description>",
2448
+ $OC07: "</description>",
2449
+ $OC08: "(may need login)",
2450
+ $OC09: "API skill for OpenClaw",
2451
+ $OC10: "endpoints",
2452
2452
  // Skill/tool markers
2453
- "$SK01": "<available_skills>",
2454
- "$SK02": "</available_skills>",
2455
- "$SK03": "<skill>",
2456
- "$SK04": "</skill>",
2453
+ $SK01: "<available_skills>",
2454
+ $SK02: "</available_skills>",
2455
+ $SK03: "<skill>",
2456
+ $SK04: "</skill>",
2457
2457
  // Schema patterns (very common in tool definitions)
2458
- "$T01": 'type: "function"',
2459
- "$T02": '"type": "function"',
2460
- "$T03": '"type": "string"',
2461
- "$T04": '"type": "object"',
2462
- "$T05": '"type": "array"',
2463
- "$T06": '"type": "boolean"',
2464
- "$T07": '"type": "number"',
2458
+ $T01: 'type: "function"',
2459
+ $T02: '"type": "function"',
2460
+ $T03: '"type": "string"',
2461
+ $T04: '"type": "object"',
2462
+ $T05: '"type": "array"',
2463
+ $T06: '"type": "boolean"',
2464
+ $T07: '"type": "number"',
2465
2465
  // Common descriptions
2466
- "$D01": "description:",
2467
- "$D02": '"description":',
2466
+ $D01: "description:",
2467
+ $D02: '"description":',
2468
2468
  // Common instructions
2469
- "$I01": "You are a personal assistant",
2470
- "$I02": "Tool names are case-sensitive",
2471
- "$I03": "Call tools exactly as listed",
2472
- "$I04": "Use when",
2473
- "$I05": "without asking",
2469
+ $I01: "You are a personal assistant",
2470
+ $I02: "Tool names are case-sensitive",
2471
+ $I03: "Call tools exactly as listed",
2472
+ $I04: "Use when",
2473
+ $I05: "without asking",
2474
2474
  // Safety phrases
2475
- "$S01": "Do not manipulate or persuade",
2476
- "$S02": "Prioritize safety and human oversight",
2477
- "$S03": "unless explicitly requested",
2475
+ $S01: "Do not manipulate or persuade",
2476
+ $S02: "Prioritize safety and human oversight",
2477
+ $S03: "unless explicitly requested",
2478
2478
  // JSON patterns
2479
- "$J01": '"required": ["',
2480
- "$J02": '"properties": {',
2481
- "$J03": '"additionalProperties": false',
2479
+ $J01: '"required": ["',
2480
+ $J02: '"properties": {',
2481
+ $J03: '"additionalProperties": false',
2482
2482
  // Heartbeat patterns
2483
- "$H01": "HEARTBEAT_OK",
2484
- "$H02": "Read HEARTBEAT.md if it exists",
2483
+ $H01: "HEARTBEAT_OK",
2484
+ $H02: "Read HEARTBEAT.md if it exists",
2485
2485
  // Role markers
2486
- "$R01": '"role": "system"',
2487
- "$R02": '"role": "user"',
2488
- "$R03": '"role": "assistant"',
2489
- "$R04": '"role": "tool"',
2486
+ $R01: '"role": "system"',
2487
+ $R02: '"role": "user"',
2488
+ $R03: '"role": "assistant"',
2489
+ $R04: '"role": "tool"',
2490
2490
  // Common endings/phrases
2491
- "$E01": "would you like to",
2492
- "$E02": "Let me know if you",
2493
- "$E03": "internal APIs",
2494
- "$E04": "session cookies",
2491
+ $E01: "would you like to",
2492
+ $E02: "Let me know if you",
2493
+ $E03: "internal APIs",
2494
+ $E04: "session cookies",
2495
2495
  // BlockRun model aliases (common in prompts)
2496
- "$M01": "blockrun/",
2497
- "$M02": "openai/",
2498
- "$M03": "anthropic/",
2499
- "$M04": "google/",
2500
- "$M05": "xai/"
2496
+ $M01: "blockrun/",
2497
+ $M02: "openai/",
2498
+ $M03: "anthropic/",
2499
+ $M04: "google/",
2500
+ $M05: "xai/"
2501
2501
  };
2502
2502
  function getInverseCodebook() {
2503
2503
  const inverse = {};
@@ -2594,7 +2594,7 @@ function findFrequentPrefixes(paths) {
2594
2594
  prefixCounts.set(prefix, (prefixCounts.get(prefix) || 0) + 1);
2595
2595
  }
2596
2596
  }
2597
- return Array.from(prefixCounts.entries()).filter(([_, count]) => count >= 3).sort((a, b) => b[0].length - a[0].length).slice(0, 5).map(([prefix]) => prefix);
2597
+ return Array.from(prefixCounts.entries()).filter(([, count]) => count >= 3).sort((a, b) => b[0].length - a[0].length).slice(0, 5).map(([prefix]) => prefix);
2598
2598
  }
2599
2599
  function shortenPaths(messages) {
2600
2600
  const allPaths = extractPaths(messages);
@@ -2663,7 +2663,7 @@ function compactToolCalls(toolCalls) {
2663
2663
  function compactMessagesJson(messages) {
2664
2664
  let charsSaved = 0;
2665
2665
  const result = messages.map((message) => {
2666
- let newMessage = { ...message };
2666
+ const newMessage = { ...message };
2667
2667
  if (message.tool_calls && message.tool_calls.length > 0) {
2668
2668
  const originalLength = JSON.stringify(message.tool_calls).length;
2669
2669
  newMessage.tool_calls = compactToolCalls(message.tool_calls);
@@ -2849,9 +2849,7 @@ function applyDynamicCodebook(messages) {
2849
2849
  for (const [code, phrase] of Object.entries(codebook)) {
2850
2850
  phraseToCode[phrase] = code;
2851
2851
  }
2852
- const sortedPhrases = Object.keys(phraseToCode).sort(
2853
- (a, b) => b.length - a.length
2854
- );
2852
+ const sortedPhrases = Object.keys(phraseToCode).sort((a, b) => b.length - a.length);
2855
2853
  let charsSaved = 0;
2856
2854
  let substitutions = 0;
2857
2855
  const result = messages.map((msg) => {
@@ -2903,10 +2901,7 @@ function prependCodebookHeader(messages, usedCodes, pathMap) {
2903
2901
  if (!header) return messages;
2904
2902
  const userIndex = messages.findIndex((m) => m.role === "user");
2905
2903
  if (userIndex === -1) {
2906
- return [
2907
- { role: "system", content: header },
2908
- ...messages
2909
- ];
2904
+ return [{ role: "system", content: header }, ...messages];
2910
2905
  }
2911
2906
  return messages.map((msg, i) => {
2912
2907
  if (i === userIndex) {
@@ -3997,7 +3992,9 @@ async function proxyRequest(req, res, apiBase, payFetch, options, routerOpts, de
3997
3992
  const tools = parsed.tools;
3998
3993
  const hasTools = Array.isArray(tools) && tools.length > 0;
3999
3994
  if (hasTools) {
4000
- console.log(`[ClawRouter] Tools detected (${tools.length}), agentic mode via keywords`);
3995
+ console.log(
3996
+ `[ClawRouter] Tools detected (${tools.length}), agentic mode via keywords`
3997
+ );
4001
3998
  }
4002
3999
  routingDecision = route(prompt, systemPrompt, maxTokens, {
4003
4000
  ...routerOpts,
@@ -4031,7 +4028,9 @@ async function proxyRequest(req, res, apiBase, payFetch, options, routerOpts, de
4031
4028
  const requestSizeKB = Math.ceil(body.length / 1024);
4032
4029
  if (autoCompress && requestSizeKB > compressionThreshold) {
4033
4030
  try {
4034
- console.log(`[ClawRouter] Request size ${requestSizeKB}KB exceeds threshold ${compressionThreshold}KB, applying compression...`);
4031
+ console.log(
4032
+ `[ClawRouter] Request size ${requestSizeKB}KB exceeds threshold ${compressionThreshold}KB, applying compression...`
4033
+ );
4035
4034
  const parsed = JSON.parse(body.toString());
4036
4035
  if (parsed.messages && parsed.messages.length > 0 && shouldCompress(parsed.messages)) {
4037
4036
  const compressionResult = await compressContext(parsed.messages, {
@@ -4084,7 +4083,9 @@ async function proxyRequest(req, res, apiBase, payFetch, options, routerOpts, de
4084
4083
  }
4085
4084
  }
4086
4085
  } catch (err) {
4087
- console.warn(`[ClawRouter] Compression failed: ${err instanceof Error ? err.message : String(err)}`);
4086
+ console.warn(
4087
+ `[ClawRouter] Compression failed: ${err instanceof Error ? err.message : String(err)}`
4088
+ );
4088
4089
  }
4089
4090
  }
4090
4091
  const finalSizeKB = Math.ceil(body.length / 1024);
@@ -4561,7 +4562,15 @@ async function resolveOrGenerateWalletKey() {
4561
4562
  }
4562
4563
 
4563
4564
  // src/index.ts
4564
- import { readFileSync, writeFileSync, existsSync, readdirSync, mkdirSync } from "fs";
4565
+ import {
4566
+ readFileSync,
4567
+ writeFileSync,
4568
+ existsSync,
4569
+ readdirSync,
4570
+ mkdirSync,
4571
+ copyFileSync,
4572
+ renameSync
4573
+ } from "fs";
4565
4574
  import { homedir as homedir4 } from "os";
4566
4575
  import { join as join5 } from "path";
4567
4576
  import { privateKeyToAccount as privateKeyToAccount4 } from "viem/accounts";
@@ -4669,11 +4678,17 @@ function injectModelsConfig(logger) {
4669
4678
  needsWrite = true;
4670
4679
  }
4671
4680
  } catch (err) {
4681
+ const backupPath = `${configPath}.backup.${Date.now()}`;
4682
+ try {
4683
+ copyFileSync(configPath, backupPath);
4684
+ logger.info(`Config parse failed, backed up to ${backupPath}`);
4685
+ } catch {
4686
+ logger.info("Config parse failed, could not create backup");
4687
+ }
4672
4688
  logger.info(
4673
- `Failed to parse config (will recreate): ${err instanceof Error ? err.message : String(err)}`
4689
+ `Skipping config injection (corrupt file): ${err instanceof Error ? err.message : String(err)}`
4674
4690
  );
4675
- config = {};
4676
- needsWrite = true;
4691
+ return;
4677
4692
  }
4678
4693
  } else {
4679
4694
  logger.info("OpenClaw config not found, creating");
@@ -4765,12 +4780,7 @@ function injectModelsConfig(logger) {
4765
4780
  { id: "gemini", alias: "gemini" },
4766
4781
  { id: "flash", alias: "flash" }
4767
4782
  ];
4768
- const DEPRECATED_ALIASES = [
4769
- "blockrun/nvidia",
4770
- "blockrun/gpt",
4771
- "blockrun/o3",
4772
- "blockrun/grok"
4773
- ];
4783
+ const DEPRECATED_ALIASES = ["blockrun/nvidia", "blockrun/gpt", "blockrun/o3", "blockrun/grok"];
4774
4784
  if (!defaults.models) {
4775
4785
  defaults.models = {};
4776
4786
  needsWrite = true;
@@ -4792,7 +4802,9 @@ function injectModelsConfig(logger) {
4792
4802
  }
4793
4803
  if (needsWrite) {
4794
4804
  try {
4795
- writeFileSync(configPath, JSON.stringify(config, null, 2));
4805
+ const tmpPath = `${configPath}.tmp.${process.pid}`;
4806
+ writeFileSync(tmpPath, JSON.stringify(config, null, 2));
4807
+ renameSync(tmpPath, configPath);
4796
4808
  logger.info("Smart routing enabled (blockrun/auto)");
4797
4809
  } catch (err) {
4798
4810
  logger.info(`Failed to write config: ${err instanceof Error ? err.message : String(err)}`);