-
Notifications
You must be signed in to change notification settings - Fork 1
feat: add pluggable DevInsCompilerService for switchable compiler core #24
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
* chore(plugin): update plugin name, vendor email, and description Renamed plugin to "AutoDev Next", updated vendor email, and revised description for clarity. * feat(ui): add platform-specific UTF-8 font support Introduce getUtf8FontFamily() for proper CJK/UTF-8 rendering on WASM using Noto Sans SC, while other platforms use system defaults. Also exclude heavy dependencies and large font assets from the IntelliJ plugin build to reduce size.
- Add DevInsCompilerService interface in mpp-core with global instance management - Add DefaultDevInsCompilerService using mpp-core's AST-based compiler - Add IdeaDevInsCompilerService in mpp-idea using devins-lang's PSI-based compiler - Modify KoogLLMService to accept optional compiler service injection - Update IdeaAgentViewModel to inject IDEA compiler for full IDE feature support - Add unit tests for DevInsCompilerService This enables mpp-idea to use the full-featured PSI-based DevInsCompiler with IDE capabilities (Symbol resolution, Refactor, Database, etc.) while CLI/Desktop continues using the cross-platform AST-based compiler.
WalkthroughIntroduces a pluggable DevIns compiler service infrastructure with core/default/IDEA implementations, wires it into KoogLLMService and IDE integration, refactors font selection across platforms to a unified API, and updates plugin metadata alongside build optimizations. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes
Possibly related PRs
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Review completed. 3 suggestions posted.
Comment augment review to trigger a new review at any time.
| * 注册为全局编译器服务 | ||
| * 应在 IDEA 插件启动时调用 | ||
| */ | ||
| fun registerAsGlobal(project: Project, editor: Editor? = null) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
registerAsGlobal stores a Project in a global singleton with no disposal, which can leak the Project after it closes; consider using a project-scoped service or resetting on project dispose. (Guideline: no_memory_leaks) (Guideline: no_memory_leaks)
🤖 Was this useful? React with 👍 or 👎
| textStyle = | ||
| TextStyle( | ||
| fontFamily = if (Platform.isWasm) FontFamily(Font(Res.font.NotoSansSC_Regular)) else FontFamily.Monospace, | ||
| fontFamily = getUtf8FontFamily(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The editor input now uses the default font family; for code-like input, a monospace font preserves alignment and readability across platforms. Consider keeping a monospace family while still handling UTF-8 fallbacks.
🤖 Was this useful? React with 👍 or 👎
|
|
||
| if (compiledResult.hasError) { | ||
| logger.warn { "⚠️ [KoogLLMService] 编译错误: ${compiledResult.errorMessage}" } | ||
| logger.warn { "⚠️ [KoogLLMService] 编译错误 (${actualCompilerService.getName()}): ${compiledResult.errorMessage}" } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When using the IDEA compiler, errorMessage is always null (converter sets it null), so this log prints "null" even when hasError=true. Consider logging hasError or mapping an error description to avoid "null" in logs.
🤖 Was this useful? React with 👍 or 👎
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (4)
mpp-idea/src/main/resources/META-INF/plugin.xml (1)
4-4: Consider clarifying plugin name vs. description branding.The plugin name is now "AutoDev Next" (line 4), but the description uses "AutoDev Idea" (line 8). This naming inconsistency may confuse users about what the plugin is actually called and what "AutoDev Idea" refers to.
If "AutoDev Idea" is intentional as a module-level descriptor, consider clarifying it in the description (e.g., "AutoDev Idea module provides..."). Otherwise, align both to use the same primary branding name.
Also applies to: 8-8
mpp-core/src/commonMain/kotlin/cc/unitmesh/agent/CodingAgent.kt (1)
88-90: Validate impact of highercontentThresholdand consider making it configurableBumping
contentThresholdto 15000 may increase latency and risk hitting model context limits depending onModelConfig.default()and the underlying LLM. Consider wiring this through configuration (or deriving it from the active model’s max context) instead of hard‑coding the value, and verify that this size is safe for all supported models/runtimes.mpp-core/src/commonMain/kotlin/cc/unitmesh/devins/compiler/service/DevInsCompilerService.kt (1)
81-83: Consider caching the default compiler instance.The current implementation creates a new
DefaultDevInsCompilerService()instance on every call togetInstance()when no global instance is set. This is inconsistent with typical singleton patterns and could lead to unexpected behavior.Since
actualCompilerServiceinKoogLLMServiceis aget()property that callsgetInstance()every time it's accessed, this could create multiple compiler instances unnecessarily.Apply this diff to cache the default instance:
fun getInstance(): DevInsCompilerService { - return instance ?: DefaultDevInsCompilerService() + return instance ?: DefaultDevInsCompilerService().also { instance = it } }Alternatively, if the intention is to allow per-call instances, consider renaming the method to better reflect this behavior:
- fun getInstance(): DevInsCompilerService { + fun getOrCreateDefault(): DevInsCompilerService { return instance ?: DefaultDevInsCompilerService() }mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/compiler/IdeaDevInsCompilerService.kt (1)
41-48: Track the TODO for variable support.The TODO comment indicates that custom variable injection is not yet implemented in the IDEA compiler service. This could lead to inconsistent behavior between the default and IDEA compilers when variables are provided.
Would you like me to:
- Open a new issue to track this implementation?
- Provide a code snippet showing how to inject variables into the IDEA compiler's VariableTable?
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (18)
mpp-core/src/commonMain/kotlin/cc/unitmesh/agent/CodingAgent.kt(1 hunks)mpp-core/src/commonMain/kotlin/cc/unitmesh/devins/compiler/service/DefaultDevInsCompilerService.kt(1 hunks)mpp-core/src/commonMain/kotlin/cc/unitmesh/devins/compiler/service/DevInsCompilerService.kt(1 hunks)mpp-core/src/commonMain/kotlin/cc/unitmesh/llm/KoogLLMService.kt(3 hunks)mpp-core/src/jvmTest/kotlin/cc/unitmesh/devins/compiler/service/DevInsCompilerServiceTest.kt(1 hunks)mpp-idea/build.gradle.kts(3 hunks)mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/compiler/IdeaDevInsCompilerService.kt(1 hunks)mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/toolwindow/IdeaAgentViewModel.kt(3 hunks)mpp-idea/src/main/resources/META-INF/plugin.xml(1 hunks)mpp-ui/build.gradle.kts(1 hunks)mpp-ui/src/androidMain/kotlin/cc/unitmesh/devins/ui/compose/sketch/CodeFont.android.kt(2 hunks)mpp-ui/src/commonMain/kotlin/cc/unitmesh/devins/ui/compose/agent/AgentMessageList.kt(2 hunks)mpp-ui/src/commonMain/kotlin/cc/unitmesh/devins/ui/compose/editor/DevInEditorInput.kt(2 hunks)mpp-ui/src/commonMain/kotlin/cc/unitmesh/devins/ui/compose/sketch/CodeFont.kt(2 hunks)mpp-ui/src/iosMain/kotlin/cc/unitmesh/devins/ui/compose/sketch/CodeFont.ios.kt(2 hunks)mpp-ui/src/jsMain/kotlin/cc/unitmesh/devins/ui/compose/sketch/CodeFont.js.kt(2 hunks)mpp-ui/src/jvmMain/kotlin/cc/unitmesh/devins/ui/compose/sketch/CodeFont.jvm.kt(2 hunks)mpp-ui/src/wasmJsMain/kotlin/cc/unitmesh/devins/ui/compose/sketch/CodeFont.wasmJs.kt(1 hunks)
🧰 Additional context used
📓 Path-based instructions (5)
**/*.kt
📄 CodeRabbit inference engine (AGENTS.md)
Use
expect/actualfor platform-specific code in KMP projects (e.g., file I/O on JVM/JS/Wasm)
Files:
mpp-core/src/commonMain/kotlin/cc/unitmesh/devins/compiler/service/DevInsCompilerService.ktmpp-ui/src/commonMain/kotlin/cc/unitmesh/devins/ui/compose/sketch/CodeFont.ktmpp-ui/src/iosMain/kotlin/cc/unitmesh/devins/ui/compose/sketch/CodeFont.ios.ktmpp-core/src/commonMain/kotlin/cc/unitmesh/devins/compiler/service/DefaultDevInsCompilerService.ktmpp-ui/src/jsMain/kotlin/cc/unitmesh/devins/ui/compose/sketch/CodeFont.js.ktmpp-ui/src/jvmMain/kotlin/cc/unitmesh/devins/ui/compose/sketch/CodeFont.jvm.ktmpp-ui/src/wasmJsMain/kotlin/cc/unitmesh/devins/ui/compose/sketch/CodeFont.wasmJs.ktmpp-ui/src/commonMain/kotlin/cc/unitmesh/devins/ui/compose/agent/AgentMessageList.ktmpp-ui/src/commonMain/kotlin/cc/unitmesh/devins/ui/compose/editor/DevInEditorInput.ktmpp-core/src/jvmTest/kotlin/cc/unitmesh/devins/compiler/service/DevInsCompilerServiceTest.ktmpp-core/src/commonMain/kotlin/cc/unitmesh/agent/CodingAgent.ktmpp-ui/src/androidMain/kotlin/cc/unitmesh/devins/ui/compose/sketch/CodeFont.android.ktmpp-core/src/commonMain/kotlin/cc/unitmesh/llm/KoogLLMService.ktmpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/compiler/IdeaDevInsCompilerService.ktmpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/toolwindow/IdeaAgentViewModel.kt
{mpp-core,mpp-ui}/**/*.kt
📄 CodeRabbit inference engine (AGENTS.md)
Check export first in mpp-core and mpp-ui; if some functions are not working well with CLI (TypeScript), verify @JsExport usage
Files:
mpp-core/src/commonMain/kotlin/cc/unitmesh/devins/compiler/service/DevInsCompilerService.ktmpp-ui/src/commonMain/kotlin/cc/unitmesh/devins/ui/compose/sketch/CodeFont.ktmpp-ui/src/iosMain/kotlin/cc/unitmesh/devins/ui/compose/sketch/CodeFont.ios.ktmpp-core/src/commonMain/kotlin/cc/unitmesh/devins/compiler/service/DefaultDevInsCompilerService.ktmpp-ui/src/jsMain/kotlin/cc/unitmesh/devins/ui/compose/sketch/CodeFont.js.ktmpp-ui/src/jvmMain/kotlin/cc/unitmesh/devins/ui/compose/sketch/CodeFont.jvm.ktmpp-ui/src/wasmJsMain/kotlin/cc/unitmesh/devins/ui/compose/sketch/CodeFont.wasmJs.ktmpp-ui/src/commonMain/kotlin/cc/unitmesh/devins/ui/compose/agent/AgentMessageList.ktmpp-ui/src/commonMain/kotlin/cc/unitmesh/devins/ui/compose/editor/DevInEditorInput.ktmpp-core/src/jvmTest/kotlin/cc/unitmesh/devins/compiler/service/DevInsCompilerServiceTest.ktmpp-core/src/commonMain/kotlin/cc/unitmesh/agent/CodingAgent.ktmpp-ui/src/androidMain/kotlin/cc/unitmesh/devins/ui/compose/sketch/CodeFont.android.ktmpp-core/src/commonMain/kotlin/cc/unitmesh/llm/KoogLLMService.kt
**/jsMain/**/*.kt
📄 CodeRabbit inference engine (AGENTS.md)
**/jsMain/**/*.kt: In Kotlin/JS @JsExport: AvoidFlow, usePromiseinstead
In Kotlin/JS @JsExport: Use concrete classes as return types and parameter types, avoid interface types (JS cannot correctly handle interface type conversion)
Files:
mpp-ui/src/jsMain/kotlin/cc/unitmesh/devins/ui/compose/sketch/CodeFont.js.kt
**/src/{androidMain,desktopMain}/**/*.kt
📄 CodeRabbit inference engine (AGENTS.md)
For Compose (Desktop/Android), use
AutoDevColorsfromcc.unitmesh.devins.ui.compose.themeorMaterialTheme.colorScheme
Files:
mpp-ui/src/androidMain/kotlin/cc/unitmesh/devins/ui/compose/sketch/CodeFont.android.kt
{mpp-ui/src/jsMain/typescript/**/*.{ts,tsx},**/src/{androidMain,desktopMain}/**/*.kt}
📄 CodeRabbit inference engine (AGENTS.md)
DO NOT hardcode colors (e.g.,
Color(0xFF...)or#hex). Always use design tokens for consistency across platforms
Files:
mpp-ui/src/androidMain/kotlin/cc/unitmesh/devins/ui/compose/sketch/CodeFont.android.kt
🧠 Learnings (8)
📚 Learning: 2025-11-30T02:30:49.805Z
Learnt from: CR
Repo: phodal/auto-dev-sketch PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-30T02:30:49.805Z
Learning: Applies to **/wasmMain/**/*.kt : For WASM platform, do not use emoji and utf8 in code
Applied to files:
mpp-ui/build.gradle.ktsmpp-ui/src/commonMain/kotlin/cc/unitmesh/devins/ui/compose/sketch/CodeFont.ktmpp-ui/src/iosMain/kotlin/cc/unitmesh/devins/ui/compose/sketch/CodeFont.ios.ktmpp-ui/src/jsMain/kotlin/cc/unitmesh/devins/ui/compose/sketch/CodeFont.js.ktmpp-ui/src/wasmJsMain/kotlin/cc/unitmesh/devins/ui/compose/sketch/CodeFont.wasmJs.ktmpp-ui/src/commonMain/kotlin/cc/unitmesh/devins/ui/compose/agent/AgentMessageList.ktmpp-ui/src/commonMain/kotlin/cc/unitmesh/devins/ui/compose/editor/DevInEditorInput.kt
📚 Learning: 2025-11-30T02:30:49.805Z
Learnt from: CR
Repo: phodal/auto-dev-sketch PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-30T02:30:49.805Z
Learning: Applies to **/*.kt : Use `expect`/`actual` for platform-specific code in KMP projects (e.g., file I/O on JVM/JS/Wasm)
Applied to files:
mpp-ui/src/commonMain/kotlin/cc/unitmesh/devins/ui/compose/sketch/CodeFont.ktmpp-idea/build.gradle.kts
📚 Learning: 2025-11-30T02:30:49.805Z
Learnt from: CR
Repo: phodal/auto-dev-sketch PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-30T02:30:49.805Z
Learning: Applies to **/src/{androidMain,desktopMain}/**/*.kt : For Compose (Desktop/Android), use `AutoDevColors` from `cc.unitmesh.devins.ui.compose.theme` or `MaterialTheme.colorScheme`
Applied to files:
mpp-ui/src/commonMain/kotlin/cc/unitmesh/devins/ui/compose/sketch/CodeFont.ktmpp-ui/src/iosMain/kotlin/cc/unitmesh/devins/ui/compose/sketch/CodeFont.ios.ktmpp-ui/src/jsMain/kotlin/cc/unitmesh/devins/ui/compose/sketch/CodeFont.js.ktmpp-ui/src/jvmMain/kotlin/cc/unitmesh/devins/ui/compose/sketch/CodeFont.jvm.ktmpp-ui/src/wasmJsMain/kotlin/cc/unitmesh/devins/ui/compose/sketch/CodeFont.wasmJs.ktmpp-ui/src/commonMain/kotlin/cc/unitmesh/devins/ui/compose/agent/AgentMessageList.ktmpp-ui/src/commonMain/kotlin/cc/unitmesh/devins/ui/compose/editor/DevInEditorInput.ktmpp-idea/src/main/resources/META-INF/plugin.xmlmpp-ui/src/androidMain/kotlin/cc/unitmesh/devins/ui/compose/sketch/CodeFont.android.kt
📚 Learning: 2025-11-30T02:30:49.805Z
Learnt from: CR
Repo: phodal/auto-dev-sketch PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-30T02:30:49.805Z
Learning: Applies to **/jsMain/**/*.kt : In Kotlin/JS JsExport: Use concrete classes as return types and parameter types, avoid interface types (JS cannot correctly handle interface type conversion)
Applied to files:
mpp-ui/src/jsMain/kotlin/cc/unitmesh/devins/ui/compose/sketch/CodeFont.js.kt
📚 Learning: 2025-11-30T02:30:49.805Z
Learnt from: CR
Repo: phodal/auto-dev-sketch PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-30T02:30:49.805Z
Learning: Applies to {mpp-ui/src/jsMain/typescript/**/*.{ts,tsx},**/src/{androidMain,desktopMain}/**/*.kt} : DO NOT hardcode colors (e.g., `Color(0xFF...)` or `#hex`). Always use design tokens for consistency across platforms
Applied to files:
mpp-ui/src/commonMain/kotlin/cc/unitmesh/devins/ui/compose/agent/AgentMessageList.ktmpp-ui/src/commonMain/kotlin/cc/unitmesh/devins/ui/compose/editor/DevInEditorInput.kt
📚 Learning: 2025-11-30T02:30:49.805Z
Learnt from: CR
Repo: phodal/auto-dev-sketch PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-30T02:30:49.805Z
Learning: Use `cd mpp-idea && ../gradlew test --tests "cc.unitmesh.devins.idea.renderer.JewelRendererTest"` for running standalone JUnit 5 tests that do not require IntelliJ Platform
Applied to files:
mpp-core/src/jvmTest/kotlin/cc/unitmesh/devins/compiler/service/DevInsCompilerServiceTest.ktmpp-idea/build.gradle.kts
📚 Learning: 2025-11-30T02:30:49.805Z
Learnt from: CR
Repo: phodal/auto-dev-sketch PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-30T02:30:49.805Z
Learning: For IntelliJ IDEA Plugin build, use `cd mpp-idea && ../gradlew compileKotlin` instead of `./gradlew :mpp-idea:compileKotlin` from root
Applied to files:
mpp-idea/build.gradle.kts
📚 Learning: 2025-11-30T02:30:49.805Z
Learnt from: CR
Repo: phodal/auto-dev-sketch PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-30T02:30:49.805Z
Learning: Applies to {mpp-core,mpp-ui}/**/*.kt : Check export first in mpp-core and mpp-ui; if some functions are not working well with CLI (TypeScript), verify JsExport usage
Applied to files:
mpp-idea/build.gradle.kts
🧬 Code graph analysis (3)
mpp-ui/src/commonMain/kotlin/cc/unitmesh/devins/ui/compose/agent/AgentMessageList.kt (6)
mpp-ui/src/androidMain/kotlin/cc/unitmesh/devins/ui/compose/sketch/CodeFont.android.kt (1)
getUtf8FontFamily(39-40)mpp-ui/src/commonMain/kotlin/cc/unitmesh/devins/ui/compose/sketch/CodeFont.kt (1)
getUtf8FontFamily(22-23)mpp-ui/src/iosMain/kotlin/cc/unitmesh/devins/ui/compose/sketch/CodeFont.ios.kt (1)
getUtf8FontFamily(20-21)mpp-ui/src/jsMain/kotlin/cc/unitmesh/devins/ui/compose/sketch/CodeFont.js.kt (1)
getUtf8FontFamily(23-24)mpp-ui/src/jvmMain/kotlin/cc/unitmesh/devins/ui/compose/sketch/CodeFont.jvm.kt (1)
getUtf8FontFamily(38-39)mpp-ui/src/wasmJsMain/kotlin/cc/unitmesh/devins/ui/compose/sketch/CodeFont.wasmJs.kt (1)
getUtf8FontFamily(24-27)
mpp-ui/src/commonMain/kotlin/cc/unitmesh/devins/ui/compose/editor/DevInEditorInput.kt (6)
mpp-ui/src/androidMain/kotlin/cc/unitmesh/devins/ui/compose/sketch/CodeFont.android.kt (1)
getUtf8FontFamily(39-40)mpp-ui/src/commonMain/kotlin/cc/unitmesh/devins/ui/compose/sketch/CodeFont.kt (1)
getUtf8FontFamily(22-23)mpp-ui/src/iosMain/kotlin/cc/unitmesh/devins/ui/compose/sketch/CodeFont.ios.kt (1)
getUtf8FontFamily(20-21)mpp-ui/src/jsMain/kotlin/cc/unitmesh/devins/ui/compose/sketch/CodeFont.js.kt (1)
getUtf8FontFamily(23-24)mpp-ui/src/jvmMain/kotlin/cc/unitmesh/devins/ui/compose/sketch/CodeFont.jvm.kt (1)
getUtf8FontFamily(38-39)mpp-ui/src/wasmJsMain/kotlin/cc/unitmesh/devins/ui/compose/sketch/CodeFont.wasmJs.kt (1)
getUtf8FontFamily(24-27)
mpp-core/src/jvmTest/kotlin/cc/unitmesh/devins/compiler/service/DevInsCompilerServiceTest.kt (4)
mpp-core/src/commonMain/kotlin/cc/unitmesh/devins/test/DevInsTestCase.kt (3)
assertNotNull(54-59)assertEquals(45-49)assertTrue(29-33)mpp-core/src/commonMain/kotlin/cc/unitmesh/devins/compiler/service/DefaultDevInsCompilerService.kt (3)
compile(22-69)compile(24-30)compile(32-53)mpp-core/src/commonMain/kotlin/cc/unitmesh/devins/compiler/service/DevInsCompilerService.kt (3)
compile(25-100)compile(34-34)compile(44-48)mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/compiler/IdeaDevInsCompilerService.kt (2)
compile(37-39)compile(41-48)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: Test mpp-core (KMP)
- GitHub Check: Build (241)
- GitHub Check: Build (223)
🔇 Additional comments (21)
mpp-idea/src/main/resources/META-INF/plugin.xml (1)
5-5: Verify vendor email change is intentional and valid.The vendor email was updated from "phodal@gmail.com" to "h@phodal.com". Please confirm this change is intentional and that the email address is correct and actively monitored for support inquiries.
mpp-idea/build.gradle.kts (2)
40-63: Global dependency exclusions are comprehensive and well‑justified.The configuration strategically removes ~100+ MB of unused dependencies (AWS SDK, Tika, POI, PlantUML, etc.) that would bloat the plugin distribution. The placement before the
dependenciesblock ensures transitive dependencies are caught. The strategy complements the specific mpp-core/mpp-ui exclusions (lines 106–127) by avoiding redundancy through the comment on line 126.
221-234: PrepareSandboxTask.exclude() API is supported and correctly implemented.
PrepareSandboxTaskis aCopy/AbstractCopyTaskand fully supports theexclude()method with ANT-style patterns (as used here). The code at lines 221-234 is correct—exclude()is the standard Gradle CopySpec API for filtering files during the copy operation. No changes needed.mpp-ui/build.gradle.kts (1)
699-701: LGTM! Platform-specific font bundling optimization.Moving the font download directory to
wasmJsMainensures that the large CJK font files (~18MB) are only bundled in WASM builds, reducing bundle size for other platforms that use system default fonts.mpp-ui/src/commonMain/kotlin/cc/unitmesh/devins/ui/compose/agent/AgentMessageList.kt (1)
25-25: LGTM! Simplified font selection.The refactoring to use
getUtf8FontFamily()removes platform-specific branching from common code and delegates font selection to the appropriate platform implementation.Also applies to: 278-278
mpp-ui/src/androidMain/kotlin/cc/unitmesh/devins/ui/compose/sketch/CodeFont.android.kt (1)
3-3: LGTM! Android implementation is appropriate.Using
FontFamily.Defaultis the correct choice for Android, as the system fonts provide excellent UTF-8 and CJK support out of the box.Also applies to: 35-40
mpp-ui/src/commonMain/kotlin/cc/unitmesh/devins/ui/compose/editor/DevInEditorInput.kt (1)
42-42: LGTM! Consistent font API usage.The unified
getUtf8FontFamily()call ensures consistent font rendering in the text input field across all platforms.Also applies to: 486-486
mpp-ui/src/commonMain/kotlin/cc/unitmesh/devins/ui/compose/sketch/CodeFont.kt (1)
3-3: LGTM! Well-documented multi-platform API.The
expectdeclaration is properly structured with clear documentation explaining platform-specific behavior. The@Composableannotation is necessary to support the WASM implementation's resource loading.Also applies to: 17-23
mpp-ui/src/iosMain/kotlin/cc/unitmesh/devins/ui/compose/sketch/CodeFont.ios.kt (1)
3-3: LGTM! iOS implementation is appropriate.Using
FontFamily.Defaultis correct for iOS, as Apple's system fonts (San Francisco) provide comprehensive UTF-8 and CJK support.Also applies to: 16-21
mpp-ui/src/jsMain/kotlin/cc/unitmesh/devins/ui/compose/sketch/CodeFont.js.kt (1)
3-3: LGTM! JS implementation is appropriate.Using
FontFamily.Defaultis correct for the JS/browser platform, as modern browsers provide excellent UTF-8 support through system fonts.Also applies to: 19-24
mpp-ui/src/wasmJsMain/kotlin/cc/unitmesh/devins/ui/compose/sketch/CodeFont.wasmJs.kt (1)
20-27: The font loading mechanism is properly configured. The build task dependencies are correctly wired—downloadWasmFontsruns before resource processing tasks (copyNonXmlValueResources,prepareComposeResources,generateComposeResClass), and the download task includes error handling that throws on failure. Font resources are loaded through Compose's resource system, which handles availability at build time.mpp-ui/src/jvmMain/kotlin/cc/unitmesh/devins/ui/compose/sketch/CodeFont.jvm.kt (1)
34-39: No actionable concerns. ThegetUtf8FontFamily()function is used for general UTF-8 text rendering in message displays and text input fields, not for code display. Code display uses the separategetFiraCodeFontFamily()function. ReturningFontFamily.Defaultis appropriate for UTF-8 support across platforms, while WasmJs correctly overrides withNoto Sans SCfor CJK character coverage in the browser environment.Likely an incorrect or invalid review comment.
mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/toolwindow/IdeaAgentViewModel.kt (2)
70-73: LGTM! Clean lazy initialization pattern.The lazy initialization of the IDEA compiler service is well-structured and thread-safe. The descriptive comment clearly explains the purpose of using the PSI-based compiler with full IDE features.
131-136: LGTM! Proper compiler service injection.The KoogLLMService construction correctly injects the IDEA compiler service, enabling full IDE feature support. The comment clearly indicates the purpose of the injection.
mpp-core/src/commonMain/kotlin/cc/unitmesh/llm/KoogLLMService.kt (3)
29-33: LGTM! Clean optional dependency injection.The optional
compilerServiceparameter enables pluggable compiler implementations while maintaining backward compatibility with a sensible default.
49-51: LGTM! Appropriate fallback strategy.The
actualCompilerServiceresolver correctly prioritizes the injected service and falls back to the global instance when not provided.
137-147: LGTM! Improved compiler integration with logging.The updated
compilePromptmethod correctly uses the resolved compiler service and provides helpful debug logging that includes the compiler name and IDE feature support status.mpp-core/src/commonMain/kotlin/cc/unitmesh/devins/compiler/service/DefaultDevInsCompilerService.kt (1)
24-68: LGTM! Clean implementation of the default compiler service.The implementation correctly handles both compile variants (with and without variables), properly infers variable types, and maintains appropriate boundaries for a cross-platform compiler (no IDE features). The stateless design is appropriate for a default implementation.
mpp-core/src/jvmTest/kotlin/cc/unitmesh/devins/compiler/service/DevInsCompilerServiceTest.kt (1)
12-119: LGTM! Comprehensive test coverage.The test suite thoroughly covers the compiler service lifecycle (getInstance, setInstance, reset), compilation behavior (with and without variables), IDE feature support, and naming. The
tearDownmethod properly ensures test isolation by resetting global state.mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/compiler/IdeaDevInsCompilerService.kt (2)
70-81: LGTM! Proper PSI element resolution with whitespace handling.The
getElementAtCaretmethod correctly uses read actions and handles whitespace elements by falling back to the parent element.
86-114: The null/empty field assignments in this conversion are intentional and acceptable.The
convertToMppResultadapter intentionally setserrorMessagetonulland config fields to empty collections because the IDEA compiler doesn't provide these values. These fields have nullable/empty defaults inDevInsCompiledResult(line 34 and 49), and no downstream code accesseserrorMessageor config subfields from results produced by this conversion. If error information is needed, callers can use thegetError()method which provides "Unknown error" as a fallback for null values.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR implements a pluggable compiler service architecture that enables platform-specific DevIns compilation strategies. The primary goal is to allow IntelliJ IDEA to use its PSI-based compiler with full IDE features while maintaining the lightweight AST-based compiler for other platforms.
Key Changes:
- Introduces
DevInsCompilerServiceinterface with default (AST-based) and IDEA-specific (PSI-based) implementations - Refactors
KoogLLMServiceto accept optional compiler service injection - Consolidates UTF-8 font handling through
getUtf8FontFamily()helper across platforms - Optimizes plugin size by excluding unused dependencies and resources
Reviewed changes
Copilot reviewed 18 out of 18 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
mpp-core/.../service/DevInsCompilerService.kt |
Defines compiler service interface with singleton pattern and capability checks |
mpp-core/.../service/DefaultDevInsCompilerService.kt |
Cross-platform AST-based compiler implementation for CLI/Desktop/WASM |
mpp-idea/.../compiler/IdeaDevInsCompilerService.kt |
IDEA-specific PSI-based compiler with full IDE feature support |
mpp-core/.../llm/KoogLLMService.kt |
Added optional compiler service injection parameter |
mpp-idea/.../toolwindow/IdeaAgentViewModel.kt |
Instantiates and injects IDEA compiler service |
mpp-core/.../service/DevInsCompilerServiceTest.kt |
Unit tests for compiler service interface and default implementation |
mpp-ui/.../sketch/CodeFont.*.kt |
Platform-specific implementations of UTF-8 font family helper |
mpp-ui/.../editor/DevInEditorInput.kt |
Refactored to use getUtf8FontFamily() helper |
mpp-ui/.../agent/AgentMessageList.kt |
Refactored to use getUtf8FontFamily() helper |
mpp-ui/build.gradle.kts |
Moved font resources to WASM-specific directory |
mpp-idea/build.gradle.kts |
Added global dependency exclusions and font file filtering |
mpp-idea/.../META-INF/plugin.xml |
Updated plugin name and vendor email |
mpp-core/.../agent/CodingAgent.kt |
Increased AnalysisAgent content threshold from 5000 to 15000 |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
|
||
| private val errorRecoveryAgent = ErrorRecoveryAgent(projectPath, llmService) | ||
| private val analysisAgent = AnalysisAgent(llmService, contentThreshold = 5000) | ||
| private val analysisAgent = AnalysisAgent(llmService, contentThreshold = 15000) |
Copilot
AI
Dec 2, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The contentThreshold for AnalysisAgent has been increased from 5000 to 15000 characters without documentation. This is a significant change (3x increase) that affects when content analysis is triggered. Consider:
- Adding a comment explaining the rationale for this threshold value
- Documenting whether this was tested with real-world content sizes
- Considering making this threshold configurable rather than hardcoded
The change may be related to "Enhanced content analysis capacity" mentioned in the PR description, but the reasoning should be clear in the code.
| override suspend fun compile(source: String, fileSystem: ProjectFileSystem): DevInsCompiledResult { | ||
| return compileInternal(source) | ||
| } | ||
|
|
||
| override suspend fun compile( | ||
| source: String, | ||
| fileSystem: ProjectFileSystem, | ||
| variables: Map<String, Any> | ||
| ): DevInsCompiledResult { | ||
| // TODO: 支持自定义变量注入到 VariableTable | ||
| return compileInternal(source) | ||
| } |
Copilot
AI
Dec 2, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The fileSystem parameter is not used in either compile method. Both methods ignore this parameter and call compileInternal(source) directly. Consider whether the fileSystem should be passed to the underlying DevInsCompiler or if it needs to be utilized for PSI-based compilation. If it's intentionally unused, add a comment explaining why.
| // TODO: 支持自定义变量注入到 VariableTable | ||
| return compileInternal(source) |
Copilot
AI
Dec 2, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The variables parameter in the compile overload is not used. The TODO comment indicates future support for variable injection, but the current implementation simply ignores these variables and calls compileInternal(source). Consider either implementing variable injection now or throwing an UnsupportedOperationException until it's implemented to make the limitation explicit to callers.
| // TODO: 支持自定义变量注入到 VariableTable | |
| return compileInternal(source) | |
| throw UnsupportedOperationException("Variable injection is not yet supported in IdeaDevInsCompilerService.compile. The 'variables' parameter is ignored. This will be implemented in a future version.") |
| @Volatile | ||
| private var instance: DevInsCompilerService? = null |
Copilot
AI
Dec 2, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The @Volatile annotation is used on a JVM/Kotlin Multiplatform shared variable, but in Kotlin Multiplatform, @Volatile is only available on JVM targets. For proper thread-safety across all platforms (including JS, WASM, Native), consider using AtomicReference from kotlinx.atomicfu or document that this singleton pattern is only thread-safe on JVM platforms.
| * 如果未设置,返回默认实现 | ||
| */ | ||
| fun getInstance(): DevInsCompilerService { | ||
| return instance ?: DefaultDevInsCompilerService() |
Copilot
AI
Dec 2, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
getInstance() creates a new DefaultDevInsCompilerService instance every time it's called when instance is null. This could lead to multiple instances being created in concurrent scenarios. Consider using double-checked locking or lazy initialization to ensure a singleton pattern, or document that creating multiple default instances is acceptable.
| return instance ?: DefaultDevInsCompilerService() | |
| if (instance == null) { | |
| synchronized(this) { | |
| if (instance == null) { | |
| instance = DefaultDevInsCompilerService() | |
| } | |
| } | |
| } | |
| return instance!! |
| <name>AutoDev Compose UI</name> | ||
| <vendor email="phodal@gmail.com" url="https://github.com/unit-mesh">UnitMesh</vendor> | ||
| <name>AutoDev Next</name> | ||
| <vendor email="h@phodal.com" url="https://github.com/unit-mesh">UnitMesh</vendor> |
Copilot
AI
Dec 2, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] The vendor email has been changed from "phodal@gmail.com" to "h@phodal.com". Ensure this email change is intentional and that the new email address is valid and monitored for plugin support inquiries.
| package cc.unitmesh.devins.idea.compiler | ||
|
|
||
| import cc.unitmesh.devins.compiler.result.DevInsCompiledResult | ||
| import cc.unitmesh.devins.compiler.service.DevInsCompilerService | ||
| import cc.unitmesh.devins.filesystem.ProjectFileSystem | ||
| import cc.unitmesh.devti.language.compiler.DevInsCompiler | ||
| import cc.unitmesh.devti.language.psi.DevInFile | ||
| import com.intellij.openapi.application.runReadAction | ||
| import com.intellij.openapi.editor.Editor | ||
| import com.intellij.openapi.fileEditor.FileEditorManager | ||
| import com.intellij.openapi.project.Project | ||
| import com.intellij.psi.PsiElement | ||
| import com.intellij.psi.PsiWhiteSpace | ||
| import com.intellij.psi.util.PsiUtilBase | ||
|
|
||
| /** | ||
| * IDEA 专用的 DevIns 编译器服务 | ||
| * | ||
| * 使用 devins-lang 模块的 DevInsCompiler,基于 IntelliJ PSI 解析。 | ||
| * 支持完整的 IDE 功能: | ||
| * - Symbol 解析 (/symbol 命令) | ||
| * - 代码重构 (/refactor 命令) | ||
| * - 数据库操作 (/database 命令) | ||
| * - 代码结构分析 (/structure 命令) | ||
| * - 符号使用查找 (/usage 命令) | ||
| * - 文件操作 (/file, /write, /edit_file 命令) | ||
| * - 进程管理 (/launch_process, /kill_process 等) | ||
| * | ||
| * @param project IntelliJ Project 实例 | ||
| * @param editor 可选的编辑器实例,用于获取当前光标位置 | ||
| */ | ||
| class IdeaDevInsCompilerService( | ||
| private val project: Project, | ||
| private val editor: Editor? = null | ||
| ) : DevInsCompilerService { | ||
|
|
||
| override suspend fun compile(source: String, fileSystem: ProjectFileSystem): DevInsCompiledResult { | ||
| return compileInternal(source) | ||
| } | ||
|
|
||
| override suspend fun compile( | ||
| source: String, | ||
| fileSystem: ProjectFileSystem, | ||
| variables: Map<String, Any> | ||
| ): DevInsCompiledResult { | ||
| // TODO: 支持自定义变量注入到 VariableTable | ||
| return compileInternal(source) | ||
| } | ||
|
|
||
| override fun supportsIdeFeatures(): Boolean = true | ||
|
|
||
| override fun getName(): String = "IdeaDevInsCompilerService (devins-lang PSI)" | ||
|
|
||
| private suspend fun compileInternal(source: String): DevInsCompiledResult { | ||
| // 从字符串创建 DevInFile | ||
| val devInFile = DevInFile.fromString(project, source) | ||
|
|
||
| // 获取当前编辑器和光标位置的元素 | ||
| val currentEditor = editor ?: FileEditorManager.getInstance(project).selectedTextEditor | ||
| val element = currentEditor?.let { getElementAtCaret(it) } | ||
|
|
||
| // 创建并执行编译器 | ||
| val compiler = DevInsCompiler(project, devInFile, currentEditor, element) | ||
| val ideaResult = compiler.compile() | ||
|
|
||
| // 转换为 mpp-core 的 DevInsCompiledResult | ||
| return convertToMppResult(ideaResult) | ||
| } | ||
|
|
||
| private fun getElementAtCaret(editor: Editor): PsiElement? { | ||
| return runReadAction { | ||
| val offset = editor.caretModel.currentCaret.offset | ||
| val psiFile = PsiUtilBase.getPsiFileInEditor(editor, project) ?: return@runReadAction null | ||
|
|
||
| var element = psiFile.findElementAt(offset) ?: return@runReadAction null | ||
| if (element is PsiWhiteSpace) { | ||
| element = element.parent | ||
| } | ||
| element | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * 将 devins-lang 的编译结果转换为 mpp-core 的格式 | ||
| */ | ||
| private fun convertToMppResult( | ||
| ideaResult: cc.unitmesh.devti.language.compiler.DevInsCompiledResult | ||
| ): DevInsCompiledResult { | ||
| return DevInsCompiledResult( | ||
| input = ideaResult.input, | ||
| output = ideaResult.output, | ||
| isLocalCommand = ideaResult.isLocalCommand, | ||
| hasError = ideaResult.hasError, | ||
| errorMessage = null, // IDEA 版本没有 errorMessage 字段 | ||
| executeAgent = ideaResult.executeAgent?.let { agent -> | ||
| cc.unitmesh.devins.compiler.result.CustomAgentConfig( | ||
| name = agent.name, | ||
| type = agent.state.name, | ||
| parameters = emptyMap() | ||
| ) | ||
| }, | ||
| nextJob = null, // DevInFile 不能直接转换,需要时再处理 | ||
| config = ideaResult.config?.let { hobbitHole -> | ||
| cc.unitmesh.devins.compiler.result.FrontMatterConfig( | ||
| name = hobbitHole.name, | ||
| description = hobbitHole.description, | ||
| variables = emptyMap(), | ||
| lifecycle = emptyMap(), | ||
| functions = emptyList(), | ||
| agents = emptyList() | ||
| ) | ||
| } | ||
| ) | ||
| } | ||
|
|
||
| companion object { | ||
| /** | ||
| * 创建 IDEA 编译器服务实例 | ||
| */ | ||
| fun create(project: Project, editor: Editor? = null): IdeaDevInsCompilerService { | ||
| return IdeaDevInsCompilerService(project, editor) | ||
| } | ||
|
|
||
| /** | ||
| * 注册为全局编译器服务 | ||
| * 应在 IDEA 插件启动时调用 | ||
| */ | ||
| fun registerAsGlobal(project: Project, editor: Editor? = null) { | ||
| DevInsCompilerService.setInstance(IdeaDevInsCompilerService(project, editor)) | ||
| } | ||
| } | ||
| } | ||
|
|
Copilot
AI
Dec 2, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The new IdeaDevInsCompilerService class lacks test coverage. Consider adding unit tests to verify:
- Compilation of simple DevIns source code
- Correct conversion from IDEA's DevInsCompiledResult to mpp-core's format
- Editor and element retrieval logic
- Error handling when PSI elements are unavailable
Tests exist for other components in mpp-idea (e.g., JewelRenderer, IdeaAgentViewModel), so following the same testing pattern would improve code quality and maintainability.
Summary
This PR implements a pluggable DevInsCompilerService architecture that allows switching between different compiler implementations:
{{FILE_CONTENT:...}}Changes
New Files
mpp-core/.../service/DevInsCompilerService.ktgetInstance(),setInstance(),reset())supportsIdeFeatures()capability checkmpp-core/.../service/DefaultDevInsCompilerService.ktmpp-idea/.../compiler/IdeaDevInsCompilerService.ktmpp-core/.../service/DevInsCompilerServiceTest.ktModified Files
mpp-core/.../llm/KoogLLMService.ktcompilerServiceconstructor parametercompilePrompt()to use injected compiler servicempp-idea/.../toolwindow/IdeaAgentViewModel.ktIdeaDevInsCompilerServiceinstanceKoogLLMServiceUsage
Benefits
Pull Request opened by Augment Code with guidance from the PR author
Summary by CodeRabbit
New Features
Chores
✏️ Tip: You can customize this high-level summary in your review settings.