import { strict as assert } from 'node:assert' import { test } from 'node:test' import { cleanVariant, createExpander, parseVariants } from '../lib/expand.js' /** A stub endpoint that answers with a canned model response. */ function stubFetch(response, options = {}) { const { status = 200, hang = false } = options const calls = [] const impl = async (url, init) => { calls.push({ url, body: JSON.parse(init.body) }) if (hang) { return new Promise((_resolve, reject) => { init.signal.addEventListener('abort', () => reject(init.signal.reason), { once: true }) }) } return { ok: status === 200, status, json: async () => ({ response }) } } impl.calls = calls return impl } const MODEL = { apiBase: 'http://stub:11434', model: 'small-model', timeoutMs: 2_000, count: 4 } test('cleanVariant strips what models add around a list', () => { assert.equal(cleanVariant('1. occupancy state machine'), 'occupancy state machine') assert.equal(cleanVariant('- presence detection'), 'presence detection') assert.equal(cleanVariant('* room occupied handler'), 'room occupied handler') assert.equal(cleanVariant('"roomOccupied"'), 'roomOccupied') assert.equal(cleanVariant('occupancy check — this finds the handler'), 'occupancy check') assert.equal(cleanVariant(' '), undefined) assert.equal(cleanVariant('x'.repeat(300)), undefined, 'a paragraph is not a search phrase') assert.equal(cleanVariant('Here are some phrasings:'), undefined) }) test('model commentary is never mistaken for a phrasing', () => { // A line like this is not a weak variant, it is not a variant at all: // embedding it would search the codebase for the model's apology. for (const line of ['I cannot help with that.', "I can't do that.", 'Sorry, I need more context.', 'Unfortunately I do not have enough information.', 'Here are some phrasings:']) { assert.equal(cleanVariant(line), undefined, `accepted ${line}`) } // But a question-shaped phrasing is entirely legitimate, and must survive. assert.equal(cleanVariant('how does a room decide it is occupied'), 'how does a room decide it is occupied') assert.equal(cleanVariant('where is the occupancy handler'), 'where is the occupancy handler') }) test('parseVariants dedupes, drops the original, and caps the count', () => { const body = ['occupancy state machine', 'room occupied detection', 'OCCUPANCY STATE MACHINE', 'presence tracking', 'extra one', 'extra two'].join('\n') const variants = parseVariants(body, 'how does a room decide it is occupied', 3) assert.deepEqual(variants, ['occupancy state machine', 'room occupied detection', 'presence tracking']) }) test('expansion returns the original first, then the variants', async () => { const fetchImpl = stubFetch('occupancy state machine\nroom occupied handler') const variants = await createExpander({ ...MODEL, fetchImpl }).expand('how does a room decide it is occupied') assert.equal(variants[0], 'how does a room decide it is occupied') assert.deepEqual(variants.slice(1), ['occupancy state machine', 'room occupied handler']) // The query must actually reach the model. assert.match(fetchImpl.calls[0].body.prompt, /how does a room decide it is occupied/) assert.equal(fetchImpl.calls[0].body.stream, false) }) test('an unreachable endpoint degrades to the original query, never an error', async () => { const fetchImpl = async () => { throw new Error('ECONNREFUSED') } const variants = await createExpander({ ...MODEL, fetchImpl }).expand('some query') assert.deepEqual(variants, ['some query']) }) test('a WEDGED endpoint degrades to the original query, and does not hang', async () => { // The failure actually observed on the box: the socket opens and nothing ever // comes back. Expansion must give up on its own deadline rather than pass the // wait on to a search that has nothing to do with the local model. const fetchImpl = stubFetch('', { hang: true }) const started = Date.now() const variants = await createExpander({ ...MODEL, fetchImpl, timeoutMs: 120 }).expand('some query') assert.deepEqual(variants, ['some query']) assert.ok(Date.now() - started < 3_000, 'the internal deadline must bound the wait') }) test('a non-200 response degrades rather than throwing', async () => { const variants = await createExpander({ ...MODEL, fetchImpl: stubFetch('', { status: 500 }) }).expand('q') assert.deepEqual(variants, ['q']) }) test('a response with nothing usable leaves just the original', async () => { const variants = await createExpander({ ...MODEL, fetchImpl: stubFetch('I cannot help with that.') }).expand('q') assert.deepEqual(variants, ['q']) }) test('a non-finite timeout is clamped, not turned into a silent fallback', async () => { // Without the clamp, AbortSignal.timeout(NaN) throws and the catch below // reports it as "the model had nothing to say" — a misconfiguration wearing // the disguise of a slow model. const fetchImpl = stubFetch('occupancy handler') const variants = await createExpander({ ...MODEL, fetchImpl, timeoutMs: Number.NaN }).expand('q') assert.deepEqual(variants, ['q', 'occupancy handler']) }) test('a malformed payload degrades rather than throwing', async () => { const fetchImpl = async () => ({ ok: true, status: 200, json: async () => ({}) }) assert.deepEqual(await createExpander({ ...MODEL, fetchImpl }).expand('q'), ['q']) }) test('an empty or oversized query is not sent at all', async () => { const fetchImpl = stubFetch('variant one') const expander = createExpander({ ...MODEL, fetchImpl }) assert.deepEqual(await expander.expand(' '), ['']) assert.deepEqual(await expander.expand('x'.repeat(600)), ['x'.repeat(600)]) assert.equal(fetchImpl.calls.length, 0, 'nothing worth asking about') }) test('caller cancellation stops expansion and returns the original', async () => { const controller = new AbortController() controller.abort() const fetchImpl = stubFetch('variant one') assert.deepEqual(await createExpander({ ...MODEL, fetchImpl }).expand('q', controller.signal), ['q']) assert.equal(fetchImpl.calls.length, 0) })