refactor(runtime): add prepared runtime foundation (#78248)

* docs(runtime): document prepared runtime guidance

* refactor(provider-runtime): thread prepared provider handles

* refactor(runtime-plan): add prepared runtime foundation

* refactor(outbound): add prepared channel runtime facts

* refactor(models): add scoped model reference helpers

* refactor(plugin-sdk): expose prepared runtime helper surfaces
This commit is contained in:
Marcus Castro
2026-05-07 18:49:42 -03:00
committed by GitHub
parent 70eabd3b08
commit 5df08201ff
22 changed files with 824 additions and 66 deletions

View File

@@ -22,8 +22,9 @@ import type {
} from "./types.js";
const providerRuntimePluginCache: ConfigScopedRuntimeCache<ProviderPlugin | null> = new WeakMap();
const PREPARED_PROVIDER_RUNTIME_SURFACES = ["channel"] as const;
type ProviderRuntimePluginLookupParams = {
export type ProviderRuntimePluginLookupParams = {
provider: string;
config?: OpenClawConfig;
workspaceDir?: string;
@@ -33,6 +34,14 @@ type ProviderRuntimePluginLookupParams = {
bundledProviderVitestCompat?: boolean;
};
export type ProviderRuntimePluginHandle = ProviderRuntimePluginLookupParams & {
plugin?: ProviderPlugin;
};
export type ProviderRuntimePluginHandleParams = ProviderRuntimePluginLookupParams & {
runtimeHandle?: ProviderRuntimePluginHandle;
};
function matchesProviderId(provider: ProviderPlugin, providerId: string): boolean {
const normalized = normalizeProviderId(providerId);
if (!normalized) {
@@ -68,13 +77,42 @@ function matchesProviderLiteralId(provider: ProviderPlugin, providerId: string):
return !!normalized && normalizeLowercaseStringOrEmpty(provider.id) === normalized;
}
function resolveCompatibleActiveProviderRegistry(
params: ProviderRuntimePluginLookupParams,
): PluginRegistry | undefined {
return getLoadedRuntimePluginRegistry({
env: params.env,
workspaceDir: params.workspaceDir,
function findProviderRuntimePluginInLoadedRegistries(params: {
lookup: ProviderRuntimePluginLookupParams;
apiOwnerHint?: string;
}): ProviderPlugin | undefined {
const activeRegistry = getLoadedRuntimePluginRegistry({
env: params.lookup.env,
workspaceDir: params.lookup.workspaceDir,
});
const activePlugin = activeRegistry
? findProviderRuntimePluginInRegistry({
registry: activeRegistry,
provider: params.lookup.provider,
apiOwnerHint: params.apiOwnerHint,
})
: undefined;
if (activePlugin) {
return activePlugin;
}
for (const surface of PREPARED_PROVIDER_RUNTIME_SURFACES) {
const registry = getLoadedRuntimePluginRegistry({
env: params.lookup.env,
workspaceDir: params.lookup.workspaceDir,
surface,
});
const plugin = registry
? findProviderRuntimePluginInRegistry({
registry,
provider: params.lookup.provider,
apiOwnerHint: params.apiOwnerHint,
})
: undefined;
if (plugin) {
return plugin;
}
}
return undefined;
}
function findProviderRuntimePluginInRegistry(params: {
@@ -100,7 +138,7 @@ export function resolveProviderPluginsForHooks(params: {
workspaceDir?: string;
env?: NodeJS.ProcessEnv;
onlyPluginIds?: string[];
providerRefs?: string[];
providerRefs?: readonly string[];
applyAutoEnable?: boolean;
bundledProviderAllowlistCompat?: boolean;
bundledProviderVitestCompat?: boolean;
@@ -139,16 +177,12 @@ export function resolveProviderRuntimePlugin(
provider: params.provider,
config: params.config,
});
const activeRegistry = resolveCompatibleActiveProviderRegistry(params);
const activePlugin = activeRegistry
? findProviderRuntimePluginInRegistry({
registry: activeRegistry,
provider: params.provider,
apiOwnerHint,
})
: undefined;
if (activePlugin) {
return activePlugin;
const loadedPlugin = findProviderRuntimePluginInLoadedRegistries({
lookup: params,
apiOwnerHint,
});
if (loadedPlugin) {
return loadedPlugin;
}
const cacheConfig = params.env && params.env !== process.env ? undefined : params.config;
const plugin = resolveConfigScopedRuntimeCacheValue({
@@ -196,14 +230,43 @@ export function resolveProviderHookPlugin(params: {
);
}
export function resolveProviderRuntimePluginHandle(
params: ProviderRuntimePluginLookupParams,
): ProviderRuntimePluginHandle {
const workspaceDir = params.workspaceDir ?? getActivePluginRegistryWorkspaceDirFromState();
const env = params.env;
const runtimePlugin = resolveProviderRuntimePlugin({
...params,
workspaceDir,
env,
});
return {
...params,
workspaceDir,
env,
plugin: runtimePlugin,
};
}
export function ensureProviderRuntimePluginHandle(
params: ProviderRuntimePluginHandleParams,
): ProviderRuntimePluginHandle {
return params.runtimeHandle ?? resolveProviderRuntimePluginHandle(params);
}
export function prepareProviderExtraParams(params: {
provider: string;
config?: OpenClawConfig;
workspaceDir?: string;
env?: NodeJS.ProcessEnv;
runtimeHandle?: ProviderRuntimePluginHandle;
context: ProviderPrepareExtraParamsContext;
}) {
return resolveProviderRuntimePlugin(params)?.prepareExtraParams?.(params.context) ?? undefined;
return (
ensureProviderRuntimePluginHandle(params).plugin?.prepareExtraParams?.(params.context) ??
undefined
);
}
export function resolveProviderExtraParamsForTransport(params: {
@@ -211,10 +274,12 @@ export function resolveProviderExtraParamsForTransport(params: {
config?: OpenClawConfig;
workspaceDir?: string;
env?: NodeJS.ProcessEnv;
runtimeHandle?: ProviderRuntimePluginHandle;
context: ProviderExtraParamsForTransportContext;
}) {
return (
resolveProviderRuntimePlugin(params)?.extraParamsForTransport?.(params.context) ?? undefined
ensureProviderRuntimePluginHandle(params).plugin?.extraParamsForTransport?.(params.context) ??
undefined
);
}
@@ -223,9 +288,12 @@ export function resolveProviderAuthProfileId(params: {
config?: OpenClawConfig;
workspaceDir?: string;
env?: NodeJS.ProcessEnv;
runtimeHandle?: ProviderRuntimePluginHandle;
context: ProviderResolveAuthProfileIdContext;
}): string | undefined {
const resolved = resolveProviderRuntimePlugin(params)?.resolveAuthProfileId?.(params.context);
const resolved = ensureProviderRuntimePluginHandle(params).plugin?.resolveAuthProfileId?.(
params.context,
);
return typeof resolved === "string" && resolved.trim() ? resolved.trim() : undefined;
}
@@ -234,9 +302,13 @@ export function resolveProviderFollowupFallbackRoute(params: {
config?: OpenClawConfig;
workspaceDir?: string;
env?: NodeJS.ProcessEnv;
runtimeHandle?: ProviderRuntimePluginHandle;
context: ProviderFollowupFallbackRouteContext;
}): ProviderFollowupFallbackRouteResult | undefined {
return resolveProviderHookPlugin(params)?.followupFallbackRoute?.(params.context) ?? undefined;
return (
ensureProviderRuntimePluginHandle(params).plugin?.followupFallbackRoute?.(params.context) ??
undefined
);
}
export function wrapProviderStreamFn(params: {
@@ -244,7 +316,10 @@ export function wrapProviderStreamFn(params: {
config?: OpenClawConfig;
workspaceDir?: string;
env?: NodeJS.ProcessEnv;
runtimeHandle?: ProviderRuntimePluginHandle;
context: ProviderWrapStreamFnContext;
}) {
return resolveProviderRuntimePlugin(params)?.wrapStreamFn?.(params.context) ?? undefined;
return (
ensureProviderRuntimePluginHandle(params).plugin?.wrapStreamFn?.(params.context) ?? undefined
);
}

View File

@@ -18,9 +18,11 @@ import {
resolveProviderAuthProfileId,
resolveProviderExtraParamsForTransport,
resolveProviderFollowupFallbackRoute,
ensureProviderRuntimePluginHandle,
resolveProviderHookPlugin,
resolveProviderPluginsForHooks,
resolveProviderRuntimePlugin,
type ProviderRuntimePluginHandle,
wrapProviderStreamFn,
} from "./provider-hook-runtime.js";
import { resolveBundledProviderPolicySurface } from "./provider-public-artifacts.js";
@@ -188,9 +190,10 @@ export function resolveProviderSystemPromptContribution(params: {
config?: OpenClawConfig;
workspaceDir?: string;
env?: NodeJS.ProcessEnv;
runtimeHandle?: ProviderRuntimePluginHandle;
context: ProviderSystemPromptContributionContext;
}): ProviderSystemPromptContribution | undefined {
const plugin = resolveProviderRuntimePlugin(params);
const plugin = ensureProviderRuntimePluginHandle(params).plugin;
const baseOverlay = resolveGpt5SystemPromptContribution({
config: params.context.config ?? params.config,
providerId: params.context.provider ?? params.provider,
@@ -240,9 +243,10 @@ export function transformProviderSystemPrompt(params: {
config?: OpenClawConfig;
workspaceDir?: string;
env?: NodeJS.ProcessEnv;
runtimeHandle?: ProviderRuntimePluginHandle;
context: ProviderTransformSystemPromptContext;
}): string {
const plugin = resolveProviderRuntimePlugin(params);
const plugin = ensureProviderRuntimePluginHandle(params).plugin;
const textTransforms = mergePluginTextTransforms(
resolveRuntimeTextTransforms(),
plugin?.textTransforms,
@@ -257,10 +261,11 @@ export function resolveProviderTextTransforms(params: {
config?: OpenClawConfig;
workspaceDir?: string;
env?: NodeJS.ProcessEnv;
runtimeHandle?: ProviderRuntimePluginHandle;
}): PluginTextTransforms | undefined {
return mergePluginTextTransforms(
resolveRuntimeTextTransforms(),
resolveProviderRuntimePlugin(params)?.textTransforms,
ensureProviderRuntimePluginHandle(params).plugin?.textTransforms,
);
}
@@ -554,9 +559,13 @@ export function normalizeProviderToolSchemasWithPlugin(params: {
config?: OpenClawConfig;
workspaceDir?: string;
env?: NodeJS.ProcessEnv;
runtimeHandle?: ProviderRuntimePluginHandle;
context: ProviderNormalizeToolSchemasContext;
}) {
return resolveProviderRuntimePlugin(params)?.normalizeToolSchemas?.(params.context) ?? undefined;
return (
ensureProviderRuntimePluginHandle(params).plugin?.normalizeToolSchemas?.(params.context) ??
undefined
);
}
export function inspectProviderToolSchemasWithPlugin(params: {
@@ -564,9 +573,13 @@ export function inspectProviderToolSchemasWithPlugin(params: {
config?: OpenClawConfig;
workspaceDir?: string;
env?: NodeJS.ProcessEnv;
runtimeHandle?: ProviderRuntimePluginHandle;
context: ProviderNormalizeToolSchemasContext;
}) {
return resolveProviderRuntimePlugin(params)?.inspectToolSchemas?.(params.context) ?? undefined;
return (
ensureProviderRuntimePluginHandle(params).plugin?.inspectToolSchemas?.(params.context) ??
undefined
);
}
export function resolveProviderReasoningOutputModeWithPlugin(params: {