import test from 'node:test'; import assert from 'node:assert/strict'; import { request } from 'node:http'; import { createLoader, hasModule } from '../src/loader.mjs'; import { selectModelProvider } from '../src/model-provider-selection.mjs'; import * as fixture from '../model-provider/fixture/index.mjs'; import { createEndpoint, HOST, lifetimeSeconds, serve, TTL_DEFAULT_S, TTL_MAX_S, TTL_MIN_S } from '../model-provider/fixture/endpoint.mjs'; const { FIXTURE_ENTRY, FIXTURE_KEY, FIXTURE_MODEL, FIXTURE_WORD } = fixture; test('the loader accepts the fixture as a model-provider module', async () => { assert.equal(hasModule('model-provider', 'fixture'), true); const log = []; const loader = createLoader({ log: e => log.push(e) }); const r = await loader.load({ 'model-provider': ['fixture'] }); assert.deepEqual(r.refused, []); assert.deepEqual(log, []); assert.deepEqual(loader.snapshot('model-provider').map(m => m.name), ['fixture']); }); test('catalogue offers one static model for pi with no upstream credential', async () => { const c = await fixture.catalogue({ now: () => '2026-11-07T00:00:00.000Z' }); assert.equal(c.status, 'ready'); assert.deepEqual(c.models.map(m => [m.key, m.provider, m.model, m.upstream, m.available, m.harnesses]), [['fixture-deterministic', 'proxy', FIXTURE_MODEL, 'fixture', true, ['pi']]]); }); test('route answers only the fixture entry and only for pi', () => { const route = fixture.route({ selection: FIXTURE_ENTRY, harness: 'pi' }); assert.deepEqual(route, { provider: 'proxy', model: FIXTURE_MODEL, upstream: 'fixture', routeId: 'fixture', endpoint: 'root', api: 'anthropic-messages', piProvider: 'mosaic-fixture', compat: null }); assert.deepEqual(fixture.route({ selection: { ...FIXTURE_ENTRY, model: 'claude-opus' }, harness: 'pi' }), { code: 'model-provider-unavailable' }); assert.deepEqual(fixture.route({ selection: { ...FIXTURE_ENTRY, upstream: 'zai' }, harness: 'pi' }), { code: 'model-provider-unavailable' }); assert.deepEqual(fixture.route({ selection: { ...FIXTURE_ENTRY, module: 'cliproxy' }, harness: 'pi' }), { code: 'model-provider-unavailable' }); assert.deepEqual(fixture.route({ selection: { ...FIXTURE_ENTRY, provider: 'anthropic' }, harness: 'pi' }), { code: 'model-provider-unavailable' }); assert.deepEqual(fixture.route({ selection: FIXTURE_ENTRY, harness: 'claude-code' }), { code: 'model-harness-incompatible' }); }); test('preflight allows the fixture model for pi without a catalogue and refuses anything else', () => { assert.deepEqual(fixture.preflight({ selection: FIXTURE_ENTRY, harness: 'pi', catalogue: { status: 'unavailable' } }), { allow: true }); assert.deepEqual(fixture.preflight({ selection: FIXTURE_ENTRY, harness: 'claude-code' }), { allow: false, code: 'model-harness-incompatible' }); assert.deepEqual(fixture.preflight({ selection: { ...FIXTURE_ENTRY, model: 'other' }, harness: 'pi' }), { allow: false, code: 'model-provider-unavailable' }); }); test('selection picks the fixture module for its entry', () => { const picked = selectModelProvider([{ name: 'fixture', module: fixture }], FIXTURE_ENTRY); assert.equal(picked.name, 'fixture'); assert.equal(selectModelProvider([{ name: 'fixture', module: fixture }], { ...FIXTURE_ENTRY, module: 'cliproxy' }), null); }); function call(baseUrl, { method = 'POST', path = '/v1/messages', key = FIXTURE_KEY, body } = {}) { return new Promise((resolve, reject) => { const req = request(`${baseUrl}${path}`, { method, headers: { 'content-type': 'application/json', ...(key ? { 'x-api-key': key } : {}) } }, res => { let text = ''; res.setEncoding('utf8'); res.on('data', c => { text += c; }); res.on('end', () => resolve({ status: res.statusCode, type: res.headers['content-type'], text })); }); req.on('error', reject); req.end(body === undefined ? undefined : JSON.stringify(body)); }); } test('the endpoint binds loopback, answers the fixed word and refuses a wrong key or model', async t => { const ep = createEndpoint(); const { port, baseUrl } = await ep.listen(0); t.after(() => ep.close()); assert.equal(ep.server.address().address, HOST); assert.equal(baseUrl, `http://127.0.0.1:${port}`); const health = JSON.parse((await call(baseUrl, { method: 'GET', path: '/health' })).text); assert.deepEqual([health.ok, health.upstream, health.model], [true, 'none', FIXTURE_MODEL]); const plain = await call(baseUrl, { body: { model: FIXTURE_MODEL, max_tokens: 8, messages: [{ role: 'user', content: 'hi' }] } }); assert.equal(plain.status, 200); assert.equal(JSON.parse(plain.text).content[0].text, FIXTURE_WORD); const stream = await call(baseUrl, { body: { model: FIXTURE_MODEL, stream: true, messages: [] } }); assert.equal(stream.status, 200); assert.match(stream.type, /^text\/event-stream/); assert.match(stream.text, new RegExp(`"text":"${FIXTURE_WORD}"`)); assert.match(stream.text, /event: message_stop/); assert.equal((await call(baseUrl, { key: 'sk-ant-real-looking', body: { model: FIXTURE_MODEL } })).status, 401); assert.equal((await call(baseUrl, { key: null, body: { model: FIXTURE_MODEL } })).status, 401); assert.equal((await call(baseUrl, { body: { model: 'claude-opus' } })).status, 404); assert.equal((await call(baseUrl, { method: 'GET' })).status, 404); assert.deepEqual(ep.counts, { messages: 2, refused: 4 }); }); // P19 #882: the lifetime an endpoint process takes from MOSAIC_FIXTURE_TTL_S. test('the endpoint lifetime: a default, 0 for no expiry, and bounds a Node timer can hold', () => { for (const raw of [undefined, '', 'soon']) assert.equal(lifetimeSeconds(raw), TTL_DEFAULT_S, String(raw)); assert.equal(TTL_DEFAULT_S, 14400); assert.equal(lifetimeSeconds('0'), 0); assert.equal(lifetimeSeconds('120'), 120); for (const raw of ['5', '-3']) assert.equal(lifetimeSeconds(raw), TTL_MIN_S, raw); // Past 2^31-1 ms a timer fires after 1 ms, so a longer lifetime is held to the longest one. for (const raw of [String(TTL_MAX_S + 1), '1e12']) assert.equal(lifetimeSeconds(raw), TTL_MAX_S, raw); assert.ok(TTL_MAX_S * 1000 <= 2 ** 31 - 1); }); test('serve expires the endpoint when its lifetime ends, and never with a lifetime of 0', async t => { const open = await serve({ ttlSeconds: 0, expire: () => assert.fail('a lifetime of 0 expired') }); t.after(() => open.endpoint.close()); assert.equal(open.timer, null); const health = JSON.parse((await call(open.baseUrl, { method: 'GET', path: '/health' })).text); assert.deepEqual([health.ok, health.ttlSeconds, health.expiresAt], [true, 0, null]); t.mock.timers.enable({ apis: ['setTimeout'] }); let expired = 0; const before = Date.now(); const timed = await serve({ ttlSeconds: 120, expire: () => { expired++; } }); t.after(() => timed.endpoint.close()); const at = Date.parse(timed.expiresAt) - before; assert.ok(at >= 120000 && at < 130000, timed.expiresAt); t.mock.timers.tick(119999); assert.equal(expired, 0); t.mock.timers.tick(1); assert.equal(expired, 1); t.mock.timers.tick(TTL_MAX_S * 1000); assert.equal(expired, 1, 'a lifetime of 0 set no timer'); });