feat: add OpenAI OAuth, strict model overrides, and Gmail pull mode
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
||||
|
||||
import { OpenAIClient } from './openai.js';
|
||||
|
||||
vi.mock('../auth/openai.js', () => ({
|
||||
ensureValidOpenAIAuth: vi.fn(async () => ({
|
||||
access_token: 'at',
|
||||
refresh_token: 'rt',
|
||||
expires_at: Date.now() + 60_000,
|
||||
created_at: new Date().toISOString(),
|
||||
account_id: 'acct',
|
||||
})),
|
||||
}));
|
||||
|
||||
function makeSse(events: Array<{ event: string; data: any }>): string {
|
||||
return events
|
||||
.map((e) => `event: ${e.event}\ndata: ${JSON.stringify(e.data)}\n\n`)
|
||||
.join('');
|
||||
}
|
||||
|
||||
describe('OpenAIClient OAuth (Codex)', () => {
|
||||
const originalFetch = globalThis.fetch;
|
||||
|
||||
beforeEach(() => {
|
||||
vi.useFakeTimers();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
globalThis.fetch = originalFetch;
|
||||
vi.useRealTimers();
|
||||
vi.restoreAllMocks();
|
||||
});
|
||||
|
||||
it('streams SSE and accumulates output_text.delta', async () => {
|
||||
const sse = makeSse([
|
||||
{ event: 'response.created', data: { type: 'response.created', response: { id: 'r1' } } },
|
||||
{ event: 'response.output_text.delta', data: { type: 'response.output_text.delta', delta: 'hel' } },
|
||||
{ event: 'response.output_text.delta', data: { type: 'response.output_text.delta', delta: 'lo' } },
|
||||
{ event: 'response.completed', data: { type: 'response.completed', response: { usage: { input_tokens: 2, output_tokens: 2 } } } },
|
||||
]);
|
||||
|
||||
globalThis.fetch = vi.fn(async (_url: any, init?: any) => {
|
||||
const parsed = JSON.parse(init.body);
|
||||
expect(parsed.store).toBe(false);
|
||||
expect(parsed.stream).toBe(true);
|
||||
expect(typeof parsed.instructions).toBe('string');
|
||||
expect(Array.isArray(parsed.input)).toBe(true);
|
||||
|
||||
const stream = new ReadableStream({
|
||||
start(controller) {
|
||||
controller.enqueue(new TextEncoder().encode(sse));
|
||||
controller.close();
|
||||
},
|
||||
});
|
||||
|
||||
return new Response(stream, { status: 200 });
|
||||
}) as any;
|
||||
|
||||
const client = new OpenAIClient({ model: 'gpt-5.3-codex', useOAuth: true });
|
||||
const resp = await client.chat({
|
||||
system: 'You are helpful.',
|
||||
messages: [{ role: 'user', content: 'hi' }],
|
||||
});
|
||||
|
||||
expect(resp.content).toBe('hello');
|
||||
expect(resp.usage).toEqual({ inputTokens: 2, outputTokens: 2 });
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user