create-theokit 1.18.0 → 1.19.0
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
|
@@ -24,6 +24,18 @@ import { streamAgentTurnInProcess } from 'theokit/server/agent'
|
|
|
24
24
|
|
|
25
25
|
import * as chatAgent from '../agents/chat.js'
|
|
26
26
|
import { AGENT } from '../shared/agent.js'
|
|
27
|
+
// Everything visual (accent, banner wordmark + copy, spinner words, placeholder) lives in ONE file —
|
|
28
|
+
// edit `tui/theme.ts` to restyle; this component never needs touching for a rebrand.
|
|
29
|
+
import {
|
|
30
|
+
ACCENT,
|
|
31
|
+
BANNER_TIPS,
|
|
32
|
+
BANNER_WHATS_NEW,
|
|
33
|
+
LOGO,
|
|
34
|
+
PLACEHOLDER,
|
|
35
|
+
THEME,
|
|
36
|
+
THINKING_PHRASES,
|
|
37
|
+
WIDE_COLS,
|
|
38
|
+
} from './theme.js'
|
|
27
39
|
|
|
28
40
|
/** Shown in the status bar (from `shared/agent.ts`). */
|
|
29
41
|
const MODEL = AGENT.model
|
|
@@ -32,32 +44,6 @@ const CWD = process.cwd().replace(homedir(), '~')
|
|
|
32
44
|
/** Compact token count for the footer: `128000 → 128k`, `12300 → 12.3k`, `462 → 462`. */
|
|
33
45
|
const fmtK = (n: number): string =>
|
|
34
46
|
n >= 1000 ? `${(Math.round(n / 100) / 10).toString().replace(/\.0$/, '')}k` : `${n}`
|
|
35
|
-
/** Claude Code's warm accent (truecolor; degrades gracefully on 256-color terminals). */
|
|
36
|
-
const ACCENT = '#d97757'
|
|
37
|
-
/** The "Theo" wordmark (figlet ANSI-Shadow, block glyphs — single-width, renders everywhere). */
|
|
38
|
-
const THEO_LOGO = [
|
|
39
|
-
'████████╗██╗ ██╗███████╗ ██████╗',
|
|
40
|
-
'╚══██╔══╝██║ ██║██╔════╝██╔═══██╗',
|
|
41
|
-
' ██║ ███████║█████╗ ██║ ██║',
|
|
42
|
-
' ██║ ██╔══██║██╔══╝ ██║ ██║',
|
|
43
|
-
' ██║ ██║ ██║███████╗╚██████╔╝',
|
|
44
|
-
' ╚═╝ ╚═╝ ╚═╝╚══════╝ ╚═════╝ ',
|
|
45
|
-
].join('\n')
|
|
46
|
-
/** Below this column count the welcome box collapses to a single column (the two-column aside needs room). */
|
|
47
|
-
const WIDE_COLS = 90
|
|
48
|
-
/** Whimsical status words cycled while the agent thinks (Claude Code idiom — the ✻ spinner rotates these). */
|
|
49
|
-
const THINKING_PHRASES = [
|
|
50
|
-
'Thinking',
|
|
51
|
-
'Pondering',
|
|
52
|
-
'Noodling',
|
|
53
|
-
'Percolating',
|
|
54
|
-
'Baking',
|
|
55
|
-
'Brewing',
|
|
56
|
-
'Simmering',
|
|
57
|
-
'Conjuring',
|
|
58
|
-
'Musing',
|
|
59
|
-
'Marinating',
|
|
60
|
-
] as const
|
|
61
47
|
|
|
62
48
|
/** The agent's opening line — a short warm intro; the banner already carries the how-to tips. */
|
|
63
49
|
const GREETING: UIMessageLike = {
|
|
@@ -110,7 +96,7 @@ function Banner(): ReactElement {
|
|
|
110
96
|
{/* Fixed-width left column (fits the 34-wide wordmark) so a long cwd truncates instead of pushing
|
|
111
97
|
the right column off-screen — the box stays full width, the content stays grouped on the left. */}
|
|
112
98
|
<Box flexDirection="column" width={38} flexShrink={0}>
|
|
113
|
-
<Text color={ACCENT}>{
|
|
99
|
+
<Text color={ACCENT}>{LOGO}</Text>
|
|
114
100
|
<Box marginTop={1} flexDirection="column">
|
|
115
101
|
<Text color={ACCENT} bold wrap="truncate-end">
|
|
116
102
|
✻ Welcome to {APP_NAME}
|
|
@@ -129,16 +115,22 @@ function Banner(): ReactElement {
|
|
|
129
115
|
Tips for getting started
|
|
130
116
|
</Text>
|
|
131
117
|
<Box marginTop={1} flexDirection="column">
|
|
132
|
-
|
|
133
|
-
|
|
118
|
+
{BANNER_TIPS.map((tip) => (
|
|
119
|
+
<Text key={tip} dimColor>
|
|
120
|
+
{tip}
|
|
121
|
+
</Text>
|
|
122
|
+
))}
|
|
134
123
|
</Box>
|
|
135
124
|
<Box marginTop={1} flexDirection="column">
|
|
136
125
|
<Text color={ACCENT} bold>
|
|
137
126
|
What's new
|
|
138
127
|
</Text>
|
|
139
128
|
<Box marginTop={1} flexDirection="column">
|
|
140
|
-
|
|
141
|
-
|
|
129
|
+
{BANNER_WHATS_NEW.map((line) => (
|
|
130
|
+
<Text key={line} dimColor>
|
|
131
|
+
{line}
|
|
132
|
+
</Text>
|
|
133
|
+
))}
|
|
142
134
|
</Box>
|
|
143
135
|
</Box>
|
|
144
136
|
</Box>
|
|
@@ -217,7 +209,7 @@ export function App(): ReactElement {
|
|
|
217
209
|
}
|
|
218
210
|
|
|
219
211
|
return (
|
|
220
|
-
<TheoTUIProvider theme={
|
|
212
|
+
<TheoTUIProvider theme={THEME}>
|
|
221
213
|
{/* InkInputProvider bridges Ink's stdin to @theokit/tui's interactive surfaces (ApprovalPrompt's
|
|
222
214
|
choice bar) so they receive keys under plain Ink — the ChatComposer keeps using Ink's own hooks. */}
|
|
223
215
|
<InkInputProvider>
|
|
@@ -255,7 +247,7 @@ export function App(): ReactElement {
|
|
|
255
247
|
</ApprovalPrompt>
|
|
256
248
|
) : (
|
|
257
249
|
<ChatComposer
|
|
258
|
-
placeholder=
|
|
250
|
+
placeholder={PLACEHOLDER}
|
|
259
251
|
bordered
|
|
260
252
|
hint={exitArmed ? 'Press Ctrl+C again to quit' : undefined}
|
|
261
253
|
commands={[
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ════════════════════════════════════════════════════════════════════════════════════════════════
|
|
3
|
+
* tui/theme.ts — the ONE place to restyle your terminal UI.
|
|
4
|
+
*
|
|
5
|
+
* Everything visual lives here: the accent color, the welcome-banner wordmark + copy, the "thinking"
|
|
6
|
+
* words, and the input placeholder. Edit this file to rebrand — `tui/App.tsx` reads from it and never
|
|
7
|
+
* needs touching for a restyle.
|
|
8
|
+
* ════════════════════════════════════════════════════════════════════════════════════════════════
|
|
9
|
+
*/
|
|
10
|
+
import type { TheoThemeProp } from '@theokit/tui'
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* The accent color — used for the banner, the `✻`/`⏺` markers, the box borders, and the `>` prompt.
|
|
14
|
+
* Any Ink color: a name (`'cyan'`, `'green'`, `'magenta'`) or a hex (`'#d97757'`, truecolor).
|
|
15
|
+
*/
|
|
16
|
+
export const ACCENT = '#d97757'
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* The global `@theokit/tui` theme applied by `<TheoTUIProvider>`. Partial-merge: override only what you
|
|
20
|
+
* pass — everything else inherits the base theme. Uncomment a block below to restyle the bullets:
|
|
21
|
+
*
|
|
22
|
+
* role: { assistant: { glyph: '▸ ' } }, // the assistant message bullet
|
|
23
|
+
* toolStatus: { success: { glyph: '◆' }, failed: { glyph: '✗' } }, // per-status tool bullets
|
|
24
|
+
*/
|
|
25
|
+
export const THEME: TheoThemeProp = {
|
|
26
|
+
base: 'dark', // 'dark' · 'light' · 'no-color'
|
|
27
|
+
override: {
|
|
28
|
+
accent: ACCENT,
|
|
29
|
+
// role: { assistant: { glyph: '⏺ ' } },
|
|
30
|
+
// toolStatus: { pending: { glyph: '○' }, success: { glyph: '●' }, failed: { glyph: '✗' } },
|
|
31
|
+
},
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* The wordmark at the top of the welcome banner (ASCII art). Swap it for your own — generate one with
|
|
36
|
+
* `npx figlet -f "ANSI Shadow" "YourApp"` — or set it to `''` to hide it. Use single-width glyphs so it
|
|
37
|
+
* renders on every terminal.
|
|
38
|
+
*/
|
|
39
|
+
export const LOGO = [
|
|
40
|
+
'████████╗██╗ ██╗███████╗ ██████╗',
|
|
41
|
+
'╚══██╔══╝██║ ██║██╔════╝██╔═══██╗',
|
|
42
|
+
' ██║ ███████║█████╗ ██║ ██║',
|
|
43
|
+
' ██║ ██╔══██║██╔══╝ ██║ ██║',
|
|
44
|
+
' ██║ ██║ ██║███████╗╚██████╔╝',
|
|
45
|
+
' ╚═╝ ╚═╝ ╚═╝╚══════╝ ╚═════╝ ',
|
|
46
|
+
].join('\n')
|
|
47
|
+
|
|
48
|
+
/** The welcome banner's right column (shown on wide terminals). One string per line. */
|
|
49
|
+
export const BANNER_TIPS = [
|
|
50
|
+
'Ask me anything — I stream a reply',
|
|
51
|
+
'/help · @ mention a file · esc interrupts',
|
|
52
|
+
]
|
|
53
|
+
export const BANNER_WHATS_NEW = ['Human-in-the-loop approvals', 'Live token usage in the footer']
|
|
54
|
+
|
|
55
|
+
/** Whimsical words the "thinking" spinner cycles through while the agent works. */
|
|
56
|
+
export const THINKING_PHRASES = [
|
|
57
|
+
'Thinking',
|
|
58
|
+
'Pondering',
|
|
59
|
+
'Noodling',
|
|
60
|
+
'Percolating',
|
|
61
|
+
'Baking',
|
|
62
|
+
'Brewing',
|
|
63
|
+
'Simmering',
|
|
64
|
+
'Conjuring',
|
|
65
|
+
'Musing',
|
|
66
|
+
'Marinating',
|
|
67
|
+
]
|
|
68
|
+
|
|
69
|
+
/** The dim placeholder shown in the empty input box. */
|
|
70
|
+
export const PLACEHOLDER = 'Ask {{name}} anything…'
|
|
71
|
+
|
|
72
|
+
/** Below this terminal width the welcome banner collapses from two columns to one. */
|
|
73
|
+
export const WIDE_COLS = 90
|