@chrysb/alphaclaw 0.8.7-beta.0 → 0.8.7-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/alphaclaw.js +25 -7
- package/lib/server/openclaw-runtime.js +260 -0
- package/lib/server/pending-openclaw-update.js +11 -11
- package/package.json +1 -1
package/bin/alphaclaw.js
CHANGED
|
@@ -19,6 +19,11 @@ const {
|
|
|
19
19
|
const {
|
|
20
20
|
applyPendingOpenclawUpdate,
|
|
21
21
|
} = require("../lib/server/pending-openclaw-update");
|
|
22
|
+
const {
|
|
23
|
+
getManagedOpenclawRuntimeDir,
|
|
24
|
+
prependManagedOpenclawBinToPath,
|
|
25
|
+
syncManagedOpenclawRuntimeWithBundled,
|
|
26
|
+
} = require("../lib/server/openclaw-runtime");
|
|
22
27
|
|
|
23
28
|
const kUsageTrackerPluginPath = path.resolve(
|
|
24
29
|
__dirname,
|
|
@@ -206,21 +211,34 @@ if (fs.existsSync(pendingUpdateMarker)) {
|
|
|
206
211
|
}
|
|
207
212
|
|
|
208
213
|
const pendingOpenclawUpdateMarker = path.join(rootDir, ".openclaw-update-pending");
|
|
214
|
+
const managedOpenclawRuntimeDir = getManagedOpenclawRuntimeDir({ rootDir });
|
|
209
215
|
if (fs.existsSync(pendingOpenclawUpdateMarker)) {
|
|
210
|
-
const alphaPkgRoot = path.resolve(__dirname, "..");
|
|
211
|
-
const nmIndex = alphaPkgRoot.lastIndexOf(
|
|
212
|
-
`${path.sep}node_modules${path.sep}`,
|
|
213
|
-
);
|
|
214
|
-
const installDir =
|
|
215
|
-
nmIndex >= 0 ? alphaPkgRoot.slice(0, nmIndex) : alphaPkgRoot;
|
|
216
216
|
applyPendingOpenclawUpdate({
|
|
217
217
|
execSyncImpl: execSync,
|
|
218
218
|
fsModule: fs,
|
|
219
|
-
installDir,
|
|
219
|
+
installDir: managedOpenclawRuntimeDir,
|
|
220
220
|
logger: console,
|
|
221
221
|
markerPath: pendingOpenclawUpdateMarker,
|
|
222
222
|
});
|
|
223
223
|
}
|
|
224
|
+
try {
|
|
225
|
+
syncManagedOpenclawRuntimeWithBundled({
|
|
226
|
+
execSyncImpl: execSync,
|
|
227
|
+
fsModule: fs,
|
|
228
|
+
logger: console,
|
|
229
|
+
runtimeDir: managedOpenclawRuntimeDir,
|
|
230
|
+
});
|
|
231
|
+
} catch (error) {
|
|
232
|
+
console.log(
|
|
233
|
+
`[alphaclaw] Could not sync managed OpenClaw runtime from bundled install: ${error.message}`,
|
|
234
|
+
);
|
|
235
|
+
}
|
|
236
|
+
prependManagedOpenclawBinToPath({
|
|
237
|
+
env: process.env,
|
|
238
|
+
fsModule: fs,
|
|
239
|
+
logger: console,
|
|
240
|
+
runtimeDir: managedOpenclawRuntimeDir,
|
|
241
|
+
});
|
|
224
242
|
|
|
225
243
|
// ---------------------------------------------------------------------------
|
|
226
244
|
// 3. Symlink ~/.openclaw -> <root>/.openclaw
|
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
const fs = require("fs");
|
|
2
|
+
const path = require("path");
|
|
3
|
+
|
|
4
|
+
const { kRootDir } = require("./constants");
|
|
5
|
+
const {
|
|
6
|
+
compareVersionParts,
|
|
7
|
+
normalizeOpenclawVersion,
|
|
8
|
+
} = require("./helpers");
|
|
9
|
+
|
|
10
|
+
const getManagedOpenclawRuntimeDir = ({ rootDir = kRootDir } = {}) =>
|
|
11
|
+
path.join(rootDir, ".openclaw-runtime");
|
|
12
|
+
|
|
13
|
+
const getManagedOpenclawBinDir = ({ runtimeDir } = {}) =>
|
|
14
|
+
path.join(
|
|
15
|
+
runtimeDir || getManagedOpenclawRuntimeDir(),
|
|
16
|
+
"node_modules",
|
|
17
|
+
".bin",
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
const getManagedOpenclawBinPath = ({ runtimeDir } = {}) =>
|
|
21
|
+
path.join(getManagedOpenclawBinDir({ runtimeDir }), "openclaw");
|
|
22
|
+
|
|
23
|
+
const getManagedOpenclawPackageJsonPath = ({ runtimeDir } = {}) =>
|
|
24
|
+
path.join(
|
|
25
|
+
runtimeDir || getManagedOpenclawRuntimeDir(),
|
|
26
|
+
"node_modules",
|
|
27
|
+
"openclaw",
|
|
28
|
+
"package.json",
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
const ensureManagedOpenclawRuntimeProject = ({
|
|
32
|
+
fsModule = fs,
|
|
33
|
+
runtimeDir,
|
|
34
|
+
} = {}) => {
|
|
35
|
+
const resolvedRuntimeDir = runtimeDir || getManagedOpenclawRuntimeDir();
|
|
36
|
+
const packageJsonPath = path.join(resolvedRuntimeDir, "package.json");
|
|
37
|
+
fsModule.mkdirSync(resolvedRuntimeDir, { recursive: true });
|
|
38
|
+
if (!fsModule.existsSync(packageJsonPath)) {
|
|
39
|
+
fsModule.writeFileSync(
|
|
40
|
+
packageJsonPath,
|
|
41
|
+
JSON.stringify(
|
|
42
|
+
{
|
|
43
|
+
name: "alphaclaw-openclaw-runtime",
|
|
44
|
+
private: true,
|
|
45
|
+
},
|
|
46
|
+
null,
|
|
47
|
+
2,
|
|
48
|
+
),
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
return {
|
|
52
|
+
runtimeDir: resolvedRuntimeDir,
|
|
53
|
+
packageJsonPath,
|
|
54
|
+
};
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const readManagedOpenclawRuntimeVersion = ({
|
|
58
|
+
fsModule = fs,
|
|
59
|
+
runtimeDir,
|
|
60
|
+
} = {}) => {
|
|
61
|
+
try {
|
|
62
|
+
const pkg = JSON.parse(
|
|
63
|
+
fsModule.readFileSync(
|
|
64
|
+
getManagedOpenclawPackageJsonPath({ runtimeDir }),
|
|
65
|
+
"utf8",
|
|
66
|
+
),
|
|
67
|
+
);
|
|
68
|
+
return normalizeOpenclawVersion(pkg?.version || "");
|
|
69
|
+
} catch {
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
const readBundledOpenclawVersion = ({
|
|
75
|
+
fsModule = fs,
|
|
76
|
+
resolveImpl = require.resolve,
|
|
77
|
+
} = {}) => {
|
|
78
|
+
try {
|
|
79
|
+
const pkgPath = resolveImpl("openclaw/package.json");
|
|
80
|
+
const pkg = JSON.parse(fsModule.readFileSync(pkgPath, "utf8"));
|
|
81
|
+
return normalizeOpenclawVersion(pkg?.version || "");
|
|
82
|
+
} catch {
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
const shellQuote = (value) =>
|
|
88
|
+
`'${String(value || "").replace(/'/g, `'\"'\"'`)}'`;
|
|
89
|
+
|
|
90
|
+
const applyManagedOpenclawPatch = ({
|
|
91
|
+
execSyncImpl,
|
|
92
|
+
fsModule = fs,
|
|
93
|
+
logger = console,
|
|
94
|
+
runtimeDir,
|
|
95
|
+
version,
|
|
96
|
+
alphaclawRoot = path.resolve(__dirname, "..", ".."),
|
|
97
|
+
} = {}) => {
|
|
98
|
+
const normalizedVersion = normalizeOpenclawVersion(version);
|
|
99
|
+
if (!normalizedVersion) return false;
|
|
100
|
+
const patchesDir = path.join(alphaclawRoot, "patches");
|
|
101
|
+
const patchFileName = `openclaw+${normalizedVersion}.patch`;
|
|
102
|
+
const patchFilePath = path.join(patchesDir, patchFileName);
|
|
103
|
+
if (!fsModule.existsSync(patchFilePath)) {
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const runtimePatchDirName = ".alphaclaw-patches";
|
|
108
|
+
const runtimePatchDirPath = path.join(runtimeDir, runtimePatchDirName);
|
|
109
|
+
try {
|
|
110
|
+
if (fsModule.existsSync(runtimePatchDirPath)) {
|
|
111
|
+
fsModule.rmSync(runtimePatchDirPath, { recursive: true, force: true });
|
|
112
|
+
}
|
|
113
|
+
} catch {}
|
|
114
|
+
fsModule.symlinkSync(patchesDir, runtimePatchDirPath);
|
|
115
|
+
|
|
116
|
+
const patchPackageMain = require.resolve("patch-package/dist/index.js", {
|
|
117
|
+
paths: [alphaclawRoot],
|
|
118
|
+
});
|
|
119
|
+
logger.log(
|
|
120
|
+
`[alphaclaw] Applying bundled OpenClaw patch for ${normalizedVersion}...`,
|
|
121
|
+
);
|
|
122
|
+
execSyncImpl(
|
|
123
|
+
`${shellQuote(process.execPath)} ${shellQuote(patchPackageMain)} --patch-dir ${shellQuote(runtimePatchDirName)}`,
|
|
124
|
+
{
|
|
125
|
+
cwd: runtimeDir,
|
|
126
|
+
stdio: "inherit",
|
|
127
|
+
timeout: 120000,
|
|
128
|
+
},
|
|
129
|
+
);
|
|
130
|
+
return true;
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
const installManagedOpenclawRuntime = ({
|
|
134
|
+
execSyncImpl,
|
|
135
|
+
fsModule = fs,
|
|
136
|
+
logger = console,
|
|
137
|
+
runtimeDir,
|
|
138
|
+
spec,
|
|
139
|
+
alphaclawRoot,
|
|
140
|
+
} = {}) => {
|
|
141
|
+
const normalizedSpec = String(spec || "").trim() || "openclaw@latest";
|
|
142
|
+
ensureManagedOpenclawRuntimeProject({
|
|
143
|
+
fsModule,
|
|
144
|
+
runtimeDir,
|
|
145
|
+
});
|
|
146
|
+
execSyncImpl(
|
|
147
|
+
`npm install ${shellQuote(normalizedSpec)} --omit=dev --no-save --save=false --package-lock=false --prefer-online`,
|
|
148
|
+
{
|
|
149
|
+
cwd: runtimeDir,
|
|
150
|
+
stdio: "inherit",
|
|
151
|
+
timeout: 180000,
|
|
152
|
+
},
|
|
153
|
+
);
|
|
154
|
+
const installedVersion = readManagedOpenclawRuntimeVersion({
|
|
155
|
+
fsModule,
|
|
156
|
+
runtimeDir,
|
|
157
|
+
});
|
|
158
|
+
applyManagedOpenclawPatch({
|
|
159
|
+
execSyncImpl,
|
|
160
|
+
fsModule,
|
|
161
|
+
logger,
|
|
162
|
+
runtimeDir,
|
|
163
|
+
version: installedVersion,
|
|
164
|
+
alphaclawRoot,
|
|
165
|
+
});
|
|
166
|
+
return {
|
|
167
|
+
spec: normalizedSpec,
|
|
168
|
+
version: installedVersion,
|
|
169
|
+
};
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
const syncManagedOpenclawRuntimeWithBundled = ({
|
|
173
|
+
execSyncImpl,
|
|
174
|
+
fsModule = fs,
|
|
175
|
+
logger = console,
|
|
176
|
+
runtimeDir,
|
|
177
|
+
resolveImpl,
|
|
178
|
+
alphaclawRoot,
|
|
179
|
+
} = {}) => {
|
|
180
|
+
const bundledVersion = readBundledOpenclawVersion({
|
|
181
|
+
fsModule,
|
|
182
|
+
resolveImpl,
|
|
183
|
+
});
|
|
184
|
+
if (!bundledVersion) {
|
|
185
|
+
return {
|
|
186
|
+
checked: false,
|
|
187
|
+
synced: false,
|
|
188
|
+
bundledVersion: null,
|
|
189
|
+
runtimeVersion: readManagedOpenclawRuntimeVersion({ fsModule, runtimeDir }),
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
const runtimeVersion = readManagedOpenclawRuntimeVersion({
|
|
194
|
+
fsModule,
|
|
195
|
+
runtimeDir,
|
|
196
|
+
});
|
|
197
|
+
if (runtimeVersion && compareVersionParts(runtimeVersion, bundledVersion) >= 0) {
|
|
198
|
+
return {
|
|
199
|
+
checked: true,
|
|
200
|
+
synced: false,
|
|
201
|
+
bundledVersion,
|
|
202
|
+
runtimeVersion,
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
logger.log(
|
|
207
|
+
runtimeVersion
|
|
208
|
+
? `[alphaclaw] Managed OpenClaw runtime ${runtimeVersion} is older than bundled ${bundledVersion}; syncing runtime...`
|
|
209
|
+
: `[alphaclaw] Managed OpenClaw runtime missing; seeding bundled OpenClaw ${bundledVersion}...`,
|
|
210
|
+
);
|
|
211
|
+
const installResult = installManagedOpenclawRuntime({
|
|
212
|
+
execSyncImpl,
|
|
213
|
+
fsModule,
|
|
214
|
+
logger,
|
|
215
|
+
runtimeDir,
|
|
216
|
+
spec: `openclaw@${bundledVersion}`,
|
|
217
|
+
alphaclawRoot,
|
|
218
|
+
});
|
|
219
|
+
return {
|
|
220
|
+
checked: true,
|
|
221
|
+
synced: true,
|
|
222
|
+
bundledVersion,
|
|
223
|
+
runtimeVersion: installResult.version || bundledVersion,
|
|
224
|
+
};
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
const prependManagedOpenclawBinToPath = ({
|
|
228
|
+
env = process.env,
|
|
229
|
+
fsModule = fs,
|
|
230
|
+
logger = console,
|
|
231
|
+
runtimeDir,
|
|
232
|
+
} = {}) => {
|
|
233
|
+
const resolvedRuntimeDir = runtimeDir || getManagedOpenclawRuntimeDir();
|
|
234
|
+
const binDir = getManagedOpenclawBinDir({ runtimeDir: resolvedRuntimeDir });
|
|
235
|
+
const binPath = getManagedOpenclawBinPath({ runtimeDir: resolvedRuntimeDir });
|
|
236
|
+
if (!fsModule.existsSync(binPath)) {
|
|
237
|
+
return false;
|
|
238
|
+
}
|
|
239
|
+
const currentEntries = String(env.PATH || "")
|
|
240
|
+
.split(path.delimiter)
|
|
241
|
+
.filter(Boolean);
|
|
242
|
+
const nextEntries = [binDir, ...currentEntries.filter((entry) => entry !== binDir)];
|
|
243
|
+
env.PATH = nextEntries.join(path.delimiter);
|
|
244
|
+
logger.log(`[alphaclaw] Using managed OpenClaw runtime from ${resolvedRuntimeDir}`);
|
|
245
|
+
return true;
|
|
246
|
+
};
|
|
247
|
+
|
|
248
|
+
module.exports = {
|
|
249
|
+
applyManagedOpenclawPatch,
|
|
250
|
+
ensureManagedOpenclawRuntimeProject,
|
|
251
|
+
getManagedOpenclawBinDir,
|
|
252
|
+
getManagedOpenclawBinPath,
|
|
253
|
+
getManagedOpenclawPackageJsonPath,
|
|
254
|
+
getManagedOpenclawRuntimeDir,
|
|
255
|
+
installManagedOpenclawRuntime,
|
|
256
|
+
prependManagedOpenclawBinToPath,
|
|
257
|
+
readBundledOpenclawVersion,
|
|
258
|
+
readManagedOpenclawRuntimeVersion,
|
|
259
|
+
syncManagedOpenclawRuntimeWithBundled,
|
|
260
|
+
};
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
const {
|
|
2
|
+
installManagedOpenclawRuntime,
|
|
3
|
+
} = require("./openclaw-runtime");
|
|
4
|
+
|
|
1
5
|
const buildPendingOpenclawInstallSpec = (marker = {}) => {
|
|
2
6
|
const explicitSpec = String(marker?.spec || "").trim();
|
|
3
7
|
if (explicitSpec) {
|
|
@@ -7,9 +11,6 @@ const buildPendingOpenclawInstallSpec = (marker = {}) => {
|
|
|
7
11
|
return `openclaw@${targetVersion}`;
|
|
8
12
|
};
|
|
9
13
|
|
|
10
|
-
const shellQuote = (value) =>
|
|
11
|
-
`'${String(value || "").replace(/'/g, `'\"'\"'`)}'`;
|
|
12
|
-
|
|
13
14
|
const applyPendingOpenclawUpdate = ({
|
|
14
15
|
execSyncImpl,
|
|
15
16
|
fsModule,
|
|
@@ -36,14 +37,13 @@ const applyPendingOpenclawUpdate = ({
|
|
|
36
37
|
logger.log(`[alphaclaw] Pending OpenClaw update detected, installing ${spec}...`);
|
|
37
38
|
|
|
38
39
|
try {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
);
|
|
40
|
+
installManagedOpenclawRuntime({
|
|
41
|
+
execSyncImpl,
|
|
42
|
+
fsModule,
|
|
43
|
+
logger,
|
|
44
|
+
runtimeDir: installDir,
|
|
45
|
+
spec,
|
|
46
|
+
});
|
|
47
47
|
fsModule.unlinkSync(markerPath);
|
|
48
48
|
logger.log("[alphaclaw] OpenClaw update applied successfully");
|
|
49
49
|
return {
|