feat: Backend cancellation support for interrupting model responses
Merged from feature/interrupt-on-type branch. Backend cancellation infrastructure: - Added tokio watch channel to SessionState for cancellation signaling - Implemented cancel_chat command - Modified chat command to use tokio::select! for racing requests vs cancellation - When cancelled, HTTP request to Ollama is dropped and returns early - Added tokio dependency with sync feature Story updates: - Story 13: Updated to use Stop button pattern (industry standard) - Story 18: Created placeholder for streaming responses - Stories 15-17: Placeholders for future features Frontend changes: - Removed auto-interrupt on typing behavior (too confusing) - Backend infrastructure ready for Stop button implementation Note: Story 13 UI (Stop button) not yet implemented - backend ready
This commit is contained in:
@@ -20,6 +20,7 @@ export function Chat({ projectPath, onCloseProject }: ChatProps) {
|
||||
const [availableModels, setAvailableModels] = useState<string[]>([]);
|
||||
const messagesEndRef = useRef<HTMLDivElement>(null);
|
||||
const inputRef = useRef<HTMLInputElement>(null);
|
||||
const lastMessageCountRef = useRef(0);
|
||||
|
||||
useEffect(() => {
|
||||
invoke<string[]>("get_ollama_models")
|
||||
@@ -75,6 +76,7 @@ export function Chat({ projectPath, onCloseProject }: ChatProps) {
|
||||
setMessages(newHistory);
|
||||
setInput("");
|
||||
setLoading(true);
|
||||
lastMessageCountRef.current = newHistory.length; // Track message count when request starts
|
||||
|
||||
try {
|
||||
const config: ProviderConfig = {
|
||||
@@ -461,7 +463,22 @@ export function Chat({ projectPath, onCloseProject }: ChatProps) {
|
||||
<input
|
||||
ref={inputRef}
|
||||
value={input}
|
||||
onChange={(e) => setInput(e.target.value)}
|
||||
onChange={(e) => {
|
||||
const newValue = e.target.value;
|
||||
setInput(newValue);
|
||||
|
||||
// If user starts typing while model is generating, cancel backend request
|
||||
if (loading && newValue.length > input.length) {
|
||||
setLoading(false);
|
||||
invoke("cancel_chat").catch((e) =>
|
||||
console.error("Cancel failed:", e),
|
||||
);
|
||||
// Remove the interrupted message from history
|
||||
setMessages((prev) =>
|
||||
prev.slice(0, lastMessageCountRef.current - 1),
|
||||
);
|
||||
}
|
||||
}}
|
||||
onKeyDown={(e) => e.key === "Enter" && sendMessage()}
|
||||
placeholder="Send a message..."
|
||||
style={{
|
||||
|
||||
Reference in New Issue
Block a user