Skip to content

Commit 57784d6

Browse files
committed
fix: fill Vertex ADC static catalog auth
1 parent d729342 commit 57784d6

4 files changed

Lines changed: 69 additions & 1 deletion

File tree

extensions/google/index.test.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import type { RealtimeVoiceProviderPlugin } from "openclaw/plugin-sdk/realtime-v
1717
import { describe, expect, it, vi } from "vitest";
1818
import { registerGoogleGeminiCliProvider } from "./gemini-cli-provider.js";
1919
import googlePlugin from "./index.js";
20+
import googleProviderDiscovery from "./provider-discovery.js";
2021
import { registerGoogleProvider } from "./provider-registration.js";
2122

2223
const googleProviderPlugin = {
@@ -207,6 +208,16 @@ describe("google provider plugin hooks", () => {
207208
},
208209
}),
209210
).toBe("gcp-vertex-credentials");
211+
expect(
212+
googleProviderDiscovery.resolveConfigApiKey?.({
213+
provider: "google-vertex",
214+
env: {
215+
GOOGLE_APPLICATION_CREDENTIALS: credentialsPath,
216+
GOOGLE_CLOUD_PROJECT: "vertex-project",
217+
GOOGLE_CLOUD_LOCATION: "global",
218+
},
219+
}),
220+
).toBe("gcp-vertex-credentials");
210221
});
211222

212223
it("owns Gemini tool schema normalization for direct and CLI providers", async () => {

extensions/google/provider-discovery.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,15 @@ import {
44
buildGoogleStaticCatalogProvider,
55
buildGoogleVertexStaticCatalogProvider,
66
} from "./provider-catalog.js";
7+
import { resolveGoogleVertexConfigApiKey } from "./vertex-adc.js";
78

89
const googleProviderDiscovery: ProviderPlugin = {
910
id: "google",
1011
label: "Google AI Studio",
1112
docsPath: "/providers/models",
1213
auth: [],
14+
resolveConfigApiKey: ({ provider, env }) =>
15+
provider === "google-vertex" ? resolveGoogleVertexConfigApiKey(env) : undefined,
1316
staticCatalog: {
1417
order: "simple",
1518
run: async () => ({

src/agents/models-config.providers.implicit.discovery-scope.test.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
// Exercises startup provider discovery scoping without loading real plugin manifests.
2+
import { mkdtemp, writeFile } from "node:fs/promises";
3+
import os from "node:os";
4+
import path from "node:path";
25
import { beforeEach, describe, expect, it, vi } from "vitest";
36
import type { PluginMetadataSnapshotOwnerMaps } from "../plugins/plugin-metadata-snapshot.js";
47
import type { ProviderPlugin } from "../plugins/types.js";
@@ -205,6 +208,38 @@ describe("resolveImplicitProviders startup discovery scope", () => {
205208
expect(mocks.runProviderCatalog).not.toHaveBeenCalled();
206209
});
207210

211+
it("fills missing static catalog apiKey from Google Vertex ADC auth evidence", async () => {
212+
const tempDir = await mkdtemp(path.join(os.tmpdir(), "openclaw-google-vertex-adc-"));
213+
const credentialsPath = path.join(tempDir, "application_default_credentials.json");
214+
await writeFile(credentialsPath, JSON.stringify({ type: "authorized_user" }));
215+
mocks.resolveRuntimePluginDiscoveryProviders.mockResolvedValue([
216+
createStaticOnlyProvider("google"),
217+
]);
218+
mocks.runProviderStaticCatalog.mockResolvedValue({
219+
providers: {
220+
"google-vertex": {
221+
baseUrl: "https://aiplatform.googleapis.com",
222+
api: "google-vertex" as const,
223+
models: [createTextModel("gemini-3.1-pro-preview", "Gemini 3.1 Pro Preview")],
224+
},
225+
},
226+
});
227+
228+
const providers = await resolveImplicitProviders({
229+
agentDir: "/tmp/openclaw-agent",
230+
config: {},
231+
env: {
232+
GOOGLE_APPLICATION_CREDENTIALS: credentialsPath,
233+
GOOGLE_CLOUD_PROJECT: "vertex-project",
234+
GOOGLE_CLOUD_LOCATION: "global",
235+
} as NodeJS.ProcessEnv,
236+
explicitProviders: {},
237+
providerDiscoveryEntriesOnly: true,
238+
});
239+
240+
expect(providers?.["google-vertex"]?.apiKey).toBe("gcp-vertex-credentials");
241+
});
242+
208243
it("falls back to static provider catalogs when runtime discovery has no rows", async () => {
209244
mocks.resolveRuntimePluginDiscoveryProviders.mockResolvedValue([
210245
createProviderWithStaticCatalog("minimax"),

src/agents/models-config.providers.implicit.ts

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import type {
3838
import {
3939
createProviderApiKeyResolver,
4040
createProviderAuthResolver,
41+
resolveMissingProviderApiKey,
4142
} from "./models-config.providers.secrets.js";
4243

4344
const log = createSubsystemLogger("agents/model-providers");
@@ -293,6 +294,19 @@ function mergeImplicitProviderConfig(params: {
293294
};
294295
}
295296

297+
function resolveImplicitProviderAuthMarker(params: {
298+
ctx: ImplicitProviderContext;
299+
providerId: string;
300+
provider: ProviderConfig;
301+
}): ProviderConfig {
302+
return resolveMissingProviderApiKey({
303+
providerKey: params.providerId,
304+
provider: params.provider,
305+
env: params.ctx.env,
306+
profileApiKey: undefined,
307+
});
308+
}
309+
296310
function resolveConfiguredImplicitProvider(params: {
297311
configuredProviders?: Record<string, ProviderConfig> | null;
298312
providerIds: readonly string[];
@@ -430,7 +444,7 @@ async function resolvePluginImplicitProviders(
430444
result,
431445
});
432446
for (const [providerId, implicitProvider] of Object.entries(normalizedResult)) {
433-
discovered[providerId] = mergeImplicitProviderConfig({
447+
const mergedProvider = mergeImplicitProviderConfig({
434448
providerId,
435449
existing:
436450
discovered[providerId] ??
@@ -449,6 +463,11 @@ async function resolvePluginImplicitProviders(
449463
providerId,
450464
}),
451465
});
466+
discovered[providerId] = resolveImplicitProviderAuthMarker({
467+
ctx,
468+
providerId,
469+
provider: mergedProvider,
470+
});
452471
}
453472
}
454473
return Object.keys(discovered).length > 0 ? discovered : undefined;

0 commit comments

Comments
 (0)