- Added a new script `bundle-openclaw.mjs` to bundle OpenClaw runtime dependencies. - Updated `after-pack.cjs` to copy bundled OpenClaw runtime and its node_modules. - Improved cleanup of unnecessary development files in node_modules. - Adjusted paths for resources in the packaging process. style: update loading indicator styles in ChatHistoryPanel - Changed the border radius and padding for the loading indicator in ChatHistoryPanel. fix: improve ProvidersSection to handle provider account syncing - Added logic to sync model configuration to provider accounts. - Introduced error handling and loading states during the sync process. - Enhanced vendor resolution and account management logic. fix: fallback session handling in chat store - Implemented fallback session logic in loadSessions to ensure a valid session is always available on error.
145 lines
3.6 KiB
TypeScript
145 lines
3.6 KiB
TypeScript
import {
|
|
ensureOpenClawRuntimeLayout,
|
|
getOpenClawPackageStatus,
|
|
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;
|
|
packageExists: boolean;
|
|
entryExists: boolean;
|
|
nodeModulesPath: string;
|
|
nodeModulesExists: boolean;
|
|
lastError?: string;
|
|
}
|
|
|
|
export interface OpenClawProcessOwnerOptions {
|
|
runtimePaths?: Partial<OpenClawRuntimePaths>;
|
|
}
|
|
|
|
export interface OpenClawProcessOwnerLike {
|
|
prepare(): Promise<void>;
|
|
start(): Promise<void>;
|
|
stop(): Promise<void>;
|
|
restart(): Promise<void>;
|
|
getStatus(): OpenClawProcessOwnerStatus;
|
|
getRuntimePaths(): OpenClawRuntimePaths;
|
|
}
|
|
|
|
function mergeRuntimePaths(
|
|
base: OpenClawRuntimePaths,
|
|
override?: Partial<OpenClawRuntimePaths>,
|
|
): 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;
|
|
|
|
private syncPackageStatus(): void {
|
|
const packageStatus = getOpenClawPackageStatus(this.status.runtimePaths);
|
|
this.status.packageExists = packageStatus.packageExists;
|
|
this.status.entryExists = packageStatus.entryExists;
|
|
this.status.nodeModulesPath = packageStatus.nodeModulesDir;
|
|
this.status.nodeModulesExists = packageStatus.nodeModulesExists;
|
|
}
|
|
|
|
constructor(options?: OpenClawProcessOwnerOptions) {
|
|
const runtimePaths = mergeRuntimePaths(
|
|
getOpenClawRuntimePaths(),
|
|
options?.runtimePaths,
|
|
);
|
|
|
|
this.status = {
|
|
state: 'idle',
|
|
prepared: false,
|
|
runtimePaths,
|
|
packageExists: false,
|
|
entryExists: false,
|
|
nodeModulesPath: '',
|
|
nodeModulesExists: false,
|
|
};
|
|
|
|
this.syncPackageStatus();
|
|
}
|
|
|
|
async prepare(): Promise<void> {
|
|
if (this.status.prepared) {
|
|
return;
|
|
}
|
|
|
|
this.status.state = 'preparing';
|
|
ensureOpenClawRuntimeLayout(this.status.runtimePaths);
|
|
this.status.prepared = true;
|
|
this.syncPackageStatus();
|
|
this.status.lastError = this.status.entryExists
|
|
? undefined
|
|
: `OpenClaw entry not found at ${this.status.runtimePaths.entryPath}`;
|
|
this.status.state = 'idle';
|
|
}
|
|
|
|
async start(): Promise<void> {
|
|
if (this.status.state === 'running') {
|
|
return;
|
|
}
|
|
|
|
await this.prepare();
|
|
this.syncPackageStatus();
|
|
if (!this.status.entryExists) {
|
|
this.status.state = 'failed';
|
|
throw new Error(this.status.lastError || `OpenClaw entry not found at ${this.status.runtimePaths.entryPath}`);
|
|
}
|
|
|
|
this.status.lastError = undefined;
|
|
this.status.state = 'running';
|
|
}
|
|
|
|
async stop(): Promise<void> {
|
|
if (this.status.state === 'idle' || this.status.state === 'stopped') {
|
|
return;
|
|
}
|
|
|
|
this.status.state = 'stopping';
|
|
this.status.state = 'stopped';
|
|
}
|
|
|
|
async restart(): Promise<void> {
|
|
await this.stop();
|
|
await this.start();
|
|
}
|
|
|
|
getStatus(): OpenClawProcessOwnerStatus {
|
|
this.syncPackageStatus();
|
|
|
|
return {
|
|
...this.status,
|
|
runtimePaths: { ...this.status.runtimePaths },
|
|
};
|
|
}
|
|
|
|
getRuntimePaths(): OpenClawRuntimePaths {
|
|
return { ...this.status.runtimePaths };
|
|
}
|
|
}
|