mirror of
https://github.com/Kilo-Org/kilocode.git
synced 2026-09-19 10:02:04 +08:00
fix(jetbrains): render provider descriptions
This commit is contained in:
@@ -105,6 +105,7 @@ export type Model = Schema.Schema.Type<typeof Model>
|
||||
export const Provider = Schema.Struct({
|
||||
api: Schema.optional(Schema.String),
|
||||
name: Schema.String,
|
||||
description: Schema.optional(Schema.String), // kilocode_change
|
||||
env: Schema.Array(Schema.String),
|
||||
id: Schema.String,
|
||||
npm: Schema.optional(Schema.String),
|
||||
|
||||
+1
@@ -326,6 +326,7 @@ object KiloCliDataParser {
|
||||
ProviderSettingsProviderDto(
|
||||
id = item.str("id") ?: "",
|
||||
name = item.str("name") ?: item.str("id") ?: "",
|
||||
description = item.str("description"),
|
||||
source = item.str("source"),
|
||||
key = item.str("key"),
|
||||
metadata = parseProviderMetadata(item["metadata"].obj()),
|
||||
|
||||
+1
-1
@@ -75,7 +75,7 @@ internal class KiloBackendProviderSettingsManager(
|
||||
result.providers.forEach { provider ->
|
||||
val configured = provider.id in result.connected || provider.key != null || provider.source == "config" || provider.id in result.config
|
||||
LOG.debug {
|
||||
"provider settings provider: id=${provider.id} source=${provider.source} connected=${provider.id in result.connected} configured=$configured disabled=${provider.id in result.disabled} enabled=${provider.id in result.enabled} hasKey=${provider.key != null} auth=${result.auth[provider.id].orEmpty().map { it.type }.distinct().joinToString(",")} config=${provider.id in result.config} models=${provider.models.size}"
|
||||
"provider settings provider: id=${provider.id} source=${provider.source} connected=${provider.id in result.connected} configured=$configured disabled=${provider.id in result.disabled} enabled=${provider.id in result.enabled} hasKey=${provider.key != null} auth=${result.auth[provider.id].orEmpty().map { it.type }.distinct().joinToString(",")} config=${provider.id in result.config} models=${provider.models.size} description=${provider.description?.isNotBlank() == true} note=${provider.metadata?.note?.isNotBlank() == true} noteKey=${provider.metadata?.noteKey} icon=${provider.metadata?.icon}"
|
||||
}
|
||||
}
|
||||
LOG.debug { "provider settings state: completed dir=$directory providers=${result.providers.size} connected=${result.connected.size} auth=${result.auth.size} errors=${result.errors.size} durationMs=${System.currentTimeMillis() - start}" }
|
||||
|
||||
+2
@@ -1183,6 +1183,7 @@ class KiloCliDataParserTest {
|
||||
"all": [{
|
||||
"id": "openai",
|
||||
"name": "OpenAI",
|
||||
"description": "Build with OpenAI models",
|
||||
"source": "api",
|
||||
"metadata": {
|
||||
"noteKey": "settings.providers.note.openai",
|
||||
@@ -1201,6 +1202,7 @@ class KiloCliDataParserTest {
|
||||
val provider = result.first.single()
|
||||
|
||||
assertEquals("settings.providers.note.openai", provider.metadata?.noteKey)
|
||||
assertEquals("Build with OpenAI models", provider.description)
|
||||
assertEquals("GPT and Codex models with API key or ChatGPT login", provider.metadata?.note)
|
||||
assertEquals("openai", provider.metadata?.icon)
|
||||
assertEquals(listOf("openai"), result.second)
|
||||
|
||||
+2
-3
@@ -28,11 +28,10 @@ internal fun popularProviderIndex(id: String): Int {
|
||||
}
|
||||
|
||||
internal fun providerDescription(provider: ProviderSettingsProviderDto): String {
|
||||
provider.description?.takeIf { it.isNotBlank() }?.let { return it }
|
||||
provider.metadata?.noteKey?.let { key -> KiloBundle.optional(key)?.let { return it } }
|
||||
provider.metadata?.note?.let { return it }
|
||||
val source = provider.source ?: "catalog"
|
||||
val models = provider.models.size
|
||||
return "$source · $models models"
|
||||
return ""
|
||||
}
|
||||
|
||||
internal fun providerIcon(provider: ProviderSettingsProviderDto): Icon {
|
||||
|
||||
+9
-3
@@ -3,7 +3,10 @@ package ai.kilocode.client.settings.providers
|
||||
import ai.kilocode.client.plugin.KiloBundle
|
||||
import ai.kilocode.client.session.ui.PickerRow
|
||||
import ai.kilocode.client.ui.UiStyle
|
||||
import ai.kilocode.client.ui.layout.HAlign
|
||||
import ai.kilocode.client.ui.layout.Stack
|
||||
import ai.kilocode.client.ui.layout.VAlign
|
||||
import ai.kilocode.client.ui.layout.align
|
||||
import com.intellij.ui.CollectionListModel
|
||||
import com.intellij.ui.GroupHeaderSeparator
|
||||
import com.intellij.ui.SimpleColoredComponent
|
||||
@@ -86,6 +89,7 @@ internal class ProviderListRenderer(
|
||||
add(sep, BorderLayout.NORTH)
|
||||
}
|
||||
private val icon = JBLabel()
|
||||
private val mark = icon.align(HAlign.CENTER, VAlign.TOP)
|
||||
private val title = SimpleColoredComponent()
|
||||
private val desc = JBLabel()
|
||||
private val text = JPanel(BorderLayout()).apply {
|
||||
@@ -93,13 +97,13 @@ internal class ProviderListRenderer(
|
||||
add(desc, BorderLayout.SOUTH)
|
||||
}
|
||||
private val actions = Stack.horizontal(JBUI.scale(ACTION_GAP))
|
||||
private val row = Stack.horizontal(UiStyle.Gap.md()).next(icon).next(text)
|
||||
private val row = Stack.horizontal(UiStyle.Gap.md()).next(mark).next(text)
|
||||
private val wrap = PickerRow()
|
||||
|
||||
init {
|
||||
isOpaque = true
|
||||
top.isOpaque = true
|
||||
UiStyle.Components.transparent(row, icon, title, text, desc, actions)
|
||||
UiStyle.Components.transparent(row, mark, icon, title, text, desc, actions)
|
||||
row.border = JBUI.Borders.empty(
|
||||
UiStyle.Gap.md(),
|
||||
UiStyle.Gap.lg(),
|
||||
@@ -134,7 +138,9 @@ internal class ProviderListRenderer(
|
||||
title.clear()
|
||||
title.append(value.provider.name, SimpleTextAttributes(SimpleTextAttributes.STYLE_BOLD, fg))
|
||||
icon.icon = providerIcon(value.provider)
|
||||
desc.text = providerDescription(value.provider)
|
||||
val note = providerDescription(value.provider)
|
||||
desc.text = note
|
||||
desc.isVisible = note.isNotEmpty()
|
||||
desc.foreground = weak
|
||||
|
||||
actions.removeAll()
|
||||
|
||||
+2
-1
@@ -303,7 +303,8 @@ internal class ProvidersContent(
|
||||
@RequiresEdt
|
||||
fun update(state: ProviderSettingsDto) {
|
||||
checkEdt()
|
||||
ProvidersSettingsUi.LOG.info("provider settings content update: start providers=${state.providers.size} connected=${state.connected.size} disabled=${state.disabled.size}")
|
||||
val notes = state.providers.count { providerDescription(it).isNotBlank() }
|
||||
ProvidersSettingsUi.LOG.info("provider settings content update: start providers=${state.providers.size} connected=${state.connected.size} disabled=${state.disabled.size} descriptions=$notes")
|
||||
this.state = state
|
||||
sync()
|
||||
ProvidersSettingsUi.LOG.info("provider settings content update: completed rows=${model.size}")
|
||||
|
||||
+26
-2
@@ -357,10 +357,32 @@ class ProvidersSettingsUiTest : BasePlatformTestCase() {
|
||||
assertTrue(renderer.providerIconVisible())
|
||||
assertEquals(Dimension(JBUI.scale(20), JBUI.scale(20)), renderer.providerIconSize())
|
||||
assertEquals("GPT and Codex models with API key or ChatGPT login", renderer.descriptionText())
|
||||
assertTrue(renderer.preferredSize.height > JBUI.scale(44))
|
||||
}
|
||||
}
|
||||
|
||||
fun `test renderer falls back to generic description without metadata`() {
|
||||
fun `test renderer prefers provider description from cli`() {
|
||||
edt {
|
||||
val row = ProviderListRow(
|
||||
provider(
|
||||
"openai",
|
||||
"OpenAI",
|
||||
description = "Build with OpenAI models",
|
||||
metadata = ProviderMetadataDto(note = "Fallback metadata note"),
|
||||
),
|
||||
"Popular providers",
|
||||
listOf(ProviderListAction.CONNECT),
|
||||
)
|
||||
val list = JBList(listOf(row))
|
||||
val renderer = ProviderListRenderer(com.intellij.ui.CollectionListModel(listOf(row)))
|
||||
|
||||
renderer.getListCellRendererComponent(list, row, 0, true, false)
|
||||
|
||||
assertEquals("Build with OpenAI models", renderer.descriptionText())
|
||||
}
|
||||
}
|
||||
|
||||
fun `test renderer does not invent provider description without metadata`() {
|
||||
edt {
|
||||
val row = ProviderListRow(provider("openai", "OpenAI"), "Popular providers", listOf(ProviderListAction.CONNECT))
|
||||
val list = JBList(listOf(row))
|
||||
@@ -368,7 +390,7 @@ class ProvidersSettingsUiTest : BasePlatformTestCase() {
|
||||
|
||||
renderer.getListCellRendererComponent(list, row, 0, true, false)
|
||||
|
||||
assertEquals("catalog · 1 models", renderer.descriptionText())
|
||||
assertEquals("", renderer.descriptionText())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -496,11 +518,13 @@ class ProvidersSettingsUiTest : BasePlatformTestCase() {
|
||||
private fun provider(
|
||||
id: String,
|
||||
name: String,
|
||||
description: String? = null,
|
||||
source: String? = null,
|
||||
metadata: ProviderMetadataDto? = null,
|
||||
) = ProviderSettingsProviderDto(
|
||||
id = id,
|
||||
name = name,
|
||||
description = description,
|
||||
source = source,
|
||||
metadata = metadata,
|
||||
models = mapOf("model" to ModelDto("model", "Model")),
|
||||
|
||||
+1
@@ -18,6 +18,7 @@ data class ProviderSettingsDto(
|
||||
data class ProviderSettingsProviderDto(
|
||||
val id: String,
|
||||
val name: String,
|
||||
val description: String? = null,
|
||||
val source: String? = null,
|
||||
val key: String? = null,
|
||||
val metadata: ProviderMetadataDto? = null,
|
||||
|
||||
@@ -964,9 +964,10 @@ export type Model = Types.DeepMutable<Schema.Schema.Type<typeof Model>>
|
||||
export const Info = Schema.Struct({
|
||||
id: ProviderID,
|
||||
name: Schema.String,
|
||||
description: optionalOmitUndefined(Schema.String), // kilocode_change
|
||||
source: Schema.Literals(["env", "config", "custom", "api"]),
|
||||
env: Schema.Array(Schema.String),
|
||||
key: optionalOmitUndefined(Schema.String),
|
||||
key: optionalOmitUndefined(Schema.String), // kilocode_change
|
||||
metadata: optionalOmitUndefined(ProviderMetadata), // kilocode_change
|
||||
options: Schema.Record(Schema.String, Schema.Any),
|
||||
models: Schema.Record(Schema.String, Model),
|
||||
@@ -1163,6 +1164,7 @@ export function fromModelsDevProvider(provider: ModelsDev.Provider): Info {
|
||||
id: ProviderID.make(provider.id),
|
||||
source: "custom",
|
||||
name: provider.name,
|
||||
description: provider.description, // kilocode_change
|
||||
env: [...(provider.env ?? [])],
|
||||
options: {},
|
||||
models,
|
||||
|
||||
@@ -1522,6 +1522,7 @@ export type Model = {
|
||||
export type Provider = {
|
||||
id: string
|
||||
name: string
|
||||
description?: string
|
||||
source: "env" | "config" | "custom" | "api"
|
||||
env: Array<string>
|
||||
key?: string
|
||||
|
||||
@@ -16481,6 +16481,9 @@
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
"source": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
||||
Reference in New Issue
Block a user