diff --git a/apps/server/src/main/kotlin/com/correx/apps/server/Main.kt b/apps/server/src/main/kotlin/com/correx/apps/server/Main.kt index 77e3c5b6..2ca7b325 100644 --- a/apps/server/src/main/kotlin/com/correx/apps/server/Main.kt +++ b/apps/server/src/main/kotlin/com/correx/apps/server/Main.kt @@ -6,13 +6,17 @@ import com.correx.apps.server.registry.ProviderRegistry import com.correx.core.approvals.domain.DefaultApprovalEngine import com.correx.core.artifactstore.ArtifactStore 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.compression.DefaultContextCompressor import com.correx.core.events.EventDispatcher import com.correx.core.events.stores.EventStore +import com.correx.core.inference.CapabilityScore import com.correx.core.inference.DefaultInferenceRouter import com.correx.core.inference.InferenceProjector 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.DefaultSessionOrchestrator 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.llama.cpp.LlamaCppInferenceProvider import com.correx.infrastructure.tools.FileEditConfig +import com.correx.infrastructure.tools.FileReadConfig import com.correx.infrastructure.tools.FileWriteConfig import com.correx.infrastructure.tools.ShellConfig import com.correx.infrastructure.tools.ToolConfig @@ -56,17 +61,19 @@ fun main() { logStoresInfo(eventStore, artifactStore) - val llamaProvider = buildLlamaProvider() - val infraRegistry = InfrastructureModule.createProviderRegistry(listOf(llamaProvider)) - val modelId = System.getenv("CORREX_MODEL_ID") ?: "default" - val modelPath = System.getenv("CORREX_MODEL_PATH") ?: "(not set)" - val llamaUrl = System.getenv("CORREX_LLAMA_URL") ?: "http://127.0.0.1:10000" + val correxConfig = ConfigLoader.load() + val providers = buildProviders(correxConfig) + require(providers.isNotEmpty()) { "At least one provider must be configured" } + val infraRegistry = InfrastructureModule.createProviderRegistry(providers) + val llamaProvider = providers.first() + val modelId = llamaProvider.id.value + val modelPath = "(from config)" + val llamaUrl = "(from config)" logModelInfo(modelId, modelPath, llamaUrl, infraRegistry) val repositories = buildRepositories(eventStore) val approvalEngine = DefaultApprovalEngine() - val correxConfig = ConfigLoader.load() val toolsConfig = correxConfig.tools val sandboxRoot = System.getenv("CORREX_SANDBOX_ROOT") ?.let { Path.of(it) } @@ -83,6 +90,7 @@ fun main() { sandboxRoot, workingDir, shellAllowedExecutables, + toolsConfig, ), ) val toolExecutor = InfrastructureModule.createToolExecutor( @@ -180,11 +188,58 @@ private fun logStoresInfo( log.info(" artifact store: {}", artifactStore::class.simpleName) } -private fun buildLlamaProvider(): LlamaCppInferenceProvider = 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 buildProviders(config: CorrexConfig): List { + return if (config.providers.isNotEmpty()) { + log.info("Loading {} provider(s) from config", config.providers.size) + 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): Set { + val result = mutableSetOf() + 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( eventStore: EventStore, @@ -206,22 +261,27 @@ private fun buildToolConfig( sandboxRoot: Path, workingDir: Path, shellAllowedExecutables: Set, + toolsConfig: com.correx.core.config.ToolsConfig, ): ToolConfig = ToolConfig( shell = ShellConfig( - enabled = true, + enabled = toolsConfig.shellEnabled, allowedExecutables = shellAllowedExecutables, workingDir = workingDir, ), + fileRead = FileReadConfig( + enabled = toolsConfig.fileReadEnabled, + allowedPaths = setOf(sandboxRoot, workingDir), + ), fileWrite = FileWriteConfig( allowedPaths = setOf(sandboxRoot, workingDir), - enabled = true, + enabled = toolsConfig.fileWriteEnabled, artifactStore = artifactStore, materializingWriter = DefaultMaterializingArtifactWriter(), sandboxRoot = sandboxRoot, workingDir = workingDir, ), fileEdit = FileEditConfig( - enabled = true, + enabled = toolsConfig.fileEditEnabled, allowedPaths = setOf(sandboxRoot, workingDir), workingDir = workingDir, ), diff --git a/core/config/src/main/kotlin/com/correx/core/config/CorrexConfig.kt b/core/config/src/main/kotlin/com/correx/core/config/CorrexConfig.kt index bccdef2f..2e37a008 100644 --- a/core/config/src/main/kotlin/com/correx/core/config/CorrexConfig.kt +++ b/core/config/src/main/kotlin/com/correx/core/config/CorrexConfig.kt @@ -9,6 +9,7 @@ data class CorrexConfig( val cli: CliConfig = CliConfig(), val approval: ApprovalConfig = ApprovalConfig(), val tools: ToolsConfig = ToolsConfig(), + val providers: List = emptyList(), ) @Serializable @@ -39,4 +40,18 @@ data class ToolsConfig( val workingDir: String = "", val shellAllowedExecutables: List = emptyList(), 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 = emptyMap(), )