@@ -2,6 +2,7 @@ import fs from "node:fs";
22import os from "node:os" ;
33import path from "node:path" ;
44import { afterEach , beforeEach , describe , expect , it , vi } from "vitest" ;
5+ import type { OpenClawConfig } from "../config/types.openclaw.js" ;
56import {
67 clearCurrentPluginMetadataSnapshot ,
78 resolvePluginMetadataControlPlaneFingerprint ,
@@ -11,6 +12,7 @@ import { resolveInstalledPluginIndexPolicyHash } from "./installed-plugin-index-
1112import type { InstalledPluginIndex } from "./installed-plugin-index.js" ;
1213import { listOpenClawPluginManifestMetadata } from "./manifest-metadata-scan.js" ;
1314import { normalizeProviderModelIdWithManifest } from "./manifest-model-id-normalization.js" ;
15+ import { clearPluginMetadataLifecycleCaches } from "./plugin-metadata-lifecycle.js" ;
1416import type { PluginMetadataSnapshot } from "./plugin-metadata-snapshot.js" ;
1517import { createEmptyPluginRegistry } from "./registry-empty.js" ;
1618import { resetPluginRuntimeStateForTest , setActivePluginRegistry } from "./runtime.js" ;
@@ -87,8 +89,10 @@ function createCurrentSnapshot(params: {
8789 manifestHash : string ;
8890 prefix : string ;
8991 workspaceDir ?: string ;
92+ config ?: OpenClawConfig ;
9093} ) : PluginMetadataSnapshot {
91- const policyHash = resolveInstalledPluginIndexPolicyHash ( { } ) ;
94+ const config = params . config ?? { } ;
95+ const policyHash = resolveInstalledPluginIndexPolicyHash ( config ) ;
9296 const index : InstalledPluginIndex = {
9397 version : 1 ,
9498 hostContractVersion : "test-host" ,
@@ -119,15 +123,12 @@ function createCurrentSnapshot(params: {
119123 } ;
120124 return {
121125 policyHash,
122- configFingerprint : resolvePluginMetadataControlPlaneFingerprint (
123- { } ,
124- {
125- env : process . env ,
126- index,
127- policyHash,
128- workspaceDir : params . workspaceDir ,
129- } ,
130- ) ,
126+ configFingerprint : resolvePluginMetadataControlPlaneFingerprint ( config , {
127+ env : process . env ,
128+ index,
129+ policyHash,
130+ workspaceDir : params . workspaceDir ,
131+ } ) ,
131132 workspaceDir : params . workspaceDir ,
132133 index,
133134 registryDiagnostics : [ ] ,
@@ -153,6 +154,17 @@ function normalizeDemoModel(modelId = "demo-model"): string | undefined {
153154 } ) ;
154155}
155156
157+ function normalizeDemoModelWithEnv (
158+ env : NodeJS . ProcessEnv ,
159+ modelId = "demo-model" ,
160+ ) : string | undefined {
161+ return normalizeProviderModelIdWithManifest ( {
162+ provider : "demo" ,
163+ env,
164+ context : { provider : "demo" , modelId } ,
165+ } ) ;
166+ }
167+
156168describe ( "manifest model id normalization" , ( ) => {
157169 beforeEach ( ( ) => {
158170 resetPluginRuntimeStateForTest ( ) ;
@@ -234,6 +246,45 @@ describe("manifest model id normalization", () => {
234246 expect ( normalizeDemoModel ( ) ) . toBe ( "alpha/demo-model" ) ;
235247 } ) ;
236248
249+ it ( "reuses current metadata when callers omit config" , ( ) => {
250+ const config : OpenClawConfig = { plugins : { allow : [ "normalizer" ] } } ;
251+ setCurrentPluginMetadataSnapshot (
252+ createCurrentSnapshot ( {
253+ manifestHash : "alpha" ,
254+ prefix : "alpha" ,
255+ config,
256+ } ) ,
257+ { config, env : process . env } ,
258+ ) ;
259+
260+ expect ( normalizeDemoModel ( ) ) . toBe ( "alpha/demo-model" ) ;
261+ } ) ;
262+
263+ it ( "validates explicit env before reusing current metadata" , ( ) => {
264+ setCurrentPluginMetadataSnapshot (
265+ createCurrentSnapshot ( {
266+ manifestHash : "alpha" ,
267+ prefix : "alpha" ,
268+ } ) ,
269+ { config : { } , env : process . env } ,
270+ ) ;
271+
272+ const stateDir = makeTempDir ( ) ;
273+ const pluginDir = path . join ( stateDir , "extensions" , "normalizer" ) ;
274+ writeInstallIndex ( { stateDir, pluginDir } ) ;
275+ writeNormalizerManifest ( { pluginDir, prefix : "bravo" } ) ;
276+
277+ const env = {
278+ ...process . env ,
279+ OPENCLAW_STATE_DIR : stateDir ,
280+ OPENCLAW_HOME : undefined ,
281+ OPENCLAW_DISABLE_BUNDLED_PLUGINS : "1" ,
282+ OPENCLAW_BUNDLED_PLUGINS_DIR : undefined ,
283+ } ;
284+
285+ expect ( normalizeDemoModelWithEnv ( env ) ) . toBe ( "bravo/demo-model" ) ;
286+ } ) ;
287+
237288 it ( "reflects manifest edits and state-dir changes on the next lookup" , ( ) => {
238289 const stateDirA = makeTempDir ( ) ;
239290 const pluginDirA = path . join ( stateDirA , "extensions" , "normalizer" ) ;
@@ -248,6 +299,7 @@ describe("manifest model id normalization", () => {
248299 expect ( normalizeDemoModel ( ) ) . toBe ( "alpha/demo-model" ) ;
249300
250301 writeNormalizerManifest ( { pluginDir : pluginDirA , prefix : "bravo-local" } ) ;
302+ clearPluginMetadataLifecycleCaches ( ) ;
251303 expect ( normalizeDemoModel ( ) ) . toBe ( "bravo-local/demo-model" ) ;
252304
253305 const stateDirB = makeTempDir ( ) ;
@@ -256,6 +308,7 @@ describe("manifest model id normalization", () => {
256308 writeNormalizerManifest ( { pluginDir : pluginDirB , prefix : "charlie" } ) ;
257309
258310 process . env . OPENCLAW_STATE_DIR = stateDirB ;
311+ clearPluginMetadataLifecycleCaches ( ) ;
259312 expect ( normalizeDemoModel ( ) ) . toBe ( "charlie/demo-model" ) ;
260313 } ) ;
261314
0 commit comments