import assert from 'node:assert/strict' import { build } from 'esbuild' import { mkdtemp, mkdir, writeFile, rm } from 'node:fs/promises' import { tmpdir } from 'node:os' import { join } from 'node:path' import { pathToFileURL } from 'node:url' import { resolveSelectedModel } from '../src/shared/model-selection' import type { CustomModelProfile, CustomModelInput } from '../src/shared/models' const temp = await mkdtemp(join(tmpdir(), 'ycode-model-alignment-')) const state = { path: join(temp, 'fresh') } ;(globalThis as any).__modelAlignment = state let count = 0 try { const outfile = join(temp, 'models.mjs') await build({ entryPoints: ['src/main/models.ts'], outfile, bundle: true, platform: 'node', format: 'esm', logLevel: 'silent', plugins: [{ name: 'offline-host', setup(b) { b.onResolve({filter:/^electron$/},()=>({path:'host',namespace:'fixture'})) b.onLoad({filter:/.*/,namespace:'fixture'},()=>({contents:`export const app={getPath:()=>globalThis.__modelAlignment.path}; export const safeStorage={isEncryptionAvailable:()=>false};`,loader:'js'})) b.onResolve({filter:/^\.\/model-connection$/},()=>({path:'connection',namespace:'offline'})) b.onResolve({filter:/^\.\/model-metadata$/},()=>({path:'metadata',namespace:'offline'})) b.onLoad({filter:/.*/,namespace:'offline'},args=>({contents:args.path==='metadata' ? `export const modelMetadata=async()=>null;` : `export const cachedConnection=()=>undefined,cachedGeneration=()=>undefined,discoverModelConnection=async()=>undefined,modelFetch=()=>{throw Error('external network forbidden in regression')},readModelJson=()=>{},rememberGeneration=()=>{};`,loader:'js'})) }}] }) const reload=()=>import(`${pathToFileURL(outfile).href}?${++count}`) as Promise let models=await reload() assert.deepEqual(await models.listModels(),{models:[],selectedModelId:null},'fresh install must not synthesize deepseek') const input=(id:string):CustomModelInput=>({id,name:id,model:id,baseUrl:'https://offline.invalid',providerId:'custom',authMode:'none',protocol:'anthropic'}) assert.equal((await models.saveModel(input('one'))).selectedModelId,'one') assert.equal((await models.saveModel(input('two'))).selectedModelId,'two','new model becomes default') assert.equal((await models.saveModel({...input('one'),previousId:'one'})).selectedModelId,'two','editing another model preserves selection') const before=(await models.listModels()).models assert.equal(resolveSelectedModel(before,'stale','two')?.id,'two') assert.equal(resolveSelectedModel(before,'one','two')?.id,'one') assert.equal(resolveSelectedModel(before,'stale','stale')?.id,'one') assert.equal(resolveSelectedModel([],'one','two'),null) assert.equal((await models.deleteModel('two')).selectedModelId,'one') await models.deleteModel('one'); models=await reload() assert.deepEqual(await models.listModels(),{models:[],selectedModelId:null}) assert.equal((await models.saveModel(input('three'))).selectedModelId,'three') state.path=join(temp,'legacy'); await mkdir(state.path) await writeFile(join(state.path,'config.json'),JSON.stringify({model:'user-model',baseUrl:'https://configured.invalid',temperature:0.2,maxToolRounds:4})) models=await reload(); assert.equal((await models.listModels()).models[0]?.model,'user-model','explicit legacy config preserved') state.path=join(temp,'preferences-only');await mkdir(state.path) await writeFile(join(state.path,'config.json'),JSON.stringify({preventSleep:true})) models=await reload();assert.deepEqual(await models.listModels(),{models:[],selectedModelId:null},'preferences are not a model') state.path=join(temp,'serialized-defaults');await mkdir(state.path) await writeFile(join(state.path,'config.json'),JSON.stringify({model:'deepseek-chat',baseUrl:'https://api.deepseek.com/v1',preventSleep:true})) models=await reload();assert.deepEqual(await models.listModels(),{models:[],selectedModelId:null},'old preference writes of defaults are not real configuration') console.log('PASS model alignment: fresh/legacy migration, new/edit/default/delete/reload, valid selection (offline host fixtures)') } finally { delete (globalThis as any).__modelAlignment; await rm(temp,{recursive:true,force:true}) }