feat(router): inject available-workflows and project-profile into router L0 context
This commit is contained in:
@@ -17,11 +17,17 @@ import com.correx.core.router.model.RouterL2Entry
|
||||
import com.correx.core.router.model.RouterState
|
||||
import com.correx.core.router.model.RouterTurn
|
||||
import com.correx.core.router.model.TurnRole
|
||||
import com.correx.core.router.model.WorkflowSummary
|
||||
import java.util.*
|
||||
import kotlinx.coroutines.CancellationException
|
||||
|
||||
interface RouterContextBuilder {
|
||||
suspend fun build(state: RouterState, budget: TokenBudget): ContextPack
|
||||
suspend fun build(
|
||||
state: RouterState,
|
||||
budget: TokenBudget,
|
||||
availableWorkflows: List<WorkflowSummary> = emptyList(),
|
||||
projectProfileText: String? = null,
|
||||
): ContextPack
|
||||
|
||||
/**
|
||||
* Builds a minimal [ContextPack] for a narration inference call.
|
||||
@@ -32,7 +38,7 @@ interface RouterContextBuilder {
|
||||
* without needing a stub override.
|
||||
*/
|
||||
suspend fun buildNarrationContext(state: RouterState, trigger: NarrationTrigger, budget: TokenBudget): ContextPack =
|
||||
build(state, budget)
|
||||
build(state, budget, emptyList(), null)
|
||||
}
|
||||
|
||||
class DefaultRouterContextBuilder(
|
||||
@@ -68,7 +74,12 @@ class DefaultRouterContextBuilder(
|
||||
private const val RECALLED_MEMORY_PREFIX = "[recalled memory]"
|
||||
}
|
||||
|
||||
override suspend fun build(state: RouterState, budget: TokenBudget): ContextPack {
|
||||
override suspend fun build(
|
||||
state: RouterState,
|
||||
budget: TokenBudget,
|
||||
availableWorkflows: List<WorkflowSummary>,
|
||||
projectProfileText: String?,
|
||||
): ContextPack {
|
||||
// Protected frame: system prompt and workflow status are ALWAYS included regardless of budget.
|
||||
val systemPrompt = buildContextEntry(
|
||||
sourceType = "systemPrompt",
|
||||
@@ -84,14 +95,39 @@ class DefaultRouterContextBuilder(
|
||||
layer = ContextLayer.L0,
|
||||
role = EntryRole.SYSTEM,
|
||||
)
|
||||
val availableWorkflowsEntry: ContextEntry? = availableWorkflows
|
||||
.takeIf { it.isNotEmpty() }
|
||||
?.let {
|
||||
buildContextEntry(
|
||||
sourceType = "availableWorkflows",
|
||||
sourceId = "available-workflows",
|
||||
content = buildAvailableWorkflowsContent(it),
|
||||
layer = ContextLayer.L0,
|
||||
role = EntryRole.SYSTEM,
|
||||
)
|
||||
}
|
||||
val projectProfileEntry: ContextEntry? = projectProfileText
|
||||
?.takeIf { it.isNotBlank() }
|
||||
?.let {
|
||||
buildContextEntry(
|
||||
sourceType = "projectProfile",
|
||||
sourceId = "project-profile",
|
||||
content = it,
|
||||
layer = ContextLayer.L0,
|
||||
role = EntryRole.SYSTEM,
|
||||
)
|
||||
}
|
||||
|
||||
// Compute remaining budget after protected frame.
|
||||
val protectedTokens = systemPrompt.tokenEstimate + workflowStatusEntry.tokenEstimate
|
||||
val protectedTokens = systemPrompt.tokenEstimate + workflowStatusEntry.tokenEstimate +
|
||||
(availableWorkflowsEntry?.tokenEstimate ?: 0) + (projectProfileEntry?.tokenEstimate ?: 0)
|
||||
var remainingBudget = (budget.limit - protectedTokens).coerceAtLeast(0)
|
||||
|
||||
val allEntries = mutableListOf<ContextEntry>()
|
||||
allEntries += systemPrompt
|
||||
allEntries += workflowStatusEntry
|
||||
availableWorkflowsEntry?.let { allEntries += it }
|
||||
projectProfileEntry?.let { allEntries += it }
|
||||
|
||||
var droppedCount = 0
|
||||
val truncatedLayers = mutableSetOf<ContextLayer>()
|
||||
@@ -258,6 +294,14 @@ class DefaultRouterContextBuilder(
|
||||
return base + reason + steering
|
||||
}
|
||||
|
||||
private fun buildAvailableWorkflowsContent(workflows: List<WorkflowSummary>): String =
|
||||
buildString {
|
||||
append("## Available workflows\n")
|
||||
workflows.forEach { wf ->
|
||||
append("- ${wf.id}: ${wf.description} (stages: ${wf.stageIds.joinToString(" → ")})\n")
|
||||
}
|
||||
}.trimEnd()
|
||||
|
||||
private suspend fun buildContextEntry(
|
||||
sourceType: String,
|
||||
sourceId: String,
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.correx.core.router.model
|
||||
|
||||
data class WorkflowSummary(
|
||||
val id: String,
|
||||
val description: String,
|
||||
val stageIds: List<String>,
|
||||
)
|
||||
Reference in New Issue
Block a user