@@ -20,6 +20,7 @@ import {
2020 writeManagedServiceEnvKeysToEnvironment ,
2121} from "../daemon/service-managed-env.js" ;
2222import { isNonMinimalServicePathEntry } from "../daemon/service-path-policy.js" ;
23+ import type { GatewayServiceEnvironmentValueSource } from "../daemon/service-types.js" ;
2324import {
2425 isDangerousHostEnvOverrideVarName ,
2526 isDangerousHostEnvVarName ,
@@ -40,6 +41,7 @@ type GatewayInstallPlan = {
4041 programArguments : string [ ] ;
4142 workingDirectory ?: string ;
4243 environment : Record < string , string | undefined > ;
44+ environmentValueSources ?: Record < string , GatewayServiceEnvironmentValueSource | undefined > ;
4345} ;
4446
4547let daemonInstallAuthProfileSourceRuntimePromise :
@@ -360,6 +362,22 @@ function collectPreservedExistingServiceEnvVars(
360362 return preserved ;
361363}
362364
365+ function readExistingEnvironmentValueSource ( params : {
366+ existingEnvironmentValueSources ?: Record <
367+ string ,
368+ GatewayServiceEnvironmentValueSource | undefined
369+ > ;
370+ normalizedKey : string ;
371+ } ) : GatewayServiceEnvironmentValueSource | undefined {
372+ for ( const [ rawKey , source ] of Object . entries ( params . existingEnvironmentValueSources ?? { } ) ) {
373+ const key = normalizeEnvVarKey ( rawKey , { portable : true } ) ?. toUpperCase ( ) ;
374+ if ( key === params . normalizedKey ) {
375+ return source ;
376+ }
377+ }
378+ return undefined ;
379+ }
380+
363381function resolveGatewayInstallWorkingDirectory ( params : {
364382 env : Record < string , string | undefined > ;
365383 platform : NodeJS . Platform ;
@@ -381,8 +399,15 @@ async function buildGatewayInstallEnvironment(params: {
381399 warn ?: DaemonInstallWarnFn ;
382400 serviceEnvironment : Record < string , string | undefined > ;
383401 existingEnvironment ?: Record < string , string | undefined > ;
402+ existingEnvironmentValueSources ?: Record <
403+ string ,
404+ GatewayServiceEnvironmentValueSource | undefined
405+ > ;
384406 platform : NodeJS . Platform ;
385- } ) : Promise < Record < string , string | undefined > > {
407+ } ) : Promise < {
408+ environment : Record < string , string | undefined > ;
409+ environmentValueSources : Record < string , GatewayServiceEnvironmentValueSource | undefined > ;
410+ } > {
386411 const durableEnvironment = collectDurableServiceEnvVars ( {
387412 env : params . env ,
388413 config : params . config ,
@@ -404,21 +429,47 @@ async function buildGatewayInstallEnvironment(params: {
404429 authStore : params . authStore ,
405430 warn : params . warn ,
406431 } ) ;
432+ const preservedExistingEnvironment = collectPreservedExistingServiceEnvVars (
433+ params . existingEnvironment ,
434+ readManagedServiceEnvKeysFromEnvironment ( params . existingEnvironment ) ,
435+ ) ;
407436 const environment : Record < string , string | undefined > = {
408- ...collectPreservedExistingServiceEnvVars (
409- params . existingEnvironment ,
410- readManagedServiceEnvKeysFromEnvironment ( params . existingEnvironment ) ,
411- ) ,
437+ ...preservedExistingEnvironment ,
412438 ...durableEnvironment ,
413439 ...configSecretRefEnvironment ,
414440 ...execSecretRefPassEnvEnvironment ,
415441 ...authProfileEnvironment ,
416442 } ;
443+ const environmentValueSources : Record < string , GatewayServiceEnvironmentValueSource | undefined > =
444+ { } ;
445+ for ( const rawKey of Object . keys ( preservedExistingEnvironment ) ) {
446+ const normalizedKey = normalizeEnvVarKey ( rawKey , { portable : true } ) ?. toUpperCase ( ) ;
447+ environmentValueSources [ rawKey ] = normalizedKey
448+ ? ( readExistingEnvironmentValueSource ( {
449+ existingEnvironmentValueSources : params . existingEnvironmentValueSources ,
450+ normalizedKey,
451+ } ) ?? "inline" )
452+ : "inline" ;
453+ }
454+ for ( const key of Object . keys ( {
455+ ...durableEnvironment ,
456+ ...configSecretRefEnvironment ,
457+ ...execSecretRefPassEnvEnvironment ,
458+ ...authProfileEnvironment ,
459+ } ) ) {
460+ environmentValueSources [ key ] = "inline" ;
461+ }
417462 const managedServiceEnvKeys = formatManagedServiceEnvKeys ( durableEnvironment , {
418463 omitKeys : Object . keys ( params . serviceEnvironment ) ,
419464 } ) ;
420465 writeManagedServiceEnvKeysToEnvironment ( environment , managedServiceEnvKeys ) ;
466+ if ( environment . OPENCLAW_SERVICE_MANAGED_ENV_KEYS ) {
467+ environmentValueSources . OPENCLAW_SERVICE_MANAGED_ENV_KEYS = "inline" ;
468+ }
421469 Object . assign ( environment , params . serviceEnvironment ) ;
470+ for ( const key of Object . keys ( params . serviceEnvironment ) ) {
471+ environmentValueSources [ key ] = "inline" ;
472+ }
422473 const mergedPath = mergeServicePath (
423474 params . serviceEnvironment . PATH ,
424475 params . existingEnvironment ?. PATH ,
@@ -427,8 +478,14 @@ async function buildGatewayInstallEnvironment(params: {
427478 ) ;
428479 if ( mergedPath ) {
429480 environment . PATH = mergedPath ;
481+ environmentValueSources . PATH = "inline" ;
482+ }
483+ for ( const key of Object . keys ( environmentValueSources ) ) {
484+ if ( ! Object . hasOwn ( environment , key ) ) {
485+ delete environmentValueSources [ key ] ;
486+ }
430487 }
431- return environment ;
488+ return { environment, environmentValueSources } ;
432489}
433490
434491export async function buildGatewayInstallPlan ( params : {
@@ -444,6 +501,10 @@ export async function buildGatewayInstallPlan(params: {
444501 /** Full config to extract env vars from (env vars + inline env keys). */
445502 config ?: OpenClawConfig ;
446503 authStore ?: AuthProfileStore ;
504+ existingEnvironmentValueSources ?: Record <
505+ string ,
506+ GatewayServiceEnvironmentValueSource | undefined
507+ > ;
447508} ) : Promise < GatewayInstallPlan > {
448509 const platform = params . platform ?? process . platform ;
449510 const { devMode, nodePath } = await resolveDaemonInstallRuntimeInputs ( {
@@ -483,6 +544,17 @@ export async function buildGatewayInstallPlan(params: {
483544 extraPathDirs : resolveDaemonNodeBinDir ( nodePath ) ,
484545 } ) ;
485546
547+ const { environment, environmentValueSources } = await buildGatewayInstallEnvironment ( {
548+ env : serviceInputEnv ,
549+ config : params . config ,
550+ authStore : params . authStore ,
551+ warn : params . warn ,
552+ serviceEnvironment,
553+ existingEnvironment : params . existingEnvironment ,
554+ existingEnvironmentValueSources : params . existingEnvironmentValueSources ,
555+ platform,
556+ } ) ;
557+
486558 // Lowest to highest: preserved custom vars, durable config, auth env refs, generated service env.
487559 return {
488560 programArguments,
@@ -491,15 +563,8 @@ export async function buildGatewayInstallPlan(params: {
491563 platform,
492564 workingDirectory,
493565 } ) ,
494- environment : await buildGatewayInstallEnvironment ( {
495- env : serviceInputEnv ,
496- config : params . config ,
497- authStore : params . authStore ,
498- warn : params . warn ,
499- serviceEnvironment,
500- existingEnvironment : params . existingEnvironment ,
501- platform,
502- } ) ,
566+ environment,
567+ ...( Object . keys ( environmentValueSources ) . length > 0 ? { environmentValueSources } : { } ) ,
503568 } ;
504569}
505570
0 commit comments