refactor: isolate native CLI availability resolver (#129374)

Moved native CLI availability ownership resolution into the model-list auth owner and removed the stale test callback, restoring lint without changing behavior.

Refs #129332.
This commit is contained in:
Shakker
2026-08-25 15:30:08 +01:00
committed by GitHub
parent 433cf95d71
commit 2390f3d938
3 changed files with 60 additions and 55 deletions
@@ -1,3 +1,4 @@
import { normalizeProviderId } from "@openclaw/model-catalog-core/provider-id";
import type { PreparedAgentCredentialModes } from "../../agents/agent-auth-credential-modes.js";
import { resolveAgentDir } from "../../agents/agent-scope.js";
import { resolveExternalCliAuthScopeFromConfig } from "../../agents/auth-profiles/external-cli-scope.js";
@@ -7,9 +8,13 @@ import {
createModelAuthAvailabilityResolver,
type ModelAuthAvailabilityResolver,
} from "../../agents/model-auth-availability.js";
import type { ModelCatalogEntry } from "../../agents/model-catalog.types.js";
import { createOpenAIModelRoutesResolver } from "../../agents/openai-model-routes.js";
import type { OpenClawConfig } from "../../config/types.openclaw.js";
import { normalizePluginsConfig } from "../../plugins/config-state.js";
import { isActivatedManifestOwner } from "../../plugins/manifest-owner-policy.js";
import type { PluginMetadataSnapshot } from "../../plugins/plugin-metadata-snapshot.types.js";
import { resolveModelChoiceAgentRuntime } from "./models-list-public-projection.js";
function listEnabledSyntheticAuthProviderRefs(
metadataSnapshot: PluginMetadataSnapshot,
@@ -19,6 +24,48 @@ function listEnabledSyntheticAuthProviderRefs(
.flatMap((plugin) => plugin.syntheticAuthRefs ?? []);
}
export function createPreparedSyntheticCliRuntimeResolver(params: {
cfg: OpenClawConfig;
agentId: string;
metadataSnapshot: PluginMetadataSnapshot;
}): (entry: ModelCatalogEntry) => string | undefined {
const normalizedPluginConfig = normalizePluginsConfig(params.cfg.plugins);
const activatedPluginIds = new Set(
params.metadataSnapshot.plugins
.filter((plugin) =>
isActivatedManifestOwner({
plugin,
normalizedConfig: normalizedPluginConfig,
rootConfig: params.cfg,
}),
)
.map((plugin) => plugin.id),
);
return (entry) => {
const runtime = normalizeProviderId(
resolveModelChoiceAgentRuntime({
cfg: params.cfg,
agentId: params.agentId,
entry,
})?.id ?? "",
);
if (!runtime || runtime === "openclaw") {
return undefined;
}
const provider = normalizeProviderId(entry.provider);
const providerOwners = new Set(params.metadataSnapshot.owners.providers.get(provider) ?? []);
const owners = (params.metadataSnapshot.owners.cliBackends.get(runtime) ?? []).filter(
(pluginId) =>
providerOwners.has(pluginId) &&
activatedPluginIds.has(pluginId) &&
params.metadataSnapshot.byPluginId
.get(pluginId)
?.syntheticAuthRefs?.some((candidate) => normalizeProviderId(candidate) === runtime),
);
return owners.length === 1 ? runtime : undefined;
};
}
export function createModelsListAuthResolver(params: {
cfg: OpenClawConfig;
agentId: string;
@@ -45,15 +45,16 @@ import { preparedModelRuntimeConfigsMatch } from "../../agents/prepared-model-ru
import { resolveDefaultAgentWorkspaceDir } from "../../agents/workspace.js";
import { getRuntimeConfigSourceSnapshot } from "../../config/config.js";
import type { OpenClawConfig } from "../../config/types.openclaw.js";
import { normalizePluginsConfig } from "../../plugins/config-state.js";
import { isActivatedManifestOwner } from "../../plugins/manifest-owner-policy.js";
import type { PluginMetadataSnapshot } from "../../plugins/plugin-metadata-snapshot.types.js";
import type { ProviderCatalogOutcome } from "../../plugins/provider-catalog.types.js";
import { normalizeAgentId } from "../../routing/session-key.js";
import { loadDeferredCatalog, readPreparedCatalog } from "../server-model-catalog-auth.js";
import { resolveGatewayModelThinkingProfile } from "../session-utils-model.js";
import { resolveModelProviderCapabilities } from "./model-provider-capabilities.js";
import { createModelsListAuthResolver } from "./models-list-auth-resolver.js";
import {
createModelsListAuthResolver,
createPreparedSyntheticCliRuntimeResolver,
} from "./models-list-auth-resolver.js";
import { prepareModelsListHarnessCatalog } from "./models-list-harness-catalog.js";
import {
buildPublicModelProjection,
@@ -73,36 +74,6 @@ type ModelsListResult = {
let loggedSlowModelsListCatalog = false;
function resolvePreparedSyntheticCliRuntime(params: {
cfg: OpenClawConfig;
agentId: string;
entry: ModelCatalogEntry;
metadataSnapshot: PluginMetadataSnapshot;
activatedPluginIds: ReadonlySet<string>;
}): string | undefined {
const runtime = normalizeProviderId(
resolveModelChoiceAgentRuntime({
cfg: params.cfg,
agentId: params.agentId,
entry: params.entry,
})?.id ?? "",
);
if (!runtime || runtime === "openclaw") {
return undefined;
}
const provider = normalizeProviderId(params.entry.provider);
const providerOwners = new Set(params.metadataSnapshot.owners.providers.get(provider) ?? []);
const owners = (params.metadataSnapshot.owners.cliBackends.get(runtime) ?? []).filter(
(pluginId) =>
providerOwners.has(pluginId) &&
params.activatedPluginIds.has(pluginId) &&
params.metadataSnapshot.byPluginId
.get(pluginId)
?.syntheticAuthRefs?.some((candidate) => normalizeProviderId(candidate) === runtime),
);
return owners.length === 1 ? runtime : undefined;
}
function resolveModelsListView(params: Record<string, unknown>): ModelCatalogBrowseView {
const view = params.view;
return view === "configured" || view === "provider-config" || view === "all" ? view : "default";
@@ -115,19 +86,13 @@ function resolveLegacyEntryAvailability(params: {
cfg: OpenClawConfig;
agentId: string;
metadataSnapshot: PluginMetadataSnapshot;
activatedPluginIds: ReadonlySet<string>;
resolvePreparedSyntheticCliRuntime: (entry: ModelCatalogEntry) => string | undefined;
}): ModelAuthAvailability {
if (params.primaryAvailability === true) {
return true;
}
let available = params.primaryAvailability;
const preparedSyntheticRuntime = resolvePreparedSyntheticCliRuntime({
cfg: params.cfg,
agentId: params.agentId,
entry: params.entry,
metadataSnapshot: params.metadataSnapshot,
activatedPluginIds: params.activatedPluginIds,
});
const preparedSyntheticRuntime = params.resolvePreparedSyntheticCliRuntime(params.entry);
const runtimeProvider =
resolveCliRuntimeExecutionProvider({
provider: params.entry.provider,
@@ -163,18 +128,11 @@ function createModelsListEntryEvaluator(params: {
entry: ModelCatalogEntry,
routeVariants?: readonly ModelCatalogEntry[],
) => Promise<ModelAuthAvailabilityEvaluation> {
const normalizedPluginConfig = normalizePluginsConfig(params.cfg.plugins);
const activatedPluginIds = new Set(
params.metadataSnapshot.plugins
.filter((plugin) =>
isActivatedManifestOwner({
plugin,
normalizedConfig: normalizedPluginConfig,
rootConfig: params.cfg,
}),
)
.map((plugin) => plugin.id),
);
const resolvePreparedSyntheticCliRuntime = createPreparedSyntheticCliRuntimeResolver({
cfg: params.cfg,
agentId: params.agentId,
metadataSnapshot: params.metadataSnapshot,
});
const pending = new Map<string, Promise<ModelAuthAvailabilityEvaluation>>();
return (entry, routeVariants = [entry]) => {
const identity = openAIModelCatalogRoutePolicy.resolveIdentity(entry);
@@ -204,7 +162,7 @@ function createModelsListEntryEvaluator(params: {
cfg: params.cfg,
agentId: params.agentId,
metadataSnapshot: params.metadataSnapshot,
activatedPluginIds,
resolvePreparedSyntheticCliRuntime,
}),
}
: evaluation;
+1 -1
View File
@@ -1641,7 +1641,7 @@ describe("models.list", () => {
prefix: "openclaw-models-list-cli-runtime-",
agentEnv: "main",
},
async (state) => {
async () => {
const runtimeConfig = {
agents: {
defaults: {