feat: Add character names to scenarios and UI
Introduces `characterName` to the `Scenario` type, enabling AI personas to be explicitly named. This change also updates the `ScenarioCard` component to display the character name and adds foundational support for potential future scenario deletion functionality. The README has been updated with a new AI Studio link.
This commit is contained in:
1 parent
e92c489db5
commit
a4946ed04d
18 files changed
+3585
-320
No files matched your search
@@ -1,8 +1,9 @@
|
||||
|
||||
import React, { useState } from 'react';
|
||||
import { GoogleGenAI, Type } from "@google/genai";
|
||||
import { Scenario } from '../types';
|
||||
import { CBT_GLOSSARY } from '../constants';
|
||||
import { Sparkles, X, Loader2, AlertCircle, Info, Target, UserCircle2, BrainCircuit, Check } from 'lucide-react';
|
||||
import { Sparkles, X, Loader2, AlertCircle, Info, Target, UserCircle2, BrainCircuit, Check, BarChart } from 'lucide-react';
|
||||
|
||||
interface ScenarioGeneratorProps {
|
||||
onGenerate: (scenario: Scenario) => void;
|
||||
@@ -12,6 +13,7 @@ interface ScenarioGeneratorProps {
|
||||
const ScenarioGenerator: React.FC<ScenarioGeneratorProps> = ({ onGenerate, onCancel }) => {
|
||||
const [prompt, setPrompt] = useState('');
|
||||
const [selectedConcepts, setSelectedConcepts] = useState<string[]>([]);
|
||||
const [selectedDifficulty, setSelectedDifficulty] = useState<Scenario['difficulty']>('Intermediate');
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
@@ -35,6 +37,7 @@ const ScenarioGenerator: React.FC<ScenarioGeneratorProps> = ({ onGenerate, onCan
|
||||
properties: {
|
||||
id: { type: Type.STRING },
|
||||
title: { type: Type.STRING },
|
||||
characterName: { type: Type.STRING },
|
||||
description: { type: Type.STRING },
|
||||
category: {
|
||||
type: Type.STRING,
|
||||
@@ -51,7 +54,7 @@ const ScenarioGenerator: React.FC<ScenarioGeneratorProps> = ({ onGenerate, onCan
|
||||
items: { type: Type.STRING }
|
||||
}
|
||||
},
|
||||
required: ['id', 'title', 'description', 'category', 'difficulty', 'systemInstruction', 'initialMessage', 'cbtFocus']
|
||||
required: ['id', 'title', 'characterName', 'description', 'category', 'difficulty', 'systemInstruction', 'initialMessage', 'cbtFocus']
|
||||
};
|
||||
|
||||
const selectedContext = selectedConcepts.length > 0
|
||||
@@ -69,17 +72,18 @@ const ScenarioGenerator: React.FC<ScenarioGeneratorProps> = ({ onGenerate, onCan
|
||||
|
||||
CORE INSTRUCTIONS:
|
||||
1. CLINICAL FOCUS: ${selectedContext}
|
||||
2. CATEGORIZATION: You MUST assign the scenario to exactly one of the following categories based on its primary context:
|
||||
2. CATEGORIZATION: Based on the user's input, you MUST suggest the most appropriate category for the scenario:
|
||||
- 'Social Anxiety': Situations involving social performance, fear of judgment, or networking.
|
||||
- 'Workplace': Scenarios involving colleagues, supervisors, career growth, or professional conflict.
|
||||
- 'Relationships': Dynamics with family, friends, or romantic partners; boundary setting.
|
||||
- 'Self-Talk': Purely internal cognitive restructuring, rumination, or self-compassion work.
|
||||
3. DIFFICULTY CALIBRATION: Assign a level based on cognitive load:
|
||||
- 'Beginner': Low stakes, high support, clear-cut distortions.
|
||||
- 'Intermediate': Ambiguous stakes, moderate social friction, subtle distortions.
|
||||
- 'Advanced': High emotional triggers, persistent clinical resistance from AI character, deep-seated patterns.
|
||||
4. INTERNAL LOGIC: The 'systemInstruction' must include a detailed "INTERNAL CBT LOGIC" section. This tells the AI how to react to the user's progress or cognitive lapses.
|
||||
5. CONSISTENCY: Ensure 'cbtFocus' includes the selected concepts.
|
||||
3. DIFFICULTY CALIBRATION: The user has explicitly requested a '${selectedDifficulty}' level.
|
||||
Generate the scenario content and the AI character's behavior to match this complexity:
|
||||
- 'Beginner': Low stakes, high support, clear-cut distortions, AI character is cooperative.
|
||||
- 'Intermediate': Ambiguous stakes, moderate social friction, subtle distortions, AI character has specific needs/points.
|
||||
- 'Advanced': High emotional triggers, persistent clinical resistance from AI character, complex deep-seated cognitive patterns.
|
||||
4. INTERNAL LOGIC: The 'systemInstruction' for the character MUST include a detailed "INTERNAL CBT LOGIC" section. This instructs the AI character how to react to the user's progress or cognitive lapses.
|
||||
5. CHARACTER VOICE: Define a realistic voice profile for the character, including their likely emotional state (frustrated, busy, anxious, etc.).
|
||||
`
|
||||
},
|
||||
contents: [
|
||||
@@ -89,6 +93,8 @@ const ScenarioGenerator: React.FC<ScenarioGeneratorProps> = ({ onGenerate, onCan
|
||||
|
||||
if (result.text) {
|
||||
const scenario = JSON.parse(result.text) as Scenario;
|
||||
// Enforce the user-selected difficulty in the final object
|
||||
scenario.difficulty = selectedDifficulty;
|
||||
scenario.id = `custom-${Date.now()}-${scenario.id}`;
|
||||
onGenerate(scenario);
|
||||
} else {
|
||||
@@ -162,6 +168,29 @@ const ScenarioGenerator: React.FC<ScenarioGeneratorProps> = ({ onGenerate, onCan
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Difficulty Selection */}
|
||||
<div className="space-y-3">
|
||||
<label className="block text-[10px] font-black text-slate-400 uppercase tracking-widest">
|
||||
Communication Difficulty
|
||||
</label>
|
||||
<div className="grid grid-cols-3 gap-2">
|
||||
{(['Beginner', 'Intermediate', 'Advanced'] as const).map((level) => (
|
||||
<button
|
||||
key={level}
|
||||
onClick={() => setSelectedDifficulty(level)}
|
||||
className={`flex items-center justify-center gap-2 py-2.5 rounded-xl border-2 transition-all text-[11px] font-bold ${
|
||||
selectedDifficulty === level
|
||||
? 'bg-teal-50 border-teal-600 text-teal-700 shadow-sm shadow-teal-50'
|
||||
: 'bg-white border-slate-100 text-slate-400 hover:border-slate-200'
|
||||
}`}
|
||||
>
|
||||
<BarChart size={14} className={selectedDifficulty === level ? 'text-teal-600' : 'text-slate-300'} />
|
||||
{level}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Clinical Targets (Selection) */}
|
||||
<div className="space-y-3">
|
||||
<label className="block text-[10px] font-black text-slate-400 uppercase tracking-widest">
|
||||
@@ -229,4 +258,4 @@ const ScenarioGenerator: React.FC<ScenarioGeneratorProps> = ({ onGenerate, onCan
|
||||
);
|
||||
};
|
||||
|
||||
export default ScenarioGenerator;
|
||||
export default ScenarioGenerator;
|
||||
Reference in new issue
Block a user