claudish 6.10.1 → 6.11.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 +101 -11
  2. package/package.json +5 -5
package/dist/index.js CHANGED
@@ -16928,6 +16928,45 @@ var init_logger = __esm(() => {
16928
16928
  ]);
16929
16929
  });
16930
16930
 
16931
+ // src/handlers/shared/anthropic-error.ts
16932
+ function statusToErrorType(status) {
16933
+ switch (status) {
16934
+ case 400:
16935
+ return "invalid_request_error";
16936
+ case 401:
16937
+ return "authentication_error";
16938
+ case 403:
16939
+ return "permission_error";
16940
+ case 404:
16941
+ return "not_found_error";
16942
+ case 429:
16943
+ return "rate_limit_error";
16944
+ case 503:
16945
+ case 529:
16946
+ return "overloaded_error";
16947
+ default:
16948
+ return "api_error";
16949
+ }
16950
+ }
16951
+ function wrapAnthropicError(status, message, errorType) {
16952
+ const type = errorType || statusToErrorType(status);
16953
+ return {
16954
+ type: "error",
16955
+ error: { type, message }
16956
+ };
16957
+ }
16958
+ function ensureAnthropicErrorFormat(status, body) {
16959
+ if (body?.type === "error" && typeof body?.error?.type === "string" && typeof body?.error?.message === "string") {
16960
+ return body;
16961
+ }
16962
+ if (typeof body?.error?.type === "string" && typeof body?.error?.message === "string") {
16963
+ return { type: "error", error: body.error };
16964
+ }
16965
+ const message = body?.error?.message || body?.message || body?.error || (typeof body === "string" ? body : JSON.stringify(body));
16966
+ const errorType = body?.error?.type || body?.type || body?.code;
16967
+ return wrapAnthropicError(status, String(message), errorType);
16968
+ }
16969
+
16931
16970
  // src/handlers/native-handler.ts
16932
16971
  class NativeHandler {
16933
16972
  apiKey;
@@ -17019,7 +17058,7 @@ class NativeHandler {
17019
17058
  return c.json(data, { status: anthropicResponse.status, headers: responseHeaders });
17020
17059
  } catch (error2) {
17021
17060
  log(`[Native] Fetch Error: ${error2}`);
17022
- return c.json({ error: { type: "api_error", message: String(error2) } }, 500);
17061
+ return c.json(wrapAnthropicError(500, String(error2)), 500);
17023
17062
  }
17024
17063
  }
17025
17064
  async shutdown() {}
@@ -18583,6 +18622,24 @@ var init_tool_call_recovery = __esm(() => {
18583
18622
  init_logger();
18584
18623
  });
18585
18624
 
18625
+ // src/handlers/shared/web-search-detector.ts
18626
+ function isWebSearchToolCall(toolName) {
18627
+ return WEB_SEARCH_NAMES.has(toolName);
18628
+ }
18629
+ function warnWebSearchUnsupported(toolName, modelName) {
18630
+ log(`[WebSearch] Tool call '${toolName}' detected from model '${modelName}' \u2014 not yet supported`);
18631
+ logStderr(`Warning: Model requested web search ('${toolName}') but server-side web search is not yet implemented. ` + `The tool call will pass through to the client as-is.`);
18632
+ }
18633
+ var WEB_SEARCH_NAMES;
18634
+ var init_web_search_detector = __esm(() => {
18635
+ init_logger();
18636
+ WEB_SEARCH_NAMES = new Set([
18637
+ "web_search",
18638
+ "brave_web_search",
18639
+ "tavily_search"
18640
+ ]);
18641
+ });
18642
+
18586
18643
  // src/handlers/shared/stream-parsers/openai-sse.ts
18587
18644
  function validateToolArguments(toolName, argsStr, toolSchemas, textContent) {
18588
18645
  const result = validateAndRepairToolCall(toolName, argsStr, toolSchemas, textContent);
@@ -18913,6 +18970,9 @@ data: ${JSON.stringify(d)}
18913
18970
  buffered: !!toolSchemas && toolSchemas.length > 0
18914
18971
  };
18915
18972
  state.tools.set(idx, t);
18973
+ if (isWebSearchToolCall(restoredName)) {
18974
+ warnWebSearchUnsupported(restoredName, target);
18975
+ }
18916
18976
  }
18917
18977
  if (!t.started && !t.buffered) {
18918
18978
  send("content_block_start", {
@@ -19079,6 +19139,7 @@ function estimateTokens(text) {
19079
19139
  var init_openai_sse = __esm(() => {
19080
19140
  init_logger();
19081
19141
  init_tool_call_recovery();
19142
+ init_web_search_detector();
19082
19143
  });
19083
19144
 
19084
19145
  // src/handlers/shared/openai-compat.ts
@@ -21001,7 +21062,7 @@ var init_token_tracker = __esm(() => {
21001
21062
  function createResponsesStreamHandler(c, response, opts) {
21002
21063
  const reader = response.body?.getReader();
21003
21064
  if (!reader) {
21004
- return c.json({ error: "No response body" }, 500);
21065
+ return c.json(wrapAnthropicError(500, "No response body"), 500);
21005
21066
  }
21006
21067
  const encoder = new TextEncoder;
21007
21068
  const decoder = new TextDecoder;
@@ -21284,8 +21345,24 @@ function createAnthropicPassthroughStream(c, response, opts) {
21284
21345
  const encoder = new TextEncoder;
21285
21346
  const decoder = new TextDecoder;
21286
21347
  let isClosed = false;
21348
+ let lastActivity = Date.now();
21349
+ let pingInterval = null;
21287
21350
  return c.body(new ReadableStream({
21288
21351
  async start(controller) {
21352
+ const sendPing = () => {
21353
+ if (!isClosed) {
21354
+ controller.enqueue(encoder.encode(`event: ping
21355
+ data: {"type":"ping"}
21356
+
21357
+ `));
21358
+ }
21359
+ };
21360
+ sendPing();
21361
+ pingInterval = setInterval(() => {
21362
+ if (!isClosed && Date.now() - lastActivity > 1000) {
21363
+ sendPing();
21364
+ }
21365
+ }, 1000);
21289
21366
  try {
21290
21367
  const reader = response.body.getReader();
21291
21368
  let buffer = "";
@@ -21300,6 +21377,7 @@ function createAnthropicPassthroughStream(c, response, opts) {
21300
21377
  if (done)
21301
21378
  break;
21302
21379
  buffer += decoder.decode(value, { stream: true });
21380
+ lastActivity = Date.now();
21303
21381
  const lines = buffer.split(`
21304
21382
  `);
21305
21383
  buffer = lines.pop() || "";
@@ -21342,19 +21420,31 @@ function createAnthropicPassthroughStream(c, response, opts) {
21342
21420
  opts.onTokenUpdate(inputTokens, outputTokens);
21343
21421
  }
21344
21422
  if (!isClosed) {
21345
- controller.close();
21346
21423
  isClosed = true;
21424
+ if (pingInterval) {
21425
+ clearInterval(pingInterval);
21426
+ pingInterval = null;
21427
+ }
21428
+ controller.close();
21347
21429
  }
21348
21430
  } catch (e) {
21349
21431
  log(`[AnthropicSSE] Stream error: ${e}`);
21350
21432
  if (!isClosed) {
21351
- controller.close();
21352
21433
  isClosed = true;
21434
+ if (pingInterval) {
21435
+ clearInterval(pingInterval);
21436
+ pingInterval = null;
21437
+ }
21438
+ controller.close();
21353
21439
  }
21354
21440
  }
21355
21441
  },
21356
21442
  cancel() {
21357
21443
  isClosed = true;
21444
+ if (pingInterval) {
21445
+ clearInterval(pingInterval);
21446
+ pingInterval = null;
21447
+ }
21358
21448
  }
21359
21449
  }), {
21360
21450
  headers: {
@@ -22237,7 +22327,7 @@ var init_profile_config = __esm(() => {
22237
22327
  });
22238
22328
 
22239
22329
  // src/version.ts
22240
- var VERSION = "6.10.1";
22330
+ var VERSION = "6.11.0";
22241
22331
 
22242
22332
  // src/telemetry.ts
22243
22333
  var exports_telemetry = {};
@@ -24218,7 +24308,7 @@ class ComposedHandler {
24218
24308
  invocation_mode: this.options.invocationMode ?? "auto-route"
24219
24309
  });
24220
24310
  } catch {}
24221
- return c.json({ error: { type: "connection_error", message: msg } }, 503);
24311
+ return c.json(wrapAnthropicError(503, msg, "connection_error"), 503);
24222
24312
  }
24223
24313
  throw error2;
24224
24314
  }
@@ -24280,7 +24370,7 @@ class ComposedHandler {
24280
24370
  invocation_mode: this.options.invocationMode ?? "auto-route"
24281
24371
  });
24282
24372
  } catch {}
24283
- return c.json({ error: errorText }, retryResp.status);
24373
+ return c.json(wrapAnthropicError(retryResp.status, errorText), retryResp.status);
24284
24374
  }
24285
24375
  } catch (err) {
24286
24376
  log(`[${this.provider.displayName}] Auth refresh failed: ${err.message}`);
@@ -24317,7 +24407,7 @@ class ComposedHandler {
24317
24407
  invocation_mode: this.options.invocationMode ?? "auto-route"
24318
24408
  });
24319
24409
  } catch {}
24320
- return c.json({ error: { type: "authentication_error", message: err.message } }, 401);
24410
+ return c.json(wrapAnthropicError(401, err.message, "authentication_error"), 401);
24321
24411
  }
24322
24412
  } else {
24323
24413
  const errorText = await response.text();
@@ -24370,7 +24460,7 @@ class ComposedHandler {
24370
24460
  } catch {
24371
24461
  errorBody = { error: { type: "api_error", message: errorText } };
24372
24462
  }
24373
- return c.json(errorBody, response.status);
24463
+ return c.json(ensureAnthropicErrorFormat(response.status, errorBody), response.status);
24374
24464
  }
24375
24465
  }
24376
24466
  if (droppedParams.length > 0) {
@@ -29224,7 +29314,7 @@ async function createProxyServer(port, openrouterApiKey, model, monitorMode = fa
29224
29314
  return c.json({ input_tokens: Math.ceil(txt.length / 4) });
29225
29315
  }
29226
29316
  } catch (e) {
29227
- return c.json({ error: String(e) }, 500);
29317
+ return c.json(wrapAnthropicError(500, String(e)), 500);
29228
29318
  }
29229
29319
  });
29230
29320
  app.post("/v1/messages", async (c) => {
@@ -29234,7 +29324,7 @@ async function createProxyServer(port, openrouterApiKey, model, monitorMode = fa
29234
29324
  return handler.handle(c, body);
29235
29325
  } catch (e) {
29236
29326
  log(`[Proxy] Error: ${e}`);
29237
- return c.json({ error: { type: "server_error", message: String(e) } }, 500);
29327
+ return c.json(wrapAnthropicError(500, String(e)), 500);
29238
29328
  }
29239
29329
  });
29240
29330
  const server = serve({ fetch: app.fetch, port, hostname: "127.0.0.1" });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claudish",
3
- "version": "6.10.1",
3
+ "version": "6.11.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",
@@ -59,10 +59,10 @@
59
59
  "ai"
60
60
  ],
61
61
  "optionalDependencies": {
62
- "@claudish/magmux-darwin-arm64": "6.10.1",
63
- "@claudish/magmux-darwin-x64": "6.10.1",
64
- "@claudish/magmux-linux-arm64": "6.10.1",
65
- "@claudish/magmux-linux-x64": "6.10.1"
62
+ "@claudish/magmux-darwin-arm64": "6.11.0",
63
+ "@claudish/magmux-darwin-x64": "6.11.0",
64
+ "@claudish/magmux-linux-arm64": "6.11.0",
65
+ "@claudish/magmux-linux-x64": "6.11.0"
66
66
  },
67
67
  "author": "Jack Rudenko <i@madappgang.com>",
68
68
  "license": "MIT",