fix: store actual rendered prompt artifact instead of contextpack.toString()

Extract message-rendering logic from LlamaCppInferenceProvider into a
provider-agnostic PromptRenderer in core:inference. SessionOrchestrator
now serializes the rendered ChatMessage list as JSON for the prompt
artifact, so the audit trail reflects what the LLM actually saw.

Resolves the TODO at SessionOrchestrator.kt:691.
This commit is contained in:
2026-05-30 00:32:38 +04:00
parent f922b855eb
commit d276148e2c
4 changed files with 57 additions and 36 deletions
@@ -0,0 +1,41 @@
package com.correx.core.inference
import com.correx.core.context.model.ContextLayer
import com.correx.core.context.model.ContextPack
import com.correx.core.context.model.EntryRole
import kotlinx.serialization.Serializable
@Serializable
data class ChatMessage(
val role: String,
val content: String,
)
object PromptRenderer {
fun render(contextPack: ContextPack): List<ChatMessage> {
val sorted = contextPack.layers.entries.sortedBy { it.key.ordinal }
val systemContent = sorted
.filter { it.key == ContextLayer.L0 }
.flatMap { it.value }
.joinToString("\n\n") { it.content }
.takeIf { it.isNotBlank() }
val conversationMessages = sorted.filter { it.key != ContextLayer.L0 }.flatMap { (_, entries) ->
entries.map { entry ->
ChatMessage(
role = when (entry.role) {
EntryRole.SYSTEM -> "system"
EntryRole.ASSISTANT -> "assistant"
EntryRole.TOOL -> "tool"
EntryRole.USER -> "user"
},
content = entry.content,
)
}
}
val messages = buildList {
systemContent?.let { add(ChatMessage("system", it)) }
addAll(conversationMessages)
}
return messages.ifEmpty { listOf(ChatMessage("user", "")) }
}
}
@@ -61,6 +61,7 @@ import com.correx.core.inference.InferenceRepository
import com.correx.core.inference.InferenceRequest
import com.correx.core.inference.InferenceResponse
import com.correx.core.inference.InferenceRouter
import com.correx.core.inference.PromptRenderer
import com.correx.core.inference.ResponseFormat
import com.correx.core.inference.Tokenizer
import com.correx.core.inference.ToolCallRequest
@@ -91,6 +92,7 @@ import kotlinx.coroutines.TimeoutCancellationException
import kotlinx.coroutines.withContext
import kotlinx.coroutines.withTimeout
import kotlinx.datetime.Clock
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonObject
import org.slf4j.LoggerFactory
@@ -688,8 +690,8 @@ abstract class SessionOrchestrator(
),
)
// TODO: capture rendered prompt; currently contextpack.toString()
val promptArtifactId = artifactStore.put(contextPack.toString().toByteArray())
val renderedMessages = PromptRenderer.render(contextPack)
val promptArtifactId = artifactStore.put(Json.encodeToString(renderedMessages).toByteArray())
emit(sessionId, InferenceStartedEvent(requestId, sessionId, stageId, provider.id, promptArtifactId))
if (isCancelled(sessionId)) return InferenceResult.Cancelled