mirror of
https://github.com/openclaw/openclaw.git
synced 2026-06-08 20:22:56 +00:00
chore: remove old unused helpers
This commit is contained in:
@@ -1,8 +1,7 @@
|
||||
import { accessSync, constants, existsSync, readFileSync, realpathSync } from "node:fs";
|
||||
import { existsSync, readFileSync } from "node:fs";
|
||||
import { homedir } from "node:os";
|
||||
import { basename, dirname, join, resolve, sep, win32 } from "node:path";
|
||||
import { dirname, join, resolve } from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { spawnProcessSync } from "./utils/child-process.ts";
|
||||
|
||||
// =============================================================================
|
||||
// Package Detection
|
||||
@@ -20,321 +19,6 @@ export const isBunBinary =
|
||||
import.meta.url.includes("~BUN") ||
|
||||
import.meta.url.includes("%7EBUN");
|
||||
|
||||
/** Detect if Bun is the runtime (compiled binary or bun run) */
|
||||
export const isBunRuntime = !!process.versions.bun;
|
||||
|
||||
// =============================================================================
|
||||
// Install Method Detection
|
||||
// =============================================================================
|
||||
|
||||
export type InstallMethod = "bun-binary" | "npm" | "pnpm" | "yarn" | "bun" | "unknown";
|
||||
|
||||
interface SelfUpdateCommandStep {
|
||||
command: string;
|
||||
args: string[];
|
||||
display: string;
|
||||
}
|
||||
|
||||
export interface SelfUpdateCommand extends SelfUpdateCommandStep {
|
||||
steps?: SelfUpdateCommandStep[];
|
||||
}
|
||||
|
||||
function makeSelfUpdateCommand(
|
||||
installStep: SelfUpdateCommandStep,
|
||||
uninstallStep?: SelfUpdateCommandStep,
|
||||
): SelfUpdateCommand {
|
||||
if (!uninstallStep) {
|
||||
return installStep;
|
||||
}
|
||||
return {
|
||||
...installStep,
|
||||
display: `${uninstallStep.display} && ${installStep.display}`,
|
||||
steps: [uninstallStep, installStep],
|
||||
};
|
||||
}
|
||||
|
||||
function makeSelfUpdateCommandStep(command: string, args: string[]): SelfUpdateCommandStep {
|
||||
return {
|
||||
command,
|
||||
args,
|
||||
display: [command, ...args].map((arg) => (/\s/.test(arg) ? `"${arg}"` : arg)).join(" "),
|
||||
};
|
||||
}
|
||||
|
||||
export function detectInstallMethod(): InstallMethod {
|
||||
if (isBunBinary) {
|
||||
return "bun-binary";
|
||||
}
|
||||
|
||||
const resolvedPath = `${currentDir}\0${process.execPath || ""}`.toLowerCase().replace(/\\/g, "/");
|
||||
|
||||
if (resolvedPath.includes("/pnpm/") || resolvedPath.includes("/.pnpm/")) {
|
||||
return "pnpm";
|
||||
}
|
||||
if (resolvedPath.includes("/yarn/") || resolvedPath.includes("/.yarn/")) {
|
||||
return "yarn";
|
||||
}
|
||||
if (isBunRuntime || resolvedPath.includes("/install/global/node_modules/")) {
|
||||
return "bun";
|
||||
}
|
||||
if (resolvedPath.includes("/npm/") || resolvedPath.includes("/node_modules/")) {
|
||||
return "npm";
|
||||
}
|
||||
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
function getInferredNpmInstall(): { root: string; prefix: string } | undefined {
|
||||
const packageDir = getPackageDir();
|
||||
const path =
|
||||
process.platform === "win32" || packageDir.includes("\\") ? win32 : { basename, dirname };
|
||||
const parent = path.dirname(packageDir);
|
||||
let root: string | undefined;
|
||||
if (
|
||||
path.basename(parent).startsWith("@") &&
|
||||
path.basename(path.dirname(parent)) === "node_modules"
|
||||
) {
|
||||
root = path.dirname(parent);
|
||||
} else if (path.basename(parent) === "node_modules") {
|
||||
root = parent;
|
||||
}
|
||||
if (!root) {
|
||||
return undefined;
|
||||
}
|
||||
const rootParent = path.dirname(root);
|
||||
if (path.basename(rootParent) === "lib") {
|
||||
return { root, prefix: path.dirname(rootParent) };
|
||||
}
|
||||
// Windows global npm prefixes use `<prefix>\\node_modules`, which is
|
||||
// indistinguishable from local project installs by path shape alone. Do not
|
||||
// infer unsupported Windows custom prefixes without `npm root -g` evidence.
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function getSelfUpdateCommandForMethod(
|
||||
method: InstallMethod,
|
||||
installedPackageName: string,
|
||||
updatePackageName = installedPackageName,
|
||||
npmCommand?: string[],
|
||||
): SelfUpdateCommand | undefined {
|
||||
switch (method) {
|
||||
case "bun-binary":
|
||||
return undefined;
|
||||
case "pnpm":
|
||||
return makeSelfUpdateCommand(
|
||||
makeSelfUpdateCommandStep("pnpm", ["install", "-g", "--ignore-scripts", updatePackageName]),
|
||||
updatePackageName === installedPackageName
|
||||
? undefined
|
||||
: makeSelfUpdateCommandStep("pnpm", ["remove", "-g", installedPackageName]),
|
||||
);
|
||||
case "yarn":
|
||||
return makeSelfUpdateCommand(
|
||||
makeSelfUpdateCommandStep("yarn", ["global", "add", "--ignore-scripts", updatePackageName]),
|
||||
updatePackageName === installedPackageName
|
||||
? undefined
|
||||
: makeSelfUpdateCommandStep("yarn", ["global", "remove", installedPackageName]),
|
||||
);
|
||||
case "bun":
|
||||
return makeSelfUpdateCommand(
|
||||
makeSelfUpdateCommandStep("bun", ["install", "-g", "--ignore-scripts", updatePackageName]),
|
||||
updatePackageName === installedPackageName
|
||||
? undefined
|
||||
: makeSelfUpdateCommandStep("bun", ["uninstall", "-g", installedPackageName]),
|
||||
);
|
||||
case "npm": {
|
||||
const [command = "npm", ...npmArgs] = npmCommand ?? [];
|
||||
const inferred = npmCommand?.length ? undefined : getInferredNpmInstall();
|
||||
const prefixArgs = [...npmArgs, ...(inferred ? ["--prefix", inferred.prefix] : [])];
|
||||
const installStep = makeSelfUpdateCommandStep(command, [
|
||||
...prefixArgs,
|
||||
"install",
|
||||
"-g",
|
||||
"--ignore-scripts",
|
||||
updatePackageName,
|
||||
]);
|
||||
const uninstallStep =
|
||||
updatePackageName === installedPackageName
|
||||
? undefined
|
||||
: makeSelfUpdateCommandStep(command, [
|
||||
...prefixArgs,
|
||||
"uninstall",
|
||||
"-g",
|
||||
installedPackageName,
|
||||
]);
|
||||
return makeSelfUpdateCommand(installStep, uninstallStep);
|
||||
}
|
||||
case "unknown":
|
||||
return undefined;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function readCommandOutput(
|
||||
command: string,
|
||||
args: string[],
|
||||
options: { requireSuccess?: boolean } = {},
|
||||
): string | undefined {
|
||||
const result = spawnProcessSync(command, args, {
|
||||
encoding: "utf-8",
|
||||
stdio: ["ignore", "pipe", "pipe"],
|
||||
});
|
||||
if (result.status === 0) {
|
||||
return result.stdout.trim() || undefined;
|
||||
}
|
||||
if (options.requireSuccess) {
|
||||
const reason =
|
||||
result.error?.message || result.stderr.trim() || `exit code ${result.status ?? "unknown"}`;
|
||||
throw new Error(`Failed to run ${[command, ...args].join(" ")}: ${reason}`);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function getGlobalPackageRoots(
|
||||
method: InstallMethod,
|
||||
_packageName: string,
|
||||
npmCommand?: string[],
|
||||
): string[] {
|
||||
switch (method) {
|
||||
case "npm": {
|
||||
const configured = !!npmCommand?.length;
|
||||
const [command = "npm", ...npmArgs] = npmCommand ?? [];
|
||||
if (configured && command === "bun") {
|
||||
const bunBin = readCommandOutput(command, [...npmArgs, "pm", "bin", "-g"], {
|
||||
requireSuccess: true,
|
||||
});
|
||||
const roots = [join(homedir(), ".bun", "install", "global", "node_modules")];
|
||||
if (bunBin) {
|
||||
roots.push(join(dirname(bunBin), "install", "global", "node_modules"));
|
||||
}
|
||||
return roots;
|
||||
}
|
||||
const root = readCommandOutput(command, [...npmArgs, "root", "-g"], {
|
||||
requireSuccess: configured,
|
||||
});
|
||||
const inferred = configured ? undefined : getInferredNpmInstall();
|
||||
return [root, inferred?.root].filter((x): x is string => !!x);
|
||||
}
|
||||
case "pnpm": {
|
||||
const root = readCommandOutput("pnpm", ["root", "-g"]);
|
||||
return root ? [root, dirname(root)] : [];
|
||||
}
|
||||
case "yarn": {
|
||||
const dir = readCommandOutput("yarn", ["global", "dir"]);
|
||||
return dir ? [dir, join(dir, "node_modules")] : [];
|
||||
}
|
||||
case "bun": {
|
||||
const bunBin = readCommandOutput("bun", ["pm", "bin", "-g"]);
|
||||
const roots = [join(homedir(), ".bun", "install", "global", "node_modules")];
|
||||
if (bunBin) {
|
||||
roots.push(join(dirname(bunBin), "install", "global", "node_modules"));
|
||||
}
|
||||
return roots;
|
||||
}
|
||||
case "bun-binary":
|
||||
case "unknown":
|
||||
return [];
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
function normalizeExistingPathForComparison(
|
||||
path: string,
|
||||
resolveSymlinks: boolean,
|
||||
): string | undefined {
|
||||
const resolvedPath = resolve(path);
|
||||
if (!existsSync(resolvedPath)) {
|
||||
return undefined;
|
||||
}
|
||||
let normalizedPath = resolvedPath;
|
||||
if (resolveSymlinks) {
|
||||
try {
|
||||
normalizedPath = realpathSync(resolvedPath);
|
||||
} catch {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
if (process.platform === "win32") {
|
||||
normalizedPath = normalizedPath.toLowerCase();
|
||||
}
|
||||
return normalizedPath;
|
||||
}
|
||||
|
||||
function getPathComparisonCandidates(path: string): string[] {
|
||||
return Array.from(
|
||||
new Set(
|
||||
[
|
||||
normalizeExistingPathForComparison(path, false),
|
||||
normalizeExistingPathForComparison(path, true),
|
||||
].filter((candidate): candidate is string => !!candidate),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
function getEntrypointPackageDir(): string | undefined {
|
||||
const entrypoint = process.argv[1];
|
||||
if (!entrypoint) {
|
||||
return undefined;
|
||||
}
|
||||
let dir = dirname(entrypoint);
|
||||
while (dir !== dirname(dir)) {
|
||||
if (existsSync(join(dir, "package.json"))) {
|
||||
return dir;
|
||||
}
|
||||
dir = dirname(dir);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function isSelfUpdatePathWritable(): boolean {
|
||||
const packageDir = getPackageDir();
|
||||
try {
|
||||
accessSync(packageDir, constants.W_OK);
|
||||
accessSync(dirname(packageDir), constants.W_OK);
|
||||
return true;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function isManagedByGlobalPackageManager(
|
||||
method: InstallMethod,
|
||||
packageName: string,
|
||||
npmCommand?: string[],
|
||||
): boolean {
|
||||
const packageDirs = [getPackageDir(), getEntrypointPackageDir()].filter(
|
||||
(dir): dir is string => !!dir,
|
||||
);
|
||||
const packageDirCandidates = packageDirs.flatMap((dir) => getPathComparisonCandidates(dir));
|
||||
return getGlobalPackageRoots(method, packageName, npmCommand).some((root) => {
|
||||
return getPathComparisonCandidates(root).some((normalizedRoot) => {
|
||||
const rootPrefix = normalizedRoot.endsWith(sep) ? normalizedRoot : `${normalizedRoot}${sep}`;
|
||||
return packageDirCandidates.some((packageDir) => packageDir.startsWith(rootPrefix));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export function getSelfUpdateUnavailableInstruction(
|
||||
packageName: string,
|
||||
npmCommand?: string[],
|
||||
updatePackageName = packageName,
|
||||
): string {
|
||||
const method = detectInstallMethod();
|
||||
if (method === "bun-binary") {
|
||||
return `Download from: https://github.com/openclaw/openclaw/releases/latest`;
|
||||
}
|
||||
const command = getSelfUpdateCommandForMethod(method, packageName, updatePackageName, npmCommand);
|
||||
if (command) {
|
||||
if (
|
||||
isManagedByGlobalPackageManager(method, packageName, npmCommand) &&
|
||||
!isSelfUpdatePathWritable()
|
||||
) {
|
||||
return `This installation is managed by a global ${method} install, but the install path is not writable. Update it yourself with: ${command.display}`;
|
||||
}
|
||||
return `This installation is not managed by a global ${method} install. Update it with the package manager, wrapper, or source checkout that provides it.`;
|
||||
}
|
||||
return `Update ${updatePackageName} using the package manager, wrapper, or source checkout that provides this installation.`;
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// Package Asset Paths (shipped with executable)
|
||||
// =============================================================================
|
||||
|
||||
@@ -1,14 +1,4 @@
|
||||
export {
|
||||
bashExecutionToText,
|
||||
BRANCH_SUMMARY_PREFIX,
|
||||
BRANCH_SUMMARY_SUFFIX,
|
||||
COMPACTION_SUMMARY_PREFIX,
|
||||
COMPACTION_SUMMARY_SUFFIX,
|
||||
convertToLlm,
|
||||
createBranchSummaryMessage,
|
||||
createCompactionSummaryMessage,
|
||||
createCustomMessage,
|
||||
} from "../../../packages/agent-core/src/harness/messages.js";
|
||||
export { convertToLlm } from "../../../packages/agent-core/src/harness/messages.js";
|
||||
|
||||
export type {
|
||||
BashExecutionMessage,
|
||||
|
||||
@@ -114,25 +114,6 @@ export function resolveConfigValueOrThrow(config: string, description: string):
|
||||
throw new Error(`Failed to resolve ${description}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve all header values using the same resolution logic as API keys.
|
||||
*/
|
||||
export function resolveHeaders(
|
||||
headers: Record<string, string> | undefined,
|
||||
): Record<string, string> | undefined {
|
||||
if (!headers) {
|
||||
return undefined;
|
||||
}
|
||||
const resolved: Record<string, string> = {};
|
||||
for (const [key, value] of Object.entries(headers)) {
|
||||
const resolvedValue = resolveConfigValue(value);
|
||||
if (resolvedValue) {
|
||||
resolved[key] = resolvedValue;
|
||||
}
|
||||
}
|
||||
return Object.keys(resolved).length > 0 ? resolved : undefined;
|
||||
}
|
||||
|
||||
export function resolveHeadersOrThrow(
|
||||
headers: Record<string, string> | undefined,
|
||||
description: string,
|
||||
|
||||
@@ -22,7 +22,6 @@ import { DefaultResourceLoader } from "./resource-loader.js";
|
||||
import { getDefaultSessionDir, SessionManager } from "./session-manager.js";
|
||||
import { SettingsManager } from "./settings-manager.js";
|
||||
import { isInstallTelemetryEnabled } from "./telemetry.js";
|
||||
import { time } from "./timings.js";
|
||||
import {
|
||||
createBashTool,
|
||||
createCodingTools,
|
||||
@@ -218,7 +217,6 @@ export async function createAgentSession(
|
||||
if (!resourceLoader) {
|
||||
resourceLoader = new DefaultResourceLoader({ cwd, agentDir, settingsManager });
|
||||
await resourceLoader.reload();
|
||||
time("resourceLoader.reload");
|
||||
}
|
||||
|
||||
// Check if session has existing data to restore
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
/**
|
||||
* Central timing instrumentation for startup profiling.
|
||||
* Enable with OPENCLAW_TIMING=1 environment variable.
|
||||
*/
|
||||
|
||||
const ENABLED = process.env.OPENCLAW_TIMING === "1";
|
||||
const timings: Array<{ label: string; ms: number }> = [];
|
||||
let lastTime = Date.now();
|
||||
|
||||
export function resetTimings(): void {
|
||||
if (!ENABLED) {
|
||||
return;
|
||||
}
|
||||
timings.length = 0;
|
||||
lastTime = Date.now();
|
||||
}
|
||||
|
||||
export function time(label: string): void {
|
||||
if (!ENABLED) {
|
||||
return;
|
||||
}
|
||||
const now = Date.now();
|
||||
timings.push({ label, ms: now - lastTime });
|
||||
lastTime = now;
|
||||
}
|
||||
|
||||
export function printTimings(): void {
|
||||
if (!ENABLED || timings.length === 0) {
|
||||
return;
|
||||
}
|
||||
console.error("\n--- Startup Timings ---");
|
||||
for (const t of timings) {
|
||||
console.error(` ${t.label}: ${t.ms}ms`);
|
||||
}
|
||||
console.error(` TOTAL: ${timings.reduce((a, b) => a + b.ms, 0)}ms`);
|
||||
console.error("------------------------\n");
|
||||
}
|
||||
@@ -2,11 +2,8 @@ import {
|
||||
type ChildProcess,
|
||||
type ChildProcessByStdio,
|
||||
spawn as nodeSpawn,
|
||||
spawnSync as nodeSpawnSync,
|
||||
type SpawnOptions,
|
||||
type SpawnOptionsWithStdioTuple,
|
||||
type SpawnSyncOptionsWithStringEncoding,
|
||||
type SpawnSyncReturns,
|
||||
type StdioNull,
|
||||
type StdioPipe,
|
||||
} from "node:child_process";
|
||||
@@ -27,16 +24,6 @@ export function spawnProcess(command: string, args: string[], options: SpawnOpti
|
||||
: nodeSpawn(command, args, options);
|
||||
}
|
||||
|
||||
export function spawnProcessSync(
|
||||
command: string,
|
||||
args: string[],
|
||||
options: SpawnSyncOptionsWithStringEncoding,
|
||||
): SpawnSyncReturns<string> {
|
||||
return process.platform === "win32"
|
||||
? crossSpawn.sync(command, args, options)
|
||||
: nodeSpawnSync(command, args, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait for a child process to terminate without hanging on inherited stdio handles.
|
||||
*
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import "./fs-safe-defaults.js";
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import { tryReadJsonSync, tryReadJson, writeJsonSync } from "@openclaw/fs-safe/json";
|
||||
import { tryReadJsonSync, writeJsonSync } from "@openclaw/fs-safe/json";
|
||||
|
||||
export { tryReadJson, tryReadJsonSync, writeJsonSync };
|
||||
export const readJsonFile = tryReadJson;
|
||||
export { tryReadJsonSync, writeJsonSync };
|
||||
|
||||
function resolveJsonSymlinkTarget(pathname: string): string | undefined {
|
||||
let stat: fs.Stats;
|
||||
|
||||
Reference in New Issue
Block a user