























@@ -62,7 +62,7 @@ function hashFile(filePath: string): string {
6262return crypto.createHash("sha256").update(fs.readFileSync(filePath)).digest("hex");
6363}
646465-function createCandidate(rootDir: string): PluginCandidate {
65+function createCandidate(rootDir: string, pluginId = "demo"): PluginCandidate {
6666fs.writeFileSync(
6767path.join(rootDir, "index.ts"),
6868"throw new Error('runtime entry should not load while reading plugin registry');\n",
@@ -71,46 +71,46 @@ function createCandidate(rootDir: string): PluginCandidate {
7171fs.writeFileSync(
7272path.join(rootDir, "openclaw.plugin.json"),
7373JSON.stringify({
74-id: "demo",
75-name: "Demo",
74+id: pluginId,
75+name: pluginId,
7676configSchema: { type: "object" },
77-providers: ["demo"],
78-channels: ["demo-chat"],
79-cliBackends: ["demo-cli"],
77+providers: [pluginId],
78+channels: [`${pluginId}-chat`],
79+cliBackends: [`${pluginId}-cli`],
8080setup: {
81-providers: [{ id: "demo-setup", envVars: ["DEMO_API_KEY"] }],
82-cliBackends: ["demo-setup-cli"],
81+providers: [{ id: `${pluginId}-setup`, envVars: ["DEMO_API_KEY"] }],
82+cliBackends: [`${pluginId}-setup-cli`],
8383},
8484channelConfigs: {
85-"demo-chat": {
85+[`${pluginId}-chat`]: {
8686schema: { type: "object" },
8787},
8888},
8989modelCatalog: {
9090aliases: {
91-"demo-alias": {
92-provider: "demo",
91+[`${pluginId}-alias`]: {
92+provider: pluginId,
9393},
9494},
9595providers: {
96-demo: {
97-models: [{ id: "demo-model" }],
96+[pluginId]: {
97+models: [{ id: `${pluginId}-model` }],
9898},
9999},
100100},
101-commandAliases: [{ name: "demo-command" }],
101+commandAliases: [{ name: `${pluginId}-command` }],
102102contracts: {
103-tools: ["demo-tool"],
104-webSearchProviders: ["demo-search"],
103+tools: [`${pluginId}-tool`],
104+webSearchProviders: [`${pluginId}-search`],
105105},
106106configContracts: {
107-compatibilityRuntimePaths: ["tools.web.search.demo-search.apiKey"],
107+compatibilityRuntimePaths: [`tools.web.search.${pluginId}-search.apiKey`],
108108},
109109}),
110110"utf8",
111111);
112112return {
113-idHint: "demo",
113+idHint: pluginId,
114114source: path.join(rootDir, "index.ts"),
115115 rootDir,
116116origin: "global",
@@ -748,6 +748,30 @@ describe("plugin registry facade", () => {
748748expect(manifestReadsAfterSecond).toBe(manifestReadsAfterFirst);
749749});
750750751+it("does not reuse the process registry memo after profile extensions change", () => {
752+const stateDir = makeTempDir();
753+const configDir = makeTempDir();
754+const extensionsDir = path.join(configDir, "extensions");
755+const firstRoot = path.join(extensionsDir, "first");
756+fs.mkdirSync(firstRoot, { recursive: true });
757+createCandidate(firstRoot, "first");
758+const env = hermeticEnv({
759+OPENCLAW_CONFIG_PATH: path.join(configDir, "openclaw.json"),
760+OPENCLAW_DISABLE_BUNDLED_PLUGINS: "1",
761+});
762+763+const first = loadPluginRegistrySnapshotWithMetadata({ stateDir, env });
764+const secondRoot = path.join(extensionsDir, "second");
765+fs.mkdirSync(secondRoot, { recursive: true });
766+createCandidate(secondRoot, "second");
767+const second = loadPluginRegistrySnapshotWithMetadata({ stateDir, env });
768+769+expect(first.source).toBe("derived");
770+expect(second.source).toBe("derived");
771+expectSnapshotPluginIds(first.snapshot, ["first"]);
772+expectSnapshotPluginIds(second.snapshot, ["first", "second"]);
773+});
774+751775it("keys the process registry memo by resolved host contract version", () => {
752776const stateDir = makeTempDir();
753777const bundledRoot = makeTempDir();
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。