import { ensureOpenClawRuntimeLayout, getOpenClawRuntimePaths, type OpenClawRuntimePaths, } from '@electron/utils/paths'; export type OpenClawProcessOwnerState = | 'idle' | 'preparing' | 'running' | 'stopping' | 'stopped' | 'failed'; export interface OpenClawProcessOwnerStatus { state: OpenClawProcessOwnerState; prepared: boolean; runtimePaths: OpenClawRuntimePaths; lastError?: string; } export interface OpenClawProcessOwnerOptions { runtimePaths?: Partial; } export interface OpenClawProcessOwnerLike { prepare(): Promise; start(): Promise; stop(): Promise; restart(): Promise; getStatus(): OpenClawProcessOwnerStatus; getRuntimePaths(): OpenClawRuntimePaths; } function mergeRuntimePaths( base: OpenClawRuntimePaths, override?: Partial, ): OpenClawRuntimePaths { if (!override) { return base; } return { configDir: override.configDir ?? base.configDir, runtimeDir: override.runtimeDir ?? base.runtimeDir, dir: override.dir ?? base.dir, resolvedDir: override.resolvedDir ?? base.resolvedDir, entryPath: override.entryPath ?? base.entryPath, }; } export class OpenClawProcessOwner implements OpenClawProcessOwnerLike { private status: OpenClawProcessOwnerStatus; constructor(options?: OpenClawProcessOwnerOptions) { const runtimePaths = mergeRuntimePaths( getOpenClawRuntimePaths(), options?.runtimePaths, ); this.status = { state: 'idle', prepared: false, runtimePaths, }; } async prepare(): Promise { if (this.status.prepared) { return; } this.status.state = 'preparing'; ensureOpenClawRuntimeLayout(this.status.runtimePaths); this.status.prepared = true; this.status.state = 'idle'; } async start(): Promise { if (this.status.state === 'running') { return; } await this.prepare(); this.status.state = 'running'; } async stop(): Promise { if (this.status.state === 'idle' || this.status.state === 'stopped') { return; } this.status.state = 'stopping'; this.status.state = 'stopped'; } async restart(): Promise { await this.stop(); await this.start(); } getStatus(): OpenClawProcessOwnerStatus { return { ...this.status, runtimePaths: { ...this.status.runtimePaths }, }; } getRuntimePaths(): OpenClawRuntimePaths { return { ...this.status.runtimePaths }; } }