Spaces:
Runtime error
Runtime error
File size: 4,022 Bytes
077865a | 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 | import { describe, it, expect, beforeAll, beforeEach, afterEach, vi } from 'vitest';
import type { Express } from 'express';
import { createApp } from '../../app.js';
import { initDb, getDb, getUnifiedApiKey } from '../../db/index.js';
import { mintDashboardToken, isGatedApiPath } from '../helpers/auth.js';
let dashToken = '';
async function request(app: Express, method: string, path: string, body?: any, headers: Record<string, string> = {}) {
const server = app.listen(0);
const addr = server.address() as any;
const url = `http://127.0.0.1:${addr.port}${path}`;
const res = await fetch(url, {
method,
headers: { ...(body ? { 'Content-Type': 'application/json' } : {}), ...(isGatedApiPath(path) && !('Authorization' in headers) ? { Authorization: `Bearer ${dashToken}` } : {}), ...headers },
body: body ? JSON.stringify(body) : undefined,
});
const data = await res.text();
server.close();
let json: any = null;
try { json = JSON.parse(data); } catch {}
return { status: res.status, body: json };
}
function authHeaders() {
return { Authorization: `Bearer ${getUnifiedApiKey()}` };
}
// requested_model logging: a pinned request records the model id the client
// named; an auto request records NULL. This is what lets analytics split
// pinned vs auto traffic and surface failover overrides.
describe('requested_model analytics logging', () => {
let app: Express;
let groqModelId: string;
beforeAll(() => {
process.env.ENCRYPTION_KEY = '0'.repeat(64);
initDb(':memory:');
app = createApp();
dashToken = mintDashboardToken();
// Any enabled groq model from the seeded catalog will do as the pin target.
groqModelId = (getDb().prepare(`
SELECT m.model_id FROM models m
JOIN fallback_config fc ON fc.model_db_id = m.id
WHERE m.platform = 'groq' AND m.enabled = 1
ORDER BY fc.priority LIMIT 1
`).get() as { model_id: string }).model_id;
});
beforeEach(async () => {
const db = getDb();
db.prepare('DELETE FROM api_keys').run();
db.prepare('DELETE FROM requests').run();
const addKey = await request(app, 'POST', '/api/keys', {
platform: 'groq',
key: 'gsk_pinned_model_test',
label: 'pinned-model',
});
expect(addKey.status).toBe(201);
const origFetch = global.fetch;
vi.spyOn(global, 'fetch').mockImplementation(async (url, init) => {
const urlStr = typeof url === 'string' ? url : url.toString();
if (urlStr.includes('api.groq.com')) {
return {
ok: true,
json: () => Promise.resolve({
id: 'chatcmpl-pin', object: 'chat.completion', created: 1, model: groqModelId,
choices: [{ index: 0, message: { role: 'assistant', content: 'hi' }, finish_reason: 'stop' }],
usage: { prompt_tokens: 2, completion_tokens: 1, total_tokens: 3 },
}),
} as any;
}
return origFetch(url, init);
});
});
afterEach(() => {
vi.restoreAllMocks();
});
it('logs the pinned model id when the client names a model', async () => {
const { status } = await request(app, 'POST', '/v1/chat/completions', {
model: groqModelId,
messages: [{ role: 'user', content: 'hi' }],
}, authHeaders());
expect(status).toBe(200);
const row = getDb().prepare('SELECT model_id, requested_model FROM requests ORDER BY id DESC LIMIT 1').get() as any;
expect(row.requested_model).toBe(groqModelId);
expect(row.model_id).toBe(groqModelId); // pin honored
});
it.each([['auto'], [undefined]])('logs NULL requested_model for auto routing (model: %s)', async (model) => {
const { status } = await request(app, 'POST', '/v1/chat/completions', {
...(model ? { model } : {}),
messages: [{ role: 'user', content: 'hi' }],
}, authHeaders());
expect(status).toBe(200);
const row = getDb().prepare('SELECT requested_model FROM requests ORDER BY id DESC LIMIT 1').get() as any;
expect(row.requested_model).toBeNull();
});
});
|