fix: fix/skip interrupt banner for server tools (#353)

Co-authored-by: Letta <noreply@letta.com>
This commit is contained in:
Charles Packer
2025-12-22 18:39:12 -08:00
committed by GitHub
parent 21a89a6220
commit fc195be7b7
2 changed files with 18 additions and 4 deletions

View File

@@ -836,6 +836,7 @@ export default function App({
);
// Core streaming function - iterative loop that processes conversation turns
// biome-ignore lint/correctness/useExhaustiveDependencies: refs read .current dynamically
const processConversation = useCallback(
async (
initialInput: Array<MessageCreate | ApprovalCreate>,
@@ -849,6 +850,12 @@ export default function App({
return;
}
// Guard against concurrent processConversation calls
// This can happen if user submits two messages in quick succession
if (streamingRef.current) {
return;
}
setStreaming(true);
abortControllerRef.current = new AbortController();
@@ -1532,10 +1539,13 @@ export default function App({
// Set cancellation flag to prevent processConversation from starting
userCancelledRef.current = true;
// Stop streaming and show error message
// Stop streaming and show error message (unless tool calls were cancelled,
// since the tool result will show "Interrupted by user")
setStreaming(false);
markIncompleteToolsAsCancelled(buffersRef.current);
appendError("Stream interrupted by user");
const toolsCancelled = markIncompleteToolsAsCancelled(buffersRef.current);
if (!toolsCancelled) {
appendError("Stream interrupted by user");
}
refreshDerived();
// Clear any pending approvals since we're cancelling

View File

@@ -170,11 +170,13 @@ export function markCurrentLineAsFinished(b: Buffers) {
/**
* Mark any incomplete tool calls as cancelled when stream is interrupted.
* This prevents blinking tool calls from staying in progress state.
* @returns true if any tool calls were marked as cancelled
*/
export function markIncompleteToolsAsCancelled(b: Buffers) {
export function markIncompleteToolsAsCancelled(b: Buffers): boolean {
// Mark buffer as interrupted to skip stale throttled refreshes
b.interrupted = true;
let anyToolsCancelled = false;
for (const [id, line] of b.byId.entries()) {
if (line.kind === "tool_call" && line.phase !== "finished") {
const updatedLine = {
@@ -184,10 +186,12 @@ export function markIncompleteToolsAsCancelled(b: Buffers) {
resultText: INTERRUPTED_BY_USER,
};
b.byId.set(id, updatedLine);
anyToolsCancelled = true;
}
}
// Also mark any streaming assistant/reasoning lines as finished
markCurrentLineAsFinished(b);
return anyToolsCancelled;
}
type ToolCallLine = Extract<Line, { kind: "tool_call" }>;