Plugins: extract loader pipeline
This commit is contained in:
parent
d6d28037db
commit
a8b3b1c008
@ -42,8 +42,9 @@ This is an implementation checklist, not a future-design spec.
|
||||
| Loader module-export, config-validation, and memory-slot decisions | `src/plugins/loader.ts` | `src/extension-host/loader-runtime.ts` | `partial` | Module export resolution, export-metadata application, config validation, and early or final memory-slot decisions now delegate through host-owned loader-runtime helpers. |
|
||||
| Loader post-import planning and register execution | `src/plugins/loader.ts` | `src/extension-host/loader-register.ts` | `partial` | Definition application, post-import validation planning, and `register(...)` execution now delegate through host-owned loader-register helpers while preserving current plugin behavior. |
|
||||
| Loader per-candidate orchestration | `src/plugins/loader.ts` | `src/extension-host/loader-flow.ts` | `partial` | The per-candidate load flow now runs through a host-owned orchestrator that composes planning, import, runtime validation, register execution, and record-state helpers. |
|
||||
| Loader top-level load orchestration | `src/plugins/loader.ts` | `src/extension-host/loader-orchestrator.ts` | `partial` | Cache hits, runtime creation, discovery, manifest loading, candidate ordering, candidate processing, and finalization now route through a host-owned loader orchestrator while `src/plugins/loader.ts` remains the compatibility facade. |
|
||||
| Loader top-level load orchestration | `src/plugins/loader.ts` | `src/extension-host/loader-orchestrator.ts` | `partial` | High-level load entry and compatibility facade behavior now route through a host-owned loader orchestrator while `src/plugins/loader.ts` remains the external compatibility surface. |
|
||||
| Loader preflight and cache-hit setup | mixed inside `src/plugins/loader.ts` and `src/extension-host/loader-orchestrator.ts` | `src/extension-host/loader-preflight.ts` | `partial` | Test-default application, config normalization, cache-key construction, cache-hit activation, and command-clear preflight now delegate through a host-owned loader-preflight helper. |
|
||||
| Loader post-preflight pipeline composition | mixed inside `src/plugins/loader.ts` and `src/extension-host/loader-orchestrator.ts` | `src/extension-host/loader-pipeline.ts` | `partial` | Post-preflight execution setup and session-run composition now delegate through a host-owned loader-pipeline helper. |
|
||||
| Loader execution setup composition | mixed inside `src/plugins/loader.ts` and `src/extension-host/loader-orchestrator.ts` | `src/extension-host/loader-execution.ts` | `partial` | Runtime creation, registry creation, bootstrap setup, module-loader creation, and session creation now delegate through a host-owned loader-execution helper. |
|
||||
| Loader discovery and manifest bootstrap | mixed inside `src/plugins/loader.ts` and `src/extension-host/loader-orchestrator.ts` | `src/extension-host/loader-bootstrap.ts` | `partial` | Discovery, manifest loading, manifest diagnostics, discovery-policy logging, provenance building, and candidate ordering now delegate through a host-owned loader-bootstrap helper. |
|
||||
| Loader mutable activation state session | local variables in `src/extension-host/loader-orchestrator.ts` | `src/extension-host/loader-session.ts` | `partial` | Seen-id tracking, memory-slot selection state, and finalization inputs now live in a host-owned loader session instead of being spread across top-level loader variables. |
|
||||
|
||||
@ -1,25 +1,22 @@
|
||||
import type { OpenClawConfig } from "../config/config.js";
|
||||
import { activateExtensionHostRegistry } from "../extension-host/activation.js";
|
||||
import {
|
||||
clearExtensionHostRegistryCache,
|
||||
setCachedExtensionHostRegistry,
|
||||
} from "../extension-host/loader-cache.js";
|
||||
import type { GatewayRequestHandler } from "../gateway/server-methods/types.js";
|
||||
import { clearExtensionHostRegistryCache } from "../extension-host/loader-cache.js";
|
||||
import { createSubsystemLogger } from "../logging/subsystem.js";
|
||||
import { clearPluginCommands } from "../plugins/commands.js";
|
||||
import type { PluginRegistry } from "../plugins/registry.js";
|
||||
import { createPluginRuntime, type CreatePluginRuntimeOptions } from "../plugins/runtime/index.js";
|
||||
import type { PluginLogger } from "../plugins/types.js";
|
||||
import { prepareExtensionHostLoaderExecution } from "./loader-execution.js";
|
||||
import { executeExtensionHostLoaderPipeline } from "./loader-pipeline.js";
|
||||
import { prepareExtensionHostLoaderPreflight } from "./loader-preflight.js";
|
||||
import { runExtensionHostLoaderSession } from "./loader-run.js";
|
||||
|
||||
export type ExtensionHostPluginLoadOptions = {
|
||||
config?: OpenClawConfig;
|
||||
workspaceDir?: string;
|
||||
env?: NodeJS.ProcessEnv;
|
||||
logger?: PluginLogger;
|
||||
coreGatewayHandlers?: Record<string, GatewayRequestHandler>;
|
||||
coreGatewayHandlers?: Record<
|
||||
string,
|
||||
import("../gateway/server-methods/types.js").GatewayRequestHandler
|
||||
>;
|
||||
runtimeOptions?: CreatePluginRuntimeOptions;
|
||||
cache?: boolean;
|
||||
mode?: "full" | "validate";
|
||||
@ -46,30 +43,13 @@ export function loadExtensionHostPluginRegistry(
|
||||
return preflight.registry;
|
||||
}
|
||||
|
||||
const execution = prepareExtensionHostLoaderExecution({
|
||||
config: preflight.config,
|
||||
return executeExtensionHostLoaderPipeline({
|
||||
preflight,
|
||||
workspaceDir: options.workspaceDir,
|
||||
env: preflight.env,
|
||||
cache: options.cache,
|
||||
cacheKey: preflight.cacheKey,
|
||||
normalizedConfig: preflight.normalizedConfig,
|
||||
logger: preflight.logger,
|
||||
coreGatewayHandlers: options.coreGatewayHandlers as Record<string, GatewayRequestHandler>,
|
||||
coreGatewayHandlers: options.coreGatewayHandlers,
|
||||
runtimeOptions: options.runtimeOptions,
|
||||
warningCache: openAllowlistWarningCache,
|
||||
setCachedRegistry: setCachedExtensionHostRegistry,
|
||||
activateRegistry: activateExtensionHostRegistry,
|
||||
createRuntime: createPluginRuntime,
|
||||
});
|
||||
|
||||
return runExtensionHostLoaderSession({
|
||||
session: execution.session,
|
||||
orderedCandidates: execution.orderedCandidates,
|
||||
manifestByRoot: execution.manifestByRoot,
|
||||
normalizedConfig: preflight.normalizedConfig,
|
||||
rootConfig: preflight.config,
|
||||
validateOnly: preflight.validateOnly,
|
||||
createApi: execution.createApi,
|
||||
loadModule: execution.loadModule,
|
||||
});
|
||||
}
|
||||
|
||||
46
src/extension-host/loader-pipeline.test.ts
Normal file
46
src/extension-host/loader-pipeline.test.ts
Normal file
@ -0,0 +1,46 @@
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import { executeExtensionHostLoaderPipeline } from "./loader-pipeline.js";
|
||||
|
||||
describe("extension host loader pipeline", () => {
|
||||
it("threads preflight data through execution setup and session run", () => {
|
||||
const session = {} as never;
|
||||
const createApi = vi.fn() as never;
|
||||
const loadModule = vi.fn() as never;
|
||||
const registry = { plugins: [] } as never;
|
||||
const resultRegistry = { plugins: [{ id: "demo" }] } as never;
|
||||
|
||||
const result = executeExtensionHostLoaderPipeline({
|
||||
preflight: {
|
||||
cacheHit: false,
|
||||
env: { TEST: "1" },
|
||||
config: { plugins: { enabled: true } },
|
||||
logger: { info() {}, warn() {}, error() {} },
|
||||
validateOnly: true,
|
||||
normalizedConfig: {
|
||||
enabled: true,
|
||||
allow: [],
|
||||
loadPaths: [],
|
||||
entries: {},
|
||||
slots: {},
|
||||
},
|
||||
cacheKey: "cache-key",
|
||||
},
|
||||
workspaceDir: "/workspace",
|
||||
cache: false,
|
||||
coreGatewayHandlers: { ping: vi.fn() as never },
|
||||
warningCache: new Set<string>(),
|
||||
createRuntime: vi.fn(() => ({}) as never) as never,
|
||||
prepareExecution: vi.fn(() => ({
|
||||
registry,
|
||||
createApi,
|
||||
loadModule,
|
||||
session,
|
||||
orderedCandidates: [{ rootDir: "/plugins/a" }],
|
||||
manifestByRoot: new Map([["/plugins/a", { rootDir: "/plugins/a" }]]),
|
||||
})) as never,
|
||||
runSession: vi.fn(() => resultRegistry) as never,
|
||||
});
|
||||
|
||||
expect(result).toBe(resultRegistry);
|
||||
});
|
||||
});
|
||||
51
src/extension-host/loader-pipeline.ts
Normal file
51
src/extension-host/loader-pipeline.ts
Normal file
@ -0,0 +1,51 @@
|
||||
import type { GatewayRequestHandler } from "../gateway/server-methods/types.js";
|
||||
import type { PluginRegistry } from "../plugins/registry.js";
|
||||
import type { CreatePluginRuntimeOptions } from "../plugins/runtime/index.js";
|
||||
import type { PluginRuntime } from "../plugins/runtime/types.js";
|
||||
import { activateExtensionHostRegistry } from "./activation.js";
|
||||
import { setCachedExtensionHostRegistry } from "./loader-cache.js";
|
||||
import { prepareExtensionHostLoaderExecution } from "./loader-execution.js";
|
||||
import type { ExtensionHostLoaderPreflightReady } from "./loader-preflight.js";
|
||||
import { runExtensionHostLoaderSession } from "./loader-run.js";
|
||||
|
||||
export function executeExtensionHostLoaderPipeline(params: {
|
||||
preflight: ExtensionHostLoaderPreflightReady;
|
||||
workspaceDir?: string;
|
||||
cache?: boolean;
|
||||
coreGatewayHandlers?: Record<string, GatewayRequestHandler>;
|
||||
runtimeOptions?: CreatePluginRuntimeOptions;
|
||||
warningCache: Set<string>;
|
||||
createRuntime: (runtimeOptions?: CreatePluginRuntimeOptions) => PluginRuntime;
|
||||
prepareExecution?: typeof prepareExtensionHostLoaderExecution;
|
||||
runSession?: typeof runExtensionHostLoaderSession;
|
||||
}): PluginRegistry {
|
||||
const prepareExecution = params.prepareExecution ?? prepareExtensionHostLoaderExecution;
|
||||
const runSession = params.runSession ?? runExtensionHostLoaderSession;
|
||||
|
||||
const execution = prepareExecution({
|
||||
config: params.preflight.config,
|
||||
workspaceDir: params.workspaceDir,
|
||||
env: params.preflight.env,
|
||||
cache: params.cache,
|
||||
cacheKey: params.preflight.cacheKey,
|
||||
normalizedConfig: params.preflight.normalizedConfig,
|
||||
logger: params.preflight.logger,
|
||||
coreGatewayHandlers: params.coreGatewayHandlers as Record<string, GatewayRequestHandler>,
|
||||
runtimeOptions: params.runtimeOptions,
|
||||
warningCache: params.warningCache,
|
||||
setCachedRegistry: setCachedExtensionHostRegistry,
|
||||
activateRegistry: activateExtensionHostRegistry,
|
||||
createRuntime: params.createRuntime,
|
||||
});
|
||||
|
||||
return runSession({
|
||||
session: execution.session,
|
||||
orderedCandidates: execution.orderedCandidates,
|
||||
manifestByRoot: execution.manifestByRoot,
|
||||
normalizedConfig: params.preflight.normalizedConfig,
|
||||
rootConfig: params.preflight.config,
|
||||
validateOnly: params.preflight.validateOnly,
|
||||
createApi: execution.createApi,
|
||||
loadModule: execution.loadModule,
|
||||
});
|
||||
}
|
||||
@ -18,6 +18,27 @@ export type ExtensionHostLoaderPreflightOptions = {
|
||||
mode?: ExtensionHostPluginLoadMode;
|
||||
};
|
||||
|
||||
export type ExtensionHostLoaderPreflightCacheHit = {
|
||||
cacheHit: true;
|
||||
registry: ReturnType<typeof getCachedExtensionHostRegistry> extends infer T
|
||||
? Exclude<T, undefined>
|
||||
: never;
|
||||
};
|
||||
|
||||
export type ExtensionHostLoaderPreflightReady = {
|
||||
cacheHit: false;
|
||||
env: NodeJS.ProcessEnv;
|
||||
config: OpenClawConfig;
|
||||
logger: PluginLogger;
|
||||
validateOnly: boolean;
|
||||
normalizedConfig: ReturnType<typeof normalizePluginsConfig>;
|
||||
cacheKey: string;
|
||||
};
|
||||
|
||||
export type ExtensionHostLoaderPreflightResult =
|
||||
| ExtensionHostLoaderPreflightCacheHit
|
||||
| ExtensionHostLoaderPreflightReady;
|
||||
|
||||
export function prepareExtensionHostLoaderPreflight(params: {
|
||||
options: ExtensionHostLoaderPreflightOptions;
|
||||
createDefaultLogger: () => PluginLogger;
|
||||
@ -27,7 +48,7 @@ export function prepareExtensionHostLoaderPreflight(params: {
|
||||
buildCacheKey?: typeof buildExtensionHostRegistryCacheKey;
|
||||
getCachedRegistry?: typeof getCachedExtensionHostRegistry;
|
||||
activateRegistry?: typeof activateExtensionHostRegistry;
|
||||
}) {
|
||||
}): ExtensionHostLoaderPreflightResult {
|
||||
const applyTestDefaults = params.applyTestDefaults ?? applyTestPluginDefaults;
|
||||
const normalizeConfig = params.normalizeConfig ?? normalizePluginsConfig;
|
||||
const buildCacheKey = params.buildCacheKey ?? buildExtensionHostRegistryCacheKey;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user