ec27228a8e
Em dashes (—) and en dashes (–) had spread across comments, docs, tests, and a few UI strings, reading as AI-generated boilerplate rather than house style. Replaced each with punctuation matching its context: colon for explanatory clauses, comma for asides, plain hyphen for numeric/legal ranges (e.g. "21-23§"), "to"/"till" for date ranges, parentheses for paired-dash asides. messages/en.json and messages/sv.json were fixed by hand together to keep sv/en in sync. Left untouched where the dash is the functional subject rather than decorative punctuation: date-range-parser.ts's separator regex, charset-repair.ts's CP1252 byte-mapping table (and its test), the SIE encoding mojibake docs, generic-csv.ts's minus-sign normalizer, the agent system-prompt files that already instruct against em dashes, and a golden iXBRL test fixture compared byte-for-byte. Also fixes two bugs surfaced along the way: an off-by-one in ApiKeysPanel's scope-label split (a leftover from an earlier partial pass), and a charset-repair test that had lost the literal en-dash it exists to verify. Regenerated the agent atom seed migration (skills:generate) since 27 SKILL.md files changed. Added a CLAUDE.md rule against em/en dashes, with an explicit carve-out for the functional-dash cases above. Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
43 lines
2.1 KiB
TypeScript
43 lines
2.1 KiB
TypeScript
// Avatar registry for the specialized accountant agent.
|
|
//
|
|
// We use the dicebear "notionists" style: clean line illustrations that
|
|
// match the editorial monochrome brand without the cartoony feel of most
|
|
// avatar libraries. 8 hand-picked seeds give distinct faces without being
|
|
// overwhelming. The user picks one during Phase B review; the choice is
|
|
// persisted as agent_profiles.avatar_id.
|
|
//
|
|
// URLs are served by dicebear's free CDN. They're public SVGs derived from
|
|
// the seed only: no user data leaves gnubok. If we ever need fully offline
|
|
// generation, swap to @dicebear/core npm package and render server-side.
|
|
|
|
export interface AvatarOption {
|
|
id: string
|
|
label: string
|
|
url: string
|
|
}
|
|
|
|
// Build URL from seed. Public dicebear CDN. ?radius=50 rounds the bounding
|
|
// box; ?backgroundColor=transparent keeps the editorial paper-white feel.
|
|
function dicebearNotionists(seed: string): string {
|
|
return `https://api.dicebear.com/9.x/notionists/svg?seed=${encodeURIComponent(seed)}&radius=50&backgroundColor=f5f3ed`
|
|
}
|
|
|
|
// Eight neutral seeds: names chosen to produce visibly different faces.
|
|
// Labels are just for the picker tooltip; the user names the agent
|
|
// themselves in the adjacent text field.
|
|
export const AVATAR_OPTIONS: readonly AvatarOption[] = [
|
|
{ id: 'notionists-1', label: 'Linn', url: dicebearNotionists('linn-revisor-1') },
|
|
{ id: 'notionists-2', label: 'Erik', url: dicebearNotionists('erik-revisor-2') },
|
|
{ id: 'notionists-3', label: 'Maja', url: dicebearNotionists('maja-revisor-3') },
|
|
{ id: 'notionists-4', label: 'Anders', url: dicebearNotionists('anders-revisor-4') },
|
|
{ id: 'notionists-5', label: 'Karin', url: dicebearNotionists('karin-revisor-5') },
|
|
{ id: 'notionists-6', label: 'Johan', url: dicebearNotionists('johan-revisor-6') },
|
|
{ id: 'notionists-7', label: 'Eva', url: dicebearNotionists('eva-revisor-7') },
|
|
{ id: 'notionists-8', label: 'Per', url: dicebearNotionists('per-revisor-8') },
|
|
]
|
|
|
|
export function getAvatarUrl(avatarId: string | null | undefined): string | null {
|
|
if (!avatarId) return null
|
|
return AVATAR_OPTIONS.find((a) => a.id === avatarId)?.url ?? null
|
|
}
|