claudish 7.14.0 → 7.16.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 +147 -53
  2. package/package.json +5 -5
package/dist/index.js CHANGED
@@ -581,7 +581,7 @@ var init_onepassword_config = __esm(() => {
581
581
  });
582
582
 
583
583
  // src/version.ts
584
- var VERSION = "7.14.0";
584
+ var VERSION = "7.16.0";
585
585
 
586
586
  // src/logger.ts
587
587
  var exports_logger = {};
@@ -4306,7 +4306,7 @@ function computeHasOpSources() {
4306
4306
  if (argv.some((a) => a === "--op" || a.startsWith("--op=") || a === "--op-env" || a.startsWith("--op-env="))) {
4307
4307
  return true;
4308
4308
  }
4309
- if (readAllOnepasswordEnvironments().length > 0)
4309
+ if (configEnvironmentIds().length > 0)
4310
4310
  return true;
4311
4311
  const cfg = readConfigRaw();
4312
4312
  if (cfg.apiKeys) {
@@ -4351,6 +4351,31 @@ function runOpExclusive(op, label = "op:resolve", meta) {
4351
4351
  });
4352
4352
  return run;
4353
4353
  }
4354
+ function flagEnvironmentIds() {
4355
+ const argv = process.argv.slice(2);
4356
+ const ids = [];
4357
+ for (let i = 0;i < argv.length; i++) {
4358
+ const a = argv[i];
4359
+ if (a === "--op-env") {
4360
+ const v = argv[i + 1];
4361
+ if (v && !v.startsWith("-"))
4362
+ ids.push(v);
4363
+ } else if (a.startsWith("--op-env=")) {
4364
+ const v = a.slice("--op-env=".length);
4365
+ if (v)
4366
+ ids.push(v);
4367
+ }
4368
+ }
4369
+ return ids;
4370
+ }
4371
+ function configEnvironmentIds() {
4372
+ if (testSeams?.config)
4373
+ return testSeams.config.onepasswordEnvironments ?? [];
4374
+ return readAllOnepasswordEnvironments();
4375
+ }
4376
+ function registeredEnvironmentIds() {
4377
+ return [...new Set([...configEnvironmentIds(), ...flagEnvironmentIds()])];
4378
+ }
4354
4379
  function maskGlobForTrace(globPath) {
4355
4380
  const body = globPath.startsWith("op://") ? globPath.slice("op://".length) : globPath;
4356
4381
  const segments = body.split("/");
@@ -4387,10 +4412,34 @@ async function resolveGlobShared(globPath, auth) {
4387
4412
  });
4388
4413
  return { resolved: await promise, cacheHit: false };
4389
4414
  }
4415
+ async function resolveEnvironmentShared(envId, auth) {
4416
+ const existing = environmentResolutions.get(envId);
4417
+ if (existing)
4418
+ return { resolved: await existing, cacheHit: true };
4419
+ const spanName = `op:env-resolve(${envId})`;
4420
+ const promise = (async () => {
4421
+ const { readEnvironment: readEnvironment2, recordOpHydratedVars: recordOpHydratedVars2 } = await Promise.resolve().then(() => (init_onepassword(), exports_onepassword));
4422
+ const resolved = await traceSpan(spanName, () => readEnvironment2(envId, { auth, sdkFactory: testSeams?.sdkFactory }));
4423
+ addSpanMeta(spanName, { vars: Object.keys(resolved).length });
4424
+ for (const [k, v] of Object.entries(resolved)) {
4425
+ resolvedCache.set(k, v);
4426
+ globResolvedVars.add(k);
4427
+ }
4428
+ recordOpHydratedVars2(Object.keys(resolved));
4429
+ return resolved;
4430
+ })();
4431
+ environmentResolutions.set(envId, promise);
4432
+ promise.catch(() => {
4433
+ if (environmentResolutions.get(envId) === promise)
4434
+ environmentResolutions.delete(envId);
4435
+ });
4436
+ return { resolved: await promise, cacheHit: false };
4437
+ }
4390
4438
  function invalidateOpResolutionCache() {
4391
4439
  resolvedCache.clear();
4392
4440
  globResolutions.clear();
4393
4441
  globResolvedVars.clear();
4442
+ environmentResolutions.clear();
4394
4443
  sniffed = undefined;
4395
4444
  }
4396
4445
  async function resolveOpKeyForEnvVars(wanted, opts = {}) {
@@ -4514,6 +4563,28 @@ async function resolveOpKeyForEnvVarsInner(wanted, opts = {}, span) {
4514
4563
  Object.assign(out, resolved);
4515
4564
  }
4516
4565
  }
4566
+ const stillWantedEnv = new Set([...wanted].filter((w) => !(w in out)));
4567
+ if (stillWantedEnv.size > 0) {
4568
+ for (const envId of registeredEnvironmentIds()) {
4569
+ if (stillWantedEnv.size === 0)
4570
+ break;
4571
+ try {
4572
+ const { resolved, cacheHit } = await resolveEnvironmentShared(envId, auth);
4573
+ if (cacheHit)
4574
+ span?.addMeta({ globCacheHit: true });
4575
+ for (const w of [...stillWantedEnv]) {
4576
+ const v = resolved[w];
4577
+ if (v !== undefined) {
4578
+ out[w] = v;
4579
+ stillWantedEnv.delete(w);
4580
+ }
4581
+ }
4582
+ } catch (envErr) {
4583
+ const m = envErr instanceof Error ? envErr.message : String(envErr);
4584
+ console.error(`[claudish] 1Password environment skipped: ${m}`);
4585
+ }
4586
+ }
4587
+ }
4517
4588
  } catch (err) {
4518
4589
  if (err instanceof OpAuthError && onAuthFailure === "skip") {
4519
4590
  console.error(`[claudish] 1Password resolution skipped: ${err.message}`);
@@ -4528,7 +4599,7 @@ async function resolveOpKeyForEnvVarsInner(wanted, opts = {}, span) {
4528
4599
  recordOpHydratedVars2(Object.keys(out));
4529
4600
  return out;
4530
4601
  }
4531
- var OpAuthError, cachedSdkAuth, sdkAuthResolved = false, authInFlight, testSeams, sniffed, opQueue, resolvedCache, globResolutions, globResolvedVars;
4602
+ var OpAuthError, cachedSdkAuth, sdkAuthResolved = false, authInFlight, testSeams, sniffed, opQueue, resolvedCache, globResolutions, globResolvedVars, environmentResolutions;
4532
4603
  var init_op_source = __esm(() => {
4533
4604
  init_onepassword_config();
4534
4605
  init_startup_trace();
@@ -4542,6 +4613,7 @@ var init_op_source = __esm(() => {
4542
4613
  resolvedCache = new Map;
4543
4614
  globResolutions = new Map;
4544
4615
  globResolvedVars = new Set;
4616
+ environmentResolutions = new Map;
4545
4617
  });
4546
4618
 
4547
4619
  // src/onepassword-command.ts
@@ -27508,6 +27580,9 @@ function loadConfig() {
27508
27580
  if (config2.defaultProvider !== undefined) {
27509
27581
  merged.defaultProvider = config2.defaultProvider;
27510
27582
  }
27583
+ if (config2.debug !== undefined) {
27584
+ merged.debug = config2.debug;
27585
+ }
27511
27586
  if (config2.customEndpoints !== undefined) {
27512
27587
  merged.customEndpoints = config2.customEndpoints;
27513
27588
  }
@@ -30829,8 +30904,24 @@ var init_all_models_cache = __esm(() => {
30829
30904
 
30830
30905
  // src/adapters/model-catalog.ts
30831
30906
  function lookupModel(modelId, cachePath) {
30907
+ const entry = findCacheEntry(modelId, cachePath);
30908
+ if (!entry || entry.contextWindow === undefined)
30909
+ return;
30910
+ return {
30911
+ modelId: entry.modelId,
30912
+ contextWindow: entry.contextWindow,
30913
+ supportsVision: entry.supportsVision
30914
+ };
30915
+ }
30916
+ function lookupModelForProvider(modelId, provider, cachePath) {
30917
+ const entry = findCacheEntry(modelId, cachePath);
30918
+ if (!entry)
30919
+ return;
30920
+ return entry.aggregators?.find((a) => a.provider === provider)?.contextWindow ?? entry.contextWindow;
30921
+ }
30922
+ function findCacheEntry(modelId, cachePath) {
30832
30923
  if (modelId.includes("@")) {
30833
- throw new Error(`lookupModel() received provider-routed ID "${modelId}" \u2014 callers must strip the "@" prefix before calling`);
30924
+ throw new Error(`model-catalog lookup received provider-routed ID "${modelId}" \u2014 callers must strip the "@" prefix before calling`);
30834
30925
  }
30835
30926
  const cache = readAllModelsCache(cachePath);
30836
30927
  if (!cache || cache.entries.length === 0)
@@ -30842,13 +30933,7 @@ function lookupModel(modelId, cachePath) {
30842
30933
  const exactMatch = entryId === unprefixed || entryId === lower;
30843
30934
  const aliasMatch = entry.aliases?.some((a) => a.toLowerCase() === unprefixed || a.toLowerCase() === lower);
30844
30935
  if (exactMatch || aliasMatch) {
30845
- if (entry.contextWindow === undefined)
30846
- return;
30847
- return {
30848
- modelId: entry.modelId,
30849
- contextWindow: entry.contextWindow,
30850
- supportsVision: entry.supportsVision
30851
- };
30936
+ return entry;
30852
30937
  }
30853
30938
  }
30854
30939
  return;
@@ -38382,9 +38467,20 @@ data: ${JSON.stringify(data)}
38382
38467
  const errMsg = err.message || event.message || "Unknown API error";
38383
38468
  const errCode = err.code || event.code || "";
38384
38469
  log(`[ResponsesSSE] API error: ${errCode} - ${errMsg}`);
38470
+ opts.onApiError?.(errCode, errMsg);
38385
38471
  closeReasoning();
38386
38472
  closeText();
38387
38473
  closeTools();
38474
+ const isCtxOverflow = errCode === "context_length_exceeded" || /context (length|window)|exceeds? the context|too long|maximum context/i.test(errMsg);
38475
+ let errorText = `
38476
+
38477
+ [API Error: ${errCode} ${errMsg}]`;
38478
+ if (isCtxOverflow) {
38479
+ const cap = opts.contextWindow && opts.contextWindow > 0 ? ` ~${Math.round(opts.contextWindow / 1000)}K tokens` : "";
38480
+ errorText = `
38481
+
38482
+ [Context limit reached] This model's backend enforces a smaller context window${cap} than its API spec. ` + "Run /clear to start fresh (/compact will also fail \u2014 it re-sends the full conversation), " + `or route the model via \`oai@${opts.modelName}\` to use the full-size window.`;
38483
+ }
38388
38484
  const errorIdx = curIdx++;
38389
38485
  send("content_block_start", {
38390
38486
  type: "content_block_start",
@@ -38394,9 +38490,7 @@ data: ${JSON.stringify(data)}
38394
38490
  send("content_block_delta", {
38395
38491
  type: "content_block_delta",
38396
38492
  index: errorIdx,
38397
- delta: { type: "text_delta", text: `
38398
-
38399
- [API Error: ${errCode} ${errMsg}]` }
38493
+ delta: { type: "text_delta", text: errorText }
38400
38494
  });
38401
38495
  send("content_block_stop", { type: "content_block_stop", index: errorIdx });
38402
38496
  send("message_delta", {
@@ -39075,6 +39169,7 @@ class ComposedHandler {
39075
39169
  }
39076
39170
  latencyMs = Math.round(performance.now() - startTime);
39077
39171
  const httpStatus = response.status;
39172
+ let streamApiError = null;
39078
39173
  const onStreamComplete = () => {
39079
39174
  try {
39080
39175
  const isFreeModel = this.tokenTracker.getTotalCost() === 0;
@@ -39083,7 +39178,7 @@ class ComposedHandler {
39083
39178
  provider_name: this.provider.name,
39084
39179
  stream_format: this.provider.streamFormat,
39085
39180
  latency_ms: latencyMs,
39086
- success: true,
39181
+ success: streamApiError === null,
39087
39182
  http_status: httpStatus,
39088
39183
  input_tokens: this.tokenTracker.getInputTokens(),
39089
39184
  output_tokens: this.tokenTracker.getOutputTokens(),
@@ -39099,9 +39194,11 @@ class ComposedHandler {
39099
39194
  });
39100
39195
  } catch {}
39101
39196
  };
39102
- return this.handleStream(c, response, adapter, claudeRequest, toolNameMap, onStreamComplete);
39197
+ return this.handleStream(c, response, adapter, claudeRequest, toolNameMap, onStreamComplete, (code, message) => {
39198
+ streamApiError = { code, message };
39199
+ });
39103
39200
  }
39104
- handleStream(c, response, adapter, claudeRequest, toolNameMap, onComplete) {
39201
+ handleStream(c, response, adapter, claudeRequest, toolNameMap, onComplete, onApiError) {
39105
39202
  let pendingOnComplete = onComplete;
39106
39203
  const onTokenUpdate = (input, output) => {
39107
39204
  const strategy = this.options.tokenStrategy || "standard";
@@ -39134,7 +39231,9 @@ class ComposedHandler {
39134
39231
  return createResponsesStreamHandler(c, response, {
39135
39232
  modelName: this.bareModelName,
39136
39233
  onTokenUpdate,
39137
- toolNameMap: adapter.getToolNameMap()
39234
+ toolNameMap: adapter.getToolNameMap(),
39235
+ contextWindow: lookupModelForProvider(this.bareModelName, this.provider.name),
39236
+ onApiError
39138
39237
  });
39139
39238
  case "anthropic-sse":
39140
39239
  return createAnthropicPassthroughStream(c, response, {
@@ -39237,6 +39336,7 @@ var init_composed_handler = __esm(() => {
39237
39336
  init_anthropic_sse();
39238
39337
  init_gemini_sse();
39239
39338
  init_ollama_jsonl();
39339
+ init_model_catalog();
39240
39340
  init_openai_responses_sse();
39241
39341
  init_openai_sse();
39242
39342
  init_token_tracker();
@@ -41872,6 +41972,7 @@ var init_ollamacloud = __esm(() => {
41872
41972
  var OpenAICodexTransport;
41873
41973
  var init_openai_codex = __esm(() => {
41874
41974
  init_codex_api_format();
41975
+ init_model_catalog();
41875
41976
  init_authority();
41876
41977
  init_openai();
41877
41978
  OpenAICodexTransport = class OpenAICodexTransport extends OpenAIProviderTransport {
@@ -41901,6 +42002,9 @@ var init_openai_codex = __esm(() => {
41901
42002
  }
41902
42003
  return this.cachedAuth?.transformPayload?.(normalizedPayload) ?? normalizedPayload;
41903
42004
  }
42005
+ getContextWindow() {
42006
+ return lookupModelForProvider(this.modelName, this.name) ?? 0;
42007
+ }
41904
42008
  };
41905
42009
  });
41906
42010
 
@@ -58600,7 +58704,8 @@ var init_config = __esm(() => {
58600
58704
  OPENAI_API_KEY: "OPENAI_API_KEY",
58601
58705
  OPENAI_BASE_URL: "OPENAI_BASE_URL",
58602
58706
  CLAUDISH_SUMMARIZE_TOOLS: "CLAUDISH_SUMMARIZE_TOOLS",
58603
- CLAUDISH_DIAG_MODE: "CLAUDISH_DIAG_MODE"
58707
+ CLAUDISH_DIAG_MODE: "CLAUDISH_DIAG_MODE",
58708
+ CLAUDISH_DEBUG: "CLAUDISH_DEBUG"
58604
58709
  };
58605
58710
  OPENROUTER_HEADERS = {
58606
58711
  "HTTP-Referer": "https://claudish.com",
@@ -62416,11 +62521,23 @@ async function parseArgs(args) {
62416
62521
  if (fileConfig.diagMode && ["auto", "logfile", "off"].includes(fileConfig.diagMode)) {
62417
62522
  config3.diagMode = fileConfig.diagMode;
62418
62523
  }
62524
+ if (fileConfig.debug === true) {
62525
+ config3.debug = true;
62526
+ }
62419
62527
  } catch {}
62420
62528
  const envDiagMode = process.env[ENV.CLAUDISH_DIAG_MODE]?.toLowerCase();
62421
62529
  if (envDiagMode && ["auto", "logfile", "off"].includes(envDiagMode)) {
62422
62530
  config3.diagMode = envDiagMode;
62423
62531
  }
62532
+ const envDebug = process.env[ENV.CLAUDISH_DEBUG]?.toLowerCase();
62533
+ if (envDebug === "1" || envDebug === "true") {
62534
+ config3.debug = true;
62535
+ } else if (envDebug === "0" || envDebug === "false") {
62536
+ config3.debug = false;
62537
+ }
62538
+ if (config3.debug && config3.logLevel === "info") {
62539
+ config3.logLevel = "debug";
62540
+ }
62424
62541
  let i = 0;
62425
62542
  while (i < args.length) {
62426
62543
  const arg = args[i];
@@ -62473,6 +62590,8 @@ async function parseArgs(args) {
62473
62590
  if (config3.logLevel === "info") {
62474
62591
  config3.logLevel = "debug";
62475
62592
  }
62593
+ } else if (arg === "--no-debug-claudish") {
62594
+ config3.debug = false;
62476
62595
  } else if (arg === "--log-debug") {
62477
62596
  console.error("--log-debug was renamed to --debug-claudish (it enables claudish's own debug log, not Claude Code's --debug).");
62478
62597
  process.exit(1);
@@ -63578,6 +63697,8 @@ ${h("OPTIONS")}
63578
63697
  ${green("--op-env")} ${yellow("<id>")} Load env vars from a 1Password Environment (highest priority)
63579
63698
  ${green("--port")} ${yellow("<port>")} Proxy server port (default: random)
63580
63699
  ${green("-d, --debug-claudish")} Enable claudish debug logging to file (logs/claudish_*.log)
63700
+ ${dim('Always-on: CLAUDISH_DEBUG=1 env var or "debug": true in config.json')}
63701
+ ${green("--no-debug-claudish")} Force debug logging off for this run (when globally enabled)
63581
63702
  ${green("--log-off")} Disable always-on structural logging (~/.claudish/logs/)
63582
63703
  ${green("--log-diag")} ${yellow("<mode>")} Diagnostic output: auto (default), logfile, off
63583
63704
  ${dim('Also: CLAUDISH_DIAG_MODE env var or "diagMode" in config.json')}
@@ -63741,6 +63862,7 @@ ${h("ENVIRONMENT VARIABLES")}
63741
63862
  ${blue("CLAUDISH_PORT")} Default proxy port
63742
63863
  ${blue("CLAUDISH_CONTEXT_WINDOW")} Override context window size
63743
63864
  ${blue("CLAUDISH_DIAG_MODE")} Diagnostic output: auto / logfile / off
63865
+ ${blue("CLAUDISH_DEBUG")} Always enable debug logging: 1 / true ${dim("(same as -d)")}
63744
63866
  ${blue("CLAUDISH_MCP_TOOLS")} MCP tool gating: all / low-level / agentic / channel
63745
63867
  ${blue("CLAUDISH_MODEL_OPUS")} Override model for Opus role
63746
63868
  ${blue("CLAUDISH_MODEL_SONNET")} Override model for Sonnet role
@@ -72215,7 +72337,6 @@ var init_team_grid = __esm(() => {
72215
72337
 
72216
72338
  // src/index.ts
72217
72339
  init_op_source();
72218
- init_onepassword_config();
72219
72340
  init_startup_trace();
72220
72341
  var import_dotenv3 = __toESM(require_main(), 1);
72221
72342
  import { readFileSync as readFileSync23 } from "fs";
@@ -72252,42 +72373,15 @@ process.on("exit", () => {
72252
72373
  });
72253
72374
  async function applyOpEnvironment() {
72254
72375
  const argv = process.argv.slice(2);
72255
- let flagEnvId;
72256
72376
  for (let i = 0;i < argv.length; i++) {
72257
72377
  const a = argv[i];
72258
- if (a === "--op-env") {
72259
- flagEnvId = argv[i + 1];
72260
- break;
72261
- }
72262
- if (a.startsWith("--op-env=")) {
72263
- flagEnvId = a.slice("--op-env=".length);
72264
- break;
72265
- }
72266
- }
72267
- if (flagEnvId !== undefined && (flagEnvId === "" || flagEnvId.startsWith("-"))) {
72268
- console.error("[claudish] --op-env requires a 1Password Environment ID");
72269
- process.exit(1);
72270
- }
72271
- const configEnvIds = readAllOnepasswordEnvironments();
72272
- const envIds = [...configEnvIds];
72273
- if (flagEnvId !== undefined && flagEnvId !== "")
72274
- envIds.push(flagEnvId);
72275
- if (envIds.length === 0)
72276
- return;
72277
- try {
72278
- const { readEnvironment: readEnvironment2, recordOpHydratedVars: recordOpHydratedVars2 } = await Promise.resolve().then(() => (init_onepassword(), exports_onepassword));
72279
- const auth = await resolveExplicitFlagAuth();
72280
- for (const envId of envIds) {
72281
- const vars = await readEnvironment2(envId, { auth });
72282
- for (const [key, value] of Object.entries(vars)) {
72283
- process.env[key] = value;
72284
- }
72285
- recordOpHydratedVars2(Object.keys(vars));
72378
+ if (a !== "--op-env" && !a.startsWith("--op-env="))
72379
+ continue;
72380
+ const val = a === "--op-env" ? argv[i + 1] : a.slice("--op-env=".length);
72381
+ if (val === undefined || val === "" || val.startsWith("-")) {
72382
+ console.error("[claudish] --op-env requires a 1Password Environment ID");
72383
+ process.exit(1);
72286
72384
  }
72287
- } catch (err) {
72288
- const message = err instanceof Error ? err.message : String(err);
72289
- console.error(`[claudish] 1Password Environment load failed: ${message}`);
72290
- process.exit(1);
72291
72385
  }
72292
72386
  }
72293
72387
  async function applyOpImport() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claudish",
3
- "version": "7.14.0",
3
+ "version": "7.16.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.14.0",
64
- "@claudish/magmux-darwin-x64": "7.14.0",
65
- "@claudish/magmux-linux-arm64": "7.14.0",
66
- "@claudish/magmux-linux-x64": "7.14.0"
63
+ "@claudish/magmux-darwin-arm64": "7.16.0",
64
+ "@claudish/magmux-darwin-x64": "7.16.0",
65
+ "@claudish/magmux-linux-arm64": "7.16.0",
66
+ "@claudish/magmux-linux-x64": "7.16.0"
67
67
  },
68
68
  "author": "Jack Rudenko <i@madappgang.com>",
69
69
  "license": "MIT",