mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-02 11:31:34 +00:00
* fix(anthropic-vertex): shim native fetch so Google auth avoids gaxios's node-fetch import @anthropic-ai/vertex-sdk's bundled gaxios only uses native fetch when a global `window.fetch` exists; otherwise it dynamically imports `node-fetch`, which can fail to resolve depending on how the plugin's dependencies are installed. That failure surfaces deep inside gaxios's token-exchange path as "Cannot convert undefined or null to object", breaking every Vertex auth request (#107341). The same gaxios root cause hit a different provider in #41380, where a global window.fetch shim was the confirmed workaround. Fixes #107341 * fix(anthropic-vertex): compare window directly against undefined oxlint's unicorn/no-typeof-undefined flagged the typeof check; a direct comparison is safe here since target.window is a property access, not a possibly-undeclared identifier. * fix(anthropic-vertex): keep ADC fetch provider-local Co-authored-by: Ian Alloway <ian@allowayllc.com> * test(anthropic-vertex): inject auth in API fixtures Co-authored-by: Ian Alloway <ian@allowayllc.com> * refactor(anthropic-vertex): clarify auth transport contract Co-authored-by: Ian Alloway <ian@allowayllc.com> * fix(anthropic-vertex): preserve ADC proxy routing * chore: leave changelog to release workflow --------- Co-authored-by: Ian Alloway <ian@allowayllc.com> Co-authored-by: Peter Steinberger <steipete@gmail.com>
82 lines
2.9 KiB
TypeScript
82 lines
2.9 KiB
TypeScript
// Anthropic Vertex tests cover api plugin behavior.
|
|
import { createAssistantMessageEventStream, type Model } from "openclaw/plugin-sdk/llm";
|
|
import { beforeAll, describe, expect, it, vi } from "vitest";
|
|
import type { AnthropicVertexStreamDeps } from "./stream-runtime.js";
|
|
|
|
function createStreamDeps(): {
|
|
deps: AnthropicVertexStreamDeps;
|
|
streamAnthropicMock: ReturnType<typeof vi.fn>;
|
|
anthropicVertexCtorMock: ReturnType<typeof vi.fn>;
|
|
} {
|
|
const streamAnthropicMock = vi.fn(
|
|
(..._args: Parameters<AnthropicVertexStreamDeps["streamAnthropic"]>) =>
|
|
createAssistantMessageEventStream(),
|
|
);
|
|
const anthropicVertexCtorMock = vi.fn();
|
|
const MockAnthropicVertex = function MockAnthropicVertex(options: unknown) {
|
|
anthropicVertexCtorMock(options);
|
|
} as unknown as AnthropicVertexStreamDeps["AnthropicVertex"];
|
|
const MockGoogleAuth =
|
|
function MockGoogleAuth() {} as unknown as AnthropicVertexStreamDeps["GoogleAuth"];
|
|
|
|
return {
|
|
deps: {
|
|
AnthropicVertex: MockAnthropicVertex,
|
|
GoogleAuth: MockGoogleAuth,
|
|
streamAnthropic: streamAnthropicMock,
|
|
},
|
|
streamAnthropicMock,
|
|
anthropicVertexCtorMock,
|
|
};
|
|
}
|
|
|
|
let createAnthropicVertexStreamFn: typeof import("./api.js").createAnthropicVertexStreamFn;
|
|
let createAnthropicVertexStreamFnForModel: typeof import("./api.js").createAnthropicVertexStreamFnForModel;
|
|
|
|
function makeModel(): Model<"anthropic-messages"> {
|
|
return {
|
|
id: "claude-sonnet-4-6",
|
|
api: "anthropic-messages",
|
|
provider: "anthropic-vertex",
|
|
maxTokens: 128000,
|
|
} as Model<"anthropic-messages">;
|
|
}
|
|
|
|
describe("Anthropic Vertex API stream factories", () => {
|
|
beforeAll(async () => {
|
|
({ createAnthropicVertexStreamFn, createAnthropicVertexStreamFnForModel } =
|
|
await import("./api.js"));
|
|
});
|
|
|
|
it("reuses the runtime stream factory across direct stream calls", async () => {
|
|
const { deps, streamAnthropicMock, anthropicVertexCtorMock } = createStreamDeps();
|
|
const streamFn = createAnthropicVertexStreamFn("vertex-project", "us-east5", undefined, deps);
|
|
const model = makeModel();
|
|
|
|
await streamFn(model, { messages: [] }, {});
|
|
await streamFn(model, { messages: [] }, {});
|
|
|
|
expect(anthropicVertexCtorMock).toHaveBeenCalledTimes(1);
|
|
expect(streamAnthropicMock).toHaveBeenCalledTimes(2);
|
|
});
|
|
|
|
it("reuses the runtime stream factory across model-derived stream calls", async () => {
|
|
const { deps, streamAnthropicMock, anthropicVertexCtorMock } = createStreamDeps();
|
|
const streamFn = createAnthropicVertexStreamFnForModel(
|
|
makeModel(),
|
|
{
|
|
ANTHROPIC_VERTEX_PROJECT_ID: "vertex-project",
|
|
GOOGLE_CLOUD_LOCATION: "us-east5",
|
|
} as NodeJS.ProcessEnv,
|
|
deps,
|
|
);
|
|
const model = makeModel();
|
|
|
|
await streamFn(model, { messages: [] }, {});
|
|
await streamFn(model, { messages: [] }, {});
|
|
|
|
expect(anthropicVertexCtorMock).toHaveBeenCalledTimes(1);
|
|
expect(streamAnthropicMock).toHaveBeenCalledTimes(2);
|
|
});
|
|
});
|