feat: add interactive chat example for cactus crate#4878
feat: add interactive chat example for cactus crate#4878twill-hq[bot] wants to merge 2 commits intomainfrom
Conversation
Simple CLI example that loads a model from a given path and lets you have a multi-turn conversation via streaming token output. Usage: cargo run -p cactus --example chat -- /path/to/model.gguf
✅ Deploy Preview for char-cli-web canceled.
|
✅ Deploy Preview for hyprnote canceled.
|
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 2 potential issues.
Bugbot Autofix prepared fixes for both issues found in the latest run.
- ✅ Fixed: Empty input exits chat instead of reprompting
- The loop now breaks only on EOF (
read_linereturning 0) while blank trimmed input usescontinueto reprompt.
- The loop now breaks only on EOF (
- ✅ Fixed: Failed completion leaves orphaned user message in history
- On completion errors the just-appended user message is popped from
messages, preventing malformed history for subsequent turns.
- On completion errors the just-appended user message is popped from
Or push these changes by commenting:
@cursor push aeeb1a6acc
Preview (aeeb1a6acc)
diff --git a/crates/cactus/examples/chat.rs b/crates/cactus/examples/chat.rs
--- a/crates/cactus/examples/chat.rs
+++ b/crates/cactus/examples/chat.rs
@@ -22,10 +22,17 @@
let _ = io::stdout().flush();
let mut input = String::new();
- io::stdin().lock().read_line(&mut input).unwrap();
+ let bytes_read = io::stdin().lock().read_line(&mut input).unwrap();
+ if bytes_read == 0 {
+ break;
+ }
let input = input.trim();
- if input.is_empty() || input == "exit" || input == "quit" {
+ if input.is_empty() {
+ continue;
+ }
+
+ if input == "exit" || input == "quit" {
break;
}
@@ -44,7 +51,10 @@
match result {
Ok(_) => messages.push(Message::assistant(&response_text)),
- Err(e) => eprintln!("Error: {e}"),
+ Err(e) => {
+ let _ = messages.pop();
+ eprintln!("Error: {e}");
+ }
}
}
}This Bugbot Autofix run was free. To enable autofix for future PRs, go to the Cursor dashboard.
|
|
||
| if input.is_empty() || input == "exit" || input == "quit" { | ||
| break; | ||
| } |
There was a problem hiding this comment.
Empty input exits chat instead of reprompting
Medium Severity
The input.is_empty() check in the break condition causes the chat loop to exit when the user simply presses Enter without typing anything. Most interactive CLI chat applications skip blank lines and re-display the prompt. This makes accidental exits too easy and contradicts the PR description which states only "exit" or "quit" trigger clean shutdown. The is_empty() condition conflates EOF handling with blank-line handling — EOF from read_line (returning Ok(0)) could be detected via the return value instead.
| match result { | ||
| Ok(_) => messages.push(Message::assistant(&response_text)), | ||
| Err(e) => eprintln!("Error: {e}"), | ||
| } |
There was a problem hiding this comment.
Failed completion leaves orphaned user message in history
Medium Severity
The user message is pushed into messages on line 32 before complete_streaming is called. If complete_streaming returns Err, the error branch only prints the error — it never removes the user message that was already appended. On subsequent turns, the conversation history contains a user message with no corresponding assistant reply, breaking the expected alternating user/assistant pattern. This corrupts multi-turn context for all future turns in the session.
- Replace manual Default impl with derive for CreateWhisperTranscriptionOptions (clippy::derivable_impls triggered by Rust 1.94) - Remove OpenAIAdapter from realtime live e2e tests since it only supports batch transcription, not RealtimeSttAdapter
|
You have used all of your free Bugbot PR reviews. To receive reviews on all of your PRs, visit the Cursor dashboard to activate Pro and start your 14-day free trial. |
|
Applied locally in /Users/yujonglee/dev/char with a smaller example-focused pass and local cleanup. |



Summary
crates/cactus/examples/chat.rscrates/cactus/tests/llm.rsUsage
Test plan
cargo check -p cactus --example chatcompiles without errorsView on Twill
Note
Low Risk
Adds a standalone example binary only; no library/API behavior changes, so risk is limited to example compilation/runtime issues.
Overview
Adds a new
cactusexample (examples/chat.rs) that runs an interactive, multi-turn CLI chat loop usingModel::complete_streaming, streaming tokens to stdout and persisting conversation history until the user exits.Written by Cursor Bugbot for commit 1ce30e5. This will update automatically on new commits. Configure here.