1
1
import { useCallback , useContext } from 'react' ;
2
- import { useRecoilValue } from 'recoil' ;
2
+ import { useRecoilState , useRecoilValue } from 'recoil' ;
3
3
import { v4 as uuidv4 } from 'uuid' ;
4
4
5
5
import {
@@ -8,31 +8,68 @@ import {
8
8
IStep ,
9
9
useAuth ,
10
10
useChatData ,
11
- useChatInteract
11
+ useChatInteract ,
12
+ commandsState ,
13
+ toggleCommandsState
12
14
} from '@chainlit/react-client' ;
13
15
16
+ import Icon from '@/components/Icon' ;
14
17
import { Button } from '@/components/ui/button' ;
15
18
16
- import { persistentCommandState } from '@/state/chat' ;
19
+ import { IToggleable , persistentCommandState , toggleableStates } from '@/state/chat' ;
17
20
18
21
interface StarterProps {
19
22
starter : IStarter ;
20
23
}
21
24
22
25
export default function Starter ( { starter } : StarterProps ) {
23
26
const apiClient = useContext ( ChainlitContext ) ;
24
- const selectedCommand = useRecoilValue ( persistentCommandState ) ;
27
+ const [ selectedCommand , setSelectedCommand ] = useRecoilState ( persistentCommandState ) ;
28
+ const [ toggleables , setToggleables ] = useRecoilState ( toggleableStates ) ;
25
29
const { sendMessage } = useChatInteract ( ) ;
26
30
const { loading, connected } = useChatData ( ) ;
27
31
const { user } = useAuth ( ) ;
32
+ const commands = useRecoilValue ( commandsState ) ;
33
+ const toggleCommands = useRecoilValue ( toggleCommandsState ) ;
28
34
29
35
const disabled = loading || ! connected ;
30
36
31
37
const onSubmit = useCallback ( async ( ) => {
38
+ // 处理命令激活
39
+ if ( starter . commands && starter . commands . length > 0 ) {
40
+ const commandToActivate = commands . find ( cmd => cmd . id === starter . commands ! [ 0 ] ) ;
41
+ if ( commandToActivate ) {
42
+ setSelectedCommand ( commandToActivate ) ;
43
+ }
44
+ }
45
+
46
+ // 处理可切换命令激活
47
+ if ( starter . toggle_commands && starter . toggle_commands . length > 0 ) {
48
+ const newToggleables : IToggleable [ ] = [ ...toggleables ] ;
49
+
50
+ // 移除所有非持久的toggleables
51
+ const persistentOnly = newToggleables . filter ( t => t . persistent ) ;
52
+
53
+ // 添加starter中指定的toggle_commands
54
+ starter . toggle_commands . forEach ( cmdId => {
55
+ const toggleCmd = toggleCommands . find ( cmd => cmd . id === cmdId ) ;
56
+ if ( toggleCmd ) {
57
+ persistentOnly . push ( {
58
+ id : toggleCmd . id ,
59
+ active : true ,
60
+ persistent : toggleCmd . persistent
61
+ } ) ;
62
+ }
63
+ } ) ;
64
+
65
+ setToggleables ( persistentOnly ) ;
66
+ }
67
+
32
68
const message : IStep = {
33
69
threadId : '' ,
34
70
id : uuidv4 ( ) ,
35
- command : selectedCommand ?. id ,
71
+ command : starter . commands && starter . commands . length > 0 ? starter . commands [ 0 ] : selectedCommand ?. id ,
72
+ toggleables : starter . toggle_commands || [ ] ,
36
73
name : user ?. identifier || 'User' ,
37
74
type : 'user_message' ,
38
75
output : starter . message ,
@@ -41,7 +78,15 @@ export default function Starter({ starter }: StarterProps) {
41
78
} ;
42
79
43
80
sendMessage ( message , [ ] ) ;
44
- } , [ user , selectedCommand , sendMessage , starter ] ) ;
81
+ } , [ user , selectedCommand , toggleables , commands , toggleCommands , sendMessage , starter , setSelectedCommand , setToggleables ] ) ;
82
+
83
+ // 检查是否是图片URL
84
+ const isImageUrl = ( url : string ) : boolean => {
85
+ return url . startsWith ( 'http' ) ||
86
+ url . startsWith ( '/' ) ||
87
+ url . startsWith ( './' ) ||
88
+ url . startsWith ( '../' ) ;
89
+ } ;
45
90
46
91
return (
47
92
< Button
@@ -53,15 +98,19 @@ export default function Starter({ starter }: StarterProps) {
53
98
>
54
99
< div className = "flex gap-2" >
55
100
{ starter . icon ? (
56
- < img
57
- className = "h-5 w-5 rounded-md"
58
- src = {
59
- starter . icon ?. startsWith ( '/public' )
60
- ? apiClient . buildEndpoint ( starter . icon )
61
- : starter . icon
62
- }
63
- alt = { starter . label }
64
- />
101
+ isImageUrl ( starter . icon ) ? (
102
+ < img
103
+ className = "h-5 w-5 rounded-md"
104
+ src = {
105
+ starter . icon ?. startsWith ( '/public' )
106
+ ? apiClient . buildEndpoint ( starter . icon )
107
+ : starter . icon
108
+ }
109
+ alt = { starter . label }
110
+ />
111
+ ) : (
112
+ < Icon name = { starter . icon } className = "!h-5 !w-5" />
113
+ )
65
114
) : null }
66
115
< p className = "text-sm text-muted-foreground truncate" >
67
116
{ starter . label }
0 commit comments