File size: 4,435 Bytes
dcedb25 | 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 | import { describe, expect, it } from 'vitest';
import { parseKeysFromFile, parseModelList } from '../../lib/key-parser.js';
// #382: a paste can declare the models a custom endpoint serves next to its
// key, either as CUSTOM_<n>_MODELS beside the paired CUSTOM_<n>_* lines or as
// <PREFIX>_CUSTOM_MODELS beside <PREFIX>_BASE_URL + <PREFIX>_API_KEY/_KEY.
describe('parseModelList (#382)', () => {
it('splits on commas and strips trailing capability suffixes', () => {
expect(parseModelList('llama3, qwen3-TOOLS,pixtral-VISION')).toEqual([
{ id: 'llama3' },
{ id: 'qwen3', supportsTools: true },
{ id: 'pixtral', supportsVision: true },
]);
});
it('accepts both suffixes in either order', () => {
expect(parseModelList('m1-TOOLS-VISION,m2-VISION-TOOLS')).toEqual([
{ id: 'm1', supportsTools: true, supportsVision: true },
{ id: 'm2', supportsTools: true, supportsVision: true },
]);
});
it('never touches a TOOLS/VISION that is not trailing', () => {
expect(parseModelList('qwen-TOOLS-preview,llama-VISION-8b')).toEqual([
{ id: 'qwen-TOOLS-preview' },
{ id: 'llama-VISION-8b' },
]);
});
it('treats lowercase suffixes as part of the model id', () => {
expect(parseModelList('devstral-tools,moondream-vision')).toEqual([
{ id: 'devstral-tools' },
{ id: 'moondream-vision' },
]);
});
it('drops blanks and dedupes ids after stripping', () => {
expect(parseModelList('a, ,a-TOOLS,')).toEqual([{ id: 'a' }]);
});
});
describe('model lists in .env pastes (#382)', () => {
it('attaches CUSTOM_<n>_MODELS to its own endpoint only', () => {
const env = [
'CUSTOM_1_BASE_URL=http://relay-a.example/v1',
'CUSTOM_1_KEY=sk-a',
'CUSTOM_1_MODELS=llama3,qwen3-TOOLS',
'CUSTOM_2_BASE_URL=http://relay-b.example/v1',
'CUSTOM_2_KEY=sk-b',
].join('\n');
const result = parseKeysFromFile(env, 'keys.env');
expect(result.keys).toEqual([
{
rawKey: 'CUSTOM_1_KEY=sk-a',
prefix: 'CUSTOM_',
platform: 'custom',
baseUrl: 'http://relay-a.example/v1',
models: [{ id: 'llama3' }, { id: 'qwen3', supportsTools: true }],
},
{
rawKey: 'CUSTOM_2_KEY=sk-b',
prefix: 'CUSTOM_',
platform: 'custom',
baseUrl: 'http://relay-b.example/v1',
},
]);
expect(result.skipped).toEqual([]);
});
it('folds <PREFIX>_BASE_URL + <PREFIX>_API_KEY + <PREFIX>_CUSTOM_MODELS into a custom endpoint', () => {
const env = [
'MYRELAY_BASE_URL=http://myrelay.example/v1',
'MYRELAY_API_KEY=sk-relay',
'MYRELAY_CUSTOM_MODELS=deepseek-v3,text-embedding-qwen',
].join('\n');
const result = parseKeysFromFile(env, 'keys.env');
expect(result.keys).toEqual([
expect.objectContaining({
rawKey: 'MYRELAY_API_KEY=sk-relay',
platform: 'custom',
baseUrl: 'http://myrelay.example/v1',
models: [{ id: 'deepseek-v3' }, { id: 'text-embedding-qwen' }],
}),
]);
expect(result.skipped).toEqual([]);
});
it('accepts <PREFIX>_KEY as the key spelling', () => {
const env = [
'MYRELAY_BASE_URL=http://myrelay.example/v1',
'MYRELAY_KEY=sk-relay',
'MYRELAY_CUSTOM_MODELS=deepseek-v3',
].join('\n');
const result = parseKeysFromFile(env, 'keys.env');
expect(result.keys).toEqual([
expect.objectContaining({
platform: 'custom',
baseUrl: 'http://myrelay.example/v1',
models: [{ id: 'deepseek-v3' }],
}),
]);
});
it('leaves a <PREFIX>_BASE_URL pair alone when no models line makes it endpoint-defining', () => {
const env = [
'MYRELAY_BASE_URL=http://myrelay.example/v1',
'MYRELAY_API_KEY=sk-relay',
].join('\n');
const result = parseKeysFromFile(env, 'keys.env');
expect(result.keys.every(k => k.platform !== 'custom')).toBe(true);
});
it('consumes and reports a models line with nothing to attach to', () => {
const env = [
'CUSTOM_1_MODELS=llama3',
'ORPHAN_CUSTOM_MODELS=qwen',
].join('\n');
const result = parseKeysFromFile(env, 'keys.env');
// The list values must never fall through and be mistaken for key material.
expect(result.keys).toEqual([]);
expect(result.skipped).toEqual([
expect.stringContaining('CUSTOM_1_MODELS'),
expect.stringContaining('ORPHAN_CUSTOM_MODELS'),
]);
});
});
|