feat(phase5): polish + deployment
- skill/SKILL.md: rewritten to 9 lines — 'status is automatic' - deploy-to-agents.sh: no AGENTS.md injection; deploys hook + npm install - install.sh: clean install flow; prints required env vars - deploy/status-watcher.service: systemd unit file - deploy/Dockerfile: containerized deployment (node:22-alpine) - src/live-status.js: deprecation warning + start-watcher/stop-watcher pass-through - README.md: full docs (architecture, install, config, upgrade guide, troubleshooting) - make check: 0 errors, 0 format issues - npm test: 59 unit + 36 integration = 95 tests passing
This commit is contained in:
262
README.md
262
README.md
@@ -1,28 +1,256 @@
|
||||
# OpenClaw Live Status Tool
|
||||
# Live Status v4
|
||||
|
||||
A lightweight CLI tool for OpenClaw agents to provide "Antigravity-style" live status updates in Mattermost channels (and others) without spamming.
|
||||
Real-time Mattermost progress updates for OpenClaw agent sessions.
|
||||
|
||||
## Features
|
||||
Version 4 replaces the manual v1 live-status CLI with a transparent infrastructure daemon.
|
||||
Agents no longer need to call `live-status`. The watcher auto-updates Mattermost as they work.
|
||||
|
||||
- **Live Updates:** Create a single message and update it repeatedly.
|
||||
- **Sub-Agent Support:** Works in clean environments via embedded config or CLI flags.
|
||||
- **Cross-Channel:** Supports dynamic channel targeting via `--channel`.
|
||||
- **One-Click Install:** Updates binaries, skills, and agent protocols automatically.
|
||||
## Architecture
|
||||
|
||||
## Installation
|
||||
```
|
||||
OpenClaw Gateway
|
||||
Agent Sessions
|
||||
-> writes {uuid}.jsonl as they run
|
||||
|
||||
Run the interactive installer wizard:
|
||||
status-watcher daemon (SINGLE PROCESS)
|
||||
-> fs.watch recursive on transcript directory (inotify, Node 22)
|
||||
-> Multiplexes all active sessions
|
||||
-> SessionState map: sessionKey -> { postId, pendingToolCalls, lines[] }
|
||||
-> Shared HTTP connection pool (keep-alive, maxSockets=4)
|
||||
-> Throttled Mattermost updates (leading edge + trailing flush, 500ms)
|
||||
-> Circuit breaker for API failure resilience
|
||||
-> Graceful shutdown (SIGTERM -> mark all boxes "interrupted")
|
||||
-> Sub-agent nesting (child sessions under parent status box)
|
||||
|
||||
```bash
|
||||
./install.sh
|
||||
gateway:startup hook
|
||||
-> hooks/status-watcher-hook/handler.js
|
||||
-> Checks PID file; spawns daemon if not running
|
||||
-> Daemon starts automatically with gateway
|
||||
|
||||
Mattermost API
|
||||
-> PUT /api/v4/posts/{id} (in-place edits, unlimited)
|
||||
-> Shared http.Agent (keepAlive, maxSockets=4)
|
||||
-> Circuit breaker: open after 5 failures, 30s cooldown
|
||||
```
|
||||
|
||||
## Usage
|
||||
## Install
|
||||
|
||||
```bash
|
||||
# Create a new status box
|
||||
ID=$(live-status create "Initializing...")
|
||||
### Prerequisites
|
||||
|
||||
# Update the status box
|
||||
live-status update $ID "Working..."
|
||||
- Node.js 22.x
|
||||
- OpenClaw gateway running
|
||||
- Mattermost bot token
|
||||
|
||||
### One-command install
|
||||
|
||||
```sh
|
||||
cd /path/to/MATTERMOST_OPENCLAW_LIVESTATUS
|
||||
bash install.sh
|
||||
```
|
||||
|
||||
This installs npm dependencies and deploys the `gateway:startup` hook.
|
||||
The daemon starts automatically on the next gateway restart.
|
||||
|
||||
### Manual start (without gateway restart)
|
||||
|
||||
Set required env vars, then:
|
||||
|
||||
```sh
|
||||
node src/watcher-manager.js start
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
All config via environment variables. No hardcoded values.
|
||||
|
||||
### Required
|
||||
|
||||
| Variable | Description |
|
||||
| ---------------- | ----------------------------------------------------- |
|
||||
| `MM_TOKEN` | Mattermost bot token |
|
||||
| `MM_URL` | Mattermost base URL (e.g. `https://slack.solio.tech`) |
|
||||
| `TRANSCRIPT_DIR` | Path to agent sessions directory |
|
||||
| `SESSIONS_JSON` | Path to sessions.json |
|
||||
|
||||
### Optional
|
||||
|
||||
| Variable | Default | Description |
|
||||
| ---------------------------- | ------------------------- | ------------------------------------------ |
|
||||
| `THROTTLE_MS` | `500` | Min interval between Mattermost updates |
|
||||
| `IDLE_TIMEOUT_S` | `60` | Inactivity before marking session complete |
|
||||
| `MAX_SESSION_DURATION_S` | `1800` | Hard timeout per session (30 min) |
|
||||
| `MAX_STATUS_LINES` | `15` | Max lines in status box (oldest dropped) |
|
||||
| `MAX_ACTIVE_SESSIONS` | `20` | Concurrent status box limit |
|
||||
| `MAX_MESSAGE_CHARS` | `15000` | Mattermost post truncation limit |
|
||||
| `HEALTH_PORT` | `9090` | Health endpoint port (0 = disabled) |
|
||||
| `LOG_LEVEL` | `info` | Logging level (pino) |
|
||||
| `PID_FILE` | `/tmp/status-watcher.pid` | PID file location |
|
||||
| `CIRCUIT_BREAKER_THRESHOLD` | `5` | Failures before circuit opens |
|
||||
| `CIRCUIT_BREAKER_COOLDOWN_S` | `30` | Cooldown before half-open probe |
|
||||
| `TOOL_LABELS_FILE` | _(built-in)_ | External tool labels JSON override |
|
||||
| `DEFAULT_CHANNEL` | _none_ | Fallback channel for non-MM sessions |
|
||||
|
||||
## Status Box Format
|
||||
|
||||
```
|
||||
[ACTIVE] main | 38s
|
||||
Reading live-status source code...
|
||||
exec: ls /agents/sessions [OK]
|
||||
Analyzing agent configurations...
|
||||
exec: grep -r live-status [OK]
|
||||
Writing new implementation...
|
||||
Sub-agent: proj035-planner
|
||||
Reading protocol...
|
||||
Analyzing JSONL format...
|
||||
[DONE] 28s
|
||||
Plan ready. Awaiting approval.
|
||||
[DONE] 53s | 12.4k tokens
|
||||
```
|
||||
|
||||
## Daemon Management
|
||||
|
||||
```sh
|
||||
# Start
|
||||
node src/watcher-manager.js start
|
||||
|
||||
# Stop (graceful shutdown)
|
||||
node src/watcher-manager.js stop
|
||||
|
||||
# Status
|
||||
node src/watcher-manager.js status
|
||||
|
||||
# Pass-through via legacy CLI
|
||||
live-status start-watcher
|
||||
live-status stop-watcher
|
||||
|
||||
# Health check
|
||||
curl http://localhost:9090/health
|
||||
```
|
||||
|
||||
## Deployment Options
|
||||
|
||||
### Hook (default)
|
||||
|
||||
The `gateway:startup` hook in `hooks/status-watcher-hook/` auto-starts the daemon.
|
||||
No configuration needed beyond deploying the hook.
|
||||
|
||||
### systemd
|
||||
|
||||
```sh
|
||||
# Copy service file
|
||||
cp deploy/status-watcher.service /etc/systemd/system/
|
||||
|
||||
# Create env file
|
||||
cat > /etc/status-watcher.env <<EOF
|
||||
MM_TOKEN=your_token
|
||||
MM_URL=https://slack.solio.tech
|
||||
TRANSCRIPT_DIR=/home/node/.openclaw/agents/main/sessions
|
||||
SESSIONS_JSON=/home/node/.openclaw/agents/main/sessions/sessions.json
|
||||
EOF
|
||||
|
||||
systemctl enable --now status-watcher
|
||||
```
|
||||
|
||||
### Docker
|
||||
|
||||
```sh
|
||||
docker build -f deploy/Dockerfile -t status-watcher .
|
||||
docker run -d \
|
||||
-e MM_TOKEN=your_token \
|
||||
-e MM_URL=https://slack.solio.tech \
|
||||
-e TRANSCRIPT_DIR=/sessions \
|
||||
-e SESSIONS_JSON=/sessions/sessions.json \
|
||||
-v /home/node/.openclaw/agents:/sessions:ro \
|
||||
-p 9090:9090 \
|
||||
status-watcher
|
||||
```
|
||||
|
||||
## Upgrade from v1
|
||||
|
||||
v1 required agents to call `live-status create/update/complete` manually.
|
||||
AGENTS.md contained a large "Live Status Protocol (MANDATORY)" section.
|
||||
|
||||
### What changes
|
||||
|
||||
1. The daemon handles all updates — no manual calls needed.
|
||||
2. AGENTS.md protocol section can be removed (see `docs/v1-removal-checklist.md`).
|
||||
3. `skill/SKILL.md` is now 9 lines: "status is automatic".
|
||||
4. `live-status` CLI still works for manual use but prints a deprecation notice.
|
||||
|
||||
### Migration steps
|
||||
|
||||
1. Run `bash install.sh` to deploy v4.
|
||||
2. Restart the gateway (hook activates).
|
||||
3. Verify the daemon is running: `curl localhost:9090/health`
|
||||
4. After 1+ hours of verified operation, remove the v1 AGENTS.md sections
|
||||
(see `docs/v1-removal-checklist.md` for exact sections to remove).
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
**Daemon not starting:**
|
||||
|
||||
- Check PID file: `cat /tmp/status-watcher.pid`
|
||||
- Check env vars: `MM_TOKEN`, `MM_URL`, `TRANSCRIPT_DIR`, `SESSIONS_JSON` must all be set
|
||||
- Start manually and check logs: `node src/watcher-manager.js start`
|
||||
|
||||
**No status updates appearing:**
|
||||
|
||||
- Check health endpoint: `curl localhost:9090/health`
|
||||
- Check circuit breaker state (shown in health response)
|
||||
- Verify `MM_TOKEN` has permission to post in the target channel
|
||||
|
||||
**Duplicate status boxes:**
|
||||
|
||||
- Multiple daemon instances — check PID file, kill extras
|
||||
- `node src/watcher-manager.js status` shows if it's running
|
||||
|
||||
**Session compaction:**
|
||||
|
||||
- When JSONL is truncated, the watcher detects it (stat.size < lastOffset)
|
||||
- Offset resets, status box shows `[session compacted - continuing]`
|
||||
- No crash, no data loss
|
||||
|
||||
## Development
|
||||
|
||||
```sh
|
||||
# Run all tests
|
||||
npm test
|
||||
|
||||
# Run unit tests only
|
||||
npm run test-unit
|
||||
|
||||
# Run integration tests only
|
||||
npm run test-integration
|
||||
|
||||
# Lint + format + test
|
||||
make check
|
||||
```
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
src/
|
||||
watcher-manager.js Entrypoint; PID file; graceful shutdown
|
||||
status-watcher.js JSONL file watcher (inotify)
|
||||
session-monitor.js sessions.json poller (2s interval)
|
||||
status-box.js Mattermost post manager (throttle, circuit breaker)
|
||||
status-formatter.js Status box text renderer
|
||||
circuit-breaker.js Circuit breaker state machine
|
||||
config.js Env var config with validation
|
||||
logger.js pino wrapper
|
||||
health.js HTTP health endpoint
|
||||
tool-labels.js Tool name -> label resolver
|
||||
tool-labels.json Built-in tool label defaults
|
||||
live-status.js Legacy CLI (deprecated; backward compat)
|
||||
|
||||
hooks/
|
||||
status-watcher-hook/ gateway:startup hook (auto-start daemon)
|
||||
|
||||
deploy/
|
||||
status-watcher.service systemd unit file
|
||||
Dockerfile Container deployment
|
||||
|
||||
test/
|
||||
unit/ Unit tests (59 tests)
|
||||
integration/ Integration tests (36 tests)
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user