Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 50 additions & 2 deletions src/stores/personasStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,41 @@ const DEFAULT_PERSONA: Persona = {
isDefault: true,
};

const STARTER_PERSONAS: Persona[] = [
{
id: 'starter-code-reviewer',
name: 'Code Reviewer',
color: '#6366f1',
systemPrompt:
'You are a senior software engineer conducting a thorough code review. Evaluate code for correctness, security vulnerabilities, performance, readability, and adherence to best practices. Be direct and specific — point to exact lines, explain why something is a problem, and suggest a concrete fix. Prioritise issues by severity (critical, major, minor).',
isDefault: false,
},
{
id: 'starter-writing-assistant',
name: 'Writing Assistant',
color: '#10b981',
systemPrompt:
'You are a professional editor who writes and edits with clarity, precision, and a neutral tone. Cut unnecessary words, favour active voice, and keep sentences concise. When editing, explain each change briefly. When writing from scratch, match the requested format and audience. Avoid jargon unless the context calls for it.',
isDefault: false,
},
{
id: 'starter-research-analyst',
name: 'Research Analyst',
color: '#f59e0b',
systemPrompt:
'You are a rigorous research analyst. Structure your responses with clear headings, bullet-point summaries, and explicit citations or source notes where relevant. Distinguish between established fact, current consensus, and contested claims. When uncertain, say so. Favour depth over breadth — go into detail on the key points rather than skimming everything.',
isDefault: false,
},
{
id: 'starter-rubber-duck',
name: 'Rubber Duck',
color: '#eab308',
systemPrompt:
'You help people think through problems by asking focused clarifying questions rather than jumping to answers. When someone presents a problem, ask one or two targeted questions to help them articulate their assumptions, constraints, or what they have already tried. Only offer a direct answer or suggestion when explicitly asked, or when the person is clearly stuck after several exchanges.',
isDefault: false,
},
];

interface PersonasState {
personas: Persona[];
addPersona: (partial: Omit<Persona, 'id' | 'isDefault'>) => Persona;
Expand All @@ -24,7 +59,7 @@ interface PersonasState {
export const usePersonasStore = create<PersonasState>()(
persist(
(set, get) => ({
personas: [DEFAULT_PERSONA],
personas: [DEFAULT_PERSONA, ...STARTER_PERSONAS],

addPersona: (partial) => {
const persona: Persona = { id: uuidv4(), isDefault: false, ...partial };
Expand Down Expand Up @@ -73,6 +108,19 @@ export const usePersonasStore = create<PersonasState>()(

getPersona: (id) => get().personas.find((p) => p.id === id),
}),
{ name: 'openconduit-personas' },
{
name: 'openconduit-personas',
version: 1,
migrate: (persisted: unknown, fromVersion: number) => {
const state = persisted as PersonasState;
if (fromVersion < 1) {
// Inject any starter persona that the user doesn't already have
const existingIds = new Set(state.personas.map((p) => p.id));
const missing = STARTER_PERSONAS.filter((p) => !existingIds.has(p.id));
return { ...state, personas: [...state.personas, ...missing] };
}
return state;
},
},
),
);