import type { OpenClawConfig } from "../config/config.js"; import { STATE_DIR } from "../config/paths.js"; import { createSubsystemLogger } from "../logging/subsystem.js"; import type { PluginRegistry } from "./registry.js"; import type { OpenClawPluginServiceContext, PluginLogger } from "./types.js"; const log = createSubsystemLogger("plugins"); function createPluginLogger(): PluginLogger { return { info: (msg) => log.info(msg), warn: (msg) => log.warn(msg), error: (msg) => log.error(msg), debug: (msg) => log.debug(msg), }; } function createServiceContext(params: { config: OpenClawConfig; workspaceDir?: string; }): OpenClawPluginServiceContext { return { config: params.config, workspaceDir: params.workspaceDir, stateDir: STATE_DIR, logger: createPluginLogger(), }; } export type PluginServicesHandle = { stop: () => Promise; }; export async function startPluginServices(params: { registry: PluginRegistry; config: OpenClawConfig; workspaceDir?: string; }): Promise { const running: Array<{ id: string; stop?: () => void | Promise; }> = []; const serviceContext = createServiceContext({ config: params.config, workspaceDir: params.workspaceDir, }); for (const entry of params.registry.services) { const service = entry.service; try { await service.start(serviceContext); running.push({ id: service.id, stop: service.stop ? () => service.stop?.(serviceContext) : undefined, }); } catch (err) { log.error(`plugin service failed (${service.id}): ${String(err)}`); } } return { stop: async () => { for (const entry of running.toReversed()) { if (!entry.stop) { continue; } try { await entry.stop(); } catch (err) { log.warn(`plugin service stop failed (${entry.id}): ${String(err)}`); } } }, }; }