hzhang 9e43021ba5 feat(kb): dynamic-kb-* tool family + <kb-block> subblock provider
Implements the HF side of Plexum DESIGN-DYNAMIC-BLOCK.md Phase 2 — the
HarborForge knowledge-base block agents cache facts into per session.
Cross-runtime aligned with the ClawSkills workflow text (same tool
names + input schemas + return shapes will land on openclaw side later).

manifest.json:
  - 5 new dynamic-kb-* tool contracts (list-kbs / list-topics /
    list-facts / cache / evict)
  - dynamicSubblocks contract entry declaring this plugin owns
    the "kb-block" <dynamic-block> subblock

internal/kbblock/ (new):
  - Per-session storage at <PLEXUM_PROFILE_ROOT>/agents/<id>/sessions/
    <sid>/plugins/harbor-forge/kb-block.json
  - Entry carries ID (HF backend DB primary key) + KBCode + SourceTopic
    + Content + InsertSeq for §9 #4 cache-insertion-order rendering
  - Render emits <kb-fact id=N kb=<code> source=topic:<slug>>...
    </kb-fact> (no title/description per §9 #8; source attr omitted
    when empty)
  - Fade NOT applied in v1 — §9 #3 lock has fade params shared with
    memory but implementation deferred until prod data informs whether
    KB needs it; agent dynamic-kb-evict is the only eviction path
  - 11 unit tests

internal/kbclient/ (new):
  - Typed HTTP client for HarborForge.Backend KB routes verified
    against app/api/routers/knowledge.py
  - GET /knowledge-bases[?project=<code>] (list KBs)
  - GET /knowledge-bases/{kb_code}/topics (list topics)
  - GET /knowledge-bases/{kb_code}/tree (full hierarchy — ListFacts
    flattens this client-side filtered by topic ids; backend has no
    flat list-facts-in-topic route)
  - GET /knowledge-facts/{id} per fact (GetFacts batch loop)
  - Auth: plugin-level Bearer APIKey. Per-agent hf-token resolution
    is a TODO when SDK exposes secret-mgr access.

internal/tools/kb.go (new) + tools.go:
  - 5 tool functions hooked into Dispatch
  - KBDeps struct bundles Client + ProfileRoot + SessionFor + Turn
  - Cache/evict use SessionFor lookup populated by main.go's
    RenderDynamicSubblock (called per turn by host; carries sessionID)

cmd/plexum-harborforge-plugin/main.go:
  - kbClient field initialized when BackendURL + APIKey present
  - profileRoot cached for kbblock path resolution
  - agentSession sync.Map tracks agentID → sessionID; populated by
    RenderDynamicSubblock so subsequent tool calls in the same turn
    can resolve the per-session kb-block.json path
  - Implements sdkplugin.DynamicBlockProvider.RenderDynamicSubblock:
    opens kbblock for (agentID, sessionID) and returns its Render()
    body; host wraps in <kb-block>...</kb-block>

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-05 20:15:34 +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 125 KiB
Languages
Go 97.3%
Shell 1.7%
Makefile 1%