llm-complete-prefer-anthropic.test.mjs
96 lines 3.2 KB
Raw
sha256:65ccb454656ea5acdea0a10e559b78bcde1eb6ff753ecc2911bc99d1c3d7cadd feat(calendar): enforce agent context tiers in retrieval AP… Human minor ⚠ breaking 1 day ago
1 /**
2 * KNOWTATION_CHAT_PREFER_ANTHROPIC reorders OpenAI vs Anthropic when both keys exist.
3 */
4 import { describe, it, beforeEach, afterEach } from 'node:test';
5 import assert from 'node:assert';
6 import { completeChat } from '../lib/llm-complete.mjs';
7
8 const origFetch = globalThis.fetch;
9 const origOpenai = process.env.OPENAI_API_KEY;
10 const origAnthropic = process.env.ANTHROPIC_API_KEY;
11 const origPrefer = process.env.KNOWTATION_CHAT_PREFER_ANTHROPIC;
12
13 function restoreEnv() {
14 process.env.OPENAI_API_KEY = origOpenai;
15 process.env.ANTHROPIC_API_KEY = origAnthropic;
16 process.env.KNOWTATION_CHAT_PREFER_ANTHROPIC = origPrefer;
17 }
18
19 describe('completeChat KNOWTATION_CHAT_PREFER_ANTHROPIC', () => {
20 beforeEach(() => {
21 delete process.env.KNOWTATION_CHAT_PREFER_ANTHROPIC;
22 });
23
24 afterEach(() => {
25 globalThis.fetch = origFetch;
26 restoreEnv();
27 });
28
29 it('default: OpenAI used when both keys set', async () => {
30 process.env.OPENAI_API_KEY = 'sk-openai-test';
31 process.env.ANTHROPIC_API_KEY = 'sk-ant-test';
32 const calls = [];
33 globalThis.fetch = async (url, init) => {
34 calls.push(String(url));
35 if (String(url).includes('api.openai.com')) {
36 return {
37 ok: true,
38 json: async () => ({
39 choices: [{ message: { content: 'from-openai' } }],
40 }),
41 };
42 }
43 return { ok: false, text: async () => 'unexpected' };
44 };
45 const out = await completeChat({}, { system: 's', user: 'u' });
46 assert.strictEqual(out, 'from-openai');
47 assert.ok(calls.some((u) => u.includes('openai.com')));
48 assert.ok(!calls.some((u) => u.includes('anthropic.com')));
49 });
50
51 it('prefer Anthropic: Claude first, OpenAI fallback on Anthropic failure', async () => {
52 process.env.KNOWTATION_CHAT_PREFER_ANTHROPIC = '1';
53 process.env.OPENAI_API_KEY = 'sk-openai-test';
54 process.env.ANTHROPIC_API_KEY = 'sk-ant-test';
55 let anthropicCalls = 0;
56 globalThis.fetch = async (url) => {
57 const u = String(url);
58 if (u.includes('anthropic.com')) {
59 anthropicCalls++;
60 return { ok: false, text: async () => 'rate limit' };
61 }
62 if (u.includes('openai.com')) {
63 return {
64 ok: true,
65 json: async () => ({
66 choices: [{ message: { content: 'from-openai-fallback' } }],
67 }),
68 };
69 }
70 return { ok: false, text: async () => 'no' };
71 };
72 const out = await completeChat({}, { system: 's', user: 'u' });
73 assert.strictEqual(out, 'from-openai-fallback');
74 assert.strictEqual(anthropicCalls, 1);
75 });
76
77 it('prefer Anthropic: returns Claude when Anthropic succeeds', async () => {
78 process.env.KNOWTATION_CHAT_PREFER_ANTHROPIC = 'true';
79 process.env.OPENAI_API_KEY = 'sk-openai-test';
80 process.env.ANTHROPIC_API_KEY = 'sk-ant-test';
81 globalThis.fetch = async (url) => {
82 const u = String(url);
83 if (u.includes('anthropic.com')) {
84 return {
85 ok: true,
86 json: async () => ({
87 content: [{ text: 'from-claude' }],
88 }),
89 };
90 }
91 return { ok: false, text: async () => 'should not reach openai' };
92 };
93 const out = await completeChat({}, { system: 's', user: 'u' });
94 assert.strictEqual(out, 'from-claude');
95 });
96 });
File History 2 commits
sha256:65ccb454656ea5acdea0a10e559b78bcde1eb6ff753ecc2911bc99d1c3d7cadd feat(calendar): enforce agent context tiers in retrieval AP… Human minor 1 day ago
sha256:9103f98c89257ed2b01c237cea895dabb3e85ea337dccb1161c175e4422355b6 docs: accept Calendar Events v0 spec with Phase 0 security … Human 1 day ago