diff --git a/src/plugins/registry.ts b/src/plugins/registry.ts index 4f24714d4e7..fde8d0e6a6d 100644 --- a/src/plugins/registry.ts +++ b/src/plugins/registry.ts @@ -12,7 +12,11 @@ import { resolveUserPath } from "../utils.js"; import { registerPluginCommand } from "./commands.js"; import { normalizePluginHttpPath } from "./http-path.js"; import type { PluginRuntime } from "./runtime/types.js"; -import { isPluginHookName, isPromptInjectionHookName } from "./types.js"; +import { + isPluginHookName, + isPromptInjectionHookName, + stripPromptMutationFieldsFromLegacyHookResult, +} from "./types.js"; import type { OpenClawPluginApi, OpenClawPluginChannelRegistration, @@ -32,7 +36,6 @@ import type { PluginLogger, PluginOrigin, PluginKind, - PluginHookBeforeAgentStartResult, PluginHookName, PluginHookHandlerMap, PluginHookRegistration as TypedPluginHookRegistration, @@ -146,24 +149,6 @@ type PluginTypedHookPolicy = { allowPromptInjection?: boolean; }; -const stripPromptMutationFieldsFromLegacyHookResult = ( - result: PluginHookBeforeAgentStartResult | void, -): PluginHookBeforeAgentStartResult | void => { - if (!result || typeof result !== "object") { - return result; - } - const { - systemPrompt: _systemPrompt, - prependContext: _prependContext, - prependSystemContext: _prependSystemContext, - appendSystemContext: _appendSystemContext, - ...remaining - } = result; - return Object.keys(remaining).length > 0 - ? (remaining as PluginHookBeforeAgentStartResult) - : undefined; -}; - const constrainLegacyPromptInjectionHook = ( handler: PluginHookHandlerMap["before_agent_start"], ): PluginHookHandlerMap["before_agent_start"] => { diff --git a/src/plugins/types.ts b/src/plugins/types.ts index ab0a1a57813..1cb2779e8c2 100644 --- a/src/plugins/types.ts +++ b/src/plugins/types.ts @@ -430,6 +430,22 @@ export type PluginHookBeforePromptBuildResult = { appendSystemContext?: string; }; +export const PLUGIN_PROMPT_MUTATION_RESULT_FIELDS = [ + "systemPrompt", + "prependContext", + "prependSystemContext", + "appendSystemContext", +] as const satisfies readonly (keyof PluginHookBeforePromptBuildResult)[]; + +type MissingPluginPromptMutationResultFields = Exclude< + keyof PluginHookBeforePromptBuildResult, + (typeof PLUGIN_PROMPT_MUTATION_RESULT_FIELDS)[number] +>; +type AssertAllPluginPromptMutationResultFieldsListed = + MissingPluginPromptMutationResultFields extends never ? true : never; +const assertAllPluginPromptMutationResultFieldsListed: AssertAllPluginPromptMutationResultFieldsListed = true; +void assertAllPluginPromptMutationResultFieldsListed; + // before_agent_start hook (legacy compatibility: combines both phases) export type PluginHookBeforeAgentStartEvent = { prompt: string; @@ -440,6 +456,26 @@ export type PluginHookBeforeAgentStartEvent = { export type PluginHookBeforeAgentStartResult = PluginHookBeforePromptBuildResult & PluginHookBeforeModelResolveResult; +export type PluginHookBeforeAgentStartOverrideResult = Omit< + PluginHookBeforeAgentStartResult, + keyof PluginHookBeforePromptBuildResult +>; + +export const stripPromptMutationFieldsFromLegacyHookResult = ( + result: PluginHookBeforeAgentStartResult | void, +): PluginHookBeforeAgentStartOverrideResult | void => { + if (!result || typeof result !== "object") { + return result; + } + const remaining: Partial = { ...result }; + for (const field of PLUGIN_PROMPT_MUTATION_RESULT_FIELDS) { + delete remaining[field]; + } + return Object.keys(remaining).length > 0 + ? (remaining as PluginHookBeforeAgentStartOverrideResult) + : undefined; +}; + // llm_input hook export type PluginHookLlmInputEvent = { runId: string;