@blockrun/clawrouter 0.10.18 → 0.10.19

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,76 @@ 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;
5287
- if (existingSession) {
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) {
5288
5290
  console.log(
5289
- `[ClawRouter] Session ${sessionId2?.slice(0, 8)}... using pinned model: ${existingSession.model}`
5291
+ `[ClawRouter] Tools detected (${tools.length}), agentic mode via keywords`
5290
5292
  );
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
- }
5293
+ }
5294
+ routingDecision = route(prompt, systemPrompt, maxTokens, {
5295
+ ...routerOpts,
5296
+ routingProfile: routingProfile ?? void 0
5297
+ });
5298
+ if (existingSession) {
5299
+ const tierRank = {
5300
+ SIMPLE: 0,
5301
+ MEDIUM: 1,
5302
+ COMPLEX: 2,
5303
+ REASONING: 3
5304
+ };
5305
+ const existingRank = tierRank[existingSession.tier] ?? 0;
5306
+ const newRank = tierRank[routingDecision.tier] ?? 0;
5307
+ if (newRank > existingRank) {
5308
+ console.log(
5309
+ `[ClawRouter] Session ${effectiveSessionId?.slice(0, 8)}... upgrading: ${existingSession.tier} \u2192 ${routingDecision.tier} (${routingDecision.model})`
5310
+ );
5311
+ parsed.model = routingDecision.model;
5312
+ modelId = routingDecision.model;
5313
+ bodyModified = true;
5314
+ if (effectiveSessionId) {
5315
+ sessionStore.setSession(
5316
+ effectiveSessionId,
5317
+ routingDecision.model,
5318
+ routingDecision.tier
5319
+ );
5304
5320
  }
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) {
5321
+ } else {
5312
5322
  console.log(
5313
- `[ClawRouter] Tools detected (${tools.length}), agentic mode via keywords`
5323
+ `[ClawRouter] Session ${effectiveSessionId?.slice(0, 8)}... keeping pinned model: ${existingSession.model} (${existingSession.tier} >= ${routingDecision.tier})`
5314
5324
  );
5325
+ parsed.model = existingSession.model;
5326
+ modelId = existingSession.model;
5327
+ bodyModified = true;
5328
+ sessionStore.touchSession(effectiveSessionId);
5329
+ routingDecision = {
5330
+ ...routingDecision,
5331
+ model: existingSession.model,
5332
+ tier: existingSession.tier
5333
+ };
5315
5334
  }
5316
- routingDecision = route(prompt, systemPrompt, maxTokens, {
5317
- ...routerOpts,
5318
- routingProfile: routingProfile ?? void 0
5319
- });
5335
+ } else {
5320
5336
  parsed.model = routingDecision.model;
5321
5337
  modelId = routingDecision.model;
5322
5338
  bodyModified = true;
5323
- if (sessionId2) {
5324
- sessionStore.setSession(sessionId2, routingDecision.model, routingDecision.tier);
5339
+ if (effectiveSessionId) {
5340
+ sessionStore.setSession(
5341
+ effectiveSessionId,
5342
+ routingDecision.model,
5343
+ routingDecision.tier
5344
+ );
5325
5345
  console.log(
5326
- `[ClawRouter] Session ${sessionId2.slice(0, 8)}... pinned to model: ${routingDecision.model}`
5346
+ `[ClawRouter] Session ${effectiveSessionId.slice(0, 8)}... pinned to model: ${routingDecision.model}`
5327
5347
  );
5328
5348
  }
5329
- options.onRouted?.(routingDecision);
5330
5349
  }
5350
+ options.onRouted?.(routingDecision);
5331
5351
  }
5332
5352
  }
5333
5353
  if (bodyModified) {
@@ -5613,6 +5633,12 @@ async function proxyRequest(req, res, apiBase, payFetch, options, routerOpts, de
5613
5633
  savings: newCosts.savings
5614
5634
  };
5615
5635
  options.onRouted?.(routingDecision);
5636
+ if (effectiveSessionId) {
5637
+ sessionStore.setSession(effectiveSessionId, actualModelUsed, routingDecision.tier);
5638
+ console.log(
5639
+ `[ClawRouter] Session ${effectiveSessionId.slice(0, 8)}... updated pin to fallback: ${actualModelUsed}`
5640
+ );
5641
+ }
5616
5642
  }
5617
5643
  if (!upstream) {
5618
5644
  const rawErrBody = lastError?.body || "All models in fallback chain failed";