@agent-native/core 0.4.2 → 0.4.3

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 (254) hide show
  1. package/dist/agent/production-agent.d.ts.map +1 -1
  2. package/dist/agent/production-agent.js +9 -3
  3. package/dist/agent/production-agent.js.map +1 -1
  4. package/dist/agent/types.d.ts +2 -0
  5. package/dist/agent/types.d.ts.map +1 -1
  6. package/dist/application-state/emitter.d.ts +10 -0
  7. package/dist/application-state/emitter.d.ts.map +1 -0
  8. package/dist/application-state/emitter.js +18 -0
  9. package/dist/application-state/emitter.js.map +1 -0
  10. package/dist/application-state/handlers.d.ts +20 -0
  11. package/dist/application-state/handlers.d.ts.map +1 -0
  12. package/dist/application-state/handlers.js +94 -0
  13. package/dist/application-state/handlers.js.map +1 -0
  14. package/dist/application-state/index.d.ts +5 -0
  15. package/dist/application-state/index.d.ts.map +1 -0
  16. package/dist/application-state/index.js +9 -0
  17. package/dist/application-state/index.js.map +1 -0
  18. package/dist/application-state/script-helpers.d.ts +17 -0
  19. package/dist/application-state/script-helpers.d.ts.map +1 -0
  20. package/dist/application-state/script-helpers.js +28 -0
  21. package/dist/application-state/script-helpers.js.map +1 -0
  22. package/dist/application-state/store.d.ts +9 -0
  23. package/dist/application-state/store.d.ts.map +1 -0
  24. package/dist/application-state/store.js +93 -0
  25. package/dist/application-state/store.js.map +1 -0
  26. package/dist/cli/create.d.ts.map +1 -1
  27. package/dist/cli/create.js +38 -24
  28. package/dist/cli/create.js.map +1 -1
  29. package/dist/client/AgentPanel.d.ts +53 -0
  30. package/dist/client/AgentPanel.d.ts.map +1 -0
  31. package/dist/client/AgentPanel.js +70 -0
  32. package/dist/client/AgentPanel.js.map +1 -0
  33. package/dist/client/AssistantChat.d.ts +27 -0
  34. package/dist/client/AssistantChat.d.ts.map +1 -0
  35. package/dist/client/AssistantChat.js +165 -0
  36. package/dist/client/AssistantChat.js.map +1 -0
  37. package/dist/client/ErrorBoundary.d.ts +4 -0
  38. package/dist/client/ErrorBoundary.d.ts.map +1 -0
  39. package/dist/client/ErrorBoundary.js +22 -0
  40. package/dist/client/ErrorBoundary.js.map +1 -0
  41. package/dist/client/MultiTabAssistantChat.d.ts +4 -0
  42. package/dist/client/MultiTabAssistantChat.d.ts.map +1 -0
  43. package/dist/client/MultiTabAssistantChat.js +125 -0
  44. package/dist/client/MultiTabAssistantChat.js.map +1 -0
  45. package/dist/client/ProductionAgentPanel.d.ts +3 -7
  46. package/dist/client/ProductionAgentPanel.d.ts.map +1 -1
  47. package/dist/client/ProductionAgentPanel.js +3 -118
  48. package/dist/client/ProductionAgentPanel.js.map +1 -1
  49. package/dist/client/agent-chat-adapter.d.ts +10 -0
  50. package/dist/client/agent-chat-adapter.d.ts.map +1 -0
  51. package/dist/client/agent-chat-adapter.js +235 -0
  52. package/dist/client/agent-chat-adapter.js.map +1 -0
  53. package/dist/client/agent-chat.d.ts +9 -1
  54. package/dist/client/agent-chat.d.ts.map +1 -1
  55. package/dist/client/agent-chat.js +11 -1
  56. package/dist/client/agent-chat.js.map +1 -1
  57. package/dist/client/index.d.ts +8 -2
  58. package/dist/client/index.d.ts.map +1 -1
  59. package/dist/client/index.js +9 -2
  60. package/dist/client/index.js.map +1 -1
  61. package/dist/client/terminal/AgentTerminal.d.ts +35 -0
  62. package/dist/client/terminal/AgentTerminal.d.ts.map +1 -0
  63. package/dist/client/terminal/AgentTerminal.js +346 -0
  64. package/dist/client/terminal/AgentTerminal.js.map +1 -0
  65. package/dist/client/terminal/index.d.ts +7 -0
  66. package/dist/client/terminal/index.d.ts.map +1 -0
  67. package/dist/client/terminal/index.js +7 -0
  68. package/dist/client/terminal/index.js.map +1 -0
  69. package/dist/client/use-agent-chat.d.ts +1 -1
  70. package/dist/client/use-agent-chat.d.ts.map +1 -1
  71. package/dist/client/use-agent-chat.js +1 -1
  72. package/dist/client/use-agent-chat.js.map +1 -1
  73. package/dist/client/useProductionAgent.d.ts +6 -1
  74. package/dist/client/useProductionAgent.d.ts.map +1 -1
  75. package/dist/client/useProductionAgent.js +4 -2
  76. package/dist/client/useProductionAgent.js.map +1 -1
  77. package/dist/db/create-get-db.d.ts +3 -0
  78. package/dist/db/create-get-db.d.ts.map +1 -0
  79. package/dist/db/create-get-db.js +18 -0
  80. package/dist/db/create-get-db.js.map +1 -0
  81. package/dist/db/index.d.ts +2 -0
  82. package/dist/db/index.d.ts.map +1 -1
  83. package/dist/db/index.js +2 -0
  84. package/dist/db/index.js.map +1 -1
  85. package/dist/db/migrations.d.ts +7 -0
  86. package/dist/db/migrations.d.ts.map +1 -0
  87. package/dist/db/migrations.js +35 -0
  88. package/dist/db/migrations.js.map +1 -0
  89. package/dist/index.d.ts +2 -0
  90. package/dist/index.d.ts.map +1 -1
  91. package/dist/index.js +2 -0
  92. package/dist/index.js.map +1 -1
  93. package/dist/oauth-tokens/index.d.ts +2 -0
  94. package/dist/oauth-tokens/index.d.ts.map +1 -0
  95. package/dist/oauth-tokens/index.js +2 -0
  96. package/dist/oauth-tokens/index.js.map +1 -0
  97. package/dist/oauth-tokens/store.d.ts +9 -0
  98. package/dist/oauth-tokens/store.d.ts.map +1 -0
  99. package/dist/oauth-tokens/store.js +90 -0
  100. package/dist/oauth-tokens/store.js.map +1 -0
  101. package/dist/scripts/db/exec.d.ts.map +1 -1
  102. package/dist/scripts/db/exec.js +31 -16
  103. package/dist/scripts/db/exec.js.map +1 -1
  104. package/dist/scripts/db/query.d.ts.map +1 -1
  105. package/dist/scripts/db/query.js +24 -8
  106. package/dist/scripts/db/query.js.map +1 -1
  107. package/dist/scripts/db/schema.d.ts.map +1 -1
  108. package/dist/scripts/db/schema.js +56 -28
  109. package/dist/scripts/db/schema.js.map +1 -1
  110. package/dist/scripts/dev/index.d.ts +15 -0
  111. package/dist/scripts/dev/index.d.ts.map +1 -0
  112. package/dist/scripts/dev/index.js +118 -0
  113. package/dist/scripts/dev/index.js.map +1 -0
  114. package/dist/scripts/dev/list-files.d.ts +5 -0
  115. package/dist/scripts/dev/list-files.d.ts.map +1 -0
  116. package/dist/scripts/dev/list-files.js +102 -0
  117. package/dist/scripts/dev/list-files.js.map +1 -0
  118. package/dist/scripts/dev/read-file.d.ts +5 -0
  119. package/dist/scripts/dev/read-file.d.ts.map +1 -0
  120. package/dist/scripts/dev/read-file.js +68 -0
  121. package/dist/scripts/dev/read-file.js.map +1 -0
  122. package/dist/scripts/dev/search-files.d.ts +5 -0
  123. package/dist/scripts/dev/search-files.d.ts.map +1 -0
  124. package/dist/scripts/dev/search-files.js +133 -0
  125. package/dist/scripts/dev/search-files.js.map +1 -0
  126. package/dist/scripts/dev/shell.d.ts +5 -0
  127. package/dist/scripts/dev/shell.d.ts.map +1 -0
  128. package/dist/scripts/dev/shell.js +65 -0
  129. package/dist/scripts/dev/shell.js.map +1 -0
  130. package/dist/scripts/dev/write-file.d.ts +5 -0
  131. package/dist/scripts/dev/write-file.d.ts.map +1 -0
  132. package/dist/scripts/dev/write-file.js +50 -0
  133. package/dist/scripts/dev/write-file.js.map +1 -0
  134. package/dist/scripts/index.d.ts +1 -0
  135. package/dist/scripts/index.d.ts.map +1 -1
  136. package/dist/scripts/index.js +1 -0
  137. package/dist/scripts/index.js.map +1 -1
  138. package/dist/server/agent-chat-plugin.d.ts +43 -0
  139. package/dist/server/agent-chat-plugin.d.ts.map +1 -0
  140. package/dist/server/agent-chat-plugin.js +92 -0
  141. package/dist/server/agent-chat-plugin.js.map +1 -0
  142. package/dist/server/auth-plugin.d.ts +6 -0
  143. package/dist/server/auth-plugin.d.ts.map +1 -0
  144. package/dist/server/auth-plugin.js +8 -0
  145. package/dist/server/auth-plugin.js.map +1 -0
  146. package/dist/server/auth.d.ts +18 -2
  147. package/dist/server/auth.d.ts.map +1 -1
  148. package/dist/server/auth.js +103 -46
  149. package/dist/server/auth.js.map +1 -1
  150. package/dist/server/create-server.d.ts +7 -0
  151. package/dist/server/create-server.d.ts.map +1 -1
  152. package/dist/server/create-server.js +7 -1
  153. package/dist/server/create-server.js.map +1 -1
  154. package/dist/server/default-watcher.d.ts +17 -0
  155. package/dist/server/default-watcher.d.ts.map +1 -0
  156. package/dist/server/default-watcher.js +37 -0
  157. package/dist/server/default-watcher.js.map +1 -0
  158. package/dist/server/file-sync-plugin.d.ts +7 -0
  159. package/dist/server/file-sync-plugin.d.ts.map +1 -0
  160. package/dist/server/file-sync-plugin.js +38 -0
  161. package/dist/server/file-sync-plugin.js.map +1 -0
  162. package/dist/server/google-auth-plugin.d.ts +22 -0
  163. package/dist/server/google-auth-plugin.d.ts.map +1 -0
  164. package/dist/server/google-auth-plugin.js +122 -0
  165. package/dist/server/google-auth-plugin.js.map +1 -0
  166. package/dist/server/index.d.ts +9 -2
  167. package/dist/server/index.d.ts.map +1 -1
  168. package/dist/server/index.js +9 -2
  169. package/dist/server/index.js.map +1 -1
  170. package/dist/server/sse.d.ts +9 -4
  171. package/dist/server/sse.d.ts.map +1 -1
  172. package/dist/server/sse.js +19 -12
  173. package/dist/server/sse.js.map +1 -1
  174. package/dist/settings/handlers.d.ts +9 -0
  175. package/dist/settings/handlers.d.ts.map +1 -0
  176. package/dist/settings/handlers.js +29 -0
  177. package/dist/settings/handlers.js.map +1 -0
  178. package/dist/settings/index.d.ts +5 -0
  179. package/dist/settings/index.d.ts.map +1 -0
  180. package/dist/settings/index.js +9 -0
  181. package/dist/settings/index.js.map +1 -0
  182. package/dist/settings/script-helpers.d.ts +9 -0
  183. package/dist/settings/script-helpers.d.ts.map +1 -0
  184. package/dist/settings/script-helpers.js +16 -0
  185. package/dist/settings/script-helpers.js.map +1 -0
  186. package/dist/settings/store.d.ts +7 -0
  187. package/dist/settings/store.d.ts.map +1 -0
  188. package/dist/settings/store.js +88 -0
  189. package/dist/settings/store.js.map +1 -0
  190. package/dist/settings/user-settings.d.ts +21 -0
  191. package/dist/settings/user-settings.d.ts.map +1 -0
  192. package/dist/settings/user-settings.js +35 -0
  193. package/dist/settings/user-settings.js.map +1 -0
  194. package/dist/tailwind.preset.js +1 -1
  195. package/dist/tailwind.preset.js.map +1 -1
  196. package/dist/terminal/cli-registry.d.ts +16 -0
  197. package/dist/terminal/cli-registry.d.ts.map +1 -0
  198. package/dist/terminal/cli-registry.js +42 -0
  199. package/dist/terminal/cli-registry.js.map +1 -0
  200. package/dist/terminal/index.d.ts +9 -0
  201. package/dist/terminal/index.d.ts.map +1 -0
  202. package/dist/terminal/index.js +9 -0
  203. package/dist/terminal/index.js.map +1 -0
  204. package/dist/terminal/pty-server.d.ts +31 -0
  205. package/dist/terminal/pty-server.d.ts.map +1 -0
  206. package/dist/terminal/pty-server.js +252 -0
  207. package/dist/terminal/pty-server.js.map +1 -0
  208. package/dist/terminal/terminal-plugin.d.ts +23 -0
  209. package/dist/terminal/terminal-plugin.d.ts.map +1 -0
  210. package/dist/terminal/terminal-plugin.js +90 -0
  211. package/dist/terminal/terminal-plugin.js.map +1 -0
  212. package/dist/vite/client.d.ts.map +1 -1
  213. package/dist/vite/client.js +19 -1
  214. package/dist/vite/client.js.map +1 -1
  215. package/dist/vite/dev-api-server.d.ts.map +1 -1
  216. package/dist/vite/dev-api-server.js +12 -0
  217. package/dist/vite/dev-api-server.js.map +1 -1
  218. package/package.json +50 -4
  219. package/src/templates/default/.agents/skills/create-skill/SKILL.md +1 -1
  220. package/src/templates/default/.agents/skills/delegate-to-agent/SKILL.md +3 -3
  221. package/src/templates/default/.agents/skills/files-as-database/SKILL.md +82 -63
  222. package/src/templates/default/.agents/skills/frontend-design/SKILL.md +2 -2
  223. package/src/templates/default/.agents/skills/scripts/SKILL.md +20 -17
  224. package/src/templates/default/.agents/skills/self-modifying-code/SKILL.md +2 -2
  225. package/src/templates/default/.agents/skills/sse-file-watcher/SKILL.md +49 -64
  226. package/src/templates/default/.ignore +0 -0
  227. package/src/templates/default/AGENTS.md +30 -55
  228. package/src/templates/default/app/global.css +95 -0
  229. package/src/templates/default/{client → app}/root.tsx +22 -9
  230. package/src/templates/default/app/routes/_index.tsx +62 -0
  231. package/src/templates/default/application-state/.gitkeep +0 -0
  232. package/src/templates/default/components.json +1 -1
  233. package/src/templates/default/data/sync-config.json +1 -0
  234. package/src/templates/default/package.json +2 -1
  235. package/src/templates/default/react-router.config.ts +1 -1
  236. package/src/templates/default/scripts/run.ts +1 -8
  237. package/src/templates/default/server/plugins/agent-chat.ts +1 -0
  238. package/src/templates/default/server/plugins/auth.ts +1 -5
  239. package/src/templates/default/server/plugins/file-sync.ts +1 -39
  240. package/src/templates/default/server/plugins/terminal.ts +1 -0
  241. package/src/templates/default/server/routes/api/events.get.ts +2 -6
  242. package/src/templates/default/server/routes/api/file-sync/status.get.ts +2 -11
  243. package/src/templates/default/tailwind.config.ts +1 -1
  244. package/src/templates/default/tsconfig.json +1 -1
  245. package/tsconfig.base.json +2 -2
  246. package/src/templates/default/client/App.tsx +0 -56
  247. package/src/templates/default/client/global.css +0 -75
  248. package/src/templates/default/client/routes/_index.tsx +0 -19
  249. package/src/templates/default/server/lib/watcher.ts +0 -21
  250. /package/src/templates/default/{client → app}/entry.client.tsx +0 -0
  251. /package/src/templates/default/{client → app}/entry.server.tsx +0 -0
  252. /package/src/templates/default/{client → app}/lib/utils.ts +0 -0
  253. /package/src/templates/default/{client → app}/routes.ts +0 -0
  254. /package/src/templates/default/{client → app}/vite-env.d.ts +0 -0
@@ -2,14 +2,14 @@
2
2
 
3
3
  ## Architecture
4
4
 
5
- This is an **@agent-native/core** application — the AI agent and UI share state through files, not a traditional database.
5
+ This is an **@agent-native/core** application — the AI agent and UI share state through a SQL database, with SSE for real-time sync.
6
6
 
7
7
  ### Core Principles
8
8
 
9
- 1. **Files as database** — All app state lives in files. Both UI and agent read/write the same files.
9
+ 1. **Shared SQL database** — All app state lives in SQL (SQLite locally, cloud DB via `DATABASE_URL` in production). Core stores: `application_state`, `settings`, `oauth_tokens`, `sessions`.
10
10
  2. **All AI through agent chat** — No inline LLM calls. UI delegates to the AI via `sendToAgentChat()` / `agentChat.submit()`.
11
11
  3. **Scripts for agent operations** — `pnpm script <name>` dispatches to callable script files in `scripts/`.
12
- 4. **Bidirectional SSE events** — The file watcher keeps the UI in sync when the agent modifies files.
12
+ 4. **SSE for real-time sync** — Database writes emit events that keep the UI in sync automatically.
13
13
  5. **Agent can update code** — The agent can modify this app's source code directly.
14
14
 
15
15
  ### Authentication
@@ -25,7 +25,7 @@ Use `getSession(event)` server-side and `useSession()` client-side. See [docs/au
25
25
  ### Directory Structure
26
26
 
27
27
  ```
28
- client/ # React frontend
28
+ app/ # React frontend
29
29
  root.tsx # HTML shell + global providers
30
30
  entry.client.tsx # Client hydration entry
31
31
  routes.ts # Route config — flatRoutes()
@@ -48,7 +48,7 @@ scripts/ # Agent-callable scripts
48
48
  run.ts # Script dispatcher
49
49
  *.ts # Individual scripts (pnpm script <name>)
50
50
 
51
- data/ # App data files (watched by SSE)
51
+ data/ # App data (SQLite DB file)
52
52
 
53
53
  react-router.config.ts # React Router framework config
54
54
  .agents/skills/ # Agent skills — detailed guidance for each rule
@@ -73,10 +73,10 @@ Skills in `.agents/skills/` provide detailed guidance for each architectural rul
73
73
 
74
74
  | Skill | When to read |
75
75
  | --------------------- | -------------------------------------------------------------- |
76
- | `files-as-database` | Before storing or reading any app state |
76
+ | `storing-data` | Before storing or reading any app state |
77
77
  | `delegate-to-agent` | Before adding LLM calls or AI delegation |
78
78
  | `scripts` | Before creating or modifying scripts |
79
- | `sse-file-watcher` | Before wiring up real-time UI sync |
79
+ | `real-time-sync` | Before wiring up real-time UI sync |
80
80
  | `self-modifying-code` | Before editing source, components, or styles |
81
81
  | `frontend-design` | Before building or restyling any UI component, page, or layout |
82
82
 
@@ -87,14 +87,14 @@ The **`frontend-design`** skill (sourced from [Anthropic's skills library](https
87
87
  **SSR-first framework, CSR-by-default content:** This app uses React Router v7 framework mode with `ssr: true`. But virtually every route renders only an SSR shell (loading spinner + meta tags). All real data fetching and rendering happens on the client via React Query hooks. Server-side data fetching is the exception — only used for public pages that need SEO/og tags.
88
88
 
89
89
  **Adding a page:**
90
- Create a file in `client/routes/`. The filename determines the URL path:
90
+ Create a file in `app/routes/`. The filename determines the URL path:
91
91
 
92
92
  ```
93
- client/routes/_index.tsx → /
94
- client/routes/settings.tsx → /settings
95
- client/routes/inbox.tsx → /inbox
96
- client/routes/inbox.$threadId.tsx → /inbox/:threadId
97
- client/routes/$id.tsx → /:id (dynamic param)
93
+ app/routes/_index.tsx → /
94
+ app/routes/settings.tsx → /settings
95
+ app/routes/inbox.tsx → /inbox
96
+ app/routes/inbox.$threadId.tsx → /inbox/:threadId
97
+ app/routes/$id.tsx → /:id (dynamic param)
98
98
  ```
99
99
 
100
100
  Each route file exports a default component, optional `meta()`, and optional `HydrateFallback()`:
@@ -135,7 +135,7 @@ server/routes/api/items/[id].patch.ts → PATCH /api/items/:id
135
135
  Each file exports a default `defineEventHandler`.
136
136
 
137
137
  **Adding a server plugin:**
138
- Startup logic (file watcher, file sync, auth) lives in `server/plugins/`. Use `defineNitroPlugin` from core:
138
+ Startup logic (auth, SSE, etc.) lives in `server/plugins/`. Use `defineNitroPlugin` from core:
139
139
 
140
140
  ```ts
141
141
  import { defineNitroPlugin } from "@agent-native/core";
@@ -147,14 +147,15 @@ export default defineNitroPlugin(async (nitroApp) => {
147
147
 
148
148
  **Key imports from `@agent-native/core`:**
149
149
 
150
- | Import | Purpose |
151
- | -------------------------------------------- | ------------------------------------------------- |
152
- | `defineNitroPlugin` | Define a server plugin (re-exported from Nitro) |
153
- | `createFileWatcher` | Watch data directory for changes |
154
- | `createSSEHandler` | Create SSE endpoint for real-time updates |
155
- | `defineEventHandler`, `readBody`, `getQuery` | H3 route handler utilities (re-exported) |
156
- | `sendToAgentChat` | Send messages to agent from UI (client-side) |
157
- | `agentChat` | Send messages to agent from scripts (server-side) |
150
+ | Import | Purpose |
151
+ | -------------------------------------------- | -------------------------------------------------------------------------- |
152
+ | `defineNitroPlugin` | Define a server plugin (re-exported from Nitro) |
153
+ | `createDefaultSSEHandler` | Create SSE endpoint for DB change events (server) |
154
+ | `readAppState`, `writeAppState` | Read/write application state (from `@agent-native/core/application-state`) |
155
+ | `readSetting`, `writeSetting` | Read/write settings (from `@agent-native/core/settings`) |
156
+ | `defineEventHandler`, `readBody`, `getQuery` | H3 route handler utilities (re-exported) |
157
+ | `sendToAgentChat` | Send messages to agent from UI (client-side) |
158
+ | `agentChat` | Send messages to agent from scripts (server-side) |
158
159
 
159
160
  **Adding a script:**
160
161
  Create `scripts/my-script.ts` exporting `default async function(args: string[])`.
@@ -178,42 +179,16 @@ import { agentChat } from "@agent-native/core";
178
179
  agentChat.submit("Generate something");
179
180
  ```
180
181
 
181
- ### File Sync (Multi-User Collaboration)
182
+ ### Database (Cloud Deployment)
182
183
 
183
- File sync is **opt-in** enabled when `FILE_SYNC_ENABLED=true` is set in `.env`.
184
+ By default, data is stored in SQLite at `data/app.db`. For production/cloud deployment, set `DATABASE_URL` to point to a remote database (Turso, Neon, Supabase, D1).
184
185
 
185
186
  **Environment variables:**
186
187
 
187
- | Variable | Required | Description |
188
- | -------------------------------- | ------------- | ---------------------------------------------------- |
189
- | `FILE_SYNC_ENABLED` | No | Set to `"true"` to enable sync |
190
- | `FILE_SYNC_BACKEND` | When enabled | `"firestore"`, `"supabase"`, or `"convex"` |
191
- | `SUPABASE_URL` | For Supabase | Project URL |
192
- | `SUPABASE_PUBLISHABLE_KEY` | For Supabase | Publishable key (or legacy `SUPABASE_ANON_KEY`) |
193
- | `GOOGLE_APPLICATION_CREDENTIALS` | For Firestore | Path to service account JSON |
194
- | `CONVEX_URL` | For Convex | Deployment URL from `npx convex dev` (must be HTTPS) |
195
-
196
- **How sync works:**
197
-
198
- - `createFileSync()` factory in `server/plugins/file-sync.ts` reads env vars and initializes sync
199
- - Files matching `sync-config.json` patterns are synced to/from the remote database
200
- - Sync events flow through SSE (`source: "sync"`) alongside file change events
201
- - Conflicts produce `.conflict` sidecar files and notify the agent
202
-
203
- **Checking sync status:**
204
-
205
- - Read `data/.sync-status.json` for current sync state (connected, conflicts, retry queue)
206
- - Read `data/.sync-failures.json` for permanently failed sync operations
207
-
208
- **Handling conflicts:**
209
-
210
- - When `application-state/sync-conflict.json` appears, a sync conflict needs resolution
211
- - Read the `.conflict` file alongside the original to understand both versions
212
- - Edit the original file to resolve, then delete the `.conflict` file
213
-
214
- **Scratch files (not synced):**
215
-
216
- - Prefix temporary files with `_tmp-` (e.g., `data/_tmp-scratch.json`) to exclude from sync
188
+ | Variable | Required | Description |
189
+ | --------------------- | ---------------- | ---------------------------------------------------------- |
190
+ | `DATABASE_URL` | No (has default) | Database connection string (default: `file:./data/app.db`) |
191
+ | `DATABASE_AUTH_TOKEN` | For remote DBs | Auth token for Turso or other remote databases |
217
192
 
218
193
  ### Tech Stack
219
194
 
@@ -221,7 +196,7 @@ File sync is **opt-in** — enabled when `FILE_SYNC_ENABLED=true` is set in `.en
221
196
  - **Frontend:** React 18, Vite, TailwindCSS, shadcn/ui
222
197
  - **Routing:** File-based via `flatRoutes()` — SSR shell + client rendering
223
198
  - **Backend:** Nitro (via @agent-native/core) — file-based API routing, server plugins, deploy-anywhere presets
224
- - **State:** File-based (SSE for real-time updates)
199
+ - **State:** SQL-backed (SSE for real-time updates)
225
200
  - **Build:** `pnpm build` (React Router build — client + SSR + Nitro server)
226
201
  - **Dev:** `pnpm dev` (Vite dev server with both React Router + Nitro plugins)
227
202
  - **Start:** `node .output/server/index.mjs` (production)
@@ -0,0 +1,95 @@
1
+ @import url("https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap");
2
+
3
+ @tailwind base;
4
+ @tailwind components;
5
+ @tailwind utilities;
6
+
7
+ @layer base {
8
+ :root {
9
+ --background: 0 0% 100%;
10
+ --foreground: 220 10% 10%;
11
+ --card: 0 0% 100%;
12
+ --card-foreground: 220 10% 10%;
13
+ --popover: 0 0% 100%;
14
+ --popover-foreground: 220 10% 10%;
15
+ --primary: 220 10% 15%;
16
+ --primary-foreground: 0 0% 100%;
17
+ --secondary: 220 10% 95%;
18
+ --secondary-foreground: 220 10% 15%;
19
+ --muted: 220 10% 95%;
20
+ --muted-foreground: 220 5% 45%;
21
+ --accent: 220 10% 95%;
22
+ --accent-foreground: 220 10% 15%;
23
+ --destructive: 0 84% 60%;
24
+ --destructive-foreground: 0 0% 98%;
25
+ --border: 220 10% 90%;
26
+ --input: 220 10% 90%;
27
+ --ring: 220 10% 40%;
28
+ --radius: 0.5rem;
29
+ --sidebar-background: 220 10% 97%;
30
+ --sidebar-foreground: 220 5% 45%;
31
+ --sidebar-primary: 220 10% 15%;
32
+ --sidebar-primary-foreground: 0 0% 100%;
33
+ --sidebar-accent: 220 10% 95%;
34
+ --sidebar-accent-foreground: 220 10% 15%;
35
+ --sidebar-border: 220 10% 90%;
36
+ --sidebar-ring: 220 10% 40%;
37
+ }
38
+
39
+ .dark {
40
+ --background: 220 6% 6%;
41
+ --foreground: 0 0% 90%;
42
+ --card: 220 5% 6%;
43
+ --card-foreground: 0 0% 90%;
44
+ --popover: 220 5% 6%;
45
+ --popover-foreground: 0 0% 90%;
46
+ --primary: 0 0% 75%;
47
+ --primary-foreground: 220 6% 6%;
48
+ --secondary: 220 4% 12%;
49
+ --secondary-foreground: 0 0% 90%;
50
+ --muted: 220 4% 10%;
51
+ --muted-foreground: 220 4% 50%;
52
+ --accent: 220 4% 13%;
53
+ --accent-foreground: 0 0% 90%;
54
+ --destructive: 0 63% 51%;
55
+ --destructive-foreground: 0 0% 98%;
56
+ --border: 220 4% 14%;
57
+ --input: 220 4% 14%;
58
+ --ring: 0 0% 60%;
59
+ --radius: 0.5rem;
60
+ --sidebar-background: 220 6% 4%;
61
+ --sidebar-foreground: 220 4% 50%;
62
+ --sidebar-primary: 0 0% 75%;
63
+ --sidebar-primary-foreground: 220 6% 6%;
64
+ --sidebar-accent: 220 4% 10%;
65
+ --sidebar-accent-foreground: 0 0% 90%;
66
+ --sidebar-border: 220 4% 10%;
67
+ --sidebar-ring: 0 0% 60%;
68
+ }
69
+ }
70
+
71
+ @layer base {
72
+ * {
73
+ @apply border-border;
74
+ }
75
+ body {
76
+ @apply bg-background text-foreground;
77
+ font-family: "Inter", sans-serif;
78
+ font-feature-settings: "cv02", "cv03", "cv04", "cv11";
79
+ }
80
+ }
81
+
82
+ ::-webkit-scrollbar {
83
+ width: 5px;
84
+ height: 5px;
85
+ }
86
+ ::-webkit-scrollbar-track {
87
+ background: transparent;
88
+ }
89
+ ::-webkit-scrollbar-thumb {
90
+ background: hsl(var(--border));
91
+ border-radius: 3px;
92
+ }
93
+ ::-webkit-scrollbar-thumb:hover {
94
+ background: hsl(var(--muted-foreground) / 0.4);
95
+ }
@@ -12,12 +12,14 @@ import {
12
12
  QueryClientProvider,
13
13
  useQueryClient,
14
14
  } from "@tanstack/react-query";
15
+ import { ThemeProvider } from "next-themes";
15
16
  import { useFileWatcher } from "@agent-native/core";
17
+ import { Toaster } from "sonner";
16
18
  import "./global.css";
17
19
 
18
20
  export function Layout({ children }: { children: React.ReactNode }) {
19
21
  return (
20
- <html lang="en" className="dark">
22
+ <html lang="en" suppressHydrationWarning>
21
23
  <head>
22
24
  <meta charSet="utf-8" />
23
25
  <meta name="viewport" content="width=device-width, initial-scale=1" />
@@ -33,20 +35,27 @@ export function Layout({ children }: { children: React.ReactNode }) {
33
35
  );
34
36
  }
35
37
 
36
- function FileWatcher({ children }: { children: React.ReactNode }) {
38
+ function FileWatcherSetup() {
37
39
  const qc = useQueryClient();
38
- useFileWatcher({ queryClient: qc, queryKeys: ["files"] });
39
- return <>{children}</>;
40
+ useFileWatcher({ queryClient: qc, queryKeys: ["files", "data"] });
41
+ return null;
40
42
  }
41
43
 
42
44
  export default function Root() {
43
45
  const [queryClient] = useState(() => new QueryClient());
44
46
  return (
45
- <QueryClientProvider client={queryClient}>
46
- <FileWatcher>
47
+ <ThemeProvider
48
+ attribute="class"
49
+ defaultTheme="system"
50
+ enableSystem
51
+ disableTransitionOnChange
52
+ >
53
+ <QueryClientProvider client={queryClient}>
54
+ <FileWatcherSetup />
47
55
  <Outlet />
48
- </FileWatcher>
49
- </QueryClientProvider>
56
+ <Toaster />
57
+ </QueryClientProvider>
58
+ </ThemeProvider>
50
59
  );
51
60
  }
52
61
 
@@ -61,7 +70,11 @@ export function ErrorBoundary({ error }: { error: unknown }) {
61
70
  error.status === 404
62
71
  ? "The requested page could not be found."
63
72
  : error.statusText || details;
64
- } else if (import.meta.env.DEV && error instanceof Error) {
73
+ } else if (
74
+ typeof process !== "undefined" &&
75
+ process.env.NODE_ENV !== "production" &&
76
+ error instanceof Error
77
+ ) {
65
78
  details = error.message;
66
79
  stack = error.stack;
67
80
  }
@@ -0,0 +1,62 @@
1
+ import { useTheme } from "next-themes";
2
+
3
+ export function meta() {
4
+ return [{ title: "{{APP_TITLE}}" }];
5
+ }
6
+
7
+ export function HydrateFallback() {
8
+ return (
9
+ <div className="flex items-center justify-center h-screen">
10
+ <div className="animate-spin rounded-full h-8 w-8 border-b-2 border-foreground" />
11
+ </div>
12
+ );
13
+ }
14
+
15
+ export default function IndexPage() {
16
+ const { theme, setTheme } = useTheme();
17
+
18
+ return (
19
+ <div className="flex flex-col items-center justify-center min-h-screen px-6">
20
+ <div className="max-w-md w-full space-y-8 text-center">
21
+ <div className="space-y-3">
22
+ <h1 className="text-2xl font-semibold tracking-tight text-foreground">
23
+ Your app is running
24
+ </h1>
25
+ <p className="text-[14px] text-muted-foreground leading-relaxed">
26
+ Start building by editing{" "}
27
+ <code className="text-[13px] bg-muted px-1.5 py-0.5 rounded font-mono">
28
+ app/routes/_index.tsx
29
+ </code>
30
+ </p>
31
+ </div>
32
+
33
+ <div className="h-px bg-border" />
34
+
35
+ <div className="grid grid-cols-2 gap-3 text-left">
36
+ <a
37
+ href="https://agent-native.dev/docs"
38
+ target="_blank"
39
+ rel="noopener noreferrer"
40
+ className="group rounded-lg border border-border/50 px-4 py-3 hover:bg-accent/50 transition-colors"
41
+ >
42
+ <p className="text-[13px] font-medium text-foreground">
43
+ Documentation
44
+ </p>
45
+ <p className="text-[12px] text-muted-foreground mt-0.5">
46
+ Learn the framework
47
+ </p>
48
+ </a>
49
+ <button
50
+ onClick={() => setTheme(theme === "dark" ? "light" : "dark")}
51
+ className="rounded-lg border border-border/50 px-4 py-3 hover:bg-accent/50 transition-colors text-left"
52
+ >
53
+ <p className="text-[13px] font-medium text-foreground">Theme</p>
54
+ <p className="text-[12px] text-muted-foreground mt-0.5">
55
+ Toggle dark / light
56
+ </p>
57
+ </button>
58
+ </div>
59
+ </div>
60
+ </div>
61
+ );
62
+ }
@@ -5,7 +5,7 @@
5
5
  "tsx": true,
6
6
  "tailwind": {
7
7
  "config": "tailwind.config.ts",
8
- "css": "client/global.css",
8
+ "css": "app/global.css",
9
9
  "baseColor": "slate",
10
10
  "cssVariables": true,
11
11
  "prefix": ""
@@ -0,0 +1 @@
1
+ { "patterns": ["data/**/*.json"] }
@@ -11,7 +11,7 @@
11
11
  },
12
12
  "dependencies": {
13
13
  "@agent-native/core": "^0.4.1",
14
- "dotenv": "^17.2.1",
14
+ "h3": "^1.13.0",
15
15
  "isbot": "^5"
16
16
  },
17
17
  "devDependencies": {
@@ -25,6 +25,7 @@
25
25
  "class-variance-authority": "^0.7.1",
26
26
  "clsx": "^2.1.1",
27
27
  "lucide-react": "^0.539.0",
28
+ "next-themes": "^0.4.6",
28
29
  "postcss": "^8.5.6",
29
30
  "prettier": "^3.6.2",
30
31
  "react": "^18.3.1",
@@ -1,6 +1,6 @@
1
1
  import type { Config } from "@react-router/dev/config";
2
2
 
3
3
  export default {
4
- appDirectory: "client",
4
+ appDirectory: "app",
5
5
  ssr: true,
6
6
  } satisfies Config;
@@ -1,9 +1,2 @@
1
- #!/usr/bin/env tsx
2
- /**
3
- * Script dispatcher — runs any script in the scripts/ folder.
4
- * Usage: pnpm script <script-name> [--args]
5
- */
6
-
7
- import { runScript } from "@agent-native/core";
8
-
1
+ import { runScript } from "@agent-native/core/scripts";
9
2
  runScript();
@@ -0,0 +1 @@
1
+ export { defaultAgentChatPlugin as default } from "@agent-native/core/server";
@@ -1,5 +1 @@
1
- import { defineNitroPlugin, autoMountAuth } from "@agent-native/core";
2
-
3
- export default defineNitroPlugin((nitroApp: any) => {
4
- autoMountAuth(nitroApp.h3App);
5
- });
1
+ export { defaultAuthPlugin as default } from "@agent-native/core/server";
@@ -1,39 +1 @@
1
- import "dotenv/config";
2
- import fs from "fs";
3
- import { defineNitroPlugin } from "@agent-native/core";
4
- import { createFileSync } from "@agent-native/core/adapters/sync";
5
- import { setSyncResult } from "../lib/watcher";
6
-
7
- export default defineNitroPlugin(async () => {
8
- const result = await createFileSync({ contentRoot: "./data" });
9
- setSyncResult(result);
10
-
11
- if (result.status === "error") {
12
- console.warn(`[app] File sync failed: ${result.reason}`);
13
- }
14
-
15
- // Graceful shutdown
16
- process.on("SIGTERM", async () => {
17
- if (result.status === "ready") await result.shutdown();
18
- process.exit(0);
19
- });
20
-
21
- // Notify agent of sync conflicts
22
- if (result.status === "ready") {
23
- result.fileSync.syncEvents.on("sync", (event: any) => {
24
- try {
25
- if (event.type === "conflict-needs-llm") {
26
- fs.mkdirSync("application-state", { recursive: true });
27
- fs.writeFileSync(
28
- "application-state/sync-conflict.json",
29
- JSON.stringify(event, null, 2),
30
- );
31
- } else if (event.type === "conflict-resolved") {
32
- fs.rmSync("application-state/sync-conflict.json", { force: true });
33
- }
34
- } catch {
35
- /* best-effort */
36
- }
37
- });
38
- }
39
- });
1
+ export { defaultFileSyncPlugin as default } from "@agent-native/core/server";
@@ -0,0 +1 @@
1
+ export { defaultTerminalPlugin as default } from "@agent-native/core/server";
@@ -1,7 +1,3 @@
1
- import { createSSEHandler } from "@agent-native/core";
2
- import { watcher, sseExtraEmitters } from "../../lib/watcher";
1
+ import { createDefaultSSEHandler } from "@agent-native/core/server";
3
2
 
4
- export default createSSEHandler(watcher, {
5
- extraEmitters: sseExtraEmitters,
6
- contentRoot: "./data",
7
- });
3
+ export default createDefaultSSEHandler();
@@ -1,13 +1,4 @@
1
1
  import { defineEventHandler } from "h3";
2
- import { syncResult } from "../../../lib/watcher";
2
+ import { defaultSyncStatusHandler } from "@agent-native/core/server";
3
3
 
4
- export default defineEventHandler(() => {
5
- if (syncResult.status !== "ready") {
6
- return { enabled: false, conflicts: 0 };
7
- }
8
- return {
9
- enabled: true,
10
- connected: true,
11
- conflicts: syncResult.fileSync.conflictCount,
12
- };
13
- });
4
+ export default defineEventHandler(() => defaultSyncStatusHandler());
@@ -3,5 +3,5 @@ import preset from "@agent-native/core/tailwind";
3
3
 
4
4
  export default {
5
5
  presets: [preset],
6
- content: ["./client/**/*.{ts,tsx}"],
6
+ content: ["./app/**/*.{ts,tsx}"],
7
7
  } satisfies Config;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "extends": "@agent-native/core/tsconfig.base.json",
3
3
  "include": [
4
- "client/**/*",
4
+ "app/**/*",
5
5
  "server/**/*",
6
6
  "shared/**/*",
7
7
  "vite.config.ts",
@@ -27,13 +27,13 @@
27
27
  "rootDirs": [".", "./.react-router/types"],
28
28
  "baseUrl": ".",
29
29
  "paths": {
30
- "@/*": ["./client/*"],
30
+ "@/*": ["./app/*"],
31
31
  "@shared/*": ["./shared/*"]
32
32
  },
33
33
  "types": ["vite/client"]
34
34
  },
35
35
  "include": [
36
- "client/**/*",
36
+ "app/**/*",
37
37
  "server/**/*",
38
38
  "shared/**/*",
39
39
  "vite.config.ts",
@@ -1,56 +0,0 @@
1
- import { StrictMode } from "react";
2
- import { createRoot } from "react-dom/client";
3
- import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
4
- import { useFileWatcher } from "@agent-native/core";
5
- import "./global.css";
6
-
7
- const queryClient = new QueryClient();
8
-
9
- function App() {
10
- return (
11
- <QueryClientProvider client={queryClient}>
12
- <Main />
13
- </QueryClientProvider>
14
- );
15
- }
16
-
17
- function Main() {
18
- useFileWatcher({ queryClient });
19
-
20
- return (
21
- <div className="min-h-screen bg-background text-foreground flex items-center justify-center">
22
- <div className="text-center space-y-4">
23
- <h1 className="text-4xl font-bold">Agent-Native App</h1>
24
- <p className="text-muted-foreground">
25
- Edit{" "}
26
- <code className="bg-muted px-2 py-1 rounded">client/App.tsx</code> to
27
- get started.
28
- </p>
29
- <p className="text-sm text-muted-foreground">
30
- API health: <HealthCheck />
31
- </p>
32
- </div>
33
- </div>
34
- );
35
- }
36
-
37
- function HealthCheck() {
38
- return (
39
- <span
40
- className="text-primary cursor-pointer hover:underline"
41
- onClick={async () => {
42
- const res = await fetch("/api/ping");
43
- const data = await res.json();
44
- alert(data.message);
45
- }}
46
- >
47
- /api/ping
48
- </span>
49
- );
50
- }
51
-
52
- createRoot(document.getElementById("root")!).render(
53
- <StrictMode>
54
- <App />
55
- </StrictMode>,
56
- );