Changeset 0.22.7 (#149)
This commit is contained in:
@@ -116,71 +116,61 @@ describe('GET /models/enabled response contract', () => {
|
||||
});
|
||||
});
|
||||
|
||||
// ── /models/enabled with preset response ─────
|
||||
// ── /models/enabled with persona response ────
|
||||
|
||||
describe('GET /models/enabled preset contract', () => {
|
||||
// ACTUAL backend UserModel for a persona includes both canonical and alias fields.
|
||||
const presetModel = {
|
||||
id: 'preset-uuid-123',
|
||||
describe('GET /models/enabled persona contract', () => {
|
||||
// ACTUAL backend UserModel for a persona (v0.22.8+: unified naming, no aliases).
|
||||
const personaModel = {
|
||||
id: 'persona-uuid-123',
|
||||
model_id: 'gpt-4o',
|
||||
display_name: 'Code Helper',
|
||||
source: 'persona',
|
||||
// Backend canonical fields
|
||||
// Backend canonical fields (v0.22.8: all use persona_ prefix)
|
||||
provider_config_id: 'cfg1',
|
||||
persona_id: 'preset-uuid-123',
|
||||
scope: 'global',
|
||||
avatar: null,
|
||||
// Frontend alias fields (populated by resolver)
|
||||
is_preset: true,
|
||||
preset_id: 'preset-uuid-123',
|
||||
preset_scope: 'global',
|
||||
preset_avatar: null,
|
||||
is_persona: true,
|
||||
persona_id: 'persona-uuid-123',
|
||||
persona_scope: 'global',
|
||||
persona_avatar: null,
|
||||
persona_team_name: null,
|
||||
config_id: 'cfg1',
|
||||
provider_name: 'OpenAI',
|
||||
capabilities: { streaming: true },
|
||||
};
|
||||
|
||||
it('preset has is_preset = true', () => {
|
||||
assert.equal(presetModel.is_preset, true);
|
||||
it('persona has is_persona = true', () => {
|
||||
assert.equal(personaModel.is_persona, true);
|
||||
});
|
||||
|
||||
it('preset has preset_id matching persona_id', () => {
|
||||
assert.ok(presetModel.preset_id);
|
||||
assert.equal(presetModel.preset_id, presetModel.persona_id,
|
||||
'preset_id alias must match persona_id');
|
||||
it('persona has persona_id', () => {
|
||||
assert.ok(personaModel.persona_id);
|
||||
});
|
||||
|
||||
it('preset has preset_scope matching scope', () => {
|
||||
assert.ok(['global', 'team', 'personal'].includes(presetModel.preset_scope));
|
||||
assert.equal(presetModel.preset_scope, presetModel.scope,
|
||||
'preset_scope alias must match scope');
|
||||
it('persona has persona_scope', () => {
|
||||
assert.ok(['global', 'team', 'personal'].includes(personaModel.persona_scope));
|
||||
});
|
||||
|
||||
it('preset ID uses preset_id not composite', () => {
|
||||
// Frontend: id = isPreset ? (m.preset_id || m.persona_id || m.id) : composite
|
||||
const id = presetModel.is_preset
|
||||
? (presetModel.preset_id || presetModel.persona_id || presetModel.id)
|
||||
: `${presetModel.config_id || presetModel.provider_config_id}:${presetModel.model_id}`;
|
||||
assert.equal(id, 'preset-uuid-123');
|
||||
it('persona ID uses persona_id not composite', () => {
|
||||
// Frontend: id = isPersona ? (m.persona_id || m.id) : composite
|
||||
const id = personaModel.is_persona
|
||||
? (personaModel.persona_id || personaModel.id)
|
||||
: `${personaModel.config_id || personaModel.provider_config_id}:${personaModel.model_id}`;
|
||||
assert.equal(id, 'persona-uuid-123');
|
||||
});
|
||||
|
||||
it('frontend works with ONLY canonical fields (no aliases)', () => {
|
||||
// If someone breaks the alias population in resolver.go,
|
||||
// the frontend fallback chain must still produce correct IDs.
|
||||
// v0.22.8: no more dual-key aliases — backend sends is_persona directly.
|
||||
const rawBackend = {
|
||||
id: 'preset-uuid-123',
|
||||
id: 'persona-uuid-123',
|
||||
model_id: 'gpt-4o',
|
||||
source: 'persona',
|
||||
provider_config_id: 'cfg1',
|
||||
persona_id: 'preset-uuid-123',
|
||||
scope: 'global',
|
||||
// NO is_preset, NO preset_id, NO config_id aliases
|
||||
is_persona: true,
|
||||
persona_id: 'persona-uuid-123',
|
||||
persona_scope: 'global',
|
||||
};
|
||||
// is_preset would be undefined/falsy → treated as catalog model
|
||||
// This test documents the FAILURE MODE if aliases break
|
||||
const isPreset = !!rawBackend.is_preset; // false!
|
||||
assert.equal(isPreset, false,
|
||||
'Without is_preset alias, persona is misidentified as catalog model');
|
||||
const isPersona = !!rawBackend.is_persona;
|
||||
assert.equal(isPersona, true,
|
||||
'is_persona field must be present for correct identification');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -441,8 +431,8 @@ describe('Response shape consistency', () => {
|
||||
assert.ok('models' in shape, 'admin/models must use "models" key');
|
||||
});
|
||||
|
||||
it('presets uses {presets:[]}', () => {
|
||||
const shape = { presets: [] };
|
||||
assert.ok('presets' in shape);
|
||||
it('personas uses {personas:[]}', () => {
|
||||
const shape = { personas: [] };
|
||||
assert.ok('personas' in shape);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -116,22 +116,24 @@ function loadSource(sandbox, filename) {
|
||||
*/
|
||||
function loadAppModules(overrides = {}) {
|
||||
const sandbox = createBrowserContext(overrides);
|
||||
loadSource(sandbox, 'app-state.js');
|
||||
loadSource(sandbox, 'api.js');
|
||||
loadSource(sandbox, 'app.js');
|
||||
return { API: sandbox.API, App: sandbox.App, sandbox };
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the model-processing transform from fetchModels.
|
||||
* Extract the model-processing transform from fetchModels (app-state.js).
|
||||
* This is the core mapping logic that converts API response → App.models.
|
||||
* v0.22.8: unified persona naming — no more preset aliases.
|
||||
*/
|
||||
function processModelsResponse(data, hiddenModels = new Set()) {
|
||||
return (data.models || []).map(m => {
|
||||
const isPreset = !!m.is_preset;
|
||||
const isPersona = !!m.is_persona;
|
||||
const baseModelId = m.model_id || m.id;
|
||||
const cfgId = m.config_id || m.provider_config_id;
|
||||
const id = isPreset
|
||||
? (m.preset_id || m.persona_id || m.id)
|
||||
const id = isPersona
|
||||
? (m.persona_id || m.id)
|
||||
: (cfgId ? `${cfgId}:${baseModelId}` : baseModelId);
|
||||
return {
|
||||
id,
|
||||
@@ -139,14 +141,14 @@ function processModelsResponse(data, hiddenModels = new Set()) {
|
||||
name: m.display_name || baseModelId,
|
||||
provider: m.provider_name || m.provider || '',
|
||||
configId: cfgId || null,
|
||||
isPreset,
|
||||
presetId: m.preset_id || m.persona_id || null,
|
||||
presetScope: m.preset_scope || (isPreset ? m.scope : null) || null,
|
||||
presetAvatar: m.preset_avatar || (isPreset ? m.avatar : null) || null,
|
||||
presetTeamName: m.preset_team_name || (isPreset ? m.team_name : null) || null,
|
||||
source: m.source || (isPreset ? 'preset' : 'global'),
|
||||
teamName: m.preset_team_name || (isPreset ? m.team_name : null) || null,
|
||||
hidden: !isPreset && hiddenModels.has(baseModelId),
|
||||
isPersona,
|
||||
personaId: m.persona_id || null,
|
||||
personaScope: m.persona_scope || (isPersona ? m.scope : null) || null,
|
||||
personaAvatar: m.persona_avatar || (isPersona ? m.avatar : null) || null,
|
||||
personaTeamName: m.persona_team_name || (isPersona ? m.team_name : null) || null,
|
||||
source: m.source || (isPersona ? 'persona' : 'global'),
|
||||
teamName: m.persona_team_name || null,
|
||||
hidden: !isPersona && hiddenModels.has(baseModelId),
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
@@ -75,9 +75,9 @@ describe('processModelsResponse — catalog models', () => {
|
||||
assert.equal(models[0].name, 'claude-3-opus');
|
||||
});
|
||||
|
||||
it('marks catalog models as NOT presets', () => {
|
||||
it('marks catalog models as NOT personas', () => {
|
||||
const models = processModelsResponse(apiResponse);
|
||||
assert.equal(models[0].isPreset, false);
|
||||
assert.equal(models[0].isPersona, false);
|
||||
});
|
||||
|
||||
it('preserves configId from config_id || provider_config_id', () => {
|
||||
@@ -93,7 +93,7 @@ describe('processModelsResponse — catalog models', () => {
|
||||
|
||||
// ── Preset transform ─────────────────────────
|
||||
|
||||
describe('processModelsResponse — presets', () => {
|
||||
describe('processModelsResponse — personas', () => {
|
||||
const apiResponse = {
|
||||
models: [
|
||||
{
|
||||
@@ -107,47 +107,47 @@ describe('processModelsResponse — presets', () => {
|
||||
avatar: '/avatars/code.png',
|
||||
source: 'persona',
|
||||
// Frontend alias fields
|
||||
is_preset: true,
|
||||
preset_id: 'preset-uuid',
|
||||
preset_scope: 'global',
|
||||
preset_avatar: '/avatars/code.png',
|
||||
preset_team_name: null,
|
||||
is_persona: true,
|
||||
persona_id: 'preset-uuid',
|
||||
persona_scope: 'global',
|
||||
persona_avatar: '/avatars/code.png',
|
||||
persona_team_name: null,
|
||||
config_id: 'cfg-uuid',
|
||||
provider_name: 'OpenAI',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
it('uses preset_id as ID (not composite)', () => {
|
||||
it('uses persona_id as ID (not composite)', () => {
|
||||
const models = processModelsResponse(apiResponse);
|
||||
assert.equal(models[0].id, 'preset-uuid',
|
||||
'preset ID must use preset_id, not config_id:model_id');
|
||||
'persona ID must use persona_id, not config_id:model_id');
|
||||
});
|
||||
|
||||
it('falls back to persona_id when preset_id is missing', () => {
|
||||
it('falls back to persona_id when not present', () => {
|
||||
const resp = {
|
||||
models: [{
|
||||
id: 'p-uuid', model_id: 'gpt-4o',
|
||||
is_preset: true, persona_id: 'p-uuid',
|
||||
is_persona: true, persona_id: 'p-uuid',
|
||||
// NO preset_id — simulates broken alias
|
||||
source: 'persona',
|
||||
}],
|
||||
};
|
||||
const models = processModelsResponse(resp);
|
||||
assert.equal(models[0].id, 'p-uuid',
|
||||
'must fall back to persona_id when preset_id is missing');
|
||||
'must fall back to persona_id');
|
||||
});
|
||||
|
||||
it('marks as preset', () => {
|
||||
it('marks as persona', () => {
|
||||
const models = processModelsResponse(apiResponse);
|
||||
assert.equal(models[0].isPreset, true);
|
||||
assert.equal(models[0].isPersona, true);
|
||||
});
|
||||
|
||||
it('preserves preset metadata', () => {
|
||||
it('preserves persona metadata', () => {
|
||||
const models = processModelsResponse(apiResponse);
|
||||
assert.equal(models[0].presetScope, 'global');
|
||||
assert.equal(models[0].presetAvatar, '/avatars/code.png');
|
||||
assert.equal(models[0].presetId, 'preset-uuid');
|
||||
assert.equal(models[0].personaScope, 'global');
|
||||
assert.equal(models[0].personaAvatar, '/avatars/code.png');
|
||||
assert.equal(models[0].personaId, 'preset-uuid');
|
||||
});
|
||||
|
||||
it('baseModelId is the underlying model', () => {
|
||||
@@ -215,16 +215,16 @@ describe('processModelsResponse — hidden models', () => {
|
||||
assert.equal(models[1].hidden, false, 'claude-3 should NOT be hidden');
|
||||
});
|
||||
|
||||
it('presets are never hidden via model ID', () => {
|
||||
it('personas are never hidden via model ID', () => {
|
||||
const resp = {
|
||||
models: [
|
||||
{ model_id: 'gpt-4o', is_preset: true, preset_id: 'p1', display_name: 'Preset' },
|
||||
{ model_id: 'gpt-4o', is_persona: true, persona_id: 'p1', display_name: 'Persona' },
|
||||
],
|
||||
};
|
||||
const hidden = new Set(['gpt-4o']);
|
||||
const models = processModelsResponse(resp, hidden);
|
||||
assert.equal(models[0].hidden, false,
|
||||
'presets must NOT be hidden by base model hidden pref');
|
||||
'personas must NOT be hidden by base model hidden pref');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -270,44 +270,44 @@ describe('Model sorting', () => {
|
||||
function sortModels(models) {
|
||||
const scopeOrder = { global: 0, team: 1, personal: 2 };
|
||||
return [...models].sort((a, b) => {
|
||||
if (a.isPreset && !b.isPreset) return -1;
|
||||
if (!a.isPreset && b.isPreset) return 1;
|
||||
if (a.isPreset && b.isPreset) {
|
||||
const sa = scopeOrder[a.presetScope] ?? 9;
|
||||
const sb = scopeOrder[b.presetScope] ?? 9;
|
||||
if (a.isPersona && !b.isPersona) return -1;
|
||||
if (!a.isPersona && b.isPersona) return 1;
|
||||
if (a.isPersona && b.isPersona) {
|
||||
const sa = scopeOrder[a.personaScope] ?? 9;
|
||||
const sb = scopeOrder[b.personaScope] ?? 9;
|
||||
if (sa !== sb) return sa - sb;
|
||||
}
|
||||
return a.name.localeCompare(b.name);
|
||||
});
|
||||
}
|
||||
|
||||
it('presets sort before regular models', () => {
|
||||
it('personas sort before regular models', () => {
|
||||
const models = [
|
||||
{ name: 'GPT-4o', isPreset: false },
|
||||
{ name: 'Code Helper', isPreset: true, presetScope: 'global' },
|
||||
{ name: 'GPT-4o', isPersona: false },
|
||||
{ name: 'Code Helper', isPersona: true, personaScope: 'global' },
|
||||
];
|
||||
const sorted = sortModels(models);
|
||||
assert.equal(sorted[0].name, 'Code Helper');
|
||||
assert.equal(sorted[1].name, 'GPT-4o');
|
||||
});
|
||||
|
||||
it('global presets sort before team presets', () => {
|
||||
it('global personas sort before team personas', () => {
|
||||
const models = [
|
||||
{ name: 'Team Bot', isPreset: true, presetScope: 'team' },
|
||||
{ name: 'Global Bot', isPreset: true, presetScope: 'global' },
|
||||
{ name: 'My Bot', isPreset: true, presetScope: 'personal' },
|
||||
{ name: 'Team Bot', isPersona: true, personaScope: 'team' },
|
||||
{ name: 'Global Bot', isPersona: true, personaScope: 'global' },
|
||||
{ name: 'My Bot', isPersona: true, personaScope: 'personal' },
|
||||
];
|
||||
const sorted = sortModels(models);
|
||||
assert.equal(sorted[0].presetScope, 'global');
|
||||
assert.equal(sorted[1].presetScope, 'team');
|
||||
assert.equal(sorted[2].presetScope, 'personal');
|
||||
assert.equal(sorted[0].personaScope, 'global');
|
||||
assert.equal(sorted[1].personaScope, 'team');
|
||||
assert.equal(sorted[2].personaScope, 'personal');
|
||||
});
|
||||
|
||||
it('regular models sort alphabetically', () => {
|
||||
const models = [
|
||||
{ name: 'Zephyr', isPreset: false },
|
||||
{ name: 'Claude', isPreset: false },
|
||||
{ name: 'GPT-4o', isPreset: false },
|
||||
{ name: 'Zephyr', isPersona: false },
|
||||
{ name: 'Claude', isPersona: false },
|
||||
{ name: 'GPT-4o', isPersona: false },
|
||||
];
|
||||
const sorted = sortModels(models);
|
||||
assert.equal(sorted[0].name, 'Claude');
|
||||
|
||||
@@ -65,12 +65,12 @@ describe('Policy wiring audit — source code', () => {
|
||||
|
||||
// ── allow_user_personas ──
|
||||
|
||||
it('UI has checkUserPresetsAllowed function', () => {
|
||||
assert.ok(uiSrc.includes('checkUserPresetsAllowed'),
|
||||
'MISSING: checkUserPresetsAllowed — preset button will show when policy is off');
|
||||
it('UI has checkUserPersonasAllowed function', () => {
|
||||
assert.ok(uiSrc.includes('checkUserPersonasAllowed'),
|
||||
'MISSING: checkUserPersonasAllowed — persona button will show when policy is off');
|
||||
});
|
||||
|
||||
it('checkUserPresetsAllowed reads App.policies.allow_user_personas', () => {
|
||||
it('checkUserPersonasAllowed reads App.policies.allow_user_personas', () => {
|
||||
assert.ok(uiSrc.includes('allow_user_personas'),
|
||||
'MISSING: allow_user_personas check in UI');
|
||||
});
|
||||
@@ -104,10 +104,10 @@ describe('Policy wiring audit — source code', () => {
|
||||
'MISSING: checkUserProvidersAllowed call after admin save');
|
||||
});
|
||||
|
||||
it('admin save calls checkUserPresetsAllowed', () => {
|
||||
it('admin save calls checkUserPersonasAllowed', () => {
|
||||
const saveFunc = appSrc.slice(appSrc.indexOf('handleSaveAdminSettings'));
|
||||
assert.ok(saveFunc.includes('checkUserPresetsAllowed'),
|
||||
'MISSING: checkUserPresetsAllowed call after admin save');
|
||||
assert.ok(saveFunc.includes('checkUserPersonasAllowed'),
|
||||
'MISSING: checkUserPersonasAllowed call after admin save');
|
||||
});
|
||||
|
||||
it('admin save calls fetchModels to refresh model list', () => {
|
||||
@@ -118,9 +118,9 @@ describe('Policy wiring audit — source code', () => {
|
||||
|
||||
// ── Models tab calls preset check ──
|
||||
|
||||
it('models tab switch calls checkUserPresetsAllowed', () => {
|
||||
assert.ok(uiSrc.includes('checkUserPresetsAllowed'),
|
||||
'MISSING: checkUserPresetsAllowed call on models tab switch');
|
||||
it('models tab switch calls checkUserPersonasAllowed', () => {
|
||||
assert.ok(uiSrc.includes('checkUserPersonasAllowed'),
|
||||
'MISSING: checkUserPersonasAllowed call on models tab switch');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -283,9 +283,9 @@ describe('Critical HTML elements exist in server templates', () => {
|
||||
|
||||
const requiredElements = [
|
||||
// Settings surface — provider section scaffold
|
||||
'userPresetList', // User preset list container
|
||||
'userAddPresetBtn', // New preset button (policy-gated)
|
||||
'userAddPresetForm', // Preset form container
|
||||
'userPersonaList', // User persona list container
|
||||
'userAddPersonaBtn', // New persona button (policy-gated)
|
||||
'userAddPersonaForm', // Persona form container
|
||||
'userProvidersDisabled', // BYOK disabled notice
|
||||
'providerShowAddBtn', // Add provider button (policy-gated)
|
||||
// Admin settings — policy toggles
|
||||
|
||||
@@ -31,7 +31,7 @@ function globalModel(modelId, configId, providerName) {
|
||||
provider_type: 'openai',
|
||||
source: 'catalog',
|
||||
scope: 'global',
|
||||
is_preset: false,
|
||||
is_persona: false,
|
||||
capabilities: { streaming: true },
|
||||
hidden: false,
|
||||
};
|
||||
@@ -48,7 +48,7 @@ function teamModel(modelId, configId, providerName, teamName) {
|
||||
provider_type: 'venice',
|
||||
source: 'catalog',
|
||||
scope: 'team',
|
||||
is_preset: false,
|
||||
is_persona: false,
|
||||
capabilities: { streaming: true },
|
||||
hidden: false,
|
||||
team_name: teamName,
|
||||
@@ -66,21 +66,21 @@ function personalModel(modelId, configId, providerName) {
|
||||
provider_type: 'venice',
|
||||
source: 'catalog',
|
||||
scope: 'personal',
|
||||
is_preset: false,
|
||||
is_persona: false,
|
||||
capabilities: { streaming: true },
|
||||
hidden: false,
|
||||
};
|
||||
}
|
||||
|
||||
function presetModel(presetId, baseModelId, scope, teamName) {
|
||||
function personaModel(personaId, baseModelId, scope, teamName) {
|
||||
return {
|
||||
id: presetId,
|
||||
id: personaId,
|
||||
model_id: baseModelId,
|
||||
display_name: `Preset: ${baseModelId}`,
|
||||
preset_id: presetId,
|
||||
preset_scope: scope,
|
||||
preset_team_name: teamName || '',
|
||||
is_preset: true,
|
||||
display_name: `Persona: ${baseModelId}`,
|
||||
persona_id: personaId,
|
||||
persona_scope: scope,
|
||||
persona_team_name: teamName || '',
|
||||
is_persona: true,
|
||||
source: 'persona',
|
||||
scope: scope,
|
||||
capabilities: { streaming: true },
|
||||
@@ -144,9 +144,9 @@ describe('User Journey: Platform Admin (no team, no BYOK)', () => {
|
||||
}
|
||||
});
|
||||
|
||||
it('source is catalog (not preset)', () => {
|
||||
it('source is catalog (not persona)', () => {
|
||||
for (const m of models) {
|
||||
assert.equal(m.isPreset, false);
|
||||
assert.equal(m.isPersona, false);
|
||||
assert.equal(m.source, 'catalog');
|
||||
}
|
||||
});
|
||||
@@ -322,42 +322,42 @@ describe('Edge: Hidden model preferences', () => {
|
||||
assert.equal(main.hidden, false, 'gpt-4o should not be hidden');
|
||||
});
|
||||
|
||||
it('presets are never hidden', () => {
|
||||
const preset = presetModel('preset-1', 'gpt-4o', 'global');
|
||||
it('personas are never hidden', () => {
|
||||
const persona = personaModel('preset-1', 'gpt-4o', 'global');
|
||||
const hidden = new Set(['gpt-4o']);
|
||||
const models = processModelsResponse({ models: [preset] }, hidden);
|
||||
assert.equal(models[0].hidden, false, 'presets must never be hidden');
|
||||
const models = processModelsResponse({ models: [persona] }, hidden);
|
||||
assert.equal(models[0].hidden, false, 'personas must never be hidden');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Edge: Presets mixed with catalog models', () => {
|
||||
describe('Edge: Personas mixed with catalog models', () => {
|
||||
const apiResponse = {
|
||||
models: [
|
||||
...GLOBAL_MODELS,
|
||||
presetModel('preset-code', 'gpt-4o', 'global'),
|
||||
presetModel('preset-team', 'llama-3.3-70b', 'team', 'Engineering'),
|
||||
personaModel('preset-code', 'gpt-4o', 'global'),
|
||||
personaModel('preset-team', 'llama-3.3-70b', 'team', 'Engineering'),
|
||||
],
|
||||
};
|
||||
const models = processModelsResponse(apiResponse);
|
||||
|
||||
it('presets use preset_id as ID, not composite', () => {
|
||||
const preset = models.find(m => m.presetId === 'preset-code');
|
||||
assert.ok(preset, 'preset-code should be present');
|
||||
assert.equal(preset.id, 'preset-code');
|
||||
assert.equal(preset.isPreset, true);
|
||||
it('personas use persona_id as ID, not composite', () => {
|
||||
const persona = models.find(m => m.personaId === 'preset-code');
|
||||
assert.ok(persona, 'preset-code should be present');
|
||||
assert.equal(persona.id, 'preset-code');
|
||||
assert.equal(persona.isPersona, true);
|
||||
});
|
||||
|
||||
it('preset and catalog model with same model_id have different IDs', () => {
|
||||
const catalog = models.find(m => !m.isPreset && m.baseModelId === 'gpt-4o');
|
||||
const preset = models.find(m => m.isPreset && m.baseModelId === 'gpt-4o');
|
||||
it('persona and catalog model with same model_id have different IDs', () => {
|
||||
const catalog = models.find(m => !m.isPersona && m.baseModelId === 'gpt-4o');
|
||||
const persona = models.find(m => m.isPersona && m.baseModelId === 'gpt-4o');
|
||||
assert.ok(catalog, 'catalog gpt-4o should exist');
|
||||
assert.ok(preset, 'preset gpt-4o should exist');
|
||||
assert.notEqual(catalog.id, preset.id);
|
||||
assert.ok(persona, 'preset gpt-4o should exist');
|
||||
assert.notEqual(catalog.id, persona.id);
|
||||
});
|
||||
|
||||
it('preset team name flows through', () => {
|
||||
const teamPreset = models.find(m => m.presetId === 'preset-team');
|
||||
assert.equal(teamPreset.presetTeamName, 'Engineering');
|
||||
it('persona team name flows through', () => {
|
||||
const teamPersona = models.find(m => m.personaId === 'preset-team');
|
||||
assert.equal(teamPersona.personaTeamName, 'Engineering');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -412,10 +412,10 @@ describe('Full Matrix: 4 actors × backend response → frontend model count', (
|
||||
`${tc.actor}: duplicate IDs: ${JSON.stringify(ids)}`);
|
||||
});
|
||||
|
||||
it(`${tc.actor}: all models have configId or are presets`, () => {
|
||||
it(`${tc.actor}: all models have configId or are personas`, () => {
|
||||
const result = processModelsResponse({ models: tc.models });
|
||||
for (const m of result) {
|
||||
if (!m.isPreset) {
|
||||
if (!m.isPersona) {
|
||||
assert.ok(m.configId,
|
||||
`${tc.actor}: model ${m.baseModelId} missing configId — ` +
|
||||
`frontend will fail to route completions`);
|
||||
|
||||
Reference in New Issue
Block a user