create-theokit 1.23.7 → 1.23.10
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 +117 -96
- package/dist/cli.js.map +1 -1
- package/package.json +11 -1
- package/templates/default/.env.example +1 -1
- package/templates/default/CLAUDE.md +1 -0
- package/templates/default/README.md.tmpl +87 -50
- package/templates/default/_gitignore +5 -2
- package/templates/default/agents/chat.ts +30 -3
- package/templates/default/app/components/ChatPanel.tsx +3 -2
- package/templates/default/app/components/Nav.tsx +1 -2
- package/templates/default/app/hooks/use-transcript.ts +9 -3
- package/templates/default/app/layout.tsx +8 -1
- package/templates/default/app/lib/constants.ts +2 -1
- package/templates/default/app/lib/renderable.ts +78 -0
- package/templates/default/app/page.test.tsx +9 -3
- package/templates/default/app/page.tsx +1 -1
- package/templates/default/docs/ARCHITECTURE.md +6 -2
- package/templates/default/dot-claude/rules/theokit-conventions.md +2 -0
- 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-gateways/SKILL.md +71 -0
- package/templates/default/dot-claude/skills/theokit-routes/SKILL.md +21 -2
- 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 +5 -11
- package/templates/default/pnpm-workspace.yaml +21 -0
- package/templates/default/public/index.html +430 -63
- package/templates/default/server/routes/health.ts +3 -0
- package/templates/default/types/jobs.d.ts +0 -1
- package/templates/surfaces/desktop/sidecar/sidecar.ts +6 -2
- package/templates/surfaces/tui/tui/main.tsx.tmpl +12 -8
|
@@ -17,6 +17,7 @@ import { z } from 'zod'
|
|
|
17
17
|
|
|
18
18
|
// GET handler — no body, optional params/query
|
|
19
19
|
export const GET = defineRoute({
|
|
20
|
+
policy: 'public', // who may call it — required
|
|
20
21
|
params: z.object({ id: z.coerce.number() }), // URL params
|
|
21
22
|
query: z.object({ page: z.coerce.number().optional() }), // Query string
|
|
22
23
|
handler: ({ params, query }) => {
|
|
@@ -26,6 +27,7 @@ export const GET = defineRoute({
|
|
|
26
27
|
|
|
27
28
|
// POST handler — with body validation + custom status
|
|
28
29
|
export const POST = defineRoute({
|
|
30
|
+
policy: ({ subject }) => subject !== null, // any authenticated caller
|
|
29
31
|
body: z.object({
|
|
30
32
|
title: z.string().min(3),
|
|
31
33
|
done: z.boolean().default(false),
|
|
@@ -38,10 +40,26 @@ export const POST = defineRoute({
|
|
|
38
40
|
})
|
|
39
41
|
|
|
40
42
|
// PUT, DELETE follow the same pattern
|
|
41
|
-
export const PUT = defineRoute({ body: z.object({...}), handler: ({body, params}) => {...} })
|
|
42
|
-
export const DELETE = defineRoute({ params: z.object({id: z.coerce.number()}), handler: ({params}) => {...} })
|
|
43
|
+
export const PUT = defineRoute({ policy: 'public', body: z.object({...}), handler: ({body, params}) => {...} })
|
|
44
|
+
export const DELETE = defineRoute({ policy: 'public', params: z.object({id: z.coerce.number()}), handler: ({params}) => {...} })
|
|
43
45
|
```
|
|
44
46
|
|
|
47
|
+
## policy — who may call this route
|
|
48
|
+
|
|
49
|
+
Required on every exported method. The scanner refuses a route file that omits it and names the
|
|
50
|
+
file, so absence is a build error rather than a route silently open to everyone.
|
|
51
|
+
|
|
52
|
+
```typescript
|
|
53
|
+
policy: 'public' // open, and said out loud
|
|
54
|
+
policy: ({ subject }) => subject !== null // any authenticated caller
|
|
55
|
+
policy: ({ subject, params }) =>
|
|
56
|
+
requireOwner(subject, ownerOf(params.id)) // this subject owns this record
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
`requireOwner` comes from `theokit/server`. The policy is evaluated identically over HTTP and
|
|
60
|
+
in-process, so a desktop or terminal surface gets the same answer a browser does. It receives no
|
|
61
|
+
headers and no cookies: identity arrives as `subject`, established by the transport.
|
|
62
|
+
|
|
45
63
|
## File-to-URL Mapping
|
|
46
64
|
|
|
47
65
|
| File path | URL | Notes |
|
|
@@ -71,6 +89,7 @@ export const createTask = defineAction({
|
|
|
71
89
|
import { TheoError } from 'theokit'
|
|
72
90
|
|
|
73
91
|
export const GET = defineRoute({
|
|
92
|
+
policy: 'public',
|
|
74
93
|
handler: ({ params }) => {
|
|
75
94
|
const task = db.select().from(tasks).where(eq(tasks.id, params.id)).get()
|
|
76
95
|
if (!task) throw new TheoError({ code: 'NOT_FOUND', message: 'Task not found' })
|
|
@@ -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>
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
"dev": "theokit dev",
|
|
8
8
|
"build": "theokit build",
|
|
9
9
|
"start": "theokit start",
|
|
10
|
+
"preview": "theokit preview",
|
|
10
11
|
"test": "vitest run",
|
|
11
12
|
"lint": "eslint .",
|
|
12
13
|
"lint:fix": "eslint . --fix",
|
|
@@ -15,10 +16,10 @@
|
|
|
15
16
|
"typecheck": "tsc --noEmit"
|
|
16
17
|
},
|
|
17
18
|
"dependencies": {
|
|
18
|
-
"theokit": "^0.
|
|
19
|
-
"@theokit/agents": "^
|
|
20
|
-
"@theokit/sdk": "^4.
|
|
21
|
-
"@theokit/ui": "^1.
|
|
19
|
+
"theokit": "^0.50.0",
|
|
20
|
+
"@theokit/agents": "^10.1.0",
|
|
21
|
+
"@theokit/sdk": "^4.52.1",
|
|
22
|
+
"@theokit/ui": "^1.1.0",
|
|
22
23
|
"@usetheo/ui": "^0.26.0",
|
|
23
24
|
"lucide-react": "^0.469.0",
|
|
24
25
|
"react": "^19.0.0",
|
|
@@ -40,12 +41,5 @@
|
|
|
40
41
|
"typescript": "^5.5.0",
|
|
41
42
|
"typescript-eslint": "^8.0.0",
|
|
42
43
|
"vitest": "^3.0.0"
|
|
43
|
-
},
|
|
44
|
-
"pnpm": {
|
|
45
|
-
"onlyBuiltDependencies": [
|
|
46
|
-
"esbuild",
|
|
47
|
-
"better-sqlite3",
|
|
48
|
-
"workerd"
|
|
49
|
-
]
|
|
50
44
|
}
|
|
51
45
|
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Build scripts this project allows its dependencies to run.
|
|
2
|
+
#
|
|
3
|
+
# pnpm 10 refuses to run a dependency's install script unless it is approved here,
|
|
4
|
+
# and it stopped reading the `pnpm` field in package.json — where this list used to
|
|
5
|
+
# live, silently doing nothing while every install printed a warning about it
|
|
6
|
+
# (usetheokit/theokit#397). Without these entries, `pnpm install` ends in
|
|
7
|
+
# ERR_PNPM_IGNORED_BUILDS with esbuild and node-pty unbuilt.
|
|
8
|
+
#
|
|
9
|
+
# Each entry is a decision, not boilerplate: an install script runs arbitrary code
|
|
10
|
+
# on your machine. These are the ones this scaffold needs.
|
|
11
|
+
allowBuilds:
|
|
12
|
+
# The bundler behind `theokit dev` and `theokit build`; ships a platform binary.
|
|
13
|
+
esbuild: true
|
|
14
|
+
# A native terminal, reached through @theokit/agents. Compiles or downloads a
|
|
15
|
+
# prebuild on install. A web-only app never opens one — see usetheokit/theokit#25
|
|
16
|
+
# if you would rather not pay for it.
|
|
17
|
+
node-pty: true
|
|
18
|
+
# Present only if you add them; harmless entries otherwise, and here so the
|
|
19
|
+
# decision is already made the day you do.
|
|
20
|
+
better-sqlite3: true
|
|
21
|
+
workerd: true
|