
























@@ -1,3 +1,4 @@
1+import fs from "node:fs";
12import path from "node:path";
23import { resolvePreferredNodePath } from "../daemon/runtime-paths.js";
34import {
@@ -51,3 +52,99 @@ export function resolveDaemonNodeBinDir(nodePath?: string): string[] | undefined
5152}
5253return [path.dirname(trimmed)];
5354}
55+56+function isOpenClawCommandBasename(basename: string, platform: NodeJS.Platform): boolean {
57+if (basename === "openclaw") {
58+return true;
59+}
60+if (platform === "win32") {
61+return (
62+basename === "openclaw.cmd" || basename === "openclaw.ps1" || basename === "openclaw.exe"
63+);
64+}
65+return false;
66+}
67+68+function safeRealpathSync(
69+inputPath: string | undefined,
70+realpathSync: (path: string) => string,
71+): string | undefined {
72+if (!inputPath) {
73+return undefined;
74+}
75+try {
76+return realpathSync(inputPath);
77+} catch {
78+return undefined;
79+}
80+}
81+82+function addUniquePathDir(dirs: string[], dir: string | undefined): void {
83+if (!dir || !path.isAbsolute(dir) || dirs.includes(dir)) {
84+return;
85+}
86+dirs.push(dir);
87+}
88+89+export function resolveDaemonOpenClawBinDir(
90+params: {
91+argv?: string[];
92+env?: Record<string, string | undefined>;
93+platform?: NodeJS.Platform;
94+existsSync?: (path: string) => boolean;
95+realpathSync?: (path: string) => string;
96+} = {},
97+): string[] | undefined {
98+const platform = params.platform ?? process.platform;
99+const argv = params.argv ?? process.argv;
100+const env = params.env ?? process.env;
101+const existsSync = params.existsSync ?? fs.existsSync;
102+const realpathSync = params.realpathSync ?? fs.realpathSync.native;
103+const argv1 = argv[1]?.trim();
104+const dirs: string[] = [];
105+106+if (
107+argv1 &&
108+path.isAbsolute(argv1) &&
109+isOpenClawCommandBasename(path.basename(argv1), platform)
110+) {
111+addUniquePathDir(dirs, path.dirname(argv1));
112+}
113+114+const argvRealpath = path.isAbsolute(argv1 ?? "")
115+ ? safeRealpathSync(argv1, realpathSync)
116+ : undefined;
117+for (const rawSegment of (env.PATH ?? "").split(path.delimiter)) {
118+const segment = rawSegment.trim();
119+if (!path.isAbsolute(segment)) {
120+continue;
121+}
122+const candidate = path.join(segment, platform === "win32" ? "openclaw.cmd" : "openclaw");
123+if (!existsSync(candidate)) {
124+continue;
125+}
126+const candidateRealpath = safeRealpathSync(candidate, realpathSync);
127+if (argvRealpath && candidateRealpath && candidateRealpath !== argvRealpath) {
128+continue;
129+}
130+addUniquePathDir(dirs, segment);
131+}
132+133+return dirs.length > 0 ? dirs : undefined;
134+}
135+136+export function resolveDaemonServicePathDirs(params: {
137+nodePath?: string;
138+argv?: string[];
139+env?: Record<string, string | undefined>;
140+platform?: NodeJS.Platform;
141+}): string[] | undefined {
142+const dirs: string[] = [];
143+for (const dir of resolveDaemonNodeBinDir(params.nodePath) ?? []) {
144+addUniquePathDir(dirs, dir);
145+}
146+for (const dir of resolveDaemonOpenClawBinDir(params) ?? []) {
147+addUniquePathDir(dirs, dir);
148+}
149+return dirs.length > 0 ? dirs : undefined;
150+}
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。