opensteer 0.6.2 → 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/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-7RMY26CM.js → chunk-SCNX4NN3.js} +32 -54
- package/dist/cli/auth.cjs +133 -89
- package/dist/cli/auth.js +2 -2
- package/dist/cli/profile.cjs +140 -104
- package/dist/cli/profile.js +4 -4
- 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
|
@@ -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,
|
|
@@ -4,67 +4,30 @@ import {
|
|
|
4
4
|
normalizeCloudBaseUrl,
|
|
5
5
|
resolveCloudSelection,
|
|
6
6
|
resolveConfigWithEnv,
|
|
7
|
+
selectCloudCredential,
|
|
7
8
|
stripTrailingSlashes
|
|
8
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-KE35RQOJ.js";
|
|
9
10
|
|
|
10
11
|
// src/cli/auth.ts
|
|
11
12
|
import open from "open";
|
|
12
13
|
|
|
13
14
|
// src/auth/credential-resolver.ts
|
|
14
15
|
function resolveCloudCredential(options) {
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
return {
|
|
22
|
-
kind: "access-token",
|
|
23
|
-
source: "flag",
|
|
24
|
-
token: flagAccessToken,
|
|
25
|
-
authScheme: "bearer"
|
|
26
|
-
};
|
|
27
|
-
}
|
|
28
|
-
if (flagApiKey) {
|
|
29
|
-
return {
|
|
30
|
-
kind: "api-key",
|
|
31
|
-
source: "flag",
|
|
32
|
-
token: flagApiKey,
|
|
33
|
-
authScheme: "api-key"
|
|
34
|
-
};
|
|
16
|
+
const flagCredential = selectCloudCredential({
|
|
17
|
+
apiKey: options.apiKeyFlag,
|
|
18
|
+
accessToken: options.accessTokenFlag
|
|
19
|
+
});
|
|
20
|
+
if (flagCredential) {
|
|
21
|
+
return toResolvedCloudCredential("flag", flagCredential);
|
|
35
22
|
}
|
|
36
23
|
const envAuthScheme = parseEnvAuthScheme(options.env.OPENSTEER_AUTH_SCHEME);
|
|
37
|
-
const
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
if (envAccessToken) {
|
|
45
|
-
return {
|
|
46
|
-
kind: "access-token",
|
|
47
|
-
source: "env",
|
|
48
|
-
token: envAccessToken,
|
|
49
|
-
authScheme: "bearer"
|
|
50
|
-
};
|
|
51
|
-
}
|
|
52
|
-
if (envApiKey) {
|
|
53
|
-
if (envAuthScheme === "bearer") {
|
|
54
|
-
return {
|
|
55
|
-
kind: "access-token",
|
|
56
|
-
source: "env",
|
|
57
|
-
token: envApiKey,
|
|
58
|
-
authScheme: "bearer",
|
|
59
|
-
compatibilityBearerApiKey: true
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
return {
|
|
63
|
-
kind: "api-key",
|
|
64
|
-
source: "env",
|
|
65
|
-
token: envApiKey,
|
|
66
|
-
authScheme: envAuthScheme ?? "api-key"
|
|
67
|
-
};
|
|
24
|
+
const envCredential = selectCloudCredential({
|
|
25
|
+
apiKey: options.env.OPENSTEER_API_KEY,
|
|
26
|
+
accessToken: options.env.OPENSTEER_ACCESS_TOKEN,
|
|
27
|
+
authScheme: envAuthScheme
|
|
28
|
+
});
|
|
29
|
+
if (envCredential) {
|
|
30
|
+
return toResolvedCloudCredential("env", envCredential);
|
|
68
31
|
}
|
|
69
32
|
return null;
|
|
70
33
|
}
|
|
@@ -94,6 +57,23 @@ function normalizeToken(value) {
|
|
|
94
57
|
const normalized = value.trim();
|
|
95
58
|
return normalized.length ? normalized : void 0;
|
|
96
59
|
}
|
|
60
|
+
function toResolvedCloudCredential(source, credential) {
|
|
61
|
+
if (credential.compatibilityBearerApiKey) {
|
|
62
|
+
return {
|
|
63
|
+
kind: credential.kind,
|
|
64
|
+
source,
|
|
65
|
+
token: credential.token,
|
|
66
|
+
authScheme: credential.authScheme,
|
|
67
|
+
compatibilityBearerApiKey: true
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
return {
|
|
71
|
+
kind: credential.kind,
|
|
72
|
+
source,
|
|
73
|
+
token: credential.token,
|
|
74
|
+
authScheme: credential.authScheme
|
|
75
|
+
};
|
|
76
|
+
}
|
|
97
77
|
|
|
98
78
|
// src/auth/machine-credential-store.ts
|
|
99
79
|
import { createHash } from "crypto";
|
|
@@ -1025,8 +1005,6 @@ async function runLogin(args, deps) {
|
|
|
1025
1005
|
return 0;
|
|
1026
1006
|
}
|
|
1027
1007
|
writeHumanLine(deps, "Opensteer CLI login successful.");
|
|
1028
|
-
writeHumanLine(deps, ` API Base URL: ${baseUrl}`);
|
|
1029
|
-
writeHumanLine(deps, ` Expires At: ${new Date(login.expiresAt).toISOString()}`);
|
|
1030
1008
|
return 0;
|
|
1031
1009
|
}
|
|
1032
1010
|
async function runStatus(args, deps) {
|
package/dist/cli/auth.cjs
CHANGED
|
@@ -94,6 +94,65 @@ function toNonEmptyString(value) {
|
|
|
94
94
|
return normalized.length ? normalized : void 0;
|
|
95
95
|
}
|
|
96
96
|
|
|
97
|
+
// src/cloud/credential-selection.ts
|
|
98
|
+
function selectCloudCredential(options) {
|
|
99
|
+
const apiKey = normalizeNonEmptyString(options.apiKey);
|
|
100
|
+
const accessToken = normalizeNonEmptyString(options.accessToken);
|
|
101
|
+
if (apiKey) {
|
|
102
|
+
if (options.authScheme === "bearer") {
|
|
103
|
+
return {
|
|
104
|
+
apiKey,
|
|
105
|
+
authScheme: "bearer",
|
|
106
|
+
kind: "access-token",
|
|
107
|
+
token: apiKey,
|
|
108
|
+
compatibilityBearerApiKey: true
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
return {
|
|
112
|
+
apiKey,
|
|
113
|
+
authScheme: "api-key",
|
|
114
|
+
kind: "api-key",
|
|
115
|
+
token: apiKey
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
if (accessToken) {
|
|
119
|
+
return {
|
|
120
|
+
accessToken,
|
|
121
|
+
authScheme: "bearer",
|
|
122
|
+
kind: "access-token",
|
|
123
|
+
token: accessToken
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
return null;
|
|
127
|
+
}
|
|
128
|
+
function selectCloudCredentialByPrecedence(layers, authScheme) {
|
|
129
|
+
for (const layer of layers) {
|
|
130
|
+
const hasApiKey = layer.hasApiKey ?? Object.prototype.hasOwnProperty.call(layer, "apiKey");
|
|
131
|
+
const hasAccessToken = layer.hasAccessToken ?? Object.prototype.hasOwnProperty.call(layer, "accessToken");
|
|
132
|
+
if (!hasApiKey && !hasAccessToken) {
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
return {
|
|
136
|
+
source: layer.source,
|
|
137
|
+
apiKey: layer.apiKey,
|
|
138
|
+
accessToken: layer.accessToken,
|
|
139
|
+
hasApiKey,
|
|
140
|
+
hasAccessToken,
|
|
141
|
+
credential: selectCloudCredential({
|
|
142
|
+
apiKey: layer.apiKey,
|
|
143
|
+
accessToken: layer.accessToken,
|
|
144
|
+
authScheme: layer.authScheme ?? authScheme
|
|
145
|
+
})
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
return null;
|
|
149
|
+
}
|
|
150
|
+
function normalizeNonEmptyString(value) {
|
|
151
|
+
if (typeof value !== "string") return void 0;
|
|
152
|
+
const normalized = value.trim();
|
|
153
|
+
return normalized.length ? normalized : void 0;
|
|
154
|
+
}
|
|
155
|
+
|
|
97
156
|
// src/config.ts
|
|
98
157
|
var DEFAULT_CONFIG = {
|
|
99
158
|
browser: {
|
|
@@ -386,11 +445,6 @@ function normalizeCloudOptions(value) {
|
|
|
386
445
|
}
|
|
387
446
|
return value;
|
|
388
447
|
}
|
|
389
|
-
function normalizeNonEmptyString(value) {
|
|
390
|
-
if (typeof value !== "string") return void 0;
|
|
391
|
-
const normalized = value.trim();
|
|
392
|
-
return normalized.length ? normalized : void 0;
|
|
393
|
-
}
|
|
394
448
|
function parseCloudEnabled(value, source) {
|
|
395
449
|
if (value == null) return void 0;
|
|
396
450
|
if (typeof value === "boolean") return value;
|
|
@@ -399,6 +453,18 @@ function parseCloudEnabled(value, source) {
|
|
|
399
453
|
`Invalid ${source} value "${String(value)}". Use true, false, or a cloud options object.`
|
|
400
454
|
);
|
|
401
455
|
}
|
|
456
|
+
function resolveCloudCredentialFields(selectedLayer) {
|
|
457
|
+
const credential = selectedLayer?.credential;
|
|
458
|
+
if (!credential) return {};
|
|
459
|
+
if (credential.kind === "api-key" || credential.compatibilityBearerApiKey === true && selectedLayer?.source !== "env") {
|
|
460
|
+
return {
|
|
461
|
+
apiKey: credential.token
|
|
462
|
+
};
|
|
463
|
+
}
|
|
464
|
+
return {
|
|
465
|
+
accessToken: credential.token
|
|
466
|
+
};
|
|
467
|
+
}
|
|
402
468
|
function resolveCloudSelection(config, env = process.env) {
|
|
403
469
|
const configCloud = parseCloudEnabled(config.cloud, "cloud");
|
|
404
470
|
if (configCloud !== void 0) {
|
|
@@ -435,6 +501,9 @@ function resolveConfigWithEnv(input = {}, options = {}) {
|
|
|
435
501
|
});
|
|
436
502
|
assertNoLegacyAiConfig(".opensteer/config.json", fileConfig);
|
|
437
503
|
assertNoLegacyRuntimeConfig(".opensteer/config.json", fileConfig);
|
|
504
|
+
const fileCloudOptions = normalizeCloudOptions(fileConfig.cloud);
|
|
505
|
+
const fileHasCloudApiKey = hasOwn(fileCloudOptions, "apiKey");
|
|
506
|
+
const fileHasCloudAccessToken = hasOwn(fileCloudOptions, "accessToken");
|
|
438
507
|
const fileRootDir = typeof fileConfig.storage?.rootDir === "string" ? fileConfig.storage.rootDir : void 0;
|
|
439
508
|
const envRootDir = input.storage?.rootDir ?? fileRootDir ?? initialRootDir;
|
|
440
509
|
const env = resolveEnv(envRootDir, {
|
|
@@ -473,13 +542,6 @@ function resolveConfigWithEnv(input = {}, options = {}) {
|
|
|
473
542
|
const envAccessTokenRaw = resolveOpensteerAccessToken(env);
|
|
474
543
|
const envBaseUrl = resolveOpensteerBaseUrl(env);
|
|
475
544
|
const envAuthScheme = resolveOpensteerAuthScheme(env);
|
|
476
|
-
if (envApiKey && envAccessTokenRaw) {
|
|
477
|
-
throw new Error(
|
|
478
|
-
"OPENSTEER_API_KEY and OPENSTEER_ACCESS_TOKEN are mutually exclusive. Set only one."
|
|
479
|
-
);
|
|
480
|
-
}
|
|
481
|
-
const envAccessToken = envAccessTokenRaw || (envAuthScheme === "bearer" ? envApiKey : void 0);
|
|
482
|
-
const envApiCredential = envAuthScheme === "bearer" && !envAccessTokenRaw ? void 0 : envApiKey;
|
|
483
545
|
const envCloudProfileId = resolveOpensteerCloudProfileId(env);
|
|
484
546
|
const envCloudProfileReuseIfActive = resolveOpensteerCloudProfileReuseIfActive(env);
|
|
485
547
|
const envCloudAnnounce = parseCloudAnnounce(
|
|
@@ -508,11 +570,6 @@ function resolveConfigWithEnv(input = {}, options = {}) {
|
|
|
508
570
|
const inputHasCloudBaseUrl = Boolean(
|
|
509
571
|
inputCloudOptions && Object.prototype.hasOwnProperty.call(inputCloudOptions, "baseUrl")
|
|
510
572
|
);
|
|
511
|
-
if (normalizeNonEmptyString(inputCloudOptions?.apiKey) && normalizeNonEmptyString(inputCloudOptions?.accessToken)) {
|
|
512
|
-
throw new Error(
|
|
513
|
-
"cloud.apiKey and cloud.accessToken are mutually exclusive. Set only one."
|
|
514
|
-
);
|
|
515
|
-
}
|
|
516
573
|
const cloudSelection = resolveCloudSelection({
|
|
517
574
|
cloud: resolved.cloud
|
|
518
575
|
}, env);
|
|
@@ -523,11 +580,6 @@ function resolveConfigWithEnv(input = {}, options = {}) {
|
|
|
523
580
|
accessToken: resolvedCloudAccessTokenRaw,
|
|
524
581
|
...resolvedCloudRest
|
|
525
582
|
} = resolvedCloud;
|
|
526
|
-
if (normalizeNonEmptyString(resolvedCloudApiKeyRaw) && normalizeNonEmptyString(resolvedCloudAccessTokenRaw)) {
|
|
527
|
-
throw new Error(
|
|
528
|
-
"Cloud config cannot include both apiKey and accessToken at the same time."
|
|
529
|
-
);
|
|
530
|
-
}
|
|
531
583
|
const resolvedCloudBrowserProfile = normalizeCloudBrowserProfileOptions(
|
|
532
584
|
resolvedCloud.browserProfile,
|
|
533
585
|
"resolved.cloud.browserProfile"
|
|
@@ -539,25 +591,40 @@ function resolveConfigWithEnv(input = {}, options = {}) {
|
|
|
539
591
|
const browserProfile = inputCloudBrowserProfile ?? envCloudBrowserProfile ?? resolvedCloudBrowserProfile;
|
|
540
592
|
let authScheme = inputAuthScheme ?? envAuthScheme ?? parseAuthScheme(resolvedCloud.authScheme, "cloud.authScheme") ?? "api-key";
|
|
541
593
|
const announce = inputCloudAnnounce ?? envCloudAnnounce ?? parseCloudAnnounce(resolvedCloud.announce, "cloud.announce") ?? "always";
|
|
542
|
-
const
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
594
|
+
const selectedCredentialLayer = selectCloudCredentialByPrecedence(
|
|
595
|
+
[
|
|
596
|
+
{
|
|
597
|
+
source: "input",
|
|
598
|
+
apiKey: inputCloudOptions?.apiKey,
|
|
599
|
+
accessToken: inputCloudOptions?.accessToken,
|
|
600
|
+
hasApiKey: inputHasCloudApiKey,
|
|
601
|
+
hasAccessToken: inputHasCloudAccessToken
|
|
602
|
+
},
|
|
603
|
+
{
|
|
604
|
+
source: "env",
|
|
605
|
+
apiKey: envApiKey,
|
|
606
|
+
accessToken: envAccessTokenRaw,
|
|
607
|
+
hasApiKey: envApiKey !== void 0,
|
|
608
|
+
hasAccessToken: envAccessTokenRaw !== void 0
|
|
609
|
+
},
|
|
610
|
+
{
|
|
611
|
+
source: "file",
|
|
612
|
+
apiKey: fileCloudOptions?.apiKey,
|
|
613
|
+
accessToken: fileCloudOptions?.accessToken,
|
|
614
|
+
hasApiKey: fileHasCloudApiKey,
|
|
615
|
+
hasAccessToken: fileHasCloudAccessToken
|
|
616
|
+
}
|
|
617
|
+
],
|
|
618
|
+
authScheme
|
|
619
|
+
);
|
|
620
|
+
const { apiKey, accessToken } = resolveCloudCredentialFields(selectedCredentialLayer);
|
|
554
621
|
if (accessToken) {
|
|
555
622
|
authScheme = "bearer";
|
|
556
623
|
}
|
|
557
624
|
resolved.cloud = {
|
|
558
625
|
...resolvedCloudRest,
|
|
559
|
-
...
|
|
560
|
-
...
|
|
626
|
+
...apiKey ? { apiKey } : selectedCredentialLayer?.hasApiKey && !accessToken ? { apiKey: selectedCredentialLayer.apiKey } : {},
|
|
627
|
+
...accessToken ? { accessToken } : selectedCredentialLayer?.hasAccessToken && !apiKey ? { accessToken: selectedCredentialLayer.accessToken } : {},
|
|
561
628
|
authScheme,
|
|
562
629
|
announce,
|
|
563
630
|
...browserProfile ? { browserProfile } : {}
|
|
@@ -577,59 +644,21 @@ function resolveConfigWithEnv(input = {}, options = {}) {
|
|
|
577
644
|
|
|
578
645
|
// src/auth/credential-resolver.ts
|
|
579
646
|
function resolveCloudCredential(options) {
|
|
580
|
-
const
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
return {
|
|
587
|
-
kind: "access-token",
|
|
588
|
-
source: "flag",
|
|
589
|
-
token: flagAccessToken,
|
|
590
|
-
authScheme: "bearer"
|
|
591
|
-
};
|
|
592
|
-
}
|
|
593
|
-
if (flagApiKey) {
|
|
594
|
-
return {
|
|
595
|
-
kind: "api-key",
|
|
596
|
-
source: "flag",
|
|
597
|
-
token: flagApiKey,
|
|
598
|
-
authScheme: "api-key"
|
|
599
|
-
};
|
|
647
|
+
const flagCredential = selectCloudCredential({
|
|
648
|
+
apiKey: options.apiKeyFlag,
|
|
649
|
+
accessToken: options.accessTokenFlag
|
|
650
|
+
});
|
|
651
|
+
if (flagCredential) {
|
|
652
|
+
return toResolvedCloudCredential("flag", flagCredential);
|
|
600
653
|
}
|
|
601
654
|
const envAuthScheme = parseEnvAuthScheme(options.env.OPENSTEER_AUTH_SCHEME);
|
|
602
|
-
const
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
if (envAccessToken) {
|
|
610
|
-
return {
|
|
611
|
-
kind: "access-token",
|
|
612
|
-
source: "env",
|
|
613
|
-
token: envAccessToken,
|
|
614
|
-
authScheme: "bearer"
|
|
615
|
-
};
|
|
616
|
-
}
|
|
617
|
-
if (envApiKey) {
|
|
618
|
-
if (envAuthScheme === "bearer") {
|
|
619
|
-
return {
|
|
620
|
-
kind: "access-token",
|
|
621
|
-
source: "env",
|
|
622
|
-
token: envApiKey,
|
|
623
|
-
authScheme: "bearer",
|
|
624
|
-
compatibilityBearerApiKey: true
|
|
625
|
-
};
|
|
626
|
-
}
|
|
627
|
-
return {
|
|
628
|
-
kind: "api-key",
|
|
629
|
-
source: "env",
|
|
630
|
-
token: envApiKey,
|
|
631
|
-
authScheme: envAuthScheme ?? "api-key"
|
|
632
|
-
};
|
|
655
|
+
const envCredential = selectCloudCredential({
|
|
656
|
+
apiKey: options.env.OPENSTEER_API_KEY,
|
|
657
|
+
accessToken: options.env.OPENSTEER_ACCESS_TOKEN,
|
|
658
|
+
authScheme: envAuthScheme
|
|
659
|
+
});
|
|
660
|
+
if (envCredential) {
|
|
661
|
+
return toResolvedCloudCredential("env", envCredential);
|
|
633
662
|
}
|
|
634
663
|
return null;
|
|
635
664
|
}
|
|
@@ -659,6 +688,23 @@ function normalizeToken(value) {
|
|
|
659
688
|
const normalized = value.trim();
|
|
660
689
|
return normalized.length ? normalized : void 0;
|
|
661
690
|
}
|
|
691
|
+
function toResolvedCloudCredential(source, credential) {
|
|
692
|
+
if (credential.compatibilityBearerApiKey) {
|
|
693
|
+
return {
|
|
694
|
+
kind: credential.kind,
|
|
695
|
+
source,
|
|
696
|
+
token: credential.token,
|
|
697
|
+
authScheme: credential.authScheme,
|
|
698
|
+
compatibilityBearerApiKey: true
|
|
699
|
+
};
|
|
700
|
+
}
|
|
701
|
+
return {
|
|
702
|
+
kind: credential.kind,
|
|
703
|
+
source,
|
|
704
|
+
token: credential.token,
|
|
705
|
+
authScheme: credential.authScheme
|
|
706
|
+
};
|
|
707
|
+
}
|
|
662
708
|
|
|
663
709
|
// src/auth/machine-credential-store.ts
|
|
664
710
|
var import_node_crypto = require("crypto");
|
|
@@ -1729,8 +1775,6 @@ async function runLogin(args, deps) {
|
|
|
1729
1775
|
return 0;
|
|
1730
1776
|
}
|
|
1731
1777
|
writeHumanLine(deps, "Opensteer CLI login successful.");
|
|
1732
|
-
writeHumanLine(deps, ` API Base URL: ${baseUrl}`);
|
|
1733
|
-
writeHumanLine(deps, ` Expires At: ${new Date(login.expiresAt).toISOString()}`);
|
|
1734
1778
|
return 0;
|
|
1735
1779
|
}
|
|
1736
1780
|
async function runStatus(args, deps) {
|