create-theokit 1.0.5 → 1.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-theokit",
3
- "version": "1.0.5",
3
+ "version": "1.0.6",
4
4
  "type": "module",
5
5
  "description": "Scaffold a new TheoKit project",
6
6
  "license": "Apache-2.0",
@@ -2,9 +2,17 @@
2
2
 
3
3
  import { useState, useEffect, useCallback, useRef, type FormEvent } from 'react'
4
4
 
5
- interface Task { id: number; title: string; priority: 'high' | 'medium' | 'low'; done: boolean }
5
+ interface Task {
6
+ id: number
7
+ title: string
8
+ priority: 'high' | 'medium' | 'low'
9
+ done: boolean
10
+ }
6
11
  type Role = '' | 'user' | 'admin'
7
- interface ChatMsg { role: 'user' | 'agent' | 'tool' | 'system' | 'error'; text: string }
12
+ interface ChatMsg {
13
+ role: 'user' | 'agent' | 'tool' | 'system' | 'error'
14
+ text: string
15
+ }
8
16
 
9
17
  export default function Page() {
10
18
  const [tasks, setTasks] = useState<Task[]>([])
@@ -12,7 +20,9 @@ export default function Page() {
12
20
  const [title, setTitle] = useState('')
13
21
  const [priority, setPriority] = useState<Task['priority']>('medium')
14
22
  const [formError, setFormError] = useState('')
15
- const [chat, setChat] = useState<ChatMsg[]>([{ role: 'system', text: 'Ask me to list, create, or complete tasks...' }])
23
+ const [chat, setChat] = useState<ChatMsg[]>([
24
+ { role: 'system', text: 'Ask me to list, create, or complete tasks...' },
25
+ ])
16
26
  const [chatInput, setChatInput] = useState('')
17
27
  const [chatBusy, setChatBusy] = useState(false)
18
28
  const chatRef = useRef<HTMLDivElement>(null)
@@ -28,15 +38,28 @@ export default function Page() {
28
38
  if (res.ok) setTasks(await res.json())
29
39
  }, [])
30
40
 
31
- useEffect(() => { loadTasks() }, [loadTasks])
41
+ useEffect(() => {
42
+ loadTasks()
43
+ }, [loadTasks])
32
44
 
33
45
  const createTask = async (e: FormEvent) => {
34
46
  e.preventDefault()
35
47
  setFormError('')
36
48
  if (!title.trim()) return
37
- const res = await fetch('/api/tasks', { method: 'POST', headers: hdrs(), body: JSON.stringify({ title, priority }) })
38
- if (res.status === 403) { setFormError('403 — Need User role'); return }
39
- if (!res.ok) { const b = await res.json(); setFormError(b.error?.issues?.[0]?.message ?? `Error ${res.status}`); return }
49
+ const res = await fetch('/api/tasks', {
50
+ method: 'POST',
51
+ headers: hdrs(),
52
+ body: JSON.stringify({ title, priority }),
53
+ })
54
+ if (res.status === 403) {
55
+ setFormError('403 — Need User role')
56
+ return
57
+ }
58
+ if (!res.ok) {
59
+ const b = await res.json()
60
+ setFormError(b.error?.issues?.[0]?.message ?? `Error ${res.status}`)
61
+ return
62
+ }
40
63
  setTitle('')
41
64
  loadTasks()
42
65
  }
@@ -45,42 +68,60 @@ export default function Page() {
45
68
  const msg = chatInput.trim()
46
69
  if (!msg || chatBusy) return
47
70
  setChatInput('')
48
- setChat(c => [...c, { role: 'user', text: msg }])
71
+ setChat((c) => [...c, { role: 'user', text: msg }])
49
72
  setChatBusy(true)
50
73
  try {
51
74
  const res = await fetch('/api/agents/assistant/chat', {
52
- method: 'POST', headers: hdrs(),
75
+ method: 'POST',
76
+ headers: hdrs(),
53
77
  body: JSON.stringify({ message: msg, sessionId: 'session-' + Date.now() }),
54
78
  })
55
- if (res.status === 403) { setChat(c => [...c, { role: 'error', text: '403 — Need User role' }]); return }
79
+ if (res.status === 403) {
80
+ setChat((c) => [...c, { role: 'error', text: '403 — Need User role' }])
81
+ return
82
+ }
56
83
  const reader = res.body?.getReader()
57
84
  if (!reader) return
58
85
  const decoder = new TextDecoder()
59
- let buf = '', agentText = ''
86
+ let buf = '',
87
+ agentText = ''
60
88
  while (true) {
61
89
  const { done, value } = await reader.read()
62
90
  if (done) break
63
91
  buf += decoder.decode(value, { stream: true })
64
- const lines = buf.split('\n'); buf = lines.pop() ?? ''
92
+ const lines = buf.split('\n')
93
+ buf = lines.pop() ?? ''
65
94
  for (const line of lines) {
66
95
  if (!line.startsWith('data: ')) continue
67
96
  try {
68
97
  const ev = JSON.parse(line.slice(6))
69
98
  if (ev.type === 'text_delta') agentText += ev.content
70
- else if (ev.type === 'tool_call') setChat(c => [...c, { role: 'tool', text: `🔧 ${ev.toolName}` }])
71
- else if (ev.type === 'tool_result') setChat(c => [...c, { role: 'tool', text: `✅ ${(ev.output ?? '').slice(0, 80)}` }])
72
- else if (ev.type === 'error') setChat(c => [...c, { role: 'error', text: ev.message }])
73
- } catch { /* partial */ }
99
+ else if (ev.type === 'tool_call')
100
+ setChat((c) => [...c, { role: 'tool', text: `🔧 ${ev.toolName}` }])
101
+ else if (ev.type === 'tool_result')
102
+ setChat((c) => [...c, { role: 'tool', text: `✅ ${(ev.output ?? '').slice(0, 80)}` }])
103
+ else if (ev.type === 'error')
104
+ setChat((c) => [...c, { role: 'error', text: ev.message }])
105
+ } catch {
106
+ /* partial */
107
+ }
74
108
  }
75
109
  }
76
- if (agentText) setChat(c => [...c, { role: 'agent', text: agentText }])
110
+ if (agentText) setChat((c) => [...c, { role: 'agent', text: agentText }])
77
111
  loadTasks()
78
112
  } catch (err) {
79
- setChat(c => [...c, { role: 'error', text: `Error: ${err instanceof Error ? err.message : String(err)}` }])
80
- } finally { setChatBusy(false) }
113
+ setChat((c) => [
114
+ ...c,
115
+ { role: 'error', text: `Error: ${err instanceof Error ? err.message : String(err)}` },
116
+ ])
117
+ } finally {
118
+ setChatBusy(false)
119
+ }
81
120
  }
82
121
 
83
- useEffect(() => { chatRef.current?.scrollTo(0, chatRef.current.scrollHeight) }, [chat])
122
+ useEffect(() => {
123
+ chatRef.current?.scrollTo(0, chatRef.current.scrollHeight)
124
+ }, [chat])
84
125
 
85
126
  return (
86
127
  <div className="page">
@@ -91,10 +132,20 @@ export default function Page() {
91
132
  <h1>TheoKit</h1>
92
133
  <p className="tagline">Build the app your agent lives in.</p>
93
134
  <nav className="ctas">
94
- <a href="https://usetheo.dev" target="_blank" rel="noopener noreferrer" className="btn primary">
135
+ <a
136
+ href="https://usetheo.dev"
137
+ target="_blank"
138
+ rel="noopener noreferrer"
139
+ className="btn primary"
140
+ >
95
141
  Get Started
96
142
  </a>
97
- <a href="https://github.com/usetheodev/theokit" target="_blank" rel="noopener noreferrer" className="btn secondary">
143
+ <a
144
+ href="https://github.com/usetheodev/theokit"
145
+ target="_blank"
146
+ rel="noopener noreferrer"
147
+ className="btn secondary"
148
+ >
98
149
  Documentation
99
150
  </a>
100
151
  </nav>
@@ -106,7 +157,7 @@ export default function Page() {
106
157
  {/* Role */}
107
158
  <div className="role-bar">
108
159
  <label htmlFor="role">Role:</label>
109
- <select id="role" value={role} onChange={e => setRole(e.target.value as Role)}>
160
+ <select id="role" value={role} onChange={(e) => setRole(e.target.value as Role)}>
110
161
  <option value="">None (public)</option>
111
162
  <option value="user">User</option>
112
163
  <option value="admin">Admin</option>
@@ -116,22 +167,44 @@ export default function Page() {
116
167
  {/* Content */}
117
168
  <div className="grid">
118
169
  <section className="card">
119
- <h2>Tasks <span className="badge">@Controller</span></h2>
170
+ <h2>
171
+ Tasks <span className="badge">@Controller</span>
172
+ </h2>
120
173
  <table>
121
- <thead><tr><th>Task</th><th>Priority</th><th>Status</th></tr></thead>
174
+ <thead>
175
+ <tr>
176
+ <th>Task</th>
177
+ <th>Priority</th>
178
+ <th>Status</th>
179
+ </tr>
180
+ </thead>
122
181
  <tbody>
123
- {tasks.map(t => (
182
+ {tasks.map((t) => (
124
183
  <tr key={t.id} className={t.done ? 'done' : ''}>
125
- <td>{t.done ? '✅ ' : '○ '}{t.title}</td>
126
- <td><span className={`prio prio-${t.priority}`}>{t.priority}</span></td>
184
+ <td>
185
+ {t.done ? '✅ ' : '○ '}
186
+ {t.title}
187
+ </td>
188
+ <td>
189
+ <span className={`prio prio-${t.priority}`}>{t.priority}</span>
190
+ </td>
127
191
  <td>{t.done ? 'Done' : 'To do'}</td>
128
192
  </tr>
129
193
  ))}
130
194
  </tbody>
131
195
  </table>
132
196
  <form onSubmit={createTask} className="create-bar">
133
- <input value={title} onChange={e => setTitle(e.target.value)} placeholder="New task..." required minLength={3} />
134
- <select value={priority} onChange={e => setPriority(e.target.value as Task['priority'])}>
197
+ <input
198
+ value={title}
199
+ onChange={(e) => setTitle(e.target.value)}
200
+ placeholder="New task..."
201
+ required
202
+ minLength={3}
203
+ />
204
+ <select
205
+ value={priority}
206
+ onChange={(e) => setPriority(e.target.value as Task['priority'])}
207
+ >
135
208
  <option value="medium">Medium</option>
136
209
  <option value="high">High</option>
137
210
  <option value="low">Low</option>
@@ -142,26 +215,45 @@ export default function Page() {
142
215
  </section>
143
216
 
144
217
  <section className="card">
145
- <h2>AI Assistant <span className="badge badge-ai">@Agent + SSE</span></h2>
218
+ <h2>
219
+ AI Assistant <span className="badge badge-ai">@Agent + SSE</span>
220
+ </h2>
146
221
  <div ref={chatRef} className="chat-box">
147
222
  {chat.map((m, i) => (
148
- <div key={i} className={`msg ${m.role}`}>{m.role === 'user' ? `You: ${m.text}` : m.text}</div>
223
+ <div key={i} className={`msg ${m.role}`}>
224
+ {m.role === 'user' ? `You: ${m.text}` : m.text}
225
+ </div>
149
226
  ))}
150
227
  </div>
151
228
  <div className="chat-bar">
152
- <input value={chatInput} onChange={e => setChatInput(e.target.value)} onKeyDown={e => e.key === 'Enter' && sendChat()} placeholder="Message the AI assistant..." disabled={chatBusy} />
153
- <button type="button" onClick={sendChat} disabled={chatBusy}>Send</button>
229
+ <input
230
+ value={chatInput}
231
+ onChange={(e) => setChatInput(e.target.value)}
232
+ onKeyDown={(e) => e.key === 'Enter' && sendChat()}
233
+ placeholder="Message the AI assistant..."
234
+ disabled={chatBusy}
235
+ />
236
+ <button type="button" onClick={sendChat} disabled={chatBusy}>
237
+ Send
238
+ </button>
154
239
  </div>
155
240
  </section>
156
241
  </div>
157
242
 
158
243
  {/* Footer */}
159
244
  <footer className="footer">
160
- Powered by <a href="https://usetheo.dev" target="_blank" rel="noopener noreferrer">TheoKit</a>
245
+ Powered by{' '}
246
+ <a href="https://usetheo.dev" target="_blank" rel="noopener noreferrer">
247
+ TheoKit
248
+ </a>
161
249
  {' · '}
162
- <a href="https://github.com/usetheodev/theokit" target="_blank" rel="noopener noreferrer">GitHub</a>
250
+ <a href="https://github.com/usetheodev/theokit" target="_blank" rel="noopener noreferrer">
251
+ GitHub
252
+ </a>
163
253
  {' · '}
164
- <a href="https://discord.usetheo.dev" target="_blank" rel="noopener noreferrer">Discord</a>
254
+ <a href="https://discord.usetheo.dev" target="_blank" rel="noopener noreferrer">
255
+ Discord
256
+ </a>
165
257
  </footer>
166
258
  </div>
167
259
  </div>
@@ -14,7 +14,7 @@
14
14
  "typecheck": "tsc --noEmit"
15
15
  },
16
16
  "dependencies": {
17
- "theokit": "^0.5.3",
17
+ "theokit": "^0.5.4",
18
18
  "react": "^19.0.0",
19
19
  "react-dom": "^19.0.0",
20
20
  "react-router": "^7.0.0",