Compare commits

..

No commits in common. "fb6bc981d133527cf9265f92d1453e8a35d092bf" and "d28946627674f2b012c03dc9f178f14601c08bd7" have entirely different histories.

5 changed files with 18 additions and 79 deletions

View file

@ -151,9 +151,6 @@ fun ModePillsRow(
onReasoningChange: (ReasoningPreset) -> Unit, onReasoningChange: (ReasoningPreset) -> Unit,
samplingPrefs: SamplingPrefs, samplingPrefs: SamplingPrefs,
onSamplingChange: (SamplingPrefs) -> Unit, onSamplingChange: (SamplingPrefs) -> Unit,
currentModelId: String = "",
webSearchProvider: String = "google",
onWebSearchProviderChange: (String) -> Unit = {},
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
) { ) {
val cs = MaterialTheme.colorScheme val cs = MaterialTheme.colorScheme
@ -162,8 +159,6 @@ fun ModePillsRow(
var showReasoningMenu by remember { mutableStateOf(false) } var showReasoningMenu by remember { mutableStateOf(false) }
var showSamplingPopup by remember { mutableStateOf(false) } var showSamplingPopup by remember { mutableStateOf(false) }
var showSearchProviderMenu by remember { mutableStateOf(false) }
val isVertexModel = currentModelId.startsWith("vertex:")
Row( Row(
modifier modifier
@ -229,19 +224,19 @@ fun ModePillsRow(
shadowElevation = 16.dp, shadowElevation = 16.dp,
shape = KaizenShapes.md, shape = KaizenShapes.md,
) { ) {
Column(Modifier.padding(horizontal = 14.dp, vertical = 10.dp).width(220.dp)) { Column(Modifier.padding(horizontal = 16.dp, vertical = 12.dp).width(260.dp)) {
SamplingRow( SamplingRow(
label = stringResource(R.string.sampling_temperature), label = stringResource(R.string.sampling_temperature),
param = samplingPrefs.temperature, min = 0f, max = 2f, steps = 200, param = samplingPrefs.temperature, min = 0f, max = 2f, steps = 200,
onUpdate = { onSamplingChange(samplingPrefs.copy(temperature = it)) }, onUpdate = { onSamplingChange(samplingPrefs.copy(temperature = it)) },
) )
Spacer(Modifier.height(6.dp)) Spacer(Modifier.height(14.dp))
SamplingRow( SamplingRow(
label = stringResource(R.string.sampling_top_p), label = stringResource(R.string.sampling_top_p),
param = samplingPrefs.topP, min = 0f, max = 1f, steps = 100, param = samplingPrefs.topP, min = 0f, max = 1f, steps = 100,
onUpdate = { onSamplingChange(samplingPrefs.copy(topP = it)) }, onUpdate = { onSamplingChange(samplingPrefs.copy(topP = it)) },
) )
Spacer(Modifier.height(6.dp)) Spacer(Modifier.height(14.dp))
SamplingRow( SamplingRow(
label = stringResource(R.string.sampling_top_k), label = stringResource(R.string.sampling_top_k),
param = samplingPrefs.topK, min = 1f, max = 100f, steps = 99, param = samplingPrefs.topK, min = 1f, max = 100f, steps = 99,
@ -260,51 +255,6 @@ fun ModePillsRow(
active = active, active = active,
onClick = { onToggle(mode.labelRes) }, onClick = { onToggle(mode.labelRes) },
) )
// Search provider dropdown — only for Vertex models when search is active
if (mode.labelRes == R.string.mode_search && active && isVertexModel) {
Box {
val providerLabel = stringResource(
if (webSearchProvider == "enterprise") R.string.search_provider_enterprise
else R.string.search_provider_google
)
ModePill(
icon = KaizenIcons.Globe,
label = providerLabel,
active = true,
showChevron = true,
onClick = { showSearchProviderMenu = true },
)
DropdownMenu(
expanded = showSearchProviderMenu,
onDismissRequest = { showSearchProviderMenu = false },
containerColor = if (isDark) Color(0xFF1A2030) else Color(0xFFF8F9FB),
shadowElevation = 16.dp,
shape = KaizenShapes.md,
) {
listOf("google" to R.string.search_provider_google, "enterprise" to R.string.search_provider_enterprise).forEach { (value, labelRes) ->
Row(
Modifier
.fillMaxWidth()
.clickable { onWebSearchProviderChange(value); showSearchProviderMenu = false }
.padding(horizontal = 16.dp, vertical = 10.dp),
verticalAlignment = Alignment.CenterVertically,
) {
Text(
stringResource(labelRes),
fontSize = 13.5.sp,
color = if (value == webSearchProvider) accent.primary else cs.onBackground.copy(alpha = 0.85f),
fontWeight = if (value == webSearchProvider) FontWeight.SemiBold else FontWeight.Normal,
modifier = Modifier.weight(1f),
)
if (value == webSearchProvider) {
Icon(KaizenIcons.Check, null, tint = accent.primary, modifier = Modifier.size(15.dp))
}
}
}
}
}
}
} }
} }
} }
@ -322,22 +272,22 @@ private fun ModePill(
val accent = LocalKaizenAccent.current val accent = LocalKaizenAccent.current
val bg = when { val bg = when {
active -> accent.primary.copy(alpha = if (isDark) 0.20f else 0.12f) active -> accent.primary.copy(alpha = if (isDark) 0.15f else 0.10f)
else -> if (isDark) Color.White.copy(alpha = 0.10f) else Color.Black.copy(alpha = 0.07f) else -> if (isDark) Color.White.copy(alpha = 0.06f) else Color.Black.copy(alpha = 0.04f)
} }
val borderBrush = if (active) { val borderBrush = if (active) {
Brush.verticalGradient(listOf( Brush.verticalGradient(listOf(
accent.primary.copy(alpha = if (isDark) 0.40f else 0.30f), accent.primary.copy(alpha = if (isDark) 0.30f else 0.22f),
accent.primary.copy(alpha = if (isDark) 0.12f else 0.08f), accent.primary.copy(alpha = if (isDark) 0.08f else 0.06f),
)) ))
} else { } else {
Brush.verticalGradient(listOf( Brush.verticalGradient(listOf(
if (isDark) Color.White.copy(alpha = 0.14f) else Color.Black.copy(alpha = 0.10f), if (isDark) Color.White.copy(alpha = 0.08f) else Color.White.copy(alpha = 0.40f),
if (isDark) Color.White.copy(alpha = 0.05f) else Color.Black.copy(alpha = 0.04f), if (isDark) Color.White.copy(alpha = 0.02f) else Color.Black.copy(alpha = 0.03f),
)) ))
} }
val iconTint = if (active) accent.primary else cs.onSurfaceVariant.copy(alpha = 0.75f) val iconTint = if (active) accent.primary else cs.onSurfaceVariant.copy(alpha = 0.60f)
val textColor = if (active) cs.onBackground else cs.onSurfaceVariant.copy(alpha = 0.80f) val textColor = if (active) cs.onBackground else cs.onSurfaceVariant.copy(alpha = 0.70f)
Row( Row(
Modifier Modifier
@ -367,7 +317,7 @@ private fun SamplingRow(label: String, param: SamplingParam, min: Float, max: Fl
Row(verticalAlignment = Alignment.CenterVertically) { Row(verticalAlignment = Alignment.CenterVertically) {
Box( Box(
Modifier Modifier
.size(16.dp) .size(20.dp)
.clip(KaizenShapes.xs) .clip(KaizenShapes.xs)
.border( .border(
1.dp, 1.dp,
@ -379,17 +329,18 @@ private fun SamplingRow(label: String, param: SamplingParam, min: Float, max: Fl
contentAlignment = Alignment.Center, contentAlignment = Alignment.Center,
) { ) {
if (param.enabled) { if (param.enabled) {
Icon(KaizenIcons.Check, null, tint = accent.primary, modifier = Modifier.size(11.dp)) Icon(KaizenIcons.Check, null, tint = accent.primary, modifier = Modifier.size(13.dp))
} }
} }
Spacer(Modifier.width(8.dp)) Spacer(Modifier.width(10.dp))
Text(label, color = cs.onBackground.copy(alpha = if (param.enabled) 0.90f else 0.50f), fontSize = 12.sp, modifier = Modifier.weight(1f)) Text(label, color = cs.onBackground.copy(alpha = if (param.enabled) 0.90f else 0.50f), fontSize = 13.sp, modifier = Modifier.weight(1f))
Text( Text(
if (max > 2f) param.value.toInt().toString() else "%.2f".format(param.value), if (max > 2f) param.value.toInt().toString() else "%.2f".format(param.value),
color = if (param.enabled) accent.primary else cs.onSurfaceVariant.copy(alpha = 0.40f), color = if (param.enabled) accent.primary else cs.onSurfaceVariant.copy(alpha = 0.40f),
fontSize = 11.sp, fontWeight = FontWeight.Medium, fontSize = 12.sp, fontWeight = FontWeight.Medium,
) )
} }
Spacer(Modifier.height(4.dp))
Slider( Slider(
value = param.value, onValueChange = { onUpdate(param.copy(value = it)) }, value = param.value, onValueChange = { onUpdate(param.copy(value = it)) },
valueRange = min..max, steps = steps, valueRange = min..max, steps = steps,
@ -402,7 +353,7 @@ private fun SamplingRow(label: String, param: SamplingParam, min: Float, max: Fl
disabledActiveTrackColor = cs.onSurfaceVariant.copy(alpha = 0.15f), disabledActiveTrackColor = cs.onSurfaceVariant.copy(alpha = 0.15f),
disabledInactiveTrackColor = if (isDark) Color.White.copy(alpha = 0.05f) else Color.Black.copy(alpha = 0.04f), disabledInactiveTrackColor = if (isDark) Color.White.copy(alpha = 0.05f) else Color.Black.copy(alpha = 0.04f),
), ),
modifier = Modifier.fillMaxWidth().height(28.dp), modifier = Modifier.fillMaxWidth(),
) )
} }

View file

@ -114,7 +114,6 @@ fun ChatScreen(
var activeMode by remember { mutableStateOf<Int?>(null) } var activeMode by remember { mutableStateOf<Int?>(null) }
var reasoningPreset by remember { mutableStateOf(ReasoningPreset.Standard) } var reasoningPreset by remember { mutableStateOf(ReasoningPreset.Standard) }
var samplingPrefs by remember { mutableStateOf(SamplingPrefs()) } var samplingPrefs by remember { mutableStateOf(SamplingPrefs()) }
var webSearchProvider by remember { mutableStateOf("google") }
var usedTokens by remember { mutableStateOf(0) } var usedTokens by remember { mutableStateOf(0) }
var chatModel by remember { mutableStateOf<String?>(null) } var chatModel by remember { mutableStateOf<String?>(null) }
var streamJob by remember { mutableStateOf<Job?>(null) } var streamJob by remember { mutableStateOf<Job?>(null) }
@ -585,7 +584,6 @@ fun ChatScreen(
preferThroughput = reasoningPreset.throughput, preferThroughput = reasoningPreset.throughput,
attachments = uploadedAtts.takeIf { it.isNotEmpty() }, attachments = uploadedAtts.takeIf { it.isNotEmpty() },
webSearch = activeMode == R.string.mode_search, webSearch = activeMode == R.string.mode_search,
webSearchProvider = if (activeMode == R.string.mode_search && cfg.model.startsWith("vertex:")) webSearchProvider else null,
temperature = samplingPrefs.temperature.takeIf { it.enabled }?.value, temperature = samplingPrefs.temperature.takeIf { it.enabled }?.value,
topP = samplingPrefs.topP.takeIf { it.enabled }?.value, topP = samplingPrefs.topP.takeIf { it.enabled }?.value,
topK = samplingPrefs.topK.takeIf { it.enabled }?.value?.toInt(), topK = samplingPrefs.topK.takeIf { it.enabled }?.value?.toInt(),
@ -1057,9 +1055,6 @@ fun ChatScreen(
onReasoningChange = { reasoningPreset = it; haptics.tick() }, onReasoningChange = { reasoningPreset = it; haptics.tick() },
samplingPrefs = samplingPrefs, samplingPrefs = samplingPrefs,
onSamplingChange = { samplingPrefs = it }, onSamplingChange = { samplingPrefs = it },
currentModelId = session.config?.model ?: "",
webSearchProvider = webSearchProvider,
onWebSearchProviderChange = { webSearchProvider = it; haptics.tick() },
) )
Spacer(Modifier.height(if (imeVisible) 6.dp else 10.dp)) Spacer(Modifier.height(if (imeVisible) 6.dp else 10.dp))
ChatInput( ChatInput(

View file

@ -37,7 +37,6 @@ import java.util.concurrent.TimeUnit
val preferThroughput: Boolean? = null, val preferThroughput: Boolean? = null,
val attachments: List<Attachment>? = null, val attachments: List<Attachment>? = null,
val webSearch: Boolean? = null, val webSearch: Boolean? = null,
val webSearchProvider: String? = null,
val temperature: Float? = null, val temperature: Float? = null,
val topP: Float? = null, val topP: Float? = null,
val topK: Int? = null, val topK: Int? = null,
@ -488,7 +487,6 @@ object KaizenApi {
preferThroughput: Boolean = false, preferThroughput: Boolean = false,
attachments: List<Attachment>? = null, attachments: List<Attachment>? = null,
webSearch: Boolean = false, webSearch: Boolean = false,
webSearchProvider: String? = null,
temperature: Float? = null, temperature: Float? = null,
topP: Float? = null, topP: Float? = null,
topK: Int? = null, topK: Int? = null,
@ -501,7 +499,6 @@ object KaizenApi {
preferThroughput = if (preferThroughput) true else null, preferThroughput = if (preferThroughput) true else null,
attachments = attachments?.takeIf { it.isNotEmpty() }, attachments = attachments?.takeIf { it.isNotEmpty() },
webSearch = if (webSearch) true else null, webSearch = if (webSearch) true else null,
webSearchProvider = if (webSearch) webSearchProvider else null,
temperature = temperature, temperature = temperature,
topP = topP, topP = topP,
topK = topK, topK = topK,

View file

@ -48,8 +48,6 @@
<string name="mode_search">Search</string> <string name="mode_search">Search</string>
<string name="mode_video">Video</string> <string name="mode_video">Video</string>
<string name="mode_audio">Audio</string> <string name="mode_audio">Audio</string>
<string name="search_provider_google">Google</string>
<string name="search_provider_enterprise">Enterprise</string>
<!-- Suggestion pills --> <!-- Suggestion pills -->
<string name="suggest_brainstorm">Brainstorm</string> <string name="suggest_brainstorm">Brainstorm</string>

View file

@ -50,8 +50,6 @@
<string name="mode_search">Suche</string> <string name="mode_search">Suche</string>
<string name="mode_video">Video</string> <string name="mode_video">Video</string>
<string name="mode_audio">Audio</string> <string name="mode_audio">Audio</string>
<string name="search_provider_google">Google</string>
<string name="search_provider_enterprise">Enterprise</string>
<!-- Suggestion pills --> <!-- Suggestion pills -->
<string name="suggest_brainstorm">Brainstormen</string> <string name="suggest_brainstorm">Brainstormen</string>