Skip to content

Conversation

@phodal
Copy link
Owner

@phodal phodal commented Dec 9, 2025

Summary

This PR adds support for creating new model configurations in all three versions (UI, IDEA, and VSCode) of the ModelConfigDialog.

Changes

UI Version (mpp-ui)

  • ✅ Added "Add New Config" option in ModelSelector
  • ✅ Added isNewConfig state to distinguish between new and edit modes
  • ✅ Modified ModelConfigDialog to support new config mode (when currentConfigName is null)
  • ✅ Added i18n strings: addNewConfig and add in English and Chinese

IDEA Version (mpp-idea)

  • ✅ Added "Add New Config" option in IdeaModelSelector
  • ✅ Added isNewConfig state and related methods in IdeaAgentViewModel
  • ✅ Modified dialog invocation in IdeaAgentApp to support new config mode
  • ✅ Added "Add New Config" button in SwingBottomToolbar for Swing version
  • ✅ Added onAddNewConfig callback support in IdeaDevInInputArea

VSCode Version (mpp-vscode)

  • ✅ Added "Add New Config" option in ModelSelector
  • ✅ Created ModelConfigDialog component with form and validation
  • ✅ Created ModelConfigDialog.css styling
  • ✅ Integrated dialog in App.tsx with support for both new and edit modes
  • ✅ Added onAddNewConfig callback support in ChatInput

Problem Solved

Previously, users could only edit existing model configurations. The model selector was a dropdown that only allowed selecting from existing configs, making it impossible to create new ones. Now users can:

  • Click "Add New Config" to create a new configuration
  • Click "Configure Model" to edit the current configuration

Testing

  • Tested in UI version (Desktop)
  • Tested in IDEA plugin
  • Tested in VSCode extension
  • Verified i18n strings display correctly
  • Verified new configs can be saved and loaded

Related Issues

Fixes the issue where users could only modify existing model configs and couldn't create new ones.

Summary by CodeRabbit

  • New Features

    • Added "Add New Config" action across UI (toolbar, input area, selector) to create new model configurations and open a dedicated config dialog.
    • New Model Config dialog for creating/editing LLM settings with provider selection, API/base URL handling, validation, save (with name deduplication), and feedback.
  • Localization

    • Added English and Chinese strings for "Add" and "Add New Config".

✏️ Tip: You can customize this high-level summary in your review settings.

- Add 'Add New Config' option in ModelSelector for UI, IDEA, and VSCode versions
- Support new config mode when currentConfigName is null
- Add i18n strings for 'addNewConfig' and 'add' in English and Chinese
- Create ModelConfigDialog component for VSCode webview
- Update IdeaAgentViewModel to support new config mode
- Add onAddNewConfig callback throughout the component hierarchy

This allows users to create new model configurations instead of only being able to edit existing ones.
Copilot AI review requested due to automatic review settings December 9, 2025 01:26
@coderabbitai
Copy link

coderabbitai bot commented Dec 9, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

Adds an "Add New Config" flow across IntelliJ and VSCode: new UI actions, dialog component, ViewModel state to distinguish add vs edit, config-save plumbing in the extension, and localization strings.

Changes

Cohort / File(s) Summary
IntelliJ selector & toolbar
mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/editor/IdeaModelSelector.kt, mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/editor/SwingBottomToolbar.kt, mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/editor/IdeaBottomToolbar.kt
Added onAddNewConfig callback parameter and UI entry; injected new Add button and exposed setOnAddNewConfig on Swing toolbar; threaded callback through IdeaBottomToolbar → IdeaModelSelector.
IntelliJ app & viewmodel
mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/toolwindow/IdeaAgentViewModel.kt, mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/toolwindow/IdeaAgentApp.kt, mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/toolwindow/IdeaDevInInputArea.kt
Added _isNewConfig/isNewConfig state and showAddNewConfigDialog() / showEditConfigDialog() helpers; updated App to call these and to initialize dialog with either fresh ModelConfig (new) or existing config; propagated onAddNewConfig through DevInInputArea and SwingDevInInputArea (new setter).
Cross-platform compose UI
mpp-ui/src/commonMain/kotlin/cc/unitmesh/devins/ui/compose/editor/ModelSelector.kt
Added isNewConfig state and an "Add New Config" dropdown item that toggles new-config flow and opens the config dialog; adjusted Configure flow to reset isNewConfig.
Localization
mpp-ui/src/commonMain/i18n/cc/unitmesh/devins/ui/i18n/AutoDevStrings_en.properties, mpp-ui/src/commonMain/i18n/cc/unitmesh/devins/ui/i18n/AutoDevStrings_zh.properties, mpp-ui/src/commonMain/kotlin/cc/unitmesh/devins/ui/i18n/I18n.kt
Added common.add and modelConfig.addNewConfig keys (EN/ZH) and exposed Strings.add and Strings.addNewConfig properties.
VSCode webview app & components
mpp-vscode/webview/src/App.tsx, mpp-vscode/webview/src/components/ChatInput.tsx, mpp-vscode/webview/src/components/ModelSelector.tsx
Added onAddNewConfig prop, isNewConfig/dialog state in App, handlers handleAddNewConfig/handleOpenConfig, and passed callback through ChatInput → ModelSelector; ModelSelector conditionally renders "Add New Config" entry and invokes callback.
VSCode ModelConfigDialog & styles
mpp-vscode/webview/src/components/ModelConfigDialog.tsx, mpp-vscode/webview/src/components/ModelConfigDialog.css
Added new ModelConfigDialog React component and CSS: form state (name, provider, model, apiKey, baseUrl, temperature, maxTokens), validation, isNewConfig handling, and posts saveModelConfig message on save.
Extension message handling & config manager
mpp-vscode/src/providers/chat-view.ts, mpp-vscode/src/services/config-manager.ts
Added handler for saveModelConfig in chat view that builds LLMConfig, ensures unique name for new configs, saves config, reloads and notifies webview; added ConfigManager.saveConfig and generateUniqueConfigName utilities to persist/update configs and avoid name collisions.
sequenceDiagram
    participant User
    participant UI as Client UI
    participant App as Webview/App/Compose
    participant VM as ViewModel
    participant Dialog as ModelConfigDialog
    participant Ext as Extension (chat-view)
    participant CM as ConfigManager

    User->>UI: Click "Add New Config"
    UI->>App: onAddNewConfig()
    App->>VM: showAddNewConfigDialog() / set isNewConfig=true
    VM->>Dialog: open dialog (currentConfig = fresh, currentName=null)
    User->>Dialog: Fill form → Save
    Dialog->>Ext: postMessage(saveModelConfig, data with isNewConfig)
    Ext->>CM: saveConfig(data, setActive?)
    CM-->>Ext: persisted, possibly renamed unique name
    Ext->>App: post configs update & success
    App->>UI: refresh list / close dialog
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25–35 minutes

  • Areas needing attention:
    • ModelConfigDialog validation and provider-specific required fields (apiKey/baseUrl)
    • Extension's saveModelConfig flow: name deduplication and overwrite logic
    • State propagation of isNewConfig across Compose ↔ ViewModel ↔ Swing boundaries
    • Correct wiring of onAddNewConfig through multiple component layers

Possibly related PRs

Poem

🐰 A tiny hop, a new config born today,
I nibble keys and dialogs on my way.
From UI click to backend's gentle hum,
Names get unique and validation's done.
Hooray — new configs hop into the sun! ✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 30.77% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically describes the main change: adding support for creating new model configs in ModelConfigDialog across multiple variants.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/add-new-model-config-support

Comment @coderabbitai help to get the list of available commands and usage tips.

@phodal
Copy link
Owner Author

phodal commented Dec 9, 2025

augment review

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/toolwindow/IdeaAgentApp.kt (1)

320-329: Potential bug in unique name generation for new configs.

The name conflict check uses currentConfigName from the outer scope (line 324), but when creating a new config (isNewConfig = true), currentConfigName still holds the previously active config's name (not null). This means if a user creates a new config with the same name as the currently active config, the condition currentConfigName != configName would be false, and auto-rename would NOT trigger - potentially overwriting the existing config.

Consider using dialogConfigName instead:

                         val finalConfigName =
-                            if (currentConfigName != configName && configName in existingNames) {
+                            if (dialogConfigName != configName && configName in existingNames) {
                                 // Auto-increment: my-glm -> my-glm-1 -> my-glm-2, etc.
                                 ConfigManager.generateUniqueConfigName(configName, existingNames)
                             } else {
                                 configName
                             }
🧹 Nitpick comments (4)
mpp-vscode/webview/src/App.tsx (1)

513-513: Consider resetting all dialog state on close.

The onClose handler only resets showModelConfigDialog. For consistency with the Kotlin implementation (which resets both showConfigDialog and isNewConfig on dismiss), consider also resetting modelConfigDialogConfig and isNewConfig:

-          onClose={() => setShowModelConfigDialog(false)}
+          onClose={() => {
+            setShowModelConfigDialog(false);
+            setModelConfigDialogConfig(null);
+            setIsNewConfig(false);
+          }}
mpp-vscode/webview/src/components/ModelConfigDialog.tsx (3)

57-76: Potential state persistence issue when reopening dialog.

The useEffect has two branches but doesn't handle the case when isOpen=true, currentConfig=null, and isNewConfig=false. In this scenario, old form values from a previous interaction would persist. While the typical usage may avoid this, consider adding an else branch or always resetting state when opening:

  useEffect(() => {
    if (isOpen && currentConfig) {
      setConfigName(currentConfig.name || '');
      setProvider(currentConfig.provider || 'openai');
      setModel(currentConfig.model || '');
      setApiKey(currentConfig.apiKey || '');
      setBaseUrl(currentConfig.baseUrl || '');
      setTemperature(currentConfig.temperature?.toString() || '0.7');
      setMaxTokens(currentConfig.maxTokens?.toString() || '8192');
    } else if (isOpen && isNewConfig) {
      // Reset to defaults for new config
      setConfigName('');
      setProvider('openai');
      setModel('');
      setApiKey('');
      setBaseUrl('');
      setTemperature('0.7');
      setMaxTokens('8192');
+   } else if (isOpen) {
+     // Fallback: reset if dialog opened without clear intent
+     setConfigName('');
+     setProvider('openai');
+     setModel('');
+     setApiKey('');
+     setBaseUrl('');
+     setTemperature('0.7');
+     setMaxTokens('8192');
    }
  }, [isOpen, currentConfig, isNewConfig]);

83-116: Consider improving validation UX and save confirmation.

The current implementation has a few user experience concerns:

  1. alert() for validation: While functional, alerts are disruptive and not modern UX. Consider using inline error messages below each field.

  2. No save confirmation: The dialog closes immediately after postMessage without waiting for confirmation from the extension. If the save operation fails on the extension side, the user won't see any feedback.

  3. Missing numeric validation: Temperature is constrained in HTML (min="0" max="2") but parseFloat doesn't enforce this. Consider validating the parsed values:

const tempValue = parseFloat(temperature);
if (isNaN(tempValue) || tempValue < 0 || tempValue > 2) {
  alert('Temperature must be between 0 and 2');
  return;
}

27-38: Consider extracting constants and types for better maintainability.

The PROVIDERS constant and the message types used in postMessage could be extracted to shared files:

  1. Move PROVIDERS to a constants file (e.g., constants/providers.ts) for reuse across components.
  2. Define TypeScript types for the saveModelConfig message payload in a types file.

This would improve type safety and make it easier to maintain consistency across the codebase.

// types/messages.ts
export interface SaveModelConfigMessage {
  type: 'saveModelConfig';
  data: {
    name: string;
    provider: string;
    model: string;
    apiKey: string;
    baseUrl?: string;
    temperature: number;
    maxTokens: number;
    isNewConfig: boolean;
  };
}
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f949a61 and 29a41e5.

📒 Files selected for processing (14)
  • mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/editor/IdeaModelSelector.kt (2 hunks)
  • mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/editor/SwingBottomToolbar.kt (3 hunks)
  • mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/toolwindow/IdeaAgentApp.kt (5 hunks)
  • mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/toolwindow/IdeaAgentViewModel.kt (2 hunks)
  • mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/toolwindow/IdeaDevInInputArea.kt (4 hunks)
  • mpp-ui/src/commonMain/i18n/cc/unitmesh/devins/ui/i18n/AutoDevStrings_en.properties (2 hunks)
  • mpp-ui/src/commonMain/i18n/cc/unitmesh/devins/ui/i18n/AutoDevStrings_zh.properties (2 hunks)
  • mpp-ui/src/commonMain/kotlin/cc/unitmesh/devins/ui/compose/editor/ModelSelector.kt (3 hunks)
  • mpp-ui/src/commonMain/kotlin/cc/unitmesh/devins/ui/i18n/I18n.kt (2 hunks)
  • mpp-vscode/webview/src/App.tsx (5 hunks)
  • mpp-vscode/webview/src/components/ChatInput.tsx (3 hunks)
  • mpp-vscode/webview/src/components/ModelConfigDialog.css (1 hunks)
  • mpp-vscode/webview/src/components/ModelConfigDialog.tsx (1 hunks)
  • mpp-vscode/webview/src/components/ModelSelector.tsx (2 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{kt,ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Never use hardcoded colors - always use design tokens from the design system

Files:

  • mpp-vscode/webview/src/components/ChatInput.tsx
  • mpp-ui/src/commonMain/kotlin/cc/unitmesh/devins/ui/i18n/I18n.kt
  • mpp-vscode/webview/src/components/ModelSelector.tsx
  • mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/editor/SwingBottomToolbar.kt
  • mpp-vscode/webview/src/components/ModelConfigDialog.tsx
  • mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/editor/IdeaModelSelector.kt
  • mpp-ui/src/commonMain/kotlin/cc/unitmesh/devins/ui/compose/editor/ModelSelector.kt
  • mpp-vscode/webview/src/App.tsx
  • mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/toolwindow/IdeaDevInInputArea.kt
  • mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/toolwindow/IdeaAgentViewModel.kt
  • mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/toolwindow/IdeaAgentApp.kt
**/*.kt

📄 CodeRabbit inference engine (AGENTS.md)

**/*.kt: Use expect/actual pattern for platform-specific code (for example: Platform implementations)
Use concrete classes (not interfaces) and Promise (not Flow) for @JsExport annotations
Avoid emoji and UTF-8 characters in WASM code
When modifying CodingAgentRenderer, update ALL implementations: DefaultCodingAgentRenderer, ComposeRenderer, JewelRenderer, ServerSideRenderer, and JsRendererAdapter in Kotlin
When modifying CodingAgentRenderer, update JVM CLI implementations: CodingCliRenderer and ConsoleRenderer
Use AutoDevColors or MaterialTheme.colorScheme for Compose styling

Files:

  • mpp-ui/src/commonMain/kotlin/cc/unitmesh/devins/ui/i18n/I18n.kt
  • mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/editor/SwingBottomToolbar.kt
  • mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/editor/IdeaModelSelector.kt
  • mpp-ui/src/commonMain/kotlin/cc/unitmesh/devins/ui/compose/editor/ModelSelector.kt
  • mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/toolwindow/IdeaDevInInputArea.kt
  • mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/toolwindow/IdeaAgentViewModel.kt
  • mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/toolwindow/IdeaAgentApp.kt
🧠 Learnings (2)
📚 Learning: 2025-12-07T08:40:10.850Z
Learnt from: CR
Repo: phodal/auto-dev PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-07T08:40:10.850Z
Learning: Applies to mpp-vscode/src/**/*.ts : When modifying `CodingAgentRenderer`, update VSCode implementations: `mpp-vscode/src/bridge/mpp-core.ts` and `mpp-vscode/src/providers/chat-view.ts`

Applied to files:

  • mpp-vscode/webview/src/components/ModelConfigDialog.css
  • mpp-vscode/webview/src/components/ChatInput.tsx
  • mpp-vscode/webview/src/components/ModelSelector.tsx
  • mpp-vscode/webview/src/components/ModelConfigDialog.tsx
  • mpp-vscode/webview/src/App.tsx
📚 Learning: 2025-12-07T08:40:10.850Z
Learnt from: CR
Repo: phodal/auto-dev PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-07T08:40:10.850Z
Learning: Run `./gradlew :mpp-ui:generateI18n4kFiles` command when updating i18n resources

Applied to files:

  • mpp-ui/src/commonMain/kotlin/cc/unitmesh/devins/ui/i18n/I18n.kt
🧬 Code graph analysis (5)
mpp-vscode/webview/src/components/ModelSelector.tsx (1)
mpp-ui/src/commonMain/kotlin/cc/unitmesh/devins/ui/compose/editor/ModelSelector.kt (1)
  • ModelSelector (26-224)
mpp-vscode/webview/src/components/ModelConfigDialog.tsx (2)
mpp-vscode/webview/src/hooks/useVSCode.ts (1)
  • useVSCode (100-119)
mpp-vscode/src/providers/chat-view.ts (1)
  • postMessage (267-269)
mpp-ui/src/commonMain/kotlin/cc/unitmesh/devins/ui/compose/editor/ModelSelector.kt (1)
mpp-vscode/webview/src/components/ModelSelector.tsx (1)
  • ModelConfig (11-15)
mpp-vscode/webview/src/App.tsx (2)
mpp-vscode/webview/src/components/ModelSelector.tsx (1)
  • ModelConfig (11-15)
mpp-vscode/src/bridge/mpp-core.ts (1)
  • ModelConfig (38-45)
mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/toolwindow/IdeaAgentApp.kt (2)
mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/compose/IdeaComposeEffects.kt (3)
  • IdeaLaunchedEffect (73-85)
  • IdeaLaunchedEffect (90-103)
  • IdeaLaunchedEffect (108-122)
mpp-vscode/webview/src/components/ModelSelector.tsx (1)
  • ModelConfig (11-15)
⏰ 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: Agent
  • GitHub Check: Build
  • GitHub Check: Test mpp-core (KMP)
🔇 Additional comments (22)
mpp-ui/src/commonMain/i18n/cc/unitmesh/devins/ui/i18n/AutoDevStrings_en.properties (1)

10-10: LGTM! Remember to regenerate i18n files.

The new i18n keys are correctly formatted and follow the existing naming conventions.

Based on learnings, please run the following command after adding these i18n keys:

./gradlew :mpp-ui:generateI18n4kFiles

Also applies to: 29-29

mpp-ui/src/commonMain/i18n/cc/unitmesh/devins/ui/i18n/AutoDevStrings_zh.properties (1)

10-10: LGTM!

The Chinese translations are correctly added and align with the corresponding English keys.

Also applies to: 29-29

mpp-ui/src/commonMain/kotlin/cc/unitmesh/devins/ui/i18n/I18n.kt (1)

69-69: LGTM!

The new string properties correctly map to the i18n keys and follow the existing pattern in the codebase.

Also applies to: 89-89

mpp-vscode/webview/src/components/ChatInput.tsx (1)

16-16: LGTM!

The onAddNewConfig callback is properly added to the component interface, correctly destructured, and appropriately forwarded to the ModelSelector component. The optional nature maintains backward compatibility.

Also applies to: 38-38, 230-230

mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/editor/SwingBottomToolbar.kt (1)

35-35: LGTM!

The "Add New Config" button is properly integrated with appropriate icon, tooltip, and callback wiring. The implementation follows the existing pattern for other toolbar actions.

Also applies to: 56-64, 153-155

mpp-vscode/webview/src/components/ModelConfigDialog.css (1)

1-167: LGTM!

The CSS properly uses VSCode theme variables throughout (no hardcoded colors), implements standard modal dialog patterns, and provides appropriate visual feedback for interactive elements. The styling is consistent with VSCode design conventions.

mpp-vscode/webview/src/components/ModelSelector.tsx (1)

22-22: LGTM!

The onAddNewConfig prop is correctly added to the interface and properly destructured in the component.

Also applies to: 29-30

mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/editor/IdeaModelSelector.kt (1)

38-38: LGTM!

The onAddNewConfig callback parameter is correctly added to the function signature, maintaining consistency with other callback parameters.

mpp-ui/src/commonMain/kotlin/cc/unitmesh/devins/ui/compose/editor/ModelSelector.kt (4)

30-30: LGTM!

The isNewConfig state is appropriately scoped within the composable and correctly defaults to false.


139-154: LGTM!

The "Add New Config" menu item follows the established pattern, uses proper i18n strings, and correctly sets the state before opening the dialog.


156-171: LGTM!

Explicitly resetting isNewConfig = false when editing ensures the dialog correctly distinguishes between creating and editing configurations.


174-222: LGTM!

The dialog invocation logic correctly handles both new and edit modes:

  • Fresh ModelConfig() and null name for new configs
  • Existing config and name for edits
  • Proper state cleanup on dismiss
  • Auto-rename logic correctly handles name conflicts for both scenarios
mpp-vscode/webview/src/App.tsx (3)

78-81: LGTM!

The new state variables for the model config dialog are appropriately initialized:

  • showModelConfigDialog controls visibility
  • modelConfigDialogConfig holds the config being edited (or null for new)
  • isNewConfig distinguishes between add and edit modes

335-351: LGTM!

Both handlers are correctly implemented:

  • handleOpenConfig prefers in-dialog editing when a config exists, with fallback to extension
  • handleAddNewConfig correctly initializes state for creating a new configuration
  • Dependencies in useCallback are properly specified

509-517: > Likely an incorrect or invalid review comment.

mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/toolwindow/IdeaAgentViewModel.kt (2)

84-85: LGTM!

The isNewConfig state follows the established pattern in this ViewModel:

  • Private MutableStateFlow for internal mutation
  • Public StateFlow via asStateFlow() for external observation

592-606: LGTM!

The new dialog control methods cleanly encapsulate the state transitions:

  • showAddNewConfigDialog() sets new-config mode and shows the dialog
  • showEditConfigDialog() sets edit mode and shows the dialog

This provides a clear API for UI components to trigger the appropriate dialog mode.

mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/toolwindow/IdeaAgentApp.kt (2)

68-68: LGTM!

The isNewConfig state and its collection via IdeaLaunchedEffect follow the established pattern used for other ViewModel states in this file.

Also applies to: 93-95


224-225: LGTM!

The callback wiring correctly connects UI actions to ViewModel methods:

  • onConfigureClickshowEditConfigDialog() for editing
  • onAddNewConfigshowAddNewConfigDialog() for creating
mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/toolwindow/IdeaDevInInputArea.kt (3)

83-83: LGTM!

The new onAddNewConfig parameter follows the established pattern of other callbacks in this composable (e.g., onConfigSelect, onConfigureClick), with an appropriate default empty lambda.


120-123: LGTM!

The DisposableEffect for propagating onAddNewConfig follows the same pattern used for onConfigSelect and onConfigureClick.


337-339: LGTM!

The setOnAddNewConfig method correctly delegates to SwingBottomToolbar.setOnAddNewConfig, which is properly implemented and wired to the add config button in the toolbar's initialization.

Comment on lines +135 to +158
// Add New Config button
selectableItem(
selected = false,
onClick = {
onAddNewConfig()
expanded = false
}
) {
Row(
horizontalArrangement = Arrangement.spacedBy(8.dp),
verticalAlignment = Alignment.CenterVertically
) {
Icon(
imageVector = IdeaComposeIcons.Add,
contentDescription = null,
tint = JewelTheme.globalColors.text.normal,
modifier = Modifier.size(16.dp)
)
Text(
text = "Add New Config",
style = JewelTheme.defaultTextStyle.copy(fontSize = 13.sp)
)
}
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

Use i18n for the "Add New Config" label.

Line 154 contains a hardcoded string. For consistency with the i18n infrastructure added in this PR (see Strings.addNewConfig in I18n.kt), the label should use the localization key.

Apply this diff to use the i18n string:

                        Text(
-                            text = "Add New Config",
+                            text = Strings.addNewConfig,
                            style = JewelTheme.defaultTextStyle.copy(fontSize = 13.sp)
                        )
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Add New Config button
selectableItem(
selected = false,
onClick = {
onAddNewConfig()
expanded = false
}
) {
Row(
horizontalArrangement = Arrangement.spacedBy(8.dp),
verticalAlignment = Alignment.CenterVertically
) {
Icon(
imageVector = IdeaComposeIcons.Add,
contentDescription = null,
tint = JewelTheme.globalColors.text.normal,
modifier = Modifier.size(16.dp)
)
Text(
text = "Add New Config",
style = JewelTheme.defaultTextStyle.copy(fontSize = 13.sp)
)
}
}
// Add New Config button
selectableItem(
selected = false,
onClick = {
onAddNewConfig()
expanded = false
}
) {
Row(
horizontalArrangement = Arrangement.spacedBy(8.dp),
verticalAlignment = Alignment.CenterVertically
) {
Icon(
imageVector = IdeaComposeIcons.Add,
contentDescription = null,
tint = JewelTheme.globalColors.text.normal,
modifier = Modifier.size(16.dp)
)
Text(
text = Strings.addNewConfig,
style = JewelTheme.defaultTextStyle.copy(fontSize = 13.sp)
)
}
}
🤖 Prompt for AI Agents
In mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/editor/IdeaModelSelector.kt
around lines 135-158 there is a hardcoded label "Add New Config"; replace that
literal with the i18n key by using Strings.addNewConfig (importing the Strings
object from I18n.kt if needed) so the Text composable uses the localized string
instead of the hardcoded English text; ensure the correct accessor is used
consistent with the project's i18n pattern (e.g. Strings.addNewConfig or the
project's stringResource wrapper) and keep the rest of the Text styling
unchanged.

Comment on lines 118 to 238
return (
<div className="model-config-dialog-overlay" onClick={onClose}>
<div className="model-config-dialog" onClick={(e) => e.stopPropagation()}>
<div className="model-config-dialog-header">
<h2>{isNewConfig ? 'Add New Model Config' : 'Configure Model'}</h2>
<button className="close-button" onClick={onClose}>×</button>
</div>

<div className="model-config-dialog-content">
<div className="form-field">
<label>Configuration Name</label>
<input
type="text"
value={configName}
onChange={(e) => setConfigName(e.target.value)}
placeholder="e.g., my-glm, work-gpt4"
/>
</div>

<div className="form-field">
<label>Provider</label>
<select value={provider} onChange={(e) => setProvider(e.target.value)}>
{PROVIDERS.map(p => (
<option key={p.value} value={p.value}>{p.label}</option>
))}
</select>
</div>

<div className="form-field">
<label>Model</label>
<input
type="text"
value={model}
onChange={(e) => setModel(e.target.value)}
placeholder="Enter model name"
/>
</div>

{needsApiKey && (
<div className="form-field">
<label>API Key</label>
<div className="input-with-icon">
<input
type={showApiKey ? 'text' : 'password'}
value={apiKey}
onChange={(e) => setApiKey(e.target.value)}
placeholder="Enter API key"
/>
<button
type="button"
className="toggle-visibility"
onClick={() => setShowApiKey(!showApiKey)}
>
{showApiKey ? '👁️' : '👁️‍🗨️'}
</button>
</div>
</div>
)}

{needsBaseUrl && (
<div className="form-field">
<label>Base URL</label>
<input
type="text"
value={baseUrl}
onChange={(e) => setBaseUrl(e.target.value)}
placeholder={
provider === 'ollama' ? 'http://localhost:11434' :
provider === 'glm' ? 'https://open.bigmodel.cn/api/paas/v4' :
provider === 'qwen' ? 'https://dashscope.aliyuncs.com/api/v1' :
provider === 'kimi' ? 'https://api.moonshot.cn/v1' :
'https://api.example.com/v1'
}
/>
</div>
)}

<div className="form-field">
<button
className="toggle-advanced"
onClick={() => setShowAdvanced(!showAdvanced)}
>
{showAdvanced ? '▼' : '▶'} Advanced Parameters
</button>
</div>

{showAdvanced && (
<>
<div className="form-field">
<label>Temperature</label>
<input
type="number"
step="0.1"
min="0"
max="2"
value={temperature}
onChange={(e) => setTemperature(e.target.value)}
placeholder="0.7"
/>
</div>

<div className="form-field">
<label>Max Tokens</label>
<input
type="number"
value={maxTokens}
onChange={(e) => setMaxTokens(e.target.value)}
placeholder="8192"
/>
</div>
</>
)}
</div>

<div className="model-config-dialog-footer">
<button className="cancel-button" onClick={onClose}>Cancel</button>
<button className="save-button" onClick={handleSave}>Save</button>
</div>
</div>
</div>
);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Add essential accessibility features to the dialog.

The dialog is missing several accessibility features that prevent keyboard-only users and screen reader users from effectively using the form:

  1. Labels not linked to inputs: Add htmlFor attributes to labels and corresponding id attributes to inputs.

  2. Missing ARIA labels: Add aria-label to icon buttons, especially the close button (×) and visibility toggle.

  3. No keyboard support: Add ESC key handler to close the dialog.

  4. No focus management: Implement focus trap within dialog and restore focus when closing.

  5. Missing dialog semantics: Add proper ARIA attributes to the dialog container:

-     <div className="model-config-dialog" onClick={(e) => e.stopPropagation()}>
+     <div 
+       className="model-config-dialog" 
+       role="dialog"
+       aria-labelledby="dialog-title"
+       aria-modal="true"
+       onClick={(e) => e.stopPropagation()}
+     >
        <div className="model-config-dialog-header">
-         <h2>{isNewConfig ? 'Add New Model Config' : 'Configure Model'}</h2>
+         <h2 id="dialog-title">{isNewConfig ? 'Add New Model Config' : 'Configure Model'}</h2>
-         <button className="close-button" onClick={onClose}>×</button>
+         <button className="close-button" onClick={onClose} aria-label="Close dialog">×</button>
        </div>

Example for linking labels to inputs:

          <div className="form-field">
-           <label>Configuration Name</label>
+           <label htmlFor="config-name">Configuration Name</label>
            <input
+             id="config-name"
              type="text"
              value={configName}
              onChange={(e) => setConfigName(e.target.value)}
              placeholder="e.g., my-glm, work-gpt4"
            />
          </div>

Add ESC key handler:

useEffect(() => {
  const handleKeyDown = (e: KeyboardEvent) => {
    if (e.key === 'Escape') {
      onClose();
    }
  };
  
  if (isOpen) {
    document.addEventListener('keydown', handleKeyDown);
    return () => document.removeEventListener('keydown', handleKeyDown);
  }
}, [isOpen, onClose]);
🤖 Prompt for AI Agents
mpp-vscode/webview/src/components/ModelConfigDialog.tsx around lines 118-238:
the dialog lacks accessibility wiring—labels are not linked to inputs, icon
buttons have no aria labels, there is no ESC key close handler, no focus
management or focus trap, and the dialog lacks proper dialog semantics; fix by
adding id attributes to each input and matching htmlFor on labels, add
aria-label (and title) to the close and API-key visibility toggle buttons, add
role="dialog", aria-modal="true" and aria-labelledby pointing at the dialog
header, implement an effect that saves document.activeElement on open and
restores focus on close, autofocus the first form control (use a ref), add a
keydown listener to close on Escape, and implement a simple JS focus trap inside
the dialog (handle Tab and Shift+Tab to cycle focusable elements) so
keyboard-only users cannot tab out of the modal until it is closed.

Comment on lines +98 to +114
{onAddNewConfig && (
<>
<button
className="dropdown-item configure-item"
onClick={() => {
onAddNewConfig();
setIsOpen(false);
}}
>
<svg className="settings-icon" width="14" height="14" viewBox="0 0 24 24" fill="currentColor">
<path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/>
</svg>
<span>Add New Config</span>
</button>
<div className="dropdown-separator" />
</>
)}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

Use i18n for the "Add New Config" label.

Line 110 contains a hardcoded string. For consistency with the i18n infrastructure added in this PR, the label should use the modelConfig.addNewConfig localization key.

While the UI flow is correct, proper internationalization requires using the i18n system. You'll need to import or access the i18n strings (similar to how mpp-ui uses Strings.addNewConfig) and replace the hardcoded text.

🤖 Prompt for AI Agents
In mpp-vscode/webview/src/components/ModelSelector.tsx around lines 98 to 114,
the "Add New Config" label is hardcoded; import and use the i18n string instead
(e.g., add an import for the project Strings module or the existing i18n
accessor used elsewhere in this file) and replace the literal span text with the
localized key modelConfig.addNewConfig (ensure the import path matches the
project convention, and run a quick compile to fix any import name or path
issues).

Copy link

@augmentcode augmentcode bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review completed. No suggestions at this time.

Comment augment review to trigger a new review at any time.

Copy link
Contributor

Copilot AI left a 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 adds the ability to create new model configurations across all three platforms (Desktop UI, IntelliJ IDEA plugin, and VSCode extension), addressing a significant usability gap where users could only edit existing configurations but not create new ones.

Key Changes:

  • Added "Add New Config" menu option in model selectors with visual indicators (Add icon)
  • Introduced isNewConfig state flag to distinguish between create and edit modes in dialogs
  • Added i18n strings for "Add New Config" and "Add" in English and Chinese for UI/IDEA versions

Critical Issues Identified:

  • VSCode implementation is incomplete - the webview sends a saveModelConfig message that has no handler in the extension backend, meaning configs cannot actually be saved
  • VSCode implementation lacks proper state cleanup when the dialog closes
  • Missing duplicate name validation in VSCode compared to UI/IDEA implementations

Reviewed changes

Copilot reviewed 14 out of 14 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
mpp-vscode/webview/src/components/ModelSelector.tsx Added "Add New Config" button with plus icon and callback propagation
mpp-vscode/webview/src/components/ModelConfigDialog.tsx New dialog component for config editing/creation with form validation (incomplete backend integration)
mpp-vscode/webview/src/components/ModelConfigDialog.css Complete styling for the model config dialog using VSCode theme variables
mpp-vscode/webview/src/components/ChatInput.tsx Added onAddNewConfig callback support for propagating the action
mpp-vscode/webview/src/App.tsx Added dialog state management and handlers (missing state cleanup on close)
mpp-ui/src/commonMain/kotlin/cc/unitmesh/devins/ui/i18n/I18n.kt Added add and addNewConfig string accessors for i18n support
mpp-ui/src/commonMain/kotlin/cc/unitmesh/devins/ui/compose/editor/ModelSelector.kt Added "Add New Config" menu item with proper i18n, state management, and unique name generation
mpp-ui/src/commonMain/i18n/cc/unitmesh/devins/ui/i18n/AutoDevStrings_zh.properties Added Chinese translations for new strings
mpp-ui/src/commonMain/i18n/cc/unitmesh/devins/ui/i18n/AutoDevStrings_en.properties Added English strings for new functionality
mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/toolwindow/IdeaDevInInputArea.kt Added onAddNewConfig callback propagation through Swing components
mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/toolwindow/IdeaAgentViewModel.kt Added isNewConfig state and helper methods for dialog mode management
mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/toolwindow/IdeaAgentApp.kt Integrated new config mode with proper state handling and unique name generation
mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/editor/SwingBottomToolbar.kt Added "Add New Config" button to Swing toolbar with icon
mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/editor/IdeaModelSelector.kt Added "Add New Config" menu item (uses hardcoded English string instead of i18n)
Comments suppressed due to low confidence (1)

mpp-vscode/webview/src/components/ModelSelector.tsx:126

  • [nitpick] The VSCode implementation uses hardcoded English strings "Add New Config" and "Configure Model..." instead of using an internationalization (i18n) system. While the UI and IDEA versions properly support multiple languages through i18n, the VSCode implementation lacks this feature.

Consider implementing an i18n solution for the VSCode webview to support multiple languages consistently across all platforms.

                <span>Add New Config</span>
              </button>
              <div className="dropdown-separator" />
            </>
          )}
          
          <button
            className="dropdown-item configure-item"
            onClick={() => {
              onConfigureClick();
              setIsOpen(false);
            }}
          >
            <svg className="settings-icon" width="14" height="14" viewBox="0 0 24 24" fill="currentColor">
              <path d="M19.14 12.94c.04-.31.06-.63.06-.94 0-.31-.02-.63-.06-.94l2.03-1.58c.18-.14.23-.41.12-.61l-1.92-3.32c-.12-.22-.37-.29-.59-.22l-2.39.96c-.5-.38-1.03-.7-1.62-.94l-.36-2.54c-.04-.24-.24-.41-.48-.41h-3.84c-.24 0-.43.17-.47.41l-.36 2.54c-.59.24-1.13.57-1.62.94l-2.39-.96c-.22-.08-.47 0-.59.22L2.74 8.87c-.12.21-.08.47.12.61l2.03 1.58c-.04.31-.06.63-.06.94s.02.63.06.94l-2.03 1.58c-.18.14-.23.41-.12.61l1.92 3.32c.12.22.37.29.59.22l2.39-.96c.5.38 1.03.7 1.62.94l.36 2.54c.05.24.24.41.48.41h3.84c.24 0 .44-.17.47-.41l.36-2.54c.59-.24 1.13-.56 1.62-.94l2.39.96c.22.08.47 0 .59-.22l1.92-3.32c.12-.22.07-.47-.12-.61l-2.01-1.58zM12 15.6c-1.98 0-3.6-1.62-3.6-3.6s1.62-3.6 3.6-3.6 3.6 1.62 3.6 3.6-1.62 3.6-3.6 3.6z"/>
            </svg>
            <span>Configure Model...</span>

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.


// Add New Config button
val addConfigButton = JButton(AllIcons.General.Add).apply {
toolTipText = "Add New Config"
Copy link

Copilot AI Dec 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The tooltip text "Add New Config" doesn't match the menu item text used in other implementations. The UI version uses "Add New Config" (from Strings.addNewConfig) and IDEA also uses "Add New Config". However, looking at the UI version's i18n files, the Chinese translation is "新增配置" (line 29 of AutoDevStrings_zh.properties).

For better consistency and clarity, consider using a more descriptive tooltip like "Add New Model Configuration" or ensure it matches the actual menu item text exactly.

Suggested change
toolTipText = "Add New Config"
toolTipText = "Add New Model Configuration"

Copilot uses AI. Check for mistakes.
Comment on lines +101 to +113
postMessage({
type: 'saveModelConfig',
data: {
name: configName.trim(),
provider,
model: model.trim(),
apiKey: apiKey.trim(),
baseUrl: baseUrl.trim() || undefined,
temperature: parseFloat(temperature) || 0.7,
maxTokens: parseInt(maxTokens) || 8192,
isNewConfig
}
});
Copy link

Copilot AI Dec 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The VSCode implementation sends a saveModelConfig message from the webview (line 102), but there's no corresponding handler for this message type in the extension backend (chat-view.ts). The message handler switch statement (lines 124-177 in chat-view.ts) only includes cases for sendMessage, clearHistory, action, openConfig, stopExecution, selectConfig, searchFiles, getRecentFiles, readFileContent, requestConfig, getActiveFile, getCompletions, and applyCompletion.

Without a handler for saveModelConfig, clicking the Save button in the ModelConfigDialog will not actually save the configuration. You need to add a case for saveModelConfig in the message handler and implement the logic to save the configuration to ~/.autodev/config.yaml using the ConfigManager.

Copilot uses AI. Check for mistakes.
modifier = Modifier.size(16.dp)
)
Text(
text = "Add New Config",
Copy link

Copilot AI Dec 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The IDEA implementation uses a hardcoded English string "Add New Config" instead of using the i18n string system. The UI version (mpp-ui) properly uses Strings.addNewConfig for internationalization support. For consistency with the codebase's i18n patterns and to support multiple languages, this should use an i18n string.

Since the i18n strings have already been added to the common I18n.kt file (Strings.addNewConfig), you should use that string here instead of the hardcoded "Add New Config".

Copilot uses AI. Check for mistakes.
Comment on lines 83 to 99
const handleSave = () => {
if (!configName.trim()) {
alert('Please enter a configuration name');
return;
}
if (!model.trim()) {
alert('Please enter a model name');
return;
}
if (needsApiKey && !apiKey.trim()) {
alert('Please enter an API key');
return;
}
if (needsBaseUrl && !baseUrl.trim()) {
alert('Please enter a base URL');
return;
}
Copy link

Copilot AI Dec 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The dialog uses alert() for validation errors, which is not consistent with VSCode's UI patterns. VSCode extensions should use vscode.window.showErrorMessage() or inline validation messages for a better user experience. However, since this is webview code, consider using inline error messages or toast notifications within the webview instead of browser alerts.

Additionally, the validation doesn't check for duplicate configuration names when creating a new config, unlike the UI version which implements this check (see mpp-ui ModelSelector.kt lines 186-193). This could lead to accidentally overwriting existing configurations.

Copilot uses AI. Check for mistakes.
{showModelConfigDialog && (
<ModelConfigDialog
isOpen={showModelConfigDialog}
onClose={() => setShowModelConfigDialog(false)}
Copy link

Copilot AI Dec 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When the dialog is closed via onClose, the isNewConfig state is not reset. This could lead to unexpected behavior if the user opens the "Configure Model" dialog after closing the "Add New Config" dialog, as the isNewConfig flag would still be true.

The UI version properly handles this by resetting isNewConfig to false in the onDismiss handler (see mpp-ui ModelSelector.kt lines 178-181). Consider adding similar state cleanup:

onClose={() => {
  setShowModelConfigDialog(false);
  setIsNewConfig(false);
  setModelConfigDialogConfig(null);
}}
Suggested change
onClose={() => setShowModelConfigDialog(false)}
onClose={() => {
setShowModelConfigDialog(false);
setIsNewConfig(false);
setModelConfigDialogConfig(null);
}}

Copilot uses AI. Check for mistakes.
- Fix missing onAddNewConfig parameter in IdeaBottomToolbar
- Add saveModelConfig message handler in VSCode chat-view.ts
- Add saveConfig and generateUniqueConfigName methods to ConfigManager
- Replace alert() with inline error messages in ModelConfigDialog
- Fix state reset issue in App.tsx when closing dialog
- Add error styling and validation feedback in ModelConfigDialog

Fixes build error: No value passed for parameter 'onAddNewConfig'
Copy link

@coderabbitai coderabbitai bot left a 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 (1)
mpp-vscode/src/services/config-manager.ts (1)

177-221: Consider using async fs operations for consistency.

The method uses synchronous fs operations (existsSync, mkdirSync, writeFileSync) which work correctly but could be replaced with async versions (access, mkdir, writeFile) for consistency with the load() method pattern and to avoid blocking the event loop.

Example refactor:

  static async saveConfig(config: LLMConfig, setActive: boolean = false): Promise<void> {
    try {
      // Ensure directory exists
-     if (!fs.existsSync(this.CONFIG_DIR)) {
-       fs.mkdirSync(this.CONFIG_DIR, { recursive: true });
-     }
+     await fs.promises.mkdir(this.CONFIG_DIR, { recursive: true }).catch(() => {});

      // Load existing config
      let wrapper = await this.load();
      const configFile = wrapper.getConfigFile();

      // ... existing logic ...

      // Write to file
      const yamlContent = yaml.stringify(configFile, {
        indent: 2,
        lineWidth: 0
      });
-     fs.writeFileSync(this.CONFIG_FILE, yamlContent, 'utf-8');
+     await fs.promises.writeFile(this.CONFIG_FILE, yamlContent, 'utf-8');
    } catch (error) {
      throw new Error(`Failed to save config: ${error}`);
    }
  }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 29a41e5 and 18e7818.

📒 Files selected for processing (6)
  • mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/editor/IdeaBottomToolbar.kt (2 hunks)
  • mpp-vscode/src/providers/chat-view.ts (2 hunks)
  • mpp-vscode/src/services/config-manager.ts (1 hunks)
  • mpp-vscode/webview/src/App.tsx (5 hunks)
  • mpp-vscode/webview/src/components/ModelConfigDialog.css (1 hunks)
  • mpp-vscode/webview/src/components/ModelConfigDialog.tsx (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • mpp-vscode/webview/src/components/ModelConfigDialog.tsx
🧰 Additional context used
📓 Path-based instructions (4)
**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

When modifying CodingAgentRenderer, update ALL TypeScript implementations: BaseRenderer.ts, CliRenderer.ts, ServerRenderer.ts, and TuiRenderer.ts

Files:

  • mpp-vscode/src/services/config-manager.ts
  • mpp-vscode/src/providers/chat-view.ts
mpp-vscode/src/**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

When modifying CodingAgentRenderer, update VSCode implementations: mpp-vscode/src/bridge/mpp-core.ts and mpp-vscode/src/providers/chat-view.ts

Files:

  • mpp-vscode/src/services/config-manager.ts
  • mpp-vscode/src/providers/chat-view.ts
**/*.{kt,ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Never use hardcoded colors - always use design tokens from the design system

Files:

  • mpp-vscode/src/services/config-manager.ts
  • mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/editor/IdeaBottomToolbar.kt
  • mpp-vscode/webview/src/App.tsx
  • mpp-vscode/src/providers/chat-view.ts
**/*.kt

📄 CodeRabbit inference engine (AGENTS.md)

**/*.kt: Use expect/actual pattern for platform-specific code (for example: Platform implementations)
Use concrete classes (not interfaces) and Promise (not Flow) for @JsExport annotations
Avoid emoji and UTF-8 characters in WASM code
When modifying CodingAgentRenderer, update ALL implementations: DefaultCodingAgentRenderer, ComposeRenderer, JewelRenderer, ServerSideRenderer, and JsRendererAdapter in Kotlin
When modifying CodingAgentRenderer, update JVM CLI implementations: CodingCliRenderer and ConsoleRenderer
Use AutoDevColors or MaterialTheme.colorScheme for Compose styling

Files:

  • mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/editor/IdeaBottomToolbar.kt
🧠 Learnings (1)
📚 Learning: 2025-12-07T08:40:10.850Z
Learnt from: CR
Repo: phodal/auto-dev PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-07T08:40:10.850Z
Learning: Applies to mpp-vscode/src/**/*.ts : When modifying `CodingAgentRenderer`, update VSCode implementations: `mpp-vscode/src/bridge/mpp-core.ts` and `mpp-vscode/src/providers/chat-view.ts`

Applied to files:

  • mpp-vscode/webview/src/App.tsx
  • mpp-vscode/src/providers/chat-view.ts
  • mpp-vscode/webview/src/components/ModelConfigDialog.css
🧬 Code graph analysis (3)
mpp-vscode/src/services/config-manager.ts (1)
mpp-core/src/commonMain/kotlin/cc/unitmesh/config/ConfigFile.kt (1)
  • configFile (91-171)
mpp-vscode/webview/src/App.tsx (3)
mpp-vscode/webview/src/components/ModelSelector.tsx (1)
  • ModelConfig (11-15)
mpp-vscode/src/bridge/mpp-core.ts (1)
  • ModelConfig (38-45)
mpp-vscode/src/providers/chat-view.ts (1)
  • postMessage (312-314)
mpp-vscode/src/providers/chat-view.ts (1)
mpp-vscode/src/services/config-manager.ts (3)
  • LLMConfig (18-26)
  • LLMProvider (13-13)
  • ConfigManager (111-239)
⏰ 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). (2)
  • GitHub Check: Test mpp-core (KMP)
  • GitHub Check: Build
🔇 Additional comments (9)
mpp-idea/src/main/kotlin/cc/unitmesh/devins/idea/editor/IdeaBottomToolbar.kt (1)

28-44: New onAddNewConfig callback wiring looks correct and backward compatible

The new onAddNewConfig parameter is added with a default value and passed straight through to IdeaModelSelector, so existing callers remain source-compatible and the add-config flow is cleanly exposed from this composable.

Also applies to: 59-65

mpp-vscode/src/services/config-manager.ts (1)

226-238: LGTM!

The unique name generation logic is clean and handles collisions correctly by appending incrementing numeric suffixes.

mpp-vscode/src/providers/chat-view.ts (2)

177-180: LGTM!

The message handling for saveModelConfig is properly integrated into the existing switch statement and follows the same pattern as other message handlers.


199-238: Verify that always setting the config as active is intended.

Line 226 always passes setActive: true to ConfigManager.saveConfig, which means both creating new configs and editing existing configs will set them as active. This might not be desired if a user edits a non-active config and expects it to remain inactive.

Consider making the active flag conditional:

-      // Save config
-      await ConfigManager.saveConfig(config, true);
+      // Save config (set as active only for new configs)
+      await ConfigManager.saveConfig(config, data.isNewConfig);

Alternatively, if the current behavior is intentional (always activate when saving), this can be kept as-is, but it should be documented or confirmed.

mpp-vscode/webview/src/App.tsx (4)

78-81: LGTM!

The state management for the model config dialog is well-structured with clear separation between dialog visibility, config data, and mode (new vs edit).


335-344: LGTM!

The enhanced handleOpenConfig correctly distinguishes between opening an existing config in the dialog versus falling back to opening the config file directly when no config is available.


346-351: LGTM!

The handleAddNewConfig handler correctly initializes the dialog state for creating a new configuration with an empty form.


509-521: LGTM!

The ModelConfigDialog integration is complete and correct. The onClose handler properly resets all dialog state including isNewConfig, which addresses the concern raised in the previous review.

mpp-vscode/webview/src/components/ModelConfigDialog.css (1)

1-178: LGTM!

The CSS implementation is excellent:

  • Follows the coding guideline to use design tokens (VSCode CSS variables) exclusively—no hardcoded colors
  • Includes proper accessibility features (focus states, keyboard navigation support)
  • Responsive sizing handles various screen sizes gracefully
  • Well-organized with clear class naming and structure

@phodal phodal merged commit 08f013c into master Dec 9, 2025
6 of 7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants