1- import React , { useState , useEffect } from 'react' ;
1+ import React , { useCallback , useEffect , useMemo , useState } from 'react' ;
22import { Activity , Brain , Zap , Target , Clock , TrendingUp } from 'lucide-react' ;
33
44interface BehaviorState {
@@ -9,9 +9,11 @@ interface BehaviorState {
99 goal : string ;
1010}
1111
12+ type BehaviorParameters = Record < string , unknown > ;
13+
1214interface BehaviorControlPanelProps {
1315 currentBehavior : string ;
14- onBehaviorChange : ( behavior : string , parameters : any ) => void ;
16+ onBehaviorChange : ( behavior : string , parameters : BehaviorParameters ) => void ;
1517}
1618
1719export default function BehaviorControlPanel ( { currentBehavior, onBehaviorChange } : BehaviorControlPanelProps ) {
@@ -24,73 +26,66 @@ export default function BehaviorControlPanel({ currentBehavior, onBehaviorChange
2426 } ) ;
2527
2628 const [ isAutoMode , setIsAutoMode ] = useState ( false ) ;
27- const [ decisionInterval , setDecisionInterval ] = useState ( 3000 ) ;
28- const [ learningRate , setLearningRate ] = useState ( 0.1 ) ;
29-
30- const behaviors = [
31- {
32- name : 'idle' ,
33- label : 'Idle' ,
34- icon : < Clock size = { 20 } /> ,
35- color : 'text-gray-400' ,
36- description : 'Basic standby loop' ,
37- parameters : { idleTime : 5000 , breathing : true }
38- } ,
39- {
40- name : 'greeting' ,
41- label : 'Greet' ,
42- icon : < Target size = { 20 } /> ,
43- color : 'text-green-400' ,
44- description : 'Friendly wave & smile' ,
45- parameters : { wave : true , smile : true , duration : 3000 }
46- } ,
47- {
48- name : 'listening' ,
49- label : 'Listen' ,
50- icon : < Brain size = { 20 } /> ,
51- color : 'text-blue-400' ,
52- description : 'Active attention focus' ,
53- parameters : { headNod : true , eyeContact : true , attention : 0.9 }
54- } ,
55- {
56- name : 'thinking' ,
57- label : 'Think' ,
58- icon : < Activity size = { 20 } /> ,
59- color : 'text-yellow-400' ,
60- description : 'Processing animation' ,
61- parameters : { headTilt : true , pause : true , processing : true }
62- } ,
63- {
64- name : 'speaking' ,
65- label : 'Speak' ,
66- icon : < TrendingUp size = { 20 } /> ,
67- color : 'text-purple-400' ,
68- description : 'Active conversation' ,
69- parameters : { mouthMove : true , gestures : true , emphasis : 0.8 }
70- } ,
71- {
72- name : 'excited' ,
73- label : 'Excite' ,
74- icon : < Zap size = { 20 } /> ,
75- color : 'text-orange-400' ,
76- description : 'High energy state' ,
77- parameters : { energy : 0.9 , movement : true , animation : 'bounce' }
78- }
79- ] ;
80-
81- // Auto Decision Mock
82- useEffect ( ( ) => {
83- if ( ! isAutoMode ) return ;
84- const interval = setInterval ( ( ) => {
85- makeAutoDecision ( ) ;
86- } , decisionInterval ) ;
87- return ( ) => clearInterval ( interval ) ;
88- } , [ isAutoMode , decisionInterval ] ) ;
29+ const decisionInterval = 3000 ;
30+
31+ const behaviors = useMemo (
32+ ( ) => [
33+ {
34+ name : 'idle' ,
35+ label : 'Idle' ,
36+ icon : < Clock size = { 20 } /> ,
37+ color : 'text-gray-400' ,
38+ description : 'Basic standby loop' ,
39+ parameters : { idleTime : 5000 , breathing : true } ,
40+ } ,
41+ {
42+ name : 'greeting' ,
43+ label : 'Greet' ,
44+ icon : < Target size = { 20 } /> ,
45+ color : 'text-green-400' ,
46+ description : 'Friendly wave & smile' ,
47+ parameters : { wave : true , smile : true , duration : 3000 } ,
48+ } ,
49+ {
50+ name : 'listening' ,
51+ label : 'Listen' ,
52+ icon : < Brain size = { 20 } /> ,
53+ color : 'text-blue-400' ,
54+ description : 'Active attention focus' ,
55+ parameters : { headNod : true , eyeContact : true , attention : 0.9 } ,
56+ } ,
57+ {
58+ name : 'thinking' ,
59+ label : 'Think' ,
60+ icon : < Activity size = { 20 } /> ,
61+ color : 'text-yellow-400' ,
62+ description : 'Processing animation' ,
63+ parameters : { headTilt : true , pause : true , processing : true } ,
64+ } ,
65+ {
66+ name : 'speaking' ,
67+ label : 'Speak' ,
68+ icon : < TrendingUp size = { 20 } /> ,
69+ color : 'text-purple-400' ,
70+ description : 'Active conversation' ,
71+ parameters : { mouthMove : true , gestures : true , emphasis : 0.8 } ,
72+ } ,
73+ {
74+ name : 'excited' ,
75+ label : 'Excite' ,
76+ icon : < Zap size = { 20 } /> ,
77+ color : 'text-orange-400' ,
78+ description : 'High energy state' ,
79+ parameters : { energy : 0.9 , movement : true , animation : 'bounce' } ,
80+ } ,
81+ ] ,
82+ [ ]
83+ ) ;
8984
90- const makeAutoDecision = ( ) => {
85+ const makeAutoDecision = useCallback ( ( ) => {
9186 const now = new Date ( ) ;
9287 let newBehavior = 'idle' ;
93- let newParameters = { } ;
88+ let newParameters : BehaviorParameters = { } ;
9489 let newConfidence = 0.7 ;
9590
9691 if ( Math . random ( ) > 0.7 ) {
@@ -113,9 +108,18 @@ export default function BehaviorControlPanel({ currentBehavior, onBehaviorChange
113108 } ) ;
114109
115110 onBehaviorChange ( newBehavior , newParameters ) ;
116- } ;
111+ } , [ behaviors , onBehaviorChange ] ) ;
112+
113+ // Auto Decision Mock
114+ useEffect ( ( ) => {
115+ if ( ! isAutoMode ) return ;
116+ const interval = setInterval ( ( ) => {
117+ makeAutoDecision ( ) ;
118+ } , decisionInterval ) ;
119+ return ( ) => clearInterval ( interval ) ;
120+ } , [ decisionInterval , isAutoMode , makeAutoDecision ] ) ;
117121
118- const handleBehaviorClick = ( behaviorName : string , parameters : any ) => {
122+ const handleBehaviorClick = ( behaviorName : string , parameters : BehaviorParameters ) => {
119123 const behavior = behaviors . find ( b => b . name === behaviorName ) ;
120124 if ( ! behavior ) return ;
121125
0 commit comments