diff --git a/lib/sandbox/__tests__/ensure-agent.test.ts b/lib/sandbox/__tests__/ensure-agent.test.ts new file mode 100644 index 00000000..f8dab2d5 --- /dev/null +++ b/lib/sandbox/__tests__/ensure-agent.test.ts @@ -0,0 +1,36 @@ +import { describe, it, expect } from 'vitest' +import { SANDBOX_AGENT_NAME, SANDBOX_PROFILE_SUMMARY } from '../ensure-agent' + +/** + * The sandbox assistant is called "Assistenten", not a first name: nobody in + * the sandbox chose a persona, so a first name implies a relationship the + * visitor never opted into. + * + * The pairing is the part worth pinning. profile_summary is the agent's own + * self-description inside the system prompt, so if it drifts from the display + * name the header says one thing and the assistant introduces itself as + * another in its first sentence: a mismatch nothing else in the stack checks. + */ +describe('sandbox agent persona', () => { + it('is named Assistenten', () => { + expect(SANDBOX_AGENT_NAME).toBe('Assistenten') + }) + + it('introduces itself by the same name the UI shows', () => { + expect(SANDBOX_PROFILE_SUMMARY).toContain(`Du är ${SANDBOX_AGENT_NAME}`) + }) + + it('does not still call itself Anna anywhere in the persona', () => { + expect(SANDBOX_AGENT_NAME).not.toContain('Anna') + expect(SANDBOX_PROFILE_SUMMARY).not.toContain('Anna') + }) + + it('keeps the demo company description the persona depends on', () => { + // The sandbox data is a Stockholm IT consultancy on the cash method with + // quarterly VAT. The summary is what makes the assistant's answers match + // the seeded books, so a rename must not quietly drop it. + expect(SANDBOX_PROFILE_SUMMARY).toContain('enskild firma') + expect(SANDBOX_PROFILE_SUMMARY).toContain('kontantmetoden') + expect(SANDBOX_PROFILE_SUMMARY).toContain('momsregistrerat') + }) +}) diff --git a/lib/sandbox/ensure-agent.ts b/lib/sandbox/ensure-agent.ts index 7eea5e29..036784a0 100644 --- a/lib/sandbox/ensure-agent.ts +++ b/lib/sandbox/ensure-agent.ts @@ -3,6 +3,24 @@ import { createLogger } from '@/lib/logger' const log = createLogger('sandbox:ensure-agent') +/** + * The sandbox assistant is called "Assistenten", not a first name. + * + * A named persona is right once someone has been through onboarding and chosen + * it: it is their assistant, and they named it. In the sandbox nobody chose + * anything, so a first name reads as a character the product invented and + * implies a relationship the visitor has not opted into. "Assistenten" says + * what it is. + * + * The summary is the agent's own self-description in the system prompt, so it + * has to agree with the display name: otherwise the header says one thing and + * the assistant introduces itself as another in its first sentence. + */ +export const SANDBOX_AGENT_NAME = 'Assistenten' + +export const SANDBOX_PROFILE_SUMMARY = + 'Du är Assistenten, en revisorsassistent för en svensk enskild firma som tillhandahåller IT-konsulttjänster i Stockholm. Företaget är momsregistrerat (kvartalsvis), använder kontantmetoden och fakturerar både svenska och utländska kunder.' + /** * Backfill a verified agent_profile for sandbox companies. Single source of * truth for the sandbox assistant's persona (name, avatar, atoms, summary): @@ -35,7 +53,7 @@ export async function ensureSandboxAgentProfile( const { error } = await supabase.from('agent_profiles').insert({ company_id: companyId, - display_name: 'Anna', + display_name: SANDBOX_AGENT_NAME, avatar_id: 'notionists-3', horizontal_atoms: [ 'horizontal/swedish-vat', @@ -43,8 +61,7 @@ export async function ensureSandboxAgentProfile( ], vertical_atoms: ['vertical/consulting'], modifier_atoms: [], - profile_summary: - 'Du är Anna, en revisorsassistent för en svensk enskild firma som tillhandahåller IT-konsulttjänster i Stockholm. Företaget är momsregistrerat (kvartalsvis), använder kontantmetoden och fakturerar både svenska och utländska kunder.', + profile_summary: SANDBOX_PROFILE_SUMMARY, source_signals: { is_sandbox: true }, field_overrides: {}, composer_model: 'sandbox-demo',