create-theokit 1.0.5 → 1.0.7

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.7",
4
4
  "type": "module",
5
5
  "description": "Scaffold a new TheoKit project",
6
6
  "license": "Apache-2.0",
@@ -220,6 +220,7 @@ code, pre { font-family: var(--font-mono); }
220
220
  border: 1px solid var(--border);
221
221
  border-radius: 12px;
222
222
  padding: 24px;
223
+ width: 100%;
223
224
  }
224
225
 
225
226
  .card h2 {
@@ -314,6 +315,41 @@ tr.done td { opacity: 0.4; text-decoration: line-through; }
314
315
  }
315
316
  .chat-bar input:focus { border-color: var(--accent); }
316
317
 
318
+ /* ─── Features grid ─────────────────────────────────── */
319
+
320
+ .features {
321
+ margin-top: 32px;
322
+ }
323
+
324
+ .feature {
325
+ padding: 20px;
326
+ border: 1px solid var(--border);
327
+ border-radius: 12px;
328
+ background: var(--card);
329
+ }
330
+
331
+ .feature h3 {
332
+ font-size: 14px;
333
+ font-weight: 600;
334
+ margin-bottom: 6px;
335
+ font-family: var(--font-mono);
336
+ color: var(--accent);
337
+ }
338
+
339
+ .feature p {
340
+ font-size: 13px;
341
+ line-height: 1.5;
342
+ color: var(--text-secondary);
343
+ }
344
+
345
+ .feature code {
346
+ background: var(--bg);
347
+ border: 1px solid var(--border);
348
+ padding: 1px 5px;
349
+ border-radius: 4px;
350
+ font-size: 12px;
351
+ }
352
+
317
353
  /* ─── Footer ────────────────────────────────────────── */
318
354
 
319
355
  .footer {
@@ -1,10 +1,9 @@
1
1
  'use client'
2
2
 
3
- import { useState, useEffect, useCallback, useRef, type FormEvent } from 'react'
3
+ import { useState, useEffect, useCallback, type FormEvent } from 'react'
4
4
 
5
5
  interface Task { id: number; title: string; priority: 'high' | 'medium' | 'low'; done: boolean }
6
6
  type Role = '' | 'user' | 'admin'
7
- interface ChatMsg { role: 'user' | 'agent' | 'tool' | 'system' | 'error'; text: string }
8
7
 
9
8
  export default function Page() {
10
9
  const [tasks, setTasks] = useState<Task[]>([])
@@ -12,10 +11,6 @@ export default function Page() {
12
11
  const [title, setTitle] = useState('')
13
12
  const [priority, setPriority] = useState<Task['priority']>('medium')
14
13
  const [formError, setFormError] = useState('')
15
- const [chat, setChat] = useState<ChatMsg[]>([{ role: 'system', text: 'Ask me to list, create, or complete tasks...' }])
16
- const [chatInput, setChatInput] = useState('')
17
- const [chatBusy, setChatBusy] = useState(false)
18
- const chatRef = useRef<HTMLDivElement>(null)
19
14
 
20
15
  const hdrs = useCallback((): Record<string, string> => {
21
16
  const h: Record<string, string> = { 'Content-Type': 'application/json' }
@@ -41,47 +36,6 @@ export default function Page() {
41
36
  loadTasks()
42
37
  }
43
38
 
44
- const sendChat = async () => {
45
- const msg = chatInput.trim()
46
- if (!msg || chatBusy) return
47
- setChatInput('')
48
- setChat(c => [...c, { role: 'user', text: msg }])
49
- setChatBusy(true)
50
- try {
51
- const res = await fetch('/api/agents/assistant/chat', {
52
- method: 'POST', headers: hdrs(),
53
- body: JSON.stringify({ message: msg, sessionId: 'session-' + Date.now() }),
54
- })
55
- if (res.status === 403) { setChat(c => [...c, { role: 'error', text: '403 — Need User role' }]); return }
56
- const reader = res.body?.getReader()
57
- if (!reader) return
58
- const decoder = new TextDecoder()
59
- let buf = '', agentText = ''
60
- while (true) {
61
- const { done, value } = await reader.read()
62
- if (done) break
63
- buf += decoder.decode(value, { stream: true })
64
- const lines = buf.split('\n'); buf = lines.pop() ?? ''
65
- for (const line of lines) {
66
- if (!line.startsWith('data: ')) continue
67
- try {
68
- const ev = JSON.parse(line.slice(6))
69
- 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 */ }
74
- }
75
- }
76
- if (agentText) setChat(c => [...c, { role: 'agent', text: agentText }])
77
- loadTasks()
78
- } catch (err) {
79
- setChat(c => [...c, { role: 'error', text: `Error: ${err instanceof Error ? err.message : String(err)}` }])
80
- } finally { setChatBusy(false) }
81
- }
82
-
83
- useEffect(() => { chatRef.current?.scrollTo(0, chatRef.current.scrollHeight) }, [chat])
84
-
85
39
  return (
86
40
  <div className="page">
87
41
  <div className="main">
@@ -99,7 +53,7 @@ export default function Page() {
99
53
  </a>
100
54
  </nav>
101
55
  <p className="hint">
102
- Edit <code>app/page.tsx</code> to get started.
56
+ Edit <code>app/page.tsx</code> to get started. Changes hot-reload instantly.
103
57
  </p>
104
58
  </header>
105
59
 
@@ -113,46 +67,51 @@ export default function Page() {
113
67
  </select>
114
68
  </div>
115
69
 
116
- {/* Content */}
117
- <div className="grid">
118
- <section className="card">
119
- <h2>Tasks <span className="badge">@Controller</span></h2>
120
- <table>
121
- <thead><tr><th>Task</th><th>Priority</th><th>Status</th></tr></thead>
122
- <tbody>
123
- {tasks.map(t => (
124
- <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>
127
- <td>{t.done ? 'Done' : 'To do'}</td>
128
- </tr>
129
- ))}
130
- </tbody>
131
- </table>
132
- <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'])}>
135
- <option value="medium">Medium</option>
136
- <option value="high">High</option>
137
- <option value="low">Low</option>
138
- </select>
139
- <button type="submit">Add</button>
140
- </form>
141
- {formError && <p className="error">{formError}</p>}
142
- </section>
143
-
144
- <section className="card">
145
- <h2>AI Assistant <span className="badge badge-ai">@Agent + SSE</span></h2>
146
- <div ref={chatRef} className="chat-box">
147
- {chat.map((m, i) => (
148
- <div key={i} className={`msg ${m.role}`}>{m.role === 'user' ? `You: ${m.text}` : m.text}</div>
70
+ {/* Tasks */}
71
+ <section className="card">
72
+ <h2>Tasks <span className="badge">@Controller</span></h2>
73
+ <table>
74
+ <thead><tr><th>Task</th><th>Priority</th><th>Status</th></tr></thead>
75
+ <tbody>
76
+ {tasks.map(t => (
77
+ <tr key={t.id} className={t.done ? 'done' : ''}>
78
+ <td>{t.done ? '' : ''}{t.title}</td>
79
+ <td><span className={`prio prio-${t.priority}`}>{t.priority}</span></td>
80
+ <td>{t.done ? 'Done' : 'To do'}</td>
81
+ </tr>
149
82
  ))}
150
- </div>
151
- <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>
154
- </div>
155
- </section>
83
+ </tbody>
84
+ </table>
85
+ <form onSubmit={createTask} className="create-bar">
86
+ <input value={title} onChange={e => setTitle(e.target.value)} placeholder="New task..." required minLength={3} />
87
+ <select value={priority} onChange={e => setPriority(e.target.value as Task['priority'])}>
88
+ <option value="medium">Medium</option>
89
+ <option value="high">High</option>
90
+ <option value="low">Low</option>
91
+ </select>
92
+ <button type="submit">Add</button>
93
+ </form>
94
+ {formError && <p className="error">{formError}</p>}
95
+ </section>
96
+
97
+ {/* Features */}
98
+ <div className="grid features">
99
+ <div className="feature">
100
+ <h3>@Controller</h3>
101
+ <p>NestJS-style decorators with convention naming. <code>TasksController</code> → <code>/api/tasks</code></p>
102
+ </div>
103
+ <div className="feature">
104
+ <h3>defineRoute</h3>
105
+ <p>Typed API routes with Zod validation. See <code>server/routes/health.ts</code></p>
106
+ </div>
107
+ <div className="feature">
108
+ <h3>@Agent + @Tool</h3>
109
+ <p>AI agents with SSE streaming, budget control, and human-in-the-loop approval.</p>
110
+ </div>
111
+ <div className="feature">
112
+ <h3>React + Vite</h3>
113
+ <p>File-based routing, HMR, SSR streaming. Edit and see changes instantly.</p>
114
+ </div>
156
115
  </div>
157
116
 
158
117
  {/* Footer */}
@@ -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",