refactor(tui-03): remove ConnectSession from SessionStarted, keep on SessionSnapshot
SessionSnapshot is the correct trigger for connectSession() — the client has enough state to stream live events at that point. SessionStarted fires pre-snapshot and no longer needs to emit ConnectSession.
This commit is contained in:
@@ -16,10 +16,10 @@ object RootReducer {
|
|||||||
val phase = SnapshotPhaseReducer.process(state, action)
|
val phase = SnapshotPhaseReducer.process(state, action)
|
||||||
var current = phase.state
|
var current = phase.state
|
||||||
val allEffects = mutableListOf<Effect>()
|
val allEffects = mutableListOf<Effect>()
|
||||||
val isReplay = action is Action.ServerEventReceived &&
|
val replayingBufferedEvents = action is Action.ServerEventReceived &&
|
||||||
action.message is ServerMessage.SnapshotComplete
|
action.message is ServerMessage.SnapshotComplete
|
||||||
for (a in phase.actionsToDispatch) {
|
for (a in phase.actionsToDispatch) {
|
||||||
if (isReplay) {
|
if (replayingBufferedEvents) {
|
||||||
val inner = SnapshotPhaseReducer.process(current, a)
|
val inner = SnapshotPhaseReducer.process(current, a)
|
||||||
current = inner.state
|
current = inner.state
|
||||||
for (ia in inner.actionsToDispatch) {
|
for (ia in inner.actionsToDispatch) {
|
||||||
|
|||||||
@@ -337,7 +337,7 @@ object SessionsReducer {
|
|||||||
msg: ServerMessage.SessionStarted,
|
msg: ServerMessage.SessionStarted,
|
||||||
clock: () -> Long,
|
clock: () -> Long,
|
||||||
sessions: SessionsState,
|
sessions: SessionsState,
|
||||||
): Pair<SessionsState, List<Effect.ConnectSession>> {
|
): Pair<SessionsState, List<Effect>> {
|
||||||
val summary = SessionSummary(
|
val summary = SessionSummary(
|
||||||
id = msg.sessionId.value,
|
id = msg.sessionId.value,
|
||||||
status = "ACTIVE",
|
status = "ACTIVE",
|
||||||
@@ -348,8 +348,7 @@ object SessionsReducer {
|
|||||||
lastOutput = null,
|
lastOutput = null,
|
||||||
)
|
)
|
||||||
val selected = sessions.selectedId ?: msg.sessionId.value
|
val selected = sessions.selectedId ?: msg.sessionId.value
|
||||||
return sessions.copy(sessions = sessions.sessions + summary, selectedId = selected) to
|
return sessions.copy(sessions = sessions.sessions + summary, selectedId = selected) to emptyList()
|
||||||
listOf(Effect.ConnectSession(msg.sessionId))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun processInferenceCompletedMessage(
|
private fun processInferenceCompletedMessage(
|
||||||
|
|||||||
@@ -77,6 +77,7 @@ object SnapshotPhaseReducer {
|
|||||||
is ServerMessage.ToolFailed -> msg.sessionId.value
|
is ServerMessage.ToolFailed -> msg.sessionId.value
|
||||||
is ServerMessage.ToolRejected -> msg.sessionId.value
|
is ServerMessage.ToolRejected -> msg.sessionId.value
|
||||||
is ServerMessage.ApprovalRequired -> msg.sessionId.value
|
is ServerMessage.ApprovalRequired -> msg.sessionId.value
|
||||||
|
is ServerMessage.SessionSnapshot -> msg.sessionId.value
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -118,6 +118,20 @@ class RootReducerTest {
|
|||||||
assertEquals(state.sessions.sessions, newState.sessions.sessions)
|
assertEquals(state.sessions.sessions, newState.sessions.sessions)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `SnapshotComplete with empty pendingEvents flips phase and produces no sessions`() {
|
||||||
|
val initial = TuiState(snapshotPhase = true, pendingEvents = emptyList())
|
||||||
|
val (result, effects) = RootReducer.reduce(
|
||||||
|
initial,
|
||||||
|
Action.ServerEventReceived(com.correx.apps.server.protocol.ServerMessage.SnapshotComplete),
|
||||||
|
fixedClock,
|
||||||
|
)
|
||||||
|
assertEquals(false, result.snapshotPhase)
|
||||||
|
assertTrue(result.pendingEvents.isEmpty())
|
||||||
|
assertTrue(result.sessions.sessions.isEmpty())
|
||||||
|
assertTrue(effects.isEmpty())
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `AppendChar followed by Backspace returns to original buffer`() {
|
fun `AppendChar followed by Backspace returns to original buffer`() {
|
||||||
val initial = TuiState(inputMode = InputMode.ROUTER, inputBuffer = "ab")
|
val initial = TuiState(inputMode = InputMode.ROUTER, inputBuffer = "ab")
|
||||||
|
|||||||
@@ -96,8 +96,7 @@ class SessionsReducerTest {
|
|||||||
assertEquals(1, state.sessions.size)
|
assertEquals(1, state.sessions.size)
|
||||||
assertEquals("s1", state.sessions[0].id)
|
assertEquals("s1", state.sessions[0].id)
|
||||||
assertEquals("s1", state.selectedId)
|
assertEquals("s1", state.selectedId)
|
||||||
assertEquals(1, effects.size)
|
assertTrue(effects.isEmpty())
|
||||||
assertTrue(effects[0] is Effect.ConnectSession)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
Reference in New Issue
Block a user