Commit graph hyperhive/hive-agent
Author SHA1 Message Date
damocles
c42d02e12a prompts: collapse tool bullet list to avoid duplicating mcp descriptions 2026-07-26 17:33:41 +02:00
damocles
aedfd512c6 prompts: stop steering agents to busy-wait on recv when idle 2026-07-26 16:46:56 +02:00
atlas
31008c83df feat: pause an agent's turn loop without stopping its container
A paused agent keeps its container, its claude session and its
dashboard/todo servers up, but stops driving turns. Messages queue
unacked and are drained on resume.

The whole protocol is a single marker file, `<harness>/paused`. That
directory is already a bind-mount shared between host and container, so
both sides just stat the same path: the harness reads it to decide
whether to drive a turn, hive-c0re reads it to render the badge and
writes/removes it for `hivectl pause|resume`. No new wire protocol, no
container round-trip, and it is sticky across restarts by construction.

Not calling `recv_next` while paused *is* the queueing semantic, so
there is no fencing to get wrong: reminders buffer in their unbounded
channel, the todo `Notify` permit coalesces, and a `request_next_turn`
that raced the pause survives because the gate sits above
`self_continue.take()`.

Graceful stop is handled host-side rather than in the harness: a paused
agent provably has no turn in flight, so `run_signal` skips the fence
entirely instead of eating the full `GRACEFUL_STOP_TIMEOUT` waiting for
a checkpoint turn that will never run.

`paused` is reported on `ContainerView` / `AgentStatusRow` for the
dashboard, orthogonal to `running` and reported for stopped containers
too.

Closes: hyperhive/hyperhive issue 2271
2026-07-26 03:11:33 +02:00
damocles
7b2645078a fix(#2635): close review nits on the questions mirror (inc2 pt2) 2026-07-26 02:07:33 +02:00
damocles
e5ef5a72be feat(#2635): wire harness-local questions mirror (inc2 pt2) 2026-07-26 02:07:33 +02:00
damocles
9471201698 feat(#2635): add harness-local questions mirror store (inc2 pt2, unwired) 2026-07-26 02:07:33 +02:00
damocles
001ea38ea4 gate stale todo wakes on an emptiness check (#2678) 2026-07-25 22:28:38 +02:00
damocles
2316287327 remove hive-agent-wake — no shipped consumer 2026-07-25 20:05:32 +02:00
damocles
6c886d3fa6 hive-agent: inline todo dispatch arms instead of a sub-match + unreachable!
per mara's review on #2679: replace the separate dispatch_todo sub-match
(with its trailing unreachable! arm) with four small handler functions
called directly from dispatch's existing match. same behavior, no
unreachable! left in the todo path.
2026-07-25 18:42:10 +02:00
damocles
2dcbb78b40 hive-agent: add debug logging around todo upsert/clear/mark-done
diagnostic instrumentation for #2678 (phantom 'you have todos' wakes
after clearing bash-task todos). logs subsystem/key/id/changed on
UpsertTodo, subsystem/key/all/count on ClearTodo, id/count on
MarkTodoDone, and a marker when the serve loop actually consumes a
todo_wake notification. no behavior change - RUST_LOG=debug only.
2026-07-25 17:40:11 +02:00
damocles
c4fcf7fbf1 feat(#2659): serve hive-bash-mcp over persistent streamable-http, drop stdio bridge 2026-07-23 18:01:20 +02:00
damocles
29f45ddd48 docs(#2627): crate READMEs for the harness column (hive-agent, hive-agent-mcp, hive-agent-wake, hive-bash-mcp) 2026-07-23 16:41:05 +02:00
damocles
a7f0f3d231 fix(#2635): drop obsolete todos_db/reminders_db path aliases 2026-07-23 15:05:19 +02:00
damocles
c316dc852d feat(#2635): consolidate todos + reminders into one hyperhive-state.sqlite 2026-07-23 15:05:19 +02:00
damocles
e9df5def02 add agent-facing compact tool gated on context usage 2026-07-23 12:34:20 +02:00
damocles
ee072149c9 fix(#2038): don't treat MCP 'pending' status as degraded
pending is the claude CLI's normal init-event race for a freshly
spawned stdio server (status reported before the handshake completes,
then flips to connected moments later in the same turn — see
anthropics/claude-agent-sdk-typescript#368). flagging it fired on
nearly every turn for all three configured servers with zero actual
impact, which is why #2038's persistent-vs-one-turn repro question
looked answered when it wasn't — that was this false positive, not
the real bug.
2026-07-23 07:47:56 +02:00
damocles
dcb2b79715 strip issue-tag comments from #2635 inc1 commits per hive-rules 2026-07-23 00:12:30 +02:00
damocles
e11e8294a3 repoint post_turn_counts + dedup web_ui stats onto todo_server::dial (#2635 inc 1) 2026-07-23 00:12:30 +02:00
damocles
8b35b8c4af repoint per-agent stats reminder rollup off the broker (#2635 inc 1) 2026-07-23 00:12:30 +02:00
damocles
ecd9030305 wire reminder ops into the in-agent socket dispatch (#2635 inc 1) 2026-07-23 00:12:30 +02:00
damocles
174e277340 add reminder delivery timer + main.rs wiring (#2635 inc 1) 2026-07-23 00:12:30 +02:00
damocles
92276e4e14 add harness-local reminder store (#2635 inc 1) 2026-07-23 00:12:30 +02:00
iris
d0ac48299a fix(#2632): drop stale /api/bash-tasks reference from api_todos doc 2026-07-22 18:02:01 +02:00
iris
88f17320b6 fix(#2632): remove /api/loose-ends endpoint; drop refreshLooseEnds (address argus/mara review)
Both old endpoints removed. refreshLooseEnds() call sites cleaned up;
lastLooseEnds stays as empty [] for reconcileAskBinds (no-op now that
the loose-ends source is gone).
2026-07-22 18:02:01 +02:00
iris
3780f674f4 fix(#2632): remove /api/bash-tasks endpoint (address mara review) 2026-07-22 18:02:01 +02:00
iris
4905b688be feat(#2632): switch agent page loose-ends pill to todos; remove bash-tasks pill
- Add GET /api/todos backend endpoint (connects to HIVE_AGENT_SOCKET,
  calls ListTodos, returns { todos: [...] } — LooseEnd::Todo items).
- Register route in web_ui/mod.rs.
- index.html: replace loose-ends pill (🪢) + bash-tasks pill (⚙)
  with a single todos pill (📋, id=todos-pill).
- agent.css: add .header-pill-todos count colour (green, same as old tasks).
- app.js:
  - refreshTodos() fetches /api/todos, drives renderTodos/buildTodosList.
  - refreshLooseEnds() becomes background-only (no pill); still drives
    reconcileAskBinds for inline ask-form wiring.
  - Remove refreshBashTasks / buildBashTasksList / renderBashTasks.
  - Cold-load and turn_end both call refreshTodos; 4s interval replaces
    the old bash-tasks interval.
2026-07-22 18:02:01 +02:00
damocles
3188e50ab8 docs(#2628): update bash tool descriptions, docs, and system prompt for the todo model (trim impl details for agent) 2026-07-22 17:34:12 +02:00
damocles
7be37f388e fix(#2628): forge_notify falls back to default_agent_socket when hive_agent_socket unset (argus review) 2026-07-22 00:01:12 +02:00
damocles
1e1ca50da3 feat(#2626): migrate forge_notify to the in-agent todo socket (per-thread todos, not wakes) 2026-07-21 00:47:07 +02:00
damocles
86d16efa07 feat(#2569): drive a turn on a local todo signal (serve-loop select) 2026-07-20 23:29:26 +02:00
damocles
713d7f424c feat(#2569): serve the in-agent todo socket from the harness 2026-07-20 23:29:26 +02:00
damocles
993e0bbd4a feat(#2569): add the harness-local todo store 2026-07-20 23:29:26 +02:00
damocles
795dd882bb refactor(#2569): rename hive-agent-sock to hive-core-agent-sock 2026-07-20 21:58:28 +02:00
iris
35611e9f0d feat(#2608): show session count in agent stats window
Adds a 'sessions' chip to the per-agent stats summary panel showing how
many fresh claude sessions started within the selected time window.

Backend (hive-agent/src/stats.rs):
- New optional field `session_count: Option<u64>` on `Snapshot`
  (skip_serializing_if = None — inert-until-data, same pattern as
  first_turn_ctx). Counts rows in the `sessions` table whose
  started_at falls within the window; returns None when the table
  doesn't exist on an older db.
- New `read_session_count(conn, from)` helper (rusqlite::Result so the
  caller maps Err to None).
- Extracted per-row accumulation loop into `TurnAccum` struct +
  `push()` method to keep `snapshot()` under the too_many_lines limit.

Frontend (frontend/packages/agent/src/stats.js):
- New 'sessions' chip added to renderSummary, guarded by
  `typeof s.session_count === 'number'`, placed before the
  existing first-turn-ctx chip.
2026-07-20 19:14:32 +02:00
iris
b25c44f7cb feat(#2196): move send/ask/answer body to backend _body field
The three message-bearing hyperhive tools (send, ask, answer) previously
had named JS branches in renderRichToolUse that each:
- computed a summary string (recipient / line count)
- rendered the body text via detailsOpenMd (marked + DOMPurify)

This commit moves the body text and summary string to the backend,
reducing the JS dispatch table to a single generic markdown path.

Backend (stream_enrich.rs):
- rich_tool_body: new 'markdown' body_type for send/ask/answer —
  stamps _body with input.body / input.question / input.answer
- fmt_hyperhive_message_tool: new helper formats _summary as
  'send* → to' / 'ask* → to' / 'answer* #id' with ' · NL' when
  the body spans multiple lines; extracted out of fmt_hyperhive_tool
  to keep it under the too_many_lines limit
- doc: updated rich_tool_body docstring to list the new 'markdown' type

Frontend (app.js):
- Remove the three named branches (send/ask/answer) from renderRichToolUse
- Extend the generic _body path: 'markdown' type calls detailsOpenMd
- The ask-form slot logic (operator inline-answer binding) is preserved
  within the markdown branch, now reading the question from c._body
  instead of input.question — DOM mounting remains client-side
2026-07-20 19:13:43 +02:00
damocles
4287435696 chore(#2038): scope observe_mcp_health to pub(crate) per review 2026-07-20 18:24:06 +02:00
damocles
d7d46d347c feat(#2038): surface degraded mcp servers at turn start (observability) 2026-07-20 18:03:58 +02:00
iris
d4215c09c8 stream_enrich: document Write absence; skip -0 count in Edit summary 2026-07-19 18:53:51 +02:00
iris
0e4b69dd20 feat(#2196): move Write/Edit diff body to backend, drop JS branch
- fmt_builtin_tool: Edit gets its own arm computing `-N +M` line counts
  in _summary (was shared with Read/Write as bare file-path).
- is_rich_tool: drop Write (content is huge/one-sided; flat _summary row
  is correct); Edit stays rich since it has an old/new diff.
- rich_tool_body: now returns Option<(String, &'static str)> where the
  second field is the body type ('diff' or 'plain'). Edit arm builds the
  '-'/'+ ' prefixed diff body; mcp__bash__run gets type 'plain'.
- enrich_tool_use_entry: stamps both _body and _body_type.

Frontend (app.js):
- Remove the Write/Edit branch from renderRichToolUse (~25 lines).
- Generic _body path now dispatches on _body_type: 'diff' ->
  api.detailsDiff (colour-coded spans), default -> api.details.
  No tool-specific JS remains for file diff rendering.
2026-07-19 18:53:51 +02:00
damocles
da056d0043 fix(#2593): mark forge notifications read on broker-delivery 2026-07-19 18:41:51 +02:00
iris
b62652c01b feat(#2196): stamp _body on mcp__bash__run, drop tool-specific JS branch
Backend now stamps `_body` (full `$ <cmd>`) alongside `_summary` (first
line) and `_category: "rich"` for mcp__bash__run tool_use entries. The
frontend drops the mcp__bash__run-specific branch in renderRichToolUse
and uses a generic `if (c._body)` path instead — api.details() with the
backend-computed summary and body, no JS knowledge of the tool name.
2026-07-19 18:16:46 +02:00
iris
0f5367f948 frontend/agent: drop JS dispatch tables, read backend _icon/_summary/_category
Phase 2 of hyperhive#2196. The backend now pre-computes enrichment fields
on every SSE event (stream_enrich.rs); the frontend reads them directly
instead of running its own dispatch logic.

Removed (~330 lines of JS):
- fmtArgsGeneric / TOOL_ICONS / toolIcon / fmtRoom / fmtUser / fmtToolUse

renderStream changes:
- system events: dispatch on v._category (drop/thinking_tok/note/details)
  + v._summary / v._body instead of per-subtype if-chains; status tick
  still overrides label client-side when stateName === 'compacting' since
  elapsed time is a wall-clock value the backend cannot know at emit time
- tool_use: use c._category === 'rich' for rich-renderer routing,
  c._icon / c._summary for flat rows

renderRichToolUse: toolIcon(name) -> c._icon (from backend enrichment)

stream_enrich.rs: also stamp _category: 'drop' on top-level
type=result / type=rate_limit_event so the frontend can use a single
_category check instead of separate type-based early returns
2026-07-19 17:51:12 +02:00
iris
ae3f011eb3 hive-agent: add stream_enrich module — stamp _icon/_summary/_category on SSE events
Move per-message rendering logic from frontend JS to backend Rust.
A new stream_enrich::enrich() function stamps display fields onto
LiveEvent::Stream payloads at SSE-emit time (both live tail and history
replay), so the frontend can consume pre-computed fields instead of
re-implementing the dispatch logic in JavaScript.

Phase 1: backend stamps _icon/_summary/_category; client falls back to
its own JS tables when absent. Zero user-visible change.

- system events: _category (drop/thinking_tok/note/details) + _summary
  and optional _body (commands_changed expands to a slash-cmd list)
- assistant tool_use entries: _icon + _summary per tool; rich tools
  (Write, Edit, send, ask, answer) get _category: 'rich'
- enrichment applied in web_ui/stream.rs at emit time; DB stores raw
  events so no migration is needed when enrichment logic changes
- idempotent: existing _-prefixed fields are left unchanged
2026-07-19 17:32:35 +02:00
damocles
144912f8e0 address review: drop backwards-compat request/response aliases, use canonical names 2026-07-19 15:53:09 +02:00
damocles
d0beec8a40 refactor(#2581): carve per-agent mcp.sock protocol into hive-agent-sock crate 2026-07-19 15:53:09 +02:00
damocles
089abf89b4 fix(#2565): lenient local notification struct in forge_notify so forgejo schema drift can't drop notifications 2026-07-17 16:28:37 +02:00
damocles
f902592e71 forge_notify: append a comment racing the merge instead of dropping it (#2507) 2026-07-16 12:44:06 +02:00
damocles
6aa7c9613b fix(#2495): surface [PR merged] on merge notifications instead of [comment on PR] 2026-07-15 21:36:22 +02:00
damocles
3f1643c594 refactor(#2464): rename hive-ag3nt crate to hive-agent, collapse lib into main 2026-07-15 16:09:39 +02:00