@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.
@@ -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 kNodeRouteCliTimeoutMs = 12000;
16
- const kNodesStatusCliTimeoutMs = 5000;
17
- const kNodesPendingCliTimeoutMs = 5000;
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: kNodesStatusCliTimeoutMs,
201
+ timeoutMs: cliTimeouts.status,
166
202
  });
167
203
  if (!statusResult.ok) {
168
204
  return res.status(500).json({
169
205
  ok: false,
170
- error: statusResult.stderr || "Could not load nodes status",
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: kNodesPendingCliTimeoutMs,
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: kNodeRouteCliTimeoutMs,
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.stderr ||
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.11",
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.4.23",
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();