Files
stack/packages/plugins/tests/model-provider-catalogue.test.mjs

71 lines
4.7 KiB
JavaScript

import test from 'node:test';
import assert from 'node:assert/strict';
import { catalogue, preflight } from '../model-provider/cliproxy/index.mjs';
const ZAI = 'https://api.z.ai/api/anthropic';
const deps = () => ({
listAccounts: async () => ({ files: [
{ id: 'credential-1', name: 'credential-1', provider: 'claude', status: 'active' },
{ id: 'credential-2', name: 'credential-2', provider: 'codex', status: 'disabled' },
] }),
listModels: async name => ({ models: name === 'credential-1' ? [{ id: 'fixture-chat', display_name: 'Fixture', owned_by: 'anthropic', type: 'claude' }] : [] }),
listGroups: async () => [{ 'base-url': ZAI, keys: [{ auth_index: 'fixture-key' }], models: [{ name: 'fixture-model', alias: 'fixture-alias' }] }],
now: () => '2026-11-06T00:00:00.000Z',
});
test('catalogue attributes configured accounts, uses aliases, and enforces harness pairs', async () => {
const result = await catalogue(deps());
assert.equal(result.status, 'ready');
const zai = result.models.find(x => x.upstream === 'zai');
assert.deepEqual([zai.key, zai.model, zai.available, zai.harnesses], ['zai-fixture-alias', 'fixture-alias', true, ['pi']]);
const claude = result.models.find(x => x.upstream === 'claude');
assert.deepEqual(claude.harnesses, ['claude-code', 'pi']);
assert.deepEqual(preflight({ selection: zai, harness: 'claude-code', catalogue: result }), { allow: false, code: 'model-harness-incompatible' });
assert.deepEqual(preflight({ selection: zai, harness: 'pi', catalogue: result }), { allow: true });
assert.ok(!JSON.stringify(result).includes('credential-1'));
});
test('an empty group offers no models; unknown groups offer pi only and are unverified', async () => {
const d = deps();
d.listAccounts = async () => ({ files: [] });
d.listGroups = async () => [
{ 'base-url': ZAI, keys: [{ auth_index: 'a' }] },
{ 'base-url': 'https://fixture.invalid', keys: [{ auth_index: 'b' }], models: [{ name: 'fixture-other' }] },
];
const c = await catalogue(d);
assert.equal(c.models.length, 1);
assert.deepEqual([c.models[0].upstream, c.models[0].harnesses, c.models[0].reason], ['other', ['pi'], 'unverified']);
assert.ok(c.notices.includes('z.ai account has no models configured. Add them on Model proxy.'));
});
test('a failed catalogue never authorizes a saved route', async () => {
const d = deps(); d.listGroups = async () => { throw new Error('fixture private error'); };
const c = await catalogue(d);
assert.equal(c.status, 'unavailable');
assert.deepEqual(preflight({ selection: { upstream: 'zai', model: 'fixture-alias' }, harness: 'pi', catalogue: c }), { allow: false, code: 'model-catalogue-unavailable' });
});
test('module declares only supported transports and legacy routes without widening compatibility', async () => {
const { route } = await import('../model-provider/cliproxy/index.mjs');
assert.deepEqual(route({ selection: { upstream: 'codex', model: 'fixture-codex' }, harness: 'pi' }), {
provider: 'codex', model: 'fixture-codex', upstream: 'codex', routeId: 'codex', endpoint: 'v1', api: 'openai-responses', piProvider: 'mosaic-proxy-codex', compat: null,
});
assert.equal(route({ selection: { upstream: 'zai', model: 'fixture-zai' }, harness: 'claude-code' }).code, 'model-harness-incompatible');
assert.equal(route({ selection: { provider: 'proxy', route: 'unknown', model: 'fixture' }, harness: 'pi' }).code, 'proxy-route-unknown');
assert.equal(route({ selection: { provider: 'proxy', model: 'fixture' }, harness: 'pi' }).code, 'proxy-route-missing');
});
test('different model IDs that collapse to one readable slug refuse by name', async () => {
const d=deps();d.listAccounts=async()=>({files:[]});d.listGroups=async()=>[{'base-url':ZAI,keys:[{}],models:[{name:'fixture.a'},{name:'fixture-a'}]}];
const result=await catalogue(d);assert.equal(result.status,'unavailable');assert.equal(result.reason,'model-key-collision');
});
test('a second fixture module resolves independently and ambiguous legacy mappings refuse', async () => {
const {selectModelProvider}=await import('../src/model-provider-selection.mjs');
const first={name:'first-fixture',module:{route:({selection})=>selection.provider==='fixture-one'?{provider:selection.provider,model:selection.model,upstream:'one'}:{code:'unsupported'}}};
const second={name:'second-fixture',module:{route:({selection})=>selection.provider==='fixture-two'?{provider:selection.provider,model:selection.model,upstream:'two'}:{code:'unsupported'}}};
const entry={provider:'fixture-two',model:'fixture-model'};
assert.equal(selectModelProvider([first,second],entry)?.name,'second-fixture');
assert.equal(selectModelProvider([first,second],{...entry,module:'first-fixture'}),null);
assert.equal(selectModelProvider([first,second,{...second,name:'third-fixture'}],entry),null);
});