mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-08 20:30:42 +00:00
perf(agents): keep model resolution caches warm
This commit is contained in:
@@ -34,41 +34,26 @@ function matchesProviderLiteralId(provider: ProviderPlugin, providerId: string):
|
||||
return !!normalized && normalizeLowercaseStringOrEmpty(provider.id) === normalized;
|
||||
}
|
||||
|
||||
let cachedHookProvidersWithoutConfig = new WeakMap<
|
||||
NodeJS.ProcessEnv,
|
||||
Map<string, ProviderPlugin[]>
|
||||
>();
|
||||
let cachedHookProvidersByConfig = new WeakMap<
|
||||
OpenClawConfig,
|
||||
WeakMap<NodeJS.ProcessEnv, Map<string, ProviderPlugin[]>>
|
||||
>();
|
||||
let cachedHookProviders = new WeakMap<NodeJS.ProcessEnv, Map<string, ProviderPlugin[]>>();
|
||||
|
||||
function resolveHookProviderCacheBucket(params: {
|
||||
config?: OpenClawConfig;
|
||||
env: NodeJS.ProcessEnv;
|
||||
}) {
|
||||
if (!params.config) {
|
||||
let bucket = cachedHookProvidersWithoutConfig.get(params.env);
|
||||
if (!bucket) {
|
||||
bucket = new Map<string, ProviderPlugin[]>();
|
||||
cachedHookProvidersWithoutConfig.set(params.env, bucket);
|
||||
}
|
||||
return bucket;
|
||||
}
|
||||
|
||||
let envBuckets = cachedHookProvidersByConfig.get(params.config);
|
||||
if (!envBuckets) {
|
||||
envBuckets = new WeakMap<NodeJS.ProcessEnv, Map<string, ProviderPlugin[]>>();
|
||||
cachedHookProvidersByConfig.set(params.config, envBuckets);
|
||||
}
|
||||
let bucket = envBuckets.get(params.env);
|
||||
function resolveHookProviderCacheBucket(env: NodeJS.ProcessEnv) {
|
||||
let bucket = cachedHookProviders.get(env);
|
||||
if (!bucket) {
|
||||
bucket = new Map<string, ProviderPlugin[]>();
|
||||
envBuckets.set(params.env, bucket);
|
||||
cachedHookProviders.set(env, bucket);
|
||||
}
|
||||
return bucket;
|
||||
}
|
||||
|
||||
function resolveHookProviderConfigCacheShape(config: OpenClawConfig | undefined): unknown {
|
||||
if (!config) {
|
||||
return null;
|
||||
}
|
||||
return {
|
||||
plugins: config.plugins,
|
||||
};
|
||||
}
|
||||
|
||||
function buildHookProviderCacheKey(params: {
|
||||
config?: OpenClawConfig;
|
||||
workspaceDir?: string;
|
||||
@@ -81,18 +66,11 @@ function buildHookProviderCacheKey(params: {
|
||||
env: params.env,
|
||||
});
|
||||
const onlyPluginIds = normalizePluginIdScope(params.onlyPluginIds);
|
||||
return `${roots.workspace ?? ""}::${roots.global}::${roots.stock ?? ""}::${JSON.stringify(params.config ?? null)}::${serializePluginIdScope(onlyPluginIds)}::${JSON.stringify(params.providerRefs ?? [])}`;
|
||||
return `${roots.workspace ?? ""}::${roots.global}::${roots.stock ?? ""}::${JSON.stringify(resolveHookProviderConfigCacheShape(params.config))}::${serializePluginIdScope(onlyPluginIds)}::${JSON.stringify(params.providerRefs ?? [])}`;
|
||||
}
|
||||
|
||||
export function clearProviderRuntimeHookCache(): void {
|
||||
cachedHookProvidersWithoutConfig = new WeakMap<
|
||||
NodeJS.ProcessEnv,
|
||||
Map<string, ProviderPlugin[]>
|
||||
>();
|
||||
cachedHookProvidersByConfig = new WeakMap<
|
||||
OpenClawConfig,
|
||||
WeakMap<NodeJS.ProcessEnv, Map<string, ProviderPlugin[]>>
|
||||
>();
|
||||
cachedHookProviders = new WeakMap<NodeJS.ProcessEnv, Map<string, ProviderPlugin[]>>();
|
||||
}
|
||||
|
||||
export function resetProviderRuntimeHookCacheForTest(): void {
|
||||
@@ -116,10 +94,7 @@ export function resolveProviderPluginsForHooks(params: {
|
||||
}): ProviderPlugin[] {
|
||||
const env = params.env ?? process.env;
|
||||
const workspaceDir = params.workspaceDir ?? getActivePluginRegistryWorkspaceDirFromState();
|
||||
const cacheBucket = resolveHookProviderCacheBucket({
|
||||
config: params.config,
|
||||
env,
|
||||
});
|
||||
const cacheBucket = resolveHookProviderCacheBucket(env);
|
||||
const cacheKey = buildHookProviderCacheKey({
|
||||
config: params.config,
|
||||
workspaceDir,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { AgentMessage } from "@mariozechner/pi-agent-core";
|
||||
import { beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import type { ModelProviderConfig } from "../config/types.js";
|
||||
import type { ModelProviderConfig, OpenClawConfig } from "../config/types.js";
|
||||
import type { ProviderRuntimeModel } from "./provider-runtime-model.types.js";
|
||||
import {
|
||||
expectAugmentedCodexCatalog,
|
||||
@@ -503,6 +503,50 @@ describe("provider-runtime", () => {
|
||||
expect(providerRuntimeWarnMock).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("reuses catalog hook provider loads when only non-plugin config changes", () => {
|
||||
resolveCatalogHookProviderPluginIdsMock.mockReturnValue(["demo"]);
|
||||
resolvePluginProvidersMock.mockReturnValue([
|
||||
{
|
||||
id: "demo",
|
||||
label: "Demo",
|
||||
auth: [],
|
||||
suppressBuiltInModel: () => ({ suppress: true, errorMessage: "suppressed" }),
|
||||
},
|
||||
]);
|
||||
const baseConfig = {
|
||||
plugins: {
|
||||
entries: {
|
||||
demo: { enabled: true },
|
||||
},
|
||||
},
|
||||
} as OpenClawConfig;
|
||||
const firstConfig = {
|
||||
...baseConfig,
|
||||
agents: { defaults: { model: "openai/gpt-5.4" } },
|
||||
} as OpenClawConfig;
|
||||
const secondConfig = {
|
||||
...baseConfig,
|
||||
agents: { defaults: { model: "anthropic/claude-sonnet-4-5" } },
|
||||
} as OpenClawConfig;
|
||||
|
||||
expect(
|
||||
resolveProviderBuiltInModelSuppression({
|
||||
config: firstConfig,
|
||||
env: process.env,
|
||||
context: { config: firstConfig, env: process.env, provider: "openai", modelId: "demo" },
|
||||
})?.suppress,
|
||||
).toBe(true);
|
||||
expect(
|
||||
resolveProviderBuiltInModelSuppression({
|
||||
config: secondConfig,
|
||||
env: process.env,
|
||||
context: { config: secondConfig, env: process.env, provider: "openai", modelId: "demo" },
|
||||
})?.suppress,
|
||||
).toBe(true);
|
||||
|
||||
expect(resolvePluginProvidersMock).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it("returns provider-prepared runtime auth for the matched provider", async () => {
|
||||
const prepareRuntimeAuth = vi.fn(async () => ({
|
||||
apiKey: "runtime-token",
|
||||
|
||||
Reference in New Issue
Block a user