feat: externalize LLM providers and tool enable flags via config
Adds ProviderConfig + providers list and per-tool enabled flags to
CorrexConfig, and rewires apps/server/Main to build the provider list
from config instead of the hardcoded buildLlamaProvider() factory. Env
vars (CORREX_MODEL_ID, CORREX_MODEL_PATH, CORREX_LLAMA_URL) remain a
fallback only when no providers are declared in config.
Completes slice A of the config layer alongside commit 0834c70 which
already shipped the TOML parser upgrade and sample config — those
parser changes referenced these types but were committed prematurely
in isolation; this commit makes HEAD buildable.
This commit is contained in:
@@ -6,13 +6,17 @@ import com.correx.apps.server.registry.ProviderRegistry
|
|||||||
import com.correx.core.approvals.domain.DefaultApprovalEngine
|
import com.correx.core.approvals.domain.DefaultApprovalEngine
|
||||||
import com.correx.core.artifactstore.ArtifactStore
|
import com.correx.core.artifactstore.ArtifactStore
|
||||||
import com.correx.core.config.ConfigLoader
|
import com.correx.core.config.ConfigLoader
|
||||||
|
import com.correx.core.config.CorrexConfig
|
||||||
|
import com.correx.core.config.ProviderConfig
|
||||||
import com.correx.core.context.builder.DefaultContextPackBuilder
|
import com.correx.core.context.builder.DefaultContextPackBuilder
|
||||||
import com.correx.core.context.compression.DefaultContextCompressor
|
import com.correx.core.context.compression.DefaultContextCompressor
|
||||||
import com.correx.core.events.EventDispatcher
|
import com.correx.core.events.EventDispatcher
|
||||||
import com.correx.core.events.stores.EventStore
|
import com.correx.core.events.stores.EventStore
|
||||||
|
import com.correx.core.inference.CapabilityScore
|
||||||
import com.correx.core.inference.DefaultInferenceRouter
|
import com.correx.core.inference.DefaultInferenceRouter
|
||||||
import com.correx.core.inference.InferenceProjector
|
import com.correx.core.inference.InferenceProjector
|
||||||
import com.correx.core.inference.InferenceRepository
|
import com.correx.core.inference.InferenceRepository
|
||||||
|
import com.correx.core.inference.ModelCapability
|
||||||
import com.correx.core.kernel.orchestration.DefaultOrchestrationReducer
|
import com.correx.core.kernel.orchestration.DefaultOrchestrationReducer
|
||||||
import com.correx.core.kernel.orchestration.DefaultSessionOrchestrator
|
import com.correx.core.kernel.orchestration.DefaultSessionOrchestrator
|
||||||
import com.correx.core.kernel.orchestration.OrchestrationConfig
|
import com.correx.core.kernel.orchestration.OrchestrationConfig
|
||||||
@@ -37,6 +41,7 @@ import com.correx.infrastructure.inference.DefaultProviderRegistry
|
|||||||
import com.correx.infrastructure.inference.FirstAvailableRoutingStrategy
|
import com.correx.infrastructure.inference.FirstAvailableRoutingStrategy
|
||||||
import com.correx.infrastructure.inference.llama.cpp.LlamaCppInferenceProvider
|
import com.correx.infrastructure.inference.llama.cpp.LlamaCppInferenceProvider
|
||||||
import com.correx.infrastructure.tools.FileEditConfig
|
import com.correx.infrastructure.tools.FileEditConfig
|
||||||
|
import com.correx.infrastructure.tools.FileReadConfig
|
||||||
import com.correx.infrastructure.tools.FileWriteConfig
|
import com.correx.infrastructure.tools.FileWriteConfig
|
||||||
import com.correx.infrastructure.tools.ShellConfig
|
import com.correx.infrastructure.tools.ShellConfig
|
||||||
import com.correx.infrastructure.tools.ToolConfig
|
import com.correx.infrastructure.tools.ToolConfig
|
||||||
@@ -56,17 +61,19 @@ fun main() {
|
|||||||
|
|
||||||
logStoresInfo(eventStore, artifactStore)
|
logStoresInfo(eventStore, artifactStore)
|
||||||
|
|
||||||
val llamaProvider = buildLlamaProvider()
|
val correxConfig = ConfigLoader.load()
|
||||||
val infraRegistry = InfrastructureModule.createProviderRegistry(listOf(llamaProvider))
|
val providers = buildProviders(correxConfig)
|
||||||
val modelId = System.getenv("CORREX_MODEL_ID") ?: "default"
|
require(providers.isNotEmpty()) { "At least one provider must be configured" }
|
||||||
val modelPath = System.getenv("CORREX_MODEL_PATH") ?: "(not set)"
|
val infraRegistry = InfrastructureModule.createProviderRegistry(providers)
|
||||||
val llamaUrl = System.getenv("CORREX_LLAMA_URL") ?: "http://127.0.0.1:10000"
|
val llamaProvider = providers.first()
|
||||||
|
val modelId = llamaProvider.id.value
|
||||||
|
val modelPath = "(from config)"
|
||||||
|
val llamaUrl = "(from config)"
|
||||||
|
|
||||||
logModelInfo(modelId, modelPath, llamaUrl, infraRegistry)
|
logModelInfo(modelId, modelPath, llamaUrl, infraRegistry)
|
||||||
|
|
||||||
val repositories = buildRepositories(eventStore)
|
val repositories = buildRepositories(eventStore)
|
||||||
val approvalEngine = DefaultApprovalEngine()
|
val approvalEngine = DefaultApprovalEngine()
|
||||||
val correxConfig = ConfigLoader.load()
|
|
||||||
val toolsConfig = correxConfig.tools
|
val toolsConfig = correxConfig.tools
|
||||||
val sandboxRoot = System.getenv("CORREX_SANDBOX_ROOT")
|
val sandboxRoot = System.getenv("CORREX_SANDBOX_ROOT")
|
||||||
?.let { Path.of(it) }
|
?.let { Path.of(it) }
|
||||||
@@ -83,6 +90,7 @@ fun main() {
|
|||||||
sandboxRoot,
|
sandboxRoot,
|
||||||
workingDir,
|
workingDir,
|
||||||
shellAllowedExecutables,
|
shellAllowedExecutables,
|
||||||
|
toolsConfig,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
val toolExecutor = InfrastructureModule.createToolExecutor(
|
val toolExecutor = InfrastructureModule.createToolExecutor(
|
||||||
@@ -180,11 +188,58 @@ private fun logStoresInfo(
|
|||||||
log.info(" artifact store: {}", artifactStore::class.simpleName)
|
log.info(" artifact store: {}", artifactStore::class.simpleName)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun buildLlamaProvider(): LlamaCppInferenceProvider = InfrastructureModule.createLlamaCppProvider(
|
private fun buildProviders(config: CorrexConfig): List<LlamaCppInferenceProvider> {
|
||||||
modelId = System.getenv("CORREX_MODEL_ID") ?: "default",
|
return if (config.providers.isNotEmpty()) {
|
||||||
modelPath = System.getenv("CORREX_MODEL_PATH") ?: "",
|
log.info("Loading {} provider(s) from config", config.providers.size)
|
||||||
baseUrl = System.getenv("CORREX_LLAMA_URL") ?: "http://127.0.0.1:10000",
|
config.providers.mapNotNull { providerConfig ->
|
||||||
)
|
when (providerConfig.type.lowercase()) {
|
||||||
|
"llamacpp" -> buildProviderFromConfig(providerConfig)
|
||||||
|
else -> {
|
||||||
|
log.error("Unknown provider type: {}", providerConfig.type)
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.info("No providers in config; using env var fallback")
|
||||||
|
listOf(
|
||||||
|
InfrastructureModule.createLlamaCppProvider(
|
||||||
|
modelId = System.getenv("CORREX_MODEL_ID") ?: "default",
|
||||||
|
modelPath = System.getenv("CORREX_MODEL_PATH") ?: "",
|
||||||
|
baseUrl = System.getenv("CORREX_LLAMA_URL") ?: "http://127.0.0.1:10000",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun buildProviderFromConfig(config: ProviderConfig): LlamaCppInferenceProvider {
|
||||||
|
val capabilities = parseCapabilitiesFromConfig(config.capabilities)
|
||||||
|
return InfrastructureModule.createLlamaCppProvider(
|
||||||
|
modelId = config.modelId,
|
||||||
|
modelPath = config.modelPath,
|
||||||
|
baseUrl = config.url,
|
||||||
|
capabilities = capabilities,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun parseCapabilitiesFromConfig(capsMap: Map<String, Double>): Set<CapabilityScore> {
|
||||||
|
val result = mutableSetOf<CapabilityScore>()
|
||||||
|
capsMap.forEach { (capName, score) ->
|
||||||
|
val capability = when (capName.lowercase()) {
|
||||||
|
"general" -> ModelCapability.General
|
||||||
|
"coding" -> ModelCapability.Coding
|
||||||
|
"reasoning" -> ModelCapability.Reasoning
|
||||||
|
"summarization" -> ModelCapability.Summarization
|
||||||
|
"toolcalling" -> ModelCapability.ToolCalling
|
||||||
|
else -> {
|
||||||
|
log.warn("Unknown capability name: {}", capName)
|
||||||
|
return@forEach
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result.add(CapabilityScore(capability, score))
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
private fun buildRepositories(
|
private fun buildRepositories(
|
||||||
eventStore: EventStore,
|
eventStore: EventStore,
|
||||||
@@ -206,22 +261,27 @@ private fun buildToolConfig(
|
|||||||
sandboxRoot: Path,
|
sandboxRoot: Path,
|
||||||
workingDir: Path,
|
workingDir: Path,
|
||||||
shellAllowedExecutables: Set<String>,
|
shellAllowedExecutables: Set<String>,
|
||||||
|
toolsConfig: com.correx.core.config.ToolsConfig,
|
||||||
): ToolConfig = ToolConfig(
|
): ToolConfig = ToolConfig(
|
||||||
shell = ShellConfig(
|
shell = ShellConfig(
|
||||||
enabled = true,
|
enabled = toolsConfig.shellEnabled,
|
||||||
allowedExecutables = shellAllowedExecutables,
|
allowedExecutables = shellAllowedExecutables,
|
||||||
workingDir = workingDir,
|
workingDir = workingDir,
|
||||||
),
|
),
|
||||||
|
fileRead = FileReadConfig(
|
||||||
|
enabled = toolsConfig.fileReadEnabled,
|
||||||
|
allowedPaths = setOf(sandboxRoot, workingDir),
|
||||||
|
),
|
||||||
fileWrite = FileWriteConfig(
|
fileWrite = FileWriteConfig(
|
||||||
allowedPaths = setOf(sandboxRoot, workingDir),
|
allowedPaths = setOf(sandboxRoot, workingDir),
|
||||||
enabled = true,
|
enabled = toolsConfig.fileWriteEnabled,
|
||||||
artifactStore = artifactStore,
|
artifactStore = artifactStore,
|
||||||
materializingWriter = DefaultMaterializingArtifactWriter(),
|
materializingWriter = DefaultMaterializingArtifactWriter(),
|
||||||
sandboxRoot = sandboxRoot,
|
sandboxRoot = sandboxRoot,
|
||||||
workingDir = workingDir,
|
workingDir = workingDir,
|
||||||
),
|
),
|
||||||
fileEdit = FileEditConfig(
|
fileEdit = FileEditConfig(
|
||||||
enabled = true,
|
enabled = toolsConfig.fileEditEnabled,
|
||||||
allowedPaths = setOf(sandboxRoot, workingDir),
|
allowedPaths = setOf(sandboxRoot, workingDir),
|
||||||
workingDir = workingDir,
|
workingDir = workingDir,
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ data class CorrexConfig(
|
|||||||
val cli: CliConfig = CliConfig(),
|
val cli: CliConfig = CliConfig(),
|
||||||
val approval: ApprovalConfig = ApprovalConfig(),
|
val approval: ApprovalConfig = ApprovalConfig(),
|
||||||
val tools: ToolsConfig = ToolsConfig(),
|
val tools: ToolsConfig = ToolsConfig(),
|
||||||
|
val providers: List<ProviderConfig> = emptyList(),
|
||||||
)
|
)
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
@@ -39,4 +40,18 @@ data class ToolsConfig(
|
|||||||
val workingDir: String = "",
|
val workingDir: String = "",
|
||||||
val shellAllowedExecutables: List<String> = emptyList(),
|
val shellAllowedExecutables: List<String> = emptyList(),
|
||||||
val defaultSystemPromptPath: String = "~/.config/correx/prompts/default_system.md",
|
val defaultSystemPromptPath: String = "~/.config/correx/prompts/default_system.md",
|
||||||
|
val shellEnabled: Boolean = true,
|
||||||
|
val fileReadEnabled: Boolean = true,
|
||||||
|
val fileWriteEnabled: Boolean = true,
|
||||||
|
val fileEditEnabled: Boolean = true,
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class ProviderConfig(
|
||||||
|
val id: String,
|
||||||
|
val type: String,
|
||||||
|
val modelId: String,
|
||||||
|
val modelPath: String = "",
|
||||||
|
val url: String = "http://127.0.0.1:10000",
|
||||||
|
val capabilities: Map<String, Double> = emptyMap(),
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user