fix: address P0-4 chat zombie, P0-5 double SessionStarted, P0-6 steering wrong content
This commit is contained in:
@@ -5,6 +5,7 @@ import com.correx.apps.server.protocol.RiskSummaryDto
|
||||
import com.correx.apps.server.protocol.ServerMessage
|
||||
import com.correx.core.artifactstore.ArtifactStore
|
||||
import com.correx.core.events.events.ApprovalRequestedEvent
|
||||
import com.correx.core.events.events.ChatSessionStartedEvent
|
||||
import com.correx.core.events.events.InferenceCompletedEvent
|
||||
import com.correx.core.events.events.WorkflowStartedEvent
|
||||
import com.correx.core.events.events.InferenceStartedEvent
|
||||
@@ -45,6 +46,13 @@ suspend fun domainEventToServerMessage(
|
||||
): ServerMessage? {
|
||||
val seq = event.sequence
|
||||
return when (val p = event.payload) {
|
||||
is ChatSessionStartedEvent -> ServerMessage.SessionStarted(
|
||||
sessionId = p.sessionId,
|
||||
workflowId = "chat",
|
||||
sequence = seq,
|
||||
sessionSequence = sessionSequence,
|
||||
)
|
||||
|
||||
is WorkflowStartedEvent -> ServerMessage.SessionStarted(
|
||||
sessionId = p.sessionId,
|
||||
workflowId = p.workflowId,
|
||||
|
||||
@@ -14,10 +14,10 @@ import com.correx.apps.server.protocol.ToolDecl
|
||||
import com.correx.core.approvals.GrantScope
|
||||
import com.correx.core.approvals.Tier
|
||||
import com.correx.core.events.events.ApprovalGrantCreatedEvent
|
||||
import com.correx.core.events.events.ChatSessionStartedEvent
|
||||
import com.correx.core.events.events.EventMetadata
|
||||
import com.correx.core.events.events.NewEvent
|
||||
import com.correx.core.events.events.StoredEvent
|
||||
import com.correx.core.events.events.WorkflowStartedEvent
|
||||
import com.correx.core.events.types.GrantId
|
||||
import com.correx.core.events.stores.EventStore
|
||||
import com.correx.core.events.types.EventId
|
||||
@@ -275,8 +275,9 @@ class GlobalStreamHandler(private val module: ServerModule) {
|
||||
val sessionId = msg.sessionId
|
||||
log.info("starting chat session={}", sessionId.value)
|
||||
|
||||
// Emit WorkflowStartedEvent for the new session (no graph, no orchestrator).
|
||||
val event = NewEvent(
|
||||
// Emit ChatSessionStartedEvent for the new session (no graph, no orchestrator).
|
||||
// streamGlobal picks this up and maps it to SessionStarted with the real sequence.
|
||||
module.eventStore.append(NewEvent(
|
||||
metadata = EventMetadata(
|
||||
eventId = EventId(UUID.randomUUID().toString()),
|
||||
sessionId = sessionId,
|
||||
@@ -285,22 +286,8 @@ class GlobalStreamHandler(private val module: ServerModule) {
|
||||
causationId = null,
|
||||
correlationId = null,
|
||||
),
|
||||
payload = WorkflowStartedEvent(
|
||||
sessionId = sessionId,
|
||||
workflowId = "chat",
|
||||
startStageId = StageId("none"),
|
||||
),
|
||||
)
|
||||
module.eventStore.append(event)
|
||||
|
||||
// Send SessionStarted so the TUI creates the session entry immediately.
|
||||
val started = ServerMessage.SessionStarted(
|
||||
sessionId = sessionId,
|
||||
workflowId = "chat",
|
||||
sequence = 0L,
|
||||
sessionSequence = 0L,
|
||||
)
|
||||
session.send(Frame.Text(ProtocolSerializer.encodeServerMessage(started)))
|
||||
payload = ChatSessionStartedEvent(sessionId = sessionId),
|
||||
))
|
||||
|
||||
// Call router and send response.
|
||||
runCatching {
|
||||
@@ -340,17 +327,12 @@ class GlobalStreamHandler(private val module: ServerModule) {
|
||||
val sessionId: SessionId = TypeId(UUID.randomUUID().toString())
|
||||
log.info("starting session={} workflow={}", sessionId.value, msg.workflowId)
|
||||
|
||||
// Send protocol messages FIRST. If the WS is already closed, these throw and the
|
||||
// Send StageToolManifest FIRST. If the WS is already closed, this throws and the
|
||||
// orchestrator never launches — no silent data loss. The exception propagates to the
|
||||
// runCatching in handleClientMessage (caller) and is logged there.
|
||||
val started = ServerMessage.SessionStarted(
|
||||
sessionId = sessionId,
|
||||
workflowId = msg.workflowId,
|
||||
sequence = 0L,
|
||||
sessionSequence = 0L,
|
||||
)
|
||||
session.send(Frame.Text(ProtocolSerializer.encodeServerMessage(started)))
|
||||
|
||||
// SessionStarted is not sent here — it is derived from WorkflowStartedEvent
|
||||
// by streamGlobal via DomainEventMapper, ensuring exactly one SessionStarted
|
||||
// per session with the correct sequence number (P0-5).
|
||||
val stages = graph.stages.map { (stageId, stageConfig) ->
|
||||
val tools = stageConfig.allowedTools.mapNotNull { toolName ->
|
||||
module.toolRegistry.resolve(toolName)?.let { tool ->
|
||||
|
||||
Reference in New Issue
Block a user