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.
Files changed (34) hide show
  1. package/LICENSE +2 -2
  2. package/README.md +68 -0
  3. package/dist/cli.js +117 -96
  4. package/dist/cli.js.map +1 -1
  5. package/package.json +11 -1
  6. package/templates/default/.env.example +1 -1
  7. package/templates/default/CLAUDE.md +1 -0
  8. package/templates/default/README.md.tmpl +87 -50
  9. package/templates/default/_gitignore +5 -2
  10. package/templates/default/agents/chat.ts +30 -3
  11. package/templates/default/app/components/ChatPanel.tsx +3 -2
  12. package/templates/default/app/components/Nav.tsx +1 -2
  13. package/templates/default/app/hooks/use-transcript.ts +9 -3
  14. package/templates/default/app/layout.tsx +8 -1
  15. package/templates/default/app/lib/constants.ts +2 -1
  16. package/templates/default/app/lib/renderable.ts +78 -0
  17. package/templates/default/app/page.test.tsx +9 -3
  18. package/templates/default/app/page.tsx +1 -1
  19. package/templates/default/docs/ARCHITECTURE.md +6 -2
  20. package/templates/default/dot-claude/rules/theokit-conventions.md +2 -0
  21. package/templates/default/dot-claude/skills/theokit-agents/SKILL.md +1 -1
  22. package/templates/default/dot-claude/skills/theokit-config/SKILL.md +1 -1
  23. package/templates/default/dot-claude/skills/theokit-gateways/SKILL.md +71 -0
  24. package/templates/default/dot-claude/skills/theokit-routes/SKILL.md +21 -2
  25. package/templates/default/dot-claude/skills/theokit-ui/SKILL.md +3 -3
  26. package/templates/default/eslint.config.mjs +7 -7
  27. package/templates/default/index.html +11 -11
  28. package/templates/default/package.json.tmpl +5 -11
  29. package/templates/default/pnpm-workspace.yaml +21 -0
  30. package/templates/default/public/index.html +430 -63
  31. package/templates/default/server/routes/health.ts +3 -0
  32. package/templates/default/types/jobs.d.ts +0 -1
  33. package/templates/surfaces/desktop/sidecar/sidecar.ts +6 -2
  34. 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 ../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 dá é 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 acusado — e 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 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
- <!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>
@@ -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.46.1",
19
- "@theokit/agents": "^7.3.1",
20
- "@theokit/sdk": "^4.0.1",
21
- "@theokit/ui": "^1.0.0",
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