claudish 7.36.0 → 7.37.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 +291 -130
  2. package/package.json +5 -5
package/dist/index.js CHANGED
@@ -523,6 +523,68 @@ function scanConfigFlag(argv) {
523
523
  }
524
524
  var SUPPRESSED_PROJECT_CONFIG = "", overridePath = null;
525
525
 
526
+ // src/providers/op-source-entry.ts
527
+ function trimmed(v) {
528
+ return typeof v === "string" && v.trim() ? v.trim() : undefined;
529
+ }
530
+ function parseOpSourceEntry(raw, valueKey) {
531
+ const bare = trimmed(raw);
532
+ if (bare)
533
+ return { value: bare };
534
+ if (!raw || typeof raw !== "object" || Array.isArray(raw))
535
+ return;
536
+ const obj = raw;
537
+ const value = trimmed(obj[valueKey]);
538
+ if (!value)
539
+ return;
540
+ const account = trimmed(obj.account);
541
+ return account ? { value, account } : { value };
542
+ }
543
+ function parseOpSourceEntries(raw, valueKey) {
544
+ if (!Array.isArray(raw))
545
+ return [];
546
+ const out = [];
547
+ for (const item of raw) {
548
+ const parsed = parseOpSourceEntry(item, valueKey);
549
+ if (parsed)
550
+ out.push(parsed);
551
+ }
552
+ return out;
553
+ }
554
+ function serializeOpSourceEntry(entry, valueKey) {
555
+ if (!entry.account)
556
+ return entry.value;
557
+ return { [valueKey]: entry.value, account: entry.account };
558
+ }
559
+ function dedupeOpSourceEntries(entries) {
560
+ const seen = new Set;
561
+ const out = [];
562
+ for (const e of entries) {
563
+ if (seen.has(e.value))
564
+ continue;
565
+ seen.add(e.value);
566
+ out.push(e);
567
+ }
568
+ return out;
569
+ }
570
+ function groupEntriesByAccount(entries, resolveAccount) {
571
+ const byAccount = new Map;
572
+ const undeclared = [];
573
+ for (const entry of entries) {
574
+ const account = resolveAccount(entry);
575
+ if (!account) {
576
+ undeclared.push(entry);
577
+ continue;
578
+ }
579
+ const bucket = byAccount.get(account);
580
+ if (bucket)
581
+ bucket.push(entry);
582
+ else
583
+ byAccount.set(account, [entry]);
584
+ }
585
+ return { byAccount, undeclared };
586
+ }
587
+
526
588
  // src/providers/onepassword-config.ts
527
589
  import { existsSync, readFileSync, writeFileSync } from "fs";
528
590
  import { homedir } from "os";
@@ -580,60 +642,76 @@ function clearOnepasswordAccount(scope, paths = defaultOpConfigPaths) {
580
642
  }
581
643
  function readStringList(scope, key, paths) {
582
644
  const cfg = readRawConfig(pathFor(scope, paths));
583
- const raw = cfg[key];
584
- if (!Array.isArray(raw))
585
- return [];
586
- return raw.filter((v) => typeof v === "string");
645
+ const valueKey = key === "onepassword" ? "ref" : "id";
646
+ return parseOpSourceEntries(cfg[key], valueKey).map((e) => e.value);
587
647
  }
588
- function addToStringList(scope, key, entry, paths) {
648
+ function addToStringList(scope, key, entry, paths, account) {
589
649
  const value = entry.trim();
590
650
  if (!value)
591
651
  return;
652
+ const valueKey = key === "onepassword" ? "ref" : "id";
653
+ const declared = account?.trim();
592
654
  mutateConfig(scope, paths, (cfg) => {
593
- const list = Array.isArray(cfg[key]) ? cfg[key].filter((v) => typeof v === "string") : [];
594
- if (!list.includes(value))
595
- list.push(value);
596
- cfg[key] = list;
655
+ const existing = parseOpSourceEntries(cfg[key], valueKey);
656
+ const match = existing.find((e) => e.value === value);
657
+ if (match) {
658
+ if (declared && !match.account)
659
+ match.account = declared;
660
+ } else {
661
+ existing.push(declared ? { value, account: declared } : { value });
662
+ }
663
+ cfg[key] = existing.map((e) => serializeOpSourceEntry(e, valueKey));
597
664
  });
598
665
  }
599
666
  function removeFromStringList(scope, key, entry, paths) {
600
667
  const value = entry.trim();
668
+ if (!value)
669
+ return;
670
+ const valueKey = key === "onepassword" ? "ref" : "id";
601
671
  mutateConfig(scope, paths, (cfg) => {
602
- const list = Array.isArray(cfg[key]) ? cfg[key].filter((v) => typeof v === "string") : [];
603
- const next = list.filter((v) => v !== value);
604
- if (next.length === 0)
672
+ const kept = parseOpSourceEntries(cfg[key], valueKey).filter((e) => e.value !== value);
673
+ if (kept.length === 0)
605
674
  delete cfg[key];
606
675
  else
607
- cfg[key] = next;
676
+ cfg[key] = kept.map((e) => serializeOpSourceEntry(e, valueKey));
608
677
  });
609
678
  }
610
679
  function listOnepasswordImports(scope, paths = defaultOpConfigPaths) {
611
680
  return readStringList(scope, "onepassword", paths);
612
681
  }
613
- function addOnepasswordImport(entry, scope, paths = defaultOpConfigPaths) {
614
- addToStringList(scope, "onepassword", entry, paths);
682
+ function addOnepasswordImport(entry, scope, paths = defaultOpConfigPaths, account) {
683
+ addToStringList(scope, "onepassword", entry, paths, account);
615
684
  }
616
685
  function removeOnepasswordImport(entry, scope, paths = defaultOpConfigPaths) {
617
686
  removeFromStringList(scope, "onepassword", entry, paths);
618
687
  }
688
+ function readEntryList(scope, key, valueKey, paths) {
689
+ const cfg = readRawConfig(pathFor(scope, paths));
690
+ return parseOpSourceEntries(cfg[key], valueKey);
691
+ }
692
+ function listOnepasswordImportEntries(scope, paths = defaultOpConfigPaths) {
693
+ return readEntryList(scope, "onepassword", "ref", paths);
694
+ }
695
+ function listOnepasswordEnvironmentEntries(scope, paths = defaultOpConfigPaths) {
696
+ return readEntryList(scope, "onepasswordEnvironments", "id", paths);
697
+ }
698
+ function readAllOnepasswordEnvironmentEntries(paths = defaultOpConfigPaths) {
699
+ return dedupeOpSourceEntries([
700
+ ...listOnepasswordEnvironmentEntries("project", paths),
701
+ ...listOnepasswordEnvironmentEntries("global", paths)
702
+ ]);
703
+ }
704
+ function readAllOnepasswordImportEntries(paths = defaultOpConfigPaths) {
705
+ return dedupeOpSourceEntries([
706
+ ...listOnepasswordImportEntries("project", paths),
707
+ ...listOnepasswordImportEntries("global", paths)
708
+ ]);
709
+ }
619
710
  function listOnepasswordEnvironments(scope, paths = defaultOpConfigPaths) {
620
711
  return readStringList(scope, "onepasswordEnvironments", paths);
621
712
  }
622
- function readAllOnepasswordEnvironments(paths = defaultOpConfigPaths) {
623
- const project = listOnepasswordEnvironments("project", paths);
624
- const global2 = listOnepasswordEnvironments("global", paths);
625
- const seen = new Set(project);
626
- const out = [...project];
627
- for (const id of global2) {
628
- if (!seen.has(id)) {
629
- seen.add(id);
630
- out.push(id);
631
- }
632
- }
633
- return out;
634
- }
635
- function addOnepasswordEnvironment(id, scope, paths = defaultOpConfigPaths) {
636
- addToStringList(scope, "onepasswordEnvironments", id, paths);
713
+ function addOnepasswordEnvironment(id, scope, paths = defaultOpConfigPaths, account) {
714
+ addToStringList(scope, "onepasswordEnvironments", id, paths, account);
637
715
  }
638
716
  function removeOnepasswordEnvironment(id, scope, paths = defaultOpConfigPaths) {
639
717
  removeFromStringList(scope, "onepasswordEnvironments", id, paths);
@@ -651,7 +729,7 @@ var init_onepassword_config = __esm(() => {
651
729
  });
652
730
 
653
731
  // src/version.ts
654
- var VERSION = "7.36.0";
732
+ var VERSION = "7.37.0";
655
733
 
656
734
  // src/logger.ts
657
735
  var exports_logger = {};
@@ -3856,7 +3934,6 @@ __export(exports_onepassword, {
3856
3934
  detectSdkAuth: () => detectSdkAuth,
3857
3935
  defaultSdkClientFactory: () => defaultSdkClientFactory,
3858
3936
  defaultScreenLockProbe: () => defaultScreenLockProbe,
3859
- defaultOpDefaultAccountProbe: () => defaultOpDefaultAccountProbe,
3860
3937
  defaultOpAccountLister: () => defaultOpAccountLister,
3861
3938
  defaultAppLockProbe: () => defaultAppLockProbe,
3862
3939
  currentLockCause: () => currentLockCause,
@@ -4193,25 +4270,25 @@ function collectApiKeyRefs(apiKeys, env, opRefs) {
4193
4270
  function collectOnepasswordEntry(entry, env, opRefs, globImports, warnings) {
4194
4271
  if (typeof entry !== "string")
4195
4272
  return;
4196
- const trimmed = entry.trim();
4197
- if (trimmed === "")
4273
+ const trimmed2 = entry.trim();
4274
+ if (trimmed2 === "")
4198
4275
  return;
4199
- if (isGlobImport(trimmed)) {
4200
- globImports.push(trimmed);
4276
+ if (isGlobImport(trimmed2)) {
4277
+ globImports.push(trimmed2);
4201
4278
  return;
4202
4279
  }
4203
- if (trimmed.startsWith("op://")) {
4204
- const name = envNameFromOpRef(trimmed);
4280
+ if (trimmed2.startsWith("op://")) {
4281
+ const name = envNameFromOpRef(trimmed2);
4205
4282
  if (name === null) {
4206
- warnings.push(`[claudish] skipped 1Password ref '${trimmed}' from onepassword[] (its trailing field label is not a valid env var name)`);
4283
+ warnings.push(`[claudish] skipped 1Password ref '${trimmed2}' from onepassword[] (its trailing field label is not a valid env var name)`);
4207
4284
  return;
4208
4285
  }
4209
4286
  if (!env[name]) {
4210
- opRefs[name] = trimmed;
4287
+ opRefs[name] = trimmed2;
4211
4288
  }
4212
4289
  return;
4213
4290
  }
4214
- warnings.push(`[claudish] skipped 1Password entry '${trimmed}' from onepassword[] (not a glob import or op:// reference)`);
4291
+ warnings.push(`[claudish] skipped 1Password entry '${trimmed2}' from onepassword[] (not a glob import or op:// reference)`);
4215
4292
  }
4216
4293
  function parseOpFlag(argv) {
4217
4294
  let glob;
@@ -4444,17 +4521,10 @@ function resolveDesktopAccount(opts = {}) {
4444
4521
  if (opts.interactive) {
4445
4522
  return { needsPicker: accounts };
4446
4523
  }
4447
- const probe = opts.opDefaultAccountProbe ?? defaultOpDefaultAccountProbe;
4448
- const defaultUuid = probe();
4449
- if (defaultUuid) {
4450
- const match = accounts.find((a) => a.account_uuid === defaultUuid);
4451
- if (match)
4452
- return { accountName: match.url };
4453
- }
4454
4524
  const listing = accounts.map((a) => ` - ${a.url}${a.email ? ` (${a.email})` : ""}`).join(`
4455
4525
  `);
4456
4526
  return {
4457
- error: `Multiple 1Password accounts are available, this is a non-interactive session, and \`op\` could not name a default account. ${remediation}
4527
+ error: `Multiple 1Password accounts are available and none is configured, so claudish cannot tell which one holds your keys. ${remediation}
4458
4528
  Accounts:
4459
4529
  ${listing}`
4460
4530
  };
@@ -4468,8 +4538,7 @@ async function resolveSdkAuth(opts = {}) {
4468
4538
  env,
4469
4539
  configAccount: opts.configAccount,
4470
4540
  interactive: opts.interactive,
4471
- opAccountLister: opts.opAccountLister,
4472
- opDefaultAccountProbe: opts.opDefaultAccountProbe
4541
+ opAccountLister: opts.opAccountLister
4473
4542
  });
4474
4543
  if ("accountName" in result) {
4475
4544
  return { kind: "desktop", accountName: result.accountName };
@@ -4613,7 +4682,7 @@ var OP_REF_RE, opHydratedVars, opSourceFailures, ENV_VAR_NAME_RE, sdkClientCache
4613
4682
  }
4614
4683
  }, screenLockProbe, defaultAppLockProbe = () => false, appLockProbe, OP_PROBE_TIMEOUT_MS = 5000, defaultOpAccountLister = () => {
4615
4684
  try {
4616
- const res = spawnSync("op", ["account", "list", "--format=json"], {
4685
+ const res = spawnSync("op", ["--cache=false", "account", "list", "--format=json"], {
4617
4686
  encoding: "utf-8",
4618
4687
  timeout: OP_PROBE_TIMEOUT_MS
4619
4688
  });
@@ -4640,19 +4709,6 @@ var OP_REF_RE, opHydratedVars, opSourceFailures, ENV_VAR_NAME_RE, sdkClientCache
4640
4709
  } catch {
4641
4710
  return null;
4642
4711
  }
4643
- }, defaultOpDefaultAccountProbe = () => {
4644
- try {
4645
- const res = spawnSync("op", ["account", "get", "--format=json"], {
4646
- encoding: "utf-8",
4647
- timeout: OP_PROBE_TIMEOUT_MS
4648
- });
4649
- if (res.error || res.status !== 0)
4650
- return null;
4651
- const parsed = JSON.parse(res.stdout ?? "");
4652
- return typeof parsed.id === "string" && parsed.id ? parsed.id : null;
4653
- } catch {
4654
- return null;
4655
- }
4656
4712
  };
4657
4713
  var init_onepassword = __esm(() => {
4658
4714
  init_env_placeholder();
@@ -4740,8 +4796,11 @@ async function pickOnepasswordAccount(accounts) {
4740
4796
  return accounts[idx - 1].url;
4741
4797
  }
4742
4798
  async function getSdkAuth(allowPrompt) {
4743
- if (sdkAuthResolved)
4799
+ if (sdkAuthResolved) {
4800
+ if (cachedAuthError)
4801
+ throw cachedAuthError;
4744
4802
  return cachedSdkAuth;
4803
+ }
4745
4804
  if (authInFlight)
4746
4805
  return authInFlight;
4747
4806
  authInFlight = (async () => {
@@ -4765,13 +4824,25 @@ async function getSdkAuth(allowPrompt) {
4765
4824
  return auth;
4766
4825
  } catch (err) {
4767
4826
  const message = err instanceof Error ? err.message : String(err);
4768
- throw new OpAuthError(message);
4827
+ cachedAuthError = new OpAuthError(message);
4828
+ sdkAuthResolved = true;
4829
+ throw cachedAuthError;
4769
4830
  } finally {
4770
4831
  authInFlight = undefined;
4771
4832
  }
4772
4833
  })();
4773
4834
  return authInFlight;
4774
4835
  }
4836
+ async function authForEntry(entry, allowPrompt) {
4837
+ const token = process.env.OP_SERVICE_ACCOUNT_TOKEN?.trim();
4838
+ if (token)
4839
+ return { kind: "token", token };
4840
+ if (entry.account)
4841
+ return { kind: "desktop", accountName: entry.account };
4842
+ if (testSeams?.auth)
4843
+ return testSeams.auth;
4844
+ return getSdkAuth(allowPrompt);
4845
+ }
4775
4846
  function resolveExplicitFlagAuth() {
4776
4847
  return getSdkAuth(true);
4777
4848
  }
@@ -4863,12 +4934,27 @@ function flagEnvironmentIds() {
4863
4934
  return ids;
4864
4935
  }
4865
4936
  function configEnvironmentIds() {
4866
- if (testSeams?.config)
4867
- return testSeams.config.onepasswordEnvironments ?? [];
4868
- return readAllOnepasswordEnvironments();
4937
+ return configEnvironmentEntries().map((e) => e.value);
4938
+ }
4939
+ function configEnvironmentEntries() {
4940
+ if (testSeams?.config) {
4941
+ return parseOpSourceEntries(testSeams.config.onepasswordEnvironments ?? [], "id");
4942
+ }
4943
+ return readAllOnepasswordEnvironmentEntries();
4869
4944
  }
4870
- function registeredEnvironmentIds() {
4871
- return [...new Set([...configEnvironmentIds(), ...flagEnvironmentIds()])];
4945
+ function registeredEnvironmentEntries() {
4946
+ const seen = new Set;
4947
+ const out = [];
4948
+ for (const entry of [
4949
+ ...configEnvironmentEntries(),
4950
+ ...flagEnvironmentIds().map((value) => ({ value }))
4951
+ ]) {
4952
+ if (seen.has(entry.value))
4953
+ continue;
4954
+ seen.add(entry.value);
4955
+ out.push(entry);
4956
+ }
4957
+ return out;
4872
4958
  }
4873
4959
  function maskGlobForTrace(globPath) {
4874
4960
  const body = globPath.startsWith("op://") ? globPath.slice("op://".length) : globPath;
@@ -4980,6 +5066,34 @@ async function resolveOpKeyForEnvVars(wanted, opts = {}) {
4980
5066
  return out;
4981
5067
  }, label);
4982
5068
  }
5069
+ function hasNonEnvironmentOpSources() {
5070
+ const cfg = testSeams?.config ?? readConfigRaw();
5071
+ if (cfg.apiKeys) {
5072
+ for (const v of Object.values(cfg.apiKeys)) {
5073
+ if (typeof v === "string" && v.startsWith("op://"))
5074
+ return true;
5075
+ }
5076
+ }
5077
+ if (Array.isArray(cfg.onepassword) && cfg.onepassword.length > 0)
5078
+ return true;
5079
+ if (cfg.customEndpoints && typeof cfg.customEndpoints === "object") {
5080
+ for (const raw of Object.values(cfg.customEndpoints)) {
5081
+ if (raw && typeof raw === "object") {
5082
+ const apiKey = raw.apiKey;
5083
+ if (typeof apiKey === "string" && apiKey.startsWith("op://"))
5084
+ return true;
5085
+ }
5086
+ }
5087
+ }
5088
+ return false;
5089
+ }
5090
+ function importAccountLookup() {
5091
+ const entries = testSeams?.config ? parseOpSourceEntries(testSeams.config.onepassword ?? [], "ref") : readAllOnepasswordImportEntries();
5092
+ const out = new Map;
5093
+ for (const e of entries)
5094
+ out.set(e.value, e.account);
5095
+ return out;
5096
+ }
4983
5097
  async function resolveOpKeyForEnvVarsInner(wanted, opts = {}, span) {
4984
5098
  if (wanted.size === 0)
4985
5099
  return {};
@@ -4987,20 +5101,35 @@ async function resolveOpKeyForEnvVarsInner(wanted, opts = {}, span) {
4987
5101
  return {};
4988
5102
  const onAuthFailure = opts.onAuthFailure ?? "skip";
4989
5103
  const allowPrompt = opts.allowPrompt ?? false;
5104
+ let ambientFailure;
5105
+ const ambientAuth = async () => {
5106
+ if (testSeams?.auth)
5107
+ return testSeams.auth;
5108
+ if (ambientFailure)
5109
+ throw ambientFailure;
5110
+ try {
5111
+ return await getSdkAuth(allowPrompt);
5112
+ } catch (err) {
5113
+ if (err instanceof OpAuthError)
5114
+ ambientFailure = err;
5115
+ throw err;
5116
+ }
5117
+ };
5118
+ const reportAuthFailure = async (err) => {
5119
+ if (!(err instanceof OpAuthError) || onAuthFailure !== "skip")
5120
+ throw err;
5121
+ warnOnce(`[claudish] 1Password auth unavailable, skipping op:// keys: ${err.message}`);
5122
+ const { recordOpFailure: recordOpFailure3 } = await Promise.resolve().then(() => (init_onepassword(), exports_onepassword));
5123
+ recordOpFailure3({ kind: "auth", message: err.message });
5124
+ };
4990
5125
  let auth;
4991
5126
  if (testSeams?.auth) {
4992
5127
  auth = testSeams.auth;
4993
- } else {
5128
+ } else if (hasNonEnvironmentOpSources()) {
4994
5129
  try {
4995
- auth = await getSdkAuth(allowPrompt);
5130
+ auth = await ambientAuth();
4996
5131
  } catch (err) {
4997
- if (err instanceof OpAuthError && onAuthFailure === "skip") {
4998
- warnOnce(`[claudish] 1Password auth unavailable, skipping op:// keys: ${err.message}`);
4999
- const { recordOpFailure: recordOpFailure3 } = await Promise.resolve().then(() => (init_onepassword(), exports_onepassword));
5000
- recordOpFailure3({ kind: "auth", message: err.message });
5001
- return {};
5002
- }
5003
- throw err;
5132
+ await reportAuthFailure(err);
5004
5133
  }
5005
5134
  }
5006
5135
  const {
@@ -5013,7 +5142,11 @@ async function resolveOpKeyForEnvVarsInner(wanted, opts = {}, span) {
5013
5142
  const cfg = readConfigRaw();
5014
5143
  const out = {};
5015
5144
  try {
5016
- const collected = collectConfigImports2({ apiKeys: cfg.apiKeys, onepassword: cfg.onepassword }, process.env);
5145
+ const importAccounts = importAccountLookup();
5146
+ const collected = collectConfigImports2({
5147
+ apiKeys: cfg.apiKeys,
5148
+ onepassword: parseOpSourceEntries(cfg.onepassword ?? [], "ref").map((e) => e.value)
5149
+ }, process.env);
5017
5150
  for (const w of collected.warnings)
5018
5151
  console.error(w);
5019
5152
  const wantedRefs = {};
@@ -5022,15 +5155,38 @@ async function resolveOpKeyForEnvVarsInner(wanted, opts = {}, span) {
5022
5155
  wantedRefs[envVar] = ref;
5023
5156
  }
5024
5157
  if (Object.keys(wantedRefs).length > 0) {
5025
- const resolved = await withSdkRetry2(() => resolveSecrets2(wantedRefs, { auth, sdkFactory: testSeams?.sdkFactory }), "op:resolve-refs");
5026
- Object.assign(out, resolved);
5158
+ const refEntries = Object.entries(wantedRefs).map(([envVar, ref]) => ({
5159
+ value: envVar,
5160
+ ...importAccounts.get(ref) ? { account: importAccounts.get(ref) } : {}
5161
+ }));
5162
+ const { byAccount, undeclared } = groupEntriesByAccount(refEntries, (e) => e.account);
5163
+ const batches = [];
5164
+ for (const [account, entries] of byAccount) {
5165
+ batches.push({
5166
+ auth: { kind: "desktop", accountName: account },
5167
+ names: entries.map((e) => e.value)
5168
+ });
5169
+ }
5170
+ if (undeclared.length > 0)
5171
+ batches.push({ auth, names: undeclared.map((e) => e.value) });
5172
+ for (const batch of batches) {
5173
+ const refs = {};
5174
+ for (const n of batch.names)
5175
+ refs[n] = wantedRefs[n];
5176
+ const resolved = await withSdkRetry2(() => resolveSecrets2(refs, { auth: batch.auth, sdkFactory: testSeams?.sdkFactory }), "op:resolve-refs");
5177
+ Object.assign(out, resolved);
5178
+ }
5027
5179
  }
5028
5180
  const stillWanted = new Set([...wanted].filter((w) => !(w in out)));
5029
5181
  for (const globPath of collected.globImports) {
5030
5182
  if (stillWanted.size === 0)
5031
5183
  break;
5032
5184
  try {
5033
- const { resolved, cacheHit } = await resolveGlobShared(globPath, auth);
5185
+ const globAuth = await authForEntry({
5186
+ value: globPath,
5187
+ ...importAccounts.get(globPath) ? { account: importAccounts.get(globPath) } : {}
5188
+ }, allowPrompt);
5189
+ const { resolved, cacheHit } = await resolveGlobShared(globPath, globAuth);
5034
5190
  if (cacheHit)
5035
5191
  span?.addMeta({ globCacheHit: true });
5036
5192
  for (const w of [...stillWanted]) {
@@ -5065,11 +5221,13 @@ async function resolveOpKeyForEnvVarsInner(wanted, opts = {}, span) {
5065
5221
  }
5066
5222
  const stillWantedEnv = new Set([...wanted].filter((w) => !(w in out)));
5067
5223
  if (stillWantedEnv.size > 0) {
5068
- for (const envId of registeredEnvironmentIds()) {
5224
+ for (const envEntry of registeredEnvironmentEntries()) {
5069
5225
  if (stillWantedEnv.size === 0)
5070
5226
  break;
5227
+ const envId = envEntry.value;
5071
5228
  try {
5072
- const { resolved, cacheHit } = await resolveEnvironmentShared(envId, auth);
5229
+ const envAuth = await authForEntry(envEntry, allowPrompt);
5230
+ const { resolved, cacheHit } = await resolveEnvironmentShared(envId, envAuth);
5073
5231
  if (cacheHit)
5074
5232
  span?.addMeta({ globCacheHit: true });
5075
5233
  for (const w of [...stillWantedEnv]) {
@@ -5102,7 +5260,7 @@ async function resolveOpKeyForEnvVarsInner(wanted, opts = {}, span) {
5102
5260
  recordOpHydratedVars2(Object.keys(out));
5103
5261
  return out;
5104
5262
  }
5105
- var warnedMessages, opUnavailableVars, OP_UNAVAILABLE_ENV = "CLAUDISH_OP_UNAVAILABLE", OpAuthError, cachedSdkAuth, sdkAuthResolved = false, authInFlight, testSeams, sniffed, opQueue, resolvedCache, globResolutions, globResolvedVars, environmentResolutions;
5263
+ var warnedMessages, opUnavailableVars, OP_UNAVAILABLE_ENV = "CLAUDISH_OP_UNAVAILABLE", OpAuthError, cachedSdkAuth, cachedAuthError, sdkAuthResolved = false, authInFlight, testSeams, sniffed, opQueue, resolvedCache, globResolutions, globResolvedVars, environmentResolutions;
5106
5264
  var init_op_source = __esm(() => {
5107
5265
  init_onepassword_config();
5108
5266
  init_startup_trace();
@@ -5174,8 +5332,8 @@ async function opPreviewCommand(globPath, opts = {}) {
5174
5332
  continue;
5175
5333
  }
5176
5334
  importable++;
5177
- const trimmed = m.field.label !== m.envName;
5178
- const detail = trimmed ? `(trimmed from '${m.field.label}')` : m.field.section ? `(section: ${m.field.section})` : "(top-level field)";
5335
+ const trimmed2 = m.field.label !== m.envName;
5336
+ const detail = trimmed2 ? `(trimmed from '${m.field.label}')` : m.field.section ? `(section: ${m.field.section})` : "(top-level field)";
5179
5337
  console.log(` ${name} \u2713 ${detail}`);
5180
5338
  }
5181
5339
  console.log(`${importable} importable, ${skipped} skipped`);
@@ -7359,8 +7517,8 @@ var init_schemas = __esm(() => {
7359
7517
  $ZodStringFormat.init(inst, def);
7360
7518
  inst._zod.check = (payload) => {
7361
7519
  try {
7362
- const trimmed = payload.value.trim();
7363
- const url = new URL(trimmed);
7520
+ const trimmed2 = payload.value.trim();
7521
+ const url = new URL(trimmed2);
7364
7522
  if (def.hostname) {
7365
7523
  def.hostname.lastIndex = 0;
7366
7524
  if (!def.hostname.test(url.hostname)) {
@@ -7392,7 +7550,7 @@ var init_schemas = __esm(() => {
7392
7550
  if (def.normalize) {
7393
7551
  payload.value = url.href;
7394
7552
  } else {
7395
- payload.value = trimmed;
7553
+ payload.value = trimmed2;
7396
7554
  }
7397
7555
  return;
7398
7556
  } catch (_) {
@@ -28358,8 +28516,8 @@ function defaultReadStore() {
28358
28516
  }
28359
28517
  try {
28360
28518
  const out = execFileSync("security", ["find-generic-password", "-s", KC_SERVICE, "-a", KC_ACCOUNT, "-w"], { encoding: "utf8" });
28361
- const trimmed = out.trim();
28362
- return trimmed.length > 0 ? trimmed : null;
28519
+ const trimmed2 = out.trim();
28520
+ return trimmed2.length > 0 ? trimmed2 : null;
28363
28521
  } catch {
28364
28522
  return null;
28365
28523
  }
@@ -37257,24 +37415,24 @@ CRITICAL INSTRUCTION FOR OUTPUT FORMAT:
37257
37415
  const cleanedLines = [];
37258
37416
  let wasFiltered = false;
37259
37417
  for (const line of lines) {
37260
- const trimmed = line.trim();
37261
- if (!trimmed) {
37418
+ const trimmed2 = line.trim();
37419
+ if (!trimmed2) {
37262
37420
  cleanedLines.push(line);
37263
37421
  continue;
37264
37422
  }
37265
- if (this.isReasoningLine(trimmed)) {
37266
- log(`[GeminiAPIFormat] Filtered reasoning: "${trimmed.substring(0, 50)}..."`);
37423
+ if (this.isReasoningLine(trimmed2)) {
37424
+ log(`[GeminiAPIFormat] Filtered reasoning: "${trimmed2.substring(0, 50)}..."`);
37267
37425
  wasFiltered = true;
37268
37426
  this.inReasoningBlock = true;
37269
37427
  this.reasoningBlockDepth++;
37270
37428
  continue;
37271
37429
  }
37272
- if (this.inReasoningBlock && this.isReasoningContinuation(trimmed)) {
37273
- log(`[GeminiAPIFormat] Filtered reasoning continuation: "${trimmed.substring(0, 50)}..."`);
37430
+ if (this.inReasoningBlock && this.isReasoningContinuation(trimmed2)) {
37431
+ log(`[GeminiAPIFormat] Filtered reasoning continuation: "${trimmed2.substring(0, 50)}..."`);
37274
37432
  wasFiltered = true;
37275
37433
  continue;
37276
37434
  }
37277
- if (this.inReasoningBlock && trimmed.length > 20 && !this.isReasoningContinuation(trimmed)) {
37435
+ if (this.inReasoningBlock && trimmed2.length > 20 && !this.isReasoningContinuation(trimmed2)) {
37278
37436
  this.inReasoningBlock = false;
37279
37437
  this.reasoningBlockDepth = 0;
37280
37438
  }
@@ -38357,10 +38515,10 @@ function extractAvailableSkills(systemText) {
38357
38515
  const body = systemText.slice(start.index + start[0].length);
38358
38516
  for (const line of body.split(`
38359
38517
  `)) {
38360
- const trimmed = line.trim();
38361
- if (!trimmed)
38518
+ const trimmed2 = line.trim();
38519
+ if (!trimmed2)
38362
38520
  continue;
38363
- const m = SKILL_LINE.exec(trimmed);
38521
+ const m = SKILL_LINE.exec(trimmed2);
38364
38522
  if (!m) {
38365
38523
  if (out.length > 0)
38366
38524
  break;
@@ -40204,12 +40362,12 @@ function writeToDisk(events) {
40204
40362
  if (events.length === 0)
40205
40363
  return;
40206
40364
  ensureDir();
40207
- const trimmed = enforceSizeCap([...events]);
40208
- const payload = { version: 1, events: trimmed };
40365
+ const trimmed2 = enforceSizeCap([...events]);
40366
+ const payload = { version: 1, events: trimmed2 };
40209
40367
  const tmpFile = join22(CLAUDISH_DIR, `stats-buffer.tmp.${process.pid}.json`);
40210
40368
  writeFileSync9(tmpFile, JSON.stringify(payload, null, 2), "utf-8");
40211
40369
  renameSync(tmpFile, BUFFER_FILE);
40212
- memoryCache = trimmed;
40370
+ memoryCache = trimmed2;
40213
40371
  } catch {}
40214
40372
  }
40215
40373
  function flushToDisk() {
@@ -40585,8 +40743,8 @@ function enforceReportSize(report) {
40585
40743
  let msg = report.error_message_template;
40586
40744
  while (serialized.length > MAX_REPORT_BYTES && msg.length > 0) {
40587
40745
  msg = msg.slice(0, Math.max(0, msg.length - 50));
40588
- const trimmed = { ...report, error_message_template: `${msg}...` };
40589
- serialized = JSON.stringify(trimmed);
40746
+ const trimmed2 = { ...report, error_message_template: `${msg}...` };
40747
+ serialized = JSON.stringify(trimmed2);
40590
40748
  }
40591
40749
  return serialized.length <= MAX_REPORT_BYTES ? serialized : null;
40592
40750
  }
@@ -41230,8 +41388,8 @@ function buildSurfacedErrorMessage(opts) {
41230
41388
  parts[0] = `${head}: ${hint}`;
41231
41389
  const detail = (providerMessage || "").trim();
41232
41390
  if (detail && !parts[0].includes(detail)) {
41233
- const trimmed = detail.length > 600 ? `${detail.slice(0, 600)}\u2026` : detail;
41234
- parts.push(`\u2014 ${trimmed}`);
41391
+ const trimmed2 = detail.length > 600 ? `${detail.slice(0, 600)}\u2026` : detail;
41392
+ parts.push(`\u2014 ${trimmed2}`);
41235
41393
  }
41236
41394
  return parts.join(" ");
41237
41395
  }
@@ -41463,10 +41621,10 @@ async function sniffResponsesStreamHead(response, opts = {}) {
41463
41621
  `);
41464
41622
  pending = lines.pop() ?? "";
41465
41623
  for (const line of lines) {
41466
- const trimmed = line.trim();
41467
- if (!trimmed.startsWith("data:"))
41624
+ const trimmed2 = line.trim();
41625
+ if (!trimmed2.startsWith("data:"))
41468
41626
  continue;
41469
- const payload = trimmed.slice(5).trim();
41627
+ const payload = trimmed2.slice(5).trim();
41470
41628
  if (!payload || payload === "[DONE]")
41471
41629
  continue;
41472
41630
  let event;
@@ -63637,15 +63795,15 @@ async function promptForProfileName(existing = []) {
63637
63795
  const name = await dist_default5({
63638
63796
  message: "Enter profile name:",
63639
63797
  validate: (value) => {
63640
- const trimmed = value.trim();
63641
- if (!trimmed) {
63798
+ const trimmed2 = value.trim();
63799
+ if (!trimmed2) {
63642
63800
  return "Profile name cannot be empty";
63643
63801
  }
63644
- if (!/^[a-z0-9-_]+$/i.test(trimmed)) {
63802
+ if (!/^[a-z0-9-_]+$/i.test(trimmed2)) {
63645
63803
  return "Profile name can only contain letters, numbers, hyphens, and underscores";
63646
63804
  }
63647
- if (existing.includes(trimmed)) {
63648
- return `Profile "${trimmed}" already exists`;
63805
+ if (existing.includes(trimmed2)) {
63806
+ return `Profile "${trimmed2}" already exists`;
63649
63807
  }
63650
63808
  return true;
63651
63809
  }
@@ -64042,10 +64200,10 @@ function extractErrorMessage(body) {
64042
64200
  return msg.length > 160 ? `${msg.slice(0, 157)}...` : msg;
64043
64201
  }
64044
64202
  } catch {}
64045
- const trimmed = body.trim();
64046
- if (!trimmed)
64203
+ const trimmed2 = body.trim();
64204
+ if (!trimmed2)
64047
64205
  return;
64048
- return trimmed.length > 160 ? `${trimmed.slice(0, 157)}...` : trimmed;
64206
+ return trimmed2.length > 160 ? `${trimmed2.slice(0, 157)}...` : trimmed2;
64049
64207
  }
64050
64208
  async function consumeProbeStream(response, timeoutMs, startedAt) {
64051
64209
  const body = response.body;
@@ -73820,6 +73978,7 @@ function App({ requestLogin } = {}) {
73820
73978
  const [opKindCursor, setOpKindCursor] = useState5(0);
73821
73979
  const [opAccountCursor, setOpAccountCursor] = useState5(0);
73822
73980
  const [opAccounts, setOpAccounts] = useState5([]);
73981
+ const opActiveAccount = useRef4(undefined);
73823
73982
  const [opTestResults, setOpTestResults] = useState5({});
73824
73983
  const [opPendingKind, setOpPendingKind] = useState5("ref");
73825
73984
  const [opPendingValue, setOpPendingValue] = useState5("");
@@ -73996,7 +74155,7 @@ function App({ requestLogin } = {}) {
73996
74155
  setOpFieldCursor(idx < 0 ? 0 : idx);
73997
74156
  }, [opFieldOptionsFiltered, opFieldCursor, mode]);
73998
74157
  const acquireOpAuth = useCallback3(async () => {
73999
- return resolveSdkAuth({
74158
+ const auth = await resolveSdkAuth({
74000
74159
  interactive: true,
74001
74160
  configAccount: readOnepasswordAccount(),
74002
74161
  onNeedsPicker: (accounts) => new Promise((resolve4) => {
@@ -74011,6 +74170,8 @@ function App({ requestLogin } = {}) {
74011
74170
  setMode("pick_op_account");
74012
74171
  })
74013
74172
  });
74173
+ opActiveAccount.current = auth.kind === "desktop" ? auth.accountName : undefined;
74174
+ return auth;
74014
74175
  }, []);
74015
74176
  const testOpEntry = useCallback3(async (entry) => {
74016
74177
  const key = `${entry.scope}:${entry.kind}:${entry.value}`;
@@ -74074,9 +74235,9 @@ function App({ requestLogin } = {}) {
74074
74235
  if (kind === "account") {
74075
74236
  saveOnepasswordAccount(value, scope);
74076
74237
  } else if (kind === "environment") {
74077
- addOnepasswordEnvironment(value, scope);
74238
+ addOnepasswordEnvironment(value, scope, undefined, opActiveAccount.current);
74078
74239
  } else {
74079
- addOnepasswordImport(value, scope);
74240
+ addOnepasswordImport(value, scope, undefined, opActiveAccount.current);
74080
74241
  }
74081
74242
  refreshConfig();
74082
74243
  const isGlob = kind === "glob" || isGlobImport(value);
@@ -75869,13 +76030,13 @@ function chainableCommandOf(statusLine) {
75869
76030
  const { type, command } = statusLine;
75870
76031
  if (type !== "command" || typeof command !== "string")
75871
76032
  return null;
75872
- const trimmed = command.trim();
75873
- if (!trimmed)
76033
+ const trimmed2 = command.trim();
76034
+ if (!trimmed2)
75874
76035
  return null;
75875
- if (trimmed.includes("CLAUDISH_ACTIVE_MODEL_NAME") || trimmed.includes("CLAUDISH_IS_LOCAL")) {
76036
+ if (trimmed2.includes("CLAUDISH_ACTIVE_MODEL_NAME") || trimmed2.includes("CLAUDISH_IS_LOCAL")) {
75876
76037
  return null;
75877
76038
  }
75878
- return trimmed;
76039
+ return trimmed2;
75879
76040
  }
75880
76041
  function buildChainedStatusCommand(userCommand, claudishBody, claudishSegment) {
75881
76042
  const quotedUser = `'${userCommand.replace(/'/g, `'\\''`)}'`;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claudish",
3
- "version": "7.36.0",
3
+ "version": "7.37.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.36.0",
64
- "@claudish/magmux-darwin-x64": "7.36.0",
65
- "@claudish/magmux-linux-arm64": "7.36.0",
66
- "@claudish/magmux-linux-x64": "7.36.0"
63
+ "@claudish/magmux-darwin-arm64": "7.37.0",
64
+ "@claudish/magmux-darwin-x64": "7.37.0",
65
+ "@claudish/magmux-linux-arm64": "7.37.0",
66
+ "@claudish/magmux-linux-x64": "7.37.0"
67
67
  },
68
68
  "author": "Jack Rudenko <i@madappgang.com>",
69
69
  "license": "MIT",