Files
zn-ai/electron/utils/paths.ts
DEV_DSW 71bcc3b3c5 feat: implement telemetry system for application usage tracking
- 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.
2026-04-23 17:21:57 +08:00

159 lines
4.1 KiB
TypeScript

import { app } from 'electron';
import { existsSync, mkdirSync, realpathSync } from 'node:fs';
import { homedir } from 'node:os';
import { join } from 'node:path';
export const OPENCLAW_CONFIG_DIR_NAME = '.openclaw';
export const OPENCLAW_RUNTIME_DIR_NAME = 'runtime';
export const OPENCLAW_PACKAGE_DIR_NAME = 'openclaw';
export const OPENCLAW_ENTRY_FILE_NAME = 'openclaw.mjs';
export const USER_DATA_DIR_ENV_NAME = 'ZN_AI_USER_DATA_DIR';
export interface OpenClawRuntimePaths {
configDir: string;
runtimeDir: string;
dir: string;
resolvedDir: string;
entryPath: string;
}
export function getOpenClawConfigDir(): string {
return join(homedir(), OPENCLAW_CONFIG_DIR_NAME);
}
export function getUserDataDir(): string {
const override = process.env[USER_DATA_DIR_ENV_NAME]?.trim();
if (override) {
return override;
}
return app.getPath('userData');
}
export function getOpenClawRuntimeDir(): string {
return join(getOpenClawConfigDir(), OPENCLAW_RUNTIME_DIR_NAME);
}
export function getOpenClawDir(): string {
if (app.isPackaged) {
return join(process.resourcesPath, OPENCLAW_PACKAGE_DIR_NAME);
}
return join(app.getAppPath(), 'node_modules', OPENCLAW_PACKAGE_DIR_NAME);
}
export function getResourcesDir(): string {
if (app.isPackaged) {
return process.resourcesPath;
}
return join(app.getAppPath(), 'resources');
}
export function getOpenClawResolvedDir(): string {
const dir = getOpenClawDir();
if (!existsSync(dir)) {
return dir;
}
try {
return realpathSync(dir);
} catch {
return dir;
}
}
export function getOpenClawEntryPath(): string {
return join(getOpenClawDir(), OPENCLAW_ENTRY_FILE_NAME);
}
export function getOpenClawNodeModulesDir(): string {
return join(getOpenClawDir(), 'node_modules');
}
export function getOpenClawBuildDir(): string {
return join(app.getAppPath(), 'build', OPENCLAW_PACKAGE_DIR_NAME);
}
export function normalizeNodeRequirePathForNodeOptions(modulePath: string): string {
if (process.platform !== 'win32') {
return modulePath;
}
return modulePath.replace(/\\/g, '/');
}
export function appendNodeRequireToNodeOptions(
nodeOptions: string | undefined,
modulePath: string,
): string {
const normalizedPath = normalizeNodeRequirePathForNodeOptions(modulePath);
return `${nodeOptions ?? ''} --require "${normalizedPath}"`.trim();
}
export function getOpenClawPackageStatus(): {
dir: string;
entryPath: string;
nodeModulesDir: string;
packageExists: boolean;
entryExists: boolean;
nodeModulesExists: boolean;
};
export function getOpenClawPackageStatus(
overrides?: Partial<Pick<OpenClawRuntimePaths, 'dir' | 'entryPath'>>,
): {
dir: string;
entryPath: string;
nodeModulesDir: string;
packageExists: boolean;
entryExists: boolean;
nodeModulesExists: boolean;
} {
const dir = overrides?.dir ?? getOpenClawDir();
const entryPath = overrides?.entryPath ?? join(dir, OPENCLAW_ENTRY_FILE_NAME);
const nodeModulesDir = join(dir, 'node_modules');
const entryExists = existsSync(entryPath);
const nodeModulesExists = existsSync(nodeModulesDir);
return {
dir,
entryPath,
nodeModulesDir,
packageExists: existsSync(dir),
entryExists,
nodeModulesExists,
};
}
export function getClawHubCliBinPath(): string {
const binName = process.platform === 'win32' ? 'clawhub.cmd' : 'clawhub';
return join(app.getAppPath(), 'node_modules', '.bin', binName);
}
export function getClawHubCliEntryPath(): string {
return join(app.getAppPath(), 'node_modules', 'clawhub', 'bin', 'clawdhub.js');
}
export function ensureDir(dir: string): string {
if (!existsSync(dir)) {
mkdirSync(dir, { recursive: true });
}
return dir;
}
export function ensureOpenClawRuntimeLayout(
paths: OpenClawRuntimePaths = getOpenClawRuntimePaths(),
): OpenClawRuntimePaths {
ensureDir(paths.configDir);
ensureDir(paths.runtimeDir);
return paths;
}
export function getOpenClawRuntimePaths(): OpenClawRuntimePaths {
return {
configDir: getOpenClawConfigDir(),
runtimeDir: getOpenClawRuntimeDir(),
dir: getOpenClawDir(),
resolvedDir: getOpenClawResolvedDir(),
entryPath: getOpenClawEntryPath(),
};
}