@@ -3,10 +3,7 @@ import os from "node:os";
33import path from "node:path" ;
44import type { AuthProfileStore } from "../agents/auth-profiles/types.js" ;
55import { formatCliCommand } from "../cli/command-format.js" ;
6- import {
7- collectDurableServiceEnvVars ,
8- readStateDirDotEnvVars ,
9- } from "../config/state-dir-dotenv.js" ;
6+ import { collectDurableServiceEnvVarSources } from "../config/state-dir-dotenv.js" ;
107import type { OpenClawConfig } from "../config/types.js" ;
118import { resolveSecretInputRef } from "../config/types.secrets.js" ;
129import { resolveGatewayLaunchAgentLabel } from "../daemon/constants.js" ;
@@ -16,11 +13,16 @@ import {
1613 resolveGatewayProgramArguments ,
1714 resolveOpenClawWrapperPath ,
1815} from "../daemon/program-args.js" ;
16+ import {
17+ addServiceEnvPlanEntries ,
18+ compactServiceEnvPlanValueSources ,
19+ createMutableServiceEnvPlan ,
20+ } from "../daemon/service-env-plan.js" ;
21+ import { applyManagedServiceEnvRenderPolicy } from "../daemon/service-env-render-policy.js" ;
1922import { buildServiceEnvironment } from "../daemon/service-env.js" ;
2023import {
2124 formatManagedServiceEnvKeys ,
2225 readManagedServiceEnvKeysFromEnvironment ,
23- writeManagedServiceEnvKeysToEnvironment ,
2426} from "../daemon/service-managed-env.js" ;
2527import { isNonMinimalServicePathEntry } from "../daemon/service-path-policy.js" ;
2628import type { GatewayServiceEnvironmentValueSource } from "../daemon/service-types.js" ;
@@ -395,35 +397,6 @@ function resolveGatewayInstallWorkingDirectory(params: {
395397 return resolveGatewayStateDir ( params . env ) ;
396398}
397399
398- function retainLaunchAgentManagedServiceEnvValues ( params : {
399- environment : Record < string , string | undefined > ;
400- durableEnvironment : Record < string , string | undefined > ;
401- managedServiceEnvKeys : string | undefined ;
402- stateDirDotEnvEnvironment : Record < string , string | undefined > ;
403- serviceEnvironment : Record < string , string | undefined > ;
404- platform : NodeJS . Platform ;
405- } ) : void {
406- if ( params . platform !== "darwin" || ! params . serviceEnvironment . OPENCLAW_LAUNCHD_LABEL ?. trim ( ) ) {
407- return ;
408- }
409- const managedKeys = readManagedServiceEnvKeysFromEnvironment ( {
410- OPENCLAW_SERVICE_MANAGED_ENV_KEYS : params . managedServiceEnvKeys ,
411- } ) ;
412- if ( managedKeys . size === 0 ) {
413- return ;
414- }
415- for ( const [ rawKey , value ] of Object . entries ( params . stateDirDotEnvEnvironment ) ) {
416- const key = normalizeEnvVarKey ( rawKey , { portable : true } ) ?. toUpperCase ( ) ;
417- if ( ! key || ! managedKeys . has ( key ) || typeof value !== "string" || ! value . trim ( ) ) {
418- continue ;
419- }
420- if ( params . durableEnvironment [ rawKey ] !== value ) {
421- continue ;
422- }
423- params . environment [ rawKey ] = value ;
424- }
425- }
426-
427400async function buildGatewayInstallEnvironment ( params : {
428401 env : Record < string , string | undefined > ;
429402 config ?: OpenClawConfig ;
@@ -440,11 +413,11 @@ async function buildGatewayInstallEnvironment(params: {
440413 environment : Record < string , string | undefined > ;
441414 environmentValueSources : Record < string , GatewayServiceEnvironmentValueSource | undefined > ;
442415} > {
443- const stateDirDotEnvEnvironment = readStateDirDotEnvVars ( params . env ) ;
444- const durableEnvironment = collectDurableServiceEnvVars ( {
445- env : params . env ,
446- config : params . config ,
447- } ) ;
416+ const { stateDirDotEnvEnvironment, configEnvironment , durableEnvironment } =
417+ collectDurableServiceEnvVarSources ( {
418+ env : params . env ,
419+ config : params . config ,
420+ } ) ;
448421 const configSecretRefEnvironment = collectConfigSecretRefServiceEnvVars ( {
449422 env : params . env ,
450423 config : params . config ,
@@ -466,67 +439,48 @@ async function buildGatewayInstallEnvironment(params: {
466439 params . existingEnvironment ,
467440 readManagedServiceEnvKeysFromEnvironment ( params . existingEnvironment ) ,
468441 ) ;
469- const environment : Record < string , string | undefined > = {
470- ...preservedExistingEnvironment ,
471- ...durableEnvironment ,
472- ...configSecretRefEnvironment ,
473- ...execSecretRefPassEnvEnvironment ,
474- ...authProfileEnvironment ,
475- } ;
476- const environmentValueSources : Record < string , GatewayServiceEnvironmentValueSource | undefined > =
477- { } ;
478- for ( const rawKey of Object . keys ( preservedExistingEnvironment ) ) {
479- const normalizedKey = normalizeEnvVarKey ( rawKey , { portable : true } ) ?. toUpperCase ( ) ;
480- environmentValueSources [ rawKey ] = normalizedKey
481- ? ( readExistingEnvironmentValueSource ( {
482- existingEnvironmentValueSources : params . existingEnvironmentValueSources ,
483- normalizedKey,
484- } ) ?? "inline" )
485- : "inline" ;
486- }
487- for ( const key of Object . keys ( {
488- ...durableEnvironment ,
489- ...configSecretRefEnvironment ,
490- ...execSecretRefPassEnvEnvironment ,
491- ...authProfileEnvironment ,
492- } ) ) {
493- environmentValueSources [ key ] = "inline" ;
494- }
442+ const plan = createMutableServiceEnvPlan ( ) ;
443+ addServiceEnvPlanEntries ( plan , preservedExistingEnvironment , {
444+ source : "existing-preserved" ,
445+ valueSource : ( { normalizedKey } ) =>
446+ readExistingEnvironmentValueSource ( {
447+ existingEnvironmentValueSources : params . existingEnvironmentValueSources ,
448+ normalizedKey,
449+ } ) ?? "inline" ,
450+ } ) ;
451+ addServiceEnvPlanEntries ( plan , stateDirDotEnvEnvironment , { source : "state-dotenv" } ) ;
452+ addServiceEnvPlanEntries ( plan , configEnvironment , { source : "config-env" } ) ;
453+ addServiceEnvPlanEntries ( plan , configSecretRefEnvironment , { source : "config-secretref-env" } ) ;
454+ addServiceEnvPlanEntries ( plan , execSecretRefPassEnvEnvironment , { source : "exec-passenv" } ) ;
455+ addServiceEnvPlanEntries ( plan , authProfileEnvironment , { source : "auth-profile-env" } ) ;
495456 const managedServiceEnvKeys = formatManagedServiceEnvKeys ( durableEnvironment , {
496457 omitKeys : Object . keys ( params . serviceEnvironment ) ,
497458 } ) ;
498- writeManagedServiceEnvKeysToEnvironment ( environment , managedServiceEnvKeys ) ;
499- retainLaunchAgentManagedServiceEnvValues ( {
500- environment,
501- durableEnvironment,
459+ applyManagedServiceEnvRenderPolicy ( {
460+ plan,
502461 managedServiceEnvKeys,
503- stateDirDotEnvEnvironment,
504462 serviceEnvironment : params . serviceEnvironment ,
505463 platform : params . platform ,
506464 } ) ;
507- if ( environment . OPENCLAW_SERVICE_MANAGED_ENV_KEYS ) {
508- environmentValueSources . OPENCLAW_SERVICE_MANAGED_ENV_KEYS = "inline" ;
509- }
510- Object . assign ( environment , params . serviceEnvironment ) ;
511- for ( const key of Object . keys ( params . serviceEnvironment ) ) {
512- environmentValueSources [ key ] = "inline" ;
513- }
465+ addServiceEnvPlanEntries ( plan , params . serviceEnvironment , {
466+ source : "service-generated" ,
467+ includeRawKeys : true ,
468+ } ) ;
514469 const mergedPath = mergeServicePath (
515470 params . serviceEnvironment . PATH ,
516471 params . existingEnvironment ?. PATH ,
517472 params . serviceEnvironment . TMPDIR ,
518473 params . platform ,
519474 ) ;
520475 if ( mergedPath ) {
521- environment . PATH = mergedPath ;
522- environmentValueSources . PATH = "inline" ;
476+ plan . environment . PATH = mergedPath ;
477+ plan . environmentValueSources . PATH = "inline" ;
523478 }
524- for ( const key of Object . keys ( environmentValueSources ) ) {
525- if ( ! Object . hasOwn ( environment , key ) ) {
526- delete environmentValueSources [ key ] ;
527- }
528- }
529- return { environment, environmentValueSources } ;
479+ compactServiceEnvPlanValueSources ( plan ) ;
480+ return {
481+ environment : plan . environment ,
482+ environmentValueSources : plan . environmentValueSources ,
483+ } ;
530484}
531485
532486export async function buildGatewayInstallPlan ( params : {
0 commit comments