fix: orchestrator race conditions, diff preview, session snapshot tools, and test fixes

- Fix duplicate inference requests after approval resume by registering orchestrator
  jobs in activeSessionJobs (ServerModule.launchSessionRun), so the guard in the
  OrchestrationResumedEvent subscription prevents spurious duplicate resume.
- Replace blocking Files.readString in computeToolPreview with withContext(Dispatchers.IO)
  by making the function suspend — no blocking I/O on the coroutine dispatcher.
- Guard orderedIds.add() in rebuildTools against duplicate invocation IDs on replayed
  ToolInvocationRequestedEvent to prevent duplicate tool records in snapshots.
- Add unified-diff preview for file_write tools: computeToolPreview reads existing
  file and generates ---/+++ diff before emitting ApprovalRequestedEvent.
- Render diff preview with color coding in ApprovalSurface (@@ yellow, +/- green/red).
- Include current-stage tool records in SessionSnapshot via rebuildTools event replay.
- Fix RouterContextBuilderTest: recursive buildPack helper and 2 tests using class-level
  builder instead of their local builder instances (conversationKeepLast mismatch).
- Add suspend keyword to RouterFacadeTest mock, fix buildPack recursion.
This commit is contained in:
2026-05-28 15:37:16 +04:00
parent e05532e7b2
commit 57d2237ba0
11 changed files with 230 additions and 82 deletions
@@ -247,7 +247,7 @@ class RouterFacadeTest {
fun `budget is passed through to context builder`(): Unit = runBlocking {
val capturedBudget = mutableListOf<TokenBudget>()
val mockContextBuilder = object : RouterContextBuilder {
override fun build(state: RouterState, budget: TokenBudget): ContextPack {
override suspend fun build(state: RouterState, budget: TokenBudget): ContextPack {
capturedBudget.add(budget)
return emptyContextPack()
}