Commit graph

242 commits

Author SHA1 Message Date
damocles
748536203b refactor: split long functions per review feedback; remove all #[allow] attributes 2026-05-22 19:24:44 +02:00
damocles
bbe2112dc9 fix: use try_from for i64/u64 casts; split format_notification into helpers 2026-05-22 19:14:22 +02:00
damocles
484cea62c7 fix #265: resolve all remaining clippy warnings (cast, too_many_lines, doc nits) 2026-05-22 19:11:40 +02:00
damocles
30d82148e0 clippy: apply auto-fixable warnings across workspace (closes #265 partial) 2026-05-22 18:55:57 +02:00
damocles
4a0d08154e forge_notify: detect review requests via requested_reviewers (closes #253) 2026-05-22 16:54:29 +02:00
damocles
845fafdf1b forge_notify: show assignees and reviewers unconditionally (closes #256) 2026-05-22 16:45:41 +02:00
damocles
5c360e8293 forge_notify: filter self-notifications, detect PR reviews (closes #230, closes #231) 2026-05-22 15:29:38 +02:00
damocles
66f1568e8f apply_commit handles first-time spawns, request_spawn deprecated 2026-05-22 10:52:02 +02:00
damocles
3e098c56ff update_meta_inputs: require operator approval, rename to request_update_meta_inputs 2026-05-22 10:49:20 +02:00
damocles
597e4ba03a manager: add update_meta_inputs tool to update flake.lock on demand (closes #235) 2026-05-22 10:49:20 +02:00
iris
15e44955a8 web: clickable links in terminal rows and dashboard messages (issue #233) 2026-05-22 01:17:38 +02:00
damocles
4b51c198d5 forge_notify: add repo slug to notification header for multi-repo disambiguation 2026-05-22 00:50:19 +02:00
damocles
20bb343f27 forge_notify: add issue/PR number to header, drop repo: line, show assignee on new items (closes #225) 2026-05-22 00:50:19 +02:00
damocles
c99261b042 harness: add request_next_turn MCP tool — immediate self-continuation (closes #216) 2026-05-22 00:35:13 +02:00
damocles
de6ff3da29 hive-forge: add milestone verb (list/create/close), closes #226 2026-05-22 00:18:45 +02:00
damocles
0615b0521f hive-forge: add pr-create and issue-create verbs, closes #209 2026-05-21 23:44:27 +02:00
damocles
5de795c55f hive-forge: drop notifications/notif-read verbs — conflict with forge_notify daemon 2026-05-21 23:39:11 +02:00
damocles
c8b544d340 hive-forge: add diff, notifications, notif-read, subscription verbs (closes #214) 2026-05-21 23:35:41 +02:00
iris
f510a321df screen: add match-size — RFB SetDesktopSize to resize the remote desktop 2026-05-21 23:15:36 +02:00
damocles
717086b02d forge_notify: HIVE_FORGE_KEEP_SUBSCRIPTIONS=1 disables auto-unsubscribe 2026-05-21 22:33:35 +02:00
damocles
eb63c7ebb1 forge_notify: auto-unsubscribe from repo watches on subscribed notifications 2026-05-21 22:33:35 +02:00
damocles
6ffee8e6f6 hive-forge: add attach-issue and attach-comment verbs (closes #206) 2026-05-21 22:33:00 +02:00
damocles
da8a711a60 forge_notify: explicit open/empty state, unknown states show raw value 2026-05-21 22:27:22 +02:00
damocles
8cc6306728 forge_notify: generic type label helper, compose kind from label+state 2026-05-21 22:27:22 +02:00
damocles
13b7a94257 forge_notify: fix notification type strings and PR state detection (fixes #201) 2026-05-21 22:27:22 +02:00
damocles
0884a54960 agent page: backend-supplied links list replaces hardcoded stats/screen/forge (closes #189) 2026-05-21 20:49:34 +02:00
iris
fc3490086b agent page: assemble forge URL backend-side
Per review: build the full forge profile URL in the harness instead
of the client. /api/state now returns forge_url: Option<String>
(assembled from the request Host header — resolves against whatever
host the operator reached the page on), replacing the forge_present
bool. The JS just links forge_url when present — no client-side URL
construction.
2026-05-21 20:27:43 +02:00
iris
6ab667901d agent page: link to the agent's forge profile
Add a '⬡ forge ↗' link to the per-agent page's meta row, next to
the stats + screen links. It opens the agent's Forgejo profile
(http://<host>:3000/<label> — the per-agent forge user is named
after the agent) in a new tab.

- web_ui.rs: StateSnapshot gains forge_present, true when the
  agent's forge-token file exists in the state dir (same signal
  that tells the agent it has a forge account).
- index.html / app.js: hidden link, shown + href-filled when
  forge_present, mirroring the existing gui_enabled/screen-link
  pattern. Host comes from window.location so it works off
  whatever host the page is served from.

closes #185
2026-05-21 20:27:43 +02:00
iris
4814aaefdb fix: screen fit-to-window — lift flex auto-minimum on the canvas
PR #171 made relayoutCanvas() set canvas.style.width/height
explicitly, but the canvas is a flex item: flex items default to
min-width/min-height: auto, which resolves to the canvas's intrinsic
framebuffer resolution and clamps the JS-set display size right back
up to native — so fit mode still did nothing (#133, "still same
behavior").

Add min-width/min-height: 0 (+ flex: none) on the canvas in fit mode
so the explicit downscaled size actually sticks. Scoped to
#canvas-wrap.fit so non-fit mode keeps native size + scroll.

re #133
2026-05-21 19:40:17 +02:00
damocles
3b44410427 manager: receive forge notifications (ManagerRequest::Wake) 2026-05-21 19:05:53 +02:00
damocles
e28b0a1dab refactor: extract format_wake_prompt/now_unix/build_row into serve_common (closes #169) 2026-05-21 18:53:41 +02:00
iris
dfee0574a5 fix: screen fit-to-window actually scales the canvas (#133)
The fit toggle relied on canvas.fit { max-width/max-height: 100% }.
The canvas is a flex item, and a flex item's automatic minimum size
(min-width/min-height: auto → the replaced element's intrinsic size)
overrides max-*, so an oversized desktop never shrank — it just got
centred and clipped, looking like the toggle did nothing.

Replace the CSS approach with explicit JS sizing: relayoutCanvas()
computes a scale factor (min of width/height ratios, capped at 1 so
it never upscales) and sets canvas.style.width/height in px,
preserving aspect ratio. Recomputed on fit toggle, window resize,
and framebuffer-size (ServerInit). Pointer mapping is unaffected —
sendPointer already derives scale from getBoundingClientRect().
2026-05-21 18:45:13 +02:00
iris
4539091f3c terminal: show recv wait/max params + bash [bg] flag
recv tool-use rows rendered as a bare recv() regardless of args,
hiding whether a turn is parked on a long-poll (wait_seconds) or
draining a burst (max). fmtToolUse now surfaces both. Bash rows
gain a [bg] flag when run_in_background is set.

closes #158
2026-05-21 17:57:24 +02:00
iris
62aa3bb3ec agent icon: render on dashboard + per-agent web UI
Consumes the GET /icon endpoint from #139:

- Dashboard: each container card shows the agent's icon next to its
  name (26px). Loaded from <agent-url>/icon; onerror hides it for a
  stopped container whose web server isn't answering.
- Per-agent web UI: the agent's icon next to the page title (40px),
  and /icon as the favicon on the index, stats, and screen pages.

/icon always returns an image (configured SVG or the default
hyperhive logo), so no presence check is needed.

Closes #140
2026-05-21 15:36:58 +02:00
iris
39bd46b244 agent icon: add hyperhive.icon option + GET /icon endpoint
Foundation for the per-agent icon feature (#137).

- harness-base.nix: new hyperhive.icon option (nullable path to an
  SVG). An agent commits an SVG into its config repo and references
  it as ./icon.svg; when set it lands at /etc/hyperhive/icon.svg.
- web_ui.rs: GET /icon serves the configured SVG, falling back to the
  bundled hyperhive logo when none is set — so it always returns an
  image and consumers can hit it unconditionally.

Closes #139
2026-05-21 01:06:34 +02:00
iris
305a32220b screen: add fit-to-window toggle
Adds a 'fit' toolbar toggle on the /screen VNC viewer. When on (the
default), the canvas is CSS-scaled down to fit the browser viewport
preserving aspect ratio — no more scrolling a desktop larger than the
window. When off, the canvas renders at native resolution with scroll.
The choice persists in localStorage.

The canvas's intrinsic resolution is never touched — only its display
size. sendPointer now rescales client coordinates by the canvas
display-vs-intrinsic ratio so clicks stay accurate in fit mode (this
also fixes a latent off-by-scale bug). Toolbar buttons share a .tbtn
class for consistent styling.

Issue #133 (fit toggle now; dynamic desktop resize tracked separately).
2026-05-20 22:56:19 +02:00
iris
1f52746bd9 manager: add optional agent param to reminder RPCs
CountPendingReminders and ReminderRollup were hardcoded to
MANAGER_AGENT. Both now take agent: Option<String> — None keeps the
current behavior (manager's own), Some(name) returns that agent's
reminder stats. The broker functions already take an agent name, so
this is a thin wire-protocol change. Callers (web UI stats page,
post-turn counts) pass None.

Closes #122
2026-05-20 22:14:09 +02:00
iris
01cbd5e7cc manager prompt: update get_loose_ends docs for agent param
PR #119 changed get_loose_ends to default to the manager's own items
and accept an optional agent arg ("*" = hive-wide, "<name>" = one
agent), but the manager system prompt still described it as
"hive-wide ... no args". docs/turn-loop.md was already updated;
only manager.md was missed.
2026-05-20 22:13:25 +02:00
iris
a5ef10c10c screen: fix framebuffer height parse and stray byte consume
Two RFB protocol bugs in the /screen client:

1. ServerInit parsed framebuffer-height from byte offset 1 instead of
   2. RFB 3.8 ServerInit is width@0-1, height@2-3; u16be(b,1) mixes
   the low byte of width with the high byte of height. The wrong
   height went into the initial non-incremental FramebufferUpdate-
   Request; neatvnc feeds the client's width/height straight into
   pixman_region_union_rect un-clipped (src/server.c), so an
   out-of-range height corrupts the server damage region and pixman
   reports 'Invalid rectangle passed'.

2. FramebufferUpdate handler had a stray drainTo(1) after the 3-byte
   padding+nRects header, consuming the first byte of the first
   rectangle and desyncing every update.

Closes #128
2026-05-20 22:11:28 +02:00
iris
c10b4e26ef screen: fix MD5 rotation schedule and send root username
Two bugs found via the weston journal (issue #92):

1. MD5 rotation index used (j>>2 & 3) for the round number, which
   cycles every 4 steps instead of every 16. Verified against RFC 1321
   test vectors: md5("") was 7a1dce5b... instead of d41d8cd9... — the
   derived AES key was wrong, so the server decrypted the credentials
   to garbage. Fixed to j>>4.

2. weston's vnc_handle_auth calls getpwnam(username) and requires
   pw_uid == weston's own uid before PAM is consulted. We sent an empty
   username, which fails outright ("VNC: wrong user"). weston runs as
   root, so send username "root"; the empty password still passes via
   pam_permit.so on the weston-remote-access service.

Fixes #92
2026-05-20 21:47:27 +02:00
iris
d348ce885f manager: add optional agent param to GetLooseEnds
GetLooseEnds now takes agent: Option<String>:
- None   = manager's own loose ends (default; the bug fix)
- Some("*")    = hive-wide view (every approval/question/reminder)
- Some("name") = that agent's loose ends

The get_loose_ends MCP tool exposes this as an optional agent arg, so
the manager can still scan the whole swarm on demand. The web UI and
post-turn counts pass None (manager's own).
2026-05-20 21:44:17 +02:00
damocles
a13f63f30c forge_notify: check mark-read HTTP status, warn on non-2xx 2026-05-20 21:22:53 +02:00
iris
e7d7aef1aa screen: fix Apple-DH response byte order
rfb_apple_dh_client_msg has encrypted_credentials at offset 0 and
public_key as a flexible array at offset 128. We were sending them
in the wrong order (pub_key first), so neatvnc decrypted the wrong
bytes as credentials and sent the wrong bytes as the DH public key,
causing a mismatched shared secret and SecurityResult=1.

Fixes #92
2026-05-20 20:53:30 +02:00
iris
f9d1e69a50 stats: add 1h, 4h, 3d time range windows
Adds Hour (5-min buckets), FourHour (15-min buckets), and ThreeDay
(hourly buckets) to the Window enum, plus the matching tab buttons
in stats.html. Simplifies web_ui.rs to use Window::span_secs()
instead of a duplicate match.

Closes #25
2026-05-20 20:23:09 +02:00
damocles
5951758b35 track compacted turns separately in stats 2026-05-20 19:59:59 +02:00
damocles
de2179540a fix: enrich forge notifications with subject body and comment content 2026-05-20 19:30:28 +02:00
iris
3224178d2d screen: implement Apple-DH (type 30) auth for neatvnc 0.9 compatibility 2026-05-20 19:12:40 +02:00
damocles
cddaacd12f feat: poll forge notifications in agent harness
Closes #27
2026-05-20 17:59:56 +02:00
iris
76061eb3ae screen: reject unsupported security types with clear error instead of mishandling 2026-05-20 17:49:26 +02:00
iris
86e4f41203 screen: add RFB debug log panel for handshake diagnosis 2026-05-20 17:13:35 +02:00