-
Notifications
You must be signed in to change notification settings - Fork 133
Expand file tree
/
Copy pathllm-provider.integration.test.js
More file actions
137 lines (116 loc) · 4.19 KB
/
Copy pathllm-provider.integration.test.js
File metadata and controls
137 lines (116 loc) · 4.19 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
import { resolveLLMConfig, buildRequestBody, stripThinkTags } from '../scripts/llm-provider.js';
/**
* Integration tests for LLM provider module.
*
* These tests verify end-to-end provider configuration resolution and
* request building across different provider scenarios.
*
* Tests marked with `MINIMAX_API_KEY` in the environment will attempt
* a live API call to verify connectivity.
*/
describe('Integration: provider config resolution', () => {
const envBackup = { ...process.env };
beforeEach(() => {
delete process.env.LLM_PROVIDER;
delete process.env.LLM_API_KEY;
delete process.env.LLM_BASE_URL;
delete process.env.LLM_MODEL;
delete process.env.MINIMAX_API_KEY;
delete process.env.OPENAI_API_KEY;
delete process.env.DEEPSEEK_API_KEY;
});
afterEach(() => {
process.env = { ...envBackup };
});
it('should produce a valid MiniMax chat completion request body', () => {
process.env.LLM_PROVIDER = 'minimax';
process.env.MINIMAX_API_KEY = 'test-key';
const config = resolveLLMConfig();
const messages = [
{ role: 'system', content: 'You are a helpful assistant.' },
{ role: 'user', content: 'Hello' },
];
const body = buildRequestBody(config.provider, config.model, messages, {
temperature: 0.1,
responseFormat: { type: 'json_object' },
});
expect(body.model).toBe('MiniMax-M3');
expect(body.temperature).toBe(0.1);
expect(body.response_format).toEqual({ type: 'json_object' });
expect(body.messages).toHaveLength(2);
// Verify the full request URL would be correct
const url = `${config.baseUrl}/chat/completions`;
expect(url).toBe('https://api.minimax.io/v1/chat/completions');
});
it('should auto-detect MiniMax and resolve full config from MINIMAX_API_KEY alone', () => {
process.env.MINIMAX_API_KEY = 'mm-test-key';
const config = resolveLLMConfig();
expect(config.provider).toBe('minimax');
expect(config.baseUrl).toBe('https://api.minimax.io/v1');
expect(config.model).toBe('MiniMax-M3');
expect(config.apiKey).toBe('mm-test-key');
});
it('should handle MiniMax response with think tags in JSON output', () => {
const rawResponse = `<think>
Let me evaluate these projects...
Project 1 looks good for the agents category.
Project 2 is not AI-related.
</think>
{
"evaluations": [
{
"id": 0,
"is_valuable": true,
"category_id": "agents",
"project": { "name": "test-agent", "description": "测试代理", "tags": ["agent"], "health": "Active" }
},
{
"id": 1,
"is_valuable": false,
"reason": "Not AI-related"
}
]
}`;
const cleaned = stripThinkTags(rawResponse);
const parsed = JSON.parse(cleaned);
expect(parsed.evaluations).toHaveLength(2);
expect(parsed.evaluations[0].is_valuable).toBe(true);
expect(parsed.evaluations[1].is_valuable).toBe(false);
});
});
describe('Integration: live MiniMax API call', () => {
const apiKey = process.env.MINIMAX_API_KEY;
it.skipIf(!apiKey)('should successfully call MiniMax chat completions API', async () => {
const config = {
provider: 'minimax',
baseUrl: 'https://api.minimax.io/v1',
apiKey,
model: 'MiniMax-M3',
};
const messages = [
{ role: 'system', content: 'Respond ONLY with valid JSON.' },
{ role: 'user', content: 'Return a JSON object with a single key "status" and value "ok".' },
];
const body = buildRequestBody(config.provider, config.model, messages, {
temperature: 0.1,
responseFormat: { type: 'json_object' },
});
const res = await fetch(`${config.baseUrl}/chat/completions`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${config.apiKey}`,
},
body: JSON.stringify(body),
});
expect(res.ok).toBe(true);
const data = await res.json();
expect(data.choices).toBeDefined();
expect(data.choices.length).toBeGreaterThan(0);
let content = data.choices[0].message.content;
content = stripThinkTags(content);
const parsed = JSON.parse(content);
expect(parsed.status).toBe('ok');
}, 30000);
});