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.
@@ -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 **agent chat surface** wired to a mock
6
- streaming agent, ready for you to plug in your LLM. Run it and you immediately
7
- see your agent talking that's the point.
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
- npm install
12
+ # 1. Install dependencies
13
+ pnpm install
14
14
 
15
- # Start development server (HMR)
16
- npm run dev
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 with the agent. Edit the agent at `agents/chat.ts`
20
- (pick your model / add tools) the `@theokit/sdk` runtime resolves OpenRouter /
21
- Anthropic / Ollama / OpenAI from env vars (see the file's header comment).
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
- ├── app/
28
- │ ├── page.tsx # Chat surface (@theokit/ui: ChatThread, ChatComposer, …)
29
- └── layout.tsx # Root layout
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
- ├── chat.ts # Streaming agent endpoint (mockreplace with your LLM)
33
- │ └── health.ts # GET /api/health
34
- ├── tailwind.config.ts # TheoUI design tokens
35
- ├── theo.config.ts # TheoKit configuration
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
- - **Agent chat surface** `app/page.tsx` renders `@theokit/ui` chat components
42
- driven by the streaming endpoint.
43
- - **`agents/chat.ts` (`defineAgent`)** one file auto-served at `POST /api/agents/chat`,
44
- streaming the ai-sdk `UIMessageStream` wire; `useAgent('/api/agents/chat')` on the client
45
- reconstructs `UIMessage[]` you render via `message.parts`. `@theokit/sdk` owns
46
- conversation persistence and provider resolution.
47
- - **`defineAgentTool`** — declare typed tools (the template ships a
48
- `current_time` example).
49
-
50
- ## About `@theokit/sdk`
51
-
52
- `@theokit/sdk` is the agent runtime this template depends on. Its publish to the
53
- public npm registry is **operator-deferred** — if `npm install` cannot resolve
54
- it yet, scaffold the registry-free variant instead (see Bare mode below) and add
55
- the SDK once it is published.
56
-
57
- ## Bare mode (`--bare`)
58
-
59
- Want the minimal "Hello Theo" scaffold with **no** agent UI and **no** unpublished
60
- registry dependencies? Scaffold with `--bare`:
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
- npm create theokit my-app -- --template=default --bare
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
- npm run dev # Start dev server with HMR
74
- npm run build # Build for production
75
- npm run start # Run production build
76
- npm run test # Run tests (vitest)
77
- npm run lint # ESLint check
78
- npm run typecheck # TypeScript type check
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`. See
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`. See
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` + `docs/ARCHITECTURE.md` § Adding a screen).
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** — the conventional sub-folders under `agents/` (`prompts/`, `tools/`, `skills/`,
46
- `lib/`, `hooks/`, `channels/`, `connections/`, `subagents/`, `schedules/`) are **that concern, not routes**.
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:
@@ -107,7 +107,7 @@ export class TaskTools {
107
107
  }
108
108
  }
109
109
 
110
- // compõe no agente:
110
+ // compose onto the agent:
111
111
  // new ToolboxCapability(new TaskTools(db), { namespace: 'tasks' }) → tasks.list_tasks
112
112
  ```
113
113
 
@@ -91,7 +91,7 @@ export default defineConfig({
91
91
  openapi: {
92
92
  title: 'My App API',
93
93
  version: '1.0.0',
94
- outDir: 'docs/api',
94
+ outDir: '.theokit',
95
95
  },
96
96
  })
97
97
  ```
@@ -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 ../theo-ui && npm pack # produces theokit-ui-X.Y.Z.tgz
29
- cd ../my-app && npm install ../theo-ui/theokit-ui-X.Y.Z.tgz
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:../theo-ui` to install — causes dual-React (use tarball or npm registry)
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
- // Arquivos de declaração carregam as augmentações de módulo do TheoKit — `JobRegistry` em
16
- // `types/jobs.d.ts` nasce VAZIA de propósito, para o app preencher conforme cria jobs. Sem esta
17
- // exceção, um app recém-scaffoldado reprova no próprio `npm run lint` no minuto zero (#93), e a
18
- // primeira lição que o TheoKit é que o gate dele mente.
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'` em vez de desligar a regra: interface vazia é a forma canônica de
21
- // declaration merging, mas `type X = {}` continua sendo acusadoe esse ainda é um erro de
22
- // verdade, porque `{}` aceita qualquer valor não-nulo, inclusive `0` e `""`.
20
+ // `allowInterfaces: 'always'` rather than disabling the rule: an empty interface is the canonical
21
+ // form of declaration merging, but `type X = {}` is still flaggedand 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
- <!DOCTYPE html>
1
+ <!doctype html>
2
2
  <html lang="en">
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>
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.46.1",
19
- "@theokit/agents": "^7.3.1",
20
- "@theokit/sdk": "^4.0.1",
21
- "@theokit/ui": "^1.0.0",
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",