clippy: apply auto-fixable warnings across workspace (closes #265 partial)
This commit is contained in:
parent
56d0b02c2f
commit
30d82148e0
18 changed files with 83 additions and 102 deletions
|
|
@ -312,24 +312,19 @@ pub fn context_window_tokens(model: &str) -> u64 {
|
|||
let m = model.to_ascii_lowercase();
|
||||
// Per-model env vars set by `hyperhive.contextWindowTokens` in Nix.
|
||||
for (key, val) in std::env::vars() {
|
||||
if let Some(suffix) = key.strip_prefix("HIVE_CONTEXT_WINDOW_TOKENS_") {
|
||||
if !suffix.is_empty() && m.contains(&suffix.to_ascii_lowercase()) {
|
||||
if let Ok(v) = val.trim().parse::<u64>() {
|
||||
if v > 0 {
|
||||
if let Some(suffix) = key.strip_prefix("HIVE_CONTEXT_WINDOW_TOKENS_")
|
||||
&& !suffix.is_empty() && m.contains(&suffix.to_ascii_lowercase())
|
||||
&& let Ok(v) = val.trim().parse::<u64>()
|
||||
&& v > 0 {
|
||||
return v;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Global override (single value, any model).
|
||||
if let Ok(s) = std::env::var("HIVE_CONTEXT_WINDOW_TOKENS") {
|
||||
if let Ok(v) = s.trim().parse::<u64>() {
|
||||
if v > 0 {
|
||||
if let Ok(s) = std::env::var("HIVE_CONTEXT_WINDOW_TOKENS")
|
||||
&& let Ok(v) = s.trim().parse::<u64>()
|
||||
&& v > 0 {
|
||||
return v;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Hard fallback for dev/test outside NixOS where env vars aren't set.
|
||||
200_000
|
||||
}
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ pub async fn run(socket: PathBuf, is_manager: bool) {
|
|||
let url = format!("{forge_url}/api/v1/user");
|
||||
fetch_json(&client, &url, &token)
|
||||
.await
|
||||
.and_then(|v| v["login"].as_str().map(|s| s.to_owned()))
|
||||
.and_then(|v| v["login"].as_str().map(std::borrow::ToOwned::to_owned))
|
||||
.unwrap_or_default()
|
||||
};
|
||||
if own_login.is_empty() {
|
||||
|
|
@ -184,7 +184,7 @@ fn truncate(s: &str, max: usize) -> String {
|
|||
/// Map a Forgejo review state to a readable action label.
|
||||
/// Returns `None` for non-review states (regular comments have no `state` field;
|
||||
/// `PENDING` means the review was saved but not submitted yet).
|
||||
/// Forgejo review states: "APPROVED", "REQUEST_CHANGES", "COMMENT", "PENDING".
|
||||
/// Forgejo review states: "APPROVED", "`REQUEST_CHANGES`", "COMMENT", "PENDING".
|
||||
fn review_state_label(state: &str) -> Option<&str> {
|
||||
match state {
|
||||
"APPROVED" => Some("approved"),
|
||||
|
|
@ -204,7 +204,7 @@ fn review_state_label(state: &str) -> Option<&str> {
|
|||
/// - New item: `[new issue #N repo] title\nurl: ...\nassignee: user`
|
||||
/// - State: `[PR merged #N repo] title\nurl: ...\nassignee: user`
|
||||
///
|
||||
/// Assignees (and, for PRs, requested_reviewers) are appended unconditionally
|
||||
/// Assignees (and, for PRs, `requested_reviewers`) are appended unconditionally
|
||||
/// on all issue/PR notifications (closes #256).
|
||||
///
|
||||
/// Number is extracted from `html_url` last path segment before any `#`.
|
||||
|
|
@ -246,10 +246,10 @@ async fn format_notification(
|
|||
|
||||
// Always fetch subject detail for assignee/reviewer metadata (#256).
|
||||
// Keeps agents informed of current ownership without a follow-up fetch.
|
||||
let subject = if !subject_api_url.is_empty() {
|
||||
fetch_json(client, subject_api_url, token).await
|
||||
} else {
|
||||
let subject = if subject_api_url.is_empty() {
|
||||
None
|
||||
} else {
|
||||
fetch_json(client, subject_api_url, token).await
|
||||
};
|
||||
|
||||
let is_pr = matches!(notif_type, "Pull Request" | "Pull");
|
||||
|
|
@ -328,10 +328,10 @@ async fn format_notification(
|
|||
// Review submission on a PR.
|
||||
let kind = format!("PR {review_label}{num}{repo}");
|
||||
let mut out = format!("[{kind}] {title}\nurl: {url}");
|
||||
if !body_text.is_empty() {
|
||||
out.push_str(&format!("\n\n{author}: {}", truncate(body_text, BODY_TRUNCATE)));
|
||||
} else {
|
||||
if body_text.is_empty() {
|
||||
out.push_str(&format!("\n\nreviewer: {author}"));
|
||||
} else {
|
||||
out.push_str(&format!("\n\n{author}: {}", truncate(body_text, BODY_TRUNCATE)));
|
||||
}
|
||||
out.push_str(&meta_suffix);
|
||||
Some(out)
|
||||
|
|
@ -457,12 +457,9 @@ async fn poll_once(
|
|||
let body_opt = format_notification(client, token, notif, own_login).await;
|
||||
|
||||
// None means self-echo — mark read silently, no delivery.
|
||||
let body = match body_opt {
|
||||
Some(b) => b,
|
||||
None => {
|
||||
mark_read(client, forge_url, token, id).await;
|
||||
continue;
|
||||
}
|
||||
let body = if let Some(b) = body_opt { b } else {
|
||||
mark_read(client, forge_url, token, id).await;
|
||||
continue;
|
||||
};
|
||||
|
||||
let delivered = if is_manager {
|
||||
|
|
@ -501,9 +498,9 @@ async fn poll_once(
|
|||
// when HIVE_FORGE_KEEP_SUBSCRIPTIONS=1 — triage and other firehose
|
||||
// consumers set this to retain broad repo visibility.
|
||||
let reason = notif["reason"].as_str().unwrap_or("");
|
||||
if !keep_subscriptions && reason == "subscribed" {
|
||||
if let Some(repo) = notif["repository"]["full_name"].as_str() {
|
||||
if !unsubbed_repos.contains(repo) {
|
||||
if !keep_subscriptions && reason == "subscribed"
|
||||
&& let Some(repo) = notif["repository"]["full_name"].as_str()
|
||||
&& !unsubbed_repos.contains(repo) {
|
||||
let unsub_url = format!("{forge_url}/api/v1/repos/{repo}/subscription");
|
||||
match client
|
||||
.delete(&unsub_url)
|
||||
|
|
@ -523,8 +520,6 @@ async fn poll_once(
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -681,7 +681,7 @@ pub async fn serve_manager_stdio(socket: PathBuf) -> Result<()> {
|
|||
|
||||
#[derive(Debug, serde::Deserialize, schemars::JsonSchema)]
|
||||
pub struct RequestInitConfigArgs {
|
||||
/// New sub-agent name (≤9 chars). Queues an InitConfig approval; on
|
||||
/// New sub-agent name (≤9 chars). Queues an `InitConfig` approval; on
|
||||
/// approval hive-c0re seeds the proposed config repo at
|
||||
/// `/agents/<name>/config/agent.nix` with the default template.
|
||||
/// After the approval the manager can edit and commit the config before
|
||||
|
|
|
|||
|
|
@ -272,11 +272,10 @@ pub async fn drive_turn(prompt: &str, files: &TurnFiles, bus: &Bus) -> TurnOutco
|
|||
// turn overflows into the reactive path. Best-effort — never changes
|
||||
// the outcome of the turn that already succeeded, but records it as
|
||||
// `Compacted` so turn stats can distinguish it from a plain `Ok`.
|
||||
if matches!(outcome, TurnOutcome::Ok) {
|
||||
if maybe_checkpoint_and_compact(files, bus).await {
|
||||
if matches!(outcome, TurnOutcome::Ok)
|
||||
&& maybe_checkpoint_and_compact(files, bus).await {
|
||||
return TurnOutcome::Compacted;
|
||||
}
|
||||
}
|
||||
outcome
|
||||
}
|
||||
|
||||
|
|
@ -528,42 +527,39 @@ async fn run_claude(prompt: &str, files: &TurnFiles, bus: &Bus) -> Result<(bool,
|
|||
if line.contains(PROMPT_TOO_LONG_MARKER) {
|
||||
flag_out.store(true, Ordering::Relaxed);
|
||||
}
|
||||
match serde_json::from_str::<serde_json::Value>(&line) {
|
||||
Ok(v) => {
|
||||
// Rate-limit detection: only fire on JSON `error` events,
|
||||
// not on arbitrary text content. An agent discussing a past
|
||||
// rate limit in its response would otherwise trigger a false
|
||||
// positive (the full conversation flows through stdout as
|
||||
// stream-json, so any text the model outputs is visible here).
|
||||
if v.get("type").and_then(|t| t.as_str()) == Some("error") {
|
||||
let raw = v.to_string();
|
||||
if RATE_LIMIT_MARKERS.iter().any(|m| raw.contains(m)) {
|
||||
rate_out.store(true, Ordering::Relaxed);
|
||||
}
|
||||
}
|
||||
if let Some(u) = crate::events::TokenUsage::from_assistant_event(&v) {
|
||||
last_inference = Some(u);
|
||||
}
|
||||
if let Some(cost) = crate::events::TokenUsage::from_stream_event(&v) {
|
||||
// Fallback to `cost` if the turn somehow produced
|
||||
// a result without any assistant event — keeps the
|
||||
// ctx badge from going stale on a degenerate turn.
|
||||
let ctx = last_inference.unwrap_or(cost);
|
||||
bus_out.record_turn_usage(ctx, cost);
|
||||
}
|
||||
bus_out.observe_stream(&v);
|
||||
bus_out.emit(LiveEvent::Stream(v));
|
||||
}
|
||||
Err(_) => {
|
||||
// Non-JSON stdout: raw text check is fine here since these
|
||||
// are claude CLI messages, not conversation content.
|
||||
if RATE_LIMIT_MARKERS.iter().any(|m| line.contains(m)) {
|
||||
if let Ok(v) = serde_json::from_str::<serde_json::Value>(&line) {
|
||||
// Rate-limit detection: only fire on JSON `error` events,
|
||||
// not on arbitrary text content. An agent discussing a past
|
||||
// rate limit in its response would otherwise trigger a false
|
||||
// positive (the full conversation flows through stdout as
|
||||
// stream-json, so any text the model outputs is visible here).
|
||||
if v.get("type").and_then(|t| t.as_str()) == Some("error") {
|
||||
let raw = v.to_string();
|
||||
if RATE_LIMIT_MARKERS.iter().any(|m| raw.contains(m)) {
|
||||
rate_out.store(true, Ordering::Relaxed);
|
||||
}
|
||||
bus_out.emit(LiveEvent::Note {
|
||||
text: format!("(non-json) {line}"),
|
||||
});
|
||||
}
|
||||
if let Some(u) = crate::events::TokenUsage::from_assistant_event(&v) {
|
||||
last_inference = Some(u);
|
||||
}
|
||||
if let Some(cost) = crate::events::TokenUsage::from_stream_event(&v) {
|
||||
// Fallback to `cost` if the turn somehow produced
|
||||
// a result without any assistant event — keeps the
|
||||
// ctx badge from going stale on a degenerate turn.
|
||||
let ctx = last_inference.unwrap_or(cost);
|
||||
bus_out.record_turn_usage(ctx, cost);
|
||||
}
|
||||
bus_out.observe_stream(&v);
|
||||
bus_out.emit(LiveEvent::Stream(v));
|
||||
} else {
|
||||
// Non-JSON stdout: raw text check is fine here since these
|
||||
// are claude CLI messages, not conversation content.
|
||||
if RATE_LIMIT_MARKERS.iter().any(|m| line.contains(m)) {
|
||||
rate_out.store(true, Ordering::Relaxed);
|
||||
}
|
||||
bus_out.emit(LiveEvent::Note {
|
||||
text: format!("(non-json) {line}"),
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -265,7 +265,7 @@ async fn screen_ws(
|
|||
}
|
||||
|
||||
/// Pure byte pump: forwards raw bytes between the WebSocket client and
|
||||
/// the VNC TCP stream. Transparent to any RFB variant (plain, VeNCrypt).
|
||||
/// the VNC TCP stream. Transparent to any RFB variant (plain, `VeNCrypt`).
|
||||
async fn relay_ws_vnc(socket: axum::extract::ws::WebSocket, vnc_port: u16) {
|
||||
// Import futures traits locally so they don't conflict with
|
||||
// tokio_stream::StreamExt used at module scope.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue