@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.
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +9 -3
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/agent/types.d.ts +2 -0
- package/dist/agent/types.d.ts.map +1 -1
- package/dist/application-state/emitter.d.ts +10 -0
- package/dist/application-state/emitter.d.ts.map +1 -0
- package/dist/application-state/emitter.js +18 -0
- package/dist/application-state/emitter.js.map +1 -0
- package/dist/application-state/handlers.d.ts +20 -0
- package/dist/application-state/handlers.d.ts.map +1 -0
- package/dist/application-state/handlers.js +94 -0
- package/dist/application-state/handlers.js.map +1 -0
- package/dist/application-state/index.d.ts +5 -0
- package/dist/application-state/index.d.ts.map +1 -0
- package/dist/application-state/index.js +9 -0
- package/dist/application-state/index.js.map +1 -0
- package/dist/application-state/script-helpers.d.ts +17 -0
- package/dist/application-state/script-helpers.d.ts.map +1 -0
- package/dist/application-state/script-helpers.js +28 -0
- package/dist/application-state/script-helpers.js.map +1 -0
- package/dist/application-state/store.d.ts +9 -0
- package/dist/application-state/store.d.ts.map +1 -0
- package/dist/application-state/store.js +93 -0
- package/dist/application-state/store.js.map +1 -0
- package/dist/cli/create.d.ts.map +1 -1
- package/dist/cli/create.js +38 -24
- package/dist/cli/create.js.map +1 -1
- package/dist/client/AgentPanel.d.ts +53 -0
- package/dist/client/AgentPanel.d.ts.map +1 -0
- package/dist/client/AgentPanel.js +70 -0
- package/dist/client/AgentPanel.js.map +1 -0
- package/dist/client/AssistantChat.d.ts +27 -0
- package/dist/client/AssistantChat.d.ts.map +1 -0
- package/dist/client/AssistantChat.js +165 -0
- package/dist/client/AssistantChat.js.map +1 -0
- package/dist/client/ErrorBoundary.d.ts +4 -0
- package/dist/client/ErrorBoundary.d.ts.map +1 -0
- package/dist/client/ErrorBoundary.js +22 -0
- package/dist/client/ErrorBoundary.js.map +1 -0
- package/dist/client/MultiTabAssistantChat.d.ts +4 -0
- package/dist/client/MultiTabAssistantChat.d.ts.map +1 -0
- package/dist/client/MultiTabAssistantChat.js +125 -0
- package/dist/client/MultiTabAssistantChat.js.map +1 -0
- package/dist/client/ProductionAgentPanel.d.ts +3 -7
- package/dist/client/ProductionAgentPanel.d.ts.map +1 -1
- package/dist/client/ProductionAgentPanel.js +3 -118
- package/dist/client/ProductionAgentPanel.js.map +1 -1
- package/dist/client/agent-chat-adapter.d.ts +10 -0
- package/dist/client/agent-chat-adapter.d.ts.map +1 -0
- package/dist/client/agent-chat-adapter.js +235 -0
- package/dist/client/agent-chat-adapter.js.map +1 -0
- package/dist/client/agent-chat.d.ts +9 -1
- package/dist/client/agent-chat.d.ts.map +1 -1
- package/dist/client/agent-chat.js +11 -1
- package/dist/client/agent-chat.js.map +1 -1
- package/dist/client/index.d.ts +8 -2
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +9 -2
- package/dist/client/index.js.map +1 -1
- package/dist/client/terminal/AgentTerminal.d.ts +35 -0
- package/dist/client/terminal/AgentTerminal.d.ts.map +1 -0
- package/dist/client/terminal/AgentTerminal.js +346 -0
- package/dist/client/terminal/AgentTerminal.js.map +1 -0
- package/dist/client/terminal/index.d.ts +7 -0
- package/dist/client/terminal/index.d.ts.map +1 -0
- package/dist/client/terminal/index.js +7 -0
- package/dist/client/terminal/index.js.map +1 -0
- package/dist/client/use-agent-chat.d.ts +1 -1
- package/dist/client/use-agent-chat.d.ts.map +1 -1
- package/dist/client/use-agent-chat.js +1 -1
- package/dist/client/use-agent-chat.js.map +1 -1
- package/dist/client/useProductionAgent.d.ts +6 -1
- package/dist/client/useProductionAgent.d.ts.map +1 -1
- package/dist/client/useProductionAgent.js +4 -2
- package/dist/client/useProductionAgent.js.map +1 -1
- package/dist/db/create-get-db.d.ts +3 -0
- package/dist/db/create-get-db.d.ts.map +1 -0
- package/dist/db/create-get-db.js +18 -0
- package/dist/db/create-get-db.js.map +1 -0
- package/dist/db/index.d.ts +2 -0
- package/dist/db/index.d.ts.map +1 -1
- package/dist/db/index.js +2 -0
- package/dist/db/index.js.map +1 -1
- package/dist/db/migrations.d.ts +7 -0
- package/dist/db/migrations.d.ts.map +1 -0
- package/dist/db/migrations.js +35 -0
- package/dist/db/migrations.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/oauth-tokens/index.d.ts +2 -0
- package/dist/oauth-tokens/index.d.ts.map +1 -0
- package/dist/oauth-tokens/index.js +2 -0
- package/dist/oauth-tokens/index.js.map +1 -0
- package/dist/oauth-tokens/store.d.ts +9 -0
- package/dist/oauth-tokens/store.d.ts.map +1 -0
- package/dist/oauth-tokens/store.js +90 -0
- package/dist/oauth-tokens/store.js.map +1 -0
- package/dist/scripts/db/exec.d.ts.map +1 -1
- package/dist/scripts/db/exec.js +31 -16
- package/dist/scripts/db/exec.js.map +1 -1
- package/dist/scripts/db/query.d.ts.map +1 -1
- package/dist/scripts/db/query.js +24 -8
- package/dist/scripts/db/query.js.map +1 -1
- package/dist/scripts/db/schema.d.ts.map +1 -1
- package/dist/scripts/db/schema.js +56 -28
- package/dist/scripts/db/schema.js.map +1 -1
- package/dist/scripts/dev/index.d.ts +15 -0
- package/dist/scripts/dev/index.d.ts.map +1 -0
- package/dist/scripts/dev/index.js +118 -0
- package/dist/scripts/dev/index.js.map +1 -0
- package/dist/scripts/dev/list-files.d.ts +5 -0
- package/dist/scripts/dev/list-files.d.ts.map +1 -0
- package/dist/scripts/dev/list-files.js +102 -0
- package/dist/scripts/dev/list-files.js.map +1 -0
- package/dist/scripts/dev/read-file.d.ts +5 -0
- package/dist/scripts/dev/read-file.d.ts.map +1 -0
- package/dist/scripts/dev/read-file.js +68 -0
- package/dist/scripts/dev/read-file.js.map +1 -0
- package/dist/scripts/dev/search-files.d.ts +5 -0
- package/dist/scripts/dev/search-files.d.ts.map +1 -0
- package/dist/scripts/dev/search-files.js +133 -0
- package/dist/scripts/dev/search-files.js.map +1 -0
- package/dist/scripts/dev/shell.d.ts +5 -0
- package/dist/scripts/dev/shell.d.ts.map +1 -0
- package/dist/scripts/dev/shell.js +65 -0
- package/dist/scripts/dev/shell.js.map +1 -0
- package/dist/scripts/dev/write-file.d.ts +5 -0
- package/dist/scripts/dev/write-file.d.ts.map +1 -0
- package/dist/scripts/dev/write-file.js +50 -0
- package/dist/scripts/dev/write-file.js.map +1 -0
- package/dist/scripts/index.d.ts +1 -0
- package/dist/scripts/index.d.ts.map +1 -1
- package/dist/scripts/index.js +1 -0
- package/dist/scripts/index.js.map +1 -1
- package/dist/server/agent-chat-plugin.d.ts +43 -0
- package/dist/server/agent-chat-plugin.d.ts.map +1 -0
- package/dist/server/agent-chat-plugin.js +92 -0
- package/dist/server/agent-chat-plugin.js.map +1 -0
- package/dist/server/auth-plugin.d.ts +6 -0
- package/dist/server/auth-plugin.d.ts.map +1 -0
- package/dist/server/auth-plugin.js +8 -0
- package/dist/server/auth-plugin.js.map +1 -0
- package/dist/server/auth.d.ts +18 -2
- package/dist/server/auth.d.ts.map +1 -1
- package/dist/server/auth.js +103 -46
- package/dist/server/auth.js.map +1 -1
- package/dist/server/create-server.d.ts +7 -0
- package/dist/server/create-server.d.ts.map +1 -1
- package/dist/server/create-server.js +7 -1
- package/dist/server/create-server.js.map +1 -1
- package/dist/server/default-watcher.d.ts +17 -0
- package/dist/server/default-watcher.d.ts.map +1 -0
- package/dist/server/default-watcher.js +37 -0
- package/dist/server/default-watcher.js.map +1 -0
- package/dist/server/file-sync-plugin.d.ts +7 -0
- package/dist/server/file-sync-plugin.d.ts.map +1 -0
- package/dist/server/file-sync-plugin.js +38 -0
- package/dist/server/file-sync-plugin.js.map +1 -0
- package/dist/server/google-auth-plugin.d.ts +22 -0
- package/dist/server/google-auth-plugin.d.ts.map +1 -0
- package/dist/server/google-auth-plugin.js +122 -0
- package/dist/server/google-auth-plugin.js.map +1 -0
- package/dist/server/index.d.ts +9 -2
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +9 -2
- package/dist/server/index.js.map +1 -1
- package/dist/server/sse.d.ts +9 -4
- package/dist/server/sse.d.ts.map +1 -1
- package/dist/server/sse.js +19 -12
- package/dist/server/sse.js.map +1 -1
- package/dist/settings/handlers.d.ts +9 -0
- package/dist/settings/handlers.d.ts.map +1 -0
- package/dist/settings/handlers.js +29 -0
- package/dist/settings/handlers.js.map +1 -0
- package/dist/settings/index.d.ts +5 -0
- package/dist/settings/index.d.ts.map +1 -0
- package/dist/settings/index.js +9 -0
- package/dist/settings/index.js.map +1 -0
- package/dist/settings/script-helpers.d.ts +9 -0
- package/dist/settings/script-helpers.d.ts.map +1 -0
- package/dist/settings/script-helpers.js +16 -0
- package/dist/settings/script-helpers.js.map +1 -0
- package/dist/settings/store.d.ts +7 -0
- package/dist/settings/store.d.ts.map +1 -0
- package/dist/settings/store.js +88 -0
- package/dist/settings/store.js.map +1 -0
- package/dist/settings/user-settings.d.ts +21 -0
- package/dist/settings/user-settings.d.ts.map +1 -0
- package/dist/settings/user-settings.js +35 -0
- package/dist/settings/user-settings.js.map +1 -0
- package/dist/tailwind.preset.js +1 -1
- package/dist/tailwind.preset.js.map +1 -1
- package/dist/terminal/cli-registry.d.ts +16 -0
- package/dist/terminal/cli-registry.d.ts.map +1 -0
- package/dist/terminal/cli-registry.js +42 -0
- package/dist/terminal/cli-registry.js.map +1 -0
- package/dist/terminal/index.d.ts +9 -0
- package/dist/terminal/index.d.ts.map +1 -0
- package/dist/terminal/index.js +9 -0
- package/dist/terminal/index.js.map +1 -0
- package/dist/terminal/pty-server.d.ts +31 -0
- package/dist/terminal/pty-server.d.ts.map +1 -0
- package/dist/terminal/pty-server.js +252 -0
- package/dist/terminal/pty-server.js.map +1 -0
- package/dist/terminal/terminal-plugin.d.ts +23 -0
- package/dist/terminal/terminal-plugin.d.ts.map +1 -0
- package/dist/terminal/terminal-plugin.js +90 -0
- package/dist/terminal/terminal-plugin.js.map +1 -0
- package/dist/vite/client.d.ts.map +1 -1
- package/dist/vite/client.js +19 -1
- package/dist/vite/client.js.map +1 -1
- package/dist/vite/dev-api-server.d.ts.map +1 -1
- package/dist/vite/dev-api-server.js +12 -0
- package/dist/vite/dev-api-server.js.map +1 -1
- package/package.json +50 -4
- package/src/templates/default/.agents/skills/create-skill/SKILL.md +1 -1
- package/src/templates/default/.agents/skills/delegate-to-agent/SKILL.md +3 -3
- package/src/templates/default/.agents/skills/files-as-database/SKILL.md +82 -63
- package/src/templates/default/.agents/skills/frontend-design/SKILL.md +2 -2
- package/src/templates/default/.agents/skills/scripts/SKILL.md +20 -17
- package/src/templates/default/.agents/skills/self-modifying-code/SKILL.md +2 -2
- package/src/templates/default/.agents/skills/sse-file-watcher/SKILL.md +49 -64
- package/src/templates/default/.ignore +0 -0
- package/src/templates/default/AGENTS.md +30 -55
- package/src/templates/default/app/global.css +95 -0
- package/src/templates/default/{client → app}/root.tsx +22 -9
- package/src/templates/default/app/routes/_index.tsx +62 -0
- package/src/templates/default/application-state/.gitkeep +0 -0
- package/src/templates/default/components.json +1 -1
- package/src/templates/default/data/sync-config.json +1 -0
- package/src/templates/default/package.json +2 -1
- package/src/templates/default/react-router.config.ts +1 -1
- package/src/templates/default/scripts/run.ts +1 -8
- package/src/templates/default/server/plugins/agent-chat.ts +1 -0
- package/src/templates/default/server/plugins/auth.ts +1 -5
- package/src/templates/default/server/plugins/file-sync.ts +1 -39
- package/src/templates/default/server/plugins/terminal.ts +1 -0
- package/src/templates/default/server/routes/api/events.get.ts +2 -6
- package/src/templates/default/server/routes/api/file-sync/status.get.ts +2 -11
- package/src/templates/default/tailwind.config.ts +1 -1
- package/src/templates/default/tsconfig.json +1 -1
- package/tsconfig.base.json +2 -2
- package/src/templates/default/client/App.tsx +0 -56
- package/src/templates/default/client/global.css +0 -75
- package/src/templates/default/client/routes/_index.tsx +0 -19
- package/src/templates/default/server/lib/watcher.ts +0 -21
- /package/src/templates/default/{client → app}/entry.client.tsx +0 -0
- /package/src/templates/default/{client → app}/entry.server.tsx +0 -0
- /package/src/templates/default/{client → app}/lib/utils.ts +0 -0
- /package/src/templates/default/{client → app}/routes.ts +0 -0
- /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
|
|
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. **
|
|
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. **
|
|
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
|
-
|
|
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
|
|
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
|
-
| `
|
|
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
|
-
| `
|
|
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 `
|
|
90
|
+
Create a file in `app/routes/`. The filename determines the URL path:
|
|
91
91
|
|
|
92
92
|
```
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
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 (
|
|
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
|
-
| `
|
|
154
|
-
| `
|
|
155
|
-
| `
|
|
156
|
-
| `
|
|
157
|
-
| `
|
|
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
|
-
###
|
|
182
|
+
### Database (Cloud Deployment)
|
|
182
183
|
|
|
183
|
-
|
|
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
|
|
188
|
-
|
|
|
189
|
-
| `
|
|
190
|
-
| `
|
|
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:**
|
|
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"
|
|
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
|
|
38
|
+
function FileWatcherSetup() {
|
|
37
39
|
const qc = useQueryClient();
|
|
38
|
-
useFileWatcher({ queryClient: qc, queryKeys: ["files"] });
|
|
39
|
-
return
|
|
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
|
-
<
|
|
46
|
-
|
|
47
|
+
<ThemeProvider
|
|
48
|
+
attribute="class"
|
|
49
|
+
defaultTheme="system"
|
|
50
|
+
enableSystem
|
|
51
|
+
disableTransitionOnChange
|
|
52
|
+
>
|
|
53
|
+
<QueryClientProvider client={queryClient}>
|
|
54
|
+
<FileWatcherSetup />
|
|
47
55
|
<Outlet />
|
|
48
|
-
|
|
49
|
-
|
|
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 (
|
|
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
|
+
}
|
|
File without changes
|
|
@@ -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
|
-
"
|
|
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,9 +1,2 @@
|
|
|
1
|
-
|
|
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,39 +1 @@
|
|
|
1
|
-
|
|
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 {
|
|
2
|
-
import { watcher, sseExtraEmitters } from "../../lib/watcher";
|
|
1
|
+
import { createDefaultSSEHandler } from "@agent-native/core/server";
|
|
3
2
|
|
|
4
|
-
export default
|
|
5
|
-
extraEmitters: sseExtraEmitters,
|
|
6
|
-
contentRoot: "./data",
|
|
7
|
-
});
|
|
3
|
+
export default createDefaultSSEHandler();
|
|
@@ -1,13 +1,4 @@
|
|
|
1
1
|
import { defineEventHandler } from "h3";
|
|
2
|
-
import {
|
|
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());
|
package/tsconfig.base.json
CHANGED
|
@@ -27,13 +27,13 @@
|
|
|
27
27
|
"rootDirs": [".", "./.react-router/types"],
|
|
28
28
|
"baseUrl": ".",
|
|
29
29
|
"paths": {
|
|
30
|
-
"@/*": ["./
|
|
30
|
+
"@/*": ["./app/*"],
|
|
31
31
|
"@shared/*": ["./shared/*"]
|
|
32
32
|
},
|
|
33
33
|
"types": ["vite/client"]
|
|
34
34
|
},
|
|
35
35
|
"include": [
|
|
36
|
-
"
|
|
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
|
-
);
|