claudish 7.18.0 → 7.18.1

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 +123 -15
  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.18.0";
654
+ var VERSION = "7.18.1";
655
655
 
656
656
  // src/logger.ts
657
657
  var exports_logger = {};
@@ -755,7 +755,7 @@ function redactDeep(val, key) {
755
755
  return val;
756
756
  }
757
757
  function isStructuralLogWorthy(msg) {
758
- return msg.startsWith("[SSE:") || msg.startsWith("[Proxy]") || msg.startsWith("[Fallback]") || msg.startsWith("[Streaming] ===") || msg.startsWith("[Streaming] Chunk:") || msg.startsWith("[Streaming] Received") || msg.startsWith("[Streaming] Text-based tool calls") || msg.startsWith("[Streaming] Final usage") || msg.startsWith("[Streaming] Sending") || msg.startsWith("[AnthropicSSE] Stream complete") || msg.startsWith("[AnthropicSSE] Tool use:") || msg.includes("Response status:") || msg.includes("Error") || msg.includes("error") || msg.includes("[Auto-route]");
758
+ return msg.startsWith("[SSE:") || msg.startsWith("[Suppressed]") || msg.startsWith("[Proxy]") || msg.startsWith("[Fallback]") || msg.startsWith("[Streaming] ===") || msg.startsWith("[Streaming] Chunk:") || msg.startsWith("[Streaming] Received") || msg.startsWith("[Streaming] Text-based tool calls") || msg.startsWith("[Streaming] Final usage") || msg.startsWith("[Streaming] Sending") || msg.startsWith("[AnthropicSSE] Stream complete") || msg.startsWith("[AnthropicSSE] Tool use:") || msg.includes("Response status:") || msg.includes("Error") || msg.includes("error") || msg.includes("[Auto-route]");
759
759
  }
760
760
  function redactLogLine(message, timestamp) {
761
761
  if (message.startsWith("[SSE:")) {
@@ -37112,9 +37112,15 @@ function statusToErrorType(status) {
37112
37112
  return "api_error";
37113
37113
  }
37114
37114
  }
37115
+ function sanitizeErrorMessage(message, maxLength = MAX_ERROR_MESSAGE_LENGTH) {
37116
+ const flattened = String(message ?? "").replace(ANSI_ESCAPE, "").replace(CONTROL_CHARS, " ").replace(/\s+/g, " ").trim();
37117
+ if (flattened.length <= maxLength)
37118
+ return flattened;
37119
+ return `${flattened.slice(0, maxLength - 1).trimEnd()}\u2026`;
37120
+ }
37115
37121
  function wrapAnthropicError(status, message, errorType, upstreamStatus) {
37116
37122
  const type = errorType || statusToErrorType(status);
37117
- const error46 = { type, message };
37123
+ const error46 = { type, message: sanitizeErrorMessage(message) };
37118
37124
  if (upstreamStatus !== undefined)
37119
37125
  error46.upstream_status = upstreamStatus;
37120
37126
  return { type: "error", error: error46 };
@@ -37178,15 +37184,23 @@ function buildSurfacedErrorMessage(opts) {
37178
37184
  }
37179
37185
  function ensureAnthropicErrorFormat(status, body) {
37180
37186
  if (body?.type === "error" && typeof body?.error?.type === "string" && typeof body?.error?.message === "string") {
37181
- return body;
37187
+ return { ...body, error: { ...body.error, message: sanitizeErrorMessage(body.error.message) } };
37182
37188
  }
37183
37189
  if (typeof body?.error?.type === "string" && typeof body?.error?.message === "string") {
37184
- return { type: "error", error: body.error };
37190
+ return {
37191
+ type: "error",
37192
+ error: { ...body.error, message: sanitizeErrorMessage(body.error.message) }
37193
+ };
37185
37194
  }
37186
37195
  const message = body?.error?.message || body?.message || body?.error || (typeof body === "string" ? body : JSON.stringify(body));
37187
37196
  const errorType = body?.error?.type || body?.type || body?.code;
37188
37197
  return wrapAnthropicError(status, String(message), errorType);
37189
37198
  }
37199
+ var MAX_ERROR_MESSAGE_LENGTH = 600, ANSI_ESCAPE, CONTROL_CHARS;
37200
+ var init_anthropic_error = __esm(() => {
37201
+ ANSI_ESCAPE = /\x1B\[[0-?]*[ -/]*[@-~]|\x1B[@-Z\\-_]/g;
37202
+ CONTROL_CHARS = /[\x00-\x1F\x7F]/g;
37203
+ });
37190
37204
 
37191
37205
  // src/handlers/shared/connection-error.ts
37192
37206
  function findConnectionCode(error46) {
@@ -37201,8 +37215,18 @@ function findConnectionCode(error46) {
37201
37215
  const msg = String(error46?.message ?? error46 ?? "");
37202
37216
  if (/getaddrinfo|ENOTFOUND|EAI_AGAIN|nodename nor servname/i.test(msg))
37203
37217
  return "ENOTFOUND";
37218
+ if (BUN_CONNECT_MESSAGE.test(msg))
37219
+ return "ConnectionRefused";
37204
37220
  return null;
37205
37221
  }
37222
+ function isLoopback(endpoint) {
37223
+ try {
37224
+ const { hostname: hostname4 } = new URL(endpoint);
37225
+ return /^(localhost|127\.\d+\.\d+\.\d+|0\.0\.0\.0|\[?::1\]?)$/i.test(hostname4);
37226
+ } catch {
37227
+ return false;
37228
+ }
37229
+ }
37206
37230
  function classifyConnectionError(error46) {
37207
37231
  const code = findConnectionCode(error46);
37208
37232
  if (!code)
@@ -37222,12 +37246,15 @@ function buildConnectionErrorMessage(kind, displayName, endpoint) {
37222
37246
  case "dns":
37223
37247
  return `Cannot resolve ${host} for ${displayName}. This is a DNS/network problem on your machine \u2014 check your internet connection, VPN, or DNS resolver (e.g. Tailscale MagicDNS) \u2014 not ${displayName}.`;
37224
37248
  case "refused":
37225
- return `Cannot connect to ${displayName} at ${endpoint}. Make sure the server is running.`;
37249
+ if (isLoopback(endpoint)) {
37250
+ return `Cannot connect to ${displayName} at ${endpoint}. Make sure the server is running.`;
37251
+ }
37252
+ return `Cannot reach ${host} for ${displayName}. This is a network problem on your machine \u2014 check your internet connection, VPN, or DNS resolver (e.g. Tailscale MagicDNS) \u2014 not ${displayName}.`;
37226
37253
  case "unreachable":
37227
37254
  return `Cannot reach ${displayName} at ${endpoint}. Check your network connection.`;
37228
37255
  }
37229
37256
  }
37230
- var CODE_KIND;
37257
+ var CODE_KIND, BUN_CONNECT_MESSAGE;
37231
37258
  var init_connection_error = __esm(() => {
37232
37259
  CODE_KIND = {
37233
37260
  ENOTFOUND: "dns",
@@ -37239,8 +37266,13 @@ var init_connection_error = __esm(() => {
37239
37266
  EHOSTUNREACH: "unreachable",
37240
37267
  EPIPE: "unreachable",
37241
37268
  UND_ERR_CONNECT_TIMEOUT: "unreachable",
37242
- UND_ERR_SOCKET: "unreachable"
37269
+ UND_ERR_SOCKET: "unreachable",
37270
+ ConnectionRefused: "refused",
37271
+ ConnectionClosed: "unreachable",
37272
+ FailedToOpenSocket: "unreachable",
37273
+ ERR_SOCKET_CLOSED: "unreachable"
37243
37274
  };
37275
+ BUN_CONNECT_MESSAGE = /unable to connect\. is the computer able to access the url\?/i;
37244
37276
  });
37245
37277
 
37246
37278
  // src/handlers/shared/stream-parsers/anthropic-sse.ts
@@ -38206,6 +38238,7 @@ data: ${JSON.stringify(data)}
38206
38238
  var init_openai_responses_sse = __esm(() => {
38207
38239
  init_reasoning_cache();
38208
38240
  init_logger();
38241
+ init_anthropic_error();
38209
38242
  });
38210
38243
 
38211
38244
  // src/handlers/shared/token-tracker.ts
@@ -38548,7 +38581,7 @@ class ComposedHandler {
38548
38581
  isInteractive: this.isInteractive,
38549
38582
  authType: "oauth"
38550
38583
  });
38551
- return c.json({ error: { type: "authentication_error", message: err.message } }, 401);
38584
+ return c.json(wrapAnthropicError(401, err.message, "authentication_error"), 401);
38552
38585
  }
38553
38586
  }
38554
38587
  if (this.provider.getContextWindow) {
@@ -38614,7 +38647,7 @@ class ComposedHandler {
38614
38647
  invocation_mode: this.options.invocationMode ?? "auto-route"
38615
38648
  });
38616
38649
  } catch {}
38617
- return c.json(wrapAnthropicError(503, msg, "connection_error"), 503);
38650
+ return c.json(wrapAnthropicError(400, msg, "connection_error"), 400);
38618
38651
  }
38619
38652
  throw error46;
38620
38653
  }
@@ -38951,6 +38984,7 @@ var init_composed_handler = __esm(() => {
38951
38984
  init_stats();
38952
38985
  init_telemetry();
38953
38986
  init_transform();
38987
+ init_anthropic_error();
38954
38988
  init_connection_error();
38955
38989
  init_openai_compat();
38956
38990
  init_anthropic_sse();
@@ -39907,6 +39941,7 @@ var init_native_handler = __esm(() => {
39907
39941
  init_logger();
39908
39942
  init_profile_config();
39909
39943
  init_native_handler_advisor();
39944
+ init_anthropic_error();
39910
39945
  });
39911
39946
 
39912
39947
  // src/providers/api-key-map.ts
@@ -43482,7 +43517,7 @@ async function createProxyServer(port, _openrouterApiKey, model, monitorMode = f
43482
43517
  log(`[Proxy] Registered ${customEpResult.registered} custom endpoint(s) from config`);
43483
43518
  }
43484
43519
  for (const err of customEpResult.errors) {
43485
- console.error(`[claudish] customEndpoints['${err.name}'] failed validation: ${err.message}`);
43520
+ logStderr(`customEndpoints['${err.name}'] failed validation: ${err.message}`);
43486
43521
  }
43487
43522
  } catch (err) {
43488
43523
  log(`[Proxy] customEndpoints load skipped: ${err instanceof Error ? err.message : String(err)}`);
@@ -43570,9 +43605,10 @@ async function createProxyServer(port, _openrouterApiKey, model, monitorMode = f
43570
43605
  const resolution = resolveModelProvider(targetModel);
43571
43606
  if (resolution.wasAutoRouted && resolution.autoRouteMessage) {
43572
43607
  if (!options.quiet) {
43573
- console.error(`[Auto-route] ${resolution.autoRouteMessage}`);
43608
+ logStderr(`[Auto-route] ${resolution.autoRouteMessage}`);
43609
+ } else {
43610
+ log(`[Auto-route] ${resolution.autoRouteMessage}`);
43574
43611
  }
43575
- log(`[Auto-route] ${resolution.autoRouteMessage}`);
43576
43612
  }
43577
43613
  if (resolution.category === "openrouter") {
43578
43614
  if (resolution.wasAutoRouted && resolution.fullModelId) {
@@ -43591,7 +43627,7 @@ async function createProxyServer(port, _openrouterApiKey, model, monitorMode = f
43591
43627
  let apiKey = "";
43592
43628
  if (resolved.provider.apiKeyEnvVar) {
43593
43629
  if (!credentials.get(resolved.provider.name)) {
43594
- console.error(`[Proxy] No credential provider registered for "${resolved.provider.name}" \u2014 treating as missing credential (authority registration gap)`);
43630
+ logStderr(`[Proxy] No credential provider registered for "${resolved.provider.name}" \u2014 treating as missing credential (authority registration gap)`);
43595
43631
  log(`[Proxy] Credential authority has no provider registered under "${resolved.provider.name}"`);
43596
43632
  return null;
43597
43633
  }
@@ -43749,6 +43785,11 @@ ${plan.hint}` : `[Route] ${plan.reason}`;
43749
43785
  };
43750
43786
  const app = new Hono2;
43751
43787
  app.use("*", cors());
43788
+ app.onError((err, c) => {
43789
+ logStderr(`[Proxy] Unhandled error on ${c.req.method} ${c.req.path}: ${err?.message ?? err}`);
43790
+ log(`[Proxy] Unhandled error stack: ${err?.stack ?? "(no stack)"}`);
43791
+ return c.json(wrapAnthropicError(500, `Proxy error: ${err?.message ?? String(err)}`), 500);
43792
+ });
43752
43793
  app.get("/", (c) => c.json({
43753
43794
  status: "ok",
43754
43795
  message: "Claudish Proxy",
@@ -43828,7 +43869,7 @@ ${plan.hint}` : `[Route] ${plan.reason}`;
43828
43869
  const body = await c.req.json();
43829
43870
  log(`[RequestMeta] model=${body.model} output_config=${JSON.stringify(body.output_config) ?? "(none)"} metadata=${JSON.stringify(body.metadata) ?? "(none)"} anthropic-beta=${c.req.header("anthropic-beta") ?? "(none)"}`);
43830
43871
  const handler = await getHandlerForRequest(body.model);
43831
- return handler.handle(c, body);
43872
+ return await handler.handle(c, body);
43832
43873
  } catch (e) {
43833
43874
  log(`[Proxy] Error: ${e}`);
43834
43875
  if (e instanceof RoutingError) {
@@ -43882,6 +43923,7 @@ var init_proxy_server = __esm(() => {
43882
43923
  init_composed_handler();
43883
43924
  init_fallback_handler();
43884
43925
  init_native_handler();
43926
+ init_anthropic_error();
43885
43927
  init_logger();
43886
43928
  init_model_loader();
43887
43929
  init_profile_config();
@@ -71036,6 +71078,56 @@ var init_tui = __esm(() => {
71036
71078
  }
71037
71079
  });
71038
71080
 
71081
+ // src/terminal-isolation.ts
71082
+ import { format } from "util";
71083
+ function beginTerminalIsolation(onSuppressed) {
71084
+ if (active)
71085
+ return () => {};
71086
+ active = true;
71087
+ const emit2 = (source, text) => {
71088
+ if (routing)
71089
+ return;
71090
+ routing = true;
71091
+ try {
71092
+ onSuppressed({ source, text });
71093
+ } catch {} finally {
71094
+ routing = false;
71095
+ }
71096
+ };
71097
+ const originalConsole = {};
71098
+ for (const method of CONSOLE_METHODS) {
71099
+ originalConsole[method] = console[method];
71100
+ console[method] = (...args) => {
71101
+ emit2(`console.${method}`, format(...args));
71102
+ };
71103
+ }
71104
+ const originalStdoutWrite = process.stdout.write.bind(process.stdout);
71105
+ const originalStderrWrite = process.stderr.write.bind(process.stderr);
71106
+ const makeWrite = (source) => (chunk, encoding, callback) => {
71107
+ const done = typeof encoding === "function" ? encoding : callback;
71108
+ emit2(source, typeof chunk === "string" ? chunk : Buffer.from(chunk).toString("utf8"));
71109
+ if (typeof done === "function")
71110
+ done(null);
71111
+ return true;
71112
+ };
71113
+ process.stdout.write = makeWrite("stdout");
71114
+ process.stderr.write = makeWrite("stderr");
71115
+ return function restore() {
71116
+ if (!active)
71117
+ return;
71118
+ for (const method of CONSOLE_METHODS) {
71119
+ console[method] = originalConsole[method];
71120
+ }
71121
+ process.stdout.write = originalStdoutWrite;
71122
+ process.stderr.write = originalStderrWrite;
71123
+ active = false;
71124
+ };
71125
+ }
71126
+ var CONSOLE_METHODS, active = false, routing = false;
71127
+ var init_terminal_isolation = __esm(() => {
71128
+ CONSOLE_METHODS = ["log", "error", "warn", "info", "debug", "trace", "dir"];
71129
+ });
71130
+
71039
71131
  // src/claude-runner.ts
71040
71132
  var exports_claude_runner = {};
71041
71133
  __export(exports_claude_runner, {
@@ -71059,6 +71151,12 @@ import {
71059
71151
  import { homedir as homedir24, tmpdir as tmpdir2 } from "os";
71060
71152
  import { join as join25 } from "path";
71061
71153
  import { isatty } from "tty";
71154
+ function releaseTerminalIsolation() {
71155
+ if (!restoreTerminal)
71156
+ return;
71157
+ restoreTerminal();
71158
+ restoreTerminal = null;
71159
+ }
71062
71160
  function hasNativeAnthropicMapping(config3) {
71063
71161
  const models = [
71064
71162
  config3.model,
@@ -71417,6 +71515,11 @@ Or set CLAUDE_PATH to your custom installation:`);
71417
71515
  stdio,
71418
71516
  shell: needsShell
71419
71517
  });
71518
+ if (config3.interactive) {
71519
+ restoreTerminal = beginTerminalIsolation((entry) => {
71520
+ logStderr(`[Suppressed] ${entry.source}: ${entry.text.trimEnd()}`);
71521
+ });
71522
+ }
71420
71523
  if (ttyFd !== undefined) {
71421
71524
  const fdToClose = ttyFd;
71422
71525
  proc.on("spawn", () => {
@@ -71432,6 +71535,7 @@ Or set CLAUDE_PATH to your custom installation:`);
71432
71535
  resolve3(code ?? 1);
71433
71536
  });
71434
71537
  });
71538
+ releaseTerminalIsolation();
71435
71539
  try {
71436
71540
  unlinkSync9(tempSettingsPath);
71437
71541
  } catch {}
@@ -71441,6 +71545,7 @@ function setupSignalHandlers(proc, tempSettingsPath, quiet, onCleanup) {
71441
71545
  const signals2 = isWindows2() ? ["SIGINT", "SIGTERM"] : ["SIGINT", "SIGTERM", "SIGHUP"];
71442
71546
  for (const signal of signals2) {
71443
71547
  process.on(signal, () => {
71548
+ releaseTerminalIsolation();
71444
71549
  if (!quiet) {
71445
71550
  console.error(`
71446
71551
  [claudish] Received ${signal}, shutting down...`);
@@ -71529,12 +71634,15 @@ async function checkClaudeInstalled() {
71529
71634
  const binary = await findClaudeBinary();
71530
71635
  return binary !== null;
71531
71636
  }
71637
+ var restoreTerminal = null;
71532
71638
  var init_claude_runner = __esm(() => {
71533
71639
  init_model_catalog();
71534
71640
  init_config();
71641
+ init_logger();
71535
71642
  init_model_parser();
71536
71643
  init_routing_rules();
71537
71644
  init_telemetry();
71645
+ init_terminal_isolation();
71538
71646
  });
71539
71647
 
71540
71648
  // src/diag-output.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claudish",
3
- "version": "7.18.0",
3
+ "version": "7.18.1",
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.18.0",
64
- "@claudish/magmux-darwin-x64": "7.18.0",
65
- "@claudish/magmux-linux-arm64": "7.18.0",
66
- "@claudish/magmux-linux-x64": "7.18.0"
63
+ "@claudish/magmux-darwin-arm64": "7.18.1",
64
+ "@claudish/magmux-darwin-x64": "7.18.1",
65
+ "@claudish/magmux-linux-arm64": "7.18.1",
66
+ "@claudish/magmux-linux-x64": "7.18.1"
67
67
  },
68
68
  "author": "Jack Rudenko <i@madappgang.com>",
69
69
  "license": "MIT",