feat: implement CreateGrant handler and grant-aware approval engine

- GlobalStreamHandler.handleCreateGrant validates scope (SESSION/STAGE)
  and sends ProtocolError to client on validation failure instead of
  silent log.warn + drop.
- Derive event stageId directly from GrantScope type, removing
  redundant stageIdForEvent tuple.
- SessionOrchestrator integrates ApprovalEngine to check active grants
  before requesting user approval for T2+ tool calls.
- ContextEntry gains EntryRole (SYSTEM/USER/ASSISTANT/TOOL) field for
  proper chat message role mapping.
- RouterContextBuilder.build is now suspend; uses Tokenizer for
  accurate token estimation with fallback to character-based estimate.
- LlamaCppInferenceProvider maps EntryRole to ChatMessage role instead
  of heuristic layer-based inference.
This commit is contained in:
2026-05-28 14:06:58 +04:00
parent 92bea6c2c4
commit e05532e7b2
11 changed files with 316 additions and 133 deletions
@@ -10,6 +10,7 @@ import com.correx.core.events.EventDispatcher
import com.correx.core.events.stores.EventStore
import com.correx.core.inference.InferenceProvider
import com.correx.core.inference.InferenceRouter
import com.correx.core.inference.Tokenizer
import com.correx.core.router.DefaultRouterContextBuilder
import com.correx.core.router.DefaultRouterFacade
import com.correx.core.router.DefaultRouterReducer
@@ -120,12 +121,13 @@ object InfrastructureModule {
eventStore: EventStore,
inferenceRouter: InferenceRouter,
config: RouterConfig = RouterConfig(),
tokenizer: Tokenizer? = null,
): RouterFacade {
val reducer = DefaultRouterReducer()
val projector = RouterProjector(reducer)
val replayer = DefaultEventReplayer(eventStore, projector)
val repository = DefaultRouterRepository(replayer)
val contextBuilder = DefaultRouterContextBuilder(config)
val contextBuilder = DefaultRouterContextBuilder(config, tokenizer)
return DefaultRouterFacade(repository, contextBuilder, inferenceRouter, eventStore, config)
}
}