feat: remove active knowledge support
This commit is contained in:
+1
-25
@@ -595,7 +595,6 @@ impl App {
|
||||
self.input_history.cancel_browse();
|
||||
match kind {
|
||||
CompletionKind::File => self.input.replace_with_file_ref(start, value),
|
||||
CompletionKind::Knowledge => self.input.replace_with_knowledge_ref(start, value),
|
||||
}
|
||||
self.completion = None;
|
||||
true
|
||||
@@ -607,7 +606,6 @@ impl App {
|
||||
/// suggestion" — partial typing like `@README.` followed by
|
||||
/// Enter should chip when the popup is on `README.md`.
|
||||
///
|
||||
/// Files and Knowledge entries chipify here. Directory file entries return `false`
|
||||
/// so the caller can fall through to `apply_completion_text`
|
||||
/// for drill-in — chip-ifying a directory on Enter would strand
|
||||
/// the user with no way to inspect children.
|
||||
@@ -628,7 +626,6 @@ impl App {
|
||||
self.input_history.cancel_browse();
|
||||
match kind {
|
||||
CompletionKind::File => self.input.replace_with_file_ref(start, value),
|
||||
CompletionKind::Knowledge => self.input.replace_with_knowledge_ref(start, value),
|
||||
}
|
||||
self.completion = None;
|
||||
true
|
||||
@@ -2166,13 +2163,13 @@ impl App {
|
||||
self.blocks.push(Block::WorkerEvent { event });
|
||||
}
|
||||
session_store::SystemItem::FileAttachment { body, .. }
|
||||
| session_store::SystemItem::Knowledge { body, .. }
|
||||
| session_store::SystemItem::TaskReminder { body, .. }
|
||||
| session_store::SystemItem::Interrupt { body } => {
|
||||
self.task_store.apply_system_message_text(&body);
|
||||
self.blocks.push(Block::SystemMessage { text: body });
|
||||
}
|
||||
session_store::SystemItem::LegacyIgnored { .. } => {}
|
||||
session_store::SystemItem::LegacyKnowledgeIgnored { .. } => {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2969,24 +2966,6 @@ mod completion_flow_tests {
|
||||
assert!(app.completion.is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn outdated_completions_event_is_dropped() {
|
||||
let mut app = App::new("test".into());
|
||||
for c in "@x".chars() {
|
||||
app.insert_char(c);
|
||||
}
|
||||
let _ = app.refresh_completion();
|
||||
// Reply for a different kind shouldn't overwrite state.
|
||||
app.handle_worker_event(Event::Completions {
|
||||
kind: CompletionKind::Knowledge,
|
||||
entries: vec![CompletionEntry {
|
||||
value: "stale".into(),
|
||||
is_dir: false,
|
||||
}],
|
||||
});
|
||||
assert!(app.completion.as_ref().unwrap().entries.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn committed_user_message_survives_fresh_segment_rotation() {
|
||||
let mut app = App::new("test".into());
|
||||
@@ -3697,9 +3676,6 @@ mod completion_flow_tests {
|
||||
Segment::Text {
|
||||
content: " and ".into(),
|
||||
},
|
||||
Segment::KnowledgeRef {
|
||||
slug: "design-note".into(),
|
||||
},
|
||||
Segment::Paste {
|
||||
id: 1,
|
||||
chars: 13,
|
||||
|
||||
+6
-46
@@ -46,24 +46,11 @@ impl FileRefAtom {
|
||||
}
|
||||
}
|
||||
|
||||
/// `#<slug>` chip — confirmed completion of a Knowledge reference.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct KnowledgeRefAtom {
|
||||
pub slug: String,
|
||||
}
|
||||
|
||||
impl KnowledgeRefAtom {
|
||||
pub fn label(&self) -> String {
|
||||
format!("#{}", self.slug)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Atom {
|
||||
Char(char),
|
||||
Paste(PasteRef),
|
||||
FileRef(FileRefAtom),
|
||||
KnowledgeRef(KnowledgeRefAtom),
|
||||
}
|
||||
|
||||
impl Atom {
|
||||
@@ -74,7 +61,6 @@ impl Atom {
|
||||
Atom::Char(_) => None,
|
||||
Atom::Paste(p) => Some((Style::default().fg(Color::Magenta), p.label())),
|
||||
Atom::FileRef(r) => Some((Style::default().fg(Color::Cyan), r.label())),
|
||||
Atom::KnowledgeRef(r) => Some((Style::default().fg(Color::Green), r.label())),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -83,7 +69,7 @@ impl Atom {
|
||||
enum AtomClass {
|
||||
Word(WordKind),
|
||||
Sep,
|
||||
/// Indivisible chip — paste / file ref / knowledge ref. Word motion treats one chip as one unit; deletion
|
||||
/// Indivisible chip — paste / file ref. Word motion treats one chip as one unit; deletion
|
||||
/// removes the whole atom.
|
||||
Chip,
|
||||
}
|
||||
@@ -103,7 +89,7 @@ enum WordKind {
|
||||
fn atom_class(atom: &Atom) -> AtomClass {
|
||||
match atom {
|
||||
Atom::Char(c) => char_class(*c),
|
||||
Atom::Paste(_) | Atom::FileRef(_) | Atom::KnowledgeRef(_) => AtomClass::Chip,
|
||||
Atom::Paste(_) | Atom::FileRef(_) => AtomClass::Chip,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -195,10 +181,6 @@ impl InputBuffer {
|
||||
self.atoms
|
||||
.push(Atom::FileRef(FileRefAtom { path: path.clone() }));
|
||||
}
|
||||
protocol::Segment::KnowledgeRef { slug } => {
|
||||
self.atoms
|
||||
.push(Atom::KnowledgeRef(KnowledgeRefAtom { slug: slug.clone() }));
|
||||
}
|
||||
protocol::Segment::Unknown => {
|
||||
self.atoms
|
||||
.extend("[unknown input segment]".chars().map(Atom::Char));
|
||||
@@ -226,7 +208,6 @@ impl InputBuffer {
|
||||
Atom::Char(c) => text.push(*c),
|
||||
Atom::Paste(paste) => text.push_str(&paste.content),
|
||||
Atom::FileRef(file) => text.push_str(&file.path),
|
||||
Atom::KnowledgeRef(knowledge) => text.push_str(&knowledge.slug),
|
||||
}
|
||||
}
|
||||
text
|
||||
@@ -264,13 +245,6 @@ impl InputBuffer {
|
||||
self.cursor = start + 1;
|
||||
}
|
||||
|
||||
pub fn replace_with_knowledge_ref(&mut self, start: usize, slug: String) {
|
||||
self.atoms.drain(start..self.cursor);
|
||||
self.atoms
|
||||
.insert(start, Atom::KnowledgeRef(KnowledgeRefAtom { slug }));
|
||||
self.cursor = start + 1;
|
||||
}
|
||||
|
||||
/// Replace `atoms[start..self.cursor]` with the chars of `text`,
|
||||
/// leaving cursor at the end of the inserted run. Used by the Tab
|
||||
/// completion path: the popup-selected entry is inserted as raw
|
||||
@@ -286,7 +260,7 @@ impl InputBuffer {
|
||||
self.cursor = idx;
|
||||
}
|
||||
|
||||
/// If the cursor is currently inside a `@<typed>` / `#<typed>` /
|
||||
/// If the cursor is currently inside a `@<typed>` /
|
||||
/// `/<typed>` token that satisfies the trigger rules, return the
|
||||
/// kind, the index of the leading sigil atom, and the typed text
|
||||
/// after the sigil (sigil itself excluded).
|
||||
@@ -311,7 +285,7 @@ impl InputBuffer {
|
||||
}
|
||||
let kind = match c {
|
||||
'@' => Some(protocol::CompletionKind::File),
|
||||
'#' => Some(protocol::CompletionKind::Knowledge),
|
||||
|
||||
_ => None,
|
||||
};
|
||||
if let Some(k) = kind {
|
||||
@@ -480,7 +454,7 @@ impl InputBuffer {
|
||||
|
||||
/// Build the typed `Vec<Segment>` sent over the protocol. Adjacent
|
||||
/// `Atom::Char`s are concatenated into a single `Segment::Text`; each
|
||||
/// chip atom (`Paste` / `FileRef` / `KnowledgeRef` )
|
||||
/// chip atom (`Paste` / `FileRef`)
|
||||
/// becomes a standalone `Segment` so that clients re-rendering an
|
||||
/// `Event::UserMessage` see the same indivisible chip rather than a
|
||||
/// flattened string.
|
||||
@@ -510,12 +484,6 @@ impl InputBuffer {
|
||||
path: r.path.clone(),
|
||||
});
|
||||
}
|
||||
Atom::KnowledgeRef(r) => {
|
||||
flush_text(&mut buf, &mut out);
|
||||
out.push(protocol::Segment::KnowledgeRef {
|
||||
slug: r.slug.clone(),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
if !buf.is_empty() {
|
||||
@@ -1028,14 +996,6 @@ mod completion_prefix_tests {
|
||||
assert_eq!(prefix, "sr");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hash_sigil_triggers_knowledge_completion() {
|
||||
let buf = buf_from("#abc");
|
||||
let (kind, _, prefix) = buf.pending_completion_prefix().unwrap();
|
||||
assert_eq!(kind, CompletionKind::Knowledge);
|
||||
assert_eq!(prefix, "abc");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn newline_before_cursor_invalidates_trigger() {
|
||||
let buf = buf_from("@a\nbc");
|
||||
@@ -1234,7 +1194,7 @@ mod word_motion_tests {
|
||||
for a in &buf.atoms {
|
||||
match a {
|
||||
Atom::Char(c) => out.push(*c),
|
||||
Atom::Paste(_) | Atom::FileRef(_) | Atom::KnowledgeRef(_) => out.push_str("<P>"),
|
||||
Atom::Paste(_) | Atom::FileRef(_) => out.push_str("<P>"),
|
||||
}
|
||||
}
|
||||
out
|
||||
|
||||
@@ -965,7 +965,7 @@ fn push_padded_lines(lines: &mut Vec<Line<'static>>, text: &str, kind: MessageKi
|
||||
/// Render `Block::UserMessage` from typed segments. Each non-text
|
||||
/// segment renders as a one-piece chip whose colour matches the input
|
||||
/// area's chip presentation (paste = magenta, `@` file = cyan,
|
||||
/// `#` knowledge = green, `/` workflow = yellow), so the user
|
||||
/// `/` workflow = yellow), so the user
|
||||
/// recognises their own typed atoms in the scrollback.
|
||||
fn render_user_message(
|
||||
lines: &mut Vec<Line<'static>>,
|
||||
@@ -1097,7 +1097,6 @@ fn chip_span_for(seg: &Segment, fallback: Style) -> (Style, String) {
|
||||
format!("[Clipboard #{id} | {chars} chars, {line_count} lines]"),
|
||||
),
|
||||
Segment::FileRef { path } => (Style::default().fg(Color::Cyan), format!("@{path}")),
|
||||
Segment::KnowledgeRef { slug } => (Style::default().fg(Color::Green), format!("#{slug}")),
|
||||
Segment::Unknown => (fallback, "[unknown segment]".to_owned()),
|
||||
}
|
||||
}
|
||||
@@ -1112,7 +1111,6 @@ fn segment_display_text(seg: &Segment) -> String {
|
||||
id, chars, lines, ..
|
||||
} => format!("[Clipboard #{id} | {chars} chars, {lines} lines]"),
|
||||
Segment::FileRef { path } => format!("@{path}"),
|
||||
Segment::KnowledgeRef { slug } => format!("#{slug}"),
|
||||
Segment::Unknown => "[unknown segment]".to_owned(),
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user