claudish 7.20.0 → 7.20.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 +96 -23
  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.20.0";
654
+ var VERSION = "7.20.1";
655
655
 
656
656
  // src/logger.ts
657
657
  var exports_logger = {};
@@ -27650,6 +27650,9 @@ function loadConfig() {
27650
27650
  if (config2.onepasswordEnvironments !== undefined) {
27651
27651
  merged.onepasswordEnvironments = config2.onepasswordEnvironments;
27652
27652
  }
27653
+ if (config2.anthropicApiBilling !== undefined) {
27654
+ merged.anthropicApiBilling = config2.anthropicApiBilling;
27655
+ }
27653
27656
  if (config2.localProviders !== undefined) {
27654
27657
  merged.localProviders = Array.from(new Set(config2.localProviders)).sort();
27655
27658
  }
@@ -31758,6 +31761,14 @@ var init_web_search_detector = __esm(() => {
31758
31761
  WEB_SEARCH_NAMES = new Set(["web_search", "brave_web_search", "tavily_search"]);
31759
31762
  });
31760
31763
 
31764
+ // src/handlers/shared/stream-parsers/message-start-usage.ts
31765
+ function messageStartUsage(priorInputTokens) {
31766
+ return {
31767
+ input_tokens: priorInputTokens && priorInputTokens > 0 ? priorInputTokens : 100,
31768
+ output_tokens: 1
31769
+ };
31770
+ }
31771
+
31761
31772
  // src/handlers/shared/stream-parsers/openai-sse.ts
31762
31773
  function validateToolArguments(toolName, argsStr, toolSchemas, textContent) {
31763
31774
  const result = validateAndRepairToolCall(toolName, argsStr, toolSchemas, textContent);
@@ -31787,7 +31798,7 @@ function createStreamingState() {
31787
31798
  accumulatedText: ""
31788
31799
  };
31789
31800
  }
31790
- function createStreamingResponseHandler(c, response, adapter, target, middlewareManager, onTokenUpdate, toolSchemas, toolNameMap) {
31801
+ function createStreamingResponseHandler(c, response, adapter, target, middlewareManager, onTokenUpdate, toolSchemas, toolNameMap, priorInputTokens) {
31791
31802
  log(`[Streaming] ===== HANDLER STARTED for ${target} =====`);
31792
31803
  let isClosed = false;
31793
31804
  let ping = null;
@@ -31816,7 +31827,7 @@ data: ${JSON.stringify(d)}
31816
31827
  model: target,
31817
31828
  stop_reason: null,
31818
31829
  stop_sequence: null,
31819
- usage: { input_tokens: 100, output_tokens: 1 }
31830
+ usage: messageStartUsage(priorInputTokens)
31820
31831
  }
31821
31832
  });
31822
31833
  send("ping", { type: "ping" });
@@ -31929,7 +31940,10 @@ data: ${JSON.stringify(d)}
31929
31940
  send("message_delta", {
31930
31941
  type: "message_delta",
31931
31942
  delta: { stop_reason: stopReason, stop_sequence: null },
31932
- usage: { output_tokens: state.usage?.completion_tokens || 0 }
31943
+ usage: {
31944
+ ...state.usage?.prompt_tokens ? { input_tokens: state.usage.prompt_tokens } : {},
31945
+ output_tokens: state.usage?.completion_tokens || 0
31946
+ }
31933
31947
  });
31934
31948
  send("message_stop", { type: "message_stop" });
31935
31949
  }
@@ -31940,7 +31954,7 @@ data: ${JSON.stringify(d)}
31940
31954
  } else {
31941
31955
  const estimatedOutputTokens = Math.ceil(state.accumulatedText.length / 4);
31942
31956
  log(`[Streaming] No usage data from provider, estimating: ~${estimatedOutputTokens} output tokens`);
31943
- onTokenUpdate(100, estimatedOutputTokens);
31957
+ onTokenUpdate(priorInputTokens || 100, estimatedOutputTokens);
31944
31958
  }
31945
31959
  }
31946
31960
  if (!isClosed) {
@@ -37558,7 +37572,7 @@ data: ${JSON.stringify(data)}
37558
37572
  model: opts.modelName,
37559
37573
  stop_reason: null,
37560
37574
  stop_sequence: null,
37561
- usage: { input_tokens: 100, output_tokens: 1 }
37575
+ usage: messageStartUsage(opts.priorInputTokens)
37562
37576
  }
37563
37577
  });
37564
37578
  send("ping", { type: "ping" });
@@ -37602,7 +37616,10 @@ data: ${JSON.stringify(data)}
37602
37616
  send("message_delta", {
37603
37617
  type: "message_delta",
37604
37618
  delta: { stop_reason: hasToolCalls ? "tool_use" : "end_turn", stop_sequence: null },
37605
- usage: { output_tokens: outputTokens }
37619
+ usage: {
37620
+ ...inputTokens > 0 ? { input_tokens: inputTokens } : {},
37621
+ output_tokens: outputTokens
37622
+ }
37606
37623
  });
37607
37624
  send("message_stop", { type: "message_stop" });
37608
37625
  }
@@ -37805,7 +37822,7 @@ data: ${JSON.stringify(data)}
37805
37822
  model: opts.modelName,
37806
37823
  stop_reason: null,
37807
37824
  stop_sequence: null,
37808
- usage: { input_tokens: 100, output_tokens: 1 }
37825
+ usage: messageStartUsage(opts.priorInputTokens)
37809
37826
  }
37810
37827
  });
37811
37828
  send("ping", { type: "ping" });
@@ -37826,7 +37843,10 @@ data: ${JSON.stringify(data)}
37826
37843
  send("message_delta", {
37827
37844
  type: "message_delta",
37828
37845
  delta: { stop_reason: "end_turn", stop_sequence: null },
37829
- usage: { output_tokens: completionTokens }
37846
+ usage: {
37847
+ ...promptTokens > 0 ? { input_tokens: promptTokens } : {},
37848
+ output_tokens: completionTokens
37849
+ }
37830
37850
  });
37831
37851
  send("message_stop", { type: "message_stop" });
37832
37852
  }
@@ -37978,7 +37998,7 @@ data: ${JSON.stringify(data)}
37978
37998
  model: opts.modelName,
37979
37999
  stop_reason: null,
37980
38000
  stop_sequence: null,
37981
- usage: { input_tokens: 100, output_tokens: 1 }
38001
+ usage: messageStartUsage(opts.priorInputTokens)
37982
38002
  }
37983
38003
  });
37984
38004
  send("ping", { type: "ping" });
@@ -38241,6 +38261,13 @@ data: ${JSON.stringify(data)}
38241
38261
  } catch {}
38242
38262
  }
38243
38263
  }
38264
+ },
38265
+ cancel() {
38266
+ isClosed = true;
38267
+ if (pingInterval) {
38268
+ clearInterval(pingInterval);
38269
+ pingInterval = null;
38270
+ }
38244
38271
  }
38245
38272
  });
38246
38273
  return new Response(stream, {
@@ -38268,6 +38295,7 @@ class TokenTracker {
38268
38295
  sessionTotalCost = 0;
38269
38296
  sessionInputTokens = 0;
38270
38297
  sessionOutputTokens = 0;
38298
+ lastInputTokens = 0;
38271
38299
  modelNameOverride;
38272
38300
  quotaRemaining;
38273
38301
  constructor(port, config2) {
@@ -38284,10 +38312,11 @@ class TokenTracker {
38284
38312
  this.quotaRemaining = fraction;
38285
38313
  }
38286
38314
  rewrite() {
38287
- this.writeFile(this.sessionInputTokens, this.sessionOutputTokens);
38315
+ this.writeFile(this.getLastInputTokens(), this.sessionOutputTokens);
38288
38316
  }
38289
38317
  update(inputTokens, outputTokens) {
38290
38318
  this.sessionInputTokens = inputTokens;
38319
+ this.lastInputTokens = inputTokens;
38291
38320
  this.sessionOutputTokens += outputTokens;
38292
38321
  const pricing = this.getPricing();
38293
38322
  const cost = inputTokens / 1e6 * pricing.inputCostPer1M + outputTokens / 1e6 * pricing.outputCostPer1M;
@@ -38296,6 +38325,7 @@ class TokenTracker {
38296
38325
  }
38297
38326
  accumulateBoth(inputTokens, outputTokens) {
38298
38327
  this.sessionInputTokens += inputTokens;
38328
+ this.lastInputTokens = this.sessionInputTokens;
38299
38329
  this.sessionOutputTokens += outputTokens;
38300
38330
  const pricing = this.getPricing();
38301
38331
  const cost = this.sessionInputTokens / 1e6 * pricing.inputCostPer1M + this.sessionOutputTokens / 1e6 * pricing.outputCostPer1M;
@@ -38304,6 +38334,7 @@ class TokenTracker {
38304
38334
  }
38305
38335
  updateWithDelta(inputTokens, outputTokens) {
38306
38336
  let incrementalInputTokens;
38337
+ this.lastInputTokens = inputTokens;
38307
38338
  if (inputTokens >= this.sessionInputTokens) {
38308
38339
  incrementalInputTokens = inputTokens - this.sessionInputTokens;
38309
38340
  this.sessionInputTokens = inputTokens;
@@ -38319,10 +38350,11 @@ class TokenTracker {
38319
38350
  const pricing = this.getPricing();
38320
38351
  const cost = incrementalInputTokens / 1e6 * pricing.inputCostPer1M + outputTokens / 1e6 * pricing.outputCostPer1M;
38321
38352
  this.sessionTotalCost += cost;
38322
- this.writeFile(Math.max(inputTokens, this.sessionInputTokens), this.sessionOutputTokens, pricing.isEstimate);
38353
+ this.writeFile(inputTokens, this.sessionOutputTokens, pricing.isEstimate);
38323
38354
  }
38324
38355
  updateWithActualCost(inputTokens, outputTokens, actualCost) {
38325
38356
  this.sessionInputTokens = inputTokens;
38357
+ this.lastInputTokens = inputTokens;
38326
38358
  this.sessionOutputTokens += outputTokens;
38327
38359
  if (typeof actualCost === "number" && actualCost > 0) {
38328
38360
  this.sessionTotalCost += actualCost;
@@ -38338,6 +38370,7 @@ class TokenTracker {
38338
38370
  updateLocal(inputTokens, outputTokens) {
38339
38371
  if (inputTokens > 0) {
38340
38372
  this.sessionInputTokens = inputTokens;
38373
+ this.lastInputTokens = inputTokens;
38341
38374
  }
38342
38375
  this.sessionOutputTokens += outputTokens;
38343
38376
  this.writeFile(this.sessionInputTokens, this.sessionOutputTokens);
@@ -38351,6 +38384,9 @@ class TokenTracker {
38351
38384
  getInputTokens() {
38352
38385
  return this.sessionInputTokens;
38353
38386
  }
38387
+ getLastInputTokens() {
38388
+ return this.lastInputTokens || this.sessionInputTokens;
38389
+ }
38354
38390
  getOutputTokens() {
38355
38391
  return this.sessionOutputTokens;
38356
38392
  }
@@ -38892,16 +38928,18 @@ class ComposedHandler {
38892
38928
  }
38893
38929
  };
38894
38930
  const streamFormat = this.provider.overrideStreamFormat?.() ?? this.explicitAdapter?.getStreamFormat() ?? this.modelAdapter?.getStreamFormat() ?? this.getAdapter().getStreamFormat();
38931
+ const priorInputTokens = this.tokenTracker.getLastInputTokens();
38895
38932
  switch (streamFormat) {
38896
38933
  case "openai-sse":
38897
- return createStreamingResponseHandler(c, response, adapter, this.bareModelName, this.middlewareManager, onTokenUpdate, claudeRequest.tools, toolNameMap);
38934
+ return createStreamingResponseHandler(c, response, adapter, this.bareModelName, this.middlewareManager, onTokenUpdate, claudeRequest.tools, toolNameMap, priorInputTokens);
38898
38935
  case "openai-responses-sse":
38899
38936
  return createResponsesStreamHandler(c, response, {
38900
38937
  modelName: this.bareModelName,
38901
38938
  onTokenUpdate,
38902
38939
  toolNameMap: adapter.getToolNameMap(),
38903
38940
  contextWindow: lookupModelForProvider(this.bareModelName, this.provider.name),
38904
- onApiError
38941
+ onApiError,
38942
+ priorInputTokens
38905
38943
  });
38906
38944
  case "anthropic-sse":
38907
38945
  return createAnthropicPassthroughStream(c, response, {
@@ -38921,13 +38959,15 @@ class ComposedHandler {
38921
38959
  middlewareManager: this.middlewareManager,
38922
38960
  onTokenUpdate,
38923
38961
  onToolCall,
38924
- unwrapResponse: this.options.unwrapGeminiResponse
38962
+ unwrapResponse: this.options.unwrapGeminiResponse,
38963
+ priorInputTokens
38925
38964
  });
38926
38965
  }
38927
38966
  case "ollama-jsonl":
38928
38967
  return createOllamaJsonlStream(c, response, {
38929
38968
  modelName: this.bareModelName,
38930
- onTokenUpdate
38969
+ onTokenUpdate,
38970
+ priorInputTokens
38931
38971
  });
38932
38972
  default:
38933
38973
  throw new Error(`Unknown stream format: ${streamFormat}`);
@@ -58411,7 +58451,8 @@ var init_config = __esm(() => {
58411
58451
  OPENAI_BASE_URL: "OPENAI_BASE_URL",
58412
58452
  CLAUDISH_SUMMARIZE_TOOLS: "CLAUDISH_SUMMARIZE_TOOLS",
58413
58453
  CLAUDISH_DIAG_MODE: "CLAUDISH_DIAG_MODE",
58414
- CLAUDISH_DEBUG: "CLAUDISH_DEBUG"
58454
+ CLAUDISH_DEBUG: "CLAUDISH_DEBUG",
58455
+ CLAUDISH_ANTHROPIC_API_BILLING: "CLAUDISH_ANTHROPIC_API_BILLING"
58415
58456
  };
58416
58457
  OPENROUTER_HEADERS = {
58417
58458
  "HTTP-Referer": "https://claudish.com",
@@ -62491,6 +62532,8 @@ async function parseArgs(args) {
62491
62532
  process.exit(1);
62492
62533
  }
62493
62534
  config3.defaultProvider = dpArg;
62535
+ } else if (arg === "--anthropic-api-billing") {
62536
+ config3.anthropicApiBilling = true;
62494
62537
  } else if (arg === "--op-env" || arg.startsWith("--op-env=")) {
62495
62538
  const v = arg.startsWith("--op-env=") ? arg.slice("--op-env=".length) : args[++i];
62496
62539
  if (!v) {
@@ -63540,6 +63583,10 @@ ${h("OPTIONS")}
63540
63583
  ${green("--profile")} ${yellow("<name>")} Use named profile for model mapping (default profile if omitted)
63541
63584
  ${green("--default-provider")} ${yellow("<name>")} Fallback provider for bare model names (builtin or customEndpoints key)
63542
63585
  ${dim("Precedence: this flag > CLAUDISH_DEFAULT_PROVIDER env > config.json")}
63586
+ ${green("--anthropic-api-billing")} Use your real ANTHROPIC_API_KEY for native Claude models
63587
+ ${dim("(metered API billing). Default: the key is hidden so Claude Code")}
63588
+ ${dim("uses your claude.ai subscription. Env: CLAUDISH_ANTHROPIC_API_BILLING")}
63589
+ ${dim("Config: anthropicApiBilling: true")}
63543
63590
  ${green("--config")} ${yellow("<file>")} Use THIS config file for the run, fully replacing the machine
63544
63591
  ${dim("global (~/.claudish/config.json) AND project (.claudish.json).")}
63545
63592
  ${dim("A file naming no op:// source never touches 1Password (no prompt).")}
@@ -63715,6 +63762,7 @@ ${h("ENVIRONMENT VARIABLES")}
63715
63762
  ${blue("CLAUDISH_CONTEXT_WINDOW")} Override context window size
63716
63763
  ${blue("CLAUDISH_DIAG_MODE")} Diagnostic output: auto / logfile / off
63717
63764
  ${blue("CLAUDISH_DEBUG")} Always enable debug logging: 1 / true ${dim("(same as -d)")}
63765
+ ${blue("CLAUDISH_ANTHROPIC_API_BILLING")} Bill native Claude to your API key ${dim("(see --anthropic-api-billing)")}
63718
63766
  ${blue("CLAUDISH_MCP_TOOLS")} MCP tool gating: all / low-level / agentic / channel
63719
63767
  ${blue("CLAUDISH_MODEL_OPUS")} Override model for Opus role
63720
63768
  ${blue("CLAUDISH_MODEL_SONNET")} Override model for Sonnet role
@@ -71284,7 +71332,8 @@ __export(exports_claude_runner, {
71284
71332
  isProxyAuthMode: () => isProxyAuthMode,
71285
71333
  computeMainThreadContextWindow: () => computeMainThreadContextWindow,
71286
71334
  checkClaudeInstalled: () => checkClaudeInstalled,
71287
- buildClaudishSettingsOverlay: () => buildClaudishSettingsOverlay
71335
+ buildClaudishSettingsOverlay: () => buildClaudishSettingsOverlay,
71336
+ MIN_AUTO_COMPACT_WINDOW: () => MIN_AUTO_COMPACT_WINDOW
71288
71337
  });
71289
71338
  import { spawn as spawn4 } from "child_process";
71290
71339
  import {
@@ -71315,6 +71364,18 @@ function hasNativeAnthropicMapping(config3) {
71315
71364
  ];
71316
71365
  return models.some((m) => m && parseModelSpec(m).provider === "native-anthropic");
71317
71366
  }
71367
+ function wantsAnthropicApiBilling(config3) {
71368
+ if (config3.anthropicApiBilling)
71369
+ return true;
71370
+ const raw2 = process.env[ENV.CLAUDISH_ANTHROPIC_API_BILLING];
71371
+ if (raw2 !== undefined && raw2 !== "" && raw2 !== "0" && raw2.toLowerCase() !== "false")
71372
+ return true;
71373
+ try {
71374
+ return loadConfig().anthropicApiBilling === true;
71375
+ } catch {
71376
+ return false;
71377
+ }
71378
+ }
71318
71379
  function isProxyAuthMode(config3) {
71319
71380
  return !config3.monitor && !hasNativeAnthropicMapping(config3);
71320
71381
  }
@@ -71578,6 +71639,7 @@ async function runClaudeWithProxy(config3, proxyUrl, onCleanup) {
71578
71639
  [ENV.CLAUDISH_ACTIVE_MODEL_NAME]: modelDisplayName,
71579
71640
  CLAUDISH_IS_LOCAL: isLocalModel2 ? "true" : "false"
71580
71641
  };
71642
+ let hidAnthropicApiKey = false;
71581
71643
  delete env.CLAUDECODE;
71582
71644
  if (config3.monitor) {
71583
71645
  delete env.ANTHROPIC_API_KEY;
@@ -71591,16 +71653,23 @@ async function runClaudeWithProxy(config3, proxyUrl, onCleanup) {
71591
71653
  env[ENV.ANTHROPIC_MODEL] = modelId;
71592
71654
  env[ENV.ANTHROPIC_SMALL_FAST_MODEL] = modelId;
71593
71655
  }
71594
- if (hasNativeAnthropicMapping(config3)) {} else {
71595
- env.ANTHROPIC_API_KEY = process.env.ANTHROPIC_API_KEY || "sk-ant-api03-placeholder-not-used-proxy-handles-auth-with-openrouter-key-xxxxxxxxxxxxxxxxxxxxx";
71596
- env.ANTHROPIC_AUTH_TOKEN = process.env.ANTHROPIC_AUTH_TOKEN || "placeholder-token-not-used-proxy-handles-auth";
71656
+ if (hasNativeAnthropicMapping(config3)) {
71657
+ if (process.env.ANTHROPIC_API_KEY && !wantsAnthropicApiBilling(config3)) {
71658
+ delete env.ANTHROPIC_API_KEY;
71659
+ hidAnthropicApiKey = true;
71660
+ }
71661
+ } else {
71662
+ env.ANTHROPIC_API_KEY = "sk-ant-api03-placeholder-not-used-proxy-handles-auth-with-openrouter-key-xxxxxxxxxxxxxxxxxxxxx";
71663
+ env.ANTHROPIC_AUTH_TOKEN = "placeholder-token-not-used-proxy-handles-auth";
71597
71664
  if (!process.env[ENV.CLAUDE_CODE_AUTO_COMPACT_WINDOW]) {
71598
71665
  const autoCompactWindow = await computeMainThreadContextWindow(config3);
71599
- if (autoCompactWindow > 0) {
71666
+ if (autoCompactWindow >= MIN_AUTO_COMPACT_WINDOW) {
71600
71667
  env[ENV.CLAUDE_CODE_AUTO_COMPACT_WINDOW] = String(autoCompactWindow);
71601
71668
  if (!config3.quiet) {
71602
71669
  console.error(`[claudish] Auto-compact window: ${autoCompactWindow.toLocaleString()} tokens ` + "(Claude Code compacts before the backend's real limit)");
71603
71670
  }
71671
+ } else if (autoCompactWindow > 0 && !config3.quiet) {
71672
+ console.error(`[claudish] Model's real context window (${autoCompactWindow.toLocaleString()}) is below ` + `Claude Code's ${MIN_AUTO_COMPACT_WINDOW.toLocaleString()}-token auto-compact floor \u2014 ` + "leaving CLAUDE_CODE_AUTO_COMPACT_WINDOW unset so native auto-compaction stays on.");
71604
71673
  }
71605
71674
  }
71606
71675
  }
@@ -71616,6 +71685,9 @@ async function runClaudeWithProxy(config3, proxyUrl, onCleanup) {
71616
71685
  };
71617
71686
  if (!config3.monitor && hasNativeAnthropicMapping(config3)) {
71618
71687
  log2("[claudish] Native Claude model detected \u2014 using Claude Code subscription credentials");
71688
+ if (hidAnthropicApiKey) {
71689
+ log2("[claudish] ANTHROPIC_API_KEY found but hidden so it can't override that subscription \xB7 " + "use --anthropic-api-billing (or anthropicApiBilling: true) to bill the API instead");
71690
+ }
71619
71691
  }
71620
71692
  if (config3.interactive) {
71621
71693
  log2(`
@@ -71782,12 +71854,13 @@ async function checkClaudeInstalled() {
71782
71854
  const binary = await findClaudeBinary();
71783
71855
  return binary !== null;
71784
71856
  }
71785
- var restoreTerminal = null;
71857
+ var restoreTerminal = null, MIN_AUTO_COMPACT_WINDOW = 200000;
71786
71858
  var init_claude_runner = __esm(() => {
71787
71859
  init_model_catalog();
71788
71860
  init_config();
71789
71861
  init_logger();
71790
71862
  init_model_discovery();
71863
+ init_profile_config();
71791
71864
  init_model_parser();
71792
71865
  init_routing_rules();
71793
71866
  init_telemetry();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claudish",
3
- "version": "7.20.0",
3
+ "version": "7.20.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.20.0",
64
- "@claudish/magmux-darwin-x64": "7.20.0",
65
- "@claudish/magmux-linux-arm64": "7.20.0",
66
- "@claudish/magmux-linux-x64": "7.20.0"
63
+ "@claudish/magmux-darwin-arm64": "7.20.1",
64
+ "@claudish/magmux-darwin-x64": "7.20.1",
65
+ "@claudish/magmux-linux-arm64": "7.20.1",
66
+ "@claudish/magmux-linux-x64": "7.20.1"
67
67
  },
68
68
  "author": "Jack Rudenko <i@madappgang.com>",
69
69
  "license": "MIT",