@@ -913,6 +913,46 @@ describe("google transport stream", () => {
|
913 | 913 | expect(new Headers(guardedInit.headers).has("x-goog-api-key")).toBe(false); |
914 | 914 | }); |
915 | 915 | |
| 916 | +it("strips redundant google provider prefixes from Google Vertex model paths", async () => { |
| 917 | +const tempDir = await mkdtemp(path.join(os.tmpdir(), "openclaw-google-vertex-prefix-")); |
| 918 | +vi.stubEnv("HOME", path.join(tempDir, "home")); |
| 919 | +vi.stubEnv("APPDATA", ""); |
| 920 | +vi.stubEnv("GOOGLE_CLOUD_PROJECT", "vertex-project"); |
| 921 | +vi.stubEnv("GOOGLE_CLOUD_LOCATION", "us-central1"); |
| 922 | +googleAuthGetAccessTokenMock.mockResolvedValueOnce("ya29.transport-token"); |
| 923 | +const tokenFetchMock = vi.fn(); |
| 924 | +guardedFetchMock.mockResolvedValueOnce( |
| 925 | +buildSseResponse([ |
| 926 | +{ |
| 927 | +candidates: [{ content: { parts: [{ text: "ok" }] }, finishReason: "STOP" }], |
| 928 | +}, |
| 929 | +]), |
| 930 | +); |
| 931 | + |
| 932 | +const streamFn = createGoogleVertexTransportStreamFn(); |
| 933 | +const stream = await Promise.resolve( |
| 934 | +streamFn( |
| 935 | +buildGoogleVertexModel({ id: "google/gemini-3.1-pro-preview" }), |
| 936 | +{ |
| 937 | +messages: [{ role: "user", content: "hello", timestamp: 0 }], |
| 938 | +} as Parameters<typeof streamFn>[1], |
| 939 | +{ |
| 940 | +apiKey: "gcp-vertex-credentials", |
| 941 | +fetch: tokenFetchMock, |
| 942 | +} as Parameters<typeof streamFn>[2], |
| 943 | +), |
| 944 | +); |
| 945 | +await stream.result(); |
| 946 | + |
| 947 | +// The provider prefix must be stripped from the Vertex model path, matching |
| 948 | +// resolveGoogleModelPath; otherwise the id becomes models/google%2F... (404). |
| 949 | +const guardedCall = requireMockCall(guardedFetchMock, 0, "guarded fetch"); |
| 950 | +expect(guardedCall[0]).toContain( |
| 951 | +"/publishers/google/models/gemini-3.1-pro-preview:streamGenerateContent", |
| 952 | +); |
| 953 | +expect(guardedCall[0]).not.toContain("google%2F"); |
| 954 | +}); |
| 955 | + |
916 | 956 | it("refreshes authorized_user ADC before Google Vertex requests", async () => { |
917 | 957 | const tempDir = await mkdtemp(path.join(os.tmpdir(), "openclaw-google-vertex-adc-")); |
918 | 958 | const credentialsPath = path.join(tempDir, "application_default_credentials.json"); |
|