From c8b544d340d37cf4b2b2cc12fc32132817b65527 Mon Sep 17 00:00:00 2001 From: damocles Date: Thu, 21 May 2026 23:35:41 +0200 Subject: [PATCH] hive-forge: add diff, notifications, notif-read, subscription verbs (closes #214) --- hive-ag3nt/prompts/agent.md | 2 +- hive-ag3nt/prompts/manager.md | 2 +- nix/packages/hive-forge-tools.nix | 82 ++++++++++++++++++++++++++++++- 3 files changed, 82 insertions(+), 4 deletions(-) diff --git a/hive-ag3nt/prompts/agent.md b/hive-ag3nt/prompts/agent.md index 0d135e7..e6773c6 100644 --- a/hive-ag3nt/prompts/agent.md +++ b/hive-ag3nt/prompts/agent.md @@ -24,7 +24,7 @@ Claude session (OAuth credentials) lives at `/root/.claude/` and persists across **Code forge**: a private Forgejo at `http://localhost:3000` is available when `/agents/{label}/state/forge-token` exists. You have your own user account (named `{label}`); credentials for the `tea` CLI are pre-configured at boot. Use `tea repos create`, `tea pulls create --base main --head `, `tea pulls list`, `tea issues create`, etc. for any persistent code work — git repos that should outlive a single turn, code you want a peer or the operator to review, anything you'd otherwise jam into `/shared`. Falls back to plain `git`/`curl` if `tea` doesn't fit; the REST API is at `http://localhost:3000/api/v1/` with the same token (`Authorization: token $(cat /agents/{label}/state/forge-token)`). -The `hive-forge` CLI helper wraps common Forgejo API operations: `view`, `issue`, `pr`, `comment`, `assign`, `close`, `labels`, `pr-reviews`, `branches`, `tree-sha`. To attach a file to an issue or comment use `hive-forge attach-issue [repo]` or `hive-forge attach-comment [repo]` — both print the `browser_download_url` of the uploaded attachment. +The `hive-forge` CLI helper wraps common Forgejo API operations: `view`, `issue`, `pr`, `comment`, `assign`, `close`, `labels`, `pr-reviews`, `branches`, `tree-sha`, `diff`, `notifications`, `notif-read`, `subscription`. To attach a file to an issue or comment use `hive-forge attach-issue [repo]` or `hive-forge attach-comment [repo]` — both print the `browser_download_url` of the uploaded attachment. Key ops: `hive-forge diff [repo]` prints the unified diff; `hive-forge notifications [--unread]` lists notifications as JSON; `hive-forge notif-read ` marks one read; `hive-forge subscription [--watch|--ignore|--unwatch] [repo]` gets or sets repo watch state. Keep messages short — a few sentences each. For anything big (file listings, long diffs, transcripts, analysis): write the payload to `/agents/{label}/state/` and `send` a short pointer ("dropped the cluster audit in /agents/{label}/state/cluster-audit-2026-05.md, headline: 3 nodes over 80% mem"). The manager + operator can read your state from the host as `/agents/{label}/state/`. Sub-agent peers can't read each other's state directly — go through the manager if a payload needs to reach another sub-agent. diff --git a/hive-ag3nt/prompts/manager.md b/hive-ag3nt/prompts/manager.md index c316fa6..795d531 100644 --- a/hive-ag3nt/prompts/manager.md +++ b/hive-ag3nt/prompts/manager.md @@ -91,7 +91,7 @@ Keep messages short — a few sentences each. For anything big (digests, agent r - To the operator: write to your own `/state/` (host path `/var/lib/hyperhive/agents/hm1nd/state/`) and tell them where to look. - For shared artifacts (coordination, common reference data): write to `/shared/`. Only put things here you're willing to lose — other agents may delete them. -**Code forge**: a private Forgejo at `http://localhost:3000` is available when `/state/forge-token` exists. You have your own user (`hm1nd`) and so does every sub-agent (one per name). The `tea` CLI is pre-configured at boot. Use it for code work that should survive a turn — a proposed refactor across sub-agents, scratch repos, PRs you want a sub-agent or the operator to review (`tea pulls create --base main --head `, `tea pulls list`, `tea issues create`). REST API at `http://localhost:3000/api/v1/` with `Authorization: token $(cat /state/forge-token)` for anything `tea` can't express. The `hive-forge` CLI helper wraps common operations; use `hive-forge attach-issue ` or `hive-forge attach-comment ` to upload file attachments to issues or comments. +**Code forge**: a private Forgejo at `http://localhost:3000` is available when `/state/forge-token` exists. You have your own user (`hm1nd`) and so does every sub-agent (one per name). The `tea` CLI is pre-configured at boot. Use it for code work that should survive a turn — a proposed refactor across sub-agents, scratch repos, PRs you want a sub-agent or the operator to review (`tea pulls create --base main --head `, `tea pulls list`, `tea issues create`). REST API at `http://localhost:3000/api/v1/` with `Authorization: token $(cat /state/forge-token)` for anything `tea` can't express. The `hive-forge` CLI helper wraps common operations: `view`, `issue`, `pr`, `comment`, `assign`, `close`, `labels`, `pr-reviews`, `branches`, `tree-sha`, `diff`, `notifications`, `notif-read`, `subscription`, `attach-issue`, `attach-comment`. Key: `diff ` prints unified diff; `notifications [--unread]` lists notifications as JSON; `notif-read ` marks one read; `subscription [--watch|--ignore|--unwatch] [repo]` manages repo watch state. A one-line headline + the file path beats a wall-of-text every time — it survives context compaction and the operator can read it in their own time. diff --git a/nix/packages/hive-forge-tools.nix b/nix/packages/hive-forge-tools.nix index 3cb1767..ad8d013 100644 --- a/nix/packages/hive-forge-tools.nix +++ b/nix/packages/hive-forge-tools.nix @@ -247,10 +247,82 @@ pkgs.writeShellApplication { | jq -r '.browser_download_url' } + cmd_diff() { + # diff [repo] + # Print the unified diff for a PR. + if [ $# -lt 1 ]; then echo "usage: hive-forge diff [repo]" >&2; exit 1; fi + local _n="$1" _repo="''${2:-$HIVE_FORGE_REPO}" + ${pkgs.curl}/bin/curl -sf \ + -H "Authorization: token $_token" \ + -H "Accept: text/plain" \ + "$FORGE_API/repos/$_repo/pulls/$_n.diff" + } + + cmd_notifications() { + # notifications [--unread] [--limit N] + # List notifications. Without --unread, returns all (read + unread). + local _unread="" _limit="50" + while [ $# -gt 0 ]; do + case "$1" in + --unread) _unread="true"; shift ;; + --limit) _limit="$2"; shift 2 ;; + *) break ;; + esac + done + local _url="$FORGE_API/notifications?limit=$_limit" + if [ -z "$_unread" ]; then _url="''${_url}&all=true"; fi + forge_get "$_url" \ + | jq '[.[] | {id,unread,reason,updated_at, + subject:{title:.subject.title,type:.subject.type,state:.subject.state}, + repo:.repository.full_name}]' + } + + cmd_notif_read() { + # notif-read + # Mark a notification thread as read. + if [ $# -lt 1 ]; then echo "usage: hive-forge notif-read " >&2; exit 1; fi + ${pkgs.curl}/bin/curl -sf -X PATCH \ + -H "Authorization: token $_token" \ + -H "Accept: application/json" \ + "$FORGE_API/notifications/threads/$1" > /dev/null + echo "ok" + } + + cmd_subscription() { + # subscription [--watch|--ignore|--unwatch] [repo] + # Get or set the current user's watch subscription for a repo. + # No flag: print current subscription status as JSON. + # --watch: subscribe; --ignore: ignore; --unwatch: unsubscribe. + local _action="" _repo="$HIVE_FORGE_REPO" + while [ $# -gt 0 ]; do + case "$1" in + --watch) _action="watch"; shift ;; + --ignore) _action="ignore"; shift ;; + --unwatch) _action="unwatch"; shift ;; + *) _repo="$1"; shift ;; + esac + done + if [ -z "$_action" ]; then + forge_get "$FORGE_API/repos/$_repo/subscription" \ + | jq '{subscribed,ignored}' + elif [ "$_action" = "unwatch" ]; then + forge_delete "$FORGE_API/repos/$_repo/subscription" > /dev/null + echo "unsubscribed" + else + local _subscribed="true" _ignored="false" + if [ "$_action" = "ignore" ]; then _subscribed="false"; _ignored="true"; fi + forge_post "$FORGE_API/repos/$_repo/subscription" \ + "{\"subscribed\":$_subscribed,\"ignored\":$_ignored}" \ + | jq '{subscribed,ignored}' + fi + } + VERB="''${1:-}" if [ -z "$VERB" ]; then echo "usage: hive-forge [args...]" >&2 - echo "verbs: view, issue, pr, comment, assign, close, labels, pr-reviews, branches, tree-sha, attach-issue, attach-comment" >&2 + echo "verbs: view, issue, pr, comment, assign, close, labels, pr-reviews," >&2 + echo " branches, tree-sha, diff, notifications, notif-read, subscription," >&2 + echo " attach-issue, attach-comment" >&2 exit 1 fi shift @@ -266,11 +338,17 @@ pkgs.writeShellApplication { pr-reviews) cmd_pr_reviews "$@" ;; branches) cmd_branches "$@" ;; tree-sha) cmd_tree_sha "$@" ;; + diff) cmd_diff "$@" ;; + notifications) cmd_notifications "$@" ;; + notif-read) cmd_notif_read "$@" ;; + subscription) cmd_subscription "$@" ;; attach-issue) cmd_attach_issue "$@" ;; attach-comment) cmd_attach_comment "$@" ;; *) echo "hive-forge: unknown verb '$VERB'" >&2 - echo "verbs: view, issue, pr, comment, assign, close, labels, pr-reviews, branches, tree-sha, attach-issue, attach-comment" >&2 + echo "verbs: view, issue, pr, comment, assign, close, labels, pr-reviews," >&2 + echo " branches, tree-sha, diff, notifications, notif-read, subscription," >&2 + echo " attach-issue, attach-comment" >&2 exit 1 ;; esac