claudish 7.26.0 → 7.27.0

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 +119 -19
  2. package/package.json +5 -5
package/dist/index.js CHANGED
@@ -651,7 +651,7 @@ var init_onepassword_config = __esm(() => {
651
651
  });
652
652
 
653
653
  // src/version.ts
654
- var VERSION = "7.26.0";
654
+ var VERSION = "7.27.0";
655
655
 
656
656
  // src/logger.ts
657
657
  var exports_logger = {};
@@ -35364,7 +35364,21 @@ function createStreamingState() {
35364
35364
  accumulatedText: ""
35365
35365
  };
35366
35366
  }
35367
- function createStreamingResponseHandler(c, response, adapter, target, middlewareManager, onTokenUpdate, toolSchemas, toolNameMap, priorInputTokens) {
35367
+ function createStreamingResponseHandler(c, response, adapter, target, middlewareManager, onTokenUpdate, toolSchemas, toolNameMap, priorInputTokens, behavior) {
35368
+ const repairArgs = (toolName, argsJson) => {
35369
+ if (!behavior?.onToolCall)
35370
+ return argsJson;
35371
+ try {
35372
+ const repaired = behavior.onToolCall(toolName, argsJson);
35373
+ if (typeof repaired === "string" && repaired !== argsJson) {
35374
+ log(`[Streaming] tool call repaired by behavior layer: ${toolName}`);
35375
+ return repaired;
35376
+ }
35377
+ } catch (err) {
35378
+ log(`[Streaming] behavior onToolCall threw for ${toolName}: ${err}`);
35379
+ }
35380
+ return argsJson;
35381
+ };
35368
35382
  log(`[Streaming] ===== HANDLER STARTED for ${target} =====`);
35369
35383
  let isClosed = false;
35370
35384
  let ping = null;
@@ -35429,7 +35443,10 @@ data: ${JSON.stringify(d)}
35429
35443
  send("content_block_delta", {
35430
35444
  type: "content_block_delta",
35431
35445
  index: toolIdx,
35432
- delta: { type: "input_json_delta", partial_json: JSON.stringify(tc.arguments) }
35446
+ delta: {
35447
+ type: "input_json_delta",
35448
+ partial_json: repairArgs(tc.name, JSON.stringify(tc.arguments))
35449
+ }
35433
35450
  });
35434
35451
  send("content_block_stop", { type: "content_block_stop", index: toolIdx });
35435
35452
  }
@@ -35445,7 +35462,7 @@ data: ${JSON.stringify(d)}
35445
35462
  if (toolSchemas && toolSchemas.length > 0) {
35446
35463
  const validation = validateToolArguments(t.name, t.arguments, toolSchemas, state.accumulatedText);
35447
35464
  if (validation.valid || validation.repaired && validation.repairedArgs) {
35448
- const argsJson = JSON.stringify(validation.repaired ? validation.repairedArgs : validation.parsedArgs);
35465
+ const argsJson = repairArgs(t.name, JSON.stringify(validation.repaired ? validation.repairedArgs : validation.parsedArgs));
35449
35466
  log(`[Streaming] Sending buffered tool call (finish_reason!=tool_calls): ${t.name} with args: ${argsJson}`);
35450
35467
  send("content_block_start", {
35451
35468
  type: "content_block_start",
@@ -35468,7 +35485,7 @@ data: ${JSON.stringify(d)}
35468
35485
  t.closed = true;
35469
35486
  }
35470
35487
  } else {
35471
- const argsJson = t.arguments || "{}";
35488
+ const argsJson = repairArgs(t.name, t.arguments || "{}");
35472
35489
  log(`[Streaming] Sending buffered tool call (no validation): ${t.name} with args: ${argsJson}`);
35473
35490
  send("content_block_start", {
35474
35491
  type: "content_block_start",
@@ -35665,7 +35682,7 @@ data: ${JSON.stringify(d)}
35665
35682
  started: false,
35666
35683
  closed: false,
35667
35684
  arguments: "",
35668
- buffered: !!toolSchemas && toolSchemas.length > 0
35685
+ buffered: !!toolSchemas && toolSchemas.length > 0 || behavior?.shouldBufferTool?.(restoredName) === true
35669
35686
  };
35670
35687
  state.tools.set(idx, t);
35671
35688
  if (isWebSearchToolCall(restoredName)) {
@@ -35704,7 +35721,7 @@ data: ${JSON.stringify(d)}
35704
35721
  const validation = validateToolArguments(t.name, t.arguments, toolSchemas, state.accumulatedText);
35705
35722
  if (validation.repaired && validation.repairedArgs) {
35706
35723
  log(`[Streaming] Tool call ${t.name} was repaired with inferred parameters`);
35707
- const repairedJson = JSON.stringify(validation.repairedArgs);
35724
+ const repairedJson = repairArgs(t.name, JSON.stringify(validation.repairedArgs));
35708
35725
  log(`[Streaming] Sending repaired tool call: ${t.name} with args: ${repairedJson}`);
35709
35726
  if (t.buffered && !t.started) {
35710
35727
  send("content_block_start", {
@@ -35780,7 +35797,7 @@ data: ${JSON.stringify(d)}
35780
35797
  continue;
35781
35798
  }
35782
35799
  if (t.buffered && !t.started) {
35783
- const argsJson = JSON.stringify(validation.parsedArgs);
35800
+ const argsJson = repairArgs(t.name, JSON.stringify(validation.parsedArgs));
35784
35801
  send("content_block_start", {
35785
35802
  type: "content_block_start",
35786
35803
  index: t.blockIndex,
@@ -39448,6 +39465,70 @@ var init_stream_head_sniffer = __esm(() => {
39448
39465
  });
39449
39466
 
39450
39467
  // src/handlers/shared/stream-parsers/anthropic-sse.ts
39468
+ function createToolRepairInterceptor(opts) {
39469
+ const heldTools = new Map;
39470
+ const flush = (index, stopFrame) => {
39471
+ const held = heldTools.get(index);
39472
+ if (!held)
39473
+ return stopFrame;
39474
+ heldTools.delete(index);
39475
+ let finalArgs = held.args;
39476
+ try {
39477
+ const repaired = opts.repairToolArgs?.(held.name, finalArgs);
39478
+ if (typeof repaired === "string" && repaired !== finalArgs) {
39479
+ log(`[AnthropicSSE] tool call repaired: ${held.name}`);
39480
+ finalArgs = repaired;
39481
+ }
39482
+ } catch (err) {
39483
+ log(`[AnthropicSSE] repairToolArgs threw for ${held.name}: ${err}`);
39484
+ }
39485
+ const deltaFrame = `event: content_block_delta
39486
+ data: ${JSON.stringify({
39487
+ type: "content_block_delta",
39488
+ index,
39489
+ delta: { type: "input_json_delta", partial_json: finalArgs }
39490
+ })}
39491
+
39492
+ `;
39493
+ return `${deltaFrame}${stopFrame}`;
39494
+ };
39495
+ const noteToolStart = (data) => {
39496
+ if (data.content_block?.type !== "tool_use")
39497
+ return;
39498
+ const name = data.content_block.name;
39499
+ if (typeof name !== "string")
39500
+ return;
39501
+ if (!opts.shouldBufferTool?.(name))
39502
+ return;
39503
+ heldTools.set(data.index, { name, args: "" });
39504
+ };
39505
+ const absorbFragment = (data) => {
39506
+ if (data.delta?.type !== "input_json_delta")
39507
+ return false;
39508
+ const held = heldTools.get(data.index);
39509
+ if (!held)
39510
+ return false;
39511
+ held.args += data.delta.partial_json ?? "";
39512
+ return true;
39513
+ };
39514
+ return (data, line) => {
39515
+ const asIs = `${line}
39516
+ `;
39517
+ if (!opts.repairToolArgs || !opts.shouldBufferTool)
39518
+ return asIs;
39519
+ switch (data?.type) {
39520
+ case "content_block_start":
39521
+ noteToolStart(data);
39522
+ return asIs;
39523
+ case "content_block_delta":
39524
+ return absorbFragment(data) ? null : asIs;
39525
+ case "content_block_stop":
39526
+ return heldTools.has(data.index) ? flush(data.index, asIs) : asIs;
39527
+ default:
39528
+ return asIs;
39529
+ }
39530
+ };
39531
+ }
39451
39532
  function createAnthropicPassthroughStream(c, response, opts) {
39452
39533
  const encoder = new TextEncoder;
39453
39534
  const decoder = new TextDecoder;
@@ -39455,6 +39536,14 @@ function createAnthropicPassthroughStream(c, response, opts) {
39455
39536
  let lastActivity = Date.now();
39456
39537
  let pingInterval = null;
39457
39538
  const filterThinking = opts.adapter?.shouldFilterThinking() ?? false;
39539
+ const interceptToolFrame = createToolRepairInterceptor(opts);
39540
+ const enqueueData = (controller, data, line) => {
39541
+ if (isClosed)
39542
+ return;
39543
+ const out = interceptToolFrame(data, line);
39544
+ if (out !== null)
39545
+ controller.enqueue(encoder.encode(out));
39546
+ };
39458
39547
  return c.body(new ReadableStream({
39459
39548
  async start(controller) {
39460
39549
  const sendPing = () => {
@@ -39537,10 +39626,7 @@ data: ${JSON.stringify({
39537
39626
  `));
39538
39627
  }
39539
39628
  } else {
39540
- if (!isClosed) {
39541
- controller.enqueue(encoder.encode(`${line}
39542
- `));
39543
- }
39629
+ enqueueData(controller, data, line);
39544
39630
  }
39545
39631
  } catch {
39546
39632
  if (!isClosed) {
@@ -39572,10 +39658,7 @@ data: ${JSON.stringify({
39572
39658
  }
39573
39659
  return;
39574
39660
  }
39575
- if (!isClosed) {
39576
- controller.enqueue(encoder.encode(`${line}
39577
- `));
39578
- }
39661
+ enqueueData(controller, data, line);
39579
39662
  if (data.message?.usage) {
39580
39663
  inputTokens = data.message.usage.input_tokens || inputTokens;
39581
39664
  outputTokens = data.message.usage.output_tokens || outputTokens;
@@ -39870,7 +39953,18 @@ data: ${JSON.stringify(data)}
39870
39953
  const toolIdx = toolCalls.size;
39871
39954
  const toolId = `toolu_${Date.now()}_${toolIdx}`;
39872
39955
  const blockIndex = curIdx++;
39873
- const args = JSON.stringify(part.functionCall.args || {});
39956
+ let args = JSON.stringify(part.functionCall.args || {});
39957
+ if (opts.repairToolArgs) {
39958
+ try {
39959
+ const repaired = opts.repairToolArgs(part.functionCall.name, args);
39960
+ if (typeof repaired === "string" && repaired !== args) {
39961
+ log(`[GeminiSSE] tool call repaired: ${part.functionCall.name}`);
39962
+ args = repaired;
39963
+ }
39964
+ } catch (err) {
39965
+ log(`[GeminiSSE] repairToolArgs threw for ${part.functionCall.name}: ${err}`);
39966
+ }
39967
+ }
39874
39968
  const t = {
39875
39969
  id: toolId,
39876
39970
  name: part.functionCall.name,
@@ -41203,7 +41297,10 @@ class ComposedHandler {
41203
41297
  const priorInputTokens = this.tokenTracker.getLastInputTokens();
41204
41298
  switch (streamFormat) {
41205
41299
  case "openai-sse":
41206
- return createStreamingResponseHandler(c, response, adapter, this.bareModelName, this.middlewareManager, onTokenUpdate, claudeRequest.tools, toolNameMap, priorInputTokens);
41300
+ return createStreamingResponseHandler(c, response, adapter, this.bareModelName, this.middlewareManager, onTokenUpdate, claudeRequest.tools, toolNameMap, priorInputTokens, behaviorSession && {
41301
+ shouldBufferTool: (name) => behaviorSession.interceptsTool(name),
41302
+ onToolCall: (name, argsJson) => behaviorSession.repairToolCall(name, argsJson)
41303
+ });
41207
41304
  case "openai-responses-sse":
41208
41305
  return createResponsesStreamHandler(c, response, {
41209
41306
  modelName: this.bareModelName,
@@ -41220,7 +41317,9 @@ class ComposedHandler {
41220
41317
  return createAnthropicPassthroughStream(c, response, {
41221
41318
  modelName: this.bareModelName,
41222
41319
  onTokenUpdate,
41223
- adapter
41320
+ adapter,
41321
+ shouldBufferTool: (name) => behaviorSession?.interceptsTool(name) ?? false,
41322
+ repairToolArgs: (name, argsJson) => behaviorSession?.repairToolCall(name, argsJson) ?? null
41224
41323
  });
41225
41324
  case "gemini-sse": {
41226
41325
  const onToolCall = (toolId, name, thoughtSignature) => {
@@ -41234,6 +41333,7 @@ class ComposedHandler {
41234
41333
  middlewareManager: this.middlewareManager,
41235
41334
  onTokenUpdate,
41236
41335
  onToolCall,
41336
+ repairToolArgs: (name, argsJson) => behaviorSession?.repairToolCall(name, argsJson) ?? null,
41237
41337
  unwrapResponse: this.options.unwrapGeminiResponse,
41238
41338
  priorInputTokens
41239
41339
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claudish",
3
- "version": "7.26.0",
3
+ "version": "7.27.0",
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",
@@ -60,10 +60,10 @@
60
60
  "ai"
61
61
  ],
62
62
  "optionalDependencies": {
63
- "@claudish/magmux-darwin-arm64": "7.26.0",
64
- "@claudish/magmux-darwin-x64": "7.26.0",
65
- "@claudish/magmux-linux-arm64": "7.26.0",
66
- "@claudish/magmux-linux-x64": "7.26.0"
63
+ "@claudish/magmux-darwin-arm64": "7.27.0",
64
+ "@claudish/magmux-darwin-x64": "7.27.0",
65
+ "@claudish/magmux-linux-arm64": "7.27.0",
66
+ "@claudish/magmux-linux-x64": "7.27.0"
67
67
  },
68
68
  "author": "Jack Rudenko <i@madappgang.com>",
69
69
  "license": "MIT",