106 lines
3.3 KiB
TypeScript
106 lines
3.3 KiB
TypeScript
import { existsSync, statSync } from 'node:fs';
|
|
import path from 'node:path';
|
|
|
|
import { getErrorMessage } from '@shared/utils/errorHandling';
|
|
|
|
import {
|
|
applyOpenCodeRuntimeBinaryEnv,
|
|
OPENCODE_LEGACY_BINARY_PATH_ENV,
|
|
OPENCODE_RUNTIME_BINARY_PATH_ENV,
|
|
} from './openCodeRuntimeBinaryEnv';
|
|
|
|
export interface EnsureOpenCodeBridgeRuntimeBinaryEnvOptions {
|
|
targetEnv: NodeJS.ProcessEnv;
|
|
bridgeEnv?: NodeJS.ProcessEnv;
|
|
resolveVerifiedOpenCodeRuntimeBinaryPath: () => Promise<string | null>;
|
|
onWarning?: (message: string) => void;
|
|
}
|
|
|
|
function resolveExistingFilePath(filePath: string): string | null {
|
|
const resolvedPath = path.resolve(filePath.trim());
|
|
if (!existsSync(resolvedPath)) {
|
|
return null;
|
|
}
|
|
try {
|
|
return statSync(resolvedPath).isFile() ? resolvedPath : null;
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
function getOpenCodeRuntimeBinaryEnvValues(env: NodeJS.ProcessEnv): string[] {
|
|
return [
|
|
env[OPENCODE_RUNTIME_BINARY_PATH_ENV]?.trim(),
|
|
env[OPENCODE_LEGACY_BINARY_PATH_ENV]?.trim(),
|
|
].filter((value): value is string => Boolean(value));
|
|
}
|
|
|
|
function resolveExistingOpenCodeRuntimeBinaryEnvPath(env: NodeJS.ProcessEnv): string | null {
|
|
for (const value of getOpenCodeRuntimeBinaryEnvValues(env)) {
|
|
const resolvedPath = resolveExistingFilePath(value);
|
|
if (resolvedPath) {
|
|
return resolvedPath;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
function clearOpenCodeRuntimeBinaryEnvValues(
|
|
env: NodeJS.ProcessEnv,
|
|
invalidValues: Set<string>
|
|
): void {
|
|
for (const key of [OPENCODE_RUNTIME_BINARY_PATH_ENV, OPENCODE_LEGACY_BINARY_PATH_ENV]) {
|
|
const value = env[key]?.trim();
|
|
if (value && invalidValues.has(value)) {
|
|
delete env[key];
|
|
}
|
|
}
|
|
}
|
|
|
|
export async function ensureOpenCodeBridgeRuntimeBinaryEnv({
|
|
targetEnv,
|
|
bridgeEnv = targetEnv,
|
|
resolveVerifiedOpenCodeRuntimeBinaryPath,
|
|
onWarning,
|
|
}: EnsureOpenCodeBridgeRuntimeBinaryEnvOptions): Promise<void> {
|
|
if (
|
|
targetEnv[OPENCODE_RUNTIME_BINARY_PATH_ENV]?.trim() ||
|
|
targetEnv[OPENCODE_LEGACY_BINARY_PATH_ENV]?.trim()
|
|
) {
|
|
const existingBinaryPath = resolveExistingOpenCodeRuntimeBinaryEnvPath(targetEnv);
|
|
if (!existingBinaryPath) {
|
|
const invalidValues = new Set(getOpenCodeRuntimeBinaryEnvValues(targetEnv));
|
|
clearOpenCodeRuntimeBinaryEnvValues(targetEnv, invalidValues);
|
|
if (targetEnv !== bridgeEnv) {
|
|
clearOpenCodeRuntimeBinaryEnvValues(bridgeEnv, invalidValues);
|
|
}
|
|
} else {
|
|
targetEnv[OPENCODE_RUNTIME_BINARY_PATH_ENV] = existingBinaryPath;
|
|
targetEnv[OPENCODE_LEGACY_BINARY_PATH_ENV] = existingBinaryPath;
|
|
applyOpenCodeRuntimeBinaryEnv(targetEnv, existingBinaryPath);
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (
|
|
targetEnv[OPENCODE_RUNTIME_BINARY_PATH_ENV]?.trim() ||
|
|
targetEnv[OPENCODE_LEGACY_BINARY_PATH_ENV]?.trim()
|
|
) {
|
|
applyOpenCodeRuntimeBinaryEnv(targetEnv, null);
|
|
return;
|
|
}
|
|
|
|
try {
|
|
const openCodeBinary = await resolveVerifiedOpenCodeRuntimeBinaryPath();
|
|
applyOpenCodeRuntimeBinaryEnv(targetEnv, openCodeBinary);
|
|
if (
|
|
targetEnv !== bridgeEnv &&
|
|
targetEnv[OPENCODE_RUNTIME_BINARY_PATH_ENV] &&
|
|
!bridgeEnv[OPENCODE_RUNTIME_BINARY_PATH_ENV]
|
|
) {
|
|
applyOpenCodeRuntimeBinaryEnv(bridgeEnv, targetEnv[OPENCODE_RUNTIME_BINARY_PATH_ENV]);
|
|
}
|
|
} catch (error) {
|
|
onWarning?.(`[OpenCode] Runtime adapter OpenCode binary unresolved: ${getErrorMessage(error)}`);
|
|
}
|
|
}
|