Context: extract extension host engine runtime
This commit is contained in:
parent
67ca7cc1d8
commit
fd981bf95c
@ -1,5 +1,10 @@
|
|||||||
import type { OpenClawConfig } from "../config/config.js";
|
import {
|
||||||
import { defaultSlotIdForKey } from "../plugins/slots.js";
|
getExtensionHostContextEngineFactory,
|
||||||
|
listExtensionHostContextEngineIds,
|
||||||
|
registerExtensionHostContextEngine,
|
||||||
|
resolveExtensionHostContextEngine,
|
||||||
|
type ExtensionHostContextEngineFactory,
|
||||||
|
} from "../extension-host/context-engine-runtime.js";
|
||||||
import type { ContextEngine } from "./types.js";
|
import type { ContextEngine } from "./types.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -97,18 +102,12 @@ export function registerContextEngine(
|
|||||||
return registerContextEngineForOwner(id, factory, PUBLIC_CONTEXT_ENGINE_OWNER);
|
return registerContextEngineForOwner(id, factory, PUBLIC_CONTEXT_ENGINE_OWNER);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the factory for a registered engine, or undefined.
|
|
||||||
*/
|
|
||||||
export function getContextEngineFactory(id: string): ContextEngineFactory | undefined {
|
export function getContextEngineFactory(id: string): ContextEngineFactory | undefined {
|
||||||
return getContextEngineRegistryState().engines.get(id)?.factory;
|
return getContextEngineRegistryState().engines.get(id)?.factory;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* List all registered engine ids.
|
|
||||||
*/
|
|
||||||
export function listContextEngineIds(): string[] {
|
export function listContextEngineIds(): string[] {
|
||||||
return [...getContextEngineRegistryState().engines.keys()];
|
return listExtensionHostContextEngineIds();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|||||||
42
src/extension-host/context-engine-runtime.test.ts
Normal file
42
src/extension-host/context-engine-runtime.test.ts
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
import { describe, expect, it } from "vitest";
|
||||||
|
import type { ContextEngine } from "../context-engine/types.js";
|
||||||
|
import {
|
||||||
|
getExtensionHostContextEngineFactory,
|
||||||
|
listExtensionHostContextEngineIds,
|
||||||
|
registerExtensionHostContextEngine,
|
||||||
|
} from "./context-engine-runtime.js";
|
||||||
|
|
||||||
|
class TestContextEngine implements ContextEngine {
|
||||||
|
readonly info = {
|
||||||
|
id: "host-test",
|
||||||
|
name: "Host Test",
|
||||||
|
version: "1.0.0",
|
||||||
|
};
|
||||||
|
|
||||||
|
async ingest() {
|
||||||
|
return { ingested: false };
|
||||||
|
}
|
||||||
|
|
||||||
|
async assemble(params: { messages: [] }) {
|
||||||
|
return { messages: params.messages, estimatedTokens: 0 };
|
||||||
|
}
|
||||||
|
|
||||||
|
async afterTurn() {}
|
||||||
|
|
||||||
|
async compact() {
|
||||||
|
return { ok: true, compacted: false, reason: "noop" };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
describe("extension host context engine runtime", () => {
|
||||||
|
it("stores registered context-engine factories in the host-owned runtime", async () => {
|
||||||
|
const factory = () => new TestContextEngine();
|
||||||
|
registerExtensionHostContextEngine("host-test", factory);
|
||||||
|
|
||||||
|
expect(getExtensionHostContextEngineFactory("host-test")).toBe(factory);
|
||||||
|
expect(listExtensionHostContextEngineIds()).toContain("host-test");
|
||||||
|
expect(await getExtensionHostContextEngineFactory("host-test")?.()).toBeInstanceOf(
|
||||||
|
TestContextEngine,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
60
src/extension-host/context-engine-runtime.ts
Normal file
60
src/extension-host/context-engine-runtime.ts
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
import type { OpenClawConfig } from "../config/config.js";
|
||||||
|
import type { ContextEngine } from "../context-engine/types.js";
|
||||||
|
import { defaultSlotIdForKey } from "../plugins/slots.js";
|
||||||
|
|
||||||
|
export type ExtensionHostContextEngineFactory = () => ContextEngine | Promise<ContextEngine>;
|
||||||
|
|
||||||
|
const CONTEXT_ENGINE_RUNTIME_STATE = Symbol.for("openclaw.contextEngineRegistryState");
|
||||||
|
|
||||||
|
type ExtensionHostContextEngineRuntimeState = {
|
||||||
|
engines: Map<string, ExtensionHostContextEngineFactory>;
|
||||||
|
};
|
||||||
|
|
||||||
|
function getExtensionHostContextEngineRuntimeState(): ExtensionHostContextEngineRuntimeState {
|
||||||
|
const globalState = globalThis as typeof globalThis & {
|
||||||
|
[CONTEXT_ENGINE_RUNTIME_STATE]?: ExtensionHostContextEngineRuntimeState;
|
||||||
|
};
|
||||||
|
if (!globalState[CONTEXT_ENGINE_RUNTIME_STATE]) {
|
||||||
|
globalState[CONTEXT_ENGINE_RUNTIME_STATE] = {
|
||||||
|
engines: new Map<string, ExtensionHostContextEngineFactory>(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return globalState[CONTEXT_ENGINE_RUNTIME_STATE];
|
||||||
|
}
|
||||||
|
|
||||||
|
export function registerExtensionHostContextEngine(
|
||||||
|
id: string,
|
||||||
|
factory: ExtensionHostContextEngineFactory,
|
||||||
|
): void {
|
||||||
|
getExtensionHostContextEngineRuntimeState().engines.set(id, factory);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getExtensionHostContextEngineFactory(
|
||||||
|
id: string,
|
||||||
|
): ExtensionHostContextEngineFactory | undefined {
|
||||||
|
return getExtensionHostContextEngineRuntimeState().engines.get(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function listExtensionHostContextEngineIds(): string[] {
|
||||||
|
return [...getExtensionHostContextEngineRuntimeState().engines.keys()];
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function resolveExtensionHostContextEngine(
|
||||||
|
config?: OpenClawConfig,
|
||||||
|
): Promise<ContextEngine> {
|
||||||
|
const slotValue = config?.plugins?.slots?.contextEngine;
|
||||||
|
const engineId =
|
||||||
|
typeof slotValue === "string" && slotValue.trim()
|
||||||
|
? slotValue.trim()
|
||||||
|
: defaultSlotIdForKey("contextEngine");
|
||||||
|
|
||||||
|
const factory = getExtensionHostContextEngineRuntimeState().engines.get(engineId);
|
||||||
|
if (!factory) {
|
||||||
|
throw new Error(
|
||||||
|
`Context engine "${engineId}" is not registered. ` +
|
||||||
|
`Available engines: ${listExtensionHostContextEngineIds().join(", ") || "(none)"}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return factory();
|
||||||
|
}
|
||||||
@ -1,6 +1,5 @@
|
|||||||
import type { AnyAgentTool } from "../agents/tools/common.js";
|
import type { AnyAgentTool } from "../agents/tools/common.js";
|
||||||
import type { ChannelPlugin } from "../channels/plugins/types.js";
|
import type { ChannelPlugin } from "../channels/plugins/types.js";
|
||||||
import { registerContextEngine as registerLegacyContextEngine } from "../context-engine/registry.js";
|
|
||||||
import type { GatewayRequestHandler } from "../gateway/server-methods/types.js";
|
import type { GatewayRequestHandler } from "../gateway/server-methods/types.js";
|
||||||
import { registerInternalHook } from "../hooks/internal-hooks.js";
|
import { registerInternalHook } from "../hooks/internal-hooks.js";
|
||||||
import type { PluginRecord, PluginRegistry } from "../plugins/registry.js";
|
import type { PluginRecord, PluginRegistry } from "../plugins/registry.js";
|
||||||
@ -16,6 +15,7 @@ import type {
|
|||||||
OpenClawPluginToolFactory,
|
OpenClawPluginToolFactory,
|
||||||
PluginHookRegistration as TypedPluginHookRegistration,
|
PluginHookRegistration as TypedPluginHookRegistration,
|
||||||
} from "../plugins/types.js";
|
} from "../plugins/types.js";
|
||||||
|
import { registerExtensionHostContextEngine } from "./context-engine-runtime.js";
|
||||||
import {
|
import {
|
||||||
applyExtensionHostTypedHookPolicy,
|
applyExtensionHostTypedHookPolicy,
|
||||||
bridgeExtensionHostLegacyHooks,
|
bridgeExtensionHostLegacyHooks,
|
||||||
@ -307,7 +307,7 @@ export function createExtensionHostPluginRegistrationActions(params: {
|
|||||||
const registerContextEngine = (
|
const registerContextEngine = (
|
||||||
record: PluginRecord,
|
record: PluginRecord,
|
||||||
engineId: string,
|
engineId: string,
|
||||||
factory: Parameters<typeof registerLegacyContextEngine>[1],
|
factory: Parameters<typeof registerExtensionHostContextEngine>[1],
|
||||||
) => {
|
) => {
|
||||||
const result = resolveExtensionContextEngineRegistration({
|
const result = resolveExtensionContextEngineRegistration({
|
||||||
engineId,
|
engineId,
|
||||||
@ -325,7 +325,7 @@ export function createExtensionHostPluginRegistrationActions(params: {
|
|||||||
}
|
}
|
||||||
addExtensionContextEngineRegistration({
|
addExtensionContextEngineRegistration({
|
||||||
entry: result.entry,
|
entry: result.entry,
|
||||||
registerEngine: registerLegacyContextEngine,
|
registerEngine: registerExtensionHostContextEngine,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
import { registerContextEngine, type ContextEngineFactory } from "../context-engine/registry.js";
|
|
||||||
import type { GatewayRequestHandler } from "../gateway/server-methods/types.js";
|
import type { GatewayRequestHandler } from "../gateway/server-methods/types.js";
|
||||||
import type {
|
import type {
|
||||||
PluginChannelRegistration,
|
PluginChannelRegistration,
|
||||||
@ -13,6 +12,10 @@ import type {
|
|||||||
PluginToolRegistration,
|
PluginToolRegistration,
|
||||||
} from "../plugins/registry.js";
|
} from "../plugins/registry.js";
|
||||||
import type { PluginHookRegistration as TypedPluginHookRegistration } from "../plugins/types.js";
|
import type { PluginHookRegistration as TypedPluginHookRegistration } from "../plugins/types.js";
|
||||||
|
import {
|
||||||
|
registerExtensionHostContextEngine,
|
||||||
|
type ExtensionHostContextEngineFactory,
|
||||||
|
} from "./context-engine-runtime.js";
|
||||||
import type {
|
import type {
|
||||||
ExtensionHostChannelRegistration,
|
ExtensionHostChannelRegistration,
|
||||||
ExtensionHostCliRegistration,
|
ExtensionHostCliRegistration,
|
||||||
@ -162,8 +165,8 @@ export function addExtensionCommandRegistration(params: {
|
|||||||
|
|
||||||
export function addExtensionContextEngineRegistration(params: {
|
export function addExtensionContextEngineRegistration(params: {
|
||||||
entry: ExtensionHostContextEngineRegistration;
|
entry: ExtensionHostContextEngineRegistration;
|
||||||
registerEngine?: (engineId: string, factory: ContextEngineFactory) => void;
|
registerEngine?: (engineId: string, factory: ExtensionHostContextEngineFactory) => void;
|
||||||
}): void {
|
}): void {
|
||||||
const registerEngine = params.registerEngine ?? registerContextEngine;
|
const registerEngine = params.registerEngine ?? registerExtensionHostContextEngine;
|
||||||
registerEngine(params.entry.engineId, params.entry.factory);
|
registerEngine(params.entry.engineId, params.entry.factory);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user