import type { PluginLoadResult } from "./loader.js"; import type { PluginRecord } from "./registry.js"; import type { PluginCompatibilityNotice, PluginStatusReport } from "./status.js"; import type { PluginHookName } from "./types.js"; export const LEGACY_BEFORE_AGENT_START_MESSAGE = "still uses legacy before_agent_start; keep regression coverage on this plugin, and prefer before_model_resolve/before_prompt_build for new work."; export const HOOK_ONLY_MESSAGE = "is hook-only. This remains a supported compatibility path, but it has not migrated to explicit capability registration yet."; export function createCompatibilityNotice( params: Pick, ): PluginCompatibilityNotice { if (params.code === "legacy-before-agent-start") { return { pluginId: params.pluginId, code: params.code, severity: "warn", message: LEGACY_BEFORE_AGENT_START_MESSAGE, }; } return { pluginId: params.pluginId, code: params.code, severity: "info", message: HOOK_ONLY_MESSAGE, }; } export function createPluginRecord( overrides: Partial & Pick, ): PluginRecord { const { id, ...rest } = overrides; return { id, name: overrides.name ?? id, description: overrides.description ?? "", source: overrides.source ?? `/tmp/${id}/index.ts`, origin: overrides.origin ?? "workspace", enabled: overrides.enabled ?? true, status: overrides.status ?? "loaded", toolNames: [], hookNames: [], channelIds: [], providerIds: [], speechProviderIds: [], mediaUnderstandingProviderIds: [], imageGenerationProviderIds: [], webSearchProviderIds: [], gatewayMethods: [], cliCommands: [], services: [], commands: [], httpRoutes: 0, hookCount: 0, configSchema: false, ...rest, }; } export function createTypedHook(params: { pluginId: string; hookName: PluginHookName; source?: string; }): PluginLoadResult["typedHooks"][number] { return { pluginId: params.pluginId, hookName: params.hookName, handler: () => undefined, source: params.source ?? `/tmp/${params.pluginId}/index.ts`, }; } export function createCustomHook(params: { pluginId: string; events: string[]; name?: string; }): PluginLoadResult["hooks"][number] { const source = `/tmp/${params.pluginId}/handler.ts`; return { pluginId: params.pluginId, events: params.events, source, entry: { hook: { name: params.name ?? "legacy", description: "", source: "openclaw-plugin", pluginId: params.pluginId, filePath: `/tmp/${params.pluginId}/HOOK.md`, baseDir: `/tmp/${params.pluginId}`, handlerPath: source, }, frontmatter: {}, }, }; } export function createPluginLoadResult( overrides: Partial & Pick = { plugins: [] }, ): PluginLoadResult { const { plugins, ...rest } = overrides; return { plugins, diagnostics: [], channels: [], channelSetups: [], providers: [], speechProviders: [], mediaUnderstandingProviders: [], imageGenerationProviders: [], webSearchProviders: [], tools: [], hooks: [], typedHooks: [], httpRoutes: [], gatewayHandlers: {}, cliRegistrars: [], services: [], commands: [], conversationBindingResolvedHandlers: [], ...rest, }; } export function createPluginStatusReport( overrides: Partial & Pick, ): PluginStatusReport { const { workspaceDir, ...loadResultOverrides } = overrides; return { workspaceDir, ...createPluginLoadResult(loadResultOverrides), }; }