diff --git a/Dockerfile b/Dockerfile index c08a98241ba..42d5985359f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -392,11 +392,14 @@ ENV NPM_CONFIG_OFFLINE=true \ NPM_CONFIG_FUND=false # Install NemoClaw plugin into OpenClaw (local /opt/nemoclaw, no network). +# Re-apply WeChat account seeding after OpenClaw doctor/plugin-install touches +# openclaw.json; the seed script no-ops unless WeChat is actively configured. # Prune non-runtime metadata from staged bundled plugin dependencies before # this layer is committed; deleting it in a later layer would not reduce the # OCI image imported by k3s. # hadolint ignore=DL3059,DL4006 RUN (openclaw plugins install /opt/nemoclaw > /dev/null 2>&1 || true) \ + && python3 /usr/local/lib/nemoclaw/seed-wechat-accounts.py \ && if [ -d /sandbox/.openclaw/plugin-runtime-deps ]; then \ find /sandbox/.openclaw/plugin-runtime-deps -type f \( \ -name '*.d.ts' -o -name '*.d.mts' -o -name '*.d.cts' -o \ diff --git a/scripts/seed-wechat-accounts.py b/scripts/seed-wechat-accounts.py index eff6c49742c..5c4935c2e4f 100755 --- a/scripts/seed-wechat-accounts.py +++ b/scripts/seed-wechat-accounts.py @@ -19,8 +19,9 @@ # is registered. Without channels.openclaw-weixin.accounts..enabled=true # in openclaw.json, the plugin's auth/accounts.ts considers the account # disabled and the bridge won't start, even if the per-account state files -# above exist. generate-openclaw-config.py invokes this only after -# plugins.installs.openclaw-weixin has been preserved from the base image. +# above exist. The patch also restores the openclaw-weixin plugin registry +# entry because later OpenClaw config rewrites can drop it while leaving the +# pre-installed extension files in place. # # State dir resolution mirrors the upstream's resolveStateDir(): # $OPENCLAW_STATE_DIR || $CLAWDBOT_STATE_DIR || ~/.openclaw @@ -53,6 +54,12 @@ import sys +WECHAT_PLUGIN_ID = "openclaw-weixin" +WECHAT_PLUGIN_SPEC = "@tencent-weixin/openclaw-weixin@2.4.2" +WECHAT_PLUGIN_INSTALL = { + "source": "npm", + "spec": WECHAT_PLUGIN_SPEC, +} WECHAT_TOKEN_PLACEHOLDER = "openshell:resolve:env:WECHAT_BOT_TOKEN" @@ -141,6 +148,31 @@ def _patch_openclaw_config(account_id: str) -> None: ) return + plugins = cfg.setdefault("plugins", {}) + if not isinstance(plugins, dict): + plugins = {} + cfg["plugins"] = plugins + installs = plugins.setdefault("installs", {}) + if not isinstance(installs, dict): + installs = {} + plugins["installs"] = installs + wechat_install = installs.get(WECHAT_PLUGIN_ID) + if ( + not isinstance(wechat_install, dict) + or wechat_install.get("source") != WECHAT_PLUGIN_INSTALL["source"] + or not wechat_install.get("spec") + ): + installs[WECHAT_PLUGIN_ID] = dict(WECHAT_PLUGIN_INSTALL) + entries = plugins.setdefault("entries", {}) + if not isinstance(entries, dict): + entries = {} + plugins["entries"] = entries + wechat_entry = entries.setdefault(WECHAT_PLUGIN_ID, {}) + if not isinstance(wechat_entry, dict): + wechat_entry = {} + entries[WECHAT_PLUGIN_ID] = wechat_entry + wechat_entry["enabled"] = True + channels = cfg.setdefault("channels", {}) weixin = channels.setdefault("openclaw-weixin", {}) weixin["channelConfigUpdatedAt"] = _js_iso_utc()