opensteer 0.4.7 → 0.4.8
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/CHANGELOG.md +2 -0
- package/README.md +5 -0
- package/dist/{chunk-PIJI7FBH.js → chunk-GQ7HNCM2.js} +83 -33
- package/dist/cli/server.cjs +83 -33
- package/dist/cli/server.js +1 -1
- package/dist/index.cjs +83 -33
- package/dist/index.js +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -21,6 +21,8 @@
|
|
|
21
21
|
- Breaking: `OPENSTEER_MODE` now uses `local` or `cloud`; `remote` is no longer a supported value.
|
|
22
22
|
- Opensteer now enables built-in LLM resolve/extract by default with model `gpt-5.1`.
|
|
23
23
|
- Cloud mode now falls back to `OPENSTEER_API_KEY` when `cloud.apiKey` is omitted.
|
|
24
|
+
- Added automatic `.env` loading from `storage.rootDir` (default `process.cwd()`) so constructor config can consume env vars without requiring `import 'dotenv/config'`.
|
|
25
|
+
- `.env` autoload follows common precedence (`.env.<NODE_ENV>.local`, `.env.local`, `.env.<NODE_ENV>`, `.env`) with `.env.local` skipped in `test`, does not overwrite existing env values, and can be disabled via `OPENSTEER_DISABLE_DOTENV_AUTOLOAD`.
|
|
24
26
|
- Mutating actions now include smart best-effort post-action wait with per-action
|
|
25
27
|
profiles and optional per-call overrides via `wait`.
|
|
26
28
|
- Added structured interaction diagnostics via `OpensteerActionError` for
|
package/README.md
CHANGED
|
@@ -164,6 +164,11 @@ Opensteer defaults to local mode.
|
|
|
164
164
|
- `OPENSTEER_MODE=local` runs local Playwright.
|
|
165
165
|
- `OPENSTEER_MODE=cloud` enables cloud mode (requires `OPENSTEER_API_KEY`).
|
|
166
166
|
- `cloud: true` in constructor config always enables cloud mode.
|
|
167
|
+
- Opensteer auto-loads `.env` files from your `storage.rootDir` (default:
|
|
168
|
+
`process.cwd()`) using this order: `.env.<NODE_ENV>.local`, `.env.local`
|
|
169
|
+
(skipped when `NODE_ENV=test`), `.env.<NODE_ENV>`, `.env`.
|
|
170
|
+
- Existing `process.env` values are never overwritten by `.env` values.
|
|
171
|
+
- Set `OPENSTEER_DISABLE_DOTENV_AUTOLOAD=true` to disable auto-loading.
|
|
167
172
|
|
|
168
173
|
Cloud mode is fail-fast: it does not automatically fall back to local mode.
|
|
169
174
|
|
|
@@ -5981,6 +5981,7 @@ var BrowserPool = class {
|
|
|
5981
5981
|
import fs3 from "fs";
|
|
5982
5982
|
import path4 from "path";
|
|
5983
5983
|
import { fileURLToPath } from "url";
|
|
5984
|
+
import { parse as parseDotenv } from "dotenv";
|
|
5984
5985
|
var DEFAULT_CONFIG = {
|
|
5985
5986
|
browser: {
|
|
5986
5987
|
headless: false,
|
|
@@ -5996,6 +5997,53 @@ var DEFAULT_CONFIG = {
|
|
|
5996
5997
|
model: "gpt-5.1",
|
|
5997
5998
|
debug: false
|
|
5998
5999
|
};
|
|
6000
|
+
function dotenvFileOrder(nodeEnv) {
|
|
6001
|
+
const normalized = nodeEnv?.trim() || "";
|
|
6002
|
+
const files = [];
|
|
6003
|
+
if (normalized) {
|
|
6004
|
+
files.push(`.env.${normalized}.local`);
|
|
6005
|
+
}
|
|
6006
|
+
if (normalized !== "test") {
|
|
6007
|
+
files.push(".env.local");
|
|
6008
|
+
}
|
|
6009
|
+
if (normalized) {
|
|
6010
|
+
files.push(`.env.${normalized}`);
|
|
6011
|
+
}
|
|
6012
|
+
files.push(".env");
|
|
6013
|
+
return files;
|
|
6014
|
+
}
|
|
6015
|
+
function loadDotenvValues(rootDir, baseEnv) {
|
|
6016
|
+
const values = {};
|
|
6017
|
+
if (parseBool(baseEnv.OPENSTEER_DISABLE_DOTENV_AUTOLOAD) === true) {
|
|
6018
|
+
return values;
|
|
6019
|
+
}
|
|
6020
|
+
const baseDir = path4.resolve(rootDir);
|
|
6021
|
+
const nodeEnv = baseEnv.NODE_ENV?.trim() || "";
|
|
6022
|
+
for (const filename of dotenvFileOrder(nodeEnv)) {
|
|
6023
|
+
const filePath = path4.join(baseDir, filename);
|
|
6024
|
+
if (!fs3.existsSync(filePath)) continue;
|
|
6025
|
+
try {
|
|
6026
|
+
const raw = fs3.readFileSync(filePath, "utf8");
|
|
6027
|
+
const parsed = parseDotenv(raw);
|
|
6028
|
+
for (const [key, value] of Object.entries(parsed)) {
|
|
6029
|
+
if (values[key] === void 0) {
|
|
6030
|
+
values[key] = value;
|
|
6031
|
+
}
|
|
6032
|
+
}
|
|
6033
|
+
} catch {
|
|
6034
|
+
continue;
|
|
6035
|
+
}
|
|
6036
|
+
}
|
|
6037
|
+
return values;
|
|
6038
|
+
}
|
|
6039
|
+
function resolveEnv(rootDir) {
|
|
6040
|
+
const baseEnv = process.env;
|
|
6041
|
+
const dotenvValues = loadDotenvValues(rootDir, baseEnv);
|
|
6042
|
+
return {
|
|
6043
|
+
...dotenvValues,
|
|
6044
|
+
...baseEnv
|
|
6045
|
+
};
|
|
6046
|
+
}
|
|
5999
6047
|
function hasOwn(config, key) {
|
|
6000
6048
|
if (!config || typeof config !== "object") return false;
|
|
6001
6049
|
return Object.prototype.hasOwnProperty.call(config, key);
|
|
@@ -6124,16 +6172,13 @@ function parseCloudAnnounce(value, source) {
|
|
|
6124
6172
|
`Invalid ${source} value "${value}". Use "always", "off", or "tty".`
|
|
6125
6173
|
);
|
|
6126
6174
|
}
|
|
6127
|
-
function resolveOpensteerApiKey() {
|
|
6128
|
-
const value =
|
|
6175
|
+
function resolveOpensteerApiKey(env) {
|
|
6176
|
+
const value = env.OPENSTEER_API_KEY?.trim();
|
|
6129
6177
|
if (!value) return void 0;
|
|
6130
6178
|
return value;
|
|
6131
6179
|
}
|
|
6132
|
-
function resolveOpensteerAuthScheme() {
|
|
6133
|
-
return parseAuthScheme(
|
|
6134
|
-
process.env.OPENSTEER_AUTH_SCHEME,
|
|
6135
|
-
"OPENSTEER_AUTH_SCHEME"
|
|
6136
|
-
);
|
|
6180
|
+
function resolveOpensteerAuthScheme(env) {
|
|
6181
|
+
return parseAuthScheme(env.OPENSTEER_AUTH_SCHEME, "OPENSTEER_AUTH_SCHEME");
|
|
6137
6182
|
}
|
|
6138
6183
|
function normalizeCloudOptions(value) {
|
|
6139
6184
|
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
@@ -6149,7 +6194,7 @@ function parseCloudEnabled(value, source) {
|
|
|
6149
6194
|
`Invalid ${source} value "${String(value)}". Use true, false, or a cloud options object.`
|
|
6150
6195
|
);
|
|
6151
6196
|
}
|
|
6152
|
-
function resolveCloudSelection(config) {
|
|
6197
|
+
function resolveCloudSelection(config, env = process.env) {
|
|
6153
6198
|
const configCloud = parseCloudEnabled(config.cloud, "cloud");
|
|
6154
6199
|
if (configCloud !== void 0) {
|
|
6155
6200
|
return {
|
|
@@ -6157,10 +6202,7 @@ function resolveCloudSelection(config) {
|
|
|
6157
6202
|
source: "config.cloud"
|
|
6158
6203
|
};
|
|
6159
6204
|
}
|
|
6160
|
-
const envMode = parseRuntimeMode(
|
|
6161
|
-
process.env.OPENSTEER_MODE,
|
|
6162
|
-
"OPENSTEER_MODE"
|
|
6163
|
-
);
|
|
6205
|
+
const envMode = parseRuntimeMode(env.OPENSTEER_MODE, "OPENSTEER_MODE");
|
|
6164
6206
|
if (envMode) {
|
|
6165
6207
|
return {
|
|
6166
6208
|
cloud: envMode === "cloud",
|
|
@@ -6173,41 +6215,49 @@ function resolveCloudSelection(config) {
|
|
|
6173
6215
|
};
|
|
6174
6216
|
}
|
|
6175
6217
|
function resolveConfig(input = {}) {
|
|
6176
|
-
|
|
6218
|
+
const initialRootDir = input.storage?.rootDir ?? process.cwd();
|
|
6219
|
+
const runtimeDefaults = mergeDeep(DEFAULT_CONFIG, {
|
|
6220
|
+
storage: {
|
|
6221
|
+
rootDir: initialRootDir
|
|
6222
|
+
}
|
|
6223
|
+
});
|
|
6224
|
+
assertNoLegacyAiConfig("Opensteer constructor config", input);
|
|
6225
|
+
assertNoLegacyRuntimeConfig("Opensteer constructor config", input);
|
|
6226
|
+
const fileConfig = loadConfigFile(initialRootDir);
|
|
6227
|
+
assertNoLegacyAiConfig(".opensteer/config.json", fileConfig);
|
|
6228
|
+
assertNoLegacyRuntimeConfig(".opensteer/config.json", fileConfig);
|
|
6229
|
+
const fileRootDir = typeof fileConfig.storage?.rootDir === "string" ? fileConfig.storage.rootDir : void 0;
|
|
6230
|
+
const envRootDir = input.storage?.rootDir ?? fileRootDir ?? initialRootDir;
|
|
6231
|
+
const env = resolveEnv(envRootDir);
|
|
6232
|
+
if (env.OPENSTEER_AI_MODEL) {
|
|
6177
6233
|
throw new Error(
|
|
6178
6234
|
"OPENSTEER_AI_MODEL is no longer supported. Use OPENSTEER_MODEL instead."
|
|
6179
6235
|
);
|
|
6180
6236
|
}
|
|
6181
|
-
if (
|
|
6237
|
+
if (env.OPENSTEER_RUNTIME != null) {
|
|
6182
6238
|
throw new Error(
|
|
6183
6239
|
"OPENSTEER_RUNTIME is no longer supported. Use OPENSTEER_MODE instead."
|
|
6184
6240
|
);
|
|
6185
6241
|
}
|
|
6186
|
-
assertNoLegacyAiConfig("Opensteer constructor config", input);
|
|
6187
|
-
assertNoLegacyRuntimeConfig("Opensteer constructor config", input);
|
|
6188
|
-
const rootDir = input.storage?.rootDir ?? DEFAULT_CONFIG.storage.rootDir ?? process.cwd();
|
|
6189
|
-
const fileConfig = loadConfigFile(rootDir);
|
|
6190
|
-
assertNoLegacyAiConfig(".opensteer/config.json", fileConfig);
|
|
6191
|
-
assertNoLegacyRuntimeConfig(".opensteer/config.json", fileConfig);
|
|
6192
6242
|
const envConfig = {
|
|
6193
6243
|
browser: {
|
|
6194
|
-
headless: parseBool(
|
|
6195
|
-
executablePath:
|
|
6196
|
-
slowMo: parseNumber(
|
|
6197
|
-
connectUrl:
|
|
6198
|
-
channel:
|
|
6199
|
-
profileDir:
|
|
6244
|
+
headless: parseBool(env.OPENSTEER_HEADLESS),
|
|
6245
|
+
executablePath: env.OPENSTEER_BROWSER_PATH || void 0,
|
|
6246
|
+
slowMo: parseNumber(env.OPENSTEER_SLOW_MO),
|
|
6247
|
+
connectUrl: env.OPENSTEER_CONNECT_URL || void 0,
|
|
6248
|
+
channel: env.OPENSTEER_CHANNEL || void 0,
|
|
6249
|
+
profileDir: env.OPENSTEER_PROFILE_DIR || void 0
|
|
6200
6250
|
},
|
|
6201
|
-
model:
|
|
6202
|
-
debug: parseBool(
|
|
6251
|
+
model: env.OPENSTEER_MODEL || void 0,
|
|
6252
|
+
debug: parseBool(env.OPENSTEER_DEBUG)
|
|
6203
6253
|
};
|
|
6204
|
-
const mergedWithFile = mergeDeep(
|
|
6254
|
+
const mergedWithFile = mergeDeep(runtimeDefaults, fileConfig);
|
|
6205
6255
|
const mergedWithEnv = mergeDeep(mergedWithFile, envConfig);
|
|
6206
6256
|
const resolved = mergeDeep(mergedWithEnv, input);
|
|
6207
|
-
const envApiKey = resolveOpensteerApiKey();
|
|
6208
|
-
const envAuthScheme = resolveOpensteerAuthScheme();
|
|
6257
|
+
const envApiKey = resolveOpensteerApiKey(env);
|
|
6258
|
+
const envAuthScheme = resolveOpensteerAuthScheme(env);
|
|
6209
6259
|
const envCloudAnnounce = parseCloudAnnounce(
|
|
6210
|
-
|
|
6260
|
+
env.OPENSTEER_REMOTE_ANNOUNCE,
|
|
6211
6261
|
"OPENSTEER_REMOTE_ANNOUNCE"
|
|
6212
6262
|
);
|
|
6213
6263
|
const inputCloudOptions = normalizeCloudOptions(input.cloud);
|
|
@@ -6224,7 +6274,7 @@ function resolveConfig(input = {}) {
|
|
|
6224
6274
|
);
|
|
6225
6275
|
const cloudSelection = resolveCloudSelection({
|
|
6226
6276
|
cloud: resolved.cloud
|
|
6227
|
-
});
|
|
6277
|
+
}, env);
|
|
6228
6278
|
if (cloudSelection.cloud) {
|
|
6229
6279
|
const resolvedCloud = normalizeCloudOptions(resolved.cloud) ?? {};
|
|
6230
6280
|
const authScheme = inputAuthScheme ?? envAuthScheme ?? parseAuthScheme(resolvedCloud.authScheme, "cloud.authScheme") ?? "api-key";
|
package/dist/cli/server.cjs
CHANGED
|
@@ -806,6 +806,7 @@ var BrowserPool = class {
|
|
|
806
806
|
var import_fs = __toESM(require("fs"), 1);
|
|
807
807
|
var import_path3 = __toESM(require("path"), 1);
|
|
808
808
|
var import_url = require("url");
|
|
809
|
+
var import_dotenv = require("dotenv");
|
|
809
810
|
|
|
810
811
|
// src/storage/namespace.ts
|
|
811
812
|
var import_path2 = __toESM(require("path"), 1);
|
|
@@ -855,6 +856,53 @@ var DEFAULT_CONFIG = {
|
|
|
855
856
|
model: "gpt-5.1",
|
|
856
857
|
debug: false
|
|
857
858
|
};
|
|
859
|
+
function dotenvFileOrder(nodeEnv) {
|
|
860
|
+
const normalized = nodeEnv?.trim() || "";
|
|
861
|
+
const files = [];
|
|
862
|
+
if (normalized) {
|
|
863
|
+
files.push(`.env.${normalized}.local`);
|
|
864
|
+
}
|
|
865
|
+
if (normalized !== "test") {
|
|
866
|
+
files.push(".env.local");
|
|
867
|
+
}
|
|
868
|
+
if (normalized) {
|
|
869
|
+
files.push(`.env.${normalized}`);
|
|
870
|
+
}
|
|
871
|
+
files.push(".env");
|
|
872
|
+
return files;
|
|
873
|
+
}
|
|
874
|
+
function loadDotenvValues(rootDir, baseEnv) {
|
|
875
|
+
const values = {};
|
|
876
|
+
if (parseBool(baseEnv.OPENSTEER_DISABLE_DOTENV_AUTOLOAD) === true) {
|
|
877
|
+
return values;
|
|
878
|
+
}
|
|
879
|
+
const baseDir = import_path3.default.resolve(rootDir);
|
|
880
|
+
const nodeEnv = baseEnv.NODE_ENV?.trim() || "";
|
|
881
|
+
for (const filename of dotenvFileOrder(nodeEnv)) {
|
|
882
|
+
const filePath = import_path3.default.join(baseDir, filename);
|
|
883
|
+
if (!import_fs.default.existsSync(filePath)) continue;
|
|
884
|
+
try {
|
|
885
|
+
const raw = import_fs.default.readFileSync(filePath, "utf8");
|
|
886
|
+
const parsed = (0, import_dotenv.parse)(raw);
|
|
887
|
+
for (const [key, value] of Object.entries(parsed)) {
|
|
888
|
+
if (values[key] === void 0) {
|
|
889
|
+
values[key] = value;
|
|
890
|
+
}
|
|
891
|
+
}
|
|
892
|
+
} catch {
|
|
893
|
+
continue;
|
|
894
|
+
}
|
|
895
|
+
}
|
|
896
|
+
return values;
|
|
897
|
+
}
|
|
898
|
+
function resolveEnv(rootDir) {
|
|
899
|
+
const baseEnv = process.env;
|
|
900
|
+
const dotenvValues = loadDotenvValues(rootDir, baseEnv);
|
|
901
|
+
return {
|
|
902
|
+
...dotenvValues,
|
|
903
|
+
...baseEnv
|
|
904
|
+
};
|
|
905
|
+
}
|
|
858
906
|
function hasOwn(config, key) {
|
|
859
907
|
if (!config || typeof config !== "object") return false;
|
|
860
908
|
return Object.prototype.hasOwnProperty.call(config, key);
|
|
@@ -983,16 +1031,13 @@ function parseCloudAnnounce(value, source) {
|
|
|
983
1031
|
`Invalid ${source} value "${value}". Use "always", "off", or "tty".`
|
|
984
1032
|
);
|
|
985
1033
|
}
|
|
986
|
-
function resolveOpensteerApiKey() {
|
|
987
|
-
const value =
|
|
1034
|
+
function resolveOpensteerApiKey(env) {
|
|
1035
|
+
const value = env.OPENSTEER_API_KEY?.trim();
|
|
988
1036
|
if (!value) return void 0;
|
|
989
1037
|
return value;
|
|
990
1038
|
}
|
|
991
|
-
function resolveOpensteerAuthScheme() {
|
|
992
|
-
return parseAuthScheme(
|
|
993
|
-
process.env.OPENSTEER_AUTH_SCHEME,
|
|
994
|
-
"OPENSTEER_AUTH_SCHEME"
|
|
995
|
-
);
|
|
1039
|
+
function resolveOpensteerAuthScheme(env) {
|
|
1040
|
+
return parseAuthScheme(env.OPENSTEER_AUTH_SCHEME, "OPENSTEER_AUTH_SCHEME");
|
|
996
1041
|
}
|
|
997
1042
|
function normalizeCloudOptions(value) {
|
|
998
1043
|
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
@@ -1008,7 +1053,7 @@ function parseCloudEnabled(value, source) {
|
|
|
1008
1053
|
`Invalid ${source} value "${String(value)}". Use true, false, or a cloud options object.`
|
|
1009
1054
|
);
|
|
1010
1055
|
}
|
|
1011
|
-
function resolveCloudSelection(config) {
|
|
1056
|
+
function resolveCloudSelection(config, env = process.env) {
|
|
1012
1057
|
const configCloud = parseCloudEnabled(config.cloud, "cloud");
|
|
1013
1058
|
if (configCloud !== void 0) {
|
|
1014
1059
|
return {
|
|
@@ -1016,10 +1061,7 @@ function resolveCloudSelection(config) {
|
|
|
1016
1061
|
source: "config.cloud"
|
|
1017
1062
|
};
|
|
1018
1063
|
}
|
|
1019
|
-
const envMode = parseRuntimeMode(
|
|
1020
|
-
process.env.OPENSTEER_MODE,
|
|
1021
|
-
"OPENSTEER_MODE"
|
|
1022
|
-
);
|
|
1064
|
+
const envMode = parseRuntimeMode(env.OPENSTEER_MODE, "OPENSTEER_MODE");
|
|
1023
1065
|
if (envMode) {
|
|
1024
1066
|
return {
|
|
1025
1067
|
cloud: envMode === "cloud",
|
|
@@ -1032,41 +1074,49 @@ function resolveCloudSelection(config) {
|
|
|
1032
1074
|
};
|
|
1033
1075
|
}
|
|
1034
1076
|
function resolveConfig(input = {}) {
|
|
1035
|
-
|
|
1077
|
+
const initialRootDir = input.storage?.rootDir ?? process.cwd();
|
|
1078
|
+
const runtimeDefaults = mergeDeep(DEFAULT_CONFIG, {
|
|
1079
|
+
storage: {
|
|
1080
|
+
rootDir: initialRootDir
|
|
1081
|
+
}
|
|
1082
|
+
});
|
|
1083
|
+
assertNoLegacyAiConfig("Opensteer constructor config", input);
|
|
1084
|
+
assertNoLegacyRuntimeConfig("Opensteer constructor config", input);
|
|
1085
|
+
const fileConfig = loadConfigFile(initialRootDir);
|
|
1086
|
+
assertNoLegacyAiConfig(".opensteer/config.json", fileConfig);
|
|
1087
|
+
assertNoLegacyRuntimeConfig(".opensteer/config.json", fileConfig);
|
|
1088
|
+
const fileRootDir = typeof fileConfig.storage?.rootDir === "string" ? fileConfig.storage.rootDir : void 0;
|
|
1089
|
+
const envRootDir = input.storage?.rootDir ?? fileRootDir ?? initialRootDir;
|
|
1090
|
+
const env = resolveEnv(envRootDir);
|
|
1091
|
+
if (env.OPENSTEER_AI_MODEL) {
|
|
1036
1092
|
throw new Error(
|
|
1037
1093
|
"OPENSTEER_AI_MODEL is no longer supported. Use OPENSTEER_MODEL instead."
|
|
1038
1094
|
);
|
|
1039
1095
|
}
|
|
1040
|
-
if (
|
|
1096
|
+
if (env.OPENSTEER_RUNTIME != null) {
|
|
1041
1097
|
throw new Error(
|
|
1042
1098
|
"OPENSTEER_RUNTIME is no longer supported. Use OPENSTEER_MODE instead."
|
|
1043
1099
|
);
|
|
1044
1100
|
}
|
|
1045
|
-
assertNoLegacyAiConfig("Opensteer constructor config", input);
|
|
1046
|
-
assertNoLegacyRuntimeConfig("Opensteer constructor config", input);
|
|
1047
|
-
const rootDir = input.storage?.rootDir ?? DEFAULT_CONFIG.storage.rootDir ?? process.cwd();
|
|
1048
|
-
const fileConfig = loadConfigFile(rootDir);
|
|
1049
|
-
assertNoLegacyAiConfig(".opensteer/config.json", fileConfig);
|
|
1050
|
-
assertNoLegacyRuntimeConfig(".opensteer/config.json", fileConfig);
|
|
1051
1101
|
const envConfig = {
|
|
1052
1102
|
browser: {
|
|
1053
|
-
headless: parseBool(
|
|
1054
|
-
executablePath:
|
|
1055
|
-
slowMo: parseNumber(
|
|
1056
|
-
connectUrl:
|
|
1057
|
-
channel:
|
|
1058
|
-
profileDir:
|
|
1103
|
+
headless: parseBool(env.OPENSTEER_HEADLESS),
|
|
1104
|
+
executablePath: env.OPENSTEER_BROWSER_PATH || void 0,
|
|
1105
|
+
slowMo: parseNumber(env.OPENSTEER_SLOW_MO),
|
|
1106
|
+
connectUrl: env.OPENSTEER_CONNECT_URL || void 0,
|
|
1107
|
+
channel: env.OPENSTEER_CHANNEL || void 0,
|
|
1108
|
+
profileDir: env.OPENSTEER_PROFILE_DIR || void 0
|
|
1059
1109
|
},
|
|
1060
|
-
model:
|
|
1061
|
-
debug: parseBool(
|
|
1110
|
+
model: env.OPENSTEER_MODEL || void 0,
|
|
1111
|
+
debug: parseBool(env.OPENSTEER_DEBUG)
|
|
1062
1112
|
};
|
|
1063
|
-
const mergedWithFile = mergeDeep(
|
|
1113
|
+
const mergedWithFile = mergeDeep(runtimeDefaults, fileConfig);
|
|
1064
1114
|
const mergedWithEnv = mergeDeep(mergedWithFile, envConfig);
|
|
1065
1115
|
const resolved = mergeDeep(mergedWithEnv, input);
|
|
1066
|
-
const envApiKey = resolveOpensteerApiKey();
|
|
1067
|
-
const envAuthScheme = resolveOpensteerAuthScheme();
|
|
1116
|
+
const envApiKey = resolveOpensteerApiKey(env);
|
|
1117
|
+
const envAuthScheme = resolveOpensteerAuthScheme(env);
|
|
1068
1118
|
const envCloudAnnounce = parseCloudAnnounce(
|
|
1069
|
-
|
|
1119
|
+
env.OPENSTEER_REMOTE_ANNOUNCE,
|
|
1070
1120
|
"OPENSTEER_REMOTE_ANNOUNCE"
|
|
1071
1121
|
);
|
|
1072
1122
|
const inputCloudOptions = normalizeCloudOptions(input.cloud);
|
|
@@ -1083,7 +1133,7 @@ function resolveConfig(input = {}) {
|
|
|
1083
1133
|
);
|
|
1084
1134
|
const cloudSelection = resolveCloudSelection({
|
|
1085
1135
|
cloud: resolved.cloud
|
|
1086
|
-
});
|
|
1136
|
+
}, env);
|
|
1087
1137
|
if (cloudSelection.cloud) {
|
|
1088
1138
|
const resolvedCloud = normalizeCloudOptions(resolved.cloud) ?? {};
|
|
1089
1139
|
const authScheme = inputAuthScheme ?? envAuthScheme ?? parseAuthScheme(resolvedCloud.authScheme, "cloud.authScheme") ?? "api-key";
|
package/dist/cli/server.js
CHANGED
package/dist/index.cjs
CHANGED
|
@@ -881,6 +881,7 @@ var BrowserPool = class {
|
|
|
881
881
|
var import_fs = __toESM(require("fs"), 1);
|
|
882
882
|
var import_path3 = __toESM(require("path"), 1);
|
|
883
883
|
var import_url = require("url");
|
|
884
|
+
var import_dotenv = require("dotenv");
|
|
884
885
|
|
|
885
886
|
// src/storage/namespace.ts
|
|
886
887
|
var import_path2 = __toESM(require("path"), 1);
|
|
@@ -930,6 +931,53 @@ var DEFAULT_CONFIG = {
|
|
|
930
931
|
model: "gpt-5.1",
|
|
931
932
|
debug: false
|
|
932
933
|
};
|
|
934
|
+
function dotenvFileOrder(nodeEnv) {
|
|
935
|
+
const normalized = nodeEnv?.trim() || "";
|
|
936
|
+
const files = [];
|
|
937
|
+
if (normalized) {
|
|
938
|
+
files.push(`.env.${normalized}.local`);
|
|
939
|
+
}
|
|
940
|
+
if (normalized !== "test") {
|
|
941
|
+
files.push(".env.local");
|
|
942
|
+
}
|
|
943
|
+
if (normalized) {
|
|
944
|
+
files.push(`.env.${normalized}`);
|
|
945
|
+
}
|
|
946
|
+
files.push(".env");
|
|
947
|
+
return files;
|
|
948
|
+
}
|
|
949
|
+
function loadDotenvValues(rootDir, baseEnv) {
|
|
950
|
+
const values = {};
|
|
951
|
+
if (parseBool(baseEnv.OPENSTEER_DISABLE_DOTENV_AUTOLOAD) === true) {
|
|
952
|
+
return values;
|
|
953
|
+
}
|
|
954
|
+
const baseDir = import_path3.default.resolve(rootDir);
|
|
955
|
+
const nodeEnv = baseEnv.NODE_ENV?.trim() || "";
|
|
956
|
+
for (const filename of dotenvFileOrder(nodeEnv)) {
|
|
957
|
+
const filePath = import_path3.default.join(baseDir, filename);
|
|
958
|
+
if (!import_fs.default.existsSync(filePath)) continue;
|
|
959
|
+
try {
|
|
960
|
+
const raw = import_fs.default.readFileSync(filePath, "utf8");
|
|
961
|
+
const parsed = (0, import_dotenv.parse)(raw);
|
|
962
|
+
for (const [key, value] of Object.entries(parsed)) {
|
|
963
|
+
if (values[key] === void 0) {
|
|
964
|
+
values[key] = value;
|
|
965
|
+
}
|
|
966
|
+
}
|
|
967
|
+
} catch {
|
|
968
|
+
continue;
|
|
969
|
+
}
|
|
970
|
+
}
|
|
971
|
+
return values;
|
|
972
|
+
}
|
|
973
|
+
function resolveEnv(rootDir) {
|
|
974
|
+
const baseEnv = process.env;
|
|
975
|
+
const dotenvValues = loadDotenvValues(rootDir, baseEnv);
|
|
976
|
+
return {
|
|
977
|
+
...dotenvValues,
|
|
978
|
+
...baseEnv
|
|
979
|
+
};
|
|
980
|
+
}
|
|
933
981
|
function hasOwn(config, key) {
|
|
934
982
|
if (!config || typeof config !== "object") return false;
|
|
935
983
|
return Object.prototype.hasOwnProperty.call(config, key);
|
|
@@ -1058,16 +1106,13 @@ function parseCloudAnnounce(value, source) {
|
|
|
1058
1106
|
`Invalid ${source} value "${value}". Use "always", "off", or "tty".`
|
|
1059
1107
|
);
|
|
1060
1108
|
}
|
|
1061
|
-
function resolveOpensteerApiKey() {
|
|
1062
|
-
const value =
|
|
1109
|
+
function resolveOpensteerApiKey(env) {
|
|
1110
|
+
const value = env.OPENSTEER_API_KEY?.trim();
|
|
1063
1111
|
if (!value) return void 0;
|
|
1064
1112
|
return value;
|
|
1065
1113
|
}
|
|
1066
|
-
function resolveOpensteerAuthScheme() {
|
|
1067
|
-
return parseAuthScheme(
|
|
1068
|
-
process.env.OPENSTEER_AUTH_SCHEME,
|
|
1069
|
-
"OPENSTEER_AUTH_SCHEME"
|
|
1070
|
-
);
|
|
1114
|
+
function resolveOpensteerAuthScheme(env) {
|
|
1115
|
+
return parseAuthScheme(env.OPENSTEER_AUTH_SCHEME, "OPENSTEER_AUTH_SCHEME");
|
|
1071
1116
|
}
|
|
1072
1117
|
function normalizeCloudOptions(value) {
|
|
1073
1118
|
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
@@ -1083,7 +1128,7 @@ function parseCloudEnabled(value, source) {
|
|
|
1083
1128
|
`Invalid ${source} value "${String(value)}". Use true, false, or a cloud options object.`
|
|
1084
1129
|
);
|
|
1085
1130
|
}
|
|
1086
|
-
function resolveCloudSelection(config) {
|
|
1131
|
+
function resolveCloudSelection(config, env = process.env) {
|
|
1087
1132
|
const configCloud = parseCloudEnabled(config.cloud, "cloud");
|
|
1088
1133
|
if (configCloud !== void 0) {
|
|
1089
1134
|
return {
|
|
@@ -1091,10 +1136,7 @@ function resolveCloudSelection(config) {
|
|
|
1091
1136
|
source: "config.cloud"
|
|
1092
1137
|
};
|
|
1093
1138
|
}
|
|
1094
|
-
const envMode = parseRuntimeMode(
|
|
1095
|
-
process.env.OPENSTEER_MODE,
|
|
1096
|
-
"OPENSTEER_MODE"
|
|
1097
|
-
);
|
|
1139
|
+
const envMode = parseRuntimeMode(env.OPENSTEER_MODE, "OPENSTEER_MODE");
|
|
1098
1140
|
if (envMode) {
|
|
1099
1141
|
return {
|
|
1100
1142
|
cloud: envMode === "cloud",
|
|
@@ -1107,41 +1149,49 @@ function resolveCloudSelection(config) {
|
|
|
1107
1149
|
};
|
|
1108
1150
|
}
|
|
1109
1151
|
function resolveConfig(input = {}) {
|
|
1110
|
-
|
|
1152
|
+
const initialRootDir = input.storage?.rootDir ?? process.cwd();
|
|
1153
|
+
const runtimeDefaults = mergeDeep(DEFAULT_CONFIG, {
|
|
1154
|
+
storage: {
|
|
1155
|
+
rootDir: initialRootDir
|
|
1156
|
+
}
|
|
1157
|
+
});
|
|
1158
|
+
assertNoLegacyAiConfig("Opensteer constructor config", input);
|
|
1159
|
+
assertNoLegacyRuntimeConfig("Opensteer constructor config", input);
|
|
1160
|
+
const fileConfig = loadConfigFile(initialRootDir);
|
|
1161
|
+
assertNoLegacyAiConfig(".opensteer/config.json", fileConfig);
|
|
1162
|
+
assertNoLegacyRuntimeConfig(".opensteer/config.json", fileConfig);
|
|
1163
|
+
const fileRootDir = typeof fileConfig.storage?.rootDir === "string" ? fileConfig.storage.rootDir : void 0;
|
|
1164
|
+
const envRootDir = input.storage?.rootDir ?? fileRootDir ?? initialRootDir;
|
|
1165
|
+
const env = resolveEnv(envRootDir);
|
|
1166
|
+
if (env.OPENSTEER_AI_MODEL) {
|
|
1111
1167
|
throw new Error(
|
|
1112
1168
|
"OPENSTEER_AI_MODEL is no longer supported. Use OPENSTEER_MODEL instead."
|
|
1113
1169
|
);
|
|
1114
1170
|
}
|
|
1115
|
-
if (
|
|
1171
|
+
if (env.OPENSTEER_RUNTIME != null) {
|
|
1116
1172
|
throw new Error(
|
|
1117
1173
|
"OPENSTEER_RUNTIME is no longer supported. Use OPENSTEER_MODE instead."
|
|
1118
1174
|
);
|
|
1119
1175
|
}
|
|
1120
|
-
assertNoLegacyAiConfig("Opensteer constructor config", input);
|
|
1121
|
-
assertNoLegacyRuntimeConfig("Opensteer constructor config", input);
|
|
1122
|
-
const rootDir = input.storage?.rootDir ?? DEFAULT_CONFIG.storage.rootDir ?? process.cwd();
|
|
1123
|
-
const fileConfig = loadConfigFile(rootDir);
|
|
1124
|
-
assertNoLegacyAiConfig(".opensteer/config.json", fileConfig);
|
|
1125
|
-
assertNoLegacyRuntimeConfig(".opensteer/config.json", fileConfig);
|
|
1126
1176
|
const envConfig = {
|
|
1127
1177
|
browser: {
|
|
1128
|
-
headless: parseBool(
|
|
1129
|
-
executablePath:
|
|
1130
|
-
slowMo: parseNumber(
|
|
1131
|
-
connectUrl:
|
|
1132
|
-
channel:
|
|
1133
|
-
profileDir:
|
|
1178
|
+
headless: parseBool(env.OPENSTEER_HEADLESS),
|
|
1179
|
+
executablePath: env.OPENSTEER_BROWSER_PATH || void 0,
|
|
1180
|
+
slowMo: parseNumber(env.OPENSTEER_SLOW_MO),
|
|
1181
|
+
connectUrl: env.OPENSTEER_CONNECT_URL || void 0,
|
|
1182
|
+
channel: env.OPENSTEER_CHANNEL || void 0,
|
|
1183
|
+
profileDir: env.OPENSTEER_PROFILE_DIR || void 0
|
|
1134
1184
|
},
|
|
1135
|
-
model:
|
|
1136
|
-
debug: parseBool(
|
|
1185
|
+
model: env.OPENSTEER_MODEL || void 0,
|
|
1186
|
+
debug: parseBool(env.OPENSTEER_DEBUG)
|
|
1137
1187
|
};
|
|
1138
|
-
const mergedWithFile = mergeDeep(
|
|
1188
|
+
const mergedWithFile = mergeDeep(runtimeDefaults, fileConfig);
|
|
1139
1189
|
const mergedWithEnv = mergeDeep(mergedWithFile, envConfig);
|
|
1140
1190
|
const resolved = mergeDeep(mergedWithEnv, input);
|
|
1141
|
-
const envApiKey = resolveOpensteerApiKey();
|
|
1142
|
-
const envAuthScheme = resolveOpensteerAuthScheme();
|
|
1191
|
+
const envApiKey = resolveOpensteerApiKey(env);
|
|
1192
|
+
const envAuthScheme = resolveOpensteerAuthScheme(env);
|
|
1143
1193
|
const envCloudAnnounce = parseCloudAnnounce(
|
|
1144
|
-
|
|
1194
|
+
env.OPENSTEER_REMOTE_ANNOUNCE,
|
|
1145
1195
|
"OPENSTEER_REMOTE_ANNOUNCE"
|
|
1146
1196
|
);
|
|
1147
1197
|
const inputCloudOptions = normalizeCloudOptions(input.cloud);
|
|
@@ -1158,7 +1208,7 @@ function resolveConfig(input = {}) {
|
|
|
1158
1208
|
);
|
|
1159
1209
|
const cloudSelection = resolveCloudSelection({
|
|
1160
1210
|
cloud: resolved.cloud
|
|
1161
|
-
});
|
|
1211
|
+
}, env);
|
|
1162
1212
|
if (cloudSelection.cloud) {
|
|
1163
1213
|
const resolvedCloud = normalizeCloudOptions(resolved.cloud) ?? {};
|
|
1164
1214
|
const authScheme = inputAuthScheme ?? envAuthScheme ?? parseAuthScheme(resolvedCloud.authScheme, "cloud.authScheme") ?? "api-key";
|
package/dist/index.js
CHANGED