claudish 7.15.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 +125 -52
  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.15.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
@@ -30832,8 +30904,24 @@ var init_all_models_cache = __esm(() => {
30832
30904
 
30833
30905
  // src/adapters/model-catalog.ts
30834
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) {
30835
30923
  if (modelId.includes("@")) {
30836
- 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`);
30837
30925
  }
30838
30926
  const cache = readAllModelsCache(cachePath);
30839
30927
  if (!cache || cache.entries.length === 0)
@@ -30845,13 +30933,7 @@ function lookupModel(modelId, cachePath) {
30845
30933
  const exactMatch = entryId === unprefixed || entryId === lower;
30846
30934
  const aliasMatch = entry.aliases?.some((a) => a.toLowerCase() === unprefixed || a.toLowerCase() === lower);
30847
30935
  if (exactMatch || aliasMatch) {
30848
- if (entry.contextWindow === undefined)
30849
- return;
30850
- return {
30851
- modelId: entry.modelId,
30852
- contextWindow: entry.contextWindow,
30853
- supportsVision: entry.supportsVision
30854
- };
30936
+ return entry;
30855
30937
  }
30856
30938
  }
30857
30939
  return;
@@ -38385,9 +38467,20 @@ data: ${JSON.stringify(data)}
38385
38467
  const errMsg = err.message || event.message || "Unknown API error";
38386
38468
  const errCode = err.code || event.code || "";
38387
38469
  log(`[ResponsesSSE] API error: ${errCode} - ${errMsg}`);
38470
+ opts.onApiError?.(errCode, errMsg);
38388
38471
  closeReasoning();
38389
38472
  closeText();
38390
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
+ }
38391
38484
  const errorIdx = curIdx++;
38392
38485
  send("content_block_start", {
38393
38486
  type: "content_block_start",
@@ -38397,9 +38490,7 @@ data: ${JSON.stringify(data)}
38397
38490
  send("content_block_delta", {
38398
38491
  type: "content_block_delta",
38399
38492
  index: errorIdx,
38400
- delta: { type: "text_delta", text: `
38401
-
38402
- [API Error: ${errCode} ${errMsg}]` }
38493
+ delta: { type: "text_delta", text: errorText }
38403
38494
  });
38404
38495
  send("content_block_stop", { type: "content_block_stop", index: errorIdx });
38405
38496
  send("message_delta", {
@@ -39078,6 +39169,7 @@ class ComposedHandler {
39078
39169
  }
39079
39170
  latencyMs = Math.round(performance.now() - startTime);
39080
39171
  const httpStatus = response.status;
39172
+ let streamApiError = null;
39081
39173
  const onStreamComplete = () => {
39082
39174
  try {
39083
39175
  const isFreeModel = this.tokenTracker.getTotalCost() === 0;
@@ -39086,7 +39178,7 @@ class ComposedHandler {
39086
39178
  provider_name: this.provider.name,
39087
39179
  stream_format: this.provider.streamFormat,
39088
39180
  latency_ms: latencyMs,
39089
- success: true,
39181
+ success: streamApiError === null,
39090
39182
  http_status: httpStatus,
39091
39183
  input_tokens: this.tokenTracker.getInputTokens(),
39092
39184
  output_tokens: this.tokenTracker.getOutputTokens(),
@@ -39102,9 +39194,11 @@ class ComposedHandler {
39102
39194
  });
39103
39195
  } catch {}
39104
39196
  };
39105
- 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
+ });
39106
39200
  }
39107
- handleStream(c, response, adapter, claudeRequest, toolNameMap, onComplete) {
39201
+ handleStream(c, response, adapter, claudeRequest, toolNameMap, onComplete, onApiError) {
39108
39202
  let pendingOnComplete = onComplete;
39109
39203
  const onTokenUpdate = (input, output) => {
39110
39204
  const strategy = this.options.tokenStrategy || "standard";
@@ -39137,7 +39231,9 @@ class ComposedHandler {
39137
39231
  return createResponsesStreamHandler(c, response, {
39138
39232
  modelName: this.bareModelName,
39139
39233
  onTokenUpdate,
39140
- toolNameMap: adapter.getToolNameMap()
39234
+ toolNameMap: adapter.getToolNameMap(),
39235
+ contextWindow: lookupModelForProvider(this.bareModelName, this.provider.name),
39236
+ onApiError
39141
39237
  });
39142
39238
  case "anthropic-sse":
39143
39239
  return createAnthropicPassthroughStream(c, response, {
@@ -39240,6 +39336,7 @@ var init_composed_handler = __esm(() => {
39240
39336
  init_anthropic_sse();
39241
39337
  init_gemini_sse();
39242
39338
  init_ollama_jsonl();
39339
+ init_model_catalog();
39243
39340
  init_openai_responses_sse();
39244
39341
  init_openai_sse();
39245
39342
  init_token_tracker();
@@ -41875,6 +41972,7 @@ var init_ollamacloud = __esm(() => {
41875
41972
  var OpenAICodexTransport;
41876
41973
  var init_openai_codex = __esm(() => {
41877
41974
  init_codex_api_format();
41975
+ init_model_catalog();
41878
41976
  init_authority();
41879
41977
  init_openai();
41880
41978
  OpenAICodexTransport = class OpenAICodexTransport extends OpenAIProviderTransport {
@@ -41904,6 +42002,9 @@ var init_openai_codex = __esm(() => {
41904
42002
  }
41905
42003
  return this.cachedAuth?.transformPayload?.(normalizedPayload) ?? normalizedPayload;
41906
42004
  }
42005
+ getContextWindow() {
42006
+ return lookupModelForProvider(this.modelName, this.name) ?? 0;
42007
+ }
41907
42008
  };
41908
42009
  });
41909
42010
 
@@ -72236,7 +72337,6 @@ var init_team_grid = __esm(() => {
72236
72337
 
72237
72338
  // src/index.ts
72238
72339
  init_op_source();
72239
- init_onepassword_config();
72240
72340
  init_startup_trace();
72241
72341
  var import_dotenv3 = __toESM(require_main(), 1);
72242
72342
  import { readFileSync as readFileSync23 } from "fs";
@@ -72273,42 +72373,15 @@ process.on("exit", () => {
72273
72373
  });
72274
72374
  async function applyOpEnvironment() {
72275
72375
  const argv = process.argv.slice(2);
72276
- let flagEnvId;
72277
72376
  for (let i = 0;i < argv.length; i++) {
72278
72377
  const a = argv[i];
72279
- if (a === "--op-env") {
72280
- flagEnvId = argv[i + 1];
72281
- break;
72282
- }
72283
- if (a.startsWith("--op-env=")) {
72284
- flagEnvId = a.slice("--op-env=".length);
72285
- break;
72286
- }
72287
- }
72288
- if (flagEnvId !== undefined && (flagEnvId === "" || flagEnvId.startsWith("-"))) {
72289
- console.error("[claudish] --op-env requires a 1Password Environment ID");
72290
- process.exit(1);
72291
- }
72292
- const configEnvIds = readAllOnepasswordEnvironments();
72293
- const envIds = [...configEnvIds];
72294
- if (flagEnvId !== undefined && flagEnvId !== "")
72295
- envIds.push(flagEnvId);
72296
- if (envIds.length === 0)
72297
- return;
72298
- try {
72299
- const { readEnvironment: readEnvironment2, recordOpHydratedVars: recordOpHydratedVars2 } = await Promise.resolve().then(() => (init_onepassword(), exports_onepassword));
72300
- const auth = await resolveExplicitFlagAuth();
72301
- for (const envId of envIds) {
72302
- const vars = await readEnvironment2(envId, { auth });
72303
- for (const [key, value] of Object.entries(vars)) {
72304
- process.env[key] = value;
72305
- }
72306
- 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);
72307
72384
  }
72308
- } catch (err) {
72309
- const message = err instanceof Error ? err.message : String(err);
72310
- console.error(`[claudish] 1Password Environment load failed: ${message}`);
72311
- process.exit(1);
72312
72385
  }
72313
72386
  }
72314
72387
  async function applyOpImport() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claudish",
3
- "version": "7.15.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.15.0",
64
- "@claudish/magmux-darwin-x64": "7.15.0",
65
- "@claudish/magmux-linux-arm64": "7.15.0",
66
- "@claudish/magmux-linux-x64": "7.15.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",