refactor(hive-forge): port CLI verbs to forgejo-api
This commit is contained in:
parent
b8a3927c43
commit
4636987469
36 changed files with 1463 additions and 1153 deletions
|
|
@ -13,12 +13,12 @@
|
|||
//! `forge cli: agents keep commenting without reading prev comments`.)
|
||||
|
||||
use anyhow::Result;
|
||||
use serde_json::Value;
|
||||
use forgejo_api::structs::{NotifyGetRepoListQuery, NotifyReadThreadQuery};
|
||||
|
||||
use crate::client::Client;
|
||||
use crate::client::{Client, index, split_repo};
|
||||
|
||||
/// Forgejo's per-page notification cap.
|
||||
const PAGE_SIZE: u64 = 50;
|
||||
const PAGE_SIZE: u32 = 50;
|
||||
/// How many pages of unread notifications to scan for the thread.
|
||||
/// Notifications come newest-first and a thread the caller is about to
|
||||
/// comment on was just active, so it sits near the top; this cap keeps
|
||||
|
|
@ -26,7 +26,7 @@ const PAGE_SIZE: u64 = 50;
|
|||
/// firehose), at the cost of not detecting a match buried past
|
||||
/// `MAX_PAGES * PAGE_SIZE` unread items (degrade-open — acceptable for
|
||||
/// a courtesy guard).
|
||||
const MAX_PAGES: u64 = 5;
|
||||
const MAX_PAGES: u32 = 5;
|
||||
|
||||
/// The notification thread id of an UNREAD notification on
|
||||
/// `<repo>#<number>`, or `None` when the thread has no unread
|
||||
|
|
@ -34,24 +34,30 @@ const MAX_PAGES: u64 = 5;
|
|||
/// number can't false-match another repo. Errors only on transport /
|
||||
/// non-2xx — callers degrade open on `Err`.
|
||||
pub fn unread_thread_id(client: &Client, repo: &str, number: u64) -> Result<Option<u64>> {
|
||||
let (owner, name) = split_repo(repo)?;
|
||||
for page in 1..=MAX_PAGES {
|
||||
let v = client.get_json(&format!(
|
||||
"/repos/{repo}/notifications?all=false&page={page}&limit={PAGE_SIZE}"
|
||||
))?;
|
||||
let arr = v.as_array().cloned().unwrap_or_default();
|
||||
let len = arr.len() as u64;
|
||||
for n in &arr {
|
||||
let query = NotifyGetRepoListQuery {
|
||||
all: Some(false),
|
||||
..Default::default()
|
||||
};
|
||||
let (_, threads) = client
|
||||
.api()
|
||||
.notify_get_repo_list(owner, name, query)
|
||||
.page(page)
|
||||
.page_size(PAGE_SIZE)
|
||||
.send()?;
|
||||
for n in &threads {
|
||||
let subject_url = n
|
||||
.get("subject")
|
||||
.and_then(|s| s.get("url"))
|
||||
.and_then(Value::as_str)
|
||||
.unwrap_or("");
|
||||
.subject
|
||||
.as_ref()
|
||||
.and_then(|s| s.url.as_ref())
|
||||
.map_or("", url::Url::as_str);
|
||||
if subject_matches(subject_url, number) {
|
||||
return Ok(n.get("id").and_then(Value::as_u64));
|
||||
return Ok(n.id.and_then(|id| u64::try_from(id).ok()));
|
||||
}
|
||||
}
|
||||
// Last (short) page reached — stop.
|
||||
if len < PAGE_SIZE {
|
||||
if threads.len() < PAGE_SIZE as usize {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -62,7 +68,11 @@ pub fn unread_thread_id(client: &Client, repo: &str, number: u64) -> Result<Opti
|
|||
/// result). Clears the unread signal so a subsequent comment isn't
|
||||
/// blocked after the agent has read the thread.
|
||||
pub fn mark_thread_read(client: &Client, thread_id: u64) -> Result<()> {
|
||||
client.patch_no_content(&format!("/notifications/threads/{thread_id}"))
|
||||
client
|
||||
.api()
|
||||
.notify_read_thread(index(thread_id)?, NotifyReadThreadQuery::default())
|
||||
.send()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Reading a thread (`comments` / `view`) is the "I've seen it" signal:
|
||||
|
|
|
|||
Loading…
Reference in a new issue