1
1
import { Plus , Trash , WandSparkles } from 'lucide-solid'
2
- import { Component , createMemo , createSignal , Index , onMount , Show } from 'solid-js'
2
+ import {
3
+ Component ,
4
+ createEffect ,
5
+ createMemo ,
6
+ createSignal ,
7
+ Index ,
8
+ on ,
9
+ onMount ,
10
+ Show ,
11
+ } from 'solid-js'
3
12
import Button from './Button'
4
13
import { FormLabel } from './FormLabel'
5
14
import TextInput from './TextInput'
@@ -8,6 +17,7 @@ import { formatCharacter } from '/common/characters'
8
17
import { AppSchema } from '/common/types'
9
18
import { CharEditor } from '../pages/Character/editor'
10
19
import { SetStoreFunction } from 'solid-js/store'
20
+ import { createDebounce } from './util'
11
21
12
22
type Attr = { key : string ; values : string }
13
23
@@ -34,13 +44,58 @@ const PersonaAttributes: Component<{
34
44
const [ tokens , setTokens ] = createSignal ( 0 )
35
45
36
46
onMount ( ( ) => {
37
- updateCount ( )
47
+ countTokens ( )
38
48
} )
39
49
50
+ createEffect (
51
+ on (
52
+ ( ) => props . state ,
53
+ ( attrs ) => {
54
+ if ( ! attrs . length ) return
55
+ if ( tokens ( ) ) return
56
+
57
+ countTokens ( )
58
+ }
59
+ )
60
+ )
61
+
62
+ createEffect (
63
+ on (
64
+ ( ) => props . schema ,
65
+ ( kind , prev ) => {
66
+ // Convert the attributes to a text blob if switching from text -> attrs
67
+ if ( prev !== 'text' && kind === 'text' ) {
68
+ let squished : string [ ] = [ ]
69
+ for ( const { key, values } of props . state ) {
70
+ squished . push ( `${ key } :\n${ values } ` )
71
+ }
72
+
73
+ props . setter ( [ { key : 'text' , values : squished . join ( '\n\n' ) } ] . concat ( props . state ) )
74
+ }
75
+
76
+ // If we switch from text -> attrs, omit the 'text' attribute if it is the squished version from above
77
+ if ( kind !== 'text' && prev === 'text' ) {
78
+ const text = props . state . find ( ( s ) => s . key === 'text' )
79
+ if ( ! text ) return
80
+
81
+ let matching = true
82
+ for ( const { values } of props . state ) {
83
+ if ( ! text . values . includes ( values ) ) matching = false
84
+ break
85
+ }
86
+
87
+ if ( matching ) {
88
+ props . setter ( props . state . filter ( ( s ) => s . key !== 'text' ) )
89
+ }
90
+ }
91
+ }
92
+ )
93
+ )
94
+
40
95
const plainText = createMemo ( ( ) => props . schema === 'text' )
41
96
42
97
const updateCount = async ( ) => {
43
- if ( ! props . tokenCount || ! props . form ) return
98
+ if ( ! props . tokenCount ) return
44
99
const attributes = fromAttrs ( props . state )
45
100
46
101
const encoder = await getEncoder ( )
@@ -57,6 +112,8 @@ const PersonaAttributes: Component<{
57
112
}
58
113
}
59
114
115
+ const [ countTokens ] = createDebounce ( updateCount , 1000 )
116
+
60
117
const add = ( ) => {
61
118
const next = props . state . concat ( { key : '' , values : '' } )
62
119
props . setter ( next )
@@ -75,6 +132,7 @@ const PersonaAttributes: Component<{
75
132
76
133
const next = props . state . map ( ( a , i ) => ( i === index ? upd : a ) )
77
134
props . setter ( next )
135
+ countTokens ( )
78
136
}
79
137
80
138
return (
0 commit comments