llm-complete-openrouter-e2e.test.mjs file-level

at sha256:3 · View file ↗ · Intel ↗

History
1 files
1 commits
0 hotspots
0 🧊 dead
0 💥 blast risk
sha256:9 feat(calendar): hosted bridge/gateway route parity and timeline noteRec… · aaronrene · Jun 19, 2026
1 /**
2 * Tier 3 — END-TO-END: OpenRouter lane exercised the way real callers use completeChat
3 * (e.g. MCP summarize and Hub proposal LLM jobs), with a realistic OpenRouter response
4 * envelope. The HTTP boundary is mocked, but everything from caller config → provider
5 * selection → request shaping → response extraction runs end to end.
6 */
7 import { describe, it, beforeEach, afterEach } from 'node:test';
8 import assert from 'node:assert';
9 import { completeChat } from '../lib/llm-complete.mjs';
10
11 const ORIG = { ...process.env };
12 const origFetch = globalThis.fetch;
13
14 const CHAT_ENV_KEYS = [
15 'OPENAI_API_KEY',
16 'ANTHROPIC_API_KEY',
17 'DEEPINFRA_API_KEY',
18 'OPENROUTER_API_KEY',
19 'OPENROUTER_CHAT_MODEL',
20 'OPENROUTER_SITE_URL',
21 'OPENROUTER_APP_TITLE',
22 'KNOWTATION_CHAT_PROVIDER',
23 'KNOWTATION_CHAT_PREFER_ANTHROPIC',
24 ];
25
26 function clearChatEnv() {
27 for (const k of CHAT_ENV_KEYS) delete process.env[k];
28 }
29
30 function restoreEnv() {
31 for (const k of CHAT_ENV_KEYS) {
32 if (ORIG[k] === undefined) delete process.env[k];
33 else process.env[k] = ORIG[k];
34 }
35 }
36
37 describe('OpenRouter lane — end to end', () => {
38 beforeEach(() => {
39 clearChatEnv();
40 process.env.KNOWTATION_CHAT_PROVIDER = 'openrouter';
41 process.env.OPENROUTER_API_KEY = 'or-e2e';
42 });
43
44 afterEach(() => {
45 globalThis.fetch = origFetch;
46 restoreEnv();
47 });
48
49 it('summarize-style call returns the model summary from a realistic OpenRouter envelope', async () => {
50 let captured;
51 globalThis.fetch = async (url, init) => {
52 captured = { url: String(url), body: JSON.parse(init.body), headers: init.headers };
53 return {
54 ok: true,
55 json: async () => ({
56 id: 'gen-abc123',
57 model: 'openai/gpt-4o-mini',
58 object: 'chat.completion',
59 choices: [
60 {
61 index: 0,
62 finish_reason: 'stop',
63 message: { role: 'assistant', content: 'A concise three-line summary.' },
64 },
65 ],
66 usage: { prompt_tokens: 42, completion_tokens: 11, total_tokens: 53 },
67 }),
68 };
69 };
70
71 const config = { llm: { openrouter_chat_model: 'openai/gpt-4o-mini' } };
72 const out = await completeChat(config, {
73 system: 'You write concise note summaries.',
74 user: 'Summarize: The mitochondria is the powerhouse of the cell.',
75 maxTokens: 128,
76 });
77
78 assert.strictEqual(out, 'A concise three-line summary.');
79 assert.ok(captured.url.startsWith('https://openrouter.ai/api/v1/chat/completions'));
80 assert.strictEqual(captured.body.model, 'openai/gpt-4o-mini');
81 assert.strictEqual(captured.body.max_tokens, 128);
82 assert.strictEqual(captured.body.messages[0].role, 'system');
83 assert.strictEqual(captured.body.messages[0].content, 'You write concise note summaries.');
84 assert.strictEqual(captured.body.messages[1].role, 'user');
85 assert.match(captured.body.messages[1].content, /powerhouse of the cell/);
86 assert.strictEqual(captured.headers.Authorization, 'Bearer or-e2e');
87 });
88
89 it('defaults max_tokens to 512 when the caller omits it', async () => {
90 let body;
91 globalThis.fetch = async (url, init) => {
92 body = JSON.parse(init.body);
93 return { ok: true, json: async () => ({ choices: [{ message: { content: 'ok' } }] }) };
94 };
95 await completeChat({}, { system: 's', user: 'u' });
96 assert.strictEqual(body.max_tokens, 512);
97 });
98 });