Refactor loop detection logic in ChatInput
- Use message finish state instead of session status for loop detection - Add lastProcessedMessageId to prevent duplicate loop triggers - Add XCOpenCodeWeb.exe to .gitignore Note: Single-file exe now builds to ~150MB (down from ~300MB with Electron)
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -54,3 +54,4 @@ packages/intellij/
|
|||||||
|
|
||||||
# OS
|
# OS
|
||||||
Thumbs.db
|
Thumbs.db
|
||||||
|
web/XCOpenCodeWeb.exe
|
||||||
|
|||||||
@@ -167,11 +167,9 @@ export const ChatInput: React.FC<ChatInputProps> = ({ onOpenSettings, scrollToBo
|
|||||||
current: number;
|
current: number;
|
||||||
total: number;
|
total: number;
|
||||||
prompt: string;
|
prompt: string;
|
||||||
|
lastProcessedMessageId: string | null;
|
||||||
} | null>(null);
|
} | null>(null);
|
||||||
|
|
||||||
// Get session status from store for loop detection
|
|
||||||
const sessionStatus = useSessionStore((state) => state.sessionStatus);
|
|
||||||
|
|
||||||
const isDesktopExpanded = isExpandedInput && !isMobile;
|
const isDesktopExpanded = isExpandedInput && !isMobile;
|
||||||
|
|
||||||
const sendableAttachedFiles = React.useMemo(
|
const sendableAttachedFiles = React.useMemo(
|
||||||
@@ -856,6 +854,7 @@ export const ChatInput: React.FC<ChatInputProps> = ({ onOpenSettings, scrollToBo
|
|||||||
current: 1,
|
current: 1,
|
||||||
total: loopNum,
|
total: loopNum,
|
||||||
prompt: loopArgs,
|
prompt: loopArgs,
|
||||||
|
lastProcessedMessageId: null,
|
||||||
});
|
});
|
||||||
toast.info(`Loop started: ${loopNum} iterations`);
|
toast.info(`Loop started: ${loopNum} iterations`);
|
||||||
// Clear input
|
// Clear input
|
||||||
@@ -952,19 +951,30 @@ export const ChatInput: React.FC<ChatInputProps> = ({ onOpenSettings, scrollToBo
|
|||||||
// Update ref with latest handleSubmit on every render
|
// Update ref with latest handleSubmit on every render
|
||||||
handleSubmitRef.current = handleSubmit;
|
handleSubmitRef.current = handleSubmit;
|
||||||
|
|
||||||
// Handle loop: detect when AI finishes and send next iteration
|
// Handle loop: detect when AI finishes (finish === 'stop') and send next iteration
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (!loopState?.active || !currentSessionId) {
|
if (!loopState?.active || !currentSessionId) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const status = sessionStatus?.get(currentSessionId);
|
const messages = useMessageStore.getState().messages.get(currentSessionId);
|
||||||
if (status?.type === 'idle') {
|
if (!messages) return;
|
||||||
// AI finished, check if we should continue looping
|
|
||||||
if (loopState.current <= loopState.total) {
|
const assistantMessages = messages.filter((m) => m.info.role === 'assistant');
|
||||||
|
const lastAssistant = assistantMessages[assistantMessages.length - 1];
|
||||||
|
if (!lastAssistant) return;
|
||||||
|
|
||||||
|
const messageId = lastAssistant.info.id;
|
||||||
|
const finish = lastAssistant.info.finish;
|
||||||
|
|
||||||
|
if (finish === 'stop' && messageId !== loopState.lastProcessedMessageId) {
|
||||||
if (loopState.current < loopState.total) {
|
if (loopState.current < loopState.total) {
|
||||||
const next = loopState.current + 1;
|
const next = loopState.current + 1;
|
||||||
setLoopState({ ...loopState, current: next });
|
setLoopState({
|
||||||
|
...loopState,
|
||||||
|
current: next,
|
||||||
|
lastProcessedMessageId: messageId,
|
||||||
|
});
|
||||||
useSessionStore.getState().sendMessage(
|
useSessionStore.getState().sendMessage(
|
||||||
loopState.prompt,
|
loopState.prompt,
|
||||||
currentProviderId,
|
currentProviderId,
|
||||||
@@ -977,12 +987,10 @@ export const ChatInput: React.FC<ChatInputProps> = ({ onOpenSettings, scrollToBo
|
|||||||
inputMode
|
inputMode
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
// Loop complete - all iterations sent
|
|
||||||
setLoopState(null);
|
setLoopState(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}, [loopState, sessionMessages, currentSessionId, currentProviderId, currentModelId, currentAgentName, currentVariant, inputMode]);
|
||||||
}, [loopState, sessionStatus, currentSessionId, currentProviderId, currentModelId, currentAgentName, currentVariant, inputMode]);
|
|
||||||
|
|
||||||
// Primary action for send button - respects queue mode setting
|
// Primary action for send button - respects queue mode setting
|
||||||
const handlePrimaryAction = React.useCallback(() => {
|
const handlePrimaryAction = React.useCallback(() => {
|
||||||
|
|||||||
Reference in New Issue
Block a user