claudish 3.0.1 → 3.0.3

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.
Files changed (2) hide show
  1. package/dist/index.js +170 -11
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -34800,6 +34800,9 @@ async function parseArgs(args) {
34800
34800
  config3.interactive = true;
34801
34801
  } else if (arg === "--debug" || arg === "-d") {
34802
34802
  config3.debug = true;
34803
+ if (config3.logLevel === "info") {
34804
+ config3.logLevel = "debug";
34805
+ }
34803
34806
  } else if (arg === "--log-level") {
34804
34807
  const levelArg = args[++i];
34805
34808
  if (!levelArg || !["debug", "info", "minimal"].includes(levelArg)) {
@@ -38302,19 +38305,86 @@ var init_grok_adapter = __esm(() => {
38302
38305
  });
38303
38306
 
38304
38307
  // src/adapters/gemini-adapter.ts
38305
- var GeminiAdapter;
38308
+ var REASONING_PATTERNS, REASONING_CONTINUATION_PATTERNS, GeminiAdapter;
38306
38309
  var init_gemini_adapter = __esm(() => {
38307
38310
  init_base_adapter();
38308
38311
  init_logger();
38312
+ REASONING_PATTERNS = [
38313
+ /^Wait,?\s+I(?:'m|\s+am)\s+\w+ing\b/i,
38314
+ /^Wait[.!]?\s*$/i,
38315
+ /^Let\s+me\s+(think|check|verify|see|look|analyze|consider)/i,
38316
+ /^I\s+need\s+to\s+/i,
38317
+ /^O[kK](?:ay)?[.,!]?\s*(?:so|let|I|now|first)?/i,
38318
+ /^[Hh]mm+/,
38319
+ /^So[,.]?\s+(?:I|let|first|now|the)/i,
38320
+ /^(?:First|Next|Then|Now)[,.]?\s+(?:I|let|we)/i,
38321
+ /^(?:Thinking\s+about|Considering)/i,
38322
+ /^I(?:'ll|\s+will|\s+should)\s+(?:first|now|start|begin|try)/i,
38323
+ /^(?:Debug|Checking|Verifying|Looking\s+at):/i
38324
+ ];
38325
+ REASONING_CONTINUATION_PATTERNS = [
38326
+ /^And\s+(?:then|I|now|so)/i,
38327
+ /^But\s+(?:I|first|wait|actually)/i,
38328
+ /^Actually[,.]?\s+/i,
38329
+ /^\d+\.\s+(?:I|First|Check|Run|Create|Update|Read)/i
38330
+ ];
38309
38331
  GeminiAdapter = class GeminiAdapter extends BaseModelAdapter {
38310
38332
  thoughtSignatures = new Map;
38333
+ reasoningBuffer = [];
38334
+ inReasoningBlock = false;
38335
+ reasoningBlockDepth = 0;
38311
38336
  processTextContent(textContent, accumulatedText) {
38337
+ if (!textContent || textContent.trim() === "") {
38338
+ return { cleanedText: textContent, extractedToolCalls: [], wasTransformed: false };
38339
+ }
38340
+ const lines = textContent.split(`
38341
+ `);
38342
+ const cleanedLines = [];
38343
+ let wasFiltered = false;
38344
+ for (const line of lines) {
38345
+ const trimmed = line.trim();
38346
+ if (!trimmed) {
38347
+ cleanedLines.push(line);
38348
+ continue;
38349
+ }
38350
+ const isReasoning = this.isReasoningLine(trimmed);
38351
+ if (isReasoning) {
38352
+ log(`[GeminiAdapter] Filtered reasoning: "${trimmed.substring(0, 50)}..."`);
38353
+ wasFiltered = true;
38354
+ this.inReasoningBlock = true;
38355
+ this.reasoningBlockDepth++;
38356
+ continue;
38357
+ }
38358
+ if (this.inReasoningBlock && this.isReasoningContinuation(trimmed)) {
38359
+ log(`[GeminiAdapter] Filtered reasoning continuation: "${trimmed.substring(0, 50)}..."`);
38360
+ wasFiltered = true;
38361
+ continue;
38362
+ }
38363
+ if (this.inReasoningBlock && trimmed.length > 20 && !this.isReasoningContinuation(trimmed)) {
38364
+ this.inReasoningBlock = false;
38365
+ this.reasoningBlockDepth = 0;
38366
+ }
38367
+ cleanedLines.push(line);
38368
+ }
38369
+ const cleanedText = cleanedLines.join(`
38370
+ `);
38312
38371
  return {
38313
- cleanedText: textContent,
38372
+ cleanedText: wasFiltered ? cleanedText : textContent,
38314
38373
  extractedToolCalls: [],
38315
- wasTransformed: false
38374
+ wasTransformed: wasFiltered
38316
38375
  };
38317
38376
  }
38377
+ isReasoningLine(line) {
38378
+ return REASONING_PATTERNS.some((pattern) => pattern.test(line));
38379
+ }
38380
+ isReasoningContinuation(line) {
38381
+ return REASONING_CONTINUATION_PATTERNS.some((pattern) => pattern.test(line));
38382
+ }
38383
+ resetReasoningState() {
38384
+ this.reasoningBuffer = [];
38385
+ this.inReasoningBlock = false;
38386
+ this.reasoningBlockDepth = 0;
38387
+ }
38318
38388
  prepareRequest(request, originalRequest) {
38319
38389
  if (originalRequest.thinking) {
38320
38390
  const { budget_tokens } = originalRequest.thinking;
@@ -38359,6 +38429,7 @@ var init_gemini_adapter = __esm(() => {
38359
38429
  }
38360
38430
  reset() {
38361
38431
  this.thoughtSignatures.clear();
38432
+ this.resetReasoningState();
38362
38433
  }
38363
38434
  shouldHandle(modelId) {
38364
38435
  return modelId.includes("gemini") || modelId.includes("google/");
@@ -39864,11 +39935,30 @@ class OpenRouterHandler {
39864
39935
  const claudePayload = payload;
39865
39936
  const target = this.targetModel;
39866
39937
  await this.fetchContextWindow(target);
39867
- logStructured(`OpenRouter Request`, { targetModel: target, originalModel: claudePayload.model });
39868
39938
  const { claudeRequest, droppedParams } = transformOpenAIToClaude(claudePayload);
39869
39939
  const messages = this.convertMessages(claudeRequest, target);
39870
39940
  const tools = this.convertTools(claudeRequest);
39871
39941
  const supportsReasoning = await doesModelSupportReasoning(target);
39942
+ const systemPromptLength = typeof claudeRequest.system === "string" ? claudeRequest.system.length : 0;
39943
+ logStructured(`OpenRouter Request`, {
39944
+ targetModel: target,
39945
+ originalModel: claudePayload.model,
39946
+ messageCount: messages.length,
39947
+ toolCount: tools.length,
39948
+ systemPromptLength,
39949
+ maxTokens: claudeRequest.max_tokens
39950
+ });
39951
+ if (getLogLevel() === "debug") {
39952
+ const lastUserMsg = messages.filter((m) => m.role === "user").pop();
39953
+ if (lastUserMsg) {
39954
+ const content = typeof lastUserMsg.content === "string" ? lastUserMsg.content : JSON.stringify(lastUserMsg.content);
39955
+ log(`[OpenRouter] Last user message: ${truncateContent(content, 500)}`);
39956
+ }
39957
+ if (tools.length > 0) {
39958
+ const toolNames = tools.map((t) => t.function?.name || t.name).join(", ");
39959
+ log(`[OpenRouter] Tools: ${toolNames}`);
39960
+ }
39961
+ }
39872
39962
  const openRouterPayload = {
39873
39963
  model: target,
39874
39964
  messages,
@@ -39903,8 +39993,12 @@ class OpenRouterHandler {
39903
39993
  },
39904
39994
  body: JSON.stringify(openRouterPayload)
39905
39995
  });
39906
- if (!response.ok)
39907
- return c.json({ error: await response.text() }, response.status);
39996
+ log(`[OpenRouter] Response status: ${response.status}`);
39997
+ if (!response.ok) {
39998
+ const errorText = await response.text();
39999
+ log(`[OpenRouter] Error: ${errorText}`);
40000
+ return c.json({ error: errorText }, response.status);
40001
+ }
39908
40002
  if (droppedParams.length > 0)
39909
40003
  c.header("X-Dropped-Params", droppedParams.join(", "));
39910
40004
  return this.handleStreamingResponse(c, response, adapter, target, claudeRequest);
@@ -39927,6 +40021,21 @@ class OpenRouterHandler {
39927
40021
  else
39928
40022
  messages.unshift({ role: "system", content: msg });
39929
40023
  }
40024
+ if (modelId.includes("gemini") || modelId.includes("google/")) {
40025
+ const geminiMsg = `CRITICAL INSTRUCTION FOR OUTPUT FORMAT:
40026
+ 1. Keep ALL internal reasoning INTERNAL. Never output your thought process as visible text.
40027
+ 2. Do NOT start responses with phrases like "Wait, I'm...", "Let me think...", "Okay, so...", "First, I need to..."
40028
+ 3. Do NOT output numbered planning steps or internal debugging statements.
40029
+ 4. Only output: final responses, tool calls, and code. Nothing else.
40030
+ 5. When calling tools, proceed directly without announcing your intentions.
40031
+ 6. Your internal thinking should use the reasoning/thinking API, not visible text output.`;
40032
+ if (messages.length > 0 && messages[0].role === "system")
40033
+ messages[0].content += `
40034
+
40035
+ ` + geminiMsg;
40036
+ else
40037
+ messages.unshift({ role: "system", content: geminiMsg });
40038
+ }
39930
40039
  if (req.messages) {
39931
40040
  for (const msg of req.messages) {
39932
40041
  if (msg.role === "user")
@@ -40013,6 +40122,7 @@ class OpenRouterHandler {
40013
40122
  const encoder = new TextEncoder;
40014
40123
  const decoder = new TextDecoder;
40015
40124
  const middlewareManager = this.middlewareManager;
40125
+ const writeTokens = (input, output) => this.writeTokenFile(input, output);
40016
40126
  const streamMetadata = new Map;
40017
40127
  return c.body(new ReadableStream({
40018
40128
  async start(controller) {
@@ -40028,13 +40138,14 @@ data: ${JSON.stringify(d)}
40028
40138
  let finalized = false;
40029
40139
  let textStarted = false;
40030
40140
  let textIdx = -1;
40031
- let reasoningStarted = false;
40032
- let reasoningIdx = -1;
40141
+ let thinkingStarted = false;
40142
+ let thinkingIdx = -1;
40033
40143
  let curIdx = 0;
40034
40144
  const tools = new Map;
40035
40145
  const toolIds = new Set;
40036
40146
  let accTxt = 0;
40037
40147
  let lastActivity = Date.now();
40148
+ let accumulatedThinking = "";
40038
40149
  send("message_start", {
40039
40150
  type: "message_start",
40040
40151
  message: {
@@ -40057,9 +40168,9 @@ data: ${JSON.stringify(d)}
40057
40168
  if (finalized)
40058
40169
  return;
40059
40170
  finalized = true;
40060
- if (reasoningStarted) {
40061
- send("content_block_stop", { type: "content_block_stop", index: reasoningIdx });
40062
- reasoningStarted = false;
40171
+ if (thinkingStarted) {
40172
+ send("content_block_stop", { type: "content_block_stop", index: thinkingIdx });
40173
+ thinkingStarted = false;
40063
40174
  }
40064
40175
  if (textStarted) {
40065
40176
  send("content_block_stop", { type: "content_block_stop", index: textIdx });
@@ -40070,10 +40181,22 @@ data: ${JSON.stringify(d)}
40070
40181
  send("content_block_stop", { type: "content_block_stop", index: t.blockIndex });
40071
40182
  t.closed = true;
40072
40183
  }
40184
+ if (tools.size > 0) {
40185
+ const toolSummary = Array.from(tools.values()).map((t) => `${t.name}(${t.arguments.length} chars)`).join(", ");
40186
+ log(`[OpenRouter] Tool calls: ${toolSummary}`);
40187
+ }
40188
+ if (usage) {
40189
+ log(`[OpenRouter] Usage: prompt=${usage.prompt_tokens || 0}, completion=${usage.completion_tokens || 0}, total=${usage.total_tokens || 0}`);
40190
+ writeTokens(usage.prompt_tokens || 0, usage.completion_tokens || 0);
40191
+ } else {
40192
+ log(`[OpenRouter] Warning: No usage data received from model`);
40193
+ }
40073
40194
  await middlewareManager.afterStreamComplete(target, streamMetadata);
40074
40195
  if (reason === "error") {
40196
+ log(`[OpenRouter] Stream error: ${err}`);
40075
40197
  send("error", { type: "error", error: { type: "api_error", message: err } });
40076
40198
  } else {
40199
+ log(`[OpenRouter] Stream complete: ${reason}`);
40077
40200
  send("message_delta", { type: "message_delta", delta: { stop_reason: "end_turn", stop_sequence: null }, usage: { output_tokens: usage?.completion_tokens || 0 } });
40078
40201
  send("message_stop", { type: "message_stop" });
40079
40202
  }
@@ -40121,9 +40244,38 @@ data: ${JSON.stringify(d)}
40121
40244
  delta,
40122
40245
  metadata: streamMetadata
40123
40246
  });
40247
+ if (delta.reasoning_details && delta.reasoning_details.length > 0) {
40248
+ for (const detail of delta.reasoning_details) {
40249
+ if (detail.type === "reasoning.text" || detail.type === "reasoning.summary") {
40250
+ const thinkingContent = detail.content || detail.text || detail.summary || "";
40251
+ if (thinkingContent) {
40252
+ lastActivity = Date.now();
40253
+ if (!thinkingStarted) {
40254
+ thinkingIdx = curIdx++;
40255
+ send("content_block_start", {
40256
+ type: "content_block_start",
40257
+ index: thinkingIdx,
40258
+ content_block: { type: "thinking", thinking: "" }
40259
+ });
40260
+ thinkingStarted = true;
40261
+ }
40262
+ send("content_block_delta", {
40263
+ type: "content_block_delta",
40264
+ index: thinkingIdx,
40265
+ delta: { type: "thinking_delta", thinking: thinkingContent }
40266
+ });
40267
+ accumulatedThinking += thinkingContent;
40268
+ }
40269
+ }
40270
+ }
40271
+ }
40124
40272
  const txt = delta.content || "";
40125
40273
  if (txt) {
40126
40274
  lastActivity = Date.now();
40275
+ if (thinkingStarted) {
40276
+ send("content_block_stop", { type: "content_block_stop", index: thinkingIdx });
40277
+ thinkingStarted = false;
40278
+ }
40127
40279
  if (!textStarted) {
40128
40280
  textIdx = curIdx++;
40129
40281
  send("content_block_start", { type: "content_block_start", index: textIdx, content_block: { type: "text", text: "" } });
@@ -40139,6 +40291,10 @@ data: ${JSON.stringify(d)}
40139
40291
  let t = tools.get(idx);
40140
40292
  if (tc.function?.name) {
40141
40293
  if (!t) {
40294
+ if (thinkingStarted) {
40295
+ send("content_block_stop", { type: "content_block_stop", index: thinkingIdx });
40296
+ thinkingStarted = false;
40297
+ }
40142
40298
  if (textStarted) {
40143
40299
  send("content_block_stop", { type: "content_block_stop", index: textIdx });
40144
40300
  textStarted = false;
@@ -40165,6 +40321,8 @@ data: ${JSON.stringify(d)}
40165
40321
  if (toolSchemas.length > 0) {
40166
40322
  const validation = validateToolArguments(t.name, t.arguments, toolSchemas);
40167
40323
  if (!validation.valid) {
40324
+ log(`[OpenRouter] Tool validation FAILED: ${t.name} - missing: ${validation.missingParams.join(", ")}`);
40325
+ log(`[OpenRouter] Tool args received: ${truncateContent(t.arguments, 300)}`);
40168
40326
  const errorIdx = curIdx++;
40169
40327
  const errorMsg = `
40170
40328
 
@@ -40176,6 +40334,7 @@ data: ${JSON.stringify(d)}
40176
40334
  continue;
40177
40335
  }
40178
40336
  }
40337
+ log(`[OpenRouter] Tool validated: ${t.name}`);
40179
40338
  send("content_block_stop", { type: "content_block_stop", index: t.blockIndex });
40180
40339
  t.closed = true;
40181
40340
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claudish",
3
- "version": "3.0.1",
3
+ "version": "3.0.3",
4
4
  "description": "Run Claude Code with any model - OpenRouter, Ollama, LM Studio & local models",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",