fix(gateway): recognize env profile refs in model availability

This commit is contained in:
Ayaan Zaidi
2026-06-05 16:15:12 +05:30
parent cec5e36a39
commit 7c885528ba
2 changed files with 63 additions and 2 deletions

View File

@@ -84,6 +84,10 @@ function hasLiteralSecret(value: unknown): value is string {
return typeof value === "string" && value.trim().length > 0;
}
function hasAvailableEnvSecretRef(value: unknown): boolean {
return isSecretRef(value) && value.source === "env" && hasLiteralSecret(process.env[value.id]);
}
function profileModeAllowedForModel(
provider: string,
modelApi: string | undefined,
@@ -107,11 +111,14 @@ function profileHasReadOnlyAvailableAuth(params: {
return false;
}
if (params.credential.type === "api_key") {
return hasLiteralSecret(params.credential.key);
return (
hasLiteralSecret(params.credential.key) || hasAvailableEnvSecretRef(params.credential.keyRef)
);
}
if (params.credential.type === "token") {
return (
hasLiteralSecret(params.credential.token) &&
(hasLiteralSecret(params.credential.token) ||
hasAvailableEnvSecretRef(params.credential.tokenRef)) &&
(params.credential.expires === undefined || params.credential.expires > params.now)
);
}

View File

@@ -381,6 +381,60 @@ describe("models.list", () => {
);
});
it("marks env SecretRef-backed auth profiles available", async () => {
await withOpenClawTestState(
{
layout: "state-only",
prefix: "openclaw-models-list-env-profile-",
agentEnv: "main",
env: {
DEMO_PROVIDER_TOKEN: "test-token",
},
},
async (state) => {
await state.writeAuthProfiles({
version: 1,
profiles: {
"demo-provider:env": {
type: "token",
provider: "demo-provider",
tokenRef: {
source: "env",
provider: "default",
id: "DEMO_PROVIDER_TOKEN",
},
expires: Date.now() + 60_000,
},
},
});
const { request, respond } = requestModelsList({
view: "all",
loadGatewayModelCatalog: vi.fn(() =>
Promise.resolve([{ id: "demo-model", name: "Demo Model", provider: "demo-provider" }]),
),
reqId: "req-models-list-env-profile",
});
await request;
expect(respond).toHaveBeenCalledWith(
true,
{
models: [
{
id: "demo-model",
name: "Demo Model",
provider: "demo-provider",
available: true,
},
],
},
undefined,
);
},
);
});
it("preserves catalog load errors before the timeout fallback wins", async () => {
const { request, respond } = requestModelsList({
view: "configured",