@@ -99,6 +99,55 @@ function extractProviderFromModelRef(value: string): string | null {
9999 return normalizeProviderId ( trimmed . slice ( 0 , slash ) ) ;
100100}
101101
102+ function collectEmbeddedHarnessRuntimes ( cfg : OpenClawConfig , env : NodeJS . ProcessEnv ) : string [ ] {
103+ const runtimes = new Set < string > ( ) ;
104+ const pushRuntime = ( value : unknown ) => {
105+ if ( typeof value !== "string" ) {
106+ return ;
107+ }
108+ const normalized = normalizeOptionalLowercaseString ( value ) ;
109+ if ( ! normalized || normalized === "auto" || normalized === "pi" ) {
110+ return ;
111+ }
112+ runtimes . add ( normalized ) ;
113+ } ;
114+
115+ pushRuntime ( cfg . agents ?. defaults ?. embeddedHarness ?. runtime ) ;
116+ if ( Array . isArray ( cfg . agents ?. list ) ) {
117+ for ( const agent of cfg . agents . list ) {
118+ if ( ! isRecord ( agent ) ) {
119+ continue ;
120+ }
121+ pushRuntime ( ( agent . embeddedHarness as Record < string , unknown > | undefined ) ?. runtime ) ;
122+ }
123+ }
124+ pushRuntime ( env . OPENCLAW_AGENT_RUNTIME ) ;
125+
126+ return [ ...runtimes ] . toSorted ( ( left , right ) => left . localeCompare ( right ) ) ;
127+ }
128+
129+ function hasConfiguredEmbeddedHarnessRuntime ( cfg : OpenClawConfig , env : NodeJS . ProcessEnv ) : boolean {
130+ return collectEmbeddedHarnessRuntimes ( cfg , env ) . length > 0 ;
131+ }
132+
133+ function resolveAgentHarnessOwnerPluginIds (
134+ registry : PluginManifestRegistry ,
135+ runtime : string ,
136+ ) : string [ ] {
137+ const normalizedRuntime = normalizeOptionalLowercaseString ( runtime ) ;
138+ if ( ! normalizedRuntime ) {
139+ return [ ] ;
140+ }
141+ return registry . plugins
142+ . filter ( ( plugin ) =>
143+ ( plugin . activation ?. onAgentHarnesses ?? [ ] ) . some (
144+ ( entry ) => normalizeOptionalLowercaseString ( entry ) === normalizedRuntime ,
145+ ) ,
146+ )
147+ . map ( ( plugin ) => plugin . id )
148+ . toSorted ( ( left , right ) => left . localeCompare ( right ) ) ;
149+ }
150+
102151function isProviderConfigured ( cfg : OpenClawConfig , providerId : string ) : boolean {
103152 const normalized = normalizeProviderId ( providerId ) ;
104153 const profiles = cfg . auth ?. profiles ;
@@ -300,7 +349,7 @@ function hasPluginEntries(cfg: OpenClawConfig): boolean {
300349 return ! ! entries && typeof entries === "object" && Object . keys ( entries ) . length > 0 ;
301350}
302351
303- function configMayNeedPluginManifestRegistry ( cfg : OpenClawConfig ) : boolean {
352+ function configMayNeedPluginManifestRegistry ( cfg : OpenClawConfig , env : NodeJS . ProcessEnv ) : boolean {
304353 const pluginEntries = cfg . plugins ?. entries ;
305354 if ( Array . isArray ( cfg . plugins ?. allow ) && cfg . plugins . allow . length > 0 && hasPluginEntries ( cfg ) ) {
306355 return true ;
@@ -320,6 +369,9 @@ function configMayNeedPluginManifestRegistry(cfg: OpenClawConfig): boolean {
320369 if ( collectModelRefs ( cfg ) . length > 0 ) {
321370 return true ;
322371 }
372+ if ( hasConfiguredEmbeddedHarnessRuntime ( cfg , env ) ) {
373+ return true ;
374+ }
323375 const configuredChannels = cfg . channels as Record < string , unknown > | undefined ;
324376 if ( ! configuredChannels || typeof configuredChannels !== "object" ) {
325377 return false ;
@@ -357,6 +409,9 @@ export function configMayNeedPluginAutoEnable(
357409 if ( collectModelRefs ( cfg ) . length > 0 ) {
358410 return true ;
359411 }
412+ if ( hasConfiguredEmbeddedHarnessRuntime ( cfg , env ) ) {
413+ return true ;
414+ }
360415 if ( hasConfiguredWebSearchPluginEntry ( cfg ) || hasConfiguredWebFetchPluginEntry ( cfg ) ) {
361416 return true ;
362417 }
@@ -381,6 +436,8 @@ export function resolvePluginAutoEnableCandidateReason(
381436 return `${ candidate . providerId } auth configured` ;
382437 case "provider-model-configured" :
383438 return `${ candidate . modelRef } model configured` ;
439+ case "agent-harness-runtime-configured" :
440+ return `${ candidate . runtime } agent harness runtime configured` ;
384441 case "web-fetch-provider-selected" :
385442 return `${ candidate . providerId } web fetch provider selected` ;
386443 case "plugin-web-search-configured" :
@@ -433,6 +490,17 @@ export function resolveConfiguredPluginAutoEnableCandidates(params: {
433490 }
434491 }
435492
493+ for ( const runtime of collectEmbeddedHarnessRuntimes ( params . config , params . env ) ) {
494+ const pluginIds = resolveAgentHarnessOwnerPluginIds ( params . registry , runtime ) ;
495+ for ( const pluginId of pluginIds ) {
496+ changes . push ( {
497+ pluginId,
498+ kind : "agent-harness-runtime-configured" ,
499+ runtime,
500+ } ) ;
501+ }
502+ }
503+
436504 const webFetchProvider =
437505 typeof params . config . tools ?. web ?. fetch ?. provider === "string"
438506 ? params . config . tools . web . fetch . provider
@@ -640,7 +708,7 @@ export function resolvePluginAutoEnableManifestRegistry(params: {
640708} ) : PluginManifestRegistry {
641709 return (
642710 params . manifestRegistry ??
643- ( configMayNeedPluginManifestRegistry ( params . config )
711+ ( configMayNeedPluginManifestRegistry ( params . config , params . env )
644712 ? loadPluginManifestRegistry ( { config : params . config , env : params . env } )
645713 : EMPTY_PLUGIN_MANIFEST_REGISTRY )
646714 ) ;
0 commit comments