@chrysb/alphaclaw 0.9.11 → 0.9.13
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/lib/public/dist/app.bundle.js +1 -1
- package/lib/public/js/components/nodes-tab/connected-nodes/user-connected-nodes.js +1 -1
- package/lib/server/commands.js +5 -0
- package/lib/server/model-catalog-bootstrap.json +1431 -181
- package/lib/server/routes/nodes.js +54 -10
- package/package.json +3 -7
- package/patches/openclaw+2026.4.23.patch +0 -63
- package/scripts/apply-openclaw-patches.js +0 -99
|
@@ -12,12 +12,46 @@ const kAllowedExecAsk = new Set(["off", "on-miss", "always"]);
|
|
|
12
12
|
const kSafeNodeIdPattern = /^[\w\-:.]+$/;
|
|
13
13
|
const kNodeBrowserInvokeTimeoutMs = 30000;
|
|
14
14
|
const kNodeBrowserCliTimeoutMs = 35000;
|
|
15
|
-
const
|
|
16
|
-
const
|
|
17
|
-
const
|
|
15
|
+
const kDefaultNodeRouteCliTimeoutMs = 12000;
|
|
16
|
+
const kDefaultNodesStatusCliTimeoutMs = 12000;
|
|
17
|
+
const kDefaultNodesPendingCliTimeoutMs = 12000;
|
|
18
18
|
|
|
19
19
|
const quoteCliArg = (value) => quoteShellArg(value, { strategy: "single" });
|
|
20
20
|
|
|
21
|
+
const resolveCliTimeoutMs = (envName, fallbackMs, env = process.env) => {
|
|
22
|
+
const parsed = Number(env[envName]);
|
|
23
|
+
if (!Number.isFinite(parsed) || parsed <= 0) return fallbackMs;
|
|
24
|
+
return Math.round(parsed);
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const resolveNodeCliTimeouts = (env = process.env) => ({
|
|
28
|
+
route: resolveCliTimeoutMs(
|
|
29
|
+
"ALPHACLAW_NODE_ROUTE_TIMEOUT_MS",
|
|
30
|
+
kDefaultNodeRouteCliTimeoutMs,
|
|
31
|
+
env,
|
|
32
|
+
),
|
|
33
|
+
status: resolveCliTimeoutMs(
|
|
34
|
+
"ALPHACLAW_NODES_STATUS_TIMEOUT_MS",
|
|
35
|
+
kDefaultNodesStatusCliTimeoutMs,
|
|
36
|
+
env,
|
|
37
|
+
),
|
|
38
|
+
pending: resolveCliTimeoutMs(
|
|
39
|
+
"ALPHACLAW_NODES_PENDING_TIMEOUT_MS",
|
|
40
|
+
kDefaultNodesPendingCliTimeoutMs,
|
|
41
|
+
env,
|
|
42
|
+
),
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
const isCliTimeoutResult = (result) =>
|
|
46
|
+
Boolean(result?.timedOut || (result?.killed && result?.signal));
|
|
47
|
+
|
|
48
|
+
const formatCliFailure = ({ result, fallback, timeoutLabel, timeoutMs }) => {
|
|
49
|
+
if (isCliTimeoutResult(result)) {
|
|
50
|
+
return `${timeoutLabel} CLI timed out after ${timeoutMs}ms`;
|
|
51
|
+
}
|
|
52
|
+
return String(result?.stderr || "").trim() || fallback;
|
|
53
|
+
};
|
|
54
|
+
|
|
21
55
|
const normalizeExecAsk = (value) => {
|
|
22
56
|
const normalized = String(value || "").trim().toLowerCase();
|
|
23
57
|
if (normalized === "on") return "on-miss";
|
|
@@ -159,21 +193,28 @@ const registerNodeRoutes = ({
|
|
|
159
193
|
gatewayToken = "",
|
|
160
194
|
fsModule,
|
|
161
195
|
}) => {
|
|
196
|
+
const cliTimeouts = resolveNodeCliTimeouts();
|
|
197
|
+
|
|
162
198
|
app.get("/api/nodes", async (_req, res) => {
|
|
163
199
|
const statusResult = await clawCmd("nodes status --json", {
|
|
164
200
|
quiet: true,
|
|
165
|
-
timeoutMs:
|
|
201
|
+
timeoutMs: cliTimeouts.status,
|
|
166
202
|
});
|
|
167
203
|
if (!statusResult.ok) {
|
|
168
204
|
return res.status(500).json({
|
|
169
205
|
ok: false,
|
|
170
|
-
error:
|
|
206
|
+
error: formatCliFailure({
|
|
207
|
+
result: statusResult,
|
|
208
|
+
fallback: "Could not load nodes status",
|
|
209
|
+
timeoutLabel: "nodes status",
|
|
210
|
+
timeoutMs: cliTimeouts.status,
|
|
211
|
+
}),
|
|
171
212
|
});
|
|
172
213
|
}
|
|
173
214
|
const status = parseNodesStatus(statusResult.stdout);
|
|
174
215
|
const pendingResult = await clawCmd("nodes pending --json", {
|
|
175
216
|
quiet: true,
|
|
176
|
-
timeoutMs:
|
|
217
|
+
timeoutMs: cliTimeouts.pending,
|
|
177
218
|
});
|
|
178
219
|
const pending = pendingResult.ok
|
|
179
220
|
? parseNodesPending(pendingResult.stdout)
|
|
@@ -220,14 +261,17 @@ const registerNodeRoutes = ({
|
|
|
220
261
|
for (const command of commands) {
|
|
221
262
|
const result = await clawCmd(command, {
|
|
222
263
|
quiet: true,
|
|
223
|
-
timeoutMs:
|
|
264
|
+
timeoutMs: cliTimeouts.route,
|
|
224
265
|
});
|
|
225
266
|
if (!result.ok) {
|
|
226
267
|
return res.status(500).json({
|
|
227
268
|
ok: false,
|
|
228
|
-
error:
|
|
229
|
-
result
|
|
230
|
-
`Could not apply node routing (${command})`,
|
|
269
|
+
error: formatCliFailure({
|
|
270
|
+
result,
|
|
271
|
+
fallback: `Could not apply node routing (${command})`,
|
|
272
|
+
timeoutLabel: "node routing",
|
|
273
|
+
timeoutMs: cliTimeouts.route,
|
|
274
|
+
}),
|
|
231
275
|
});
|
|
232
276
|
}
|
|
233
277
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chrysb/alphaclaw",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.13",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -19,14 +19,11 @@
|
|
|
19
19
|
},
|
|
20
20
|
"files": [
|
|
21
21
|
"bin/",
|
|
22
|
-
"lib/"
|
|
23
|
-
"patches/",
|
|
24
|
-
"scripts/apply-openclaw-patches.js"
|
|
22
|
+
"lib/"
|
|
25
23
|
],
|
|
26
24
|
"scripts": {
|
|
27
25
|
"start": "node bin/alphaclaw.js start",
|
|
28
26
|
"build:ui": "node scripts/build-ui.mjs",
|
|
29
|
-
"postinstall": "node ./scripts/apply-openclaw-patches.js",
|
|
30
27
|
"test": "vitest run",
|
|
31
28
|
"test:watch": "vitest",
|
|
32
29
|
"test:watchdog": "vitest run tests/server/watchdog.test.js tests/server/watchdog-db.test.js tests/server/routes-watchdog.test.js",
|
|
@@ -36,8 +33,7 @@
|
|
|
36
33
|
"dependencies": {
|
|
37
34
|
"express": "^4.21.0",
|
|
38
35
|
"http-proxy": "^1.18.1",
|
|
39
|
-
"openclaw": "2026.
|
|
40
|
-
"patch-package": "^8.0.1",
|
|
36
|
+
"openclaw": "2026.5.2",
|
|
41
37
|
"ws": "^8.19.0"
|
|
42
38
|
},
|
|
43
39
|
"devDependencies": {
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
diff --git a/node_modules/openclaw/dist/plugin-sdk/src/config/zod-schema.d.ts b/node_modules/openclaw/dist/plugin-sdk/src/config/zod-schema.d.ts
|
|
2
|
-
index 8964b19..2285c33 100644
|
|
3
|
-
--- a/node_modules/openclaw/dist/plugin-sdk/src/config/zod-schema.d.ts
|
|
4
|
-
+++ b/node_modules/openclaw/dist/plugin-sdk/src/config/zod-schema.d.ts
|
|
5
|
-
@@ -4171,6 +4171,7 @@ export declare const OpenClawSchema: z.ZodObject<{
|
|
6
|
-
enabled: z.ZodOptional<z.ZodBoolean>;
|
|
7
|
-
hooks: z.ZodOptional<z.ZodObject<{
|
|
8
|
-
allowPromptInjection: z.ZodOptional<z.ZodBoolean>;
|
|
9
|
-
+ allowConversationAccess: z.ZodOptional<z.ZodBoolean>;
|
|
10
|
-
}, z.core.$strict>>;
|
|
11
|
-
subagent: z.ZodOptional<z.ZodObject<{
|
|
12
|
-
allowModelOverride: z.ZodOptional<z.ZodBoolean>;
|
|
13
|
-
diff --git a/node_modules/openclaw/dist/runtime-schema-Dgzy-2rz.js b/node_modules/openclaw/dist/runtime-schema-Dgzy-2rz.js
|
|
14
|
-
index eaaaab6..9847a80 100644
|
|
15
|
-
--- a/node_modules/openclaw/dist/runtime-schema-Dgzy-2rz.js
|
|
16
|
-
+++ b/node_modules/openclaw/dist/runtime-schema-Dgzy-2rz.js
|
|
17
|
-
@@ -19939,5 +19939,12 @@ const GENERATED_BASE_CONFIG_SCHEMA = {
|
|
18
|
-
- properties: { allowPromptInjection: {
|
|
19
|
-
- type: "boolean",
|
|
20
|
-
- title: "Allow Prompt Injection Hooks",
|
|
21
|
-
- description: "Controls whether this plugin may mutate prompts through typed hooks. Set false to block `before_prompt_build` and ignore prompt-mutating fields from legacy `before_agent_start`, while preserving legacy `modelOverride` and `providerOverride` behavior."
|
|
22
|
-
- } },
|
|
23
|
-
+ properties: {
|
|
24
|
-
+ allowPromptInjection: {
|
|
25
|
-
+ type: "boolean",
|
|
26
|
-
+ title: "Allow Prompt Injection Hooks",
|
|
27
|
-
+ description: "Controls whether this plugin may mutate prompts through typed hooks. Set false to block `before_prompt_build` and ignore prompt-mutating fields from legacy `before_agent_start`, while preserving legacy `modelOverride` and `providerOverride` behavior."
|
|
28
|
-
+ },
|
|
29
|
-
+ allowConversationAccess: {
|
|
30
|
-
+ type: "boolean",
|
|
31
|
-
+ title: "Allow Conversation Access Hooks",
|
|
32
|
-
+ description: "Explicitly allows a non-bundled plugin to receive conversation content in typed hooks. Keep false unless the plugin is trusted to inspect conversation data."
|
|
33
|
-
+ }
|
|
34
|
-
+ },
|
|
35
|
-
@@ -24760,0 +24761,5 @@ const GENERATED_BASE_CONFIG_SCHEMA = {
|
|
36
|
-
+ "plugins.entries.*.hooks.allowConversationAccess": {
|
|
37
|
-
+ label: "Allow Conversation Access Hooks",
|
|
38
|
-
+ help: "Explicitly allows a non-bundled plugin to receive conversation content in typed hooks. Keep false unless the plugin is trusted to inspect conversation data.",
|
|
39
|
-
+ tags: ["access"]
|
|
40
|
-
+ },
|
|
41
|
-
diff --git a/node_modules/openclaw/dist/server.impl-DhtU4okW.js b/node_modules/openclaw/dist/server.impl-DhtU4okW.js
|
|
42
|
-
index 93890d3..7b3c701 100644
|
|
43
|
-
--- a/node_modules/openclaw/dist/server.impl-DhtU4okW.js
|
|
44
|
-
+++ b/node_modules/openclaw/dist/server.impl-DhtU4okW.js
|
|
45
|
-
@@ -11165,7 +11165,7 @@ function attachGatewayWsMessageHandler(params) {
|
|
46
|
-
close(1008, truncateCloseReason(authMessage));
|
|
47
|
-
};
|
|
48
|
-
const clearUnboundScopes = () => {
|
|
49
|
-
- if (scopes.length > 0) {
|
|
50
|
-
+ if (scopes.length > 0 && !sharedAuthOk) {
|
|
51
|
-
scopes = [];
|
|
52
|
-
connectParams.scopes = scopes;
|
|
53
|
-
}
|
|
54
|
-
diff --git a/node_modules/openclaw/dist/zod-schema-BhKK4qYw.js b/node_modules/openclaw/dist/zod-schema-BhKK4qYw.js
|
|
55
|
-
index 1dc871e..6803778 100644
|
|
56
|
-
--- a/node_modules/openclaw/dist/zod-schema-BhKK4qYw.js
|
|
57
|
-
+++ b/node_modules/openclaw/dist/zod-schema-BhKK4qYw.js
|
|
58
|
-
@@ -775 +775,4 @@ const PluginEntrySchema = z.object({
|
|
59
|
-
- hooks: z.object({ allowPromptInjection: z.boolean().optional() }).strict().optional(),
|
|
60
|
-
+ hooks: z.object({
|
|
61
|
-
+ allowPromptInjection: z.boolean().optional(),
|
|
62
|
-
+ allowConversationAccess: z.boolean().optional()
|
|
63
|
-
+ }).strict().optional(),
|
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* patch-package resolves paths relative to the npm/yarn project root (where the
|
|
3
|
-
* lockfile lives). When this package's postinstall runs, process.cwd() is often
|
|
4
|
-
* this package directory, so a plain `patch-package` call treats that as the
|
|
5
|
-
* app root and looks for ./node_modules/openclaw under it — but openclaw is
|
|
6
|
-
* usually hoisted to the consumer's top-level node_modules.
|
|
7
|
-
*
|
|
8
|
-
* This script finds the real install root (directory containing a lockfile) and
|
|
9
|
-
* runs patch-package there with --patch-dir pointing at our bundled patches/.
|
|
10
|
-
*/
|
|
11
|
-
const { spawnSync } = require("child_process");
|
|
12
|
-
const fs = require("fs");
|
|
13
|
-
const path = require("path");
|
|
14
|
-
|
|
15
|
-
const kAlphaclawRoot = path.join(__dirname, "..");
|
|
16
|
-
|
|
17
|
-
const findProjectRootFromOpenclawDir = (openclawDir) => {
|
|
18
|
-
let dir = path.resolve(openclawDir);
|
|
19
|
-
for (let i = 0; i < 30; i += 1) {
|
|
20
|
-
if (
|
|
21
|
-
fs.existsSync(path.join(dir, "package-lock.json")) ||
|
|
22
|
-
fs.existsSync(path.join(dir, "yarn.lock")) ||
|
|
23
|
-
fs.existsSync(path.join(dir, "pnpm-lock.yaml"))
|
|
24
|
-
) {
|
|
25
|
-
return dir;
|
|
26
|
-
}
|
|
27
|
-
const parent = path.dirname(dir);
|
|
28
|
-
if (parent === dir) break;
|
|
29
|
-
dir = parent;
|
|
30
|
-
}
|
|
31
|
-
return path.dirname(path.dirname(openclawDir));
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
const main = () => {
|
|
35
|
-
const patchesDir = path.join(kAlphaclawRoot, "patches");
|
|
36
|
-
if (!fs.existsSync(patchesDir)) {
|
|
37
|
-
return;
|
|
38
|
-
}
|
|
39
|
-
const hasPatch = fs
|
|
40
|
-
.readdirSync(patchesDir)
|
|
41
|
-
.some((name) => name.endsWith(".patch"));
|
|
42
|
-
if (!hasPatch) {
|
|
43
|
-
return;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
let openclawMainPath;
|
|
47
|
-
try {
|
|
48
|
-
openclawMainPath = require.resolve("openclaw", { paths: [kAlphaclawRoot] });
|
|
49
|
-
} catch {
|
|
50
|
-
return;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
const openclawDir = (() => {
|
|
54
|
-
let dir = path.dirname(openclawMainPath);
|
|
55
|
-
for (let i = 0; i < 8; i += 1) {
|
|
56
|
-
const pkgPath = path.join(dir, "package.json");
|
|
57
|
-
if (fs.existsSync(pkgPath)) {
|
|
58
|
-
try {
|
|
59
|
-
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
|
|
60
|
-
if (pkg.name === "openclaw") return dir;
|
|
61
|
-
} catch {
|
|
62
|
-
/* continue */
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
const parent = path.dirname(dir);
|
|
66
|
-
if (parent === dir) break;
|
|
67
|
-
dir = parent;
|
|
68
|
-
}
|
|
69
|
-
return path.dirname(path.dirname(openclawMainPath));
|
|
70
|
-
})();
|
|
71
|
-
const projectRoot = findProjectRootFromOpenclawDir(openclawDir);
|
|
72
|
-
|
|
73
|
-
let relPatchDir = path.relative(projectRoot, patchesDir);
|
|
74
|
-
if (relPatchDir.startsWith("..") || path.isAbsolute(relPatchDir)) {
|
|
75
|
-
console.error(
|
|
76
|
-
"[@chrysb/alphaclaw] patch-package: could not resolve patch dir relative to project root",
|
|
77
|
-
);
|
|
78
|
-
process.exit(1);
|
|
79
|
-
}
|
|
80
|
-
relPatchDir = relPatchDir.split(path.sep).join("/");
|
|
81
|
-
|
|
82
|
-
const patchPackageMain = require.resolve("patch-package/dist/index.js", {
|
|
83
|
-
paths: [kAlphaclawRoot],
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
const result = spawnSync(
|
|
87
|
-
process.execPath,
|
|
88
|
-
[patchPackageMain, "--patch-dir", relPatchDir],
|
|
89
|
-
{ cwd: projectRoot, stdio: "inherit", env: process.env },
|
|
90
|
-
);
|
|
91
|
-
if (result.error) {
|
|
92
|
-
throw result.error;
|
|
93
|
-
}
|
|
94
|
-
if (result.status !== 0 && result.status !== null) {
|
|
95
|
-
process.exit(result.status);
|
|
96
|
-
}
|
|
97
|
-
};
|
|
98
|
-
|
|
99
|
-
main();
|