@perplexity-ai/mcp-server 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,566 +0,0 @@
1
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
- return new (P || (P = Promise))(function (resolve, reject) {
4
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
- step((generator = generator.apply(thisArg, _arguments || [])).next());
8
- });
9
- };
10
- import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
11
- import { formatSearchResults, performChatCompletion, performSearch } from "./index.js";
12
- describe("Perplexity MCP Server", () => {
13
- let originalFetch;
14
- beforeEach(() => {
15
- originalFetch = global.fetch;
16
- });
17
- afterEach(() => {
18
- global.fetch = originalFetch;
19
- vi.restoreAllMocks();
20
- });
21
- describe("formatSearchResults", () => {
22
- it("should format search results correctly", () => {
23
- const mockData = {
24
- results: [
25
- {
26
- title: "Test Result 1",
27
- url: "https://example.com/1",
28
- snippet: "This is a test snippet",
29
- date: "2025-01-01",
30
- },
31
- {
32
- title: "Test Result 2",
33
- url: "https://example.com/2",
34
- snippet: "Another snippet",
35
- },
36
- ],
37
- };
38
- const formatted = formatSearchResults(mockData);
39
- expect(formatted).toContain("Found 2 search results");
40
- expect(formatted).toContain("Test Result 1");
41
- expect(formatted).toContain("https://example.com/1");
42
- expect(formatted).toContain("This is a test snippet");
43
- expect(formatted).toContain("Date: 2025-01-01");
44
- expect(formatted).toContain("Test Result 2");
45
- });
46
- it("should handle empty results", () => {
47
- const mockData = { results: [] };
48
- const formatted = formatSearchResults(mockData);
49
- expect(formatted).toContain("Found 0 search results");
50
- });
51
- it("should handle missing results array", () => {
52
- const mockData = {};
53
- const formatted = formatSearchResults(mockData);
54
- expect(formatted).toBe("No search results found.");
55
- });
56
- });
57
- describe("performChatCompletion", () => {
58
- it("should successfully complete chat request", () => __awaiter(void 0, void 0, void 0, function* () {
59
- const mockResponse = {
60
- choices: [
61
- {
62
- message: {
63
- content: "This is a test response",
64
- },
65
- },
66
- ],
67
- };
68
- global.fetch = vi.fn().mockResolvedValue({
69
- ok: true,
70
- json: () => __awaiter(void 0, void 0, void 0, function* () { return mockResponse; }),
71
- });
72
- const messages = [{ role: "user", content: "test question" }];
73
- const result = yield performChatCompletion(messages, "sonar-pro");
74
- expect(result).toBe("This is a test response");
75
- expect(global.fetch).toHaveBeenCalledWith("https://api.perplexity.ai/chat/completions", expect.objectContaining({
76
- method: "POST",
77
- headers: {
78
- "Content-Type": "application/json",
79
- Authorization: "Bearer test-api-key",
80
- },
81
- body: JSON.stringify({
82
- model: "sonar-pro",
83
- messages,
84
- }),
85
- }));
86
- }));
87
- it("should append citations when present", () => __awaiter(void 0, void 0, void 0, function* () {
88
- const mockResponse = {
89
- choices: [
90
- {
91
- message: {
92
- content: "Response with citations",
93
- },
94
- },
95
- ],
96
- citations: [
97
- "https://example.com/source1",
98
- "https://example.com/source2",
99
- ],
100
- };
101
- global.fetch = vi.fn().mockResolvedValue({
102
- ok: true,
103
- json: () => __awaiter(void 0, void 0, void 0, function* () { return mockResponse; }),
104
- });
105
- const messages = [{ role: "user", content: "test" }];
106
- const result = yield performChatCompletion(messages);
107
- expect(result).toContain("Response with citations");
108
- expect(result).toContain("\n\nCitations:\n");
109
- expect(result).toContain("[1] https://example.com/source1");
110
- expect(result).toContain("[2] https://example.com/source2");
111
- }));
112
- it("should handle API errors", () => __awaiter(void 0, void 0, void 0, function* () {
113
- global.fetch = vi.fn().mockResolvedValue({
114
- ok: false,
115
- status: 401,
116
- statusText: "Unauthorized",
117
- text: () => __awaiter(void 0, void 0, void 0, function* () { return "Invalid API key"; }),
118
- });
119
- const messages = [{ role: "user", content: "test" }];
120
- yield expect(performChatCompletion(messages)).rejects.toThrow("Perplexity API error: 401 Unauthorized");
121
- }));
122
- it("should handle timeout errors", () => __awaiter(void 0, void 0, void 0, function* () {
123
- process.env.PERPLEXITY_TIMEOUT_MS = "100";
124
- global.fetch = vi.fn().mockImplementation((_url, options) => {
125
- return new Promise((resolve, reject) => {
126
- const signal = options === null || options === void 0 ? void 0 : options.signal;
127
- if (signal) {
128
- signal.addEventListener("abort", () => {
129
- reject(new DOMException("The operation was aborted.", "AbortError"));
130
- });
131
- }
132
- setTimeout(() => {
133
- resolve({
134
- ok: true,
135
- json: () => __awaiter(void 0, void 0, void 0, function* () { return ({ choices: [{ message: { content: "late" } }] }); }),
136
- });
137
- }, 200);
138
- });
139
- });
140
- const messages = [{ role: "user", content: "test" }];
141
- yield expect(performChatCompletion(messages)).rejects.toThrow("Request timeout");
142
- }));
143
- it("should handle network errors", () => __awaiter(void 0, void 0, void 0, function* () {
144
- global.fetch = vi.fn().mockRejectedValue(new Error("Network failure"));
145
- const messages = [{ role: "user", content: "test" }];
146
- yield expect(performChatCompletion(messages)).rejects.toThrow("Network error while calling Perplexity API");
147
- }));
148
- });
149
- describe("performSearch", () => {
150
- it("should successfully perform search", () => __awaiter(void 0, void 0, void 0, function* () {
151
- const mockResponse = {
152
- results: [
153
- {
154
- title: "Search Result",
155
- url: "https://example.com",
156
- snippet: "Test snippet",
157
- },
158
- ],
159
- };
160
- global.fetch = vi.fn().mockResolvedValue({
161
- ok: true,
162
- json: () => __awaiter(void 0, void 0, void 0, function* () { return mockResponse; }),
163
- });
164
- const result = yield performSearch("test query", 10, 1024);
165
- expect(result).toContain("Found 1 search results");
166
- expect(result).toContain("Search Result");
167
- expect(global.fetch).toHaveBeenCalledWith("https://api.perplexity.ai/search", expect.objectContaining({
168
- method: "POST",
169
- headers: {
170
- "Content-Type": "application/json",
171
- Authorization: "Bearer test-api-key",
172
- },
173
- body: JSON.stringify({
174
- query: "test query",
175
- max_results: 10,
176
- max_tokens_per_page: 1024,
177
- }),
178
- }));
179
- }));
180
- it("should include country parameter when provided", () => __awaiter(void 0, void 0, void 0, function* () {
181
- const mockResponse = { results: [] };
182
- global.fetch = vi.fn().mockResolvedValue({
183
- ok: true,
184
- json: () => __awaiter(void 0, void 0, void 0, function* () { return mockResponse; }),
185
- });
186
- yield performSearch("test", 10, 1024, "US");
187
- expect(global.fetch).toHaveBeenCalledWith("https://api.perplexity.ai/search", expect.objectContaining({
188
- body: JSON.stringify({
189
- query: "test",
190
- max_results: 10,
191
- max_tokens_per_page: 1024,
192
- country: "US",
193
- }),
194
- }));
195
- }));
196
- it("should handle search API errors", () => __awaiter(void 0, void 0, void 0, function* () {
197
- global.fetch = vi.fn().mockResolvedValue({
198
- ok: false,
199
- status: 500,
200
- statusText: "Internal Server Error",
201
- text: () => __awaiter(void 0, void 0, void 0, function* () { return "Server error"; }),
202
- });
203
- yield expect(performSearch("test")).rejects.toThrow("Perplexity Search API error: 500 Internal Server Error");
204
- }));
205
- });
206
- describe("API Response Validation", () => {
207
- it("should handle empty choices array", () => __awaiter(void 0, void 0, void 0, function* () {
208
- global.fetch = vi.fn().mockResolvedValue({
209
- ok: true,
210
- json: () => __awaiter(void 0, void 0, void 0, function* () { return ({ choices: [] }); }),
211
- });
212
- const messages = [{ role: "user", content: "test" }];
213
- yield expect(performChatCompletion(messages)).rejects.toThrow("missing or empty choices array");
214
- }));
215
- it("should handle missing message content", () => __awaiter(void 0, void 0, void 0, function* () {
216
- global.fetch = vi.fn().mockResolvedValue({
217
- ok: true,
218
- json: () => __awaiter(void 0, void 0, void 0, function* () { return ({ choices: [{ message: null }] }); }),
219
- });
220
- const messages = [{ role: "user", content: "test" }];
221
- yield expect(performChatCompletion(messages)).rejects.toThrow("missing message content");
222
- }));
223
- it("should handle missing choices property", () => __awaiter(void 0, void 0, void 0, function* () {
224
- global.fetch = vi.fn().mockResolvedValue({
225
- ok: true,
226
- json: () => __awaiter(void 0, void 0, void 0, function* () { return ({}); }),
227
- });
228
- const messages = [{ role: "user", content: "test" }];
229
- yield expect(performChatCompletion(messages)).rejects.toThrow("missing or empty choices array");
230
- }));
231
- it("should handle malformed message object", () => __awaiter(void 0, void 0, void 0, function* () {
232
- global.fetch = vi.fn().mockResolvedValue({
233
- ok: true,
234
- json: () => __awaiter(void 0, void 0, void 0, function* () { return ({ choices: [{ message: { content: 123 } }] }); }),
235
- });
236
- const messages = [{ role: "user", content: "test" }];
237
- yield expect(performChatCompletion(messages)).rejects.toThrow("missing message content");
238
- }));
239
- it("should handle null choices", () => __awaiter(void 0, void 0, void 0, function* () {
240
- global.fetch = vi.fn().mockResolvedValue({
241
- ok: true,
242
- json: () => __awaiter(void 0, void 0, void 0, function* () { return ({ choices: null }); }),
243
- });
244
- const messages = [{ role: "user", content: "test" }];
245
- yield expect(performChatCompletion(messages)).rejects.toThrow("missing or empty choices array");
246
- }));
247
- it("should handle undefined message in choice", () => __awaiter(void 0, void 0, void 0, function* () {
248
- global.fetch = vi.fn().mockResolvedValue({
249
- ok: true,
250
- json: () => __awaiter(void 0, void 0, void 0, function* () { return ({ choices: [{}] }); }),
251
- });
252
- const messages = [{ role: "user", content: "test" }];
253
- yield expect(performChatCompletion(messages)).rejects.toThrow("missing message content");
254
- }));
255
- it("should handle empty citations array gracefully", () => __awaiter(void 0, void 0, void 0, function* () {
256
- const mockResponse = {
257
- choices: [{ message: { content: "Response" } }],
258
- citations: [],
259
- };
260
- global.fetch = vi.fn().mockResolvedValue({
261
- ok: true,
262
- json: () => __awaiter(void 0, void 0, void 0, function* () { return mockResponse; }),
263
- });
264
- const messages = [{ role: "user", content: "test" }];
265
- const result = yield performChatCompletion(messages);
266
- expect(result).toBe("Response");
267
- expect(result).not.toContain("Citations:");
268
- }));
269
- it("should handle non-array citations", () => __awaiter(void 0, void 0, void 0, function* () {
270
- const mockResponse = {
271
- choices: [{ message: { content: "Response" } }],
272
- citations: "not-an-array",
273
- };
274
- global.fetch = vi.fn().mockResolvedValue({
275
- ok: true,
276
- json: () => __awaiter(void 0, void 0, void 0, function* () { return mockResponse; }),
277
- });
278
- const messages = [{ role: "user", content: "test" }];
279
- const result = yield performChatCompletion(messages);
280
- expect(result).toBe("Response");
281
- expect(result).not.toContain("Citations:");
282
- }));
283
- });
284
- describe("Edge Cases", () => {
285
- it("should handle JSON parse errors gracefully", () => __awaiter(void 0, void 0, void 0, function* () {
286
- global.fetch = vi.fn().mockResolvedValue({
287
- ok: true,
288
- json: () => __awaiter(void 0, void 0, void 0, function* () {
289
- throw new Error("Invalid JSON");
290
- }),
291
- });
292
- const messages = [{ role: "user", content: "test" }];
293
- yield expect(performChatCompletion(messages)).rejects.toThrow("Failed to parse JSON response");
294
- }));
295
- it("should handle error text parse failures", () => __awaiter(void 0, void 0, void 0, function* () {
296
- global.fetch = vi.fn().mockResolvedValue({
297
- ok: false,
298
- status: 500,
299
- statusText: "Internal Server Error",
300
- text: () => __awaiter(void 0, void 0, void 0, function* () {
301
- throw new Error("Cannot read error");
302
- }),
303
- });
304
- const messages = [{ role: "user", content: "test" }];
305
- yield expect(performChatCompletion(messages)).rejects.toThrow("Unable to parse error response");
306
- }));
307
- it("should handle special characters in messages", () => __awaiter(void 0, void 0, void 0, function* () {
308
- const mockResponse = {
309
- choices: [{ message: { content: "Response with émojis 🎉 and unicode ñ" } }],
310
- };
311
- global.fetch = vi.fn().mockResolvedValue({
312
- ok: true,
313
- json: () => __awaiter(void 0, void 0, void 0, function* () { return mockResponse; }),
314
- });
315
- const messages = [{ role: "user", content: "test with émojis 🎉" }];
316
- const result = yield performChatCompletion(messages);
317
- expect(result).toContain("émojis 🎉");
318
- expect(result).toContain("unicode ñ");
319
- }));
320
- it("should handle very long content strings", () => __awaiter(void 0, void 0, void 0, function* () {
321
- const longContent = "x".repeat(100000);
322
- const mockResponse = {
323
- choices: [{ message: { content: longContent } }],
324
- };
325
- global.fetch = vi.fn().mockResolvedValue({
326
- ok: true,
327
- json: () => __awaiter(void 0, void 0, void 0, function* () { return mockResponse; }),
328
- });
329
- const messages = [{ role: "user", content: "test" }];
330
- const result = yield performChatCompletion(messages);
331
- expect(result).toBe(longContent);
332
- expect(result.length).toBe(100000);
333
- }));
334
- it("should handle multiple models correctly", () => __awaiter(void 0, void 0, void 0, function* () {
335
- const models = ["sonar-pro", "sonar-deep-research", "sonar-reasoning-pro"];
336
- for (const model of models) {
337
- const mockResponse = {
338
- choices: [{ message: { content: `Response from ${model}` } }],
339
- };
340
- global.fetch = vi.fn().mockResolvedValue({
341
- ok: true,
342
- json: () => __awaiter(void 0, void 0, void 0, function* () { return mockResponse; }),
343
- });
344
- const messages = [{ role: "user", content: "test" }];
345
- const result = yield performChatCompletion(messages, model);
346
- expect(result).toContain(model);
347
- expect(global.fetch).toHaveBeenCalledWith("https://api.perplexity.ai/chat/completions", expect.objectContaining({
348
- body: expect.stringContaining(`"model":"${model}"`),
349
- }));
350
- }
351
- }));
352
- it("should handle search with boundary values", () => __awaiter(void 0, void 0, void 0, function* () {
353
- const mockResponse = { results: [] };
354
- global.fetch = vi.fn().mockResolvedValue({
355
- ok: true,
356
- json: () => __awaiter(void 0, void 0, void 0, function* () { return mockResponse; }),
357
- });
358
- // Test max values
359
- yield performSearch("test", 20, 2048);
360
- expect(global.fetch).toHaveBeenCalledWith("https://api.perplexity.ai/search", expect.objectContaining({
361
- body: expect.stringContaining('"max_results":20'),
362
- }));
363
- // Test min values
364
- yield performSearch("test", 1, 256);
365
- expect(global.fetch).toHaveBeenCalledWith("https://api.perplexity.ai/search", expect.objectContaining({
366
- body: expect.stringContaining('"max_results":1'),
367
- }));
368
- }));
369
- it("should handle formatSearchResults with missing optional fields", () => __awaiter(void 0, void 0, void 0, function* () {
370
- const mockData = {
371
- results: [
372
- { title: "Test", url: "https://example.com" },
373
- { title: "Test 2", url: "https://example.com/2", snippet: "snippet only" },
374
- { title: "Test 3", url: "https://example.com/3", date: "2025-01-01" },
375
- ],
376
- };
377
- const formatted = formatSearchResults(mockData);
378
- expect(formatted).toContain("Test");
379
- expect(formatted).toContain("Test 2");
380
- expect(formatted).toContain("snippet only");
381
- expect(formatted).toContain("Date: 2025-01-01");
382
- expect(formatted).not.toContain("undefined");
383
- }));
384
- it("should handle concurrent requests correctly", () => __awaiter(void 0, void 0, void 0, function* () {
385
- let callCount = 0;
386
- global.fetch = vi.fn().mockImplementation(() => __awaiter(void 0, void 0, void 0, function* () {
387
- const currentCall = ++callCount;
388
- yield new Promise((resolve) => setTimeout(resolve, 10));
389
- return {
390
- ok: true,
391
- json: () => __awaiter(void 0, void 0, void 0, function* () {
392
- return ({
393
- choices: [{ message: { content: `Response ${currentCall}` } }]
394
- });
395
- }),
396
- };
397
- }));
398
- const messages = [{ role: "user", content: "test" }];
399
- const promises = [
400
- performChatCompletion(messages),
401
- performChatCompletion(messages),
402
- performChatCompletion(messages),
403
- ];
404
- const results = yield Promise.all(promises);
405
- expect(results).toHaveLength(3);
406
- expect(global.fetch).toHaveBeenCalledTimes(3);
407
- // Results should all be present (may not be unique due to timing)
408
- expect(results.every(r => r.startsWith("Response"))).toBe(true);
409
- }));
410
- it("should respect timeout on each call independently", () => __awaiter(void 0, void 0, void 0, function* () {
411
- // First call with long timeout
412
- process.env.PERPLEXITY_TIMEOUT_MS = "1000";
413
- global.fetch = vi.fn().mockImplementation((_url, options) => {
414
- return new Promise((resolve) => {
415
- const signal = options === null || options === void 0 ? void 0 : options.signal;
416
- setTimeout(() => {
417
- if (!(signal === null || signal === void 0 ? void 0 : signal.aborted)) {
418
- resolve({
419
- ok: true,
420
- json: () => __awaiter(void 0, void 0, void 0, function* () { return ({ choices: [{ message: { content: "fast" } }] }); }),
421
- });
422
- }
423
- }, 50);
424
- });
425
- });
426
- const messages = [{ role: "user", content: "test" }];
427
- const result1 = yield performChatCompletion(messages);
428
- expect(result1).toBe("fast");
429
- // Second call with short timeout
430
- process.env.PERPLEXITY_TIMEOUT_MS = "10";
431
- global.fetch = vi.fn().mockImplementation((_url, options) => {
432
- return new Promise((resolve, reject) => {
433
- const signal = options === null || options === void 0 ? void 0 : options.signal;
434
- if (signal) {
435
- signal.addEventListener("abort", () => {
436
- reject(new DOMException("The operation was aborted.", "AbortError"));
437
- });
438
- }
439
- setTimeout(() => {
440
- resolve({
441
- ok: true,
442
- json: () => __awaiter(void 0, void 0, void 0, function* () { return ({ choices: [{ message: { content: "slow" } }] }); }),
443
- });
444
- }, 100);
445
- });
446
- });
447
- yield expect(performChatCompletion(messages)).rejects.toThrow("timeout");
448
- }));
449
- });
450
- describe("formatSearchResults Edge Cases", () => {
451
- it("should handle results with null/undefined values", () => {
452
- const mockData = {
453
- results: [
454
- { title: null, url: "https://example.com", snippet: undefined },
455
- { title: "Valid", url: null, snippet: "snippet", date: undefined },
456
- ],
457
- };
458
- const formatted = formatSearchResults(mockData);
459
- expect(formatted).toContain("null");
460
- expect(formatted).toContain("Valid");
461
- expect(formatted).not.toContain("undefined");
462
- });
463
- it("should handle empty strings in result fields", () => {
464
- const mockData = {
465
- results: [{ title: "", url: "", snippet: "", date: "" }],
466
- };
467
- const formatted = formatSearchResults(mockData);
468
- expect(formatted).toContain("Found 1 search results");
469
- });
470
- it("should handle results with extra unexpected fields", () => {
471
- const mockData = {
472
- results: [
473
- {
474
- title: "Test",
475
- url: "https://example.com",
476
- unexpectedField: "should be ignored",
477
- anotherField: 12345,
478
- },
479
- ],
480
- };
481
- const formatted = formatSearchResults(mockData);
482
- expect(formatted).toContain("Test");
483
- expect(formatted).not.toContain("unexpectedField");
484
- expect(formatted).not.toContain("12345");
485
- });
486
- });
487
- describe("strip_thinking parameter", () => {
488
- it("should strip thinking tokens when true and keep them when false", () => __awaiter(void 0, void 0, void 0, function* () {
489
- const mockResponse = {
490
- choices: [
491
- {
492
- message: {
493
- content: "<think>This is my reasoning process</think>\n\nThe answer is 4.",
494
- },
495
- },
496
- ],
497
- };
498
- // Test with stripThinking = true
499
- global.fetch = vi.fn().mockResolvedValue({
500
- ok: true,
501
- json: () => __awaiter(void 0, void 0, void 0, function* () { return mockResponse; }),
502
- });
503
- const messages = [{ role: "user", content: "What is 2+2?" }];
504
- const resultStripped = yield performChatCompletion(messages, "sonar-reasoning-pro", true);
505
- expect(resultStripped).not.toContain("<think>");
506
- expect(resultStripped).not.toContain("</think>");
507
- expect(resultStripped).not.toContain("This is my reasoning process");
508
- expect(resultStripped).toContain("The answer is 4.");
509
- // Test with stripThinking = false
510
- global.fetch = vi.fn().mockResolvedValue({
511
- ok: true,
512
- json: () => __awaiter(void 0, void 0, void 0, function* () { return mockResponse; }),
513
- });
514
- const resultKept = yield performChatCompletion(messages, "sonar-reasoning-pro", false);
515
- expect(resultKept).toContain("<think>This is my reasoning process</think>");
516
- expect(resultKept).toContain("The answer is 4.");
517
- }));
518
- });
519
- describe("Proxy Support", () => {
520
- const originalEnv = process.env;
521
- beforeEach(() => {
522
- // Reset environment variables
523
- process.env = Object.assign({}, originalEnv);
524
- delete process.env.PERPLEXITY_PROXY;
525
- delete process.env.HTTPS_PROXY;
526
- delete process.env.HTTP_PROXY;
527
- });
528
- afterEach(() => {
529
- process.env = originalEnv;
530
- });
531
- it("should use native fetch when no proxy is configured", () => __awaiter(void 0, void 0, void 0, function* () {
532
- const mockResponse = {
533
- choices: [{ message: { content: "Test response" } }],
534
- };
535
- global.fetch = vi.fn().mockResolvedValue({
536
- ok: true,
537
- json: () => __awaiter(void 0, void 0, void 0, function* () { return mockResponse; }),
538
- });
539
- const messages = [{ role: "user", content: "test" }];
540
- yield performChatCompletion(messages);
541
- // Verify native fetch was called (not undici)
542
- expect(global.fetch).toHaveBeenCalled();
543
- }));
544
- it("should read PERPLEXITY_PROXY environment variable", () => {
545
- process.env.PERPLEXITY_PROXY = "http://proxy.example.com:8080";
546
- expect(process.env.PERPLEXITY_PROXY).toBe("http://proxy.example.com:8080");
547
- });
548
- it("should prioritize PERPLEXITY_PROXY over HTTPS_PROXY", () => {
549
- process.env.PERPLEXITY_PROXY = "http://perplexity-proxy.example.com:8080";
550
- process.env.HTTPS_PROXY = "http://https-proxy.example.com:8080";
551
- // PERPLEXITY_PROXY should take precedence
552
- expect(process.env.PERPLEXITY_PROXY).toBe("http://perplexity-proxy.example.com:8080");
553
- });
554
- it("should fall back to HTTPS_PROXY when PERPLEXITY_PROXY is not set", () => {
555
- delete process.env.PERPLEXITY_PROXY;
556
- process.env.HTTPS_PROXY = "http://https-proxy.example.com:8080";
557
- expect(process.env.HTTPS_PROXY).toBe("http://https-proxy.example.com:8080");
558
- });
559
- it("should fall back to HTTP_PROXY when others are not set", () => {
560
- delete process.env.PERPLEXITY_PROXY;
561
- delete process.env.HTTPS_PROXY;
562
- process.env.HTTP_PROXY = "http://http-proxy.example.com:8080";
563
- expect(process.env.HTTP_PROXY).toBe("http://http-proxy.example.com:8080");
564
- });
565
- });
566
- });
@@ -1,19 +0,0 @@
1
- import { defineConfig } from 'vitest/config';
2
- export default defineConfig({
3
- test: {
4
- exclude: ['**/node_modules/**', '**/dist/**'],
5
- env: {
6
- PERPLEXITY_API_KEY: 'test-api-key',
7
- },
8
- coverage: {
9
- provider: 'v8',
10
- reporter: ['text', 'html', 'lcov'],
11
- exclude: [
12
- '**/node_modules/**',
13
- '**/dist/**',
14
- '**/*.test.ts',
15
- '**/*.config.ts',
16
- ],
17
- },
18
- },
19
- });