Skip to content

feat(bridges): register CLI-channel config for agents/dispatch-message; retire legacy agent-ping webhook #129

@chubes4

Description

@chubes4

Summary

Each chat bridge installer (bridges/kimaki.sh, bridges/cc-connect.sh, bridges/telegram.sh) writes a CLI-channel config entry consumed by DMC's generic CLI transport runtime (separate issue: Extra-Chill/data-machine-code#412). The runtime is generic; the per-bridge config makes each transport addressable via agents/dispatch-message.

This issue also tracks retirement of the legacy /opt/agent-ping-webhook/ stack that currently fills this role on the Extra Chill VPS (and any other install using it).

Background

Today on the Extra Chill VPS, outbound dispatch to kimaki goes through:

```
data-machine flow "EC Agent Progress Ping" (every 3 days)
└─ datamachine/agent-call ability
└─ POST https://extrachill.com/agent-ping/
└─ nginx proxy → 127.0.0.1:8422
└─ /opt/agent-ping-webhook/webhook.py (Python BaseHTTPServer, systemd unit)
└─ subprocess.Popen(['kimaki','send','--channel',...,'--prompt',...])
```

The Python webhook is currently broken — it reads payload.get('prompt') but the modern agent-call payload uses task, so every dispatch returns `400 No message content`. Beyond the bug, the whole stack is architecturally wrong:

  • The Python script lives outside any plugin or repo, undeployable via homeboy.
  • It only handles kimaki (despite three bridges existing in this repo).
  • Authentication, payload shape, and process lifecycle are all hand-rolled.
  • The receiving end of an outbound dispatch should be a configured channel runtime, not an orphan service.

Proposed change

Per-bridge config write

When a bridge installs (or upgrades), it writes a channel config entry that DMC's CLI runtime consumes. Two reasonable mechanisms — pick one per the broader infrastructure model:

Option A: mu-plugin file (preferred — file-based, version-controlled-ish, no DB write)

```
$WP_PATH/wp-content/mu-plugins/wp-coding-agents-channels.php
```

Each bridge appends/replaces its block. File registers entries via the `datamachine_code_cli_channels` filter.

Option B: WP option (simpler, DB-stored)

```
wp option update datamachine_code_cli_channels '{ "kimaki": {...}, "cc-connect": {...} }' --format=json
```

Example bridge config: kimaki

```php
'kimaki' => [
'command' => '/usr/local/bin/kimaki', // resolved at install time
'args' => [ 'send', '--channel', '{recipient}', '--prompt', '{message}' ],
'detach' => true,
'timeout' => 600,
],
```

Then a data-machine flow step calls:

```
agents/dispatch-message
channel: 'kimaki'
recipient: '1476075959806590989' // discord channel id (replaces webhook URL)
message: 'Time for your check-in.'
```

…and DMC's CLI runtime shells the configured command. No HTTP, no Python, no nginx hop.

Bridges in scope

  • bridges/kimaki.sh — `channel='kimaki'`
  • bridges/cc-connect.sh — `channel='cc-connect'`
  • bridges/telegram.sh — `channel='telegram'` (this one's a 2-service bridge; map carefully — the user-facing entry is presumably `opencode-telegram`)

Each bridge's existing install hook (`bridge_install` / `__install_systemd`) is the right place for the config write.

Resolved command paths

The config's `command` should be the absolute path resolved at install time, not a PATH-dependent name. For systemd-installed bridges, this is typically:

  • VPS: `/usr/local/bin/datamachine-kimaki` (the shim already installed by `bridges/kimaki.sh`), or `/usr/local/bin/kimaki` from the global npm install.
  • Local: `$HOME/.local/bin/datamachine-kimaki` or whatever `npm ls -g kimaki` resolves to.

Bridges already know how to resolve this — they install the shim binaries themselves.

Recipient semantics per bridge

Each bridge defines what `recipient` means for it:

  • kimaki: Discord channel/guild ID (numeric string). Substituted into `--channel`.
  • cc-connect: TBD — depends on bridge's CLI surface; document in `bridges/cc-connect.sh`.
  • telegram: chat ID or username, depending on bot config.

These belong in the bridge's own README/inline docs, not in DMC.

Legacy retirement

After Extra-Chill/data-machine-code#412 + this change deploys:

  1. Reconfigure the EC Agent Progress Ping flow to use `agents/dispatch-message` (`channel=kimaki, recipient=1476075959806590989`) instead of `agent-call` posting to `https://extrachill.com/agent-ping/\`.
  2. Verify the flow runs successfully (manual run via `wp datamachine flow run 4`).
  3. Disable + remove the legacy service:
    • `systemctl disable --now agent-ping-webhook.service`
    • `rm /etc/systemd/system/agent-ping-webhook.service`
    • `rm -rf /opt/agent-ping-webhook/`
    • Remove the `location /agent-ping/` block from `/etc/nginx/sites-available/extrachill` and reload nginx.
    • Free port 8422.
    • Remove `/home/opencode/.secrets/agent-ping-token.txt` (no longer used).

Any other install of wp-coding-agents that ran the old setup with the Python webhook should follow the same retirement path. Worth checking if an `uninstall-legacy-agent-ping.sh` helper script makes sense to include in this repo.

Acceptance criteria

  • `bridges/kimaki.sh` writes a kimaki CLI-channel config entry during install/upgrade.
  • `bridges/cc-connect.sh` writes a cc-connect CLI-channel config entry during install/upgrade.
  • `bridges/telegram.sh` writes a telegram CLI-channel config entry during install/upgrade.
  • Config write is idempotent (re-running install doesn't duplicate or corrupt entries).
  • Uninstalling a bridge removes its config entry (cleanup path documented and tested).
  • No bridge mentions kimaki/cc-connect/telegram inside DMC — the channel name is the only identifier crossing the boundary.
  • Documentation in this repo's README describes the per-bridge `recipient` semantics and the `agents/dispatch-message` calling convention.
  • Legacy /opt/agent-ping-webhook/ retirement steps are documented (and ideally automated).

Related

Out of scope

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions