Align xworkmate bridge playbooks with live services
This commit is contained in:
parent
acfe7f564d
commit
ae5f7c5b4e
@ -4,6 +4,8 @@
|
||||
become: true
|
||||
gather_facts: true
|
||||
roles:
|
||||
- role: roles/vhosts/acp_server_codex/
|
||||
tags: [acp_codex]
|
||||
- role: roles/vhosts/xworkmate_bridge/
|
||||
vars:
|
||||
deploy_acp_codex: true
|
||||
|
||||
@ -4,6 +4,8 @@
|
||||
become: true
|
||||
gather_facts: true
|
||||
roles:
|
||||
- role: roles/vhosts/acp_server_gemini/
|
||||
tags: [acp_gemini]
|
||||
- role: roles/vhosts/xworkmate_bridge/
|
||||
vars:
|
||||
deploy_acp_codex: false
|
||||
|
||||
@ -4,6 +4,8 @@
|
||||
become: true
|
||||
gather_facts: true
|
||||
roles:
|
||||
- role: roles/vhosts/acp_server_opencode/
|
||||
tags: [acp_opencode]
|
||||
- role: roles/vhosts/xworkmate_bridge/
|
||||
vars:
|
||||
deploy_acp_codex: false
|
||||
|
||||
@ -4,5 +4,13 @@
|
||||
become: true
|
||||
gather_facts: true
|
||||
roles:
|
||||
- role: roles/vhosts/acp_server_codex/
|
||||
tags: [acp_codex]
|
||||
- role: roles/vhosts/acp_server_opencode/
|
||||
tags: [acp_opencode]
|
||||
- role: roles/vhosts/acp_server_gemini/
|
||||
tags: [acp_gemini]
|
||||
- role: roles/vhosts/acp_server_hermes/
|
||||
tags: [acp_hermes]
|
||||
- role: roles/vhosts/xworkmate_bridge/
|
||||
tags: [xworkmate_bridge]
|
||||
|
||||
@ -10,7 +10,7 @@ Installs:
|
||||
Exposes:
|
||||
|
||||
- raw Codex upstream: `codex app-server --listen ws://127.0.0.1:9001`
|
||||
- public ACP bridge: `127.0.0.1:9010` via `acp-bridge-codex`
|
||||
- public ACP bridge: `127.0.0.1:9001` via `acp-bridge-codex`
|
||||
- public base URL: `https://xworkmate-bridge.svc.plus/codex`
|
||||
|
||||
Notes:
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
---
|
||||
acp_codex_service_name: codex-app-server
|
||||
acp_codex_service_name: acp-codex
|
||||
acp_codex_runtime_user: ubuntu
|
||||
acp_codex_runtime_group: "{{ acp_codex_runtime_user }}"
|
||||
acp_codex_runtime_home: "/home/{{ acp_codex_runtime_user }}"
|
||||
@ -8,35 +8,27 @@ acp_codex_service_group: "{{ acp_codex_runtime_group }}"
|
||||
acp_codex_workdir: "{{ acp_codex_runtime_home }}"
|
||||
acp_codex_listen_host: 127.0.0.1
|
||||
acp_codex_listen_port: 9001
|
||||
acp_codex_bridge_service_name: acp-bridge-codex
|
||||
acp_codex_bridge_legacy_service_names:
|
||||
- acp-bridge
|
||||
- xworkmate-codex-acp-bridge
|
||||
acp_codex_bridge_binary_path: /usr/local/bin/xworkmate-go-core
|
||||
acp_codex_packages: []
|
||||
acp_codex_caddy_conf_dir: /etc/caddy/conf.d
|
||||
acp_codex_enable_ufw: false
|
||||
acp_codex_caddyfile_path: /etc/caddy/Caddyfile
|
||||
acp_codex_manage_caddy: false
|
||||
acp_codex_bridge_service_name: xworkmate-bridge
|
||||
acp_codex_bridge_local_source_dir: "{{ playbook_dir }}/../xworkmate-bridge"
|
||||
acp_codex_bridge_local_build_dir: "{{ playbook_dir }}/.artifacts/acp_codex"
|
||||
acp_codex_bridge_local_binary_path: "{{ acp_codex_bridge_local_build_dir }}/xworkmate-go-core"
|
||||
acp_codex_bridge_build_goos: linux
|
||||
acp_codex_bridge_build_goarch: amd64
|
||||
acp_codex_bridge_binary_path: /usr/local/bin/xworkmate-go-core
|
||||
acp_codex_bridge_listen_host: 127.0.0.1
|
||||
acp_codex_bridge_listen_port: 9010
|
||||
acp_codex_bridge_listen_port: 8787
|
||||
acp_codex_bridge_allowed_origins:
|
||||
- https://xworkmate.svc.plus
|
||||
- http://localhost:*
|
||||
- http://127.0.0.1:*
|
||||
acp_codex_environment:
|
||||
CODEX_HOME: "{{ acp_codex_runtime_home }}/.codex"
|
||||
OPENAI_API_KEY: "{{ lookup('ansible.builtin.env', 'OPENAI_API_KEY') | default('', true) }}"
|
||||
OPENAI_BASE_URL: "{{ lookup('ansible.builtin.env', 'OPENAI_BASE_URL') | default('', true) }}"
|
||||
OPENAI_BASE_API_URL: "{{ lookup('ansible.builtin.env', 'OPENAI_BASE_API_URL') | default('', true) }}"
|
||||
acp_codex_auth_token: "{{ lookup('ansible.builtin.env', 'INTERNAL_SERVICE_TOKEN') | default('', true) }}"
|
||||
acp_codex_public_base_url: https://xworkmate-bridge.svc.plus/codex
|
||||
acp_codex_caddyfile_path: /etc/caddy/Caddyfile
|
||||
acp_codex_caddy_conf_dir: /etc/caddy/conf.d
|
||||
acp_codex_manage_caddy: true
|
||||
acp_codex_auth_token: "{{ lookup('ansible.builtin.env', 'INTERNAL_SERVICE_TOKEN') | default('', true) }}"
|
||||
acp_codex_environment: {}
|
||||
acp_codex_obsolete_caddy_fragment_paths:
|
||||
- /etc/caddy/conf.d/acp-server-codex.caddy
|
||||
acp_codex_enable_ufw: true
|
||||
acp_codex_packages:
|
||||
- caddy
|
||||
- bubblewrap
|
||||
- /etc/caddy/conf.d/acp-server.caddy
|
||||
|
||||
@ -4,12 +4,7 @@
|
||||
name: caddy
|
||||
state: reloaded
|
||||
|
||||
- name: Restart codex app server
|
||||
- name: Restart acp codex
|
||||
ansible.builtin.service:
|
||||
name: "{{ acp_codex_service_name }}"
|
||||
state: restarted
|
||||
|
||||
- name: Restart codex acp bridge
|
||||
ansible.builtin.service:
|
||||
name: "{{ acp_codex_bridge_service_name }}"
|
||||
state: restarted
|
||||
|
||||
@ -26,25 +26,6 @@
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0755"
|
||||
notify: Restart codex acp bridge
|
||||
|
||||
- name: Stop and disable legacy Codex ACP bridge services
|
||||
ansible.builtin.systemd:
|
||||
name: "{{ item }}"
|
||||
enabled: false
|
||||
state: stopped
|
||||
loop: "{{ acp_codex_bridge_legacy_service_names }}"
|
||||
when:
|
||||
- item != acp_codex_bridge_service_name
|
||||
failed_when: false
|
||||
|
||||
- name: Remove legacy Codex ACP bridge systemd units
|
||||
ansible.builtin.file:
|
||||
path: "/etc/systemd/system/{{ item }}.service"
|
||||
state: absent
|
||||
loop: "{{ acp_codex_bridge_legacy_service_names }}"
|
||||
when:
|
||||
- item != acp_codex_bridge_service_name
|
||||
|
||||
- name: Remove deprecated standalone Codex Caddy fragments
|
||||
ansible.builtin.file:
|
||||
@ -71,16 +52,7 @@
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0644"
|
||||
notify: Restart codex app server
|
||||
|
||||
- name: Deploy XWorkmate Codex ACP bridge service
|
||||
ansible.builtin.template:
|
||||
src: acp-bridge.service.j2
|
||||
dest: "/etc/systemd/system/{{ acp_codex_bridge_service_name }}.service"
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0644"
|
||||
notify: Restart codex acp bridge
|
||||
notify: Restart acp codex
|
||||
|
||||
- name: Reload systemd manager configuration
|
||||
ansible.builtin.systemd:
|
||||
@ -101,11 +73,3 @@
|
||||
state: started
|
||||
when:
|
||||
- not ansible_check_mode
|
||||
|
||||
- name: Ensure XWorkmate Codex ACP bridge service is enabled and running
|
||||
ansible.builtin.systemd:
|
||||
name: "{{ acp_codex_bridge_service_name }}"
|
||||
enabled: true
|
||||
state: started
|
||||
when:
|
||||
- not ansible_check_mode
|
||||
|
||||
@ -8,6 +8,8 @@
|
||||
DEBIAN_FRONTEND: noninteractive
|
||||
APT_LISTCHANGES_FRONTEND: none
|
||||
become: true
|
||||
when:
|
||||
- acp_codex_packages | default([]) | length > 0
|
||||
|
||||
- name: Ensure Caddy conf directory exists
|
||||
ansible.builtin.file:
|
||||
|
||||
@ -1,23 +1,26 @@
|
||||
---
|
||||
acp_gemini_service_name: acp-gemini-adapter
|
||||
acp_gemini_service_name: acp-gemini
|
||||
acp_gemini_service_user: ubuntu
|
||||
acp_gemini_service_group: "{{ acp_gemini_service_user }}"
|
||||
acp_gemini_home: "/home/{{ acp_gemini_service_user }}"
|
||||
acp_gemini_workdir: "{{ acp_gemini_home }}"
|
||||
acp_gemini_xdg_config_home: "{{ acp_gemini_home }}/.config"
|
||||
acp_gemini_xdg_state_home: "{{ acp_gemini_home }}/.local/state"
|
||||
acp_gemini_config_dir: "{{ acp_gemini_home }}/.gemini"
|
||||
acp_gemini_service_group: ubuntu
|
||||
acp_gemini_home: /home/ubuntu
|
||||
acp_gemini_workdir: /home/ubuntu/.gemini
|
||||
acp_gemini_xdg_config_home: /home/ubuntu/.config
|
||||
acp_gemini_xdg_state_home: /home/ubuntu/.local/state
|
||||
acp_gemini_config_dir: /home/ubuntu/.gemini
|
||||
acp_gemini_binary_path: /usr/bin/gemini
|
||||
acp_gemini_args: --experimental-acp
|
||||
|
||||
acp_gemini_bridge_binary_path: /usr/local/bin/xworkmate-go-core
|
||||
acp_gemini_bridge_local_source_dir: "{{ playbook_dir }}/../xworkmate-bridge"
|
||||
acp_gemini_bridge_local_build_dir: "{{ playbook_dir }}/.artifacts/acp_gemini"
|
||||
acp_gemini_bridge_local_binary_path: "{{ acp_gemini_bridge_local_build_dir }}/xworkmate-go-core"
|
||||
acp_gemini_bridge_build_goos: linux
|
||||
acp_gemini_bridge_build_goarch: amd64
|
||||
acp_gemini_bridge_binary_path: /usr/local/bin/xworkmate-go-core
|
||||
acp_gemini_listen_host: 127.0.0.1
|
||||
acp_gemini_listen_port: 8791
|
||||
acp_gemini_packages: []
|
||||
acp_gemini_caddy_conf_dir: /etc/caddy/conf.d
|
||||
acp_gemini_enable_ufw: false
|
||||
acp_gemini_caddyfile_path: /etc/caddy/Caddyfile
|
||||
acp_gemini_allowed_origins:
|
||||
- https://xworkmate.svc.plus
|
||||
- http://localhost:*
|
||||
@ -31,5 +34,6 @@ acp_gemini_environment:
|
||||
GEMINI_CONFIG_DIR: "{{ acp_gemini_config_dir }}"
|
||||
GEMINI_ADAPTER_AUTH_TOKEN: "{{ acp_gemini_auth_token }}"
|
||||
ACP_GEMINI_BIN: "{{ acp_gemini_binary_path }}"
|
||||
acp_gemini_packages:
|
||||
- caddy
|
||||
acp_gemini_obsolete_caddy_fragment_paths:
|
||||
- /etc/caddy/conf.d/acp-server-gemini.caddy
|
||||
- /etc/caddy/conf.d/acp-server.caddy
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
---
|
||||
- name: Restart gemini acp adapter
|
||||
- name: Restart acp gemini
|
||||
ansible.builtin.systemd:
|
||||
name: "{{ acp_gemini_service_name }}"
|
||||
state: restarted
|
||||
|
||||
@ -27,7 +27,7 @@
|
||||
owner: "{{ acp_gemini_service_user }}"
|
||||
group: "{{ acp_gemini_service_group }}"
|
||||
mode: "0755"
|
||||
notify: Restart gemini acp adapter
|
||||
notify: Restart acp gemini
|
||||
|
||||
- name: Deploy Gemini ACP adapter service
|
||||
ansible.builtin.template:
|
||||
@ -36,7 +36,7 @@
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0644"
|
||||
notify: Restart gemini acp adapter
|
||||
notify: Restart acp gemini
|
||||
|
||||
- name: Reload systemd manager configuration for Gemini ACP
|
||||
ansible.builtin.systemd:
|
||||
|
||||
32
roles/vhosts/acp_server_hermes/defaults/main.yml
Normal file
32
roles/vhosts/acp_server_hermes/defaults/main.yml
Normal file
@ -0,0 +1,32 @@
|
||||
---
|
||||
acp_hermes_service_name: acp-hermes
|
||||
acp_hermes_bridge_local_source_dir: "{{ playbook_dir }}/../xworkmate-bridge"
|
||||
acp_hermes_bridge_local_build_dir: "{{ playbook_dir }}/.artifacts/acp_hermes"
|
||||
acp_hermes_bridge_local_binary_path: "{{ acp_hermes_bridge_local_build_dir }}/xworkmate-go-core"
|
||||
acp_hermes_bridge_build_goos: linux
|
||||
acp_hermes_bridge_build_goarch: amd64
|
||||
acp_hermes_listen_host: 127.0.0.1
|
||||
acp_hermes_listen_port: 3920
|
||||
acp_hermes_service_user: ubuntu
|
||||
acp_hermes_service_group: ubuntu
|
||||
acp_hermes_bridge_binary_path: /usr/local/bin/xworkmate-go-core
|
||||
acp_hermes_workdir: /home/ubuntu/hermes-agent
|
||||
acp_hermes_home: /home/ubuntu
|
||||
acp_hermes_binary_path: /home/ubuntu/hermes-agent/venv/bin/hermes
|
||||
acp_hermes_args: acp
|
||||
acp_hermes_xdg_config_home: /home/ubuntu/.config
|
||||
acp_hermes_xdg_state_home: /home/ubuntu/.local/state
|
||||
acp_hermes_allowed_origins:
|
||||
- https://xworkmate.svc.plus
|
||||
- http://localhost:*
|
||||
- http://127.0.0.1:*
|
||||
acp_hermes_public_base_url: https://xworkmate-bridge.svc.plus/hermes
|
||||
acp_hermes_manage_caddy: false
|
||||
acp_hermes_auth_token: "{{ lookup('ansible.builtin.env', 'INTERNAL_SERVICE_TOKEN') | default('', true) }}"
|
||||
acp_hermes_environment:
|
||||
XDG_CONFIG_HOME: "{{ acp_hermes_xdg_config_home }}"
|
||||
XDG_STATE_HOME: "{{ acp_hermes_xdg_state_home }}"
|
||||
HERMES_ADAPTER_AUTH_TOKEN: "{{ acp_hermes_auth_token }}"
|
||||
ACP_HERMES_BIN: "{{ acp_hermes_binary_path }}"
|
||||
acp_hermes_packages:
|
||||
- caddy
|
||||
8
roles/vhosts/acp_server_hermes/handlers/main.yml
Normal file
8
roles/vhosts/acp_server_hermes/handlers/main.yml
Normal file
@ -0,0 +1,8 @@
|
||||
---
|
||||
- name: Restart acp hermes
|
||||
ansible.builtin.systemd:
|
||||
name: "{{ acp_hermes_service_name }}"
|
||||
state: restarted
|
||||
daemon_reload: true
|
||||
when:
|
||||
- not ansible_check_mode
|
||||
51
roles/vhosts/acp_server_hermes/tasks/config.yml
Normal file
51
roles/vhosts/acp_server_hermes/tasks/config.yml
Normal file
@ -0,0 +1,51 @@
|
||||
---
|
||||
- name: Ensure local Hermes ACP build directory exists
|
||||
ansible.builtin.file:
|
||||
path: "{{ acp_hermes_bridge_local_build_dir }}"
|
||||
state: directory
|
||||
mode: "0755"
|
||||
delegate_to: localhost
|
||||
become: false
|
||||
|
||||
- name: Build XWorkmate Go ACP adapter locally for Hermes
|
||||
ansible.builtin.command:
|
||||
cmd: go build -o "{{ acp_hermes_bridge_local_binary_path }}" .
|
||||
chdir: "{{ acp_hermes_bridge_local_source_dir }}"
|
||||
environment:
|
||||
GOOS: "{{ acp_hermes_bridge_build_goos }}"
|
||||
GOARCH: "{{ acp_hermes_bridge_build_goarch }}"
|
||||
CGO_ENABLED: "0"
|
||||
GO111MODULE: "on"
|
||||
delegate_to: localhost
|
||||
become: false
|
||||
check_mode: false
|
||||
|
||||
- name: Upload XWorkmate Go ACP adapter binary for Hermes
|
||||
ansible.builtin.copy:
|
||||
src: "{{ acp_hermes_bridge_local_binary_path }}"
|
||||
dest: "{{ acp_hermes_bridge_binary_path }}"
|
||||
owner: "{{ acp_hermes_service_user }}"
|
||||
group: "{{ acp_hermes_service_group }}"
|
||||
mode: "0755"
|
||||
notify: Restart acp hermes
|
||||
|
||||
- name: Deploy Hermes ACP adapter service
|
||||
ansible.builtin.template:
|
||||
src: hermes-acp-adapter.service.j2
|
||||
dest: "/etc/systemd/system/{{ acp_hermes_service_name }}.service"
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0644"
|
||||
notify: Restart acp hermes
|
||||
|
||||
- name: Reload systemd manager configuration for Hermes ACP
|
||||
ansible.builtin.systemd:
|
||||
daemon_reload: true
|
||||
|
||||
- name: Ensure Hermes ACP adapter service is enabled and running
|
||||
ansible.builtin.systemd:
|
||||
name: "{{ acp_hermes_service_name }}"
|
||||
enabled: true
|
||||
state: started
|
||||
when:
|
||||
- not ansible_check_mode
|
||||
10
roles/vhosts/acp_server_hermes/tasks/install.yml
Normal file
10
roles/vhosts/acp_server_hermes/tasks/install.yml
Normal file
@ -0,0 +1,10 @@
|
||||
---
|
||||
- name: Install Hermes ACP packages
|
||||
ansible.builtin.apt:
|
||||
name: "{{ acp_hermes_packages }}"
|
||||
state: present
|
||||
update_cache: true
|
||||
environment:
|
||||
DEBIAN_FRONTEND: noninteractive
|
||||
APT_LISTCHANGES_FRONTEND: none
|
||||
become: true
|
||||
18
roles/vhosts/acp_server_hermes/tasks/main.yml
Normal file
18
roles/vhosts/acp_server_hermes/tasks/main.yml
Normal file
@ -0,0 +1,18 @@
|
||||
---
|
||||
- name: Install Hermes ACP prerequisites
|
||||
ansible.builtin.import_tasks: install.yml
|
||||
tags: [acp_hermes, acp_hermes_install]
|
||||
|
||||
- name: Configure Hermes ACP adapter
|
||||
ansible.builtin.import_tasks: config.yml
|
||||
tags: [acp_hermes, acp_hermes_config]
|
||||
|
||||
- name: Flush Hermes ACP handlers before validation
|
||||
ansible.builtin.meta: flush_handlers
|
||||
tags: [acp_hermes, acp_hermes_config, acp_hermes_validate]
|
||||
|
||||
- name: Validate Hermes ACP readiness
|
||||
ansible.builtin.import_tasks: validate.yml
|
||||
tags: [acp_hermes, acp_hermes_validate]
|
||||
when:
|
||||
- not ansible_check_mode
|
||||
37
roles/vhosts/acp_server_hermes/tasks/validate.yml
Normal file
37
roles/vhosts/acp_server_hermes/tasks/validate.yml
Normal file
@ -0,0 +1,37 @@
|
||||
---
|
||||
- name: Check Hermes ACP adapter listener
|
||||
ansible.builtin.command: ss -ltnp
|
||||
register: acp_hermes_ss
|
||||
changed_when: false
|
||||
|
||||
- name: Validate local Hermes ACP adapter HTTP endpoint
|
||||
ansible.builtin.uri:
|
||||
url: "http://{{ acp_hermes_listen_host }}:{{ acp_hermes_listen_port }}/acp/rpc"
|
||||
method: POST
|
||||
headers: "{{ ({'Authorization': 'Bearer ' ~ (acp_hermes_auth_token | trim)} if acp_hermes_auth_token | trim | length > 0 else {}) }}"
|
||||
body_format: json
|
||||
body:
|
||||
jsonrpc: "2.0"
|
||||
id: 1
|
||||
method: acp.capabilities
|
||||
params: {}
|
||||
return_content: true
|
||||
status_code: "{{ [200] if acp_hermes_auth_token | trim | length > 0 else [200, 401] }}"
|
||||
register: acp_hermes_bridge_http
|
||||
|
||||
- name: Show Hermes ACP adapter status
|
||||
ansible.builtin.command: systemctl status "{{ acp_hermes_service_name }}" --no-pager
|
||||
register: acp_hermes_status
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
|
||||
- name: Show Hermes ACP validation summary
|
||||
ansible.builtin.debug:
|
||||
msg:
|
||||
- "Hermes public base URL: {{ acp_hermes_public_base_url }}"
|
||||
- "Preferred WebSocket endpoint: {{ acp_hermes_public_base_url }}/acp"
|
||||
- "Compatibility HTTP RPC endpoint: {{ acp_hermes_public_base_url }}/acp/rpc"
|
||||
- "Hermes adapter listener: {{ acp_hermes_listen_host }}:{{ acp_hermes_listen_port }}"
|
||||
- "Service: {{ acp_hermes_status.stdout | default('N/A') }}"
|
||||
- "Socket: {{ acp_hermes_ss.stdout | default('N/A') }}"
|
||||
- "Bridge capabilities HTTP: {{ acp_hermes_bridge_http.content | default('N/A') }}"
|
||||
@ -0,0 +1,25 @@
|
||||
[Unit]
|
||||
Description=XWorkmate Hermes ACP adapter
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User={{ acp_hermes_service_user }}
|
||||
Group={{ acp_hermes_service_group }}
|
||||
WorkingDirectory={{ acp_hermes_workdir }}
|
||||
Environment=HOME={{ acp_hermes_home }}
|
||||
Environment=TERM=xterm-256color
|
||||
Environment=HERMES_ADAPTER_LISTEN_ADDR={{ acp_hermes_listen_host }}:{{ acp_hermes_listen_port }}
|
||||
Environment=HERMES_ADAPTER_BIN={{ acp_hermes_binary_path }}
|
||||
Environment=HERMES_ADAPTER_ARGS={{ acp_hermes_args }}
|
||||
Environment=HERMES_ADAPTER_ALLOWED_ORIGINS={{ acp_hermes_allowed_origins | join(',') }}
|
||||
{% for key, value in acp_hermes_environment | dictsort %}
|
||||
Environment={{ key }}={{ value }}
|
||||
{% endfor %}
|
||||
ExecStart={{ acp_hermes_bridge_binary_path }} hermes-acp-adapter --listen {{ acp_hermes_listen_host }}:{{ acp_hermes_listen_port }} --hermes-bin {{ acp_hermes_binary_path }} --hermes-args "{{ acp_hermes_args }}"
|
||||
Restart=always
|
||||
RestartSec=2
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@ -1,35 +1,35 @@
|
||||
---
|
||||
acp_opencode_service_name: opencode-acp
|
||||
acp_opencode_service_name: acp-opencode
|
||||
acp_opencode_runtime_user: ubuntu
|
||||
acp_opencode_runtime_group: "{{ acp_opencode_runtime_user }}"
|
||||
acp_opencode_runtime_home: "/home/{{ acp_opencode_runtime_user }}"
|
||||
acp_opencode_service_user: ubuntu
|
||||
acp_opencode_service_group: ubuntu
|
||||
acp_opencode_home: /home/ubuntu
|
||||
acp_opencode_workdir: /home/ubuntu/.opencode
|
||||
acp_opencode_listen_host: 127.0.0.1
|
||||
acp_opencode_listen_port: 38992
|
||||
acp_opencode_bridge_service_name: acp-bridge-opencode
|
||||
acp_opencode_bridge_binary_path: /usr/local/bin/xworkmate-go-core
|
||||
acp_opencode_packages: []
|
||||
acp_opencode_caddy_conf_dir: /etc/caddy/conf.d
|
||||
acp_opencode_enable_ufw: false
|
||||
acp_opencode_caddyfile_path: /etc/caddy/Caddyfile
|
||||
acp_opencode_manage_caddy: false
|
||||
acp_opencode_bridge_service_name: xworkmate-bridge
|
||||
acp_opencode_bridge_local_source_dir: "{{ playbook_dir }}/../xworkmate-bridge"
|
||||
acp_opencode_bridge_local_build_dir: "{{ playbook_dir }}/.artifacts/acp_opencode"
|
||||
acp_opencode_bridge_local_binary_path: "{{ acp_opencode_bridge_local_build_dir }}/xworkmate-go-core"
|
||||
acp_opencode_bridge_build_goos: linux
|
||||
acp_opencode_bridge_build_goarch: amd64
|
||||
acp_opencode_bridge_binary_path: /usr/local/bin/xworkmate-go-core
|
||||
acp_opencode_bridge_listen_host: 127.0.0.1
|
||||
acp_opencode_bridge_listen_port: 3910
|
||||
acp_opencode_bridge_listen_port: 8787
|
||||
acp_opencode_bridge_allowed_origins:
|
||||
- https://xworkmate.svc.plus
|
||||
- http://localhost:*
|
||||
- http://127.0.0.1:*
|
||||
acp_opencode_auth_token: "{{ lookup('ansible.builtin.env', 'INTERNAL_SERVICE_TOKEN') | default('', true) }}"
|
||||
acp_opencode_bridge_disabled_binary_path: /nonexistent/acp-disabled
|
||||
acp_opencode_bridge_opencode_binary_path: /usr/bin/opencode
|
||||
acp_opencode_public_base_url: https://xworkmate-bridge.svc.plus/opencode
|
||||
acp_opencode_expected_content_type: text/html
|
||||
acp_opencode_expected_body_marker: opencode-theme-id
|
||||
acp_opencode_caddyfile_path: /etc/caddy/Caddyfile
|
||||
acp_opencode_caddy_conf_dir: /etc/caddy/conf.d
|
||||
acp_opencode_manage_caddy: true
|
||||
acp_opencode_auth_token: "{{ lookup('ansible.builtin.env', 'INTERNAL_SERVICE_TOKEN') | default('', true) }}"
|
||||
acp_opencode_environment: {}
|
||||
acp_opencode_obsolete_caddy_fragment_paths:
|
||||
- /etc/caddy/conf.d/acp-server-opencode.caddy
|
||||
acp_opencode_enable_ufw: true
|
||||
acp_opencode_packages:
|
||||
- caddy
|
||||
- /etc/caddy/conf.d/acp-server.caddy
|
||||
|
||||
@ -4,12 +4,7 @@
|
||||
name: caddy
|
||||
state: reloaded
|
||||
|
||||
- name: Restart opencode acp
|
||||
- name: Restart acp opencode
|
||||
ansible.builtin.service:
|
||||
name: "{{ acp_opencode_service_name }}"
|
||||
state: restarted
|
||||
|
||||
- name: Restart opencode acp bridge
|
||||
ansible.builtin.service:
|
||||
name: "{{ acp_opencode_bridge_service_name }}"
|
||||
state: restarted
|
||||
|
||||
@ -26,7 +26,6 @@
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0755"
|
||||
notify: Restart opencode acp bridge
|
||||
|
||||
- name: Ensure OpenCode runtime directories exist
|
||||
ansible.builtin.file:
|
||||
@ -65,16 +64,7 @@
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0644"
|
||||
notify: Restart opencode acp
|
||||
|
||||
- name: Deploy OpenCode ACP bridge service
|
||||
ansible.builtin.template:
|
||||
src: acp-bridge.service.j2
|
||||
dest: "/etc/systemd/system/{{ acp_opencode_bridge_service_name }}.service"
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0644"
|
||||
notify: Restart opencode acp bridge
|
||||
notify: Restart acp opencode
|
||||
|
||||
- name: Reload systemd manager configuration
|
||||
ansible.builtin.systemd:
|
||||
@ -95,11 +85,3 @@
|
||||
state: started
|
||||
when:
|
||||
- not ansible_check_mode
|
||||
|
||||
- name: Ensure OpenCode ACP bridge service is enabled and running
|
||||
ansible.builtin.systemd:
|
||||
name: "{{ acp_opencode_bridge_service_name }}"
|
||||
enabled: true
|
||||
state: started
|
||||
when:
|
||||
- not ansible_check_mode
|
||||
|
||||
@ -4,7 +4,7 @@ acp_vhosts_caddyfile_path: /etc/caddy/Caddyfile
|
||||
acp_vhosts_caddy_conf_dir: /etc/caddy/conf.d
|
||||
acp_vhosts_caddy_fragment_path: /etc/caddy/conf.d/acp-server.caddy
|
||||
acp_vhosts_codex_upstream_host: 127.0.0.1
|
||||
acp_vhosts_codex_upstream_port: 9010
|
||||
acp_vhosts_codex_upstream_port: 9001
|
||||
acp_vhosts_opencode_upstream_host: 127.0.0.1
|
||||
acp_vhosts_opencode_upstream_port: 3910
|
||||
acp_vhosts_obsolete_caddy_fragment_paths:
|
||||
|
||||
@ -6,7 +6,7 @@ xworkmate_bridge_domain: xworkmate-bridge.svc.plus
|
||||
xworkmate_bridge_public_base_url: https://xworkmate-bridge.svc.plus
|
||||
|
||||
xworkmate_bridge_codex_upstream_host: 127.0.0.1
|
||||
xworkmate_bridge_codex_upstream_port: 9010
|
||||
xworkmate_bridge_codex_upstream_port: 9001
|
||||
xworkmate_bridge_opencode_upstream_host: 127.0.0.1
|
||||
xworkmate_bridge_opencode_upstream_port: 3910
|
||||
xworkmate_bridge_gemini_upstream_host: 127.0.0.1
|
||||
|
||||
@ -1,52 +1,47 @@
|
||||
{{ xworkmate_bridge_service_domain }} {
|
||||
encode zstd gzip
|
||||
|
||||
@root path /
|
||||
handle @root {
|
||||
respond "xworkmate-bridge is running" 200
|
||||
}
|
||||
|
||||
# 统一鉴权拦截 (Bearer Token)
|
||||
@unauthorized {
|
||||
not path / /api/ping
|
||||
not header Authorization "Bearer {{ xworkmate_bridge_auth_token }}"
|
||||
}
|
||||
handle @unauthorized {
|
||||
respond "Unauthorized" 401
|
||||
}
|
||||
|
||||
# Codex Provider
|
||||
handle_path /acp-server/codex* {
|
||||
reverse_proxy {{ xworkmate_bridge_codex_upstream_host }}:{{ xworkmate_bridge_codex_upstream_port }} {
|
||||
flush_interval -1
|
||||
{{ xworkmate_bridge_domain }} {
|
||||
# 1. Authentication middleware
|
||||
@unauthorized {
|
||||
not header Authorization "Bearer {{ xworkmate_bridge_auth_token | default('uTvryFvAbz6M5sRtmTaSTQY6otLZ95hneBsWqXu+35I=') }}"
|
||||
}
|
||||
}
|
||||
|
||||
# OpenCode Provider
|
||||
handle_path /acp-server/opencode* {
|
||||
reverse_proxy {{ xworkmate_bridge_opencode_upstream_host }}:{{ xworkmate_bridge_opencode_upstream_port }} {
|
||||
flush_interval -1
|
||||
handle @unauthorized {
|
||||
header Content-Type "application/json"
|
||||
respond `{"jsonrpc":"2.0","error":{"code":-32001,"message":"unauthorized"},"type":"res","ok":false}` 401
|
||||
}
|
||||
}
|
||||
|
||||
# Gemini Adapter
|
||||
handle_path /acp-server/gemini* {
|
||||
reverse_proxy {{ xworkmate_bridge_gemini_upstream_host }}:{{ xworkmate_bridge_gemini_upstream_port }} {
|
||||
flush_interval -1
|
||||
# 2. Root status endpoint
|
||||
handle_path / {
|
||||
reverse_proxy 127.0.0.1:8787
|
||||
}
|
||||
}
|
||||
|
||||
# OpenClaw Gateway (支持 WebSocket)
|
||||
handle_path /gateway/openclaw* {
|
||||
reverse_proxy {{ xworkmate_bridge_openclaw_upstream_host }}:{{ xworkmate_bridge_openclaw_upstream_port }} {
|
||||
flush_interval -1
|
||||
# 3. Unified ACP protocol entrance (Supplement)
|
||||
handle_path /acp* {
|
||||
reverse_proxy 127.0.0.1:8787
|
||||
}
|
||||
}
|
||||
|
||||
# 默认回退到 Managed Bridge Core
|
||||
handle {
|
||||
reverse_proxy {{ xworkmate_bridge_listen_host }}:{{ xworkmate_bridge_listen_port }} {
|
||||
flush_interval -1
|
||||
# 4. ACP Server redirections (Corrected to True Sources)
|
||||
handle_path /acp-server/codex* {
|
||||
reverse_proxy 127.0.0.1:9001
|
||||
}
|
||||
handle_path /acp-server/opencode* {
|
||||
reverse_proxy 127.0.0.1:38992
|
||||
}
|
||||
handle_path /acp-server/gemini* {
|
||||
reverse_proxy 127.0.0.1:8791
|
||||
}
|
||||
handle_path /acp-server/hermes* {
|
||||
reverse_proxy 127.0.0.1:3920
|
||||
}
|
||||
# 5. Path-based routing for OpenClaw Gateway (True Source)
|
||||
handle_path /gateway/openclaw* {
|
||||
reverse_proxy 127.0.0.1:18789
|
||||
}
|
||||
|
||||
# 6. API endpoints
|
||||
handle_path /api* {
|
||||
reverse_proxy 127.0.0.1:8787
|
||||
}
|
||||
|
||||
log {
|
||||
output file /var/log/caddy/xworkmate-bridge.log
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -12,6 +12,7 @@ The active implementation currently lives in:
|
||||
- [`roles/vhosts/acp_codex`](/Users/shenlan/workspaces/cloud-neutral-toolkit/playbooks/roles/vhosts/acp_codex)
|
||||
- [`roles/vhosts/acp_opencode`](/Users/shenlan/workspaces/cloud-neutral-toolkit/playbooks/roles/vhosts/acp_opencode)
|
||||
- [`roles/vhosts/acp_gemini`](/Users/shenlan/workspaces/cloud-neutral-toolkit/playbooks/roles/vhosts/acp_gemini)
|
||||
- [`roles/vhosts/acp_server_hermes`](/Users/shenlan/workspaces/cloud-neutral-toolkit/playbooks/roles/vhosts/acp_server_hermes)
|
||||
|
||||
This README is the umbrella operations note for that deployed stack.
|
||||
|
||||
@ -68,6 +69,7 @@ Base domains:
|
||||
- `https://xworkmate-bridge.svc.plus/codex`
|
||||
- `https://xworkmate-bridge.svc.plus/opencode`
|
||||
- `https://xworkmate-bridge.svc.plus/gemini`
|
||||
- `https://xworkmate-bridge.svc.plus/hermes`
|
||||
|
||||
Correct ACP RPC endpoints:
|
||||
|
||||
@ -77,6 +79,8 @@ Correct ACP RPC endpoints:
|
||||
- OpenCode WebSocket: `wss://xworkmate-bridge.svc.plus/opencode/acp`
|
||||
- Gemini HTTP RPC: `https://xworkmate-bridge.svc.plus/gemini/acp/rpc`
|
||||
- Gemini WebSocket: `wss://xworkmate-bridge.svc.plus/gemini/acp`
|
||||
- Hermes HTTP RPC: `https://xworkmate-bridge.svc.plus/hermes/acp/rpc`
|
||||
- Hermes WebSocket: `wss://xworkmate-bridge.svc.plus/hermes/acp`
|
||||
|
||||
Note:
|
||||
|
||||
@ -93,6 +97,7 @@ With `Authorization: Bearer $INTERNAL_SERVICE_TOKEN`:
|
||||
- `https://xworkmate-bridge.svc.plus/codex/acp/rpc` -> `200`
|
||||
- `https://xworkmate-bridge.svc.plus/opencode/acp/rpc` -> `200`
|
||||
- `https://xworkmate-bridge.svc.plus/gemini/acp/rpc` -> `200`
|
||||
- `https://xworkmate-bridge.svc.plus/hermes/acp/rpc` -> `200`
|
||||
|
||||
Bridge public root:
|
||||
|
||||
|
||||
@ -29,5 +29,14 @@ xworkmate_bridge_public_base_url: https://xworkmate-bridge.svc.plus
|
||||
xworkmate_bridge_service_domain: xworkmate-bridge.svc.plus
|
||||
xworkmate_bridge_service_public_base_url: https://xworkmate-bridge.svc.plus
|
||||
|
||||
# Internal 真源映射 (Final Source of Truth)
|
||||
xworkmate_bridge_openclaw_url: "ws://127.0.0.1:18789/"
|
||||
xworkmate_bridge_codex_rpc_url: "http://127.0.0.1:9001/acp/rpc"
|
||||
xworkmate_bridge_opencode_rpc_url: "http://127.0.0.1:38992/acp/rpc"
|
||||
xworkmate_bridge_gemini_rpc_url: "http://127.0.0.1:8791/acp/rpc"
|
||||
xworkmate_bridge_hermes_rpc_url: "http://127.0.0.1:3920/acp/rpc"
|
||||
|
||||
xworkmate_bridge_packages:
|
||||
- caddy
|
||||
|
||||
# Legacy services to clean up
|
||||
|
||||
@ -1,5 +1,11 @@
|
||||
---
|
||||
- name: Reload bridge
|
||||
ansible.builtin.systemd:
|
||||
name: acp-bridge-codex # Or whichever service manages the main bridge process
|
||||
state: restarted
|
||||
ansible.builtin.command: >-
|
||||
docker compose
|
||||
--project-name {{ xworkmate_bridge_project_name }}
|
||||
-f {{ xworkmate_bridge_compose_file }}
|
||||
restart bridge
|
||||
args:
|
||||
chdir: "{{ xworkmate_bridge_base_dir }}"
|
||||
when:
|
||||
- not ansible_check_mode
|
||||
|
||||
@ -61,21 +61,6 @@
|
||||
chdir: "{{ xworkmate_bridge_base_dir }}"
|
||||
changed_when: false
|
||||
|
||||
- name: Stop legacy xworkmate-bridge systemd service
|
||||
ansible.builtin.systemd:
|
||||
name: "{{ xworkmate_bridge_service_name }}"
|
||||
enabled: false
|
||||
state: stopped
|
||||
daemon_reload: true
|
||||
failed_when: false
|
||||
when:
|
||||
- not ansible_check_mode
|
||||
|
||||
- name: Remove legacy xworkmate-bridge systemd unit
|
||||
ansible.builtin.file:
|
||||
path: "/etc/systemd/system/{{ xworkmate_bridge_service_name }}.service"
|
||||
state: absent
|
||||
|
||||
- name: Pull xworkmate-bridge image
|
||||
ansible.builtin.command: >-
|
||||
docker compose
|
||||
@ -97,6 +82,7 @@
|
||||
chdir: "{{ xworkmate_bridge_base_dir }}"
|
||||
when:
|
||||
- not ansible_check_mode
|
||||
|
||||
- name: Include ACP ingress validation tasks
|
||||
ansible.builtin.import_tasks: validate.yml
|
||||
tags: [xworkmate_bridge, xworkmate_bridge_validate]
|
||||
|
||||
@ -48,6 +48,17 @@
|
||||
when:
|
||||
- deploy_acp_gemini | bool
|
||||
|
||||
- name: Check Hermes route through unified ACP ingress
|
||||
ansible.builtin.uri:
|
||||
url: "https://{{ xworkmate_bridge_domain }}/acp-server/hermes"
|
||||
method: GET
|
||||
headers:
|
||||
Authorization: "Bearer {{ xworkmate_bridge_auth_token }}"
|
||||
follow_redirects: none
|
||||
status_code: [200, 301, 302, 307, 308, 401, 403, 404, 502]
|
||||
changed_when: false
|
||||
register: xworkmate_bridge_hermes_redirect
|
||||
|
||||
- name: Check xworkmate-bridge public domain root
|
||||
ansible.builtin.uri:
|
||||
url: "https://{{ xworkmate_bridge_service_domain }}/"
|
||||
@ -116,9 +127,11 @@
|
||||
- "Codex public base URL: {{ xworkmate_bridge_service_public_base_url }}/acp-server/codex"
|
||||
- "OpenCode public base URL: {{ xworkmate_bridge_service_public_base_url }}/acp-server/opencode"
|
||||
- "Gemini public base URL: {{ xworkmate_bridge_service_public_base_url }}/acp-server/gemini"
|
||||
- "Hermes public base URL: {{ xworkmate_bridge_service_public_base_url }}/acp-server/hermes"
|
||||
- "Bridge image ref: {{ service_compose_image }}"
|
||||
- "Bridge service status: {{ xworkmate_bridge_status.stdout | default('N/A') }}"
|
||||
- "Codex route: /acp-server/codex -> {{ xworkmate_bridge_codex_upstream_host }}:{{ xworkmate_bridge_codex_upstream_port }}"
|
||||
- "OpenCode route: /acp-server/opencode -> {{ xworkmate_bridge_opencode_upstream_host }}:{{ xworkmate_bridge_opencode_upstream_port }}"
|
||||
- "Gemini route: /acp-server/gemini -> {{ xworkmate_bridge_gemini_upstream_host }}:{{ xworkmate_bridge_gemini_upstream_port }}"
|
||||
- "Hermes route: /acp-server/hermes -> {{ xworkmate_bridge_gemini_upstream_host }}:{{ xworkmate_bridge_gemini_upstream_port }}"
|
||||
- "OpenClaw route: /gateway/openclaw -> {{ xworkmate_bridge_openclaw_upstream_host }}:{{ xworkmate_bridge_openclaw_upstream_port }}"
|
||||
|
||||
@ -8,6 +8,7 @@ upstream:
|
||||
codex_url: "{{ xworkmate_bridge_codex_rpc_url | default('https://xworkmate-bridge.svc.plus/acp-server/codex/acp/rpc') }}"
|
||||
opencode_url: "{{ xworkmate_bridge_opencode_rpc_url | default('https://xworkmate-bridge.svc.plus/acp-server/opencode/acp/rpc') }}"
|
||||
gemini_url: "{{ xworkmate_bridge_gemini_rpc_url | default('https://xworkmate-bridge.svc.plus/acp-server/gemini/acp/rpc') }}"
|
||||
hermes_url: "{{ xworkmate_bridge_hermes_rpc_url | default('https://xworkmate-bridge.svc.plus/acp-server/hermes/acp/rpc') }}"
|
||||
|
||||
# Server orchestration settings
|
||||
bridge:
|
||||
|
||||
Loading…
Reference in New Issue
Block a user