Files
Kigi-CLI/crates/common/kigi-interjection-core/src/buffer.rs
T
ZacharyZhang-NY a02b555e66 docs(comments): rewrite comments across all crates to the guidelines
Sweep every first-party crate source (1956 .rs files) to the project comment
guidelines: delete redundant restatements, decorative banners, change
narration, and end-of-line comments; keep and tighten the crucial ones
(invariants, bug rationale, SAFETY blocks, ported-source attribution).

No functional code changed. Every edit is proven comment-only against the
prior tree by a comment-stripping lexer (string/char/raw-string aware) plus a
separate doctest-fence check. Where removing a comment made rustfmt or clippy
want to re-lay-out adjacent code, the minimal triggering comment is restored so
code tokens stay byte-identical.

Gates green: cargo fmt --all --check (0 diffs), cargo check and cargo clippy
--workspace --all-targets (0 warnings).

Adds scripts/check_codegen_comment_guidelines.py — the enforcement gate for
these guidelines (flags banners, end-of-line comments, change narration, and
commented-out code).
2026-07-23 16:55:39 -04:00

73 lines
2.3 KiB
Rust

use serde::{Deserialize, Serialize};
use crate::events::EventQueue;
use crate::format::format_interjection;
/// Mid-turn interjection waiting for the next safe drain point.
/// `Attachment` is host-defined; core never inspects it.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct PendingInterjection<Attachment> {
pub text: String,
pub attachments: Vec<Attachment>,
}
/// Drained entry, framed as a synthetic user message.
#[derive(Debug, Clone, PartialEq)]
pub struct FormattedInterjection<Attachment> {
pub text: String,
pub attachments: Vec<Attachment>,
}
/// Queue of [`PendingInterjection`] values. Drain via [`drain_formatted`].
pub type InterjectionBuffer<Attachment> = EventQueue<PendingInterjection<Attachment>>;
/// Drain `buffer` FIFO, one synthetic user message per entry (never merged).
/// `sanitize_text` runs on raw text first (e.g. strip image placeholders);
/// pass `std::convert::identity` when none is needed.
pub fn drain_formatted<Attachment>(
buffer: &InterjectionBuffer<Attachment>,
sanitize_text: impl Fn(String) -> String,
) -> Vec<FormattedInterjection<Attachment>> {
buffer
.drain_all()
.into_iter()
.map(|entry| FormattedInterjection {
text: format_interjection(sanitize_text(entry.text)),
attachments: entry.attachments,
})
.collect()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn drain_formatted_sanitizes_wraps_and_preserves_order() {
let buf: InterjectionBuffer<()> = InterjectionBuffer::new();
buf.push(PendingInterjection {
text: "look at [SECRET] one".into(),
attachments: vec![],
});
buf.push(PendingInterjection {
text: "two".into(),
attachments: vec![],
});
let out = drain_formatted(&buf, |t| t.replace("[SECRET] ", ""));
assert!(buf.is_empty());
assert_eq!(out.len(), 2, "one message per entry, never merged");
assert!(
out[0]
.text
.contains("<user_query>\nlook at one\n</user_query>")
);
assert!(out[1].text.contains("<user_query>\ntwo\n</user_query>"));
assert!(
out[0]
.text
.starts_with("The user sent a message while you were working:")
);
}
}