@openclaw-cloud/agent-controller 3.1.3 → 3.2.0

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,201 @@
1
+ /**
2
+ * Plugin reconciliation — agent-controller is the SINGLE OWNER of "the plugins
3
+ * openclaw.json declares are actually installed on disk".
4
+ *
5
+ * Background (incident 2026-08-03): the EC2 user-data used to install
6
+ * `@openclaw-cloud/mcp-warmup` itself with
7
+ * su - ubuntu -c "openclaw plugins install ...@latest --force" || echo "…non-fatal"
8
+ * On a whole cohort of VMs that step died with `openclaw: command not found`
9
+ * (the login shell has no npm-global bin on PATH that early in first boot) and
10
+ * the `|| echo` swallowed it. The agents then ran for months with
11
+ * `plugins.allow=["@openclaw-cloud/mcp-warmup"]` in openclaw.json and no
12
+ * package on disk — openclaw logged "stale config entry ignored", no MCP warmup
13
+ * session ever started, and board tasks were undeliverable. Nothing noticed.
14
+ *
15
+ * So: the declared set lives in openclaw.json (written by the backend
16
+ * bootstrap), and this module makes the disk match it — at `agent-controller
17
+ * bootstrap` and again on every controller start, which is what turns a reboot
18
+ * into a self-heal instead of a permanent silent failure.
19
+ *
20
+ * SCOPE — missing-entirely only. A plugin that is installed at the "wrong"
21
+ * version is NOT touched here: version upgrades remain self-update's job
22
+ * (`runExplicitSelfUpdate` / the `agent_update` + `plugin_update` handlers,
23
+ * driven by backend targets). Reconcile answers one question — "is it there at
24
+ * all?" — so it can stay cheap enough to run on every boot.
25
+ */
26
+ import fs from 'node:fs/promises';
27
+ import { getOpenclawJsonPath } from './apply-config.js';
28
+ import { listInstalledPlugins } from './openclaw-ops.js';
29
+ import { runOpenclawStackUpdate } from './openclaw-stack-update.js';
30
+ import { isSafePackageName } from './package-install.js';
31
+ import { getReleaseChannel } from './release-channel.js';
32
+ // The runtime-targets fetch has one implementation, in the self-update CLI —
33
+ // reused rather than re-spelled so reconcile resolves plugin versions exactly
34
+ // the way self-update does.
35
+ import { fetchRuntimeTargets } from '../commands/self-update.js';
36
+ import { logCollector } from '../connection.js';
37
+ import { toErrorMessage } from './response.js';
38
+ const LOG_PREFIX = '[plugin-reconcile]';
39
+ /**
40
+ * The plugin ids openclaw.json says must be present.
41
+ *
42
+ * `plugins.allow` is the primary source: the backend's config generator writes
43
+ * exactly the external npm plugins it expects installed (today
44
+ * `['@openclaw-cloud/mcp-warmup']`).
45
+ *
46
+ * `plugins.entries` is also consulted, but ONLY for scoped ids (`@scope/name`).
47
+ * That block additionally holds openclaw's BUNDLED plugins — `telegram`,
48
+ * `discord`, `slack`, `whatsapp` — which ship inside the runtime and are not
49
+ * npm-installable; handing those to `openclaw plugins install` would fail on
50
+ * every boot. Bundled ids are bare words, external ones are scoped, so the
51
+ * `@scope/` shape is the discriminator. An entry explicitly `{enabled: false}`
52
+ * is skipped.
53
+ *
54
+ * Everything is finally filtered through `isSafePackageName` — these ids reach
55
+ * a shell via `openclaw plugins install <id>@<version>`.
56
+ */
57
+ export function declaredPluginIds(openclawConfig) {
58
+ const plugins = openclawConfig?.plugins;
59
+ if (!plugins || typeof plugins !== 'object')
60
+ return [];
61
+ const ids = new Set();
62
+ const allow = plugins.allow;
63
+ if (Array.isArray(allow)) {
64
+ for (const id of allow) {
65
+ if (typeof id === 'string' && id.trim())
66
+ ids.add(id.trim());
67
+ }
68
+ }
69
+ const entries = plugins.entries;
70
+ if (entries && typeof entries === 'object' && !Array.isArray(entries)) {
71
+ for (const [rawId, entry] of Object.entries(entries)) {
72
+ const id = rawId.trim();
73
+ if (!id.startsWith('@') || !id.includes('/'))
74
+ continue; // bundled runtime plugin
75
+ const enabled = entry?.enabled;
76
+ if (enabled === false)
77
+ continue;
78
+ ids.add(id);
79
+ }
80
+ }
81
+ return [...ids].filter(isSafePackageName);
82
+ }
83
+ async function readDeclaredPlugins() {
84
+ const raw = await fs.readFile(getOpenclawJsonPath(), 'utf-8').catch(() => null);
85
+ if (raw === null)
86
+ return [];
87
+ try {
88
+ return declaredPluginIds(JSON.parse(raw));
89
+ }
90
+ catch (err) {
91
+ console.warn(`${LOG_PREFIX} openclaw.json is not valid JSON:`, toErrorMessage(err));
92
+ return [];
93
+ }
94
+ }
95
+ /**
96
+ * Version to install a missing plugin at — resolved exactly the way
97
+ * self-update does:
98
+ * 1. the backend's runtime targets for this agent
99
+ * (`GET /api/agent/runtime-targets` → `openclaw.plugins[]`), which is what
100
+ * `runSelfUpdateCli` prefers, then
101
+ * 2. the AC_RELEASE_CHANNEL dist-tag — `beta` on the beta channel, `latest`
102
+ * on stable (the same mapping as `selfUpdate()`), which is also what the
103
+ * old user-data line used.
104
+ */
105
+ async function resolvePluginVersions(ids) {
106
+ const channel = getReleaseChannel();
107
+ const distTag = channel === 'stable' ? 'latest' : channel;
108
+ // Best-effort: fetchRuntimeTargets() already swallows every failure into null.
109
+ const targets = await fetchRuntimeTargets();
110
+ const fromBackend = new Map();
111
+ for (const p of targets?.openclaw?.plugins ?? []) {
112
+ if (p && typeof p.id === 'string' && typeof p.version === 'string' && p.version) {
113
+ fromBackend.set(p.id, p.version);
114
+ }
115
+ }
116
+ return new Map(ids.map((id) => [id, fromBackend.get(id) ?? distTag]));
117
+ }
118
+ /**
119
+ * Install every declared-but-absent plugin. NEVER throws — bootstrap and
120
+ * startup both call it on their happy path and a plugin problem must not take
121
+ * down the boot; the next controller start reconciles again.
122
+ *
123
+ * Cheap when nothing is missing: one `openclaw plugins list --json` (no npm
124
+ * traffic, no backend call). The backend/npm work only happens once something
125
+ * is actually absent.
126
+ *
127
+ * Installs go through `runOpenclawStackUpdate`, the one owner of
128
+ * "install then restart the gateway once if anything changed" — so a plugin
129
+ * installed while the gateway is already running is picked up immediately
130
+ * instead of waiting for the next restart.
131
+ */
132
+ export async function reconcilePlugins(source) {
133
+ const empty = { declared: [], missing: [], installed: [], failed: [] };
134
+ try {
135
+ const declared = await readDeclaredPlugins();
136
+ if (declared.length === 0) {
137
+ console.log(`${LOG_PREFIX} no plugins declared in openclaw.json — nothing to reconcile`);
138
+ return empty;
139
+ }
140
+ // `openclaw plugins list --json` is the source of truth, NOT the
141
+ // `plugins.installs` block of openclaw.json: the incident was precisely a
142
+ // config entry with no package behind it, so a config-derived inventory
143
+ // would report the missing plugin as present.
144
+ let installedIds;
145
+ try {
146
+ installedIds = new Set((await listInstalledPlugins()).map((p) => p.id));
147
+ }
148
+ catch (err) {
149
+ const error = toErrorMessage(err);
150
+ // Loud: without an inventory we cannot tell present from absent, and
151
+ // blind-installing on every boot would hit npm forever.
152
+ console.error(`${LOG_PREFIX} cannot list installed plugins — skipping reconcile: ${error}`);
153
+ logCollector?.push('plugin_reconcile_probe_failed', 'error', `Plugin reconcile could not read the installed plugin list: ${error}`, { source, declared, error });
154
+ return { ...empty, declared, skippedReason: error };
155
+ }
156
+ const missing = declared.filter((id) => !installedIds.has(id));
157
+ if (missing.length === 0) {
158
+ console.log(`${LOG_PREFIX} all ${declared.length} declared plugin(s) present`);
159
+ return { ...empty, declared };
160
+ }
161
+ console.log(`${LOG_PREFIX} missing plugin(s): ${missing.join(', ')} — installing`);
162
+ logCollector?.push('plugin_reconcile_missing', 'warn', `Declared plugin(s) not installed: ${missing.join(', ')}`, { source, declared, missing });
163
+ const versions = await resolvePluginVersions(missing);
164
+ const plugins = missing.map((id) => ({ id, version: versions.get(id) ?? 'latest' }));
165
+ const stack = await runOpenclawStackUpdate({
166
+ plugins,
167
+ eventPrefix: 'plugin_reconcile',
168
+ meta: { source },
169
+ });
170
+ const summary = stack.pluginSummary ?? { installed: [], skipped: [], failed: [] };
171
+ if (summary.installed.length > 0) {
172
+ console.log(`${LOG_PREFIX} installed: ${summary.installed.join(', ')}`);
173
+ logCollector?.push('plugin_reconcile_installed', 'info', `Installed ${summary.installed.length} missing plugin(s): ${summary.installed.join(', ')}`, { source, installed: summary.installed, gatewayRestarted: stack.gatewayRestarted });
174
+ }
175
+ if (stack.restartError) {
176
+ console.error(`${LOG_PREFIX} gateway restart failed: ${stack.restartError}`);
177
+ }
178
+ if (summary.failed.length > 0) {
179
+ // LOUD. A swallowed plugin install is what caused the incident; this is
180
+ // the line an operator greps for, and the backend `agent_log` row an
181
+ // alert can fire on. (In the `bootstrap` CLI process `logCollector` is
182
+ // undefined — no WS connection — so there the console line is all we
183
+ // have; the startup reconcile re-reports it to the backend.)
184
+ const detail = summary.failed.map((f) => `${f.id}: ${f.error}`).join('; ');
185
+ console.error(`${LOG_PREFIX} install FAILED for ${summary.failed.length} plugin(s): ${detail}`);
186
+ logCollector?.push('plugin_reconcile_failed', 'error', `Plugin install failed during reconcile: ${detail}`, { source, failed: summary.failed });
187
+ }
188
+ return { declared, missing, installed: summary.installed, failed: summary.failed };
189
+ }
190
+ catch (err) {
191
+ // Anything unexpected (fs, backend client construction, …). Never fatal.
192
+ const error = toErrorMessage(err);
193
+ console.error(`${LOG_PREFIX} reconcile failed: ${error}`);
194
+ logCollector?.push('plugin_reconcile_failed', 'error', `Plugin reconcile failed: ${error}`, {
195
+ source,
196
+ error,
197
+ });
198
+ return { ...empty, skippedReason: error };
199
+ }
200
+ }
201
+ //# sourceMappingURL=plugin-reconcile.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin-reconcile.js","sourceRoot":"","sources":["../../src/utils/plugin-reconcile.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openclaw-cloud/agent-controller",
3
- "version": "3.1.3",
3
+ "version": "3.2.0",
4
4
  "packageManager": "pnpm@11.5.2",
5
5
  "type": "module",
6
6
  "engines": {