- Added telemetry utility to capture application events and metrics. - Integrated PostHog for event tracking with distinct user identification. - Implemented telemetry initialization, event capturing, and shutdown procedures. feat: add UV environment setup for Python management - Created utilities to manage Python installation and configuration. - Implemented network optimization checks for Python installation mirrors. - Added functions to set up managed Python environments with error handling. feat: enhance host API communication with token management - Introduced host API token retrieval and management for secure requests. - Updated host API fetch functions to include token in headers. - Added support for creating event sources with authentication. test: add comprehensive tests for gateway protocol and startup helpers - Implemented unit tests for gateway protocol helpers, event dispatching, and state management. - Added tests for startup recovery strategies and process policies. - Ensured coverage for connection monitoring and restart governance logic.
100 lines
2.5 KiB
TypeScript
100 lines
2.5 KiB
TypeScript
import { existsSync } from 'node:fs';
|
|
import { delimiter, join } from 'node:path';
|
|
import { app } from 'electron';
|
|
import { syncBrowserConfigToOpenClaw } from '@electron/utils/openclaw-auth';
|
|
import {
|
|
getOpenClawEntryPath,
|
|
getOpenClawResolvedDir,
|
|
} from '@electron/utils/paths';
|
|
|
|
export interface GatewayLaunchContext {
|
|
openclawDir: string;
|
|
entryScript: string;
|
|
binDir: string;
|
|
gatewayArgs: string[];
|
|
forkEnv: Record<string, string | undefined>;
|
|
mode: 'dev' | 'packaged';
|
|
binPathExists: boolean;
|
|
}
|
|
|
|
export interface PrepareGatewayLaunchContextOptions {
|
|
port: number;
|
|
token: string;
|
|
skipChannels?: boolean;
|
|
}
|
|
|
|
function prependPathEntry(pathValue: string | undefined, entry: string): string {
|
|
if (!pathValue?.trim()) {
|
|
return entry;
|
|
}
|
|
|
|
const segments = pathValue.split(delimiter);
|
|
if (segments.includes(entry)) {
|
|
return pathValue;
|
|
}
|
|
|
|
return `${entry}${delimiter}${pathValue}`;
|
|
}
|
|
|
|
function getBundledBinDir(): string {
|
|
if (app.isPackaged) {
|
|
return join(process.resourcesPath, 'bin');
|
|
}
|
|
|
|
return join(process.cwd(), 'resources', 'bin', `${process.platform}-${process.arch}`);
|
|
}
|
|
|
|
export async function syncGatewayConfigBeforeLaunch(): Promise<void> {
|
|
await syncBrowserConfigToOpenClaw();
|
|
}
|
|
|
|
export async function prepareGatewayLaunchContext(
|
|
options: PrepareGatewayLaunchContextOptions,
|
|
): Promise<GatewayLaunchContext> {
|
|
await syncGatewayConfigBeforeLaunch();
|
|
|
|
const openclawDir = getOpenClawResolvedDir();
|
|
const entryScript = getOpenClawEntryPath();
|
|
|
|
if (!existsSync(entryScript)) {
|
|
throw new Error(`OpenClaw entry script not found at ${entryScript}`);
|
|
}
|
|
|
|
const gatewayArgs = [
|
|
'gateway',
|
|
'--port',
|
|
String(options.port),
|
|
'--token',
|
|
options.token,
|
|
'--allow-unconfigured',
|
|
];
|
|
|
|
const skipChannels = options.skipChannels ?? true;
|
|
const binDir = getBundledBinDir();
|
|
const binPathExists = existsSync(binDir);
|
|
|
|
const {
|
|
NODE_OPTIONS: _nodeOptions,
|
|
ELECTRON_RUN_AS_NODE: _electronRunAsNode,
|
|
...baseEnv
|
|
} = process.env;
|
|
const forkEnv: Record<string, string | undefined> = {
|
|
...baseEnv,
|
|
PATH: binPathExists ? prependPathEntry(baseEnv.PATH, binDir) : baseEnv.PATH,
|
|
OPENCLAW_GATEWAY_TOKEN: options.token,
|
|
OPENCLAW_SKIP_CHANNELS: skipChannels ? '1' : '',
|
|
CLAWDBOT_SKIP_CHANNELS: skipChannels ? '1' : '',
|
|
OPENCLAW_NO_RESPAWN: '1',
|
|
};
|
|
|
|
return {
|
|
openclawDir,
|
|
entryScript,
|
|
binDir,
|
|
gatewayArgs,
|
|
forkEnv,
|
|
mode: app.isPackaged ? 'packaged' : 'dev',
|
|
binPathExists,
|
|
};
|
|
}
|