@chrysb/alphaclaw 0.9.29 → 0.9.30

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.
@@ -0,0 +1,22 @@
1
+ const ensurePluginsShell = (cfg = {}) => {
2
+ if (!cfg.plugins || typeof cfg.plugins !== "object") cfg.plugins = {};
3
+ if (!Array.isArray(cfg.plugins.allow)) cfg.plugins.allow = [];
4
+ if (!cfg.plugins.load || typeof cfg.plugins.load !== "object") {
5
+ cfg.plugins.load = {};
6
+ }
7
+ if (!Array.isArray(cfg.plugins.load.paths)) cfg.plugins.load.paths = [];
8
+ if (!cfg.plugins.entries || typeof cfg.plugins.entries !== "object") {
9
+ cfg.plugins.entries = {};
10
+ }
11
+ };
12
+
13
+ const ensurePluginAllowed = ({ cfg = {}, pluginKey = "" }) => {
14
+ const normalizedPluginKey = String(pluginKey || "").trim();
15
+ if (!normalizedPluginKey) return;
16
+ ensurePluginsShell(cfg);
17
+ if (!cfg.plugins.allow.includes(normalizedPluginKey)) {
18
+ cfg.plugins.allow.push(normalizedPluginKey);
19
+ }
20
+ };
21
+
22
+ module.exports = { ensurePluginsShell, ensurePluginAllowed };
@@ -197,8 +197,12 @@ const registerModelRoutes = ({
197
197
  typeof cfg.agents?.defaults?.thinkingDefault === "string"
198
198
  ? cfg.agents.defaults.thinkingDefault.trim()
199
199
  : null;
200
+ const agentRuntime = String(
201
+ cfg.agents?.defaults?.models?.[modelKey]?.agentRuntime?.id || "",
202
+ ).trim();
200
203
  const { levels, modelDefault } = await resolveThinkingOptionsForModel({
201
204
  modelKey,
205
+ agentRuntime,
202
206
  });
203
207
  const inheritedDefault = globalThinkingDefault || modelDefault || "off";
204
208
  return res.json({
@@ -3,6 +3,8 @@ const { readOpenclawConfig, writeOpenclawConfig } = require("./openclaw-config")
3
3
  const {
4
4
  migrateLegacyTelegramStreamingConfig,
5
5
  } = require("./openclaw-config-migrations");
6
+ const { ensureCodexRuntimePlugin } = require("./codex-runtime-config");
7
+ const { ensurePluginsShell, ensurePluginAllowed } = require("./plugin-config");
6
8
 
7
9
  const kUsageTrackerPluginPath = path.resolve(
8
10
  __dirname,
@@ -14,27 +16,6 @@ const kConversationAccessHookPolicyKey = "allowConversationAccess";
14
16
  const kChannelPluginIds = ["telegram", "discord", "slack", "whatsapp"];
15
17
  const kDefaultDiscordGroupPolicy = "disabled";
16
18
 
17
- const ensurePluginsShell = (cfg = {}) => {
18
- if (!cfg.plugins || typeof cfg.plugins !== "object") cfg.plugins = {};
19
- if (!Array.isArray(cfg.plugins.allow)) cfg.plugins.allow = [];
20
- if (!cfg.plugins.load || typeof cfg.plugins.load !== "object") {
21
- cfg.plugins.load = {};
22
- }
23
- if (!Array.isArray(cfg.plugins.load.paths)) cfg.plugins.load.paths = [];
24
- if (!cfg.plugins.entries || typeof cfg.plugins.entries !== "object") {
25
- cfg.plugins.entries = {};
26
- }
27
- };
28
-
29
- const ensurePluginAllowed = ({ cfg = {}, pluginKey = "" }) => {
30
- const normalizedPluginKey = String(pluginKey || "").trim();
31
- if (!normalizedPluginKey) return;
32
- ensurePluginsShell(cfg);
33
- if (!cfg.plugins.allow.includes(normalizedPluginKey)) {
34
- cfg.plugins.allow.push(normalizedPluginKey);
35
- }
36
- };
37
-
38
19
  const buildUsageTrackerHookPolicy = ({ existingHooks = {} } = {}) => {
39
20
  const hooks = {};
40
21
  if (typeof existingHooks.allowPromptInjection === "boolean") {
@@ -115,6 +96,7 @@ const reconcileEnabledChannelPlugins = (cfg = {}) => {
115
96
 
116
97
  const reconcileManagedPluginConfig = (cfg = {}) => {
117
98
  let changed = ensureUsageTrackerPluginEntry(cfg);
99
+ if (ensureCodexRuntimePlugin(cfg)) changed = true;
118
100
  if (reconcileEnabledChannelPlugins(cfg)) changed = true;
119
101
  if (reconcileDiscordGroupPolicy(cfg)) changed = true;
120
102
  return changed;
@@ -63,6 +63,7 @@ const createWatchdog = ({
63
63
  pendingRecoveryNoticeSource: "",
64
64
  awaitingAutoRepairRecovery: false,
65
65
  startupConsecutiveHealthFailures: 0,
66
+ configurationErrorActive: false,
66
67
  };
67
68
  let healthTimer = null;
68
69
  let bootstrapHealthTimer = null;
@@ -90,6 +91,7 @@ const createWatchdog = ({
90
91
 
91
92
  const scheduleDegradedHealthCheck = () => {
92
93
  if (degradedHealthTimer) return;
94
+ if (state.configurationErrorActive) return;
93
95
  if (state.health !== "degraded" || state.lifecycle !== "running") return;
94
96
  degradedHealthTimer = setTimeout(async () => {
95
97
  degradedHealthTimer = null;
@@ -380,6 +382,9 @@ const createWatchdog = ({
380
382
  };
381
383
 
382
384
  const runRepair = async ({ source, correlationId, force = false }) => {
385
+ if (state.configurationErrorActive && !force) {
386
+ return { ok: false, skipped: true, reason: "configuration_error" };
387
+ }
383
388
  if (!force && !state.autoRepair) {
384
389
  return { ok: false, skipped: true, reason: "auto_repair_disabled" };
385
390
  }
@@ -389,10 +394,16 @@ const createWatchdog = ({
389
394
  if (state.operationInProgress) {
390
395
  return { ok: false, skipped: true, reason: "operation_in_progress" };
391
396
  }
397
+ if (force) {
398
+ state.configurationErrorActive = false;
399
+ }
392
400
 
393
401
  state.operationInProgress = true;
394
402
  try {
395
403
  const result = await clawCmd("doctor --fix --yes", { quiet: true });
404
+ if (state.configurationErrorActive && !force) {
405
+ return { ok: false, skipped: true, reason: "configuration_error" };
406
+ }
396
407
  const ok = !!result?.ok;
397
408
  logEvent("repair", source, ok ? "ok" : "failed", result, correlationId);
398
409
  if (ok) {
@@ -484,6 +495,7 @@ const createWatchdog = ({
484
495
  source = "health_timer",
485
496
  allowAutoRepair = true,
486
497
  } = {}) => {
498
+ if (state.configurationErrorActive) return false;
487
499
  if (
488
500
  state.expectedRestartInProgress &&
489
501
  Date.now() >= state.expectedRestartUntilMs
@@ -495,6 +507,9 @@ const createWatchdog = ({
495
507
  const correlationId = createCorrelationId();
496
508
  state.lastHealthCheckAt = new Date().toISOString();
497
509
  const parsed = await probeGatewayHealth();
510
+ // The gateway may exit with EX_CONFIG while a probe is in flight. Keep the
511
+ // latched configuration-error state from being overwritten by that result.
512
+ if (state.configurationErrorActive) return false;
498
513
  const staleAfterRestart =
499
514
  gatewayStartedAtAtStart != null &&
500
515
  state.gatewayStartedAt != null &&
@@ -727,6 +742,33 @@ const createWatchdog = ({
727
742
  return;
728
743
  }
729
744
 
745
+ if (code === 78) {
746
+ state.configurationErrorActive = true;
747
+ state.lifecycle = "configuration_error";
748
+ state.health = "unhealthy";
749
+ state.uptimeStartedAt = null;
750
+ state.crashRecoveryActive = false;
751
+ state.startupConsecutiveHealthFailures = 0;
752
+ logEvent(
753
+ "config_error",
754
+ "exit_event",
755
+ "failed",
756
+ { code, signal: signal ?? null, stderrTail },
757
+ correlationId,
758
+ );
759
+ void notifyOncePerIncident(
760
+ "gateway_config_error",
761
+ [
762
+ "🐺 *AlphaClaw Watchdog*",
763
+ withViewLogsSuffix("🔴 Gateway configuration invalid"),
764
+ "OpenClaw stopped with `EX_CONFIG`; automatic restart is paused.",
765
+ ].join("\n"),
766
+ correlationId,
767
+ "config_error",
768
+ );
769
+ return;
770
+ }
771
+
730
772
  state.lifecycle = "crashed";
731
773
  state.health = "unhealthy";
732
774
  state.uptimeStartedAt = null;
@@ -787,6 +829,7 @@ const createWatchdog = ({
787
829
 
788
830
  const onGatewayLaunch = ({ startedAt = Date.now(), pid = null } = {}) => {
789
831
  clearDegradedHealthCheckTimer();
832
+ state.configurationErrorActive = false;
790
833
  state.lifecycle = "running";
791
834
  state.health = "unknown";
792
835
  state.startupConsecutiveHealthFailures = 0;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chrysb/alphaclaw",
3
- "version": "0.9.29",
3
+ "version": "0.9.30",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -33,7 +33,7 @@
33
33
  "dependencies": {
34
34
  "express": "^4.21.0",
35
35
  "http-proxy": "^1.18.1",
36
- "openclaw": "2026.6.11",
36
+ "openclaw": "2026.7.1",
37
37
  "ws": "^8.19.0"
38
38
  },
39
39
  "devDependencies": {
@@ -51,6 +51,6 @@
51
51
  "wouter-preact": "^3.7.1"
52
52
  },
53
53
  "engines": {
54
- "node": ">=22.19.0"
54
+ "node": ">=22.22.3 <23 || >=24.15.0 <25 || >=25.9.0"
55
55
  }
56
56
  }