diff --git a/README.md b/README.md index 2d48d308ae..59f44f5403 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,14 @@ -# Xiiu(X=>)per +# AutoDev 3.0 - Xiu(X=>)per (Work in Progress) > The full platform supported AI4SDLC agents. +For Autodev 2.0 (Stable version) + +- branch: https://github.com/phodal/auto-dev/tree/autodev2 +- Intellij Plugin: https://plugins.jetbrains.com/plugin/26988 + +For AutoDev 3.0 (Development version) + - Intellij Plugin: https://plugins.jetbrains.com/plugin/29223-autodev-experiment - VSCode Extension**: [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=Phodal.autodev) - Web Version: https://phodal.github.io/auto-dev/ diff --git a/mpp-idea/build.gradle.kts b/mpp-idea/build.gradle.kts index 3814d4bc9c..3955c1736c 100644 --- a/mpp-idea/build.gradle.kts +++ b/mpp-idea/build.gradle.kts @@ -91,9 +91,9 @@ configurations.all { // pty4j/jediterm - IDEA has its own terminal (~3MB) exclude(group = "org.jetbrains.pty4j") exclude(group = "org.jetbrains.jediterm") - // Exclude Ktor serialization modules that conflict with IntelliJ's bundled versions - exclude(group = "io.ktor", module = "ktor-serialization-kotlinx-json") - exclude(group = "io.ktor", module = "ktor-serialization-kotlinx-json-jvm") + // Note: ktor-serialization-kotlinx-json is NOT excluded globally because it's required + // by ai.koog:prompt-executor-llms-all (AbstractOpenAILLMClient) at runtime. + // It's included as an explicit dependency with coroutines excluded below. } @@ -317,7 +317,17 @@ project(":") { compileOnly("io.ktor:ktor-client-core:3.2.2") compileOnly("io.ktor:ktor-client-cio:3.2.2") compileOnly("io.ktor:ktor-client-content-negotiation:3.2.2") - compileOnly("io.ktor:ktor-serialization-kotlinx-json:3.2.2") + // ktor-serialization-kotlinx-json is required at runtime by ai.koog:prompt-executor-llms-all + // (AbstractOpenAILLMClient uses JsonSupportKt for HTTP content negotiation) + // Must exclude coroutines to avoid conflicts with IntelliJ's bundled version + implementation("io.ktor:ktor-serialization-kotlinx-json:3.2.2") { + exclude(group = "org.jetbrains.kotlinx", module = "kotlinx-coroutines-core") + exclude(group = "org.jetbrains.kotlinx", module = "kotlinx-coroutines-core-jvm") + exclude(group = "org.jetbrains.kotlinx", module = "kotlinx-serialization-json") + exclude(group = "org.jetbrains.kotlinx", module = "kotlinx-serialization-json-jvm") + exclude(group = "org.jetbrains.kotlinx", module = "kotlinx-serialization-core") + exclude(group = "org.jetbrains.kotlinx", module = "kotlinx-serialization-core-jvm") + } compileOnly("io.ktor:ktor-client-logging:3.2.2") // Use compileOnly for coroutines - IntelliJ provides these at runtime diff --git a/mpp-idea/mpp-idea-core/src/main/resources/META-INF/autodev-core.xml b/mpp-idea/mpp-idea-core/src/main/resources/META-INF/autodev-core.xml new file mode 100644 index 0000000000..4cd2120546 --- /dev/null +++ b/mpp-idea/mpp-idea-core/src/main/resources/META-INF/autodev-core.xml @@ -0,0 +1,558 @@ + + messages.AutoDevBundle + + com.intellij.modules.platform + com.intellij.modules.lang + Git4Idea + + com.intellij.modules.json + Docker + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + cc.unitmesh.devti.intentions.AutoDevIntentionHelper + intention.category.llm + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + cc.unitmesh.devti.intentions.action.NewChatWithCodeBaseIntention + messages.AutoDevBundle + intention.category.llm + + + cc.unitmesh.devti.intentions.action.AutoTestThisIntention + messages.AutoDevBundle + intention.category.llm + + + cc.unitmesh.devti.intentions.action.DefaultDocumentationBaseIntention + messages.AutoDevBundle + intention.category.llm + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/mpp-idea/mpp-idea-core/src/main/resources/META-INF/docker.xml b/mpp-idea/mpp-idea-core/src/main/resources/META-INF/docker.xml new file mode 100644 index 0000000000..6e5a3a08ce --- /dev/null +++ b/mpp-idea/mpp-idea-core/src/main/resources/META-INF/docker.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/mpp-idea/mpp-idea-core/src/main/resources/META-INF/json-contrib.xml b/mpp-idea/mpp-idea-core/src/main/resources/META-INF/json-contrib.xml new file mode 100644 index 0000000000..1f2ed68710 --- /dev/null +++ b/mpp-idea/mpp-idea-core/src/main/resources/META-INF/json-contrib.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/tool/IdeaToolProvider.kt b/mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/tool/IdeaToolProvider.kt new file mode 100644 index 0000000000..07a1e27f03 --- /dev/null +++ b/mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/tool/IdeaToolProvider.kt @@ -0,0 +1,82 @@ +package cc.unitmesh.devins.idea.tool + +import cc.unitmesh.agent.tool.ExecutableTool +import cc.unitmesh.devti.provider.toolchain.ToolchainFunctionProvider +import com.intellij.openapi.project.Project +import kotlinx.coroutines.runBlocking + +/** + * ToolProvider implementation for IntelliJ IDEA. + * Collects all ToolchainFunctionProvider extensions and wraps them as ExecutableTools. + * + * This bridges the gap between IDEA's extension point system and mpp-core's tool registry, + * allowing IDEA-specific tools (like database, knowledge, component view, etc.) to be + * used by CodingAgent through the unified ToolOrchestrator. + * + * @param project The IntelliJ Project context required by ToolchainFunctionProvider + */ +class IdeaToolProvider(private val project: Project) { + + /** + * Provide all IDEA tools from ToolchainFunctionProvider extensions. + * This method does not require ToolDependencies as IDEA tools use Project context instead. + */ + fun provideTools(): List> { + val providers = ToolchainFunctionProvider.all() + val tools = mutableListOf>() + + for (provider in providers) { + try { + // Get tool infos from the provider + val toolInfos = runBlocking { provider.toolInfos(project) } + + // Create an adapter for each tool + for (agentTool in toolInfos) { + val adapter = ToolchainFunctionAdapter( + provider = provider, + project = project, + agentTool = agentTool + ) + tools.add(adapter) + } + + // If no toolInfos, try to create tools from funcNames + if (toolInfos.isEmpty()) { + val funcNames = runBlocking { provider.funcNames() } + for (funcName in funcNames) { + // Check if this provider is applicable for this function + val isApplicable = runBlocking { provider.isApplicable(project, funcName) } + if (isApplicable) { + val agentTool = cc.unitmesh.devti.agent.tool.AgentTool( + name = funcName, + description = "IDEA tool: $funcName", + example = "/$funcName" + ) + val adapter = ToolchainFunctionAdapter( + provider = provider, + project = project, + agentTool = agentTool + ) + tools.add(adapter) + } + } + } + } catch (e: Exception) { + // Log and continue with other providers + println("Warning: Failed to load tools from ${provider::class.simpleName}: ${e.message}") + } + } + + return tools + } + + companion object { + /** + * Create an IdeaToolProvider for the given project. + */ + fun create(project: Project): IdeaToolProvider { + return IdeaToolProvider(project) + } + } +} + diff --git a/mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/tool/ToolchainFunctionAdapter.kt b/mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/tool/ToolchainFunctionAdapter.kt new file mode 100644 index 0000000000..399a04213b --- /dev/null +++ b/mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/tool/ToolchainFunctionAdapter.kt @@ -0,0 +1,129 @@ +package cc.unitmesh.devins.idea.tool + +import cc.unitmesh.agent.tool.* +import cc.unitmesh.agent.tool.schema.DeclarativeToolSchema +import cc.unitmesh.agent.tool.schema.SchemaProperty +import cc.unitmesh.agent.tool.schema.SchemaPropertyBuilder +import cc.unitmesh.agent.tool.schema.ToolCategory +import cc.unitmesh.devti.agent.tool.AgentTool +import cc.unitmesh.devti.provider.toolchain.ToolchainFunctionProvider +import com.intellij.openapi.project.Project + +/** + * Parameters for ToolchainFunctionProvider execution. + * Uses a generic Map to support various parameter types from different providers. + */ +data class ToolchainFunctionParams( + val prop: String = "", + val args: List = emptyList(), + val allVariables: Map = emptyMap() +) + +/** + * Schema for ToolchainFunctionProvider tools. + * Provides a generic schema that accepts prop, args, and variables. + */ +class ToolchainFunctionSchema( + private val toolDescription: String, + private val example: String = "" +) : DeclarativeToolSchema( + description = toolDescription, + properties = mapOf( + "prop" to SchemaPropertyBuilder.string( + description = "Property or sub-command for the tool", + required = false + ), + "args" to SchemaProperty( + type = "array", + description = "Arguments to pass to the tool", + required = false, + items = SchemaProperty(type = "string", description = "Argument value") + ), + "allVariables" to SchemaProperty( + type = "object", + description = "Additional variables for the tool execution", + required = false, + additionalProperties = true + ) + ) +) { + override fun getExampleUsage(toolName: String): String { + return if (example.isNotEmpty()) example else "/$toolName" + } +} + +/** + * Adapter that wraps a ToolchainFunctionProvider as an ExecutableTool. + * This allows IDEA-specific tools to be used in mpp-core's ToolOrchestrator. + * + * @param provider The ToolchainFunctionProvider to wrap + * @param project The IntelliJ Project context + * @param agentTool The AgentTool metadata from the provider + */ +class ToolchainFunctionAdapter( + private val provider: ToolchainFunctionProvider, + private val project: Project, + private val agentTool: AgentTool +) : BaseExecutableTool() { + + override val name: String = agentTool.name + override val description: String = agentTool.description + + override val metadata: ToolMetadata = ToolMetadata( + displayName = agentTool.name.replace("_", " ").replaceFirstChar { it.uppercase() }, + tuiEmoji = "🔧", + composeIcon = "extension", + category = ToolCategory.Utility, + schema = ToolchainFunctionSchema(agentTool.description, agentTool.example) + ) + + override fun getParameterClass(): String = ToolchainFunctionParams::class.simpleName ?: "ToolchainFunctionParams" + + override fun createToolInvocation(params: ToolchainFunctionParams): ToolInvocation { + return ToolchainFunctionInvocation(params, this, provider, project, agentTool.name) + } +} + +/** + * ToolInvocation implementation for ToolchainFunctionProvider. + */ +class ToolchainFunctionInvocation( + override val params: ToolchainFunctionParams, + override val tool: ExecutableTool, + private val provider: ToolchainFunctionProvider, + private val project: Project, + private val funcName: String +) : ToolInvocation { + + override fun getDescription(): String { + return "Execute ${tool.name} with prop='${params.prop}'" + } + + override fun getToolLocations(): List = emptyList() + + override suspend fun execute(context: ToolExecutionContext): ToolResult { + return try { + val result = provider.execute( + project = project, + prop = params.prop, + args = params.args, + allVariables = params.allVariables, + commandName = funcName + ) + + // Convert the result to ToolResult + when (result) { + is String -> ToolResult.Success(result) + is ToolResult -> result + else -> ToolResult.Success(result.toString()) + } + } catch (e: Exception) { + ToolResult.Error( + message = "Failed to execute ${tool.name}: ${e.message}", + errorType = "EXECUTION_ERROR", + metadata = mapOf("exception" to (e::class.simpleName ?: "Unknown")) + ) + } + } +} + diff --git a/mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/toolwindow/IdeaAgentViewModel.kt b/mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/toolwindow/IdeaAgentViewModel.kt index 4ff5d18950..4e9741d75c 100644 --- a/mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/toolwindow/IdeaAgentViewModel.kt +++ b/mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/toolwindow/IdeaAgentViewModel.kt @@ -13,6 +13,7 @@ import cc.unitmesh.devins.compiler.service.DevInsCompilerService import cc.unitmesh.devins.idea.compiler.IdeaDevInsCompilerService import cc.unitmesh.devins.idea.renderer.JewelRenderer import cc.unitmesh.devins.idea.services.IdeaToolConfigService +import cc.unitmesh.devins.idea.tool.IdeaToolProvider import cc.unitmesh.devins.ui.config.AutoDevConfigWrapper import cc.unitmesh.devins.ui.config.ConfigManager import cc.unitmesh.llm.KoogLLMService @@ -261,6 +262,10 @@ class IdeaAgentViewModel( mcpToolConfigService = mcpToolConfigService, enableLLMStreaming = true ) + + // Register IDEA-specific tools from ToolchainFunctionProvider extensions + registerIdeaTools(codingAgent!!) + agentInitialized = true // Start observing PlanStateService and sync to renderer @@ -269,6 +274,27 @@ class IdeaAgentViewModel( return codingAgent!! } + /** + * Register IDEA-specific tools from ToolchainFunctionProvider extensions. + * This bridges IDEA's extension point system with mpp-core's tool registry. + */ + private fun registerIdeaTools(agent: CodingAgent) { + try { + val ideaToolProvider = IdeaToolProvider.create(project) + val ideaTools = ideaToolProvider.provideTools() + + for (tool in ideaTools) { + agent.registerTool(tool) + } + + if (ideaTools.isNotEmpty()) { + println("Registered ${ideaTools.size} IDEA tools from ToolchainFunctionProvider extensions") + } + } catch (e: Exception) { + println("Warning: Failed to register IDEA tools: ${e.message}") + } + } + // Job for observing PlanStateService private var planStateObserverJob: Job? = null