create-theokit 1.23.7 → 1.23.8
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/LICENSE +2 -2
- package/README.md +68 -0
- package/dist/cli.js +72 -58
- package/dist/cli.js.map +1 -1
- package/package.json +10 -1
- package/templates/default/README.md.tmpl +87 -50
- package/templates/default/agents/chat.ts +1 -2
- package/templates/default/app/components/Nav.tsx +1 -2
- package/templates/default/app/page.tsx +1 -1
- package/templates/default/docs/ARCHITECTURE.md +6 -2
- package/templates/default/dot-claude/skills/theokit-agents/SKILL.md +1 -1
- package/templates/default/dot-claude/skills/theokit-config/SKILL.md +1 -1
- package/templates/default/dot-claude/skills/theokit-ui/SKILL.md +3 -3
- package/templates/default/eslint.config.mjs +7 -7
- package/templates/default/index.html +11 -11
- package/templates/default/package.json.tmpl +4 -4
- package/templates/default/public/index.html +430 -63
- package/templates/default/types/jobs.d.ts +0 -1
- package/templates/surfaces/tui/tui/main.tsx.tmpl +12 -8
|
@@ -2,78 +2,115 @@
|
|
|
2
2
|
|
|
3
3
|
Built with [TheoKit](https://theokit.dev) — **Build the app your agent lives in.**
|
|
4
4
|
|
|
5
|
-
This is the default template: a working
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
This is the default template: a **working agent chat**, end to end. The thread
|
|
6
|
+
streams real replies, the tools really run, and the approval prompt really gates
|
|
7
|
+
the side-effecting one. Run it and you are talking to your agent.
|
|
8
8
|
|
|
9
9
|
## Getting Started
|
|
10
10
|
|
|
11
11
|
```bash
|
|
12
|
-
# Install dependencies
|
|
13
|
-
|
|
12
|
+
# 1. Install dependencies
|
|
13
|
+
pnpm install
|
|
14
14
|
|
|
15
|
-
#
|
|
16
|
-
|
|
15
|
+
# 2. Point the agent at a provider (OpenRouter, Anthropic, or OpenAI)
|
|
16
|
+
cp .env.example .env && $EDITOR .env
|
|
17
|
+
|
|
18
|
+
# 3. Start the dev server (HMR)
|
|
19
|
+
pnpm dev
|
|
17
20
|
```
|
|
18
21
|
|
|
19
|
-
Open the app and chat
|
|
20
|
-
|
|
21
|
-
|
|
22
|
+
Open the app and chat. Edit `agents/chat.ts` to change the model, add tools, or
|
|
23
|
+
swap the persona — `@theokit/sdk` is the runtime and resolves the provider from
|
|
24
|
+
your environment.
|
|
22
25
|
|
|
23
26
|
## Project Structure
|
|
24
27
|
|
|
25
28
|
```
|
|
26
29
|
{{name}}/
|
|
27
|
-
├──
|
|
28
|
-
│ ├──
|
|
29
|
-
│
|
|
30
|
+
├── agents/ # The agent, and what composes it
|
|
31
|
+
│ ├── chat.ts # the agent → POST /api/agents/chat
|
|
32
|
+
│ ├── prompts/ # system prompts / personas
|
|
33
|
+
│ ├── tools/ # tools the agent can call (weather, current-time, …)
|
|
34
|
+
│ └── skills/ # procedures the model loads on demand
|
|
35
|
+
├── app/ # Frontend — file-based routing
|
|
36
|
+
│ ├── page.tsx # the `/` route — composition root
|
|
37
|
+
│ ├── layout.tsx # root layout
|
|
38
|
+
│ ├── components/ # presentational UI
|
|
39
|
+
│ ├── hooks/ # custom hooks — where state lives
|
|
40
|
+
│ └── lib/ # app modules / config
|
|
30
41
|
├── server/
|
|
31
|
-
│ └── routes/
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
├──
|
|
35
|
-
|
|
36
|
-
└── .env.example # Environment variables
|
|
42
|
+
│ └── routes/health.ts # GET /api/health
|
|
43
|
+
├── shared/agent.ts # Branding (name, model, greeting) — one source of truth
|
|
44
|
+
├── docs/ # ARCHITECTURE · CUSTOMIZATION · ENVIRONMENT
|
|
45
|
+
├── theo.config.ts # TheoKit configuration
|
|
46
|
+
└── .env.example # Environment variables
|
|
37
47
|
```
|
|
38
48
|
|
|
39
49
|
## Key Concepts
|
|
40
50
|
|
|
41
|
-
- **
|
|
42
|
-
|
|
43
|
-
- **`
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
51
|
+
- **An agent is a file.** `agents/chat.ts` is served at `POST /api/agents/chat` —
|
|
52
|
+
nothing to register. Add a second agent as another `agents/<name>.ts`.
|
|
53
|
+
- **`AgentBuilder`** is the authoring surface. The chain accumulates type-state, so
|
|
54
|
+
`.build()` without `.model()` is a compile error, not a runtime surprise:
|
|
55
|
+
|
|
56
|
+
```ts
|
|
57
|
+
export default AgentBuilder.create()
|
|
58
|
+
.input(z.object({ message: z.string() }))
|
|
59
|
+
.model('openai/gpt-4o-mini')
|
|
60
|
+
.system(BASE_INSTRUCTIONS)
|
|
61
|
+
.tool(weatherTool)
|
|
62
|
+
.approval('send_notification', { question: 'Send this notification?' })
|
|
63
|
+
.skills([dailyBriefingSkill])
|
|
64
|
+
.build()
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
- **A tool is a file too** — `tool('name').describe(…).input(z.object({…})).execute(…).build()`.
|
|
68
|
+
Pure metadata plus a handler; it never calls an LLM.
|
|
69
|
+
- **The sub-folders under `agents/` are semantic, not routes.** `prompts/`, `tools/`,
|
|
70
|
+
`skills/` and friends are skipped by the scanner, so `agents/tools/weather.ts`
|
|
71
|
+
never becomes a phantom `/api/agents/tools/weather` endpoint.
|
|
72
|
+
- **`useAgent`** binds the client to the agent and hands you the transcript:
|
|
73
|
+
`const { thread, send, status, reset, error } = useAgent('/api/agents/chat')`.
|
|
74
|
+
- **Human-in-the-loop.** `.approval(tool, …)` pauses the run before that tool and
|
|
75
|
+
asks. Ask the agent to "notify me that …" to see it.
|
|
76
|
+
- **Styling is wired for you.** Tailwind v4 and `@theokit/ui` are detected and
|
|
77
|
+
configured by the framework — there is no `tailwind.config.ts` to maintain.
|
|
78
|
+
|
|
79
|
+
Deeper detail lives in [`docs/ARCHITECTURE.md`](./docs/ARCHITECTURE.md);
|
|
80
|
+
customization and environment variables have their own pages beside it.
|
|
81
|
+
|
|
82
|
+
## Adding a screen
|
|
83
|
+
|
|
84
|
+
Routing is file-based: a screen is a folder under `app/` with a `page.tsx`.
|
|
85
|
+
|
|
86
|
+
| You want | Create | Serves |
|
|
87
|
+
|---|---|---|
|
|
88
|
+
| a `/settings` screen | `app/settings/page.tsx` | `/settings` |
|
|
89
|
+
| a nested screen | `app/settings/billing/page.tsx` | `/settings/billing` |
|
|
90
|
+
| a dynamic screen | `app/users/[id]/page.tsx` | `/users/:id` |
|
|
91
|
+
|
|
92
|
+
Or run `theokit generate page settings`, then link it from `app/components/Nav.tsx`.
|
|
93
|
+
|
|
94
|
+
## Other scaffolds
|
|
95
|
+
|
|
96
|
+
The same agent runs behind a terminal or desktop frontend — only the transport
|
|
97
|
+
changes. Scaffold them with `--surface=tui` (Ink) or `--surface=desktop` (Tauri).
|
|
98
|
+
|
|
99
|
+
Want the opposite — a plain app with no agent and no `@theokit/*` runtime
|
|
100
|
+
dependencies? Scaffold with `--bare`: a Hello Theo page and the same clean
|
|
101
|
+
structure to grow into.
|
|
61
102
|
|
|
62
103
|
```bash
|
|
63
|
-
|
|
104
|
+
npx create-theokit my-app --bare
|
|
64
105
|
```
|
|
65
106
|
|
|
66
|
-
`--bare` strips `@theokit/ui`, `@theokit/sdk`, `lucide-react`, and the Tailwind
|
|
67
|
-
toolchain, replaces `app/page.tsx` with a plain "Hello Theo" page, and removes
|
|
68
|
-
the mock chat route — a scaffold that always installs without registry access.
|
|
69
|
-
|
|
70
107
|
## Commands
|
|
71
108
|
|
|
72
109
|
```bash
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
110
|
+
pnpm dev # Start dev server with HMR
|
|
111
|
+
pnpm build # Build for production
|
|
112
|
+
pnpm start # Run the production build
|
|
113
|
+
pnpm test # Run tests (vitest)
|
|
114
|
+
pnpm lint # ESLint check
|
|
115
|
+
pnpm typecheck # TypeScript type check
|
|
79
116
|
```
|
|
@@ -12,8 +12,7 @@ import { weatherTool } from './tools/weather.js'
|
|
|
12
12
|
* agent; it composes its neighbours under `agents/`: the persona in `prompts/`, capabilities in `tools/`,
|
|
13
13
|
* procedures in `skills/`. Those folders are that concern, NOT extra routes — the framework's scanner
|
|
14
14
|
* treats `prompts/ tools/ skills/ lib/ …` as semantic folders, so `agents/tools/weather.ts` never becomes
|
|
15
|
-
* a `/api/agents/tools/weather` endpoint. Add a second agent as another `agents/<name>.ts`.
|
|
16
|
-
* `docs/ARCHITECTURE.md`.
|
|
15
|
+
* a `/api/agents/tools/weather` endpoint. Add a second agent as another `agents/<name>.ts`.
|
|
17
16
|
*
|
|
18
17
|
* `@theokit/sdk` runs the agent; conversation turns auto-persist per session. Provider is resolved from
|
|
19
18
|
* the environment — OPENROUTER_API_KEY (preferred) OR ANTHROPIC_API_KEY / OPENAI_API_KEY; the model id is
|
|
@@ -4,8 +4,7 @@ import { Link } from 'theokit/client'
|
|
|
4
4
|
/**
|
|
5
5
|
* The primary navigation menu. Add one entry per screen you add under `app/` (a screen is a folder with a
|
|
6
6
|
* `page.tsx` — `app/settings/page.tsx` → `/settings`). Uses TheoKit's `Link` (react-router's Link + route
|
|
7
|
-
* prefetch on hover/focus) and computes the active route from `useLocation`.
|
|
8
|
-
* `docs/ARCHITECTURE.md` § Adding a screen.
|
|
7
|
+
* prefetch on hover/focus) and computes the active route from `useLocation`.
|
|
9
8
|
*/
|
|
10
9
|
const LINKS = [
|
|
11
10
|
{ to: '/', label: 'Chat', exact: true },
|
|
@@ -17,7 +17,7 @@ import { useChatTranscript } from './hooks/use-transcript'
|
|
|
17
17
|
* Add a SCREEN: routing is file-based — a screen is a folder under `app/` with a `page.tsx`
|
|
18
18
|
* (`app/settings/page.tsx` → `/settings`; `app/users/[id]/page.tsx` → `/users/:id`). Run
|
|
19
19
|
* `theokit generate page <name>`, then add a link in `app/components/Nav.tsx`. This route is `/` (see the
|
|
20
|
-
* example `app/about/page.tsx`
|
|
20
|
+
* example `app/about/page.tsx`).
|
|
21
21
|
*/
|
|
22
22
|
export default function Page() {
|
|
23
23
|
const [composerValue, setComposerValue] = useState('')
|
|
@@ -42,12 +42,16 @@ folders it composes (prompts, tools, skills) live together under `agents/`, with
|
|
|
42
42
|
## Clean names, no phantom routes
|
|
43
43
|
|
|
44
44
|
An agent is a file: `agents/<name>.ts` → `POST /api/agents/<name>`. But the framework's scanner is
|
|
45
|
-
**folder-semantic** —
|
|
46
|
-
`lib/`, `hooks/`, `channels/`, `connections/`, `subagents/`, `schedules
|
|
45
|
+
**folder-semantic** — thirteen sub-folder names under `agents/` (`tools/`, `skills/`, `prompts/`,
|
|
46
|
+
`lib/`, `hooks/`, `channels/`, `connections/`, `subagents/`, `schedules/`, `sandbox/`, `workflows/`,
|
|
47
|
+
`evals/`, `memory/`) are **that concern, not routes**.
|
|
47
48
|
So the names stay clean (`tools/`, not `_tools/`) and `agents/tools/weather.ts` never becomes a phantom
|
|
48
49
|
`/api/agents/tools/weather` endpoint. Markdown (`skills/*.md`) is never scanned either way. The
|
|
49
50
|
prompts/tools/skills are **shared** across every agent in `agents/`.
|
|
50
51
|
|
|
52
|
+
An agent that outgrows one file becomes a folder that co-locates its own composition —
|
|
53
|
+
`agents/<name>/index.ts` with `tools/` and `prompts/` beside it. Same route, same identity.
|
|
54
|
+
|
|
51
55
|
## Composition
|
|
52
56
|
|
|
53
57
|
`agents/chat.ts` is thin on purpose — it wires the pieces together:
|
|
@@ -25,8 +25,8 @@ paths:
|
|
|
25
25
|
npm install @theokit/ui
|
|
26
26
|
|
|
27
27
|
# Or from local tarball (when using source repo)
|
|
28
|
-
cd ../
|
|
29
|
-
cd ../my-app && npm install ../
|
|
28
|
+
cd ../theokit-ui && npm pack # produces theokit-ui-X.Y.Z.tgz
|
|
29
|
+
cd ../my-app && npm install ../theokit-ui/theokit-ui-X.Y.Z.tgz
|
|
30
30
|
```
|
|
31
31
|
|
|
32
32
|
**WARNING: NEVER use `npm link ../theo-ui` or `file:../theo-ui`.** The symlink exposes the sibling's nested `node_modules/react` (typically a different version), causing dual-React: "React Element from an older version" errors, broken hooks (`useState` null), and silent render failures. `resolve.dedupe` in Vite does NOT fix this — the pnpm structure physically has two React copies. Use tarball (`npm pack` → `npm install .tgz`) instead.
|
|
@@ -160,6 +160,6 @@ const myTheme = defineTheme({
|
|
|
160
160
|
- NEVER build a custom markdown renderer — `ChatMessageContent` handles it (including streaming partial fences)
|
|
161
161
|
- NEVER build a custom code highlighter — `CodeBlock` (from `@usetheo/ui`) uses shiki (lazy-loaded)
|
|
162
162
|
- Import AI-agent-surface components (ChatThread, ChatMessage, ToolCallCard, etc.) from `@theokit/ui`; import generic primitives (Button, Input, CodeBlock, PageShell, Sidebar, Avatar, Alert) from `@usetheo/ui` — both are live packages since the 2026-07-03 pivot (`@theokit/ui` depends on `@usetheo/ui`)
|
|
163
|
-
- NEVER use `npm link` or `file:../
|
|
163
|
+
- NEVER use `npm link` or `file:../theokit-ui` to install — causes dual-React (use tarball or npm registry)
|
|
164
164
|
- NEVER install ALL peer deps — only install the peers for components you actually use
|
|
165
165
|
- NEVER use components without wrapping in `TheoUIProvider` + `ThemeProvider` first
|
|
@@ -12,14 +12,14 @@ export default tseslint.config(
|
|
|
12
12
|
},
|
|
13
13
|
},
|
|
14
14
|
{
|
|
15
|
-
//
|
|
16
|
-
//
|
|
17
|
-
//
|
|
18
|
-
//
|
|
15
|
+
// Declaration files carry TheoKit's module augmentations — `JobRegistry` in `types/jobs.d.ts`
|
|
16
|
+
// is born EMPTY on purpose, for the app to fill in as it creates jobs. Without this exception, a
|
|
17
|
+
// freshly scaffolded app fails its own `npm run lint` at minute zero (#93), and the first lesson
|
|
18
|
+
// TheoKit teaches is that its gate lies.
|
|
19
19
|
//
|
|
20
|
-
// `allowInterfaces: 'always'`
|
|
21
|
-
// declaration merging,
|
|
22
|
-
//
|
|
20
|
+
// `allowInterfaces: 'always'` rather than disabling the rule: an empty interface is the canonical
|
|
21
|
+
// form of declaration merging, but `type X = {}` is still flagged — and that one is a real error,
|
|
22
|
+
// because `{}` accepts any non-null value, including `0` and `""`.
|
|
23
23
|
files: ['**/*.d.ts'],
|
|
24
24
|
rules: {
|
|
25
25
|
'@typescript-eslint/no-empty-object-type': ['error', { allowInterfaces: 'always' }],
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
<!
|
|
1
|
+
<!doctype html>
|
|
2
2
|
<html lang="en">
|
|
3
|
-
<head>
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
</head>
|
|
10
|
-
<body>
|
|
11
|
-
|
|
12
|
-
</body>
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
6
|
+
<title>TheoKit App</title>
|
|
7
|
+
<meta name="description" content="Built with TheoKit — the app your agent lives in" />
|
|
8
|
+
<link rel="icon" href="/favicon.svg" />
|
|
9
|
+
</head>
|
|
10
|
+
<body>
|
|
11
|
+
<div id="root"></div>
|
|
12
|
+
</body>
|
|
13
13
|
</html>
|
|
@@ -15,10 +15,10 @@
|
|
|
15
15
|
"typecheck": "tsc --noEmit"
|
|
16
16
|
},
|
|
17
17
|
"dependencies": {
|
|
18
|
-
"theokit": "^0.
|
|
19
|
-
"@theokit/agents": "^
|
|
20
|
-
"@theokit/sdk": "^4.
|
|
21
|
-
"@theokit/ui": "^1.
|
|
18
|
+
"theokit": "^0.48.3",
|
|
19
|
+
"@theokit/agents": "^10.1.0",
|
|
20
|
+
"@theokit/sdk": "^4.52.1",
|
|
21
|
+
"@theokit/ui": "^1.1.0",
|
|
22
22
|
"@usetheo/ui": "^0.26.0",
|
|
23
23
|
"lucide-react": "^0.469.0",
|
|
24
24
|
"react": "^19.0.0",
|