tblaisaacliao commited on
Commit
9f473d0
·
1 Parent(s): b2b8bf6

remove StudentPersonality enum

Browse files
src/app/api/agent/chat/route.ts CHANGED
@@ -1,7 +1,7 @@
1
  import { NextRequest, NextResponse } from 'next/server';
2
  import { createOpenAI } from '@ai-sdk/openai';
3
  import { AIAgent } from '@/lib/agent';
4
- import { AgentType, StudentPersonality, AgentConfig } from '@/lib/types/agent';
5
 
6
  const customOpenAI = createOpenAI({
7
  apiKey: process.env.CZ_OPENAI_API_KEY || '',
@@ -11,7 +11,7 @@ const customOpenAI = createOpenAI({
11
  const defaultConfig: AgentConfig = {
12
  id: 'legacy-agent',
13
  type: AgentType.STUDENT,
14
- personality: StudentPersonality.ADHD_COMBINED,
15
  name: 'Default Student',
16
  description: 'A helpful AI student for legacy API compatibility',
17
  systemPrompt: 'You are a helpful AI assistant that can help with educational tasks. You have access to tools for calculations and note-taking.',
 
1
  import { NextRequest, NextResponse } from 'next/server';
2
  import { createOpenAI } from '@ai-sdk/openai';
3
  import { AIAgent } from '@/lib/agent';
4
+ import { AgentType, AgentConfig } from '@/lib/types/agent';
5
 
6
  const customOpenAI = createOpenAI({
7
  apiKey: process.env.CZ_OPENAI_API_KEY || '',
 
11
  const defaultConfig: AgentConfig = {
12
  id: 'legacy-agent',
13
  type: AgentType.STUDENT,
14
+ personality: 'adhd_combined',
15
  name: 'Default Student',
16
  description: 'A helpful AI student for legacy API compatibility',
17
  systemPrompt: 'You are a helpful AI assistant that can help with educational tasks. You have access to tools for calculations and note-taking.',
src/app/api/agent/history/[id]/route.ts CHANGED
@@ -1,7 +1,7 @@
1
  import { NextRequest, NextResponse } from 'next/server';
2
  import { createOpenAI } from '@ai-sdk/openai';
3
  import { AIAgent } from '@/lib/agent';
4
- import { AgentType, StudentPersonality, AgentConfig } from '@/lib/types/agent';
5
 
6
  const customOpenAI = createOpenAI({
7
  apiKey: process.env.CZ_OPENAI_API_KEY || '',
@@ -10,7 +10,7 @@ const customOpenAI = createOpenAI({
10
  const defaultConfig: AgentConfig = {
11
  id: 'legacy-agent',
12
  type: AgentType.STUDENT,
13
- personality: StudentPersonality.ADHD_COMBINED,
14
  name: 'Default Student',
15
  description: 'A helpful AI student for legacy API compatibility',
16
  systemPrompt: 'You are a helpful AI assistant that can help with educational tasks.',
 
1
  import { NextRequest, NextResponse } from 'next/server';
2
  import { createOpenAI } from '@ai-sdk/openai';
3
  import { AIAgent } from '@/lib/agent';
4
+ import { AgentType, AgentConfig } from '@/lib/types/agent';
5
 
6
  const customOpenAI = createOpenAI({
7
  apiKey: process.env.CZ_OPENAI_API_KEY || '',
 
10
  const defaultConfig: AgentConfig = {
11
  id: 'legacy-agent',
12
  type: AgentType.STUDENT,
13
+ personality: 'adhd_combined',
14
  name: 'Default Student',
15
  description: 'A helpful AI student for legacy API compatibility',
16
  systemPrompt: 'You are a helpful AI assistant that can help with educational tasks.',
src/app/api/agents/personalities/route.ts ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { NextResponse } from 'next/server';
2
+ import { studentPrompts } from '@/lib/prompts/student-prompts';
3
+
4
+ export async function GET() {
5
+ const personalities = Object.entries(studentPrompts).map(([key, config]) => ({
6
+ id: key,
7
+ name: config.name,
8
+ description: config.description,
9
+ tools: config.tools
10
+ }));
11
+
12
+ return NextResponse.json({
13
+ personalities,
14
+ total: personalities.length
15
+ });
16
+ }
src/app/api/agents/route.ts CHANGED
@@ -1,10 +1,14 @@
1
  import { NextRequest, NextResponse } from 'next/server';
2
  import { AgentRepository } from '@/lib/repositories/agent-repository';
3
  import { requireBasicAuth, createUnauthorizedResponse } from '@/lib/middleware/basic-auth';
 
4
  import { z } from 'zod';
5
 
6
  const createAgentSchema = z.object({
7
- personality: z.enum(['adhd_inattentive', 'adhd_hyperactive', 'adhd_combined']),
 
 
 
8
  name: z.string().optional(),
9
  customPrompt: z.string().optional(),
10
  });
 
1
  import { NextRequest, NextResponse } from 'next/server';
2
  import { AgentRepository } from '@/lib/repositories/agent-repository';
3
  import { requireBasicAuth, createUnauthorizedResponse } from '@/lib/middleware/basic-auth';
4
+ import { getAvailablePersonalities } from '@/lib/prompts/student-prompts';
5
  import { z } from 'zod';
6
 
7
  const createAgentSchema = z.object({
8
+ personality: z.string().refine(
9
+ (p) => getAvailablePersonalities().includes(p),
10
+ { message: 'Invalid personality type' }
11
+ ),
12
  name: z.string().optional(),
13
  customPrompt: z.string().optional(),
14
  });
src/app/dashboard/page.tsx CHANGED
@@ -124,10 +124,15 @@ export default function Dashboard() {
124
 
125
  const createAllStudents = async () => {
126
  try {
127
- // Create all three students sequentially
128
- await createAgent('adhd_inattentive'); // 小明
129
- await createAgent('adhd_hyperactive'); // 小華
130
- await createAgent('adhd_combined'); // 小美
 
 
 
 
 
131
  // Fetch agents once after all are created
132
  await fetchAgents();
133
  } catch (error) {
 
124
 
125
  const createAllStudents = async () => {
126
  try {
127
+ // Fetch available personalities from API
128
+ const response = await fetch(`${API_URL}/api/agents/personalities`);
129
+ const data = await response.json();
130
+
131
+ // Create each personality sequentially to prevent race conditions
132
+ for (const personality of data.personalities) {
133
+ await createAgent(personality.id);
134
+ }
135
+
136
  // Fetch agents once after all are created
137
  await fetchAgents();
138
  } catch (error) {
src/lib/agent-configs.ts CHANGED
@@ -1,10 +1,9 @@
1
  import {
2
  AgentConfig,
3
  AgentType,
4
- StudentPersonality,
5
  CreateAgentRequest
6
  } from './types/agent';
7
- import { getStudentConfig, getStudentPrompt } from './prompts/student-prompts';
8
  import { allTools } from './tools';
9
 
10
  export class AgentConfigFactory {
@@ -20,7 +19,12 @@ export class AgentConfigFactory {
20
  let config: AgentConfig;
21
 
22
  if (request.type === AgentType.STUDENT) {
23
- const studentPersonality = request.personality as StudentPersonality;
 
 
 
 
 
24
  const template = getStudentConfig(studentPersonality);
25
 
26
  config = {
@@ -113,7 +117,7 @@ If you don't need a tool, just respond normally with helpful information.`;
113
  if (updatedConfig.metadata?.templateUsed) {
114
  if (config.type === AgentType.STUDENT) {
115
  updatedConfig.systemPrompt = getStudentPrompt(
116
- config.personality as StudentPersonality,
117
  updates.tools
118
  );
119
  }
@@ -143,14 +147,11 @@ If you don't need a tool, just respond normally with helpful information.`;
143
  return [
144
  {
145
  type: AgentType.STUDENT,
146
- personalities: Object.values(StudentPersonality).map(personality => {
147
- const config = getStudentConfig(personality);
148
- return {
149
- personality,
150
- name: config.name,
151
- description: config.description
152
- };
153
- })
154
  },
155
  {
156
  type: AgentType.ASSISTANT,
@@ -184,8 +185,8 @@ If you don't need a tool, just respond normally with helpful information.`;
184
  errors.push('Invalid agent type');
185
  }
186
 
187
- if (config.type === AgentType.STUDENT && !Object.values(StudentPersonality).includes(config.personality as StudentPersonality)) {
188
- errors.push('Invalid student personality');
189
  }
190
 
191
 
 
1
  import {
2
  AgentConfig,
3
  AgentType,
 
4
  CreateAgentRequest
5
  } from './types/agent';
6
+ import { getStudentConfig, getStudentPrompt, studentPrompts, isValidPersonality } from './prompts/student-prompts';
7
  import { allTools } from './tools';
8
 
9
  export class AgentConfigFactory {
 
19
  let config: AgentConfig;
20
 
21
  if (request.type === AgentType.STUDENT) {
22
+ const studentPersonality = request.personality;
23
+
24
+ if (!isValidPersonality(studentPersonality)) {
25
+ throw new Error(`Invalid student personality: ${studentPersonality}`);
26
+ }
27
+
28
  const template = getStudentConfig(studentPersonality);
29
 
30
  config = {
 
117
  if (updatedConfig.metadata?.templateUsed) {
118
  if (config.type === AgentType.STUDENT) {
119
  updatedConfig.systemPrompt = getStudentPrompt(
120
+ config.personality,
121
  updates.tools
122
  );
123
  }
 
147
  return [
148
  {
149
  type: AgentType.STUDENT,
150
+ personalities: Object.entries(studentPrompts).map(([key, config]) => ({
151
+ personality: key,
152
+ name: config.name,
153
+ description: config.description
154
+ }))
 
 
 
155
  },
156
  {
157
  type: AgentType.ASSISTANT,
 
185
  errors.push('Invalid agent type');
186
  }
187
 
188
+ if (config.type === AgentType.STUDENT && !isValidPersonality(config.personality)) {
189
+ errors.push(`Invalid student personality: ${config.personality}`);
190
  }
191
 
192
 
src/lib/prompts/student-prompts.ts CHANGED
@@ -1,16 +1,14 @@
1
- import { StudentPersonality } from '../types/agent';
2
-
3
  export interface StudentPromptTemplate {
4
- personality: StudentPersonality;
5
  name: string;
6
  description: string;
7
  systemPrompt: string;
8
  tools: string[];
9
  }
10
 
11
- export const studentPrompts: Record<StudentPersonality, StudentPromptTemplate> = {
12
- [StudentPersonality.ADHD_INATTENTIVE]: {
13
- personality: StudentPersonality.ADHD_INATTENTIVE,
14
  name: '小明 - 注意力不集中型學生',
15
  description: '患有ADHD注意力不足型的學生,在專注力、組織能力和遵循指示方面有困難',
16
  systemPrompt: `IMPORTANT: You MUST respond in Traditional Chinese (繁體中文) using Mandarin. All your responses should be in Chinese.
@@ -55,8 +53,8 @@ IMPORTANT: Keep your responses SHORT and CONCISE. Aim for 1-3 sentences maximum
55
  tools: ['calculate', 'save_note']
56
  },
57
 
58
- [StudentPersonality.ADHD_HYPERACTIVE]: {
59
- personality: StudentPersonality.ADHD_HYPERACTIVE,
60
  name: '小華 - 過動型學生',
61
  description: '患有ADHD過動型的學生,精力充沛、衝動且難以自我控制',
62
  systemPrompt: `IMPORTANT: You MUST respond in Traditional Chinese (繁體中文) using Mandarin. All your responses should be in Chinese.
@@ -100,8 +98,8 @@ IMPORTANT: Keep your responses SHORT and CONCISE. Aim for 1-3 sentences maximum
100
  tools: ['calculate', 'save_note']
101
  },
102
 
103
- [StudentPersonality.ADHD_COMBINED]: {
104
- personality: StudentPersonality.ADHD_COMBINED,
105
  name: '小美 - 混合型學生',
106
  description: '患有ADHD混合型的學生,同時有注意力不足和過動問題,並在社交線索和情緒調節方面有困難',
107
  systemPrompt: `IMPORTANT: You MUST respond in Traditional Chinese (繁體中文) using Mandarin. All your responses should be in Chinese.
@@ -146,13 +144,28 @@ IMPORTANT: Keep your responses SHORT and CONCISE. Aim for 1-3 sentences maximum
146
  }
147
  };
148
 
149
- export function getStudentPrompt(personality: StudentPersonality, availableTools: string[]): string {
 
 
 
 
 
 
 
 
150
  const template = studentPrompts[personality];
 
 
 
151
  const toolDescriptions = availableTools.map(tool => `- ${tool}: Available for use`).join('\n');
152
 
153
  return template.systemPrompt.replace('{{TOOLS}}', toolDescriptions);
154
  }
155
 
156
- export function getStudentConfig(personality: StudentPersonality) {
157
- return studentPrompts[personality];
 
 
 
 
158
  }
 
 
 
1
  export interface StudentPromptTemplate {
2
+ personality: string;
3
  name: string;
4
  description: string;
5
  systemPrompt: string;
6
  tools: string[];
7
  }
8
 
9
+ export const studentPrompts: Record<string, StudentPromptTemplate> = {
10
+ 'adhd_inattentive': {
11
+ personality: 'adhd_inattentive',
12
  name: '小明 - 注意力不集中型學生',
13
  description: '患有ADHD注意力不足型的學生,在專注力、組織能力和遵循指示方面有困難',
14
  systemPrompt: `IMPORTANT: You MUST respond in Traditional Chinese (繁體中文) using Mandarin. All your responses should be in Chinese.
 
53
  tools: ['calculate', 'save_note']
54
  },
55
 
56
+ 'adhd_hyperactive': {
57
+ personality: 'adhd_hyperactive',
58
  name: '小華 - 過動型學生',
59
  description: '患有ADHD過動型的學生,精力充沛、衝動且難以自我控制',
60
  systemPrompt: `IMPORTANT: You MUST respond in Traditional Chinese (繁體中文) using Mandarin. All your responses should be in Chinese.
 
98
  tools: ['calculate', 'save_note']
99
  },
100
 
101
+ 'adhd_combined': {
102
+ personality: 'adhd_combined',
103
  name: '小美 - 混合型學生',
104
  description: '患有ADHD混合型的學生,同時有注意力不足和過動問題,並在社交線索和情緒調節方面有困難',
105
  systemPrompt: `IMPORTANT: You MUST respond in Traditional Chinese (繁體中文) using Mandarin. All your responses should be in Chinese.
 
144
  }
145
  };
146
 
147
+ export function getAvailablePersonalities(): string[] {
148
+ return Object.keys(studentPrompts);
149
+ }
150
+
151
+ export function isValidPersonality(personality: string): boolean {
152
+ return personality in studentPrompts;
153
+ }
154
+
155
+ export function getStudentPrompt(personality: string, availableTools: string[]): string {
156
  const template = studentPrompts[personality];
157
+ if (!template) {
158
+ throw new Error(`Unknown personality: ${personality}`);
159
+ }
160
  const toolDescriptions = availableTools.map(tool => `- ${tool}: Available for use`).join('\n');
161
 
162
  return template.systemPrompt.replace('{{TOOLS}}', toolDescriptions);
163
  }
164
 
165
+ export function getStudentConfig(personality: string) {
166
+ const config = studentPrompts[personality];
167
+ if (!config) {
168
+ throw new Error(`Unknown personality: ${personality}`);
169
+ }
170
+ return config;
171
  }
src/lib/repositories/agent-repository.ts CHANGED
@@ -1,7 +1,6 @@
1
  import { FileStore } from '../persistence/file-store';
2
  import { StudentAgent } from '../types/models';
3
  import { getStudentPrompt, getStudentConfig } from '../prompts/student-prompts';
4
- import { StudentPersonality } from '../types/agent';
5
 
6
  export class AgentRepository {
7
  private store: FileStore<StudentAgent>;
@@ -12,11 +11,11 @@ export class AgentRepository {
12
 
13
  async createAgent(
14
  userId: string,
15
- personality: 'adhd_inattentive' | 'adhd_hyperactive' | 'adhd_combined',
16
  name?: string,
17
  customPrompt?: string
18
  ): Promise<StudentAgent> {
19
- const config = getStudentConfig(personality as StudentPersonality);
20
  const tools = config.tools || [];
21
 
22
  const agentData = {
@@ -24,7 +23,7 @@ export class AgentRepository {
24
  personality,
25
  name: name || config.name,
26
  description: config.description,
27
- systemPrompt: customPrompt || getStudentPrompt(personality as StudentPersonality, tools),
28
  isActive: true,
29
  createdAt: new Date().toISOString(),
30
  updatedAt: new Date().toISOString(),
 
1
  import { FileStore } from '../persistence/file-store';
2
  import { StudentAgent } from '../types/models';
3
  import { getStudentPrompt, getStudentConfig } from '../prompts/student-prompts';
 
4
 
5
  export class AgentRepository {
6
  private store: FileStore<StudentAgent>;
 
11
 
12
  async createAgent(
13
  userId: string,
14
+ personality: string,
15
  name?: string,
16
  customPrompt?: string
17
  ): Promise<StudentAgent> {
18
+ const config = getStudentConfig(personality);
19
  const tools = config.tools || [];
20
 
21
  const agentData = {
 
23
  personality,
24
  name: name || config.name,
25
  description: config.description,
26
+ systemPrompt: customPrompt || getStudentPrompt(personality, tools),
27
  isActive: true,
28
  createdAt: new Date().toISOString(),
29
  updatedAt: new Date().toISOString(),
src/lib/types/agent.ts CHANGED
@@ -15,17 +15,10 @@ export enum AgentType {
15
  ASSISTANT = 'assistant' // Legacy support
16
  }
17
 
18
- export enum StudentPersonality {
19
- ADHD_INATTENTIVE = 'adhd_inattentive',
20
- ADHD_HYPERACTIVE = 'adhd_hyperactive',
21
- ADHD_COMBINED = 'adhd_combined'
22
- }
23
-
24
-
25
  export interface AgentConfig {
26
  id: string;
27
  type: AgentType;
28
- personality: StudentPersonality;
29
  name: string;
30
  description: string;
31
  systemPrompt: string;
@@ -45,7 +38,7 @@ export interface AgentInstance {
45
 
46
  export interface CreateAgentRequest {
47
  type: AgentType;
48
- personality: StudentPersonality;
49
  name?: string;
50
  customPrompt?: string;
51
  tools?: string[];
 
15
  ASSISTANT = 'assistant' // Legacy support
16
  }
17
 
 
 
 
 
 
 
 
18
  export interface AgentConfig {
19
  id: string;
20
  type: AgentType;
21
+ personality: string;
22
  name: string;
23
  description: string;
24
  systemPrompt: string;
 
38
 
39
  export interface CreateAgentRequest {
40
  type: AgentType;
41
+ personality: string;
42
  name?: string;
43
  customPrompt?: string;
44
  tools?: string[];
src/lib/types/models.ts CHANGED
@@ -9,7 +9,7 @@ export interface User {
9
  export interface StudentAgent {
10
  id: string;
11
  userId: string;
12
- personality: 'adhd_inattentive' | 'adhd_hyperactive' | 'adhd_combined';
13
  name: string;
14
  description: string;
15
  systemPrompt: string;
 
9
  export interface StudentAgent {
10
  id: string;
11
  userId: string;
12
+ personality: string;
13
  name: string;
14
  description: string;
15
  systemPrompt: string;