feat: add hermes-zulip-plugin (install & repair) and relocate hermes-zulip-restore to repo
- hermes-zulip-plugin.prose.md: installs latest zulip-platform plugin from canonical repo, verifies _strip_html fix, sends relay success signal. Distinct from restore — plugin-layer only, no env/gateway/connection checks. - hermes-zulip-restore.prose.md: relocated from /root/ into prose-contracts repo. - Removed duplicate zulip-platform-verification from /root/vault/contracts/.
This commit is contained in:
@@ -0,0 +1,207 @@
|
|||||||
|
---
|
||||||
|
kind: function
|
||||||
|
name: hermes-zulip-plugin
|
||||||
|
description: >
|
||||||
|
Installs or updates the Zulip platform plugin for any Hermes agent from the
|
||||||
|
canonical zulip-platform-plugins repo. Ensures the agent runs the latest
|
||||||
|
adapter with all Zulip chat fixes (_strip_html, streaming, event recovery).
|
||||||
|
Runs a post-install verification and sends a relay success signal.
|
||||||
|
agent: abiba
|
||||||
|
version: 1.0.0
|
||||||
|
status: active
|
||||||
|
runtime_contract: 2
|
||||||
|
---
|
||||||
|
|
||||||
|
# Hermes Zulip Plugin — Install & Repair
|
||||||
|
|
||||||
|
Single-shot function that pulls the latest zulip-platform plugin from the
|
||||||
|
canonical git repo, installs it to the correct Hermes bundled plugin path,
|
||||||
|
verifies the installation, and signals completion.
|
||||||
|
|
||||||
|
Distinct from `hermes-zulip-restore`: this contract only touches the plugin
|
||||||
|
layer. It does NOT verify env credentials, restart the gateway, or validate
|
||||||
|
the live Zulip connection. Use `hermes-zulip-restore` for full connectivity
|
||||||
|
recovery.
|
||||||
|
|
||||||
|
## Parameters
|
||||||
|
|
||||||
|
| Param | Type | Required | Default | Description |
|
||||||
|
|-------|------|----------|---------|-------------|
|
||||||
|
| `target` | string | yes | — | Agent name: `mumuni`, `tanko`, or `koby` |
|
||||||
|
| `branch` | string | no | `feat/zulip-streaming` | Git branch to pull (overridable for pinning) |
|
||||||
|
|
||||||
|
## Maintains
|
||||||
|
|
||||||
|
- plugin_installed: bool — Whether all three adapter files exist at the bundled path
|
||||||
|
- plugin_version: string — Git commit SHA of the installed version
|
||||||
|
- strip_html_present: bool — Whether `_strip_html` fix is in the installed adapter
|
||||||
|
- signal_sent: bool — Whether relay success message was dispatched
|
||||||
|
|
||||||
|
### Postconditions
|
||||||
|
|
||||||
|
- All three adapter files (`__init__.py`, `adapter.py`, `plugin.yaml`) present in `<HERMES_HOME>/hermes-agent/plugins/platforms/zulip/`
|
||||||
|
- `_strip_html` function exists in `adapter.py` (slash-command fix, commit `55ca15d`+)
|
||||||
|
- Installed version matches HEAD of the requested branch
|
||||||
|
- Relay success signal sent to Hermes agent's inbox
|
||||||
|
|
||||||
|
## Requires
|
||||||
|
|
||||||
|
- SSH access to target host (direct or via amdpve for CTs)
|
||||||
|
- Git repo at `https://git.sysloggh.net/SyslogSolution/zulip-platform-plugins.git`
|
||||||
|
- Python 3 with `httpx` installed on target
|
||||||
|
|
||||||
|
## Live-State Fields
|
||||||
|
|
||||||
|
| Host | CT | Proxmox | IP (direct) | Hermes Home | User |
|
||||||
|
|------|-----|---------|-------------|-------------|------|
|
||||||
|
| Mumuni | CT114 | — | 192.168.68.123 | /root/.hermes | root |
|
||||||
|
| Tanko | CT112 | amdpve | 192.168.68.122 | /home/jerome/.hermes | jerome |
|
||||||
|
| Koby | CT111 | amdpve | 192.168.68.129 | /root/.hermes | root |
|
||||||
|
|
||||||
|
| Field | Value | Trust |
|
||||||
|
|-------|-------|-------|
|
||||||
|
| Git repo | `https://git.sysloggh.net/SyslogSolution/zulip-platform-plugins.git` | ✅ Verified |
|
||||||
|
| Default branch | `feat/zulip-streaming` | ✅ Verified |
|
||||||
|
| Bundled adapter path | `<HERMES_HOME>/hermes-agent/plugins/platforms/zulip/` | ✅ Verified |
|
||||||
|
| Adapter files | `__init__.py`, `adapter.py`, `plugin.yaml` | ✅ Verified |
|
||||||
|
| Strip-html commit | `55ca15d` (minimum) | ✅ Verified |
|
||||||
|
|
||||||
|
## Execution
|
||||||
|
|
||||||
|
### Step 1: Resolve Target
|
||||||
|
|
||||||
|
Map `target` to host, CT ID, hermes_home, and user from the live-state table.
|
||||||
|
For CT112 and CT111, route through `ssh root@amdpve` then `pct exec <id>`.
|
||||||
|
|
||||||
|
### Step 2: Pull Latest Plugin Source
|
||||||
|
|
||||||
|
On the target host:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Ensure deploy scratch space
|
||||||
|
mkdir -p /tmp/zulip-deploy
|
||||||
|
cd /tmp/zulip-deploy
|
||||||
|
|
||||||
|
# Clone or pull
|
||||||
|
if [ -d zulip-platform-plugins ]; then
|
||||||
|
cd zulip-platform-plugins
|
||||||
|
git fetch origin
|
||||||
|
git checkout {{branch}}
|
||||||
|
git pull origin {{branch}}
|
||||||
|
else
|
||||||
|
git clone --branch {{branch}} \
|
||||||
|
https://git.sysloggh.net/SyslogSolution/zulip-platform-plugins.git
|
||||||
|
cd zulip-platform-plugins
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Capture installed version
|
||||||
|
INSTALLED_SHA=$(git rev-parse HEAD)
|
||||||
|
echo "Installed SHA: $INSTALLED_SHA"
|
||||||
|
|
||||||
|
# Verify we're at HEAD
|
||||||
|
HEAD_SHA=$(git rev-parse origin/{{branch}})
|
||||||
|
if [ "$INSTALLED_SHA" = "$HEAD_SHA" ]; then
|
||||||
|
echo "At latest commit on {{branch}}"
|
||||||
|
else
|
||||||
|
echo "WARNING: not at HEAD — $INSTALLED_SHA vs $HEAD_SHA"
|
||||||
|
fi
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 3: Install Plugin Files
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Ensure target directory exists
|
||||||
|
mkdir -p {{hermes_home}}/hermes-agent/plugins/platforms/zulip
|
||||||
|
|
||||||
|
# Copy adapter files
|
||||||
|
cp plugins/platforms/zulip/adapter.py \
|
||||||
|
plugins/platforms/zulip/__init__.py \
|
||||||
|
plugins/platforms/zulip/plugin.yaml \
|
||||||
|
{{hermes_home}}/hermes-agent/plugins/platforms/zulip/
|
||||||
|
|
||||||
|
# Fix ownership (Tanko only — runs as jerome user)
|
||||||
|
[ "{{target}}" = "tanko" ] && chown -R jerome:jerome \
|
||||||
|
{{hermes_home}}/hermes-agent/plugins/platforms/zulip/
|
||||||
|
|
||||||
|
echo "Plugin files installed"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 4: Verify Installation
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check all three files exist
|
||||||
|
for f in __init__.py adapter.py plugin.yaml; do
|
||||||
|
if [ -f "{{hermes_home}}/hermes-agent/plugins/platforms/zulip/$f" ]; then
|
||||||
|
echo "✅ $f present"
|
||||||
|
else
|
||||||
|
echo "❌ $f MISSING"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Verify _strip_html fix
|
||||||
|
grep -q "_strip_html" {{hermes_home}}/hermes-agent/plugins/platforms/zulip/adapter.py \
|
||||||
|
&& echo "✅ _strip_html fix present" \
|
||||||
|
|| echo "❌ _strip_html MISSING — plugin may be stale"
|
||||||
|
|
||||||
|
# Show installed plugin.yaml version
|
||||||
|
grep "^version:" {{hermes_home}}/hermes-agent/plugins/platforms/zulip/plugin.yaml || true
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 5: Send Relay Success Signal
|
||||||
|
|
||||||
|
On the Abiba host (local), dispatch a relay message to the target agent:
|
||||||
|
|
||||||
|
```
|
||||||
|
ra-h-os-createRelayNode:
|
||||||
|
title: "Zulip plugin updated — {{target}}"
|
||||||
|
source: |
|
||||||
|
Plugin installed from {{branch}} @ {{INSTALLED_SHA}}
|
||||||
|
All 3 adapter files verified at {{hermes_home}}/hermes-agent/plugins/platforms/zulip/
|
||||||
|
_strip_html fix: PRESENT
|
||||||
|
Timestamp: {{timestamp}}
|
||||||
|
|
||||||
|
description: "hermes-zulip-plugin completed for {{target}} — plugin layer healthy"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 6: Report
|
||||||
|
|
||||||
|
Compile results into a single status block:
|
||||||
|
|
||||||
|
| Field | Value |
|
||||||
|
|-------|-------|
|
||||||
|
| Target | `{{target}}` |
|
||||||
|
| Branch | `{{branch}}` |
|
||||||
|
| Commit SHA | `{{INSTALLED_SHA}}` |
|
||||||
|
| Files installed | `__init__.py`, `adapter.py`, `plugin.yaml` |
|
||||||
|
| `_strip_html` | `{{present|missing}}` |
|
||||||
|
| Signal sent | `{{yes|no}}` |
|
||||||
|
|
||||||
|
## Known Failure Modes
|
||||||
|
|
||||||
|
| Symptom | Root Cause | Recovery |
|
||||||
|
|---------|-----------|----------|
|
||||||
|
| Git clone fails | No network or repo unreachable | Check VPN/network, verify repo URL |
|
||||||
|
| Permission denied on copy | Wrong user for target | Use correct user (jerome for Tanko, root for others) |
|
||||||
|
| `_strip_html` missing after install | Branch doesn't include commit `55ca15d` | Switch to `feat/zulip-streaming` branch |
|
||||||
|
| Plugin files missing after copy | Target directory doesn't exist | Ensure `mkdir -p` ran successfully |
|
||||||
|
| Relay signal fails | MCP bridge unreachable | Signal manually via `ra-h-os-createRelayNode` |
|
||||||
|
|
||||||
|
## Edge Differences from hermes-zulip-restore
|
||||||
|
|
||||||
|
| Concern | hermes-zulip-restore | hermes-zulip-plugin |
|
||||||
|
|---------|---------------------|---------------------|
|
||||||
|
| Env credential check | ✅ Full ZULIP_* verification | ❌ Out of scope |
|
||||||
|
| Gateway restart | ✅ Restarts the gateway process | ❌ Out of scope |
|
||||||
|
| Live connection test | ✅ Validates `zulip.state = connected` | ❌ Out of scope |
|
||||||
|
| Plugin deploy | ✅ Includes deploy as one step | ✅ Primary purpose |
|
||||||
|
| Version tracking | ❌ Implicit | ✅ Explicit SHA capture |
|
||||||
|
| Signal dispatch | ❌ None | ✅ Relay message to target |
|
||||||
|
|
||||||
|
For full connectivity recovery after a plugin install, chain this contract
|
||||||
|
with `hermes-zulip-restore` (skip its Step 2 to avoid redundant deploy).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Last updated**: 2026-07-08 — Created to separate plugin lifecycle from
|
||||||
|
restore workflow.
|
||||||
Reference in New Issue
Block a user