@wipcomputer/wip-ldm-os 0.4.73-alpha.31 → 0.4.73-alpha.33
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/deploy.mjs +81 -3
- package/package.json +1 -1
package/lib/deploy.mjs
CHANGED
|
@@ -558,6 +558,55 @@ function updateToolsAllow(pluginName) {
|
|
|
558
558
|
}
|
|
559
559
|
}
|
|
560
560
|
|
|
561
|
+
/**
|
|
562
|
+
* Reconcile tools.allow against plugins.entries in ~/.openclaw/openclaw.json.
|
|
563
|
+
*
|
|
564
|
+
* In OpenClaw 2026.4.8+, any plugin registered in plugins.entries but missing
|
|
565
|
+
* from tools.allow is silently blocked at runtime. Each blocked tool call
|
|
566
|
+
* spawns a root-key approval prompt to the user, flooding iMessage with
|
|
567
|
+
* approve-ids. This was observed on 2026-04-11 for model-provider plugins
|
|
568
|
+
* (anthropic, openai, xai) and imessage, which were enabled in plugins.entries
|
|
569
|
+
* but never added to tools.allow, because the per-plugin updateToolsAllow path
|
|
570
|
+
* only runs during new plugin deploys and the alpha.27/28 ReferenceError had
|
|
571
|
+
* silently dropped those entries anyway.
|
|
572
|
+
*
|
|
573
|
+
* This function is the self-healing step: at install time, walk plugins.entries,
|
|
574
|
+
* find any enabled plugin whose name is not already in tools.allow, and add it.
|
|
575
|
+
* Idempotent. Disabled plugins are skipped. Runs at both ends of installFromPath
|
|
576
|
+
* so a single `ldm install` repairs existing broken state without requiring a
|
|
577
|
+
* new plugin deploy.
|
|
578
|
+
*
|
|
579
|
+
* Background:
|
|
580
|
+
* ai/product/bugs/code-fka-devopstoolkit/2026-04-11--cc-mini--update-tools-allow-reference-error.md
|
|
581
|
+
*
|
|
582
|
+
* This function MUST remain at module top level, same as updateToolsAllow.
|
|
583
|
+
*/
|
|
584
|
+
function reconcileToolsAllow() {
|
|
585
|
+
const ocConfigPath = join(OC_ROOT, 'openclaw.json');
|
|
586
|
+
if (!existsSync(ocConfigPath)) return;
|
|
587
|
+
try {
|
|
588
|
+
const raw = readFileSync(ocConfigPath, 'utf8');
|
|
589
|
+
const config = JSON.parse(raw);
|
|
590
|
+
if (!config.plugins?.entries || typeof config.plugins.entries !== 'object') return;
|
|
591
|
+
if (!config.tools?.allow || !Array.isArray(config.tools.allow)) return;
|
|
592
|
+
|
|
593
|
+
const enabledPlugins = Object.entries(config.plugins.entries)
|
|
594
|
+
.filter(([, entry]) => entry && entry.enabled !== false)
|
|
595
|
+
.map(([name]) => name);
|
|
596
|
+
|
|
597
|
+
const allow = config.tools.allow;
|
|
598
|
+
const missing = enabledPlugins.filter(name => !allow.includes(name));
|
|
599
|
+
|
|
600
|
+
if (missing.length === 0) return;
|
|
601
|
+
|
|
602
|
+
for (const name of missing) allow.push(name);
|
|
603
|
+
writeFileSync(ocConfigPath, JSON.stringify(config, null, 2) + '\n');
|
|
604
|
+
log(`Reconciled openclaw.json tools.allow: added ${missing.join(', ')}`);
|
|
605
|
+
} catch (e) {
|
|
606
|
+
log(`Warning: failed to reconcile tools.allow: ${e.message}`);
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
|
|
561
610
|
// ── OpenClaw plugin naming (fix #8) ──
|
|
562
611
|
|
|
563
612
|
function resolveOcPluginName(repoPath, toolName) {
|
|
@@ -818,7 +867,6 @@ function registerMCP(repoPath, door, toolName) {
|
|
|
818
867
|
const envFlag = existsSync(OC_ROOT) ? ` -e OPENCLAW_HOME="${OC_ROOT}"` : '';
|
|
819
868
|
execSync(`claude mcp add --scope user ${name}${envFlag} -- node "${mcpPath}"`, { stdio: 'pipe' });
|
|
820
869
|
ok(`MCP: registered ${name} at user scope`);
|
|
821
|
-
return true;
|
|
822
870
|
} catch (e) {
|
|
823
871
|
// Fallback: write to ~/.claude.json directly
|
|
824
872
|
try {
|
|
@@ -830,12 +878,29 @@ function registerMCP(repoPath, door, toolName) {
|
|
|
830
878
|
};
|
|
831
879
|
writeJSON(ccUserPath, mcpConfig);
|
|
832
880
|
ok(`MCP: registered ${name} in ~/.claude.json (fallback)`);
|
|
833
|
-
return true;
|
|
834
881
|
} catch (e2) {
|
|
835
882
|
fail(`MCP: registration failed. ${e.message}`);
|
|
836
883
|
return false;
|
|
837
884
|
}
|
|
838
885
|
}
|
|
886
|
+
|
|
887
|
+
// Also register with OpenClaw so the MCP tools are available to all
|
|
888
|
+
// OpenClaw agents (e.g. Lēsa) without exec-approval gates. CC
|
|
889
|
+
// registration alone only gives tools to Claude Code sessions, not
|
|
890
|
+
// to OpenClaw's agent pipeline. Discovered 2026-04-11 when Lēsa
|
|
891
|
+
// lost xAI image gen tools after switching from Grok to Claude CLI.
|
|
892
|
+
try {
|
|
893
|
+
const ocMcpConfig = JSON.stringify({ command: 'node', args: [mcpPath] });
|
|
894
|
+
execSync(`openclaw mcp set ${name} '${ocMcpConfig}'`, { stdio: 'pipe' });
|
|
895
|
+
ok(`MCP: registered ${name} with OpenClaw`);
|
|
896
|
+
} catch {
|
|
897
|
+
// Non-fatal: OpenClaw may not be installed on all machines
|
|
898
|
+
}
|
|
899
|
+
|
|
900
|
+
// Add to OpenClaw tools.allow so the MCP tools are pre-authorized
|
|
901
|
+
updateToolsAllow(name);
|
|
902
|
+
|
|
903
|
+
return true;
|
|
839
904
|
}
|
|
840
905
|
|
|
841
906
|
/**
|
|
@@ -1199,10 +1264,19 @@ export function installToolbox(repoPath) {
|
|
|
1199
1264
|
// ── Full install pipeline ──
|
|
1200
1265
|
|
|
1201
1266
|
export async function installFromPath(repoPath) {
|
|
1267
|
+
// Heal tools.allow before any install runs, so the current session picks up
|
|
1268
|
+
// any drift left by earlier broken installs (alpha.27/28 ReferenceError).
|
|
1269
|
+
// Idempotent: no-op if plugins.entries and tools.allow are already in sync.
|
|
1270
|
+
reconcileToolsAllow();
|
|
1271
|
+
|
|
1202
1272
|
const subTools = detectToolbox(repoPath);
|
|
1203
1273
|
|
|
1204
1274
|
if (subTools.length > 0) {
|
|
1205
|
-
|
|
1275
|
+
const result = installToolbox(repoPath);
|
|
1276
|
+
// Heal again after toolbox install in case any plugin was newly registered
|
|
1277
|
+
// in plugins.entries but never added to tools.allow by its deploy path.
|
|
1278
|
+
reconcileToolsAllow();
|
|
1279
|
+
return result;
|
|
1206
1280
|
}
|
|
1207
1281
|
|
|
1208
1282
|
const installed = installSingleTool(repoPath);
|
|
@@ -1219,6 +1293,10 @@ export async function installFromPath(repoPath) {
|
|
|
1219
1293
|
console.log('');
|
|
1220
1294
|
}
|
|
1221
1295
|
|
|
1296
|
+
// Final reconcile pass after single-tool install, for the same reason as
|
|
1297
|
+
// the toolbox branch above.
|
|
1298
|
+
reconcileToolsAllow();
|
|
1299
|
+
|
|
1222
1300
|
return { tools: 1, interfaces: installed };
|
|
1223
1301
|
}
|
|
1224
1302
|
|