feat: auto-load ~/.openclaw/.env in buildConfig
Skills no longer need to manually export env vars. auth-runtime reads the global config file automatically on first client creation. Won't overwrite explicitly set environment variables. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
b05363e8f0
commit
22bc6f7438
|
|
@ -1 +1 @@
|
||||||
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAyB,eAAe,EAAE,MAAM,YAAY,CAAC;AAapG,MAAM,WAAW,kBAAkB;IACjC,6DAA6D;IAC7D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,0BAA0B;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,sEAAsE;IACtE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,wCAAwC;IACxC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,uDAAuD;IACvD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,0DAA0D;IAC1D,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAkBD,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAY;IACnC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAU;gBAErB,OAAO,GAAE,kBAAuB;IAU5C,iDAAiD;IAC3C,OAAO,IAAI,OAAO,CAAC,eAAe,CAAC;IAOzC,yEAAyE;IACnE,YAAY,IAAI,OAAO,CAAC,YAAY,CAAC;IAoBrC,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAIvC,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,WAAW,CAAC;IAIxD,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,WAAW,CAAC;IAIvD,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,WAAW,CAAC;IAIzD,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,WAAW,CAAC;YAMlD,OAAO;YAoBP,QAAQ;YAUR,YAAY;YASZ,YAAY;CAmB3B;AAED,wBAAgB,iBAAiB,CAAC,OAAO,CAAC,EAAE,kBAAkB,GAAG,WAAW,CAE3E"}
|
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAyB,eAAe,EAAE,MAAM,YAAY,CAAC;AAcpG,MAAM,WAAW,kBAAkB;IACjC,6DAA6D;IAC7D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,0BAA0B;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,sEAAsE;IACtE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,wCAAwC;IACxC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,uDAAuD;IACvD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,0DAA0D;IAC1D,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAmBD,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAY;IACnC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAU;gBAErB,OAAO,GAAE,kBAAuB;IAU5C,iDAAiD;IAC3C,OAAO,IAAI,OAAO,CAAC,eAAe,CAAC;IAOzC,yEAAyE;IACnE,YAAY,IAAI,OAAO,CAAC,YAAY,CAAC;IAoBrC,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAIvC,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,WAAW,CAAC;IAIxD,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,WAAW,CAAC;IAIvD,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,WAAW,CAAC;IAIzD,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,WAAW,CAAC;YAMlD,OAAO;YAoBP,QAAQ;YAUR,YAAY;YASZ,YAAY;CAmB3B;AAED,wBAAgB,iBAAiB,CAAC,OAAO,CAAC,EAAE,kBAAkB,GAAG,WAAW,CAE3E"}
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import { requestApi } from './http.js';
|
import { requestApi } from './http.js';
|
||||||
import { getCacheFile, readCachedToken, writeCache, deleteCache } from './cache.js';
|
import { getCacheFile, readCachedToken, writeCache, deleteCache } from './cache.js';
|
||||||
|
import { loadGlobalEnv } from './env.js';
|
||||||
const SESSION_RETRYABLE_STATUS = new Set([401, 403]);
|
const SESSION_RETRYABLE_STATUS = new Set([401, 403]);
|
||||||
const SESSION_RETRYABLE_BODY_MARKERS = [
|
const SESSION_RETRYABLE_BODY_MARKERS = [
|
||||||
'session not found or expired',
|
'session not found or expired',
|
||||||
|
|
@ -9,6 +10,7 @@ const SESSION_RETRYABLE_BODY_MARKERS = [
|
||||||
'client key revoked',
|
'client key revoked',
|
||||||
];
|
];
|
||||||
function buildConfig(options) {
|
function buildConfig(options) {
|
||||||
|
loadGlobalEnv();
|
||||||
return {
|
return {
|
||||||
authBase: (options.authBase || process.env.AUTH_BASE || 'https://api-gw-test.yuanwei-lnc.com').replace(/\/$/, ''),
|
authBase: (options.authBase || process.env.AUTH_BASE || 'https://api-gw-test.yuanwei-lnc.com').replace(/\/$/, ''),
|
||||||
clientKey: options.clientKey || process.env.CLIENT_KEY || '',
|
clientKey: options.clientKey || process.env.CLIENT_KEY || '',
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,5 @@
|
||||||
|
/**
|
||||||
|
* Load ~/.openclaw/.env into process.env (once, won't overwrite existing vars).
|
||||||
|
*/
|
||||||
|
export declare function loadGlobalEnv(): void;
|
||||||
|
//# sourceMappingURL=env.d.ts.map
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
{"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../src/env.ts"],"names":[],"mappings":"AAQA;;GAEG;AACH,wBAAgB,aAAa,IAAI,IAAI,CA+BpC"}
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
import * as fs from 'fs';
|
||||||
|
import * as path from 'path';
|
||||||
|
import * as os from 'os';
|
||||||
|
const GLOBAL_ENV_PATH = path.join(os.homedir(), '.openclaw', '.env');
|
||||||
|
let loaded = false;
|
||||||
|
/**
|
||||||
|
* Load ~/.openclaw/.env into process.env (once, won't overwrite existing vars).
|
||||||
|
*/
|
||||||
|
export function loadGlobalEnv() {
|
||||||
|
if (loaded)
|
||||||
|
return;
|
||||||
|
loaded = true;
|
||||||
|
let content;
|
||||||
|
try {
|
||||||
|
content = fs.readFileSync(GLOBAL_ENV_PATH, 'utf-8');
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
return; // file doesn't exist — that's fine
|
||||||
|
}
|
||||||
|
for (const line of content.split('\n')) {
|
||||||
|
const trimmed = line.trim();
|
||||||
|
if (!trimmed || trimmed.startsWith('#'))
|
||||||
|
continue;
|
||||||
|
const eqIdx = trimmed.indexOf('=');
|
||||||
|
if (eqIdx < 1)
|
||||||
|
continue;
|
||||||
|
const key = trimmed.slice(0, eqIdx).trim();
|
||||||
|
let value = trimmed.slice(eqIdx + 1).trim();
|
||||||
|
// strip surrounding quotes
|
||||||
|
if ((value.startsWith('"') && value.endsWith('"')) || (value.startsWith("'") && value.endsWith("'"))) {
|
||||||
|
value = value.slice(1, -1);
|
||||||
|
}
|
||||||
|
// don't overwrite explicitly set env vars
|
||||||
|
if (process.env[key] === undefined) {
|
||||||
|
process.env[key] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//# sourceMappingURL=env.js.map
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
{"version":3,"file":"env.js","sourceRoot":"","sources":["../src/env.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AAEzB,MAAM,eAAe,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,WAAW,EAAE,MAAM,CAAC,CAAC;AAErE,IAAI,MAAM,GAAG,KAAK,CAAC;AAEnB;;GAEG;AACH,MAAM,UAAU,aAAa;IAC3B,IAAI,MAAM;QAAE,OAAO;IACnB,MAAM,GAAG,IAAI,CAAC;IAEd,IAAI,OAAe,CAAC;IACpB,IAAI,CAAC;QACH,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,eAAe,EAAE,OAAO,CAAC,CAAC;IACtD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,mCAAmC;IAC7C,CAAC;IAED,KAAK,MAAM,IAAI,IAAI,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACvC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QAC5B,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,SAAS;QAElD,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QACnC,IAAI,KAAK,GAAG,CAAC;YAAE,SAAS;QAExB,MAAM,GAAG,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC;QAC3C,IAAI,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAE5C,2BAA2B;QAC3B,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;YACrG,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QAC7B,CAAC;QAED,0CAA0C;QAC1C,IAAI,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,SAAS,EAAE,CAAC;YACnC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;QAC3B,CAAC;IACH,CAAC;AACH,CAAC"}
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import type { ApiResponse, ClientConfig, EnvConfig, HttpMethod, SessionResponse } from './types.js';
|
import type { ApiResponse, ClientConfig, EnvConfig, HttpMethod, SessionResponse } from './types.js';
|
||||||
import { requestApi } from './http.js';
|
import { requestApi } from './http.js';
|
||||||
import { getCacheFile, readCachedToken, writeCache, deleteCache } from './cache.js';
|
import { getCacheFile, readCachedToken, writeCache, deleteCache } from './cache.js';
|
||||||
|
import { loadGlobalEnv } from './env.js';
|
||||||
|
|
||||||
const SESSION_RETRYABLE_STATUS = new Set([401, 403]);
|
const SESSION_RETRYABLE_STATUS = new Set([401, 403]);
|
||||||
const SESSION_RETRYABLE_BODY_MARKERS = [
|
const SESSION_RETRYABLE_BODY_MARKERS = [
|
||||||
|
|
@ -27,6 +28,7 @@ export interface SkillClientOptions {
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildConfig(options: SkillClientOptions): EnvConfig {
|
function buildConfig(options: SkillClientOptions): EnvConfig {
|
||||||
|
loadGlobalEnv();
|
||||||
return {
|
return {
|
||||||
authBase: (options.authBase || process.env.AUTH_BASE || 'https://api-gw-test.yuanwei-lnc.com').replace(/\/$/, ''),
|
authBase: (options.authBase || process.env.AUTH_BASE || 'https://api-gw-test.yuanwei-lnc.com').replace(/\/$/, ''),
|
||||||
clientKey: options.clientKey || process.env.CLIENT_KEY || '',
|
clientKey: options.clientKey || process.env.CLIENT_KEY || '',
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
import * as fs from 'fs';
|
||||||
|
import * as path from 'path';
|
||||||
|
import * as os from 'os';
|
||||||
|
|
||||||
|
const GLOBAL_ENV_PATH = path.join(os.homedir(), '.openclaw', '.env');
|
||||||
|
|
||||||
|
let loaded = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load ~/.openclaw/.env into process.env (once, won't overwrite existing vars).
|
||||||
|
*/
|
||||||
|
export function loadGlobalEnv(): void {
|
||||||
|
if (loaded) return;
|
||||||
|
loaded = true;
|
||||||
|
|
||||||
|
let content: string;
|
||||||
|
try {
|
||||||
|
content = fs.readFileSync(GLOBAL_ENV_PATH, 'utf-8');
|
||||||
|
} catch {
|
||||||
|
return; // file doesn't exist — that's fine
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const line of content.split('\n')) {
|
||||||
|
const trimmed = line.trim();
|
||||||
|
if (!trimmed || trimmed.startsWith('#')) continue;
|
||||||
|
|
||||||
|
const eqIdx = trimmed.indexOf('=');
|
||||||
|
if (eqIdx < 1) continue;
|
||||||
|
|
||||||
|
const key = trimmed.slice(0, eqIdx).trim();
|
||||||
|
let value = trimmed.slice(eqIdx + 1).trim();
|
||||||
|
|
||||||
|
// strip surrounding quotes
|
||||||
|
if ((value.startsWith('"') && value.endsWith('"')) || (value.startsWith("'") && value.endsWith("'"))) {
|
||||||
|
value = value.slice(1, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// don't overwrite explicitly set env vars
|
||||||
|
if (process.env[key] === undefined) {
|
||||||
|
process.env[key] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue