opensteer 0.6.1 → 0.6.3

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.
@@ -21,7 +21,6 @@ interface ProfileCommonCloudArgs {
21
21
  apiKey?: string;
22
22
  accessToken?: string;
23
23
  baseUrl?: string;
24
- siteUrl?: string;
25
24
  authScheme?: OpensteerAuthScheme;
26
25
  json?: boolean;
27
26
  }
@@ -46,7 +45,6 @@ interface ProfileSyncArgs extends ProfileCommonCloudArgs {
46
45
  interface CloudAuthContext {
47
46
  token: string;
48
47
  baseUrl: string;
49
- siteUrl: string;
50
48
  authScheme: OpensteerAuthScheme;
51
49
  kind: 'api-key' | 'access-token';
52
50
  source: 'flag' | 'env' | 'saved';
@@ -21,7 +21,6 @@ interface ProfileCommonCloudArgs {
21
21
  apiKey?: string;
22
22
  accessToken?: string;
23
23
  baseUrl?: string;
24
- siteUrl?: string;
25
24
  authScheme?: OpensteerAuthScheme;
26
25
  json?: boolean;
27
26
  }
@@ -46,7 +45,6 @@ interface ProfileSyncArgs extends ProfileCommonCloudArgs {
46
45
  interface CloudAuthContext {
47
46
  token: string;
48
47
  baseUrl: string;
49
- siteUrl: string;
50
48
  authScheme: OpensteerAuthScheme;
51
49
  kind: 'api-key' | 'access-token';
52
50
  source: 'flag' | 'env' | 'saved';
@@ -1,17 +1,17 @@
1
1
  import {
2
2
  BrowserProfileClient
3
- } from "../chunk-WJI7TGBQ.js";
3
+ } from "../chunk-FTKWQ6X3.js";
4
4
  import {
5
5
  ensureCloudCredentialsForCommand
6
- } from "../chunk-3FNI7JUU.js";
6
+ } from "../chunk-SCNX4NN3.js";
7
7
  import {
8
8
  Opensteer,
9
9
  expandHome,
10
10
  loadCookiesFromLocalProfileDir
11
- } from "../chunk-F2VDVOJO.js";
11
+ } from "../chunk-3OMXCBPD.js";
12
12
  import {
13
13
  resolveConfigWithEnv
14
- } from "../chunk-WDRMHPWL.js";
14
+ } from "../chunk-KE35RQOJ.js";
15
15
  import "../chunk-3H5RRIMZ.js";
16
16
 
17
17
  // src/cli/profile.ts
@@ -130,7 +130,6 @@ Cloud auth options (all commands):
130
130
  --api-key <key> Cloud API key (defaults to OPENSTEER_API_KEY)
131
131
  --access-token <token> Cloud bearer access token (defaults to OPENSTEER_ACCESS_TOKEN)
132
132
  --base-url <url> Cloud API base URL (defaults to env or the last selected host)
133
- --site-url <url> Cloud site URL for login/refresh/revoke flows
134
133
  --auth-scheme <scheme> api-key (default) or bearer
135
134
  --json JSON output (progress logs go to stderr)
136
135
 
@@ -217,13 +216,6 @@ function parseListArgs(rawArgs) {
217
216
  i = value.nextIndex;
218
217
  continue;
219
218
  }
220
- if (arg === "--site-url") {
221
- const value = readFlagValue(rawArgs, i, "--site-url");
222
- if (!value.ok) return { mode: "error", error: value.error };
223
- args.siteUrl = value.value;
224
- i = value.nextIndex;
225
- continue;
226
- }
227
219
  if (arg === "--auth-scheme") {
228
220
  const value = readFlagValue(rawArgs, i, "--auth-scheme");
229
221
  if (!value.ok) return { mode: "error", error: value.error };
@@ -316,13 +308,6 @@ function parseCreateArgs(rawArgs) {
316
308
  i = value.nextIndex;
317
309
  continue;
318
310
  }
319
- if (arg === "--site-url") {
320
- const value = readFlagValue(rawArgs, i, "--site-url");
321
- if (!value.ok) return { mode: "error", error: value.error };
322
- args.siteUrl = value.value;
323
- i = value.nextIndex;
324
- continue;
325
- }
326
311
  if (arg === "--auth-scheme") {
327
312
  const value = readFlagValue(rawArgs, i, "--auth-scheme");
328
313
  if (!value.ok) return { mode: "error", error: value.error };
@@ -441,13 +426,6 @@ function parseSyncArgs(rawArgs) {
441
426
  i = value.nextIndex;
442
427
  continue;
443
428
  }
444
- if (arg === "--site-url") {
445
- const value = readFlagValue(rawArgs, i, "--site-url");
446
- if (!value.ok) return { mode: "error", error: value.error };
447
- args.siteUrl = value.value;
448
- i = value.nextIndex;
449
- continue;
450
- }
451
429
  if (arg === "--auth-scheme") {
452
430
  const value = readFlagValue(rawArgs, i, "--auth-scheme");
453
431
  if (!value.ok) return { mode: "error", error: value.error };
@@ -538,7 +516,6 @@ async function buildCloudAuthContext(args, deps) {
538
516
  apiKeyFlag: args.apiKey,
539
517
  accessTokenFlag: args.accessToken,
540
518
  baseUrl: args.baseUrl,
541
- siteUrl: args.siteUrl,
542
519
  interactive: deps.isInteractive(),
543
520
  autoLoginIfNeeded: true,
544
521
  writeProgress: args.json ? deps.writeStderr : deps.writeStdout,
@@ -560,7 +537,6 @@ async function buildCloudAuthContext(args, deps) {
560
537
  return {
561
538
  token: ensured.token,
562
539
  baseUrl: ensured.baseUrl,
563
- siteUrl: ensured.siteUrl,
564
540
  authScheme: ensured.authScheme,
565
541
  kind: ensured.kind,
566
542
  source: ensured.source
@@ -1210,6 +1210,65 @@ function toJsonSafeValue(value, seen) {
1210
1210
  return void 0;
1211
1211
  }
1212
1212
 
1213
+ // src/cloud/credential-selection.ts
1214
+ function selectCloudCredential(options) {
1215
+ const apiKey = normalizeNonEmptyString(options.apiKey);
1216
+ const accessToken = normalizeNonEmptyString(options.accessToken);
1217
+ if (apiKey) {
1218
+ if (options.authScheme === "bearer") {
1219
+ return {
1220
+ apiKey,
1221
+ authScheme: "bearer",
1222
+ kind: "access-token",
1223
+ token: apiKey,
1224
+ compatibilityBearerApiKey: true
1225
+ };
1226
+ }
1227
+ return {
1228
+ apiKey,
1229
+ authScheme: "api-key",
1230
+ kind: "api-key",
1231
+ token: apiKey
1232
+ };
1233
+ }
1234
+ if (accessToken) {
1235
+ return {
1236
+ accessToken,
1237
+ authScheme: "bearer",
1238
+ kind: "access-token",
1239
+ token: accessToken
1240
+ };
1241
+ }
1242
+ return null;
1243
+ }
1244
+ function selectCloudCredentialByPrecedence(layers, authScheme) {
1245
+ for (const layer of layers) {
1246
+ const hasApiKey = layer.hasApiKey ?? Object.prototype.hasOwnProperty.call(layer, "apiKey");
1247
+ const hasAccessToken = layer.hasAccessToken ?? Object.prototype.hasOwnProperty.call(layer, "accessToken");
1248
+ if (!hasApiKey && !hasAccessToken) {
1249
+ continue;
1250
+ }
1251
+ return {
1252
+ source: layer.source,
1253
+ apiKey: layer.apiKey,
1254
+ accessToken: layer.accessToken,
1255
+ hasApiKey,
1256
+ hasAccessToken,
1257
+ credential: selectCloudCredential({
1258
+ apiKey: layer.apiKey,
1259
+ accessToken: layer.accessToken,
1260
+ authScheme: layer.authScheme ?? authScheme
1261
+ })
1262
+ };
1263
+ }
1264
+ return null;
1265
+ }
1266
+ function normalizeNonEmptyString(value) {
1267
+ if (typeof value !== "string") return void 0;
1268
+ const normalized = value.trim();
1269
+ return normalized.length ? normalized : void 0;
1270
+ }
1271
+
1213
1272
  // src/storage/namespace.ts
1214
1273
  var import_path2 = __toESM(require("path"), 1);
1215
1274
  var DEFAULT_NAMESPACE = "default";
@@ -1534,11 +1593,6 @@ function normalizeCloudOptions(value) {
1534
1593
  }
1535
1594
  return value;
1536
1595
  }
1537
- function normalizeNonEmptyString(value) {
1538
- if (typeof value !== "string") return void 0;
1539
- const normalized = value.trim();
1540
- return normalized.length ? normalized : void 0;
1541
- }
1542
1596
  function parseCloudEnabled(value, source) {
1543
1597
  if (value == null) return void 0;
1544
1598
  if (typeof value === "boolean") return value;
@@ -1547,6 +1601,18 @@ function parseCloudEnabled(value, source) {
1547
1601
  `Invalid ${source} value "${String(value)}". Use true, false, or a cloud options object.`
1548
1602
  );
1549
1603
  }
1604
+ function resolveCloudCredentialFields(selectedLayer) {
1605
+ const credential = selectedLayer?.credential;
1606
+ if (!credential) return {};
1607
+ if (credential.kind === "api-key" || credential.compatibilityBearerApiKey === true && selectedLayer?.source !== "env") {
1608
+ return {
1609
+ apiKey: credential.token
1610
+ };
1611
+ }
1612
+ return {
1613
+ accessToken: credential.token
1614
+ };
1615
+ }
1550
1616
  function resolveCloudSelection(config, env = process.env) {
1551
1617
  const configCloud = parseCloudEnabled(config.cloud, "cloud");
1552
1618
  if (configCloud !== void 0) {
@@ -1583,6 +1649,9 @@ function resolveConfigWithEnv(input = {}, options = {}) {
1583
1649
  });
1584
1650
  assertNoLegacyAiConfig(".opensteer/config.json", fileConfig);
1585
1651
  assertNoLegacyRuntimeConfig(".opensteer/config.json", fileConfig);
1652
+ const fileCloudOptions = normalizeCloudOptions(fileConfig.cloud);
1653
+ const fileHasCloudApiKey = hasOwn(fileCloudOptions, "apiKey");
1654
+ const fileHasCloudAccessToken = hasOwn(fileCloudOptions, "accessToken");
1586
1655
  const fileRootDir = typeof fileConfig.storage?.rootDir === "string" ? fileConfig.storage.rootDir : void 0;
1587
1656
  const envRootDir = input.storage?.rootDir ?? fileRootDir ?? initialRootDir;
1588
1657
  const env = resolveEnv(envRootDir, {
@@ -1621,13 +1690,6 @@ function resolveConfigWithEnv(input = {}, options = {}) {
1621
1690
  const envAccessTokenRaw = resolveOpensteerAccessToken(env);
1622
1691
  const envBaseUrl = resolveOpensteerBaseUrl(env);
1623
1692
  const envAuthScheme = resolveOpensteerAuthScheme(env);
1624
- if (envApiKey && envAccessTokenRaw) {
1625
- throw new Error(
1626
- "OPENSTEER_API_KEY and OPENSTEER_ACCESS_TOKEN are mutually exclusive. Set only one."
1627
- );
1628
- }
1629
- const envAccessToken = envAccessTokenRaw || (envAuthScheme === "bearer" ? envApiKey : void 0);
1630
- const envApiCredential = envAuthScheme === "bearer" && !envAccessTokenRaw ? void 0 : envApiKey;
1631
1693
  const envCloudProfileId = resolveOpensteerCloudProfileId(env);
1632
1694
  const envCloudProfileReuseIfActive = resolveOpensteerCloudProfileReuseIfActive(env);
1633
1695
  const envCloudAnnounce = parseCloudAnnounce(
@@ -1656,11 +1718,6 @@ function resolveConfigWithEnv(input = {}, options = {}) {
1656
1718
  const inputHasCloudBaseUrl = Boolean(
1657
1719
  inputCloudOptions && Object.prototype.hasOwnProperty.call(inputCloudOptions, "baseUrl")
1658
1720
  );
1659
- if (normalizeNonEmptyString(inputCloudOptions?.apiKey) && normalizeNonEmptyString(inputCloudOptions?.accessToken)) {
1660
- throw new Error(
1661
- "cloud.apiKey and cloud.accessToken are mutually exclusive. Set only one."
1662
- );
1663
- }
1664
1721
  const cloudSelection = resolveCloudSelection({
1665
1722
  cloud: resolved.cloud
1666
1723
  }, env);
@@ -1671,11 +1728,6 @@ function resolveConfigWithEnv(input = {}, options = {}) {
1671
1728
  accessToken: resolvedCloudAccessTokenRaw,
1672
1729
  ...resolvedCloudRest
1673
1730
  } = resolvedCloud;
1674
- if (normalizeNonEmptyString(resolvedCloudApiKeyRaw) && normalizeNonEmptyString(resolvedCloudAccessTokenRaw)) {
1675
- throw new Error(
1676
- "Cloud config cannot include both apiKey and accessToken at the same time."
1677
- );
1678
- }
1679
1731
  const resolvedCloudBrowserProfile = normalizeCloudBrowserProfileOptions(
1680
1732
  resolvedCloud.browserProfile,
1681
1733
  "resolved.cloud.browserProfile"
@@ -1687,25 +1739,40 @@ function resolveConfigWithEnv(input = {}, options = {}) {
1687
1739
  const browserProfile = inputCloudBrowserProfile ?? envCloudBrowserProfile ?? resolvedCloudBrowserProfile;
1688
1740
  let authScheme = inputAuthScheme ?? envAuthScheme ?? parseAuthScheme(resolvedCloud.authScheme, "cloud.authScheme") ?? "api-key";
1689
1741
  const announce = inputCloudAnnounce ?? envCloudAnnounce ?? parseCloudAnnounce(resolvedCloud.announce, "cloud.announce") ?? "always";
1690
- const credentialOverriddenByInput = inputHasCloudApiKey || inputHasCloudAccessToken;
1691
- let apiKey = normalizeNonEmptyString(resolvedCloudApiKeyRaw);
1692
- let accessToken = normalizeNonEmptyString(resolvedCloudAccessTokenRaw);
1693
- if (!credentialOverriddenByInput) {
1694
- if (envAccessToken) {
1695
- accessToken = envAccessToken;
1696
- apiKey = void 0;
1697
- } else if (envApiCredential) {
1698
- apiKey = envApiCredential;
1699
- accessToken = void 0;
1700
- }
1701
- }
1742
+ const selectedCredentialLayer = selectCloudCredentialByPrecedence(
1743
+ [
1744
+ {
1745
+ source: "input",
1746
+ apiKey: inputCloudOptions?.apiKey,
1747
+ accessToken: inputCloudOptions?.accessToken,
1748
+ hasApiKey: inputHasCloudApiKey,
1749
+ hasAccessToken: inputHasCloudAccessToken
1750
+ },
1751
+ {
1752
+ source: "env",
1753
+ apiKey: envApiKey,
1754
+ accessToken: envAccessTokenRaw,
1755
+ hasApiKey: envApiKey !== void 0,
1756
+ hasAccessToken: envAccessTokenRaw !== void 0
1757
+ },
1758
+ {
1759
+ source: "file",
1760
+ apiKey: fileCloudOptions?.apiKey,
1761
+ accessToken: fileCloudOptions?.accessToken,
1762
+ hasApiKey: fileHasCloudApiKey,
1763
+ hasAccessToken: fileHasCloudAccessToken
1764
+ }
1765
+ ],
1766
+ authScheme
1767
+ );
1768
+ const { apiKey, accessToken } = resolveCloudCredentialFields(selectedCredentialLayer);
1702
1769
  if (accessToken) {
1703
1770
  authScheme = "bearer";
1704
1771
  }
1705
1772
  resolved.cloud = {
1706
1773
  ...resolvedCloudRest,
1707
- ...inputHasCloudApiKey ? { apiKey: resolvedCloudApiKeyRaw } : apiKey ? { apiKey } : {},
1708
- ...inputHasCloudAccessToken ? { accessToken: resolvedCloudAccessTokenRaw } : accessToken ? { accessToken } : {},
1774
+ ...apiKey ? { apiKey } : selectedCredentialLayer?.hasApiKey && !accessToken ? { apiKey: selectedCredentialLayer.apiKey } : {},
1775
+ ...accessToken ? { accessToken } : selectedCredentialLayer?.hasAccessToken && !apiKey ? { accessToken: selectedCredentialLayer.accessToken } : {},
1709
1776
  authScheme,
1710
1777
  announce,
1711
1778
  ...browserProfile ? { browserProfile } : {}
@@ -11220,30 +11287,20 @@ var Opensteer = class _Opensteer {
11220
11287
  this.pool = new BrowserPool(resolved.browser || {});
11221
11288
  if (cloudSelection.cloud) {
11222
11289
  const cloudConfig = resolved.cloud && typeof resolved.cloud === "object" ? resolved.cloud : void 0;
11223
- const apiKey = cloudConfig?.apiKey?.trim();
11224
- const accessToken = cloudConfig?.accessToken?.trim();
11225
- if (apiKey && accessToken) {
11226
- throw new Error(
11227
- "Cloud mode cannot use both cloud.apiKey and cloud.accessToken. Set only one credential."
11228
- );
11229
- }
11230
- let credential = "";
11231
- let authScheme = cloudConfig?.authScheme ?? "api-key";
11232
- if (accessToken) {
11233
- credential = accessToken;
11234
- authScheme = "bearer";
11235
- } else if (apiKey) {
11236
- credential = apiKey;
11237
- }
11290
+ const credential = selectCloudCredential({
11291
+ apiKey: cloudConfig?.apiKey,
11292
+ accessToken: cloudConfig?.accessToken,
11293
+ authScheme: cloudConfig?.authScheme
11294
+ });
11238
11295
  if (!credential) {
11239
11296
  throw new Error(
11240
11297
  "Cloud mode requires credentials via cloud.apiKey/cloud.accessToken or OPENSTEER_API_KEY/OPENSTEER_ACCESS_TOKEN."
11241
11298
  );
11242
11299
  }
11243
11300
  this.cloud = createCloudRuntimeState(
11244
- credential,
11301
+ credential.token,
11245
11302
  cloudConfig?.baseUrl,
11246
- authScheme
11303
+ credential.authScheme
11247
11304
  );
11248
11305
  } else {
11249
11306
  this.cloud = null;
@@ -1,11 +1,11 @@
1
1
  import {
2
2
  Opensteer
3
- } from "../chunk-F2VDVOJO.js";
3
+ } from "../chunk-3OMXCBPD.js";
4
4
  import {
5
5
  normalizeError,
6
6
  resolveCloudSelection,
7
7
  resolveConfigWithEnv
8
- } from "../chunk-WDRMHPWL.js";
8
+ } from "../chunk-KE35RQOJ.js";
9
9
  import "../chunk-3H5RRIMZ.js";
10
10
 
11
11
  // src/cli/server.ts
package/dist/index.cjs CHANGED
@@ -1301,6 +1301,65 @@ function toJsonSafeValue(value, seen) {
1301
1301
  return void 0;
1302
1302
  }
1303
1303
 
1304
+ // src/cloud/credential-selection.ts
1305
+ function selectCloudCredential(options) {
1306
+ const apiKey = normalizeNonEmptyString(options.apiKey);
1307
+ const accessToken = normalizeNonEmptyString(options.accessToken);
1308
+ if (apiKey) {
1309
+ if (options.authScheme === "bearer") {
1310
+ return {
1311
+ apiKey,
1312
+ authScheme: "bearer",
1313
+ kind: "access-token",
1314
+ token: apiKey,
1315
+ compatibilityBearerApiKey: true
1316
+ };
1317
+ }
1318
+ return {
1319
+ apiKey,
1320
+ authScheme: "api-key",
1321
+ kind: "api-key",
1322
+ token: apiKey
1323
+ };
1324
+ }
1325
+ if (accessToken) {
1326
+ return {
1327
+ accessToken,
1328
+ authScheme: "bearer",
1329
+ kind: "access-token",
1330
+ token: accessToken
1331
+ };
1332
+ }
1333
+ return null;
1334
+ }
1335
+ function selectCloudCredentialByPrecedence(layers, authScheme) {
1336
+ for (const layer of layers) {
1337
+ const hasApiKey = layer.hasApiKey ?? Object.prototype.hasOwnProperty.call(layer, "apiKey");
1338
+ const hasAccessToken = layer.hasAccessToken ?? Object.prototype.hasOwnProperty.call(layer, "accessToken");
1339
+ if (!hasApiKey && !hasAccessToken) {
1340
+ continue;
1341
+ }
1342
+ return {
1343
+ source: layer.source,
1344
+ apiKey: layer.apiKey,
1345
+ accessToken: layer.accessToken,
1346
+ hasApiKey,
1347
+ hasAccessToken,
1348
+ credential: selectCloudCredential({
1349
+ apiKey: layer.apiKey,
1350
+ accessToken: layer.accessToken,
1351
+ authScheme: layer.authScheme ?? authScheme
1352
+ })
1353
+ };
1354
+ }
1355
+ return null;
1356
+ }
1357
+ function normalizeNonEmptyString(value) {
1358
+ if (typeof value !== "string") return void 0;
1359
+ const normalized = value.trim();
1360
+ return normalized.length ? normalized : void 0;
1361
+ }
1362
+
1304
1363
  // src/storage/namespace.ts
1305
1364
  var import_path2 = __toESM(require("path"), 1);
1306
1365
  var DEFAULT_NAMESPACE = "default";
@@ -1625,11 +1684,6 @@ function normalizeCloudOptions(value) {
1625
1684
  }
1626
1685
  return value;
1627
1686
  }
1628
- function normalizeNonEmptyString(value) {
1629
- if (typeof value !== "string") return void 0;
1630
- const normalized = value.trim();
1631
- return normalized.length ? normalized : void 0;
1632
- }
1633
1687
  function parseCloudEnabled(value, source) {
1634
1688
  if (value == null) return void 0;
1635
1689
  if (typeof value === "boolean") return value;
@@ -1638,6 +1692,18 @@ function parseCloudEnabled(value, source) {
1638
1692
  `Invalid ${source} value "${String(value)}". Use true, false, or a cloud options object.`
1639
1693
  );
1640
1694
  }
1695
+ function resolveCloudCredentialFields(selectedLayer) {
1696
+ const credential = selectedLayer?.credential;
1697
+ if (!credential) return {};
1698
+ if (credential.kind === "api-key" || credential.compatibilityBearerApiKey === true && selectedLayer?.source !== "env") {
1699
+ return {
1700
+ apiKey: credential.token
1701
+ };
1702
+ }
1703
+ return {
1704
+ accessToken: credential.token
1705
+ };
1706
+ }
1641
1707
  function resolveCloudSelection(config, env = process.env) {
1642
1708
  const configCloud = parseCloudEnabled(config.cloud, "cloud");
1643
1709
  if (configCloud !== void 0) {
@@ -1674,6 +1740,9 @@ function resolveConfigWithEnv(input = {}, options = {}) {
1674
1740
  });
1675
1741
  assertNoLegacyAiConfig(".opensteer/config.json", fileConfig);
1676
1742
  assertNoLegacyRuntimeConfig(".opensteer/config.json", fileConfig);
1743
+ const fileCloudOptions = normalizeCloudOptions(fileConfig.cloud);
1744
+ const fileHasCloudApiKey = hasOwn(fileCloudOptions, "apiKey");
1745
+ const fileHasCloudAccessToken = hasOwn(fileCloudOptions, "accessToken");
1677
1746
  const fileRootDir = typeof fileConfig.storage?.rootDir === "string" ? fileConfig.storage.rootDir : void 0;
1678
1747
  const envRootDir = input.storage?.rootDir ?? fileRootDir ?? initialRootDir;
1679
1748
  const env = resolveEnv(envRootDir, {
@@ -1712,13 +1781,6 @@ function resolveConfigWithEnv(input = {}, options = {}) {
1712
1781
  const envAccessTokenRaw = resolveOpensteerAccessToken(env);
1713
1782
  const envBaseUrl = resolveOpensteerBaseUrl(env);
1714
1783
  const envAuthScheme = resolveOpensteerAuthScheme(env);
1715
- if (envApiKey && envAccessTokenRaw) {
1716
- throw new Error(
1717
- "OPENSTEER_API_KEY and OPENSTEER_ACCESS_TOKEN are mutually exclusive. Set only one."
1718
- );
1719
- }
1720
- const envAccessToken = envAccessTokenRaw || (envAuthScheme === "bearer" ? envApiKey : void 0);
1721
- const envApiCredential = envAuthScheme === "bearer" && !envAccessTokenRaw ? void 0 : envApiKey;
1722
1784
  const envCloudProfileId = resolveOpensteerCloudProfileId(env);
1723
1785
  const envCloudProfileReuseIfActive = resolveOpensteerCloudProfileReuseIfActive(env);
1724
1786
  const envCloudAnnounce = parseCloudAnnounce(
@@ -1747,11 +1809,6 @@ function resolveConfigWithEnv(input = {}, options = {}) {
1747
1809
  const inputHasCloudBaseUrl = Boolean(
1748
1810
  inputCloudOptions && Object.prototype.hasOwnProperty.call(inputCloudOptions, "baseUrl")
1749
1811
  );
1750
- if (normalizeNonEmptyString(inputCloudOptions?.apiKey) && normalizeNonEmptyString(inputCloudOptions?.accessToken)) {
1751
- throw new Error(
1752
- "cloud.apiKey and cloud.accessToken are mutually exclusive. Set only one."
1753
- );
1754
- }
1755
1812
  const cloudSelection = resolveCloudSelection({
1756
1813
  cloud: resolved.cloud
1757
1814
  }, env);
@@ -1762,11 +1819,6 @@ function resolveConfigWithEnv(input = {}, options = {}) {
1762
1819
  accessToken: resolvedCloudAccessTokenRaw,
1763
1820
  ...resolvedCloudRest
1764
1821
  } = resolvedCloud;
1765
- if (normalizeNonEmptyString(resolvedCloudApiKeyRaw) && normalizeNonEmptyString(resolvedCloudAccessTokenRaw)) {
1766
- throw new Error(
1767
- "Cloud config cannot include both apiKey and accessToken at the same time."
1768
- );
1769
- }
1770
1822
  const resolvedCloudBrowserProfile = normalizeCloudBrowserProfileOptions(
1771
1823
  resolvedCloud.browserProfile,
1772
1824
  "resolved.cloud.browserProfile"
@@ -1778,25 +1830,40 @@ function resolveConfigWithEnv(input = {}, options = {}) {
1778
1830
  const browserProfile = inputCloudBrowserProfile ?? envCloudBrowserProfile ?? resolvedCloudBrowserProfile;
1779
1831
  let authScheme = inputAuthScheme ?? envAuthScheme ?? parseAuthScheme(resolvedCloud.authScheme, "cloud.authScheme") ?? "api-key";
1780
1832
  const announce = inputCloudAnnounce ?? envCloudAnnounce ?? parseCloudAnnounce(resolvedCloud.announce, "cloud.announce") ?? "always";
1781
- const credentialOverriddenByInput = inputHasCloudApiKey || inputHasCloudAccessToken;
1782
- let apiKey = normalizeNonEmptyString(resolvedCloudApiKeyRaw);
1783
- let accessToken = normalizeNonEmptyString(resolvedCloudAccessTokenRaw);
1784
- if (!credentialOverriddenByInput) {
1785
- if (envAccessToken) {
1786
- accessToken = envAccessToken;
1787
- apiKey = void 0;
1788
- } else if (envApiCredential) {
1789
- apiKey = envApiCredential;
1790
- accessToken = void 0;
1791
- }
1792
- }
1833
+ const selectedCredentialLayer = selectCloudCredentialByPrecedence(
1834
+ [
1835
+ {
1836
+ source: "input",
1837
+ apiKey: inputCloudOptions?.apiKey,
1838
+ accessToken: inputCloudOptions?.accessToken,
1839
+ hasApiKey: inputHasCloudApiKey,
1840
+ hasAccessToken: inputHasCloudAccessToken
1841
+ },
1842
+ {
1843
+ source: "env",
1844
+ apiKey: envApiKey,
1845
+ accessToken: envAccessTokenRaw,
1846
+ hasApiKey: envApiKey !== void 0,
1847
+ hasAccessToken: envAccessTokenRaw !== void 0
1848
+ },
1849
+ {
1850
+ source: "file",
1851
+ apiKey: fileCloudOptions?.apiKey,
1852
+ accessToken: fileCloudOptions?.accessToken,
1853
+ hasApiKey: fileHasCloudApiKey,
1854
+ hasAccessToken: fileHasCloudAccessToken
1855
+ }
1856
+ ],
1857
+ authScheme
1858
+ );
1859
+ const { apiKey, accessToken } = resolveCloudCredentialFields(selectedCredentialLayer);
1793
1860
  if (accessToken) {
1794
1861
  authScheme = "bearer";
1795
1862
  }
1796
1863
  resolved.cloud = {
1797
1864
  ...resolvedCloudRest,
1798
- ...inputHasCloudApiKey ? { apiKey: resolvedCloudApiKeyRaw } : apiKey ? { apiKey } : {},
1799
- ...inputHasCloudAccessToken ? { accessToken: resolvedCloudAccessTokenRaw } : accessToken ? { accessToken } : {},
1865
+ ...apiKey ? { apiKey } : selectedCredentialLayer?.hasApiKey && !accessToken ? { apiKey: selectedCredentialLayer.apiKey } : {},
1866
+ ...accessToken ? { accessToken } : selectedCredentialLayer?.hasAccessToken && !apiKey ? { accessToken: selectedCredentialLayer.accessToken } : {},
1800
1867
  authScheme,
1801
1868
  announce,
1802
1869
  ...browserProfile ? { browserProfile } : {}
@@ -11321,30 +11388,20 @@ var Opensteer = class _Opensteer {
11321
11388
  this.pool = new BrowserPool(resolved.browser || {});
11322
11389
  if (cloudSelection.cloud) {
11323
11390
  const cloudConfig = resolved.cloud && typeof resolved.cloud === "object" ? resolved.cloud : void 0;
11324
- const apiKey = cloudConfig?.apiKey?.trim();
11325
- const accessToken = cloudConfig?.accessToken?.trim();
11326
- if (apiKey && accessToken) {
11327
- throw new Error(
11328
- "Cloud mode cannot use both cloud.apiKey and cloud.accessToken. Set only one credential."
11329
- );
11330
- }
11331
- let credential = "";
11332
- let authScheme = cloudConfig?.authScheme ?? "api-key";
11333
- if (accessToken) {
11334
- credential = accessToken;
11335
- authScheme = "bearer";
11336
- } else if (apiKey) {
11337
- credential = apiKey;
11338
- }
11391
+ const credential = selectCloudCredential({
11392
+ apiKey: cloudConfig?.apiKey,
11393
+ accessToken: cloudConfig?.accessToken,
11394
+ authScheme: cloudConfig?.authScheme
11395
+ });
11339
11396
  if (!credential) {
11340
11397
  throw new Error(
11341
11398
  "Cloud mode requires credentials via cloud.apiKey/cloud.accessToken or OPENSTEER_API_KEY/OPENSTEER_ACCESS_TOKEN."
11342
11399
  );
11343
11400
  }
11344
11401
  this.cloud = createCloudRuntimeState(
11345
- credential,
11402
+ credential.token,
11346
11403
  cloudConfig?.baseUrl,
11347
- authScheme
11404
+ credential.authScheme
11348
11405
  );
11349
11406
  } else {
11350
11407
  this.cloud = null;
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  BrowserProfileClient
3
- } from "./chunk-WJI7TGBQ.js";
3
+ } from "./chunk-FTKWQ6X3.js";
4
4
  import {
5
5
  ActionWsClient,
6
6
  CounterResolutionError,
@@ -78,7 +78,7 @@ import {
78
78
  switchTab,
79
79
  typeText,
80
80
  waitForVisualStability
81
- } from "./chunk-F2VDVOJO.js";
81
+ } from "./chunk-3OMXCBPD.js";
82
82
  import {
83
83
  CloudCdpClient,
84
84
  CloudSessionClient,
@@ -87,7 +87,7 @@ import {
87
87
  cloudUnsupportedMethodError,
88
88
  normalizeNamespace,
89
89
  resolveNamespaceDir
90
- } from "./chunk-WDRMHPWL.js";
90
+ } from "./chunk-KE35RQOJ.js";
91
91
  import {
92
92
  createResolveCallback
93
93
  } from "./chunk-DN3GI5CH.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opensteer",
3
- "version": "0.6.1",
3
+ "version": "0.6.3",
4
4
  "description": "Open-source browser automation SDK and CLI that lets AI agents build complex scrapers directly in your codebase.",
5
5
  "license": "MIT",
6
6
  "type": "module",