mirror of
https://gitee.com/mateos/mateclaw.git
synced 2026-09-15 20:08:18 +08:00
fix(channel): preserve queued chat inputs across turns
This commit is contained in:
parent
a9c2d45790
commit
481cece733
@ -458,7 +458,18 @@ public class ChatStreamTracker {
|
|||||||
RunState state = runs.get(conversationId);
|
RunState state = runs.get(conversationId);
|
||||||
if (state != null && state.done) {
|
if (state != null && state.done) {
|
||||||
stopHeartbeat(conversationId);
|
stopHeartbeat(conversationId);
|
||||||
runs.put(conversationId, new RunState(conversationId));
|
RunState nextState = new RunState(conversationId);
|
||||||
|
int carried = 0;
|
||||||
|
QueuedInput queued;
|
||||||
|
while ((queued = state.messageQueue.poll()) != null) {
|
||||||
|
nextState.messageQueue.offer(queued);
|
||||||
|
carried++;
|
||||||
|
}
|
||||||
|
runs.put(conversationId, nextState);
|
||||||
|
if (carried > 0) {
|
||||||
|
log.info("[ChatStreamTracker] Carried {} queued message(s) into next run: {}",
|
||||||
|
carried, conversationId);
|
||||||
|
}
|
||||||
} else if (state != null) {
|
} else if (state != null) {
|
||||||
// Reuse path: when complete() early-returns due to activeFluxCount > 0
|
// Reuse path: when complete() early-returns due to activeFluxCount > 0
|
||||||
// (approval replay / interrupt / any leaked flux increment), the RunState
|
// (approval replay / interrupt / any leaked flux increment), the RunState
|
||||||
|
|||||||
@ -0,0 +1,52 @@
|
|||||||
|
package vip.mate.channel.web;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import org.junit.jupiter.api.DisplayName;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
class ChatStreamTrackerQueueDrainTest {
|
||||||
|
|
||||||
|
private ChatStreamTracker newTracker() {
|
||||||
|
return new ChatStreamTracker(new ObjectMapper());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("Queued inputs survive RunState replacement and drain FIFO")
|
||||||
|
void queuedInputsSurviveRunStateReplacementAndDrainFifo() {
|
||||||
|
ChatStreamTracker tracker = newTracker();
|
||||||
|
String conversationId = "queue-drain";
|
||||||
|
|
||||||
|
tracker.register(conversationId);
|
||||||
|
tracker.incrementFlux(conversationId);
|
||||||
|
assertTrue(tracker.enqueueMessage(conversationId, "q1", 101L, false));
|
||||||
|
assertTrue(tracker.enqueueMessage(conversationId, "q2", 101L, false));
|
||||||
|
assertTrue(tracker.enqueueMessage(conversationId, "q3", 101L, false));
|
||||||
|
|
||||||
|
ChatStreamTracker.CompletionResult first = tracker.completeAndConsumeIfLast(conversationId);
|
||||||
|
assertTrue(first.allDone());
|
||||||
|
assertNotNull(first.queuedInput());
|
||||||
|
assertEquals("q1", first.queuedInput().message());
|
||||||
|
|
||||||
|
tracker.register(conversationId);
|
||||||
|
tracker.incrementFlux(conversationId);
|
||||||
|
ChatStreamTracker.CompletionResult second = tracker.completeAndConsumeIfLast(conversationId);
|
||||||
|
assertTrue(second.allDone());
|
||||||
|
assertNotNull(second.queuedInput());
|
||||||
|
assertEquals("q2", second.queuedInput().message());
|
||||||
|
|
||||||
|
tracker.register(conversationId);
|
||||||
|
tracker.incrementFlux(conversationId);
|
||||||
|
ChatStreamTracker.CompletionResult third = tracker.completeAndConsumeIfLast(conversationId);
|
||||||
|
assertTrue(third.allDone());
|
||||||
|
assertNotNull(third.queuedInput());
|
||||||
|
assertEquals("q3", third.queuedInput().message());
|
||||||
|
|
||||||
|
tracker.register(conversationId);
|
||||||
|
tracker.incrementFlux(conversationId);
|
||||||
|
ChatStreamTracker.CompletionResult empty = tracker.completeAndConsumeIfLast(conversationId);
|
||||||
|
assertTrue(empty.allDone());
|
||||||
|
assertNull(empty.queuedInput());
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user