refactor(android): distill provider availability cleanup

This commit is contained in:
Ayaan Zaidi
2026-06-05 15:48:42 +05:30
parent 8b66003a0b
commit 30160933f0
4 changed files with 14 additions and 30 deletions

View File

@@ -283,7 +283,7 @@ private fun providerSetupSubtitle(
row: ProviderRow?,
): String =
when {
row?.status == "Expiring" -> "Credential expires soon"
row?.warning == true -> "Credential expires soon"
row?.ready == true -> if (row.modelCount > 0) "${row.modelCount} models available" else "Ready"
row?.available == true -> if (row.modelCount > 0) "${row.modelCount} models available" else "Available"
row?.setupRequired == true -> "Finish setup to use ${row.name}"
@@ -295,7 +295,7 @@ private fun providerSetupSubtitle(
private fun providerSetupStatusLabel(row: ProviderRow?): String =
when {
row?.ready == true -> "Ready"
row?.status == "Expiring" -> "Expiring"
row?.warning == true -> "Expiring"
row?.available == true -> "Available"
row?.setupRequired == false -> "Catalog"
else -> "Setup"
@@ -313,7 +313,6 @@ internal fun modelProviderReady(status: String): Boolean {
private fun modelProviderExpiring(status: String): Boolean = status.trim().lowercase() == "expiring"
/** Counts providers with either ready auth status or currently available configured models. */
internal fun readyModelProviderCount(
providers: List<GatewayModelProviderSummary>,
models: List<GatewayModelSummary>,
@@ -327,7 +326,6 @@ internal fun readyModelProviderCount(
// readiness path while still honoring explicit false from upgraded gateways.
private fun modelAvailabilityUsable(model: GatewayModelSummary): Boolean = model.available != false
/** Counts auth-backed providers that can serve now but need renewal soon. */
internal fun expiringModelProviderCount(providers: List<GatewayModelProviderSummary>): Int =
providers
.filter { modelProviderExpiring(it.status) }

View File

@@ -103,10 +103,7 @@ private val shellNavTabs = listOf(Tab.Overview, Tab.Chat, Tab.Voice, Tab.Setting
private val shellContentInsets: WindowInsets
@Composable get() = WindowInsets.safeDrawing.only(WindowInsetsSides.Top + WindowInsetsSides.Horizontal)
internal fun shellBottomNavVisible(
keyboardVisible: Boolean,
commandOpen: Boolean,
): Boolean = !keyboardVisible && !commandOpen
internal fun shellBottomNavVisible(keyboardVisible: Boolean, commandOpen: Boolean): Boolean = !keyboardVisible && !commandOpen
/** Main post-onboarding shell that owns top-level Android navigation state. */
@Composable

View File

@@ -44,20 +44,20 @@ function resolveModelCatalogBrowseTimeoutMs(value: number | undefined): number {
}
/** Loads catalog entries for browse views, using read-only discovery unless full catalog is required. */
export async function loadModelCatalogForBrowseWithState(params: {
export async function loadModelCatalogForBrowse(params: {
cfg: OpenClawConfig;
view?: ModelCatalogBrowseView;
loadCatalog: (params: { readOnly: boolean }) => Promise<ModelCatalogEntry[]>;
timeoutMs?: number;
onTimeout?: (timeoutMs: number) => void;
}): Promise<{ catalog: ModelCatalogEntry[]; timedOut: boolean }> {
}): Promise<ModelCatalogEntry[]> {
const view = params.view ?? "default";
if (view === "all") {
return { catalog: await params.loadCatalog({ readOnly: false }), timedOut: false };
return await params.loadCatalog({ readOnly: false });
}
if (parseConfiguredModelVisibilityEntries({ cfg: params.cfg }).providerWildcards.size > 0) {
// Wildcards depend on provider discovery; read-only cached entries can hide matching models.
return { catalog: await params.loadCatalog({ readOnly: false }), timedOut: false };
return await params.loadCatalog({ readOnly: false });
}
let timeout: NodeJS.Timeout | undefined;
@@ -75,23 +75,12 @@ export async function loadModelCatalogForBrowseWithState(params: {
// The browse path may return partial/empty results; keep late catalog failures off stderr.
catalogPromise.catch(() => undefined);
params.onTimeout?.(timeoutMs);
return { catalog: [], timedOut: true };
return [];
}
return { catalog: result, timedOut: false };
return result;
} finally {
if (timeout) {
modelCatalogBrowseDeps.clearTimeout(timeout);
}
}
}
/** Loads catalog entries for browse views, using read-only discovery unless full catalog is required. */
export async function loadModelCatalogForBrowse(params: {
cfg: OpenClawConfig;
view?: ModelCatalogBrowseView;
loadCatalog: (params: { readOnly: boolean }) => Promise<ModelCatalogEntry[]>;
timeoutMs?: number;
onTimeout?: (timeoutMs: number) => void;
}): Promise<ModelCatalogEntry[]> {
return (await loadModelCatalogForBrowseWithState(params)).catalog;
}

View File

@@ -7,8 +7,9 @@ import {
resolveDefaultAgentId,
} from "../../agents/agent-scope.js";
import { DEFAULT_PROVIDER } from "../../agents/defaults.js";
import { NON_ENV_SECRETREF_MARKER } from "../../agents/model-auth-markers.js";
import {
loadModelCatalogForBrowseWithState,
loadModelCatalogForBrowse,
type ModelCatalogBrowseView,
} from "../../agents/model-catalog-browse.js";
import {
@@ -16,12 +17,11 @@ import {
type ProviderAuthChecker,
resolveVisibleModelCatalog,
} from "../../agents/model-catalog-visibility.js";
import { NON_ENV_SECRETREF_MARKER } from "../../agents/model-auth-markers.js";
import type { ModelCatalogEntry } from "../../agents/model-catalog.types.js";
import { createProviderAuthChecker } from "../../agents/model-provider-auth.js";
import { isSecretRef } from "../../config/types.secrets.js";
import type { OpenClawConfig } from "../../config/types.openclaw.js";
import { resolveDefaultAgentWorkspaceDir } from "../../agents/workspace.js";
import type { OpenClawConfig } from "../../config/types.openclaw.js";
import { isSecretRef } from "../../config/types.secrets.js";
import type { GatewayRequestContext } from "./types.js";
type ModelsListView = ModelCatalogBrowseView;
@@ -125,7 +125,7 @@ export async function buildModelsListResult(params: {
const agentId = params.agentId ?? resolveDefaultAgentId(cfg);
const workspaceDir = resolveAgentWorkspaceDir(cfg, agentId) ?? resolveDefaultAgentWorkspaceDir();
const view = resolveModelsListView(params.params);
const { catalog } = await loadModelCatalogForBrowseWithState({
const catalog = await loadModelCatalogForBrowse({
cfg,
view,
loadCatalog: params.context.loadGatewayModelCatalog,