@blockrun/clawrouter 0.10.18 → 0.10.20

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/cli.js CHANGED
@@ -1,10 +1,4 @@
1
1
  #!/usr/bin/env node
2
- var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
3
- get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
4
- }) : x)(function(x) {
5
- if (typeof require !== "undefined") return require.apply(this, arguments);
6
- throw Error('Dynamic require of "' + x + '" is not supported');
7
- });
8
2
 
9
3
  // src/proxy.ts
10
4
  import { createServer } from "http";
@@ -3838,6 +3832,7 @@ function shouldCompress(messages) {
3838
3832
  }
3839
3833
 
3840
3834
  // src/session.ts
3835
+ import { createHash as createHash3 } from "crypto";
3841
3836
  var DEFAULT_SESSION_CONFIG = {
3842
3837
  enabled: true,
3843
3838
  timeoutMs: 30 * 60 * 1e3,
@@ -3970,7 +3965,6 @@ function deriveSessionId(messages) {
3970
3965
  const firstUser = messages.find((m) => m.role === "user");
3971
3966
  if (!firstUser) return void 0;
3972
3967
  const content = typeof firstUser.content === "string" ? firstUser.content : JSON.stringify(firstUser.content);
3973
- const { createHash: createHash3 } = __require("crypto");
3974
3968
  return createHash3("sha256").update(content).digest("hex").slice(0, 8);
3975
3969
  }
3976
3970
 
@@ -5110,6 +5104,7 @@ async function proxyRequest(req, res, apiBase, payFetch, options, routerOpts, de
5110
5104
  let accumulatedContent = "";
5111
5105
  const isChatCompletion = req.url?.includes("/chat/completions");
5112
5106
  const sessionId = getSessionId(req.headers);
5107
+ let effectiveSessionId = sessionId;
5113
5108
  if (isChatCompletion && body.length > 0) {
5114
5109
  try {
5115
5110
  const parsed = JSON.parse(body.toString());
@@ -5119,7 +5114,8 @@ async function proxyRequest(req, res, apiBase, payFetch, options, routerOpts, de
5119
5114
  let bodyModified = false;
5120
5115
  const parsedMessages = Array.isArray(parsed.messages) ? parsed.messages : [];
5121
5116
  const lastUserMsg = [...parsedMessages].reverse().find((m) => m.role === "user");
5122
- const lastContent = typeof lastUserMsg?.content === "string" ? lastUserMsg.content : "";
5117
+ const rawLastContent = lastUserMsg?.content;
5118
+ const lastContent = typeof rawLastContent === "string" ? rawLastContent : Array.isArray(rawLastContent) ? rawLastContent.filter((b) => b.type === "text").map((b) => b.text ?? "").join(" ") : "";
5123
5119
  if (sessionId && parsedMessages.length > 0) {
5124
5120
  const messages = parsedMessages;
5125
5121
  if (sessionJournal.needsContext(lastContent)) {
@@ -5282,52 +5278,74 @@ async function proxyRequest(req, res, apiBase, payFetch, options, routerOpts, de
5282
5278
  latencyMs: 0
5283
5279
  });
5284
5280
  } else {
5285
- const sessionId2 = getSessionId(req.headers) ?? deriveSessionId(parsedMessages);
5286
- const existingSession = sessionId2 ? sessionStore.getSession(sessionId2) : void 0;
5281
+ effectiveSessionId = getSessionId(req.headers) ?? deriveSessionId(parsedMessages);
5282
+ const existingSession = effectiveSessionId ? sessionStore.getSession(effectiveSessionId) : void 0;
5283
+ const rawPrompt = lastUserMsg?.content;
5284
+ const prompt = typeof rawPrompt === "string" ? rawPrompt : Array.isArray(rawPrompt) ? rawPrompt.filter((b) => b.type === "text").map((b) => b.text ?? "").join(" ") : "";
5285
+ const systemMsg = parsedMessages.find((m) => m.role === "system");
5286
+ const systemPrompt = typeof systemMsg?.content === "string" ? systemMsg.content : void 0;
5287
+ const tools = parsed.tools;
5288
+ hasTools = Array.isArray(tools) && tools.length > 0;
5289
+ if (hasTools && tools) {
5290
+ console.log(`[ClawRouter] Tools detected (${tools.length}), agentic mode via keywords`);
5291
+ }
5292
+ routingDecision = route(prompt, systemPrompt, maxTokens, {
5293
+ ...routerOpts,
5294
+ routingProfile: routingProfile ?? void 0
5295
+ });
5287
5296
  if (existingSession) {
5288
- console.log(
5289
- `[ClawRouter] Session ${sessionId2?.slice(0, 8)}... using pinned model: ${existingSession.model}`
5290
- );
5291
- parsed.model = existingSession.model;
5292
- modelId = existingSession.model;
5293
- bodyModified = true;
5294
- sessionStore.touchSession(sessionId2);
5295
- } else {
5296
- const messages = parsed.messages;
5297
- let lastUserMsg2;
5298
- if (messages) {
5299
- for (let i = messages.length - 1; i >= 0; i--) {
5300
- if (messages[i].role === "user") {
5301
- lastUserMsg2 = messages[i];
5302
- break;
5303
- }
5297
+ const tierRank = {
5298
+ SIMPLE: 0,
5299
+ MEDIUM: 1,
5300
+ COMPLEX: 2,
5301
+ REASONING: 3
5302
+ };
5303
+ const existingRank = tierRank[existingSession.tier] ?? 0;
5304
+ const newRank = tierRank[routingDecision.tier] ?? 0;
5305
+ if (newRank > existingRank) {
5306
+ console.log(
5307
+ `[ClawRouter] Session ${effectiveSessionId?.slice(0, 8)}... upgrading: ${existingSession.tier} \u2192 ${routingDecision.tier} (${routingDecision.model})`
5308
+ );
5309
+ parsed.model = routingDecision.model;
5310
+ modelId = routingDecision.model;
5311
+ bodyModified = true;
5312
+ if (effectiveSessionId) {
5313
+ sessionStore.setSession(
5314
+ effectiveSessionId,
5315
+ routingDecision.model,
5316
+ routingDecision.tier
5317
+ );
5304
5318
  }
5305
- }
5306
- const systemMsg = messages?.find((m) => m.role === "system");
5307
- const prompt = typeof lastUserMsg2?.content === "string" ? lastUserMsg2.content : "";
5308
- const systemPrompt = typeof systemMsg?.content === "string" ? systemMsg.content : void 0;
5309
- const tools = parsed.tools;
5310
- hasTools = Array.isArray(tools) && tools.length > 0;
5311
- if (hasTools && tools) {
5319
+ } else {
5312
5320
  console.log(
5313
- `[ClawRouter] Tools detected (${tools.length}), agentic mode via keywords`
5321
+ `[ClawRouter] Session ${effectiveSessionId?.slice(0, 8)}... keeping pinned model: ${existingSession.model} (${existingSession.tier} >= ${routingDecision.tier})`
5314
5322
  );
5323
+ parsed.model = existingSession.model;
5324
+ modelId = existingSession.model;
5325
+ bodyModified = true;
5326
+ sessionStore.touchSession(effectiveSessionId);
5327
+ routingDecision = {
5328
+ ...routingDecision,
5329
+ model: existingSession.model,
5330
+ tier: existingSession.tier
5331
+ };
5315
5332
  }
5316
- routingDecision = route(prompt, systemPrompt, maxTokens, {
5317
- ...routerOpts,
5318
- routingProfile: routingProfile ?? void 0
5319
- });
5333
+ } else {
5320
5334
  parsed.model = routingDecision.model;
5321
5335
  modelId = routingDecision.model;
5322
5336
  bodyModified = true;
5323
- if (sessionId2) {
5324
- sessionStore.setSession(sessionId2, routingDecision.model, routingDecision.tier);
5337
+ if (effectiveSessionId) {
5338
+ sessionStore.setSession(
5339
+ effectiveSessionId,
5340
+ routingDecision.model,
5341
+ routingDecision.tier
5342
+ );
5325
5343
  console.log(
5326
- `[ClawRouter] Session ${sessionId2.slice(0, 8)}... pinned to model: ${routingDecision.model}`
5344
+ `[ClawRouter] Session ${effectiveSessionId.slice(0, 8)}... pinned to model: ${routingDecision.model}`
5327
5345
  );
5328
5346
  }
5329
- options.onRouted?.(routingDecision);
5330
5347
  }
5348
+ options.onRouted?.(routingDecision);
5331
5349
  }
5332
5350
  }
5333
5351
  if (bodyModified) {
@@ -5613,6 +5631,12 @@ async function proxyRequest(req, res, apiBase, payFetch, options, routerOpts, de
5613
5631
  savings: newCosts.savings
5614
5632
  };
5615
5633
  options.onRouted?.(routingDecision);
5634
+ if (effectiveSessionId) {
5635
+ sessionStore.setSession(effectiveSessionId, actualModelUsed, routingDecision.tier);
5636
+ console.log(
5637
+ `[ClawRouter] Session ${effectiveSessionId.slice(0, 8)}... updated pin to fallback: ${actualModelUsed}`
5638
+ );
5639
+ }
5616
5640
  }
5617
5641
  if (!upstream) {
5618
5642
  const rawErrBody = lastError?.body || "All models in fallback chain failed";