@blockrun/clawrouter 0.8.14 → 0.8.16

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
@@ -440,6 +440,11 @@ function getModelContextWindow(modelId) {
440
440
  const model = BLOCKRUN_MODELS.find((m) => m.id === normalized);
441
441
  return model?.contextWindow;
442
442
  }
443
+ function isReasoningModel(modelId) {
444
+ const normalized = modelId.replace("blockrun/", "");
445
+ const model = BLOCKRUN_MODELS.find((m) => m.id === normalized);
446
+ return model?.reasoning ?? false;
447
+ }
443
448
 
444
449
  // src/provider.ts
445
450
  var activeProxy = null;
@@ -1615,7 +1620,11 @@ var DEFAULT_ROUTING_CONFIG = {
1615
1620
  SIMPLE: {
1616
1621
  primary: "moonshot/kimi-k2.5",
1617
1622
  // Cheaper than Haiku ($0.5/$2.4 vs $1/$5), larger context
1618
- fallback: ["anthropic/claude-haiku-4.5", "xai/grok-4-fast-non-reasoning", "openai/gpt-4o-mini"]
1623
+ fallback: [
1624
+ "anthropic/claude-haiku-4.5",
1625
+ "xai/grok-4-fast-non-reasoning",
1626
+ "openai/gpt-4o-mini"
1627
+ ]
1619
1628
  },
1620
1629
  MEDIUM: {
1621
1630
  primary: "xai/grok-code-fast-1",
@@ -2632,7 +2641,12 @@ function normalizeMessagesForThinking(messages) {
2632
2641
  if (!messages || messages.length === 0) return messages;
2633
2642
  let hasChanges = false;
2634
2643
  const normalized = messages.map((msg) => {
2635
- if (msg.role === "assistant" && msg.tool_calls && Array.isArray(msg.tool_calls) && msg.tool_calls.length > 0 && msg.reasoning_content === void 0) {
2644
+ if (msg.role !== "assistant" || msg.reasoning_content !== void 0) {
2645
+ return msg;
2646
+ }
2647
+ const hasOpenAIToolCalls = msg.tool_calls && Array.isArray(msg.tool_calls) && msg.tool_calls.length > 0;
2648
+ const hasAnthropicToolUse = Array.isArray(msg.content) && msg.content.some((block) => block?.type === "tool_use");
2649
+ if (hasOpenAIToolCalls || hasAnthropicToolUse) {
2636
2650
  hasChanges = true;
2637
2651
  return { ...msg, reasoning_content: "" };
2638
2652
  }
@@ -2954,7 +2968,8 @@ async function tryModelRequest(upstreamUrl, method, headers, body, modelId, maxT
2954
2968
  if (isGoogleModel(modelId) && Array.isArray(parsed.messages)) {
2955
2969
  parsed.messages = normalizeMessagesForGoogle(parsed.messages);
2956
2970
  }
2957
- if (parsed.thinking && Array.isArray(parsed.messages)) {
2971
+ const hasThinkingEnabled = !!(parsed.thinking || parsed.extended_thinking || isReasoningModel(modelId));
2972
+ if (hasThinkingEnabled && Array.isArray(parsed.messages)) {
2958
2973
  parsed.messages = normalizeMessagesForThinking(parsed.messages);
2959
2974
  }
2960
2975
  requestBody = Buffer.from(JSON.stringify(parsed));
@@ -3196,7 +3211,11 @@ async function proxyRequest(req, res, apiBase, payFetch, options, routerOpts, de
3196
3211
  modelsToTry = contextFiltered.slice(0, MAX_FALLBACK_ATTEMPTS);
3197
3212
  modelsToTry = prioritizeNonRateLimited(modelsToTry);
3198
3213
  } else {
3199
- modelsToTry = modelId ? [modelId] : [];
3214
+ if (modelId && modelId !== FREE_MODEL) {
3215
+ modelsToTry = [modelId, FREE_MODEL];
3216
+ } else {
3217
+ modelsToTry = modelId ? [modelId] : [];
3218
+ }
3200
3219
  }
3201
3220
  let upstream;
3202
3221
  let lastError;
@@ -3275,7 +3294,9 @@ async function proxyRequest(req, res, apiBase, payFetch, options, routerOpts, de
3275
3294
  const parsed = JSON.parse(transformedErr);
3276
3295
  errPayload = JSON.stringify(parsed);
3277
3296
  } catch {
3278
- errPayload = JSON.stringify({ error: { message: rawErrBody, type: "provider_error", status: errStatus } });
3297
+ errPayload = JSON.stringify({
3298
+ error: { message: rawErrBody, type: "provider_error", status: errStatus }
3299
+ });
3279
3300
  }
3280
3301
  const errEvent = `data: ${errPayload}
3281
3302
 
@@ -3379,7 +3400,7 @@ async function proxyRequest(req, res, apiBase, payFetch, options, routerOpts, de
3379
3400
  index,
3380
3401
  delta: {},
3381
3402
  logprobs: null,
3382
- finish_reason: choice.finish_reason ?? "stop"
3403
+ finish_reason: toolCalls && toolCalls.length > 0 ? "tool_calls" : choice.finish_reason ?? "stop"
3383
3404
  }
3384
3405
  ]
3385
3406
  };
@@ -3608,7 +3629,9 @@ function injectModelsConfig(logger) {
3608
3629
  mkdirSync(configDir, { recursive: true });
3609
3630
  logger.info("Created OpenClaw config directory");
3610
3631
  } catch (err) {
3611
- logger.info(`Failed to create config dir: ${err instanceof Error ? err.message : String(err)}`);
3632
+ logger.info(
3633
+ `Failed to create config dir: ${err instanceof Error ? err.message : String(err)}`
3634
+ );
3612
3635
  return;
3613
3636
  }
3614
3637
  }
@@ -3622,7 +3645,9 @@ function injectModelsConfig(logger) {
3622
3645
  needsWrite = true;
3623
3646
  }
3624
3647
  } catch (err) {
3625
- logger.info(`Failed to parse config (will recreate): ${err instanceof Error ? err.message : String(err)}`);
3648
+ logger.info(
3649
+ `Failed to parse config (will recreate): ${err instanceof Error ? err.message : String(err)}`
3650
+ );
3626
3651
  config = {};
3627
3652
  needsWrite = true;
3628
3653
  }