fix: pin OpenClaw Codex plugin

This commit is contained in:
Haitao Pan 2026-06-01 14:53:18 +08:00
parent ba4daa3597
commit 2f2e9d8f9b
4 changed files with 184 additions and 26 deletions

View File

@ -18,15 +18,19 @@ gateway_openclaw_binary_path: "{{ gateway_openclaw_home }}/.local/bin/openclaw"
gateway_openclaw_install_dir: "{{ gateway_openclaw_home }}/.local/lib/node_modules/openclaw"
gateway_openclaw_required_version: "2026.5.28"
gateway_openclaw_npm_package_spec: "openclaw@{{ gateway_openclaw_required_version }}"
gateway_openclaw_extension_dependency_dirs:
- "{{ gateway_openclaw_install_dir }}/dist/extensions/acpx"
gateway_openclaw_global_npm_dir: "{{ gateway_openclaw_home }}/.openclaw/npm"
gateway_openclaw_required_global_plugins:
- name: "@openclaw/codex"
version: "{{ gateway_openclaw_required_version }}"
gateway_openclaw_removed_global_plugins:
- "@openclaw/acpx"
gateway_openclaw_extension_dependency_dirs: []
gateway_openclaw_config_path: "{{ gateway_openclaw_home }}/.openclaw/openclaw.json"
gateway_openclaw_workspace_path: "{{ gateway_openclaw_home }}/.openclaw/workspace"
gateway_openclaw_workspace_mode: "0775"
gateway_openclaw_compile_cache_dir: /var/tmp/openclaw-compile-cache
gateway_openclaw_service_path: "{{ gateway_openclaw_home }}/.nix-profile/bin:{{ gateway_openclaw_home }}/.local/bin:{{ gateway_openclaw_home }}/.npm-global/bin:{{ gateway_openclaw_home }}/bin:/usr/local/bin:/usr/bin:/bin"
gateway_openclaw_extension_backup_dir: "{{ gateway_openclaw_home }}/.openclaw/backups/extensions"
gateway_openclaw_doctor_repair_enabled: true
gateway_openclaw_upstream_host: 127.0.0.1
gateway_openclaw_upstream_port: 18789

View File

@ -90,6 +90,105 @@
- not ansible_check_mode
notify: Restart openclaw gateway
- name: Ensure OpenClaw global plugin npm directory exists
ansible.builtin.file:
path: "{{ gateway_openclaw_global_npm_dir }}"
state: directory
owner: "{{ gateway_openclaw_service_user }}"
group: "{{ gateway_openclaw_service_group }}"
mode: "0700"
- name: Install required OpenClaw global plugin versions
ansible.builtin.command:
cmd: >-
npm install --omit=dev --no-audit --no-fund --save-exact
--prefix "{{ gateway_openclaw_global_npm_dir }}"
{{ item.name }}@{{ item.version }}
environment:
HOME: "{{ gateway_openclaw_home }}"
PATH: "{{ gateway_openclaw_service_path }}"
OPENCLAW_NO_RESPAWN: "1"
NODE_COMPILE_CACHE: "{{ gateway_openclaw_compile_cache_dir }}"
become: true
become_user: "{{ gateway_openclaw_service_user }}"
register: gateway_openclaw_required_global_plugin_installs
changed_when: >-
'added ' in (gateway_openclaw_required_global_plugin_installs.stdout | default('')) or
'removed ' in (gateway_openclaw_required_global_plugin_installs.stdout | default('')) or
'changed ' in (gateway_openclaw_required_global_plugin_installs.stdout | default(''))
loop: "{{ gateway_openclaw_required_global_plugins }}"
loop_control:
label: "{{ item.name }}@{{ item.version }}"
when:
- not ansible_check_mode
notify: Restart openclaw gateway
- name: Remove unsupported OpenClaw global plugin packages
ansible.builtin.command:
cmd: >-
npm uninstall --no-audit --no-fund
--prefix "{{ gateway_openclaw_global_npm_dir }}"
{{ item }}
environment:
HOME: "{{ gateway_openclaw_home }}"
PATH: "{{ gateway_openclaw_service_path }}"
OPENCLAW_NO_RESPAWN: "1"
NODE_COMPILE_CACHE: "{{ gateway_openclaw_compile_cache_dir }}"
become: true
become_user: "{{ gateway_openclaw_service_user }}"
register: gateway_openclaw_removed_global_plugin_packages
changed_when: "'removed ' in (gateway_openclaw_removed_global_plugin_packages.stdout | default(''))"
loop: "{{ gateway_openclaw_removed_global_plugins }}"
loop_control:
label: "{{ item }}"
when:
- gateway_openclaw_removed_global_plugins | length > 0
- not ansible_check_mode
notify: Restart openclaw gateway
- name: Reset OpenClaw compile cache after package or plugin changes
ansible.builtin.file:
path: "{{ gateway_openclaw_compile_cache_dir }}"
state: absent
when:
- not ansible_check_mode
- >-
(gateway_openclaw_package_install.changed | default(false))
or
(gateway_openclaw_required_global_plugin_installs.changed | default(false))
or
(gateway_openclaw_removed_global_plugin_packages.changed | default(false))
- name: Recreate OpenClaw compile cache after package or plugin changes
ansible.builtin.file:
path: "{{ gateway_openclaw_compile_cache_dir }}"
state: directory
owner: "{{ gateway_openclaw_service_user }}"
group: "{{ gateway_openclaw_service_group }}"
mode: "0755"
when:
- not ansible_check_mode
- >-
(gateway_openclaw_package_install.changed | default(false))
or
(gateway_openclaw_required_global_plugin_installs.changed | default(false))
or
(gateway_openclaw_removed_global_plugin_packages.changed | default(false))
- name: Refresh OpenClaw plugin registry
ansible.builtin.command:
cmd: "{{ gateway_openclaw_binary_path }} plugins registry --refresh"
environment:
HOME: "{{ gateway_openclaw_home }}"
PATH: "{{ gateway_openclaw_service_path }}"
OPENCLAW_NO_RESPAWN: "1"
NODE_COMPILE_CACHE: "{{ gateway_openclaw_compile_cache_dir }}"
become: true
become_user: "{{ gateway_openclaw_service_user }}"
changed_when: false
when:
- not ansible_check_mode
- name: Move stale OpenClaw plugin backups out of extension scan path
ansible.builtin.shell: |
set -euo pipefail
@ -198,27 +297,6 @@
- item.stat.exists | default(false)
- not ansible_check_mode
- name: Repair OpenClaw 2026.5 route state as service user
ansible.builtin.command:
cmd: "{{ gateway_openclaw_binary_path }} doctor --fix --non-interactive"
environment:
HOME: "{{ gateway_openclaw_home }}"
PATH: "{{ gateway_openclaw_service_path }}"
OPENCLAW_NO_RESPAWN: "1"
NODE_COMPILE_CACHE: "{{ gateway_openclaw_compile_cache_dir }}"
OPENCLAW_SERVICE_REPAIR_POLICY: external
become: true
become_user: "{{ gateway_openclaw_service_user }}"
register: gateway_openclaw_doctor_repair
changed_when: >-
((gateway_openclaw_doctor_repair.stdout | default('')) ~ '\n' ~
(gateway_openclaw_doctor_repair.stderr | default('')))
is search('(?i)(fixed|repaired|migrated|rewrote|removed|set |moved |updated|archived)')
when:
- gateway_openclaw_doctor_repair_enabled | bool
- not ansible_check_mode
notify: Restart openclaw gateway
- name: Restore immutable flag on OpenClaw gateway JSON config
ansible.builtin.command:
cmd: chattr +i "{{ gateway_openclaw_config_path }}"
@ -265,6 +343,45 @@
when:
- not ansible_check_mode
- name: Check OpenClaw plugin registry
ansible.builtin.command:
cmd: "{{ gateway_openclaw_binary_path }} plugins list --json"
environment:
HOME: "{{ gateway_openclaw_home }}"
PATH: "{{ gateway_openclaw_service_path }}"
OPENCLAW_NO_RESPAWN: "1"
NODE_COMPILE_CACHE: "{{ gateway_openclaw_compile_cache_dir }}"
become: true
become_user: "{{ gateway_openclaw_service_user }}"
register: gateway_openclaw_plugin_registry
changed_when: false
when:
- not ansible_check_mode
- name: Assert OpenClaw Codex plugin matches gateway version
ansible.builtin.assert:
that:
- >-
(
(gateway_openclaw_plugin_registry.stdout | from_json).plugins
| selectattr('id', 'equalto', 'codex')
| selectattr('version', 'equalto', gateway_openclaw_required_version)
| list
| length
) == 1
- >-
(
(gateway_openclaw_plugin_registry.stdout | from_json).plugins
| selectattr('id', 'equalto', 'acpx')
| list
| length
) == 0
fail_msg: >-
OpenClaw must run @openclaw/codex {{ gateway_openclaw_required_version }}
and must not keep stale global @openclaw/acpx.
when:
- not ansible_check_mode
- name: Ensure OpenClaw user systemd unit directory exists
ansible.builtin.file:
path: "{{ gateway_openclaw_user_service_unit_path | dirname }}"

View File

@ -116,7 +116,6 @@
"nvidia": {"enabled": true},
"deepseek": {"enabled": true},
"browser": {"enabled": false},
"acpx": {"enabled": false},
"bonjour": {"enabled": false},
"codex": {
"enabled": true,

View File

@ -273,6 +273,22 @@
):
if code in error_text:
raise SystemExit(f"legacy OpenClaw routing error remained: {code}")
final_text = json.dumps(final, ensure_ascii=False)
for marker in (
"Requested agent harness",
"provider is not one of",
"Agent failed before reply",
"ACP_HTTP_",
):
if marker in final_text:
raise SystemExit(f"OpenClaw smoke returned runtime error text: {marker}")
result = final.get("result") or final.get("payload") or {}
output_text = " ".join(
str(result.get(key, ""))
for key in ("output", "message", "summary", "resultSummary")
)
if "pong" not in output_text.lower():
raise SystemExit(f"OpenClaw smoke did not return pong: {output_text[:500]}")
PY
args:
executable: /bin/bash
@ -340,10 +356,32 @@
raise SystemExit("missing accepted SSE event")
if elapsed_seconds >= 15 and "xworkmate.bridge.keepalive" not in methods:
raise SystemExit("missing keepalive SSE event")
if "validate-openclaw-sse" not in ids:
final = next(
(item for item in payloads if isinstance(item, dict) and item.get("id") == "validate-openclaw-sse"),
None,
)
if final is None:
raise SystemExit("missing final SSE result envelope")
if not payloads or payloads[-1].get("done") is not True:
raise SystemExit("missing SSE done marker")
final_text = json.dumps(final, ensure_ascii=False)
for marker in (
"Requested agent harness",
"provider is not one of",
"Agent failed before reply",
"ACP_HTTP_",
"OPENCLAW_GATEWAY_METHOD_NOT_ALLOWED",
"OPENCLAW_GATEWAY_CONFLICT",
):
if marker in final_text:
raise SystemExit(f"OpenClaw long-task smoke returned runtime error text: {marker}")
result = final.get("result") or final.get("payload") or {}
output_text = " ".join(
str(result.get(key, ""))
for key in ("output", "message", "summary", "resultSummary")
)
if "pong" not in output_text.lower():
raise SystemExit(f"OpenClaw long-task smoke did not return pong: {output_text[:500]}")
PY
args:
executable: /bin/bash