diff options
Diffstat (limited to 'crates/dinggerd/src/hooks.rs')
| -rw-r--r-- | crates/dinggerd/src/hooks.rs | 43 |
1 files changed, 42 insertions, 1 deletions
diff --git a/crates/dinggerd/src/hooks.rs b/crates/dinggerd/src/hooks.rs index 1718ff8..82fa7bd 100644 --- a/crates/dinggerd/src/hooks.rs +++ b/crates/dinggerd/src/hooks.rs @@ -28,7 +28,9 @@ //! on an old extension once it is idle and off screen. //! //! It also carries the `draft` in the agent's input box ("" for none), for -//! marking a draft you left behind; never logged. +//! marking a draft you left behind; never logged. And `context`: how full +//! the agent's context window is, in percent, as pi's footer shows it ("" +//! when unknown, as right after compacting). //! //! Each line is answered with `{"ok":true}`. //! @@ -74,6 +76,8 @@ struct PaneReports { control: Option<String>, /// The draft in the agent's input box, as one line ("" for none). draft: Option<String>, + /// How full its context window is: whole percent ("" when unknown). + context: Option<String>, /// When the last report arrived. at: Option<Instant>, } @@ -172,6 +176,8 @@ struct HookParams { control: Option<String>, #[serde(default)] draft: Option<String>, + #[serde(default)] + context: Option<String>, } fn handle_stream(stream: UnixStream) { @@ -239,6 +245,7 @@ fn handle_stream(stream: UnixStream) { extension: params.extension, control: params.control, draft: params.draft, + context: params.context, }; record(params.pane_id, state, reported); wake(); @@ -253,6 +260,7 @@ struct Reported { extension: Option<String>, control: Option<String>, draft: Option<String>, + context: Option<String>, } /// The longest draft kept: enough to find an agent by it. @@ -298,6 +306,24 @@ fn record(pane_id: String, state: Option<AgentState>, reported: Reported) { if let Some(draft) = reported.draft { pane.draft = Some(draft_line(&draft)); } + if let Some(context) = reported.context { + pane.context = Some(context_percent(&context)); + } +} + +/// A reported context use as whole percent ("12.6" is "13"); "" for +/// unknown, or anything not a percentage. +fn context_percent(value: &str) -> String { + match value.trim().parse::<f64>() { + Ok(percent) if percent.is_finite() && percent >= 0.0 => format!("{:.0}", percent.min(999.0)), + _ => String::new(), + } +} + +/// How full the pane's agent's context window is ("" when unknown), if its +/// extension reports it. +pub fn context(pane_id: &str) -> Option<String> { + reports().get(pane_id).and_then(|pane| pane.context.clone()) } /// Start listening; reports accumulate for the watcher to consume. @@ -441,6 +467,21 @@ mod tests { } #[test] + fn context_use_is_kept_as_whole_percent_until_reported_again() { + let context = |text: &str| Reported { context: Some(text.into()), ..Default::default() }; + assert_eq!(super::context("%t6"), None, "an extension that does not report it"); + record("%t6".into(), None, context("12.6")); + assert_eq!(super::context("%t6").as_deref(), Some("13")); + record("%t6".into(), None, Reported::default()); + assert_eq!(super::context("%t6").as_deref(), Some("13"), "kept by a report without one"); + record("%t6".into(), None, context("")); + assert_eq!(super::context("%t6").as_deref(), Some(""), "unknown, after compacting"); + for (value, want) in [("0", "0"), ("0.4", "0"), ("97.5", "98"), ("1e9", "999"), ("-3", ""), ("NaN", ""), ("x", "")] { + assert_eq!(context_percent(value), want, "{value}"); + } + } + + #[test] fn a_draft_is_kept_as_one_short_line_until_reported_again() { let draft = |text: &str| Reported { draft: Some(text.into()), ..Default::default() }; record("%t5".into(), Some(AgentState::Idle), Reported::default()); |
