hzhang 046a7753e6 log monitor push start + slow heartbeat
First successful push emits an info-level "monitor push started" so
operators can confirm the loop wired up correctly. Subsequent
successes log every 60 cycles ("monitor push heartbeat") so the
journal stays quiet but still proves the loop isn't dead. Errors
already log at warn; this fills the success-side gap so a silent
journal can't hide a "no successes, no errors" pathology.
2026-06-03 13:13:33 +01:00

HarborForge.PlexumPlugin

Plexum-side equivalent of HarborForge.OpenclawPlugin: exposes Plexum-side telemetry to the HarborForge Monitor bridge, drives the HarborForge Calendar scheduler, and gives agents a tool surface for the same calendar lifecycle actions OpenClaw agents had.

Part of the HarborForge platform; tracked as a git submodule of the HarborForge umbrella repo.

  • Plugin id: harbor-forge (matches the OpenClaw counterpart so the backend's per-plugin schemas don't fork)
  • Plugin version: 0.1.0
  • Activation: eager — Monitor bridge + Calendar scheduler must be running before any agent turn fires
  • Plexum SDK version: requires Plexum-sdk-go with HostAPI.WakeAgent (commit 216cf21 or later)

What it does

  • Monitor push loop — when monitor_push_enabled: true, posts a flat telemetry payload (cpu/mem/disk/swap/load + per-agent state) to <backendUrl>/monitor/server/heartbeat every monitor_push_interval_seconds. This replaces the standalone harborforge-monitor daemon — the plugin's lifecycle (gateway start/stop) bounds the loop, so a separate supervisor isn't needed. Use the same apiKey value the standalone monitor's HF_MONITER_API_KEY carried.
  • Monitor bridge (optional) — HTTP server on 127.0.0.1:<monitor_port> that responds to /telemetry with a Snapshot. Useful when the standalone monitor is still present and you want it to enrich its push payload from the plugin's view of agents. Disable by setting monitor_port: 0.
  • Calendar scheduler — heartbeats <backendUrl>/calendar/agent/ heartbeat every interval, receives any TimeSlots due to fire, and dispatches them through HostAPI.WakeAgent (state-aware queue with depth-1 replace-newest)
  • 9 harborforge_ tools* mirroring the OpenClaw plugin's surface
Tool Use
harborforge_status resolved config + Monitor bridge health + Calendar status + telemetry snapshot
harborforge_telemetry fresh system + agent metrics
harborforge_monitor_telemetry last bridge query timing + last snapshot served
harborforge_calendar_status active slot(s) + history + heartbeat clock
harborforge_calendar_complete mark active slot completed (+optional summary)
harborforge_calendar_abort mark active slot aborted (+optional reason)
harborforge_calendar_pause pause active slot (non-terminal)
harborforge_calendar_resume resume a paused slot
harborforge_restart_status backend restart-pending flag + last poll time

Install

git clone --recurse-submodules https://git.hangman-lab.top/zhi/HarborForge.PlexumPlugin
cd HarborForge.PlexumPlugin
bash scripts/install.sh   # or:  make install

Then in ~/.plexum/plexum.json:

{
  "plugins": {
    "allow": [
      ".",
      "harbor-forge"
    ]
  }
}

And configure at ~/.plexum/plugins/harbor-forge/config.json:

{
  "backendUrl": "https://hf-api.hangman-lab.top",
  "identifier": "server-t3",
  "apiKey": "g1_xxx",
  "monitor_push_enabled": true,
  "monitor_push_interval_seconds": 30,
  "monitor_port": 0,
  "calendar_enabled": true,
  "calendar_heartbeat_interval_seconds": 30
}

Replacing the standalone harborforge-monitor container: lift the container's HF_MONITER_API_KEY into apiKey, set monitor_push_enabled: true, then docker rm -f harborforge-monitor once you've confirmed the plugin's pushes are landing (the backend's server_states.last_seen_at should keep advancing without the container running).

Restart the host (systemctl --user restart plexum) and verify:

plexum plugin-list | grep harbor
curl -s http://127.0.0.1:9100/health
curl -s http://127.0.0.1:9100/telemetry | jq .agents

How calendar wake works

When the backend returns a slot_to_fire in a heartbeat response:

  1. Scheduler builds the message from slot.wake_options.override_message or falls back to slot.prompt
  2. host.WakeAgent({agent_id, message, source: "calendar:slot-<id>"})
  3. Plexum host-side wake.Manager:
    • if agent's sm-state is idle → runs the turn synchronously in a goroutine against the agent's wake session
    • else → enqueues (depth 1; new wake replaces any pending one)
    • drains automatically when the running turn returns
  4. The source tag lands on the turn's faithful event so retros can tell which slot caused which turn

The agent uses harborforge_calendar_complete / _abort / _pause / _resume mid-turn to push status back to the backend.

Layout

HarborForge.PlexumPlugin/
├── manifest.json                    # plugin manifest (eager, 9 tools)
├── go.mod                           # → Plexum-sdk-go (replace ../)
├── cmd/plexum-harborforge-plugin/   # main entry (Serve + Init)
├── internal/config/                 # config.json schema + Resolve
├── internal/telemetry/              # /proc-based snapshot collector
├── internal/monitor/                # HTTP bridge for HF.Monitor
├── internal/calendar/               # types + backend client + scheduler
├── internal/tools/                  # 9 tool implementations
└── scripts/install.sh               # build + drop into ~/.plexum/plugins

Differences vs OpenClaw equivalent

OpenClaw plugin Plexum plugin
api.registerTool(factory) runtime ToolPlugin.CallTool + manifest contract
api.spawn({agentId, task}) HostAPI.WakeAgent({agent_id, message, source}) (state-aware queue)
api.getAgentStatus() HostAPI.ReadAgentState(ctx, agent_id)
--install-monitor / --install-cli flags n/a — Monitor + hf CLI deploy separately (e.g. via HangmanLab.Server.T3 docker compose)
TS source compiled by tsc static Go binary built per-platform
Description
Plexum-side equivalent of HarborForge.OpenclawPlugin — telemetry, monitor bridge, calendar scheduler, harborforge_* tools
Readme 98 KiB
Languages
Go 96%
Shell 2.5%
Makefile 1.5%