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.
- package/README.md +4 -5
- package/bin/opensteer.mjs +0 -1
- package/dist/{chunk-F2VDVOJO.js → chunk-3OMXCBPD.js} +10 -19
- package/dist/{chunk-WJI7TGBQ.js → chunk-FTKWQ6X3.js} +1 -1
- package/dist/{chunk-WDRMHPWL.js → chunk-KE35RQOJ.js} +106 -36
- package/dist/{chunk-3FNI7JUU.js → chunk-SCNX4NN3.js} +114 -241
- package/dist/cli/auth.cjs +215 -276
- package/dist/cli/auth.d.cts +0 -6
- package/dist/cli/auth.d.ts +0 -6
- package/dist/cli/auth.js +2 -2
- package/dist/cli/profile.cjs +199 -259
- package/dist/cli/profile.d.cts +0 -2
- package/dist/cli/profile.d.ts +0 -2
- package/dist/cli/profile.js +4 -28
- package/dist/cli/server.cjs +110 -53
- package/dist/cli/server.js +2 -2
- package/dist/index.cjs +110 -53
- package/dist/index.js +3 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -182,11 +182,10 @@ opensteer auth logout
|
|
|
182
182
|
`--no-browser` on remote shells, containers, or CI and paste the printed URL
|
|
183
183
|
into a browser manually. In `--json` mode, login prompts go to stderr and the
|
|
184
184
|
final JSON result stays on stdout.
|
|
185
|
-
- Saved machine logins remain scoped per resolved cloud host (`baseUrl`
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
different host.
|
|
185
|
+
- Saved machine logins remain scoped per resolved cloud API host (`baseUrl`).
|
|
186
|
+
The CLI also remembers the last selected cloud host, so `opensteer auth
|
|
187
|
+
status`, `opensteer auth logout`, and other cloud commands reuse it by
|
|
188
|
+
default unless `--base-url` or env vars select a different host.
|
|
190
189
|
|
|
191
190
|
- `OPENSTEER_BASE_URL` overrides the default cloud host
|
|
192
191
|
- `OPENSTEER_ACCESS_TOKEN` provides bearer auth for cloud commands
|
package/bin/opensteer.mjs
CHANGED
|
@@ -1149,7 +1149,6 @@ Environment:
|
|
|
1149
1149
|
OPENSTEER_API_KEY Cloud API key credential
|
|
1150
1150
|
OPENSTEER_ACCESS_TOKEN Cloud bearer access token credential
|
|
1151
1151
|
OPENSTEER_BASE_URL Override cloud control-plane base URL
|
|
1152
|
-
OPENSTEER_CLOUD_SITE_URL Override cloud site URL for device login endpoints
|
|
1153
1152
|
OPENSTEER_AUTH_SCHEME Cloud auth scheme: api-key (default) or bearer
|
|
1154
1153
|
OPENSTEER_REMOTE_ANNOUNCE Cloud session announcement policy: always (default), off, tty
|
|
1155
1154
|
`)
|
|
@@ -11,8 +11,9 @@ import {
|
|
|
11
11
|
resolveCloudSelection,
|
|
12
12
|
resolveConfigWithEnv,
|
|
13
13
|
resolveNamespace,
|
|
14
|
-
resolveNamespaceDir
|
|
15
|
-
|
|
14
|
+
resolveNamespaceDir,
|
|
15
|
+
selectCloudCredential
|
|
16
|
+
} from "./chunk-KE35RQOJ.js";
|
|
16
17
|
import {
|
|
17
18
|
flattenExtractionDataToFieldPlan
|
|
18
19
|
} from "./chunk-3H5RRIMZ.js";
|
|
@@ -10081,30 +10082,20 @@ var Opensteer = class _Opensteer {
|
|
|
10081
10082
|
this.pool = new BrowserPool(resolved.browser || {});
|
|
10082
10083
|
if (cloudSelection.cloud) {
|
|
10083
10084
|
const cloudConfig = resolved.cloud && typeof resolved.cloud === "object" ? resolved.cloud : void 0;
|
|
10084
|
-
const
|
|
10085
|
-
|
|
10086
|
-
|
|
10087
|
-
|
|
10088
|
-
|
|
10089
|
-
);
|
|
10090
|
-
}
|
|
10091
|
-
let credential = "";
|
|
10092
|
-
let authScheme = cloudConfig?.authScheme ?? "api-key";
|
|
10093
|
-
if (accessToken) {
|
|
10094
|
-
credential = accessToken;
|
|
10095
|
-
authScheme = "bearer";
|
|
10096
|
-
} else if (apiKey) {
|
|
10097
|
-
credential = apiKey;
|
|
10098
|
-
}
|
|
10085
|
+
const credential = selectCloudCredential({
|
|
10086
|
+
apiKey: cloudConfig?.apiKey,
|
|
10087
|
+
accessToken: cloudConfig?.accessToken,
|
|
10088
|
+
authScheme: cloudConfig?.authScheme
|
|
10089
|
+
});
|
|
10099
10090
|
if (!credential) {
|
|
10100
10091
|
throw new Error(
|
|
10101
10092
|
"Cloud mode requires credentials via cloud.apiKey/cloud.accessToken or OPENSTEER_API_KEY/OPENSTEER_ACCESS_TOKEN."
|
|
10102
10093
|
);
|
|
10103
10094
|
}
|
|
10104
10095
|
this.cloud = createCloudRuntimeState(
|
|
10105
|
-
credential,
|
|
10096
|
+
credential.token,
|
|
10106
10097
|
cloudConfig?.baseUrl,
|
|
10107
|
-
authScheme
|
|
10098
|
+
credential.authScheme
|
|
10108
10099
|
);
|
|
10109
10100
|
} else {
|
|
10110
10101
|
this.cloud = null;
|
|
@@ -261,6 +261,67 @@ import fs from "fs";
|
|
|
261
261
|
import path2 from "path";
|
|
262
262
|
import { fileURLToPath } from "url";
|
|
263
263
|
import { parse as parseDotenv } from "dotenv";
|
|
264
|
+
|
|
265
|
+
// src/cloud/credential-selection.ts
|
|
266
|
+
function selectCloudCredential(options) {
|
|
267
|
+
const apiKey = normalizeNonEmptyString(options.apiKey);
|
|
268
|
+
const accessToken = normalizeNonEmptyString(options.accessToken);
|
|
269
|
+
if (apiKey) {
|
|
270
|
+
if (options.authScheme === "bearer") {
|
|
271
|
+
return {
|
|
272
|
+
apiKey,
|
|
273
|
+
authScheme: "bearer",
|
|
274
|
+
kind: "access-token",
|
|
275
|
+
token: apiKey,
|
|
276
|
+
compatibilityBearerApiKey: true
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
return {
|
|
280
|
+
apiKey,
|
|
281
|
+
authScheme: "api-key",
|
|
282
|
+
kind: "api-key",
|
|
283
|
+
token: apiKey
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
if (accessToken) {
|
|
287
|
+
return {
|
|
288
|
+
accessToken,
|
|
289
|
+
authScheme: "bearer",
|
|
290
|
+
kind: "access-token",
|
|
291
|
+
token: accessToken
|
|
292
|
+
};
|
|
293
|
+
}
|
|
294
|
+
return null;
|
|
295
|
+
}
|
|
296
|
+
function selectCloudCredentialByPrecedence(layers, authScheme) {
|
|
297
|
+
for (const layer of layers) {
|
|
298
|
+
const hasApiKey = layer.hasApiKey ?? Object.prototype.hasOwnProperty.call(layer, "apiKey");
|
|
299
|
+
const hasAccessToken = layer.hasAccessToken ?? Object.prototype.hasOwnProperty.call(layer, "accessToken");
|
|
300
|
+
if (!hasApiKey && !hasAccessToken) {
|
|
301
|
+
continue;
|
|
302
|
+
}
|
|
303
|
+
return {
|
|
304
|
+
source: layer.source,
|
|
305
|
+
apiKey: layer.apiKey,
|
|
306
|
+
accessToken: layer.accessToken,
|
|
307
|
+
hasApiKey,
|
|
308
|
+
hasAccessToken,
|
|
309
|
+
credential: selectCloudCredential({
|
|
310
|
+
apiKey: layer.apiKey,
|
|
311
|
+
accessToken: layer.accessToken,
|
|
312
|
+
authScheme: layer.authScheme ?? authScheme
|
|
313
|
+
})
|
|
314
|
+
};
|
|
315
|
+
}
|
|
316
|
+
return null;
|
|
317
|
+
}
|
|
318
|
+
function normalizeNonEmptyString(value) {
|
|
319
|
+
if (typeof value !== "string") return void 0;
|
|
320
|
+
const normalized = value.trim();
|
|
321
|
+
return normalized.length ? normalized : void 0;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
// src/config.ts
|
|
264
325
|
var DEFAULT_CONFIG = {
|
|
265
326
|
browser: {
|
|
266
327
|
headless: false,
|
|
@@ -552,11 +613,6 @@ function normalizeCloudOptions(value) {
|
|
|
552
613
|
}
|
|
553
614
|
return value;
|
|
554
615
|
}
|
|
555
|
-
function normalizeNonEmptyString(value) {
|
|
556
|
-
if (typeof value !== "string") return void 0;
|
|
557
|
-
const normalized = value.trim();
|
|
558
|
-
return normalized.length ? normalized : void 0;
|
|
559
|
-
}
|
|
560
616
|
function parseCloudEnabled(value, source) {
|
|
561
617
|
if (value == null) return void 0;
|
|
562
618
|
if (typeof value === "boolean") return value;
|
|
@@ -565,6 +621,18 @@ function parseCloudEnabled(value, source) {
|
|
|
565
621
|
`Invalid ${source} value "${String(value)}". Use true, false, or a cloud options object.`
|
|
566
622
|
);
|
|
567
623
|
}
|
|
624
|
+
function resolveCloudCredentialFields(selectedLayer) {
|
|
625
|
+
const credential = selectedLayer?.credential;
|
|
626
|
+
if (!credential) return {};
|
|
627
|
+
if (credential.kind === "api-key" || credential.compatibilityBearerApiKey === true && selectedLayer?.source !== "env") {
|
|
628
|
+
return {
|
|
629
|
+
apiKey: credential.token
|
|
630
|
+
};
|
|
631
|
+
}
|
|
632
|
+
return {
|
|
633
|
+
accessToken: credential.token
|
|
634
|
+
};
|
|
635
|
+
}
|
|
568
636
|
function resolveCloudSelection(config, env = process.env) {
|
|
569
637
|
const configCloud = parseCloudEnabled(config.cloud, "cloud");
|
|
570
638
|
if (configCloud !== void 0) {
|
|
@@ -601,6 +669,9 @@ function resolveConfigWithEnv(input = {}, options = {}) {
|
|
|
601
669
|
});
|
|
602
670
|
assertNoLegacyAiConfig(".opensteer/config.json", fileConfig);
|
|
603
671
|
assertNoLegacyRuntimeConfig(".opensteer/config.json", fileConfig);
|
|
672
|
+
const fileCloudOptions = normalizeCloudOptions(fileConfig.cloud);
|
|
673
|
+
const fileHasCloudApiKey = hasOwn(fileCloudOptions, "apiKey");
|
|
674
|
+
const fileHasCloudAccessToken = hasOwn(fileCloudOptions, "accessToken");
|
|
604
675
|
const fileRootDir = typeof fileConfig.storage?.rootDir === "string" ? fileConfig.storage.rootDir : void 0;
|
|
605
676
|
const envRootDir = input.storage?.rootDir ?? fileRootDir ?? initialRootDir;
|
|
606
677
|
const env = resolveEnv(envRootDir, {
|
|
@@ -639,13 +710,6 @@ function resolveConfigWithEnv(input = {}, options = {}) {
|
|
|
639
710
|
const envAccessTokenRaw = resolveOpensteerAccessToken(env);
|
|
640
711
|
const envBaseUrl = resolveOpensteerBaseUrl(env);
|
|
641
712
|
const envAuthScheme = resolveOpensteerAuthScheme(env);
|
|
642
|
-
if (envApiKey && envAccessTokenRaw) {
|
|
643
|
-
throw new Error(
|
|
644
|
-
"OPENSTEER_API_KEY and OPENSTEER_ACCESS_TOKEN are mutually exclusive. Set only one."
|
|
645
|
-
);
|
|
646
|
-
}
|
|
647
|
-
const envAccessToken = envAccessTokenRaw || (envAuthScheme === "bearer" ? envApiKey : void 0);
|
|
648
|
-
const envApiCredential = envAuthScheme === "bearer" && !envAccessTokenRaw ? void 0 : envApiKey;
|
|
649
713
|
const envCloudProfileId = resolveOpensteerCloudProfileId(env);
|
|
650
714
|
const envCloudProfileReuseIfActive = resolveOpensteerCloudProfileReuseIfActive(env);
|
|
651
715
|
const envCloudAnnounce = parseCloudAnnounce(
|
|
@@ -674,11 +738,6 @@ function resolveConfigWithEnv(input = {}, options = {}) {
|
|
|
674
738
|
const inputHasCloudBaseUrl = Boolean(
|
|
675
739
|
inputCloudOptions && Object.prototype.hasOwnProperty.call(inputCloudOptions, "baseUrl")
|
|
676
740
|
);
|
|
677
|
-
if (normalizeNonEmptyString(inputCloudOptions?.apiKey) && normalizeNonEmptyString(inputCloudOptions?.accessToken)) {
|
|
678
|
-
throw new Error(
|
|
679
|
-
"cloud.apiKey and cloud.accessToken are mutually exclusive. Set only one."
|
|
680
|
-
);
|
|
681
|
-
}
|
|
682
741
|
const cloudSelection = resolveCloudSelection({
|
|
683
742
|
cloud: resolved.cloud
|
|
684
743
|
}, env);
|
|
@@ -689,11 +748,6 @@ function resolveConfigWithEnv(input = {}, options = {}) {
|
|
|
689
748
|
accessToken: resolvedCloudAccessTokenRaw,
|
|
690
749
|
...resolvedCloudRest
|
|
691
750
|
} = resolvedCloud;
|
|
692
|
-
if (normalizeNonEmptyString(resolvedCloudApiKeyRaw) && normalizeNonEmptyString(resolvedCloudAccessTokenRaw)) {
|
|
693
|
-
throw new Error(
|
|
694
|
-
"Cloud config cannot include both apiKey and accessToken at the same time."
|
|
695
|
-
);
|
|
696
|
-
}
|
|
697
751
|
const resolvedCloudBrowserProfile = normalizeCloudBrowserProfileOptions(
|
|
698
752
|
resolvedCloud.browserProfile,
|
|
699
753
|
"resolved.cloud.browserProfile"
|
|
@@ -705,25 +759,40 @@ function resolveConfigWithEnv(input = {}, options = {}) {
|
|
|
705
759
|
const browserProfile = inputCloudBrowserProfile ?? envCloudBrowserProfile ?? resolvedCloudBrowserProfile;
|
|
706
760
|
let authScheme = inputAuthScheme ?? envAuthScheme ?? parseAuthScheme(resolvedCloud.authScheme, "cloud.authScheme") ?? "api-key";
|
|
707
761
|
const announce = inputCloudAnnounce ?? envCloudAnnounce ?? parseCloudAnnounce(resolvedCloud.announce, "cloud.announce") ?? "always";
|
|
708
|
-
const
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
762
|
+
const selectedCredentialLayer = selectCloudCredentialByPrecedence(
|
|
763
|
+
[
|
|
764
|
+
{
|
|
765
|
+
source: "input",
|
|
766
|
+
apiKey: inputCloudOptions?.apiKey,
|
|
767
|
+
accessToken: inputCloudOptions?.accessToken,
|
|
768
|
+
hasApiKey: inputHasCloudApiKey,
|
|
769
|
+
hasAccessToken: inputHasCloudAccessToken
|
|
770
|
+
},
|
|
771
|
+
{
|
|
772
|
+
source: "env",
|
|
773
|
+
apiKey: envApiKey,
|
|
774
|
+
accessToken: envAccessTokenRaw,
|
|
775
|
+
hasApiKey: envApiKey !== void 0,
|
|
776
|
+
hasAccessToken: envAccessTokenRaw !== void 0
|
|
777
|
+
},
|
|
778
|
+
{
|
|
779
|
+
source: "file",
|
|
780
|
+
apiKey: fileCloudOptions?.apiKey,
|
|
781
|
+
accessToken: fileCloudOptions?.accessToken,
|
|
782
|
+
hasApiKey: fileHasCloudApiKey,
|
|
783
|
+
hasAccessToken: fileHasCloudAccessToken
|
|
784
|
+
}
|
|
785
|
+
],
|
|
786
|
+
authScheme
|
|
787
|
+
);
|
|
788
|
+
const { apiKey, accessToken } = resolveCloudCredentialFields(selectedCredentialLayer);
|
|
720
789
|
if (accessToken) {
|
|
721
790
|
authScheme = "bearer";
|
|
722
791
|
}
|
|
723
792
|
resolved.cloud = {
|
|
724
793
|
...resolvedCloudRest,
|
|
725
|
-
...
|
|
726
|
-
...
|
|
794
|
+
...apiKey ? { apiKey } : selectedCredentialLayer?.hasApiKey && !accessToken ? { apiKey: selectedCredentialLayer.apiKey } : {},
|
|
795
|
+
...accessToken ? { accessToken } : selectedCredentialLayer?.hasAccessToken && !apiKey ? { accessToken: selectedCredentialLayer.accessToken } : {},
|
|
727
796
|
authScheme,
|
|
728
797
|
announce,
|
|
729
798
|
...browserProfile ? { browserProfile } : {}
|
|
@@ -1300,6 +1369,7 @@ export {
|
|
|
1300
1369
|
createKeychainStore,
|
|
1301
1370
|
extractErrorMessage,
|
|
1302
1371
|
normalizeError,
|
|
1372
|
+
selectCloudCredential,
|
|
1303
1373
|
normalizeNamespace,
|
|
1304
1374
|
resolveNamespaceDir,
|
|
1305
1375
|
resolveCloudSelection,
|