Compare commits
5 changed files with 15 additions and 33 deletions
|
|
@ -22,9 +22,9 @@ hive-c0re/ host daemon + CLI (one binary, subcommand-dispatched)
|
||||||
src/manager_server.rs manager-privileged socket (ManagerRequest)
|
src/manager_server.rs manager-privileged socket (ManagerRequest)
|
||||||
src/agent_server.rs per-sub-agent socket listener (long-poll Recv)
|
src/agent_server.rs per-sub-agent socket listener (long-poll Recv)
|
||||||
src/broker.rs sqlite Message store + intra-process broadcast
|
src/broker.rs sqlite Message store + intra-process broadcast
|
||||||
channel (`MessageEvent`) for `recv_blocking_batch` +
|
channel (`MessageEvent`) for `recv_blocking` +
|
||||||
the dashboard forwarder; hourly vacuum of
|
the dashboard forwarder; hourly vacuum of
|
||||||
acked>30d
|
delivered>30d
|
||||||
src/dashboard_events.rs unified wire-facing event channel feeding
|
src/dashboard_events.rs unified wire-facing event channel feeding
|
||||||
`/dashboard/stream`. Carries broker `Sent` /
|
`/dashboard/stream`. Carries broker `Sent` /
|
||||||
`Delivered` (mirrored by the forwarder task
|
`Delivered` (mirrored by the forwarder task
|
||||||
|
|
|
||||||
|
|
@ -8,8 +8,8 @@ claude has access to in return.
|
||||||
Each agent harness (`hive-ag3nt serve` or `hive-m1nd serve`) runs:
|
Each agent harness (`hive-ag3nt serve` or `hive-m1nd serve`) runs:
|
||||||
|
|
||||||
1. Long-poll `Recv` on its socket. The host-side broker
|
1. Long-poll `Recv` on its socket. The host-side broker
|
||||||
(`broker.rs::recv_blocking_batch`) returns immediately if there's
|
(`broker.rs::recv_blocking`) returns immediately if there's a
|
||||||
a pending message, otherwise waits up to 30 s for a broker `Sent`
|
pending message, otherwise waits up to 30 s for a broker `Sent`
|
||||||
event for this recipient.
|
event for this recipient.
|
||||||
2. Pop one message. Peek the remaining inbox depth with `Status`.
|
2. Pop one message. Peek the remaining inbox depth with `Status`.
|
||||||
3. Emit `LiveEvent::TurnStart { from, body, unread }` onto the SSE
|
3. Emit `LiveEvent::TurnStart { from, body, unread }` onto the SSE
|
||||||
|
|
|
||||||
|
|
@ -91,13 +91,7 @@ the previous process's socket release resolves itself.
|
||||||
age + claude-creds badge). Two actions: `⊕ R3V1V3` (queues a
|
age + claude-creds badge). Two actions: `⊕ R3V1V3` (queues a
|
||||||
Spawn approval; existing state is reused), `PURG3` (wipes
|
Spawn approval; existing state is reused), `PURG3` (wipes
|
||||||
state + applied dirs; `POST /purge-tombstone/{name}`).
|
state + applied dirs; `POST /purge-tombstone/{name}`).
|
||||||
4. **M3T4 1NPUTS** — inputs in `meta/flake.lock` the operator can
|
4. **M1ND H4S QU3STI0NS** — pending operator-targeted `ask`
|
||||||
selectively `nix flake update` (hyperhive first, then
|
|
||||||
`agent-<n>` rows). Checking inputs + submitting bumps the lock
|
|
||||||
in `/meta/` and rebuilds the selected agents in sequence; each
|
|
||||||
outcome reaches the manager as a `rebuilt` system event.
|
|
||||||
`POST /meta-update`.
|
|
||||||
5. **M1ND H4S QU3STI0NS** — pending operator-targeted `ask`
|
|
||||||
questions, i.e. rows with `target IS NULL` (peer-to-peer
|
questions, i.e. rows with `target IS NULL` (peer-to-peer
|
||||||
questions live in the same table but never surface here)
|
questions live in the same table but never surface here)
|
||||||
(amber pulsing border). Free-text fallback always rendered
|
(amber pulsing border). Free-text fallback always rendered
|
||||||
|
|
@ -107,23 +101,16 @@ the previous process's socket release resolves itself.
|
||||||
with `[cancelled]`. Questions with a `ttl_seconds` show a
|
with `[cancelled]`. Questions with a `ttl_seconds` show a
|
||||||
`⏳ MM:SS` chip; the host-side watchdog auto-cancels with
|
`⏳ MM:SS` chip; the host-side watchdog auto-cancels with
|
||||||
`[expired]` when the deadline fires.
|
`[expired]` when the deadline fires.
|
||||||
6. **QU3U3D R3M1ND3RS** — reminders agents have scheduled for
|
5. **0PER4T0R 1NB0X** — recent messages addressed to `operator`,
|
||||||
themselves (via the `remind` tool) but not yet delivered.
|
|
||||||
Each row shows the owner, due time, and message; a `CANC3L`
|
|
||||||
button hard-deletes (`POST /cancel-reminder/{id}`) and a
|
|
||||||
`R3TRY` button re-arms one whose delivery failed
|
|
||||||
(`POST /retry-reminder/{id}`). Backed by `GET /api/reminders`.
|
|
||||||
7. **P3NDING APPR0VALS** — the queue (see "Approval card"
|
|
||||||
below). The R3QU3ST SP4WN form lives at the top of this
|
|
||||||
section since submitting it immediately queues an approval
|
|
||||||
that lands directly below.
|
|
||||||
8. **0PER4T0R 1NB0X** — recent messages addressed to `operator`,
|
|
||||||
derived client-side from the dashboard event stream (no longer
|
derived client-side from the dashboard event stream (no longer
|
||||||
a snapshot field). Cold load seeds from
|
a snapshot field). Cold load seeds from
|
||||||
`/dashboard/history`'s 200-message backfill; subsequent
|
`/dashboard/history`'s 200-message backfill; subsequent
|
||||||
`sent` events with `to == "operator"` are appended live. Cap
|
`sent` events with `to == "operator"` are appended live. Cap
|
||||||
50, newest-first.
|
50, newest-first.
|
||||||
9. **MESS4GE FL0W** — live broker tail wrapped in a
|
6. **P3NDING APPR0VALS** — the queue. The R3QU3ST SP4WN form
|
||||||
|
lives at the top of this section since submitting it
|
||||||
|
immediately queues an approval that lands directly below.
|
||||||
|
7. **MESS4GE FL0W** — live broker tail wrapped in a
|
||||||
`.terminal-wrap` (same chrome as the per-agent terminal).
|
`.terminal-wrap` (same chrome as the per-agent terminal).
|
||||||
Cold load backfills the last ~200 messages from
|
Cold load backfills the last ~200 messages from
|
||||||
`/dashboard/history`; live frames arrive on
|
`/dashboard/history`; live frames arrive on
|
||||||
|
|
@ -279,10 +266,6 @@ not ours.
|
||||||
- `GET /api/reminders` — list pending reminders for the
|
- `GET /api/reminders` — list pending reminders for the
|
||||||
dashboard's queued-reminders panel.
|
dashboard's queued-reminders panel.
|
||||||
- `POST /cancel-reminder/{id}` — hard-delete a pending reminder.
|
- `POST /cancel-reminder/{id}` — hard-delete a pending reminder.
|
||||||
- `POST /retry-reminder/{id}` — re-arm a reminder whose delivery
|
|
||||||
failed (clears the failure state so the scheduler retries).
|
|
||||||
- `POST /meta-update` — `nix flake update` the selected
|
|
||||||
`meta/flake.lock` inputs, then rebuild the affected agents.
|
|
||||||
- `GET /dashboard/stream` — unified live event channel:
|
- `GET /dashboard/stream` — unified live event channel:
|
||||||
broker `sent` / `delivered`, plus the mutation events listed
|
broker `sent` / `delivered`, plus the mutation events listed
|
||||||
below. Each frame carries `seq`.
|
below. Each frame carries `seq`.
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@
|
||||||
//! and re-emits each `MessageEvent` as a `DashboardEvent::Sent` /
|
//! and re-emits each `MessageEvent` as a `DashboardEvent::Sent` /
|
||||||
//! `DashboardEvent::Delivered` with a freshly-stamped seq. Keeping the
|
//! `DashboardEvent::Delivered` with a freshly-stamped seq. Keeping the
|
||||||
//! broker's intra-process channel separate avoids coupling the broker
|
//! broker's intra-process channel separate avoids coupling the broker
|
||||||
//! (used by `recv_blocking_batch` inside the harness loop) to dashboard
|
//! (used by `recv_blocking` inside the harness loop) to dashboard
|
||||||
//! presentation concerns.
|
//! presentation concerns.
|
||||||
//!
|
//!
|
||||||
//! New mutation kinds (approval added/resolved, question added/answered,
|
//! New mutation kinds (approval added/resolved, question added/answered,
|
||||||
|
|
|
||||||
|
|
@ -148,10 +148,9 @@ async fn main() -> Result<()> {
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
forge::ensure_all().await;
|
forge::ensure_all().await;
|
||||||
});
|
});
|
||||||
// Periodic broker vacuum: drop fully-acked messages older
|
// Periodic broker vacuum: drop delivered messages older than
|
||||||
// than 30 days. Delivered-but-unacked rows (recoverable via
|
// 30 days. Undelivered messages are always kept (still in
|
||||||
// requeue_inflight) and undelivered rows are always kept.
|
// flight). Runs hourly; first sweep happens immediately.
|
||||||
// Runs hourly; first sweep happens immediately.
|
|
||||||
let vacuum_coord = coord.clone();
|
let vacuum_coord = coord.clone();
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
let interval_secs = 3600u64;
|
let interval_secs = 3600u64;
|
||||||
|
|
@ -179,7 +178,7 @@ async fn main() -> Result<()> {
|
||||||
// channel with a freshly-stamped seq, so the dashboard SSE
|
// channel with a freshly-stamped seq, so the dashboard SSE
|
||||||
// sees broker messages + future mutation events on one
|
// sees broker messages + future mutation events on one
|
||||||
// stream with one monotonic seq. The broker's intra-process
|
// stream with one monotonic seq. The broker's intra-process
|
||||||
// channel (used by `recv_blocking_batch`) stays untouched.
|
// channel (used by `recv_blocking`) stays untouched.
|
||||||
spawn_broker_to_dashboard_forwarder(coord.clone());
|
spawn_broker_to_dashboard_forwarder(coord.clone());
|
||||||
let dash_coord = coord.clone();
|
let dash_coord = coord.clone();
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue