feature(event-sourcing): baseline for the architecture review fixes.
- fixed the tool overlay in tui. - fixed tool calling - added schemas. - getting all sessionIds via event store. - instead of sending all events on the replay - there's a new way for replaying. - session snapshot is now a thing getting sent for previously created sessions. - added logging to important parts. - revert workflowId from WorkflowCompletedEvent.
This commit is contained in:
-1
@@ -37,7 +37,6 @@ class EventsTest {
|
||||
sessionId = SessionId("s1"),
|
||||
terminalStageId = StageId("stage-a"),
|
||||
totalStages = 1,
|
||||
workflowId = workflowId,
|
||||
)
|
||||
|
||||
val json = eventJson.encodeToString(EventPayload.serializer(), event)
|
||||
|
||||
@@ -5,14 +5,20 @@ import com.correx.core.events.events.SteeringNoteAddedEvent
|
||||
import com.correx.core.events.events.StoredEvent
|
||||
import com.correx.core.events.stores.EventStore
|
||||
import com.correx.core.events.types.ContextPackId
|
||||
import com.correx.core.events.types.EventId
|
||||
import com.correx.core.events.types.InferenceRequestId
|
||||
import com.correx.core.events.types.ProviderId
|
||||
import com.correx.core.events.types.SessionId
|
||||
import com.correx.core.events.types.StageId
|
||||
import com.correx.core.inference.CapabilityScore
|
||||
import com.correx.core.inference.FinishReason
|
||||
import com.correx.core.inference.InferenceProvider
|
||||
import com.correx.core.inference.InferenceRequest
|
||||
import com.correx.core.inference.InferenceResponse
|
||||
import com.correx.core.inference.InferenceRouter
|
||||
import com.correx.core.inference.ModelCapability
|
||||
import com.correx.core.inference.ProviderHealth
|
||||
import com.correx.core.inference.ResponseFormat
|
||||
import com.correx.core.inference.TokenUsage
|
||||
import com.correx.core.router.ChatMode
|
||||
import com.correx.core.router.DefaultRouterFacade
|
||||
@@ -24,6 +30,8 @@ import com.correx.core.router.model.RouterResponse
|
||||
import com.correx.core.router.model.RouterState
|
||||
import com.correx.core.router.model.TurnRole
|
||||
import com.correx.core.router.model.WorkflowStatus
|
||||
import com.correx.testing.fixtures.inference.MockTokenizer
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.junit.jupiter.api.Assertions.assertEquals
|
||||
import org.junit.jupiter.api.Assertions.assertFalse
|
||||
@@ -405,25 +413,25 @@ class RouterFacadeTest {
|
||||
requiredCapabilities: Set<ModelCapability>,
|
||||
): InferenceProvider {
|
||||
return object : InferenceProvider {
|
||||
override val id = com.correx.core.events.types.ProviderId("mock")
|
||||
override val id = ProviderId("mock")
|
||||
override val name = "Mock"
|
||||
override val tokenizer = com.correx.testing.fixtures.inference.MockTokenizer()
|
||||
override val tokenizer = MockTokenizer()
|
||||
override suspend fun infer(request: InferenceRequest): InferenceResponse {
|
||||
assertEquals(1, capturedContextPacks.size)
|
||||
assertEquals(capturedContextPacks[0].id, request.contextPack.id)
|
||||
return InferenceResponse(
|
||||
requestId = request.requestId,
|
||||
text = "response",
|
||||
finishReason = com.correx.core.inference.FinishReason.Stop,
|
||||
finishReason = FinishReason.Stop,
|
||||
tokensUsed = TokenUsage(promptTokens = 10, completionTokens = 5),
|
||||
latencyMs = 0,
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun healthCheck(): com.correx.core.inference.ProviderHealth =
|
||||
com.correx.core.inference.ProviderHealth.Healthy
|
||||
override suspend fun healthCheck(): ProviderHealth =
|
||||
ProviderHealth.Healthy
|
||||
|
||||
override fun capabilities(): Set<com.correx.core.inference.CapabilityScore> = emptySet()
|
||||
override fun capabilities(): Set<CapabilityScore> = emptySet()
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -456,7 +464,7 @@ class RouterFacadeTest {
|
||||
)
|
||||
facade.onUserInput(sessionId = SessionId("test-session"), input = "Hello!")
|
||||
val req = capturedRequests[0]
|
||||
assertTrue(req.responseFormat is com.correx.core.inference.ResponseFormat.Text)
|
||||
assertTrue(req.responseFormat is ResponseFormat.Text)
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -512,22 +520,22 @@ class RouterFacadeTest {
|
||||
|
||||
private fun mockProvider(responseText: String): InferenceProvider =
|
||||
object : InferenceProvider {
|
||||
override val id = com.correx.core.events.types.ProviderId("mock")
|
||||
override val id = ProviderId("mock")
|
||||
override val name = "Mock"
|
||||
override val tokenizer = com.correx.testing.fixtures.inference.MockTokenizer()
|
||||
override val tokenizer = MockTokenizer()
|
||||
override suspend fun infer(request: InferenceRequest): InferenceResponse = InferenceResponse(
|
||||
requestId = request.requestId,
|
||||
text = responseText,
|
||||
finishReason = com.correx.core.inference.FinishReason.Stop,
|
||||
finishReason = FinishReason.Stop,
|
||||
tokensUsed = TokenUsage(promptTokens = 10, completionTokens = 5),
|
||||
latencyMs = 0,
|
||||
)
|
||||
|
||||
override suspend fun healthCheck(): com.correx.core.inference.ProviderHealth =
|
||||
com.correx.core.inference.ProviderHealth.Healthy
|
||||
override suspend fun healthCheck(): ProviderHealth =
|
||||
ProviderHealth.Healthy
|
||||
|
||||
override fun capabilities(): Set<com.correx.core.inference.CapabilityScore> =
|
||||
setOf(com.correx.core.inference.CapabilityScore(ModelCapability.General, 1.0))
|
||||
override fun capabilities(): Set<CapabilityScore> =
|
||||
setOf(CapabilityScore(ModelCapability.General, 1.0))
|
||||
}
|
||||
|
||||
private fun mockProviderWithCapture(
|
||||
@@ -535,24 +543,24 @@ class RouterFacadeTest {
|
||||
requestIds: MutableList<InferenceRequestId>,
|
||||
): InferenceProvider =
|
||||
object : InferenceProvider {
|
||||
override val id = com.correx.core.events.types.ProviderId("mock")
|
||||
override val id = ProviderId("mock")
|
||||
override val name = "Mock"
|
||||
override val tokenizer = com.correx.testing.fixtures.inference.MockTokenizer()
|
||||
override val tokenizer = MockTokenizer()
|
||||
override suspend fun infer(request: InferenceRequest): InferenceResponse {
|
||||
requestIds.add(request.requestId)
|
||||
return InferenceResponse(
|
||||
requestId = request.requestId,
|
||||
text = responseText,
|
||||
finishReason = com.correx.core.inference.FinishReason.Stop,
|
||||
finishReason = FinishReason.Stop,
|
||||
tokensUsed = TokenUsage(promptTokens = 10, completionTokens = 5),
|
||||
latencyMs = 0,
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun healthCheck(): com.correx.core.inference.ProviderHealth =
|
||||
com.correx.core.inference.ProviderHealth.Healthy
|
||||
override suspend fun healthCheck(): ProviderHealth =
|
||||
ProviderHealth.Healthy
|
||||
|
||||
override fun capabilities(): Set<com.correx.core.inference.CapabilityScore> = emptySet()
|
||||
override fun capabilities(): Set<CapabilityScore> = emptySet()
|
||||
}
|
||||
|
||||
private fun mockProviderWithRequestCapture(
|
||||
@@ -560,24 +568,24 @@ class RouterFacadeTest {
|
||||
requests: MutableList<InferenceRequest>,
|
||||
): InferenceProvider =
|
||||
object : InferenceProvider {
|
||||
override val id = com.correx.core.events.types.ProviderId("mock")
|
||||
override val id = ProviderId("mock")
|
||||
override val name = "Mock"
|
||||
override val tokenizer = com.correx.testing.fixtures.inference.MockTokenizer()
|
||||
override val tokenizer = MockTokenizer()
|
||||
override suspend fun infer(request: InferenceRequest): InferenceResponse {
|
||||
requests.add(request)
|
||||
return InferenceResponse(
|
||||
requestId = request.requestId,
|
||||
text = responseText,
|
||||
finishReason = com.correx.core.inference.FinishReason.Stop,
|
||||
finishReason = FinishReason.Stop,
|
||||
tokensUsed = TokenUsage(promptTokens = 10, completionTokens = 5),
|
||||
latencyMs = 0,
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun healthCheck(): com.correx.core.inference.ProviderHealth =
|
||||
com.correx.core.inference.ProviderHealth.Healthy
|
||||
override suspend fun healthCheck(): ProviderHealth =
|
||||
ProviderHealth.Healthy
|
||||
|
||||
override fun capabilities(): Set<com.correx.core.inference.CapabilityScore> = emptySet()
|
||||
override fun capabilities(): Set<CapabilityScore> = emptySet()
|
||||
}
|
||||
|
||||
private fun emptyContextPack(): ContextPack = ContextPack(
|
||||
@@ -591,7 +599,7 @@ class RouterFacadeTest {
|
||||
|
||||
private class MapBackedEventStore : EventStore {
|
||||
val appendedEvents = mutableListOf<NewEvent>()
|
||||
private val storedEvents = mutableMapOf<com.correx.core.events.types.EventId, StoredEvent>()
|
||||
private val storedEvents: MutableMap<EventId, StoredEvent> = mutableMapOf()
|
||||
private var nextSequence = 1L
|
||||
|
||||
override suspend fun append(event: NewEvent): StoredEvent {
|
||||
@@ -620,10 +628,12 @@ class RouterFacadeTest {
|
||||
override fun lastSequence(sessionId: SessionId): Long? =
|
||||
read(sessionId).maxOfOrNull { it.sequence }
|
||||
|
||||
override fun subscribe(sessionId: SessionId): kotlinx.coroutines.flow.Flow<StoredEvent> =
|
||||
override fun subscribe(sessionId: SessionId): Flow<StoredEvent> =
|
||||
throw UnsupportedOperationException("subscribe not implemented for mock")
|
||||
|
||||
override fun allEvents(): Sequence<StoredEvent> =
|
||||
storedEvents.values.asSequence()
|
||||
|
||||
override fun allSessionIds(): Set<SessionId> = storedEvents.values.map { it.metadata.sessionId }.toSet()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ class RouterProjectorTest {
|
||||
)
|
||||
val updated = projector.apply(
|
||||
started,
|
||||
stored(payload = WorkflowCompletedEvent(sessionId, stageId, 3, workflowId)),
|
||||
stored(payload = WorkflowCompletedEvent(sessionId, stageId, 3)),
|
||||
)
|
||||
assertEquals(WorkflowStatus.COMPLETED, updated.workflowStatus)
|
||||
assertNull(updated.currentStageId)
|
||||
@@ -176,7 +176,7 @@ class RouterProjectorTest {
|
||||
stored(payload = OrchestrationResumedEvent(sessionId, StageId("a"))),
|
||||
stored(payload = StageCompletedEvent(sessionId, StageId("b"), StageId("t2"))),
|
||||
stored(payload = StageFailedEvent(sessionId, StageId("b"), StageId("t3"), "error")),
|
||||
stored(payload = WorkflowCompletedEvent(sessionId, StageId("c"), 3, workflowId)),
|
||||
stored(payload = WorkflowCompletedEvent(sessionId, StageId("c"), 3)),
|
||||
)
|
||||
|
||||
var projected = state
|
||||
@@ -206,7 +206,7 @@ class RouterProjectorTest {
|
||||
|
||||
state = projector.apply(
|
||||
state,
|
||||
stored(payload = WorkflowCompletedEvent(sessionId, StageId("stage-A"), 1, workflowId)),
|
||||
stored(payload = WorkflowCompletedEvent(sessionId, StageId("stage-A"), 1)),
|
||||
)
|
||||
assertEquals(WorkflowStatus.COMPLETED, state.workflowStatus)
|
||||
assertNull(state.currentStageId)
|
||||
|
||||
@@ -58,7 +58,7 @@ class RouterReducerTest {
|
||||
)
|
||||
val completed = reducer.reduce(
|
||||
started,
|
||||
stored(payload = WorkflowCompletedEvent(sessionId, stageId, 3, workflowId)),
|
||||
stored(payload = WorkflowCompletedEvent(sessionId, stageId, 3)),
|
||||
)
|
||||
assertEquals(WorkflowStatus.COMPLETED, completed.workflowStatus)
|
||||
assertNull(completed.currentStageId)
|
||||
@@ -233,7 +233,7 @@ class RouterReducerTest {
|
||||
assertEquals(StageOutcomeKind.SUCCESS, s2.l2Memory[0].outcome)
|
||||
|
||||
val s3 =
|
||||
reducer.reduce(s2, stored(payload = WorkflowCompletedEvent(sessionId, StageId("stage-A"), 1, workflowId)))
|
||||
reducer.reduce(s2, stored(payload = WorkflowCompletedEvent(sessionId, StageId("stage-A"), 1)))
|
||||
assertEquals(WorkflowStatus.COMPLETED, s3.workflowStatus)
|
||||
assertNull(s3.currentStageId)
|
||||
|
||||
|
||||
@@ -81,7 +81,7 @@ class OrchestrationProjectorTest {
|
||||
failureReason = "Something went wrong",
|
||||
),
|
||||
),
|
||||
stored(payload = WorkflowCompletedEvent(sessionId, stageId, 1, workflowId)),
|
||||
stored(payload = WorkflowCompletedEvent(sessionId, stageId, 1)),
|
||||
)
|
||||
|
||||
val result1 = events.fold(initialState) { state, event ->
|
||||
@@ -101,7 +101,7 @@ class OrchestrationProjectorTest {
|
||||
val s2 =
|
||||
projector.apply(s1, stored(payload = OrchestrationPausedEvent(sessionId, stageId, "approval required")))
|
||||
val s3 = projector.apply(s2, stored(payload = OrchestrationResumedEvent(sessionId, stageId)))
|
||||
val s4 = projector.apply(s3, stored(payload = WorkflowCompletedEvent(sessionId, stageId, 1, workflowId)))
|
||||
val s4 = projector.apply(s3, stored(payload = WorkflowCompletedEvent(sessionId, stageId, 1)))
|
||||
|
||||
assertEquals(OrchestrationStatus.RUNNING, s1.status)
|
||||
assertEquals(OrchestrationStatus.PAUSED, s2.status)
|
||||
|
||||
@@ -21,8 +21,8 @@ class OrchestrationReducerTest {
|
||||
private val reducer = DefaultOrchestrationReducer()
|
||||
private val sessionId = SessionId("s1")
|
||||
private val stageId = StageId("stage-1")
|
||||
private val state = OrchestrationState(stageId)
|
||||
private val workflowId = "workflow-test"
|
||||
private val state = OrchestrationState(workflowId, stageId)
|
||||
|
||||
@Test
|
||||
fun `WorkflowStartedEvent sets status to RUNNING`() {
|
||||
@@ -58,7 +58,7 @@ class OrchestrationReducerTest {
|
||||
|
||||
val completed = reducer.reduce(
|
||||
started,
|
||||
stored(payload = WorkflowCompletedEvent(sessionId, stageId, 1, workflowId)),
|
||||
stored(payload = WorkflowCompletedEvent(sessionId, stageId, 1)),
|
||||
)
|
||||
assertTrue(completed.failureReason.isNullOrBlank())
|
||||
assertEquals(OrchestrationStatus.COMPLETED, completed.status)
|
||||
|
||||
@@ -49,7 +49,7 @@ class RouterProjectorTest {
|
||||
val started =
|
||||
projector.apply(initialState, stored(payload = WorkflowStartedEvent(sessionId, workflowId, stageId)))
|
||||
val completed =
|
||||
projector.apply(started, stored(payload = WorkflowCompletedEvent(sessionId, stageId, 1, workflowId)))
|
||||
projector.apply(started, stored(payload = WorkflowCompletedEvent(sessionId, stageId, 1)))
|
||||
assertEquals(WorkflowStatus.COMPLETED, completed.workflowStatus)
|
||||
assertNull(completed.currentStageId)
|
||||
}
|
||||
@@ -134,7 +134,7 @@ class RouterProjectorTest {
|
||||
stored(payload = StageCompletedEvent(sessionId, StageId("stage-2"), StageId("t1"))),
|
||||
stored(payload = SteeringNoteAddedEvent(sessionId, "note")),
|
||||
stored(payload = StageFailedEvent(sessionId, stageId, StageId("t2"), "timeout")),
|
||||
stored(payload = WorkflowCompletedEvent(sessionId, stageId, 2, workflowId)),
|
||||
stored(payload = WorkflowCompletedEvent(sessionId, stageId, 2)),
|
||||
)
|
||||
|
||||
val result1 = events.fold(initialState) { state, event ->
|
||||
@@ -155,7 +155,7 @@ class RouterProjectorTest {
|
||||
projector.apply(s1, stored(payload = StageCompletedEvent(sessionId, StageId("stage-2"), StageId("t1"))))
|
||||
val s3 = projector.apply(s2, stored(payload = StageFailedEvent(sessionId, stageId, StageId("t2"), "timeout")))
|
||||
val s4 = projector.apply(s3, stored(payload = WorkflowStartedEvent(sessionId, workflowId, StageId("stage-3"))))
|
||||
val s5 = projector.apply(s4, stored(payload = WorkflowCompletedEvent(sessionId, stageId, 1, workflowId)))
|
||||
val s5 = projector.apply(s4, stored(payload = WorkflowCompletedEvent(sessionId, stageId, 1)))
|
||||
|
||||
assertEquals(WorkflowStatus.RUNNING, s1.workflowStatus)
|
||||
assertEquals(StageId("stage-2"), s2.l2Memory[0].stageId)
|
||||
|
||||
Reference in New Issue
Block a user