feat: add gemini 2.0 flash model and update model combobox menu ui

This commit is contained in:
carlrobertoh@gmail.com 2025-02-10 17:14:46 +00:00
parent 5f3e2a8a92
commit 315dc5f4d7
3 changed files with 142 additions and 15 deletions

View file

@ -36,6 +36,7 @@ import ee.carlrobert.codegpt.settings.service.google.GoogleSettings;
import ee.carlrobert.codegpt.settings.service.llama.LlamaSettings;
import ee.carlrobert.codegpt.settings.service.ollama.OllamaSettings;
import ee.carlrobert.codegpt.settings.service.openai.OpenAISettings;
import ee.carlrobert.codegpt.toolwindow.ui.CodeGPTModelsListPopupAction;
import ee.carlrobert.llm.client.google.models.GoogleModel;
import ee.carlrobert.llm.client.openai.completion.OpenAIChatCompletionModel;
import java.awt.Color;
@ -311,13 +312,14 @@ public class ModelComboBoxAction extends ComboBoxAction {
}
private AnAction createCodeGPTModelAction(CodeGPTModel model, Presentation comboBoxPresentation) {
return createModelAction(CODEGPT, model.getName(), model.getIcon(), comboBoxPresentation,
() -> ApplicationManager.getApplication()
.getService(CodeGPTServiceSettings.class)
.getState()
.getChatCompletionSettings()
.setModel(model.getCode()));
return new CodeGPTModelsListPopupAction(model, comboBoxPresentation, () -> {
ApplicationManager.getApplication()
.getService(CodeGPTServiceSettings.class)
.getState()
.getChatCompletionSettings()
.setModel(model.getCode());
handleModelChange(CODEGPT);
});
}
private AnAction createOllamaModelAction(String model, Presentation comboBoxPresentation) {

View file

@ -7,7 +7,8 @@ import javax.swing.Icon
object CodeGPTAvailableModels {
val DEFAULT_CHAT_MODEL = CodeGPTModel("GPT-4o", "gpt-4o", Icons.OpenAI, INDIVIDUAL)
val DEFAULT_CHAT_MODEL =
CodeGPTModel("Gemini 2.0 Flash", "gemini-flash-2.0", Icons.Google, ANONYMOUS)
val DEFAULT_CODE_MODEL = CodeGPTModel("Codestral", "codestral", Icons.Mistral, ANONYMOUS)
@JvmStatic
@ -18,9 +19,8 @@ object CodeGPTAvailableModels {
CodeGPTModel("GPT-4o", "gpt-4o", Icons.OpenAI, INDIVIDUAL),
CodeGPTModel("Claude 3.5 Sonnet", "claude-3.5-sonnet", Icons.Anthropic, INDIVIDUAL),
CodeGPTModel("DeepSeek R1", "deepseek-r1", Icons.DeepSeek, INDIVIDUAL),
CodeGPTModel("Gemini 1.5 Pro", "gemini-pro-1.5", Icons.Google, INDIVIDUAL),
CodeGPTModel("DeepSeek Coder V2 - FREE", "deepseek-coder-v2", Icons.DeepSeek, ANONYMOUS),
CodeGPTModel("GPT-4o mini - FREE", "gpt-4o-mini", Icons.OpenAI, ANONYMOUS),
CodeGPTModel("Gemini 2.0 Flash", "gemini-flash-2.0", Icons.Google, ANONYMOUS),
CodeGPTModel("GPT-4o mini", "gpt-4o-mini", Icons.OpenAI, ANONYMOUS),
)
FREE -> listOf(
@ -31,7 +31,7 @@ object CodeGPTAvailableModels {
CodeGPTModel("DeepSeek V3", "deepseek-v3", Icons.DeepSeek, FREE),
CodeGPTModel("Qwen 2.5 Coder (32B)", "qwen-2.5-32b-chat", Icons.Qwen, FREE),
CodeGPTModel("Llama 3.1 (405B)", "llama-3.1-405b", Icons.Meta, FREE),
CodeGPTModel("DeepSeek Coder V2", "deepseek-coder-v2", Icons.DeepSeek, ANONYMOUS),
CodeGPTModel("Gemini 2.0 Flash", "gemini-flash-2.0", Icons.Google, ANONYMOUS),
)
INDIVIDUAL -> listOf(
@ -40,7 +40,7 @@ object CodeGPTAvailableModels {
CodeGPTModel("Claude 3.5 Sonnet", "claude-3.5-sonnet", Icons.Anthropic, INDIVIDUAL),
CodeGPTModel("DeepSeek R1", "deepseek-r1", Icons.DeepSeek, INDIVIDUAL),
CodeGPTModel("DeepSeek V3", "deepseek-v3", Icons.DeepSeek, FREE),
CodeGPTModel("Gemini 1.5 Pro", "gemini-pro-1.5", Icons.Google, INDIVIDUAL),
CodeGPTModel("Gemini 2.0 Flash", "gemini-flash-2.0", Icons.Google, ANONYMOUS),
)
}
}
@ -52,11 +52,11 @@ object CodeGPTAvailableModels {
CodeGPTModel("GPT-4o mini", "gpt-4o-mini", Icons.OpenAI, ANONYMOUS),
CodeGPTModel("Claude 3.5 Sonnet", "claude-3.5-sonnet", Icons.Anthropic, INDIVIDUAL),
CodeGPTModel("Gemini 1.5 Pro", "gemini-pro-1.5", Icons.Google, INDIVIDUAL),
CodeGPTModel("Gemini 2.0 Flash", "gemini-flash-2.0", Icons.Google, ANONYMOUS),
CodeGPTModel("Qwen 2.5 Coder (32B)", "qwen-2.5-32b-chat", Icons.Qwen, FREE),
CodeGPTModel("Llama 3.1 (405B)", "llama-3.1-405b", Icons.Meta, FREE),
CodeGPTModel("DeepSeek R1", "deepseek-r1", Icons.DeepSeek, INDIVIDUAL),
CodeGPTModel("DeepSeek V3", "deepseek-v3", Icons.DeepSeek, FREE),
CodeGPTModel("DeepSeek Coder V2", "deepseek-coder-v2", Icons.DeepSeek, FREE),
)
@JvmStatic
@ -76,5 +76,5 @@ data class CodeGPTModel(
val name: String,
val code: String,
val icon: Icon,
val individual: PricingPlan
val pricingPlan: PricingPlan
)

View file

@ -0,0 +1,125 @@
package ee.carlrobert.codegpt.toolwindow.ui
import com.intellij.openapi.actionSystem.*
import com.intellij.openapi.actionSystem.impl.MenuItemPresentationFactory
import com.intellij.openapi.project.DumbAwareAction
import com.intellij.ui.SimpleColoredComponent
import com.intellij.ui.SimpleTextAttributes
import com.intellij.ui.popup.PopupFactoryImpl
import com.intellij.ui.popup.PopupFactoryImpl.ActionItem
import com.intellij.ui.popup.list.PopupListElementRenderer
import com.intellij.util.ui.JBUI
import ee.carlrobert.codegpt.CodeGPTKeys.CODEGPT_USER_DETAILS
import ee.carlrobert.codegpt.settings.service.codegpt.CodeGPTModel
import ee.carlrobert.llm.client.codegpt.PricingPlan.ANONYMOUS
import ee.carlrobert.llm.client.codegpt.PricingPlan.INDIVIDUAL
import java.awt.BorderLayout
import javax.swing.*
class ModelListPopup(
actionGroup: ActionGroup,
context: DataContext
) : PopupFactoryImpl.ActionGroupPopup(
null,
actionGroup,
context,
false,
false,
true,
false,
null,
-1,
null,
null,
MenuItemPresentationFactory(),
false
) {
override fun getListElementRenderer(): ListCellRenderer<*> {
return object : PopupListElementRenderer<Any>(this) {
private lateinit var secondaryLabel: SimpleColoredComponent
override fun createLabel() {
super.createLabel()
secondaryLabel = SimpleColoredComponent()
}
override fun createItemComponent(): JComponent? {
createLabel()
val panel = JPanel(BorderLayout()).apply {
add(myTextLabel, BorderLayout.WEST)
add(secondaryLabel, BorderLayout.EAST)
}
myIconBar = createIconBar()
return layoutComponent(panel)
}
override fun createIconBar(): JComponent? {
return Box.createHorizontalBox().apply {
border = JBUI.Borders.emptyRight(JBUI.CurrentTheme.ActionsList.elementIconGap())
add(myIconLabel)
}
}
override fun customizeComponent(
list: JList<out Any>?,
value: Any?,
isSelected: Boolean
) {
super.customizeComponent(list, value, isSelected)
setupSecondaryLabel()
(value as? ActionItem)?.action?.let { action ->
if (action is CodeGPTModelsListPopupAction) {
updateSecondaryLabel(action)
}
}
}
private fun setupSecondaryLabel() {
secondaryLabel.apply {
font = JBUI.Fonts.toolbarSmallComboBoxFont()
border = JBUI.Borders.emptyLeft(8)
clear()
}
}
private fun updateSecondaryLabel(action: CodeGPTModelsListPopupAction) {
val userPricingPlan = CODEGPT_USER_DETAILS.get(project)?.pricingPlan
if (userPricingPlan != INDIVIDUAL && action.model.pricingPlan == INDIVIDUAL) {
secondaryLabel.append("PRO", SimpleTextAttributes.GRAYED_BOLD_ATTRIBUTES, true)
}
}
}
}
}
class CodeGPTModelsListPopupAction(
val model: CodeGPTModel,
private val comboBoxPresentation: Presentation,
private val onModelChanged: Runnable?
) : DumbAwareAction(model.name, "", model.icon) {
override fun update(event: AnActionEvent) {
event.presentation.isEnabled = shouldEnableAction(event)
}
private fun shouldEnableAction(event: AnActionEvent): Boolean {
val project = event.project ?: return false
val notSelected = event.presentation.text != comboBoxPresentation.text
val pricingPlan = CODEGPT_USER_DETAILS[project]?.pricingPlan
if (pricingPlan == null || pricingPlan == ANONYMOUS) {
return notSelected && model.pricingPlan == ANONYMOUS
}
return notSelected
}
override fun actionPerformed(e: AnActionEvent) {
onModelChanged?.run()
}
override fun getActionUpdateThread(): ActionUpdateThread {
return ActionUpdateThread.BGT
}
}