mirror of
https://github.com/openclaw/openclaw.git
synced 2026-07-17 04:41:35 +00:00
* feat(openai): add provider-owned route facts * fix(openai): harden provider route facts * test(codex): update rebased auth fixtures * chore: leave release notes to release workflow * fix(openai): align route auth with current contracts * test(openai): align route and shard expectations * test(openai): satisfy route fixture contracts * fix(openai): preserve direct profile forwarding * test(models): complete route auth mocks * test(codex): type compaction factory mock * fix(openai): preserve provider-native model ids * test(agents): align route auth fixtures * style(agents): format route integrations * test(plugin-sdk): pin current surface counts
103 lines
3.5 KiB
TypeScript
103 lines
3.5 KiB
TypeScript
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
import type { CodexAppServerClient } from "./client.js";
|
|
import { createClientHarness } from "./test-support.js";
|
|
|
|
const mocks = vi.hoisted(() => ({
|
|
refreshAuth: vi.fn(async () => ({ accessToken: "refreshed", chatgptAccountId: "account" })),
|
|
mergeRateLimitUpdate: vi.fn(),
|
|
}));
|
|
|
|
vi.mock("./auth-bridge.js", () => ({
|
|
refreshCodexAppServerAuthTokens: mocks.refreshAuth,
|
|
}));
|
|
|
|
vi.mock("./rate-limit-cache.js", () => ({
|
|
mergeCodexRateLimitsUpdate: mocks.mergeRateLimitUpdate,
|
|
}));
|
|
|
|
const { ensureCodexAppServerClientRuntime } = await import("./client-runtime.js");
|
|
|
|
describe("Codex app-server client runtime", () => {
|
|
const clients: CodexAppServerClient[] = [];
|
|
|
|
afterEach(() => {
|
|
for (const client of clients) {
|
|
client.close();
|
|
}
|
|
clients.length = 0;
|
|
mocks.refreshAuth.mockClear();
|
|
mocks.mergeRateLimitUpdate.mockClear();
|
|
});
|
|
|
|
it("installs shared handlers once per physical client", async () => {
|
|
const harness = createClientHarness();
|
|
clients.push(harness.client);
|
|
const context = {
|
|
agentDir: "/tmp/agent",
|
|
authProfileId: "openai:default",
|
|
config: {},
|
|
};
|
|
const updatedContext = {
|
|
...context,
|
|
authProfileStore: { version: 1 as const, profiles: {} },
|
|
config: { models: { mode: "merge" as const } },
|
|
};
|
|
const addNotificationHandler = vi.spyOn(harness.client, "addNotificationHandler");
|
|
const addRequestHandler = vi.spyOn(harness.client, "addRequestHandler");
|
|
const addCloseHandler = vi.spyOn(harness.client, "addCloseHandler");
|
|
|
|
ensureCodexAppServerClientRuntime(harness.client, context);
|
|
ensureCodexAppServerClientRuntime(harness.client, updatedContext);
|
|
|
|
expect(addNotificationHandler).toHaveBeenCalledTimes(1);
|
|
expect(addRequestHandler).toHaveBeenCalledTimes(1);
|
|
expect(addCloseHandler).not.toHaveBeenCalled();
|
|
harness.send({
|
|
method: "account/rateLimits/updated",
|
|
params: { rateLimits: { primary: { usedPercent: 12 } } },
|
|
});
|
|
harness.send({
|
|
id: "refresh-1",
|
|
method: "account/chatgptAuthTokens/refresh",
|
|
params: { reason: "expired" },
|
|
});
|
|
|
|
await vi.waitFor(() => expect(mocks.mergeRateLimitUpdate).toHaveBeenCalledTimes(1));
|
|
await vi.waitFor(() => expect(mocks.refreshAuth).toHaveBeenCalledTimes(1));
|
|
expect(mocks.refreshAuth).toHaveBeenCalledWith(updatedContext);
|
|
expect(mocks.mergeRateLimitUpdate).toHaveBeenCalledWith(harness.client, {
|
|
rateLimits: { primary: { usedPercent: 12 } },
|
|
});
|
|
await vi.waitFor(() =>
|
|
expect(harness.writes.map((line) => JSON.parse(line) as unknown)).toContainEqual({
|
|
id: "refresh-1",
|
|
result: { accessToken: "refreshed", chatgptAccountId: "account" },
|
|
}),
|
|
);
|
|
});
|
|
|
|
it("rejects ChatGPT refresh on a prepared API-key client", async () => {
|
|
const harness = createClientHarness();
|
|
clients.push(harness.client);
|
|
ensureCodexAppServerClientRuntime(harness.client, {
|
|
agentDir: "/tmp/agent",
|
|
authMode: "prepared-api-key",
|
|
});
|
|
|
|
harness.send({
|
|
id: "refresh-api-key",
|
|
method: "account/chatgptAuthTokens/refresh",
|
|
params: { reason: "expired" },
|
|
});
|
|
|
|
await vi.waitFor(() => expect(harness.writes.length).toBeGreaterThan(0));
|
|
expect(mocks.refreshAuth).not.toHaveBeenCalled();
|
|
expect(JSON.parse(harness.writes.at(-1) ?? "{}")).toMatchObject({
|
|
id: "refresh-api-key",
|
|
error: {
|
|
message: "ChatGPT token refresh is unavailable for prepared Codex API-key auth.",
|
|
},
|
|
});
|
|
});
|
|
});
|