in agents/agents-test/src/commonMain/kotlin/ai/koog/agents/testing/tools/MockLLMBuilder.kt [828:932]
public fun build(): PromptExecutor {
// Exact Matches
val processedAssistantExactMatches = assistantExactMatches.mapValues { (_, value) ->
val texts = value.map { text -> text.trimIndent() }
texts.map { text ->
Message.Assistant(
text,
ResponseMetaInfo.create(
clock,
inputTokensCount = null, // Will be updated at runtime with actual input
outputTokensCount = tokenizer?.countTokens(text),
totalTokensCount = null // Will be calculated at runtime
)
)
}
}
val combinedExactMatches =
(processedAssistantExactMatches.keys + toolCallExactMatches.keys).associateWith { key ->
val assistantList = processedAssistantExactMatches[key] ?: emptyList()
val toolCallList = toolCallExactMatches[key] ?: emptyList()
assistantList + toolCallList
}
// Partial Matches
val processedAssistantPartialMatches = assistantPartialMatches.mapValues { (_, value) ->
val texts = value.map { text -> text.trimIndent() }
texts.map { text ->
Message.Assistant(
text,
ResponseMetaInfo.create(
clock,
inputTokensCount = null, // Will be updated at runtime with actual input
outputTokensCount = tokenizer?.countTokens(text),
totalTokensCount = null // Will be calculated at runtime
)
)
}
}
val combinedPartialMatches =
(processedAssistantPartialMatches.keys + toolCallPartialMatches.keys).associateWith { key ->
val assistantList = processedAssistantPartialMatches[key] ?: emptyList()
val toolCallList = toolCallPartialMatches[key] ?: emptyList()
assistantList + toolCallList
}
// Conditional Matches
val processedAssistantConditionalMatches: Map<(String) -> Boolean, List<Message.Response>> =
conditionalResponses.takeIf { it.isNotEmpty() }?.mapValues { (_, textResponse) ->
textResponse.map { response ->
Message.Assistant(
content = response,
metaInfo = ResponseMetaInfo.create(
clock,
inputTokensCount = null, // Cannot determine input tokens for conditional matches without the actual input string
outputTokensCount = tokenizer?.countTokens(response),
totalTokensCount = null // Will be calculated at runtime
)
)
}
} ?: emptyMap()
val combinedConditionalMatches =
(processedAssistantConditionalMatches.keys + toolCallConditionalMatches.keys).associateWith { key ->
buildList {
processedAssistantConditionalMatches[key]?.let { addAll(it) }
toolCallConditionalMatches[key]?.let { addAll(it) }
}
}
val responseMatcher = ResponseMatcher(
partialMatches = combinedPartialMatches.takeIf { it.isNotEmpty() },
exactMatches = combinedExactMatches.takeIf { it.isNotEmpty() },
conditional = combinedConditionalMatches,
defaultResponse = listOf(
Message.Assistant(
defaultResponse,
ResponseMetaInfo.create(
clock,
inputTokensCount = null, // Will be updated at runtime with actual input
outputTokensCount = tokenizer?.countTokens(defaultResponse),
totalTokensCount = null // Will be calculated at runtime
)
)
)
)
val moderationResponseMatcher = ResponseMatcher(
partialMatches = moderationPartialMatches,
exactMatches = moderationExactMatches,
conditional = null, // TODO: support later once required
defaultResponse = defaultModerationResponse
)
return MockLLMExecutor(
handleLastAssistantMessage,
responseMatcher = responseMatcher,
moderationResponseMatcher = moderationResponseMatcher,
toolRegistry = toolRegistry,
toolActions = toolActions,
clock = clock,
tokenizer = tokenizer
)
}