Make model and permission choices provider-specific

This commit is contained in:
iris committed 2026-09-08 00:08:09 -04:00
1 parent 6a0202b1b5
commit 7ee88dfd9c
10 files changed
+269 -60

No files matched your search

@@ -57,10 +57,12 @@ fun SpawnScreen(
var providerName by remember { mutableStateOf<String?>(null) }
var title by remember { mutableStateOf("") }
var model by remember { mutableStateOf("") }
var providerModels by remember { mutableStateOf<List<String>>(emptyList()) }
var providerModelsLoading by remember { mutableStateOf(false) }
var providerModelsError by remember { mutableStateOf<String?>(null) }
var cwd by remember { mutableStateOf("") }
// "auto" rather than "manual": on a phone every ask is a round trip to a question card, and
// answering "allow Bash?" dozens of times per task is what this app exists to avoid.
var permissionMode by remember { mutableStateOf("auto") }
// Set only after the selected provider reports its own default. An empty value is not sent.
var permissionMode by remember { mutableStateOf("") }
// Null until the server has been asked, and null again if it answers "no level chosen" -- the
// two are told apart by [defaultsAsked], because a picker that shows a level before the answer
// arrives is one you can spawn at without having chosen it.
@@ -70,10 +72,8 @@ fun SpawnScreen(
// Only the spawn's own failure. The fetch's lives in `options`: this one leaves a filled-in
// form worth keeping, and that one leaves nothing to fill in.
var spawnError by remember { mutableStateOf<String?>(null) }
// The models on the *chosen machine*, for a llama provider to choose between. Kept separate
// from the setups: a Claude session needs none, so failing to list them must not stop the
// screen rendering. Refetched when the machine changes, because a model is a file on one
// machine -- see [fetchSetupModels].
// GGUFs on the chosen machine, for a llama provider to choose between. Kept separate from a
// coding CLI's provider catalog and refetched when the machine changes.
var models by remember { mutableStateOf<List<LocalModel>>(emptyList()) }
var modelKey by remember { mutableStateOf<String?>(null) }
var contextSize by remember { mutableStateOf("") }
@@ -145,6 +145,28 @@ fun SpawnScreen(
val isCodingCli = isClaude || isCodex
val isLlama = current?.kind == "llama_cpp"
LaunchedEffect(setup?.id, current?.name) {
model = ""
providerModels = emptyList()
providerModelsError = null
permissionMode = current?.defaultPermissionMode.orEmpty()
if (isCodingCli) {
providerModelsLoading = true
try {
providerModels =
withContext(Dispatchers.IO) {
fetchProviderModels(settings, setup.id, current.name)
}
} catch (e: ApiException) {
providerModelsError = e.message
} finally {
providerModelsLoading = false
}
} else {
providerModelsLoading = false
}
}
// The machine first, because it decides what can be run at all.
ChipGroup(
label = "Setup",
@@ -240,14 +262,34 @@ fun SpawnScreen(
}
if (isCodingCli) {
if (current.models.isNotEmpty()) {
Spacer(Modifier.height(16.dp))
ChipGroup(
label = "Model",
options = current.models,
selected = model.ifEmpty { null },
onSelect = { chosen -> model = if (model == chosen) "" else chosen },
)
when {
providerModelsLoading ->
Text(
"Loading model choices…",
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onSurfaceVariant,
)
providerModelsError != null ->
Text(
"Model choices unavailable: $providerModelsError",
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.error,
)
providerModels.isEmpty() ->
Text(
"This setup reported no selectable models.",
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onSurfaceVariant,
)
else -> {
Spacer(Modifier.height(16.dp))
ChipGroup(
label = "Model",
options = providerModels,
selected = model.ifEmpty { null },
onSelect = { chosen -> model = if (model == chosen) "" else chosen },
)
}
}
Spacer(Modifier.height(8.dp))
OutlinedTextField(
@@ -271,7 +313,7 @@ fun SpawnScreen(
ChipGroup(
label = "Permissions",
options = PERMISSION_MODES,
options = current.permissionModes,
selected = permissionMode,
onSelect = { permissionMode = it },
)