From ec6c4e8e7865cd6bb1758d768ec4b89eea868a02 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Sun, 12 Jul 2026 18:34:53 +0100 Subject: [PATCH] perf(agents): reuse current model catalog metadata (#105552) --- .../model.static-catalog.test.ts | 79 +++++++++++++++++++ .../model.static-catalog.ts | 26 ++++-- 2 files changed, 100 insertions(+), 5 deletions(-) diff --git a/src/agents/embedded-agent-runner/model.static-catalog.test.ts b/src/agents/embedded-agent-runner/model.static-catalog.test.ts index f8d257840466..ed03ad19db9a 100644 --- a/src/agents/embedded-agent-runner/model.static-catalog.test.ts +++ b/src/agents/embedded-agent-runner/model.static-catalog.test.ts @@ -2,6 +2,7 @@ import { beforeEach, describe, expect, it, vi } from "vitest"; const manifestMocks = vi.hoisted(() => ({ + getCurrentPluginMetadataSnapshot: vi.fn(), listOpenClawPluginManifestMetadata: vi.fn(), loadPluginManifest: vi.fn(), loadPluginManifestRegistry: vi.fn(), @@ -19,6 +20,10 @@ vi.mock("../../plugins/manifest-metadata-scan.js", () => ({ listOpenClawPluginManifestMetadata: manifestMocks.listOpenClawPluginManifestMetadata, })); +vi.mock("../../plugins/current-plugin-metadata-snapshot.js", () => ({ + getCurrentPluginMetadataSnapshot: manifestMocks.getCurrentPluginMetadataSnapshot, +})); + vi.mock("../../plugins/manifest.js", async (importOriginal) => ({ ...(await importOriginal()), loadPluginManifest: manifestMocks.loadPluginManifest, @@ -117,6 +122,7 @@ function createMistralManifestPlugin(overrides?: { } beforeEach(() => { + manifestMocks.getCurrentPluginMetadataSnapshot.mockReset(); manifestMocks.listOpenClawPluginManifestMetadata.mockReset(); manifestMocks.loadPluginManifest.mockReset(); manifestMocks.loadPluginManifestRegistry.mockReset(); @@ -127,6 +133,7 @@ beforeEach(() => { providerMocks.resolveRuntimePluginDiscoveryProviders.mockReset(); providerMocks.runProviderStaticCatalog.mockReset(); setManifestPlugins([]); + manifestMocks.getCurrentPluginMetadataSnapshot.mockReturnValue(undefined); manifestMocks.loadPluginManifestRegistry.mockReturnValue({ plugins: [] }); providerMocks.resolveActivatableProviderOwnerPluginIds.mockImplementation( ({ pluginIds }: { pluginIds: string[] }) => pluginIds, @@ -158,6 +165,78 @@ describe("canonicalizeManifestModelCatalogProviderAlias", () => { expect(canonicalizeManifestModelCatalogProviderAlias({ provider })).toBe("moonshot"); } }); + + it("reuses the current plugin metadata snapshot for repeated alias lookups", () => { + const plugins = [ + { + providers: ["moonshot"], + modelCatalog: { + aliases: { + "moonshot-ai": { provider: "moonshot" }, + }, + }, + }, + ]; + manifestMocks.getCurrentPluginMetadataSnapshot.mockReturnValue({ plugins }); + + expect(canonicalizeManifestModelCatalogProviderAlias({ provider: "moonshot-ai" })).toBe( + "moonshot", + ); + expect(canonicalizeManifestModelCatalogProviderAlias({ provider: "moonshot-ai" })).toBe( + "moonshot", + ); + expect(manifestMocks.loadPluginManifestRegistry).not.toHaveBeenCalled(); + expect(manifestMocks.getCurrentPluginMetadataSnapshot).toHaveBeenLastCalledWith({ + config: undefined, + env: process.env, + requireDefaultDiscoveryContext: true, + workspaceDir: undefined, + }); + }); + + it("requests an exact configured workspace snapshot", () => { + const cfg = { plugins: { allow: ["openai"] } }; + manifestMocks.getCurrentPluginMetadataSnapshot.mockReturnValue({ plugins: [] }); + + canonicalizeManifestModelCatalogProviderAlias({ + provider: "openai", + cfg, + workspaceDir: "/workspace", + }); + + expect(manifestMocks.getCurrentPluginMetadataSnapshot).toHaveBeenCalledWith({ + config: cfg, + env: process.env, + workspaceDir: "/workspace", + }); + }); + + it("keeps custom environments on their own manifest registry context", () => { + const env = { HOME: "/custom-home" }; + manifestMocks.getCurrentPluginMetadataSnapshot.mockReturnValue({ plugins: [] }); + manifestMocks.loadPluginManifestRegistry.mockReturnValue({ + plugins: [ + { + providers: ["moonshot"], + modelCatalog: { + aliases: { + "moonshot-ai": { provider: "moonshot" }, + }, + }, + }, + ], + }); + + expect(canonicalizeManifestModelCatalogProviderAlias({ provider: "moonshot-ai", env })).toBe( + "moonshot", + ); + expect(manifestMocks.getCurrentPluginMetadataSnapshot).not.toHaveBeenCalled(); + expect(manifestMocks.loadPluginManifestRegistry).toHaveBeenCalledWith({ + config: undefined, + env, + workspaceDir: undefined, + }); + }); }); describe("resolveBundledStaticCatalogModel", () => { diff --git a/src/agents/embedded-agent-runner/model.static-catalog.ts b/src/agents/embedded-agent-runner/model.static-catalog.ts index 24aa1e7fc3a1..a867af287a7c 100644 --- a/src/agents/embedded-agent-runner/model.static-catalog.ts +++ b/src/agents/embedded-agent-runner/model.static-catalog.ts @@ -7,6 +7,7 @@ import type { ModelProviderConfig } from "../../config/types.models.js"; import type { OpenClawConfig } from "../../config/types.openclaw.js"; import { planManifestModelCatalogRows } from "../../model-catalog/manifest-planner.js"; import { normalizePluginsConfig } from "../../plugins/config-state.js"; +import { getCurrentPluginMetadataSnapshot } from "../../plugins/current-plugin-metadata-snapshot.js"; import { listOpenClawPluginManifestMetadata } from "../../plugins/manifest-metadata-scan.js"; import { passesManifestOwnerBasePolicy } from "../../plugins/manifest-owner-policy.js"; import { loadPluginManifestRegistry } from "../../plugins/manifest-registry.js"; @@ -207,14 +208,29 @@ export function canonicalizeManifestModelCatalogProviderAlias(params: { if (!provider) { return params.provider; } + const env = params.env ?? process.env; + // Gateway plugin metadata is process-stable. Reuse its lifecycle-owned snapshot + // so every model turn does not rediscover the same manifest alias table. + const currentPlugins = + env === process.env + ? getCurrentPluginMetadataSnapshot({ + config: params.cfg, + workspaceDir: params.workspaceDir, + env, + ...(params.cfg === undefined ? { requireDefaultDiscoveryContext: true } : {}), + })?.plugins + : undefined; + const plugins = + currentPlugins ?? + loadPluginManifestRegistry({ + config: params.cfg, + workspaceDir: params.workspaceDir, + env, + }).plugins; return ( resolveManifestModelCatalogProviderAlias({ provider, - plugins: loadPluginManifestRegistry({ - config: params.cfg, - workspaceDir: params.workspaceDir, - env: params.env ?? process.env, - }).plugins, + plugins, }) ?? params.provider ); }