@agent-native/core 0.39.1 → 0.40.0
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/README.md +1 -1
- package/dist/action.js +12 -0
- package/dist/action.js.map +1 -1
- package/dist/cli/create.d.ts.map +1 -1
- package/dist/cli/create.js +5 -1
- package/dist/cli/create.js.map +1 -1
- package/dist/cli/index.js +1 -1
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/skills.d.ts +6 -6
- package/dist/cli/skills.d.ts.map +1 -1
- package/dist/cli/skills.js +936 -1167
- package/dist/cli/skills.js.map +1 -1
- package/dist/client/MultiTabAssistantChat.d.ts.map +1 -1
- package/dist/client/MultiTabAssistantChat.js +2 -5
- package/dist/client/MultiTabAssistantChat.js.map +1 -1
- package/dist/client/NewWorkspaceAppFlow.js +1 -1
- package/dist/client/NewWorkspaceAppFlow.js.map +1 -1
- package/dist/client/blocks/AiEditableField.d.ts +8 -0
- package/dist/client/blocks/AiEditableField.d.ts.map +1 -0
- package/dist/client/blocks/AiEditableField.js +10 -0
- package/dist/client/blocks/AiEditableField.js.map +1 -0
- package/dist/client/blocks/BlockView.d.ts +3 -3
- package/dist/client/blocks/BlockView.d.ts.map +1 -1
- package/dist/client/blocks/BlockView.js +15 -3
- package/dist/client/blocks/BlockView.js.map +1 -1
- package/dist/client/blocks/SchemaBlockEditor.js +2 -2
- package/dist/client/blocks/SchemaBlockEditor.js.map +1 -1
- package/dist/client/blocks/index.d.ts +5 -2
- package/dist/client/blocks/index.d.ts.map +1 -1
- package/dist/client/blocks/index.js +6 -3
- package/dist/client/blocks/index.js.map +1 -1
- package/dist/client/blocks/library/ApiEndpointBlock.d.ts.map +1 -1
- package/dist/client/blocks/library/ApiEndpointBlock.js +20 -6
- package/dist/client/blocks/library/ApiEndpointBlock.js.map +1 -1
- package/dist/client/blocks/library/DiffBlock.d.ts +29 -0
- package/dist/client/blocks/library/DiffBlock.d.ts.map +1 -1
- package/dist/client/blocks/library/DiffBlock.js +190 -30
- package/dist/client/blocks/library/DiffBlock.js.map +1 -1
- package/dist/client/blocks/library/FileTreeBlock.d.ts.map +1 -1
- package/dist/client/blocks/library/FileTreeBlock.js +46 -7
- package/dist/client/blocks/library/FileTreeBlock.js.map +1 -1
- package/dist/client/blocks/library/HighlightedCode.d.ts +10 -0
- package/dist/client/blocks/library/HighlightedCode.d.ts.map +1 -0
- package/dist/client/blocks/library/HighlightedCode.js +92 -0
- package/dist/client/blocks/library/HighlightedCode.js.map +1 -0
- package/dist/client/blocks/library/JsonExplorerBlock.d.ts +9 -4
- package/dist/client/blocks/library/JsonExplorerBlock.d.ts.map +1 -1
- package/dist/client/blocks/library/JsonExplorerBlock.js +66 -30
- package/dist/client/blocks/library/JsonExplorerBlock.js.map +1 -1
- package/dist/client/blocks/library/MermaidBlock.d.ts.map +1 -1
- package/dist/client/blocks/library/MermaidBlock.js +73 -44
- package/dist/client/blocks/library/MermaidBlock.js.map +1 -1
- package/dist/client/blocks/library/OpenApiSpecBlock.d.ts.map +1 -1
- package/dist/client/blocks/library/OpenApiSpecBlock.js +3 -2
- package/dist/client/blocks/library/OpenApiSpecBlock.js.map +1 -1
- package/dist/client/blocks/library/checklist.d.ts.map +1 -1
- package/dist/client/blocks/library/checklist.js +1 -0
- package/dist/client/blocks/library/checklist.js.map +1 -1
- package/dist/client/blocks/library/code-tabs.d.ts.map +1 -1
- package/dist/client/blocks/library/code-tabs.js +183 -102
- package/dist/client/blocks/library/code-tabs.js.map +1 -1
- package/dist/client/blocks/library/columns.config.d.ts +60 -0
- package/dist/client/blocks/library/columns.config.d.ts.map +1 -0
- package/dist/client/blocks/library/columns.config.js +37 -0
- package/dist/client/blocks/library/columns.config.js.map +1 -0
- package/dist/client/blocks/library/columns.d.ts +25 -0
- package/dist/client/blocks/library/columns.d.ts.map +1 -0
- package/dist/client/blocks/library/columns.js +199 -0
- package/dist/client/blocks/library/columns.js.map +1 -0
- package/dist/client/blocks/library/dev-doc-ui.d.ts +2 -1
- package/dist/client/blocks/library/dev-doc-ui.d.ts.map +1 -1
- package/dist/client/blocks/library/dev-doc-ui.js +2 -1
- package/dist/client/blocks/library/dev-doc-ui.js.map +1 -1
- package/dist/client/blocks/library/html.d.ts +1 -1
- package/dist/client/blocks/library/html.d.ts.map +1 -1
- package/dist/client/blocks/library/html.js +34 -4
- package/dist/client/blocks/library/html.js.map +1 -1
- package/dist/client/blocks/library/json-explorer.config.d.ts +3 -1
- package/dist/client/blocks/library/json-explorer.config.d.ts.map +1 -1
- package/dist/client/blocks/library/json-explorer.config.js +30 -1
- package/dist/client/blocks/library/json-explorer.config.js.map +1 -1
- package/dist/client/blocks/library/server-specs.d.ts.map +1 -1
- package/dist/client/blocks/library/server-specs.js +13 -3
- package/dist/client/blocks/library/server-specs.js.map +1 -1
- package/dist/client/blocks/library/specs.d.ts +4 -4
- package/dist/client/blocks/library/specs.d.ts.map +1 -1
- package/dist/client/blocks/library/specs.js +21 -16
- package/dist/client/blocks/library/specs.js.map +1 -1
- package/dist/client/blocks/library/table.config.d.ts +3 -0
- package/dist/client/blocks/library/table.config.d.ts.map +1 -1
- package/dist/client/blocks/library/table.config.js +13 -1
- package/dist/client/blocks/library/table.config.js.map +1 -1
- package/dist/client/blocks/library/table.d.ts.map +1 -1
- package/dist/client/blocks/library/table.js +90 -9
- package/dist/client/blocks/library/table.js.map +1 -1
- package/dist/client/blocks/library/tabs.config.d.ts +16 -8
- package/dist/client/blocks/library/tabs.config.d.ts.map +1 -1
- package/dist/client/blocks/library/tabs.config.js +10 -4
- package/dist/client/blocks/library/tabs.config.js.map +1 -1
- package/dist/client/blocks/library/tabs.d.ts.map +1 -1
- package/dist/client/blocks/library/tabs.js +146 -21
- package/dist/client/blocks/library/tabs.js.map +1 -1
- package/dist/client/blocks/server.d.ts +2 -1
- package/dist/client/blocks/server.d.ts.map +1 -1
- package/dist/client/blocks/server.js +1 -0
- package/dist/client/blocks/server.js.map +1 -1
- package/dist/client/blocks/types.d.ts +99 -9
- package/dist/client/blocks/types.d.ts.map +1 -1
- package/dist/client/blocks/types.js.map +1 -1
- package/dist/client/index.d.ts +1 -1
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +2 -2
- package/dist/client/index.js.map +1 -1
- package/dist/client/rich-markdown-editor/BubbleToolbar.d.ts.map +1 -1
- package/dist/client/rich-markdown-editor/BubbleToolbar.js +13 -3
- package/dist/client/rich-markdown-editor/BubbleToolbar.js.map +1 -1
- package/dist/client/rich-markdown-editor/DragHandle.d.ts +49 -4
- package/dist/client/rich-markdown-editor/DragHandle.d.ts.map +1 -1
- package/dist/client/rich-markdown-editor/DragHandle.js +656 -88
- package/dist/client/rich-markdown-editor/DragHandle.js.map +1 -1
- package/dist/client/rich-markdown-editor/RegistryBlockNode.d.ts +10 -1
- package/dist/client/rich-markdown-editor/RegistryBlockNode.d.ts.map +1 -1
- package/dist/client/rich-markdown-editor/RegistryBlockNode.js +180 -15
- package/dist/client/rich-markdown-editor/RegistryBlockNode.js.map +1 -1
- package/dist/client/rich-markdown-editor/SharedRichEditor.d.ts +2 -1
- package/dist/client/rich-markdown-editor/SharedRichEditor.d.ts.map +1 -1
- package/dist/client/rich-markdown-editor/SharedRichEditor.js +3 -1
- package/dist/client/rich-markdown-editor/SharedRichEditor.js.map +1 -1
- package/dist/client/rich-markdown-editor/SlashCommandMenu.d.ts +5 -0
- package/dist/client/rich-markdown-editor/SlashCommandMenu.d.ts.map +1 -1
- package/dist/client/rich-markdown-editor/SlashCommandMenu.js +33 -5
- package/dist/client/rich-markdown-editor/SlashCommandMenu.js.map +1 -1
- package/dist/client/rich-markdown-editor/index.d.ts +3 -3
- package/dist/client/rich-markdown-editor/index.d.ts.map +1 -1
- package/dist/client/rich-markdown-editor/index.js +2 -2
- package/dist/client/rich-markdown-editor/index.js.map +1 -1
- package/dist/client/rich-markdown-editor/registrySlashCommands.d.ts +14 -0
- package/dist/client/rich-markdown-editor/registrySlashCommands.d.ts.map +1 -1
- package/dist/client/rich-markdown-editor/registrySlashCommands.js +38 -0
- package/dist/client/rich-markdown-editor/registrySlashCommands.js.map +1 -1
- package/dist/client/rich-markdown-editor/useCollabReconcile.d.ts +1 -0
- package/dist/client/rich-markdown-editor/useCollabReconcile.d.ts.map +1 -1
- package/dist/client/rich-markdown-editor/useCollabReconcile.js +4 -0
- package/dist/client/rich-markdown-editor/useCollabReconcile.js.map +1 -1
- package/dist/client/settings/SettingsPanel.d.ts.map +1 -1
- package/dist/client/settings/SettingsPanel.js +11 -19
- package/dist/client/settings/SettingsPanel.js.map +1 -1
- package/dist/client/use-chat-models.d.ts.map +1 -1
- package/dist/client/use-chat-models.js +2 -5
- package/dist/client/use-chat-models.js.map +1 -1
- package/dist/db/client.d.ts.map +1 -1
- package/dist/db/client.js +17 -1
- package/dist/db/client.js.map +1 -1
- package/dist/deploy/build.d.ts.map +1 -1
- package/dist/deploy/build.js +2 -1
- package/dist/deploy/build.js.map +1 -1
- package/dist/deploy/route-discovery.d.ts +29 -0
- package/dist/deploy/route-discovery.d.ts.map +1 -1
- package/dist/deploy/route-discovery.js +158 -11
- package/dist/deploy/route-discovery.js.map +1 -1
- package/dist/server/auth.d.ts +2 -0
- package/dist/server/auth.d.ts.map +1 -1
- package/dist/server/auth.js +9 -0
- package/dist/server/auth.js.map +1 -1
- package/dist/sharing/access.d.ts +4 -2
- package/dist/sharing/access.d.ts.map +1 -1
- package/dist/sharing/access.js +8 -3
- package/dist/sharing/access.js.map +1 -1
- package/dist/sharing/actions/set-resource-visibility.d.ts.map +1 -1
- package/dist/sharing/actions/set-resource-visibility.js +2 -3
- package/dist/sharing/actions/set-resource-visibility.js.map +1 -1
- package/dist/sharing/registry.d.ts +13 -0
- package/dist/sharing/registry.d.ts.map +1 -1
- package/dist/sharing/registry.js.map +1 -1
- package/dist/styles/rich-markdown-editor.css +15 -0
- package/dist/templates/default/.agents/skills/actions/SKILL.md +96 -11
- package/dist/templates/default/.agents/skills/adding-a-feature/SKILL.md +126 -26
- package/dist/templates/default/.agents/skills/capture-learnings/SKILL.md +56 -30
- package/dist/templates/default/.agents/skills/create-skill/SKILL.md +28 -0
- package/dist/templates/default/.agents/skills/delegate-to-agent/SKILL.md +75 -5
- package/dist/templates/default/.agents/skills/frontend-design/SKILL.md +17 -0
- package/dist/templates/default/.agents/skills/real-time-collab/SKILL.md +99 -124
- package/dist/templates/default/.agents/skills/real-time-sync/SKILL.md +43 -10
- package/dist/templates/default/.agents/skills/security/SKILL.md +162 -144
- package/dist/templates/default/.agents/skills/self-modifying-code/SKILL.md +5 -3
- package/dist/templates/default/.agents/skills/shadcn-ui/SKILL.md +15 -0
- package/dist/templates/default/.agents/skills/storing-data/SKILL.md +116 -83
- package/dist/templates/default/DEVELOPING.md +10 -13
- package/dist/templates/workspace-core/.agents/skills/client-methods/references/legacy-client-fetch-audit-2026-06-03.md +9 -0
- package/dist/templates/workspace-core/.agents/skills/writing-agent-instructions/SKILL.md +27 -0
- package/docs/content/template-plan.md +5 -3
- package/docs/content/visual-plans.md +5 -2
- package/package.json +16 -1
- package/src/templates/default/.agents/skills/actions/SKILL.md +96 -11
- package/src/templates/default/.agents/skills/adding-a-feature/SKILL.md +126 -26
- package/src/templates/default/.agents/skills/capture-learnings/SKILL.md +56 -30
- package/src/templates/default/.agents/skills/create-skill/SKILL.md +28 -0
- package/src/templates/default/.agents/skills/delegate-to-agent/SKILL.md +75 -5
- package/src/templates/default/.agents/skills/frontend-design/SKILL.md +17 -0
- package/src/templates/default/.agents/skills/real-time-collab/SKILL.md +99 -124
- package/src/templates/default/.agents/skills/real-time-sync/SKILL.md +43 -10
- package/src/templates/default/.agents/skills/security/SKILL.md +162 -144
- package/src/templates/default/.agents/skills/self-modifying-code/SKILL.md +5 -3
- package/src/templates/default/.agents/skills/shadcn-ui/SKILL.md +15 -0
- package/src/templates/default/.agents/skills/storing-data/SKILL.md +116 -83
- package/src/templates/default/DEVELOPING.md +10 -13
- package/src/templates/workspace-core/.agents/skills/client-methods/references/legacy-client-fetch-audit-2026-06-03.md +9 -0
- package/src/templates/workspace-core/.agents/skills/writing-agent-instructions/SKILL.md +27 -0
|
@@ -1,128 +1,161 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: storing-data
|
|
3
3
|
description: >-
|
|
4
|
-
How
|
|
5
|
-
deciding
|
|
6
|
-
|
|
4
|
+
How to store application data in agent-native apps. All data lives in SQL.
|
|
5
|
+
Use when adding data models, deciding where to store data, or reading/writing
|
|
6
|
+
application data.
|
|
7
|
+
metadata:
|
|
8
|
+
internal: true
|
|
7
9
|
---
|
|
8
10
|
|
|
9
|
-
# Storing Data
|
|
11
|
+
# Storing Data — SQL is the Source of Truth
|
|
10
12
|
|
|
11
|
-
##
|
|
13
|
+
## Rule
|
|
12
14
|
|
|
13
|
-
All data lives in
|
|
15
|
+
All application data lives in **SQL** (SQLite locally, persistent database in production). The agent and UI share the same database. Do not store durable app data in the filesystem.
|
|
14
16
|
|
|
15
|
-
|
|
17
|
+
## How It Works
|
|
16
18
|
|
|
17
|
-
|
|
19
|
+
Agent-native apps use Drizzle ORM over the configured SQL backend. Local development works out of the box with a SQLite file at `data/app.db`; production and shared preview deploys need a persistent `DATABASE_URL` because container/serverless filesystems can reset. The code should behave the same across backends, but the local SQLite file is not durable once deployed.
|
|
18
20
|
|
|
19
|
-
|
|
21
|
+
For app code, use Drizzle's schema/query DSL by default. Raw SQL is an escape hatch for additive migrations, health checks, or one-off maintenance, not the normal way to build features.
|
|
20
22
|
|
|
21
|
-
|
|
22
|
-
import { getSetting, putSetting } from "@agent-native/core/settings";
|
|
23
|
+
### Core SQL Stores (auto-created, available in all templates)
|
|
23
24
|
|
|
24
|
-
|
|
25
|
-
|
|
25
|
+
| Store | Purpose | Access |
|
|
26
|
+
| ------------------- | ---------------------------------------------------- | ------------------------------------------ |
|
|
27
|
+
| `application_state` | Ephemeral UI state (compose windows, navigation) | `readAppState()` / `writeAppState()` |
|
|
28
|
+
| `settings` | Persistent KV config (preferences, app settings) | `getSetting()` / `putSetting()` |
|
|
29
|
+
| `oauth_tokens` | OAuth credentials | `@agent-native/core/oauth-tokens` |
|
|
30
|
+
| `sessions` | Auth sessions | `@agent-native/core/server` |
|
|
26
31
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
32
|
+
### Domain Data (per-template)
|
|
33
|
+
|
|
34
|
+
Define schema with the framework Drizzle helpers in `server/db/schema.ts`. Get a database instance with `const db = getDb()` from `server/db/index.ts`. All queries are async.
|
|
30
35
|
|
|
31
|
-
From scripts:
|
|
32
36
|
```ts
|
|
33
|
-
import {
|
|
34
|
-
|
|
35
|
-
|
|
37
|
+
import { eq } from "drizzle-orm";
|
|
38
|
+
import { table, text, integer, now } from "@agent-native/core/db/schema";
|
|
39
|
+
|
|
40
|
+
export const tasks = table("tasks", {
|
|
41
|
+
id: text("id").primaryKey(),
|
|
42
|
+
title: text("title").notNull(),
|
|
43
|
+
completed: integer("completed", { mode: "boolean" })
|
|
44
|
+
.notNull()
|
|
45
|
+
.default(false),
|
|
46
|
+
createdAt: text("created_at").notNull().default(now()),
|
|
47
|
+
});
|
|
36
48
|
|
|
37
|
-
|
|
49
|
+
const rows = await db.select().from(tasks).where(eq(tasks.id, taskId));
|
|
50
|
+
```
|
|
38
51
|
|
|
39
|
-
|
|
52
|
+
Never import `sqliteTable` / `pgTable` or column helpers from `drizzle-orm/sqlite-core` or `drizzle-orm/pg-core` in app templates. Use `@agent-native/core/db/schema` so the same schema can run against SQLite, Postgres, libSQL/Turso, D1, and other supported backends.
|
|
40
53
|
|
|
41
|
-
|
|
54
|
+
| Template | Tables |
|
|
55
|
+
| ------------ | --------------------------------------------- |
|
|
56
|
+
| **Mail** | emails, labels (+ Gmail API when connected) |
|
|
57
|
+
| **Calendar** | events, bookings |
|
|
58
|
+
| **Forms** | forms, responses |
|
|
59
|
+
| **Content** | documents |
|
|
60
|
+
| **Slides** | decks (JSON stored in SQL) |
|
|
61
|
+
| **Videos** | compositions in registry + localStorage |
|
|
42
62
|
|
|
43
|
-
|
|
44
|
-
import { readAppState, writeAppState, deleteAppState, listAppState } from "@agent-native/core/application-state";
|
|
63
|
+
### Agent Access
|
|
45
64
|
|
|
46
|
-
|
|
47
|
-
await writeAppState("navigate", { view: "inbox", threadId: "t-123" });
|
|
65
|
+
The agent uses app-specific actions to read/write the database. Core DB scripts are for inspection and maintenance, not for implementing normal product behavior:
|
|
48
66
|
|
|
49
|
-
|
|
50
|
-
|
|
67
|
+
- `pnpm action db-schema` — Show all tables, columns, types
|
|
68
|
+
- `pnpm action db-query --sql "SELECT * FROM forms"` — Run SELECT queries
|
|
69
|
+
- `pnpm action db-exec --sql "UPDATE ..."` — Last-resort ad-hoc maintenance for short columns, multi-column writes, or computed updates when no domain action exists. For several related writes, prefer `--statements '[{"sql":"...","args":[...]}]'` so they run sequentially in one transaction. Schema changes are blocked; use reviewed additive migrations/startup code instead.
|
|
70
|
+
- `pnpm action db-patch --table <t> --column <c> --where "<clause>" --find "<old>" --replace "<new>"` — **Surgical search/replace on a large text column.** Sends the diff instead of re-transmitting the whole value, so it's dramatically more token-efficient than `db-exec UPDATE` when editing multi-kilobyte documents, slide HTML, dashboard/form JSON, etc. Targets exactly one row per call — narrow `--where` by primary key. Supports `--edits '[{find,replace},...]'` for batch edits and `--all` to replace every occurrence.
|
|
71
|
+
- App-specific actions for domain operations — **always prefer these over raw SQL when one exists.** They encode business rules, power the client action hooks, and for editor-backed tables (documents, slides) also push live Yjs updates to open collaborative editors. `db-patch` is the generic fallback for tables without a dedicated edit action.
|
|
51
72
|
|
|
52
|
-
|
|
53
|
-
const drafts = await listAppState("compose-");
|
|
73
|
+
**For one-off maintenance, how to choose between `db-exec UPDATE` and `db-patch`:**
|
|
54
74
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
75
|
+
| Scenario | Use |
|
|
76
|
+
| -------------------------------------------------------------- | ------------ |
|
|
77
|
+
| `SET status = 'published'` on one row | `db-exec` |
|
|
78
|
+
| `SET calories = calories + 50` | `db-exec` |
|
|
79
|
+
| Updating several columns at once | `db-exec` |
|
|
80
|
+
| Inserting/updating several rows as one logical operation | `db-exec --statements` |
|
|
81
|
+
| Fixing a typo in a 50KB markdown document's `content` column | `db-patch` |
|
|
82
|
+
| Changing a single key in a dashboard's JSON blob | `db-patch` |
|
|
83
|
+
| Tweaking one paragraph of slide HTML stored in `decks.data` | `db-patch` |
|
|
84
|
+
| Any edit where you'd otherwise re-send thousands of characters | `db-patch` |
|
|
58
85
|
|
|
59
|
-
|
|
86
|
+
All of these honor the per-user / per-org data scoping — you can't read or write rows outside the current user's data, regardless of which tool you choose.
|
|
60
87
|
|
|
61
|
-
###
|
|
88
|
+
### Frontend Access
|
|
62
89
|
|
|
63
|
-
|
|
90
|
+
The frontend calls actions using React Query hooks from the client API. The framework owns the HTTP transport behind these hooks, so components should not call action routes with raw `fetch`.
|
|
64
91
|
|
|
65
92
|
```ts
|
|
66
|
-
import {
|
|
93
|
+
import { useActionQuery, useActionMutation } from "@agent-native/core/client";
|
|
67
94
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
endTime: integer("end_time").notNull(),
|
|
74
|
-
});
|
|
95
|
+
// Read data
|
|
96
|
+
const { data } = useActionQuery("list-meals", { date: "2025-01-01" });
|
|
97
|
+
|
|
98
|
+
// Write data
|
|
99
|
+
const { mutate } = useActionMutation("log-meal");
|
|
75
100
|
```
|
|
76
101
|
|
|
77
|
-
|
|
102
|
+
Actions are the **preferred way** for the frontend to access data. You rarely need custom `/api/` routes — only for file uploads, streaming, webhooks, or OAuth callbacks.
|
|
78
103
|
|
|
79
|
-
###
|
|
104
|
+
### Production / Cloud Deployment
|
|
80
105
|
|
|
81
|
-
|
|
106
|
+
Local SQLite works out of the box for development. To deploy to production or any environment where data must survive restarts:
|
|
82
107
|
|
|
83
|
-
|
|
84
|
-
|
|
108
|
+
1. Set `DATABASE_URL` to a persistent SQL database.
|
|
109
|
+
2. Set `DATABASE_AUTH_TOKEN` only when the provider requires a separate token, such as Turso/libSQL.
|
|
110
|
+
3. No code changes should be needed when the schema and queries stay portable.
|
|
85
111
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
112
|
+
Turso is one valid option, not the required option. Common choices include Neon or Supabase Postgres, Turso/libSQL, plain Postgres, durable SQLite, Cloudflare D1 bindings, and managed platform SQL environments when available.
|
|
113
|
+
|
|
114
|
+
### Real-time Sync
|
|
115
|
+
|
|
116
|
+
Polling streams database changes to the UI. When the agent writes to the database via scripts, the UI updates automatically via `useDbSync()` which invalidates React Query caches.
|
|
117
|
+
|
|
118
|
+
## Do
|
|
119
|
+
|
|
120
|
+
- Use Drizzle ORM for structured domain data (forms, bookings, documents)
|
|
121
|
+
- Use Drizzle query builder methods (`select`, `insert`, `update`, `delete`) and portable operators from `drizzle-orm` (`eq`, `and`, `or`, `inArray`, `desc`, etc.) for app reads/writes
|
|
122
|
+
- Use framework schema helpers from `@agent-native/core/db/schema`, not dialect-specific Drizzle imports
|
|
123
|
+
- Use the `settings` store for app configuration and user preferences
|
|
124
|
+
- Use `application-state` for ephemeral UI state that the agent and UI share
|
|
125
|
+
- Use `oauth-tokens` for OAuth credentials
|
|
126
|
+
- Use core DB scripts (`db-schema`, `db-query`, `db-exec`, `db-patch`) for ad-hoc database operations
|
|
127
|
+
- Use `db-exec --statements` instead of several separate `db-exec` calls for related writes; it is faster and rolls back the whole batch if one statement fails
|
|
128
|
+
- Reach for `db-patch` instead of `db-exec UPDATE` whenever you're making a small change to a large text/JSON column — it's much cheaper on tokens
|
|
90
129
|
|
|
91
|
-
|
|
130
|
+
## Don't
|
|
92
131
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
132
|
+
- Don't store structured app data as JSON files
|
|
133
|
+
- Don't store app state in localStorage, sessionStorage, or cookies (except for UI-only preferences like sidebar width)
|
|
134
|
+
- Don't keep state only in memory (server variables, global stores)
|
|
135
|
+
- Don't use Redis or any external state store for app data
|
|
136
|
+
- Don't implement product features with raw SQL or `getDbExec()` when Drizzle can express the query
|
|
137
|
+
- Don't write SQLite-only or Postgres-only SQL in app code
|
|
138
|
+
- Don't interpolate user input directly into SQL queries — use Drizzle ORM's query builder
|
|
99
139
|
|
|
100
|
-
##
|
|
140
|
+
## Security
|
|
101
141
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
| User preferences, theme, config | Settings | Persistent KV, SSE notifications, simple read/write |
|
|
105
|
-
| What the user sees on screen | Application State | Ephemeral, real-time sync, agent ↔ UI bridge |
|
|
106
|
-
| Compose drafts, wizard steps | Application State | Temporary, deleted when done |
|
|
107
|
-
| Domain records (forms, bookings) | Drizzle table | Needs schema, queries, relationships |
|
|
108
|
-
| API keys, service tokens, webhook secrets | Secrets / credentials | Encrypted and scoped; never client-readable |
|
|
109
|
-
| OAuth refresh tokens | OAuth Tokens | Secure, per-provider, per-account |
|
|
142
|
+
- **SQL injection** — Use Drizzle ORM's query builder, never raw string interpolation for SQL queries
|
|
143
|
+
- **Validate before writing** — Check data shape before writing, especially for user-submitted data
|
|
110
144
|
|
|
111
|
-
##
|
|
145
|
+
## Application State and Context Awareness
|
|
112
146
|
|
|
113
|
-
|
|
147
|
+
When storing app-state, include **navigation state** — the agent needs to know what the user is looking at. The `application_state` table holds ephemeral UI state that both the agent and UI share. Key patterns:
|
|
114
148
|
|
|
115
|
-
- `
|
|
116
|
-
- `
|
|
117
|
-
-
|
|
118
|
-
- `ACCESS_TOKEN` — production auth token
|
|
149
|
+
- **`navigation` key** — the UI writes current view and selection on every route change. The agent reads this before acting.
|
|
150
|
+
- **`navigate` key** — the agent writes one-shot commands to navigate the UI. The UI processes and deletes them.
|
|
151
|
+
- **Domain-specific keys** (e.g., `compose-{id}`) — bidirectional state for features like email drafts.
|
|
119
152
|
|
|
120
|
-
|
|
121
|
-
appropriate store. User/org/workspace credential values go in the encrypted
|
|
122
|
-
secrets/credential stores, not plain settings rows.
|
|
153
|
+
When adding a new data model or feature, also consider what navigation and selection state needs to be exposed via application-state. See the **context-awareness** skill for the full pattern.
|
|
123
154
|
|
|
124
|
-
##
|
|
155
|
+
## Related Skills
|
|
125
156
|
|
|
126
|
-
- **
|
|
127
|
-
- **
|
|
128
|
-
- **
|
|
157
|
+
- **context-awareness** — How to expose navigation and selection state via application-state
|
|
158
|
+
- **real-time-sync** — Set up polling so the UI updates when the database changes
|
|
159
|
+
- **actions** — Create actions with `defineAction` to query the database
|
|
160
|
+
- **client-methods** — Keep route details behind named client helpers/hooks
|
|
161
|
+
- **self-modifying-code** — The agent can also modify the app's source code
|
|
@@ -6,7 +6,7 @@ This guide is for development-mode agents editing this app's source code. For ap
|
|
|
6
6
|
|
|
7
7
|
**Client-side-first rendering:** This app uses React Router v7 framework mode with `ssr: true`, but all app content renders **client-side only**. The server renders only the HTML shell (meta tags, styles, scripts) plus a loading spinner. This is enforced by the `ClientOnly` wrapper in `root.tsx` — never remove it. Browser APIs (`window`, `localStorage`, `new Date()`) are safe to use anywhere in app code because components never run on the server.
|
|
8
8
|
|
|
9
|
-
**Do NOT fetch data server-side** in route loaders. The standard pattern is:
|
|
9
|
+
**Do NOT fetch data server-side** in route loaders unless the page genuinely needs SEO/OG content. The standard pattern is: SSR renders the shell, client hydrates, and React reads/writes normal app data through actions with `useActionQuery` / `useActionMutation`.
|
|
10
10
|
|
|
11
11
|
## Adding a Page
|
|
12
12
|
|
|
@@ -30,7 +30,7 @@ In a workspace, this app can be mounted under `/<app-id>`. React Router already
|
|
|
30
30
|
| `app/routes/review.tsx` | `/review` | `/<app-id>/review` |
|
|
31
31
|
| `app/routes/$id.tsx` | `/:id` | `/<app-id>/:id` |
|
|
32
32
|
|
|
33
|
-
Use `<Link to="/review">` and `navigate("/review")` inside this app. Do not prefix React Router paths with `/<app-id>` or the URL can double-prefix, e.g. `/<app-id>/<app-id>/review`. Use `appPath()` for raw `href`s/static assets, `
|
|
33
|
+
Use `<Link to="/review">` and `navigate("/review")` inside this app. Do not prefix React Router paths with `/<app-id>` or the URL can double-prefix, e.g. `/<app-id>/<app-id>/review`. Use `appPath()` for raw `href`s/static assets, `agentNativePath()` for `/_agent-native/*`, and `appApiPath()` only for legitimate route-only `/api/*` endpoints.
|
|
34
34
|
|
|
35
35
|
Each route file exports a default component and optional `meta()`:
|
|
36
36
|
|
|
@@ -46,17 +46,15 @@ export default function MyPageRoute() {
|
|
|
46
46
|
}
|
|
47
47
|
```
|
|
48
48
|
|
|
49
|
-
## Adding
|
|
49
|
+
## Adding App Data
|
|
50
50
|
|
|
51
|
-
|
|
51
|
+
Normal app data starts as an action, not a custom route. Add `actions/<verb>-<resource>.ts` with `defineAction`, mark reads with `http: { method: "GET" }`, and call reads/writes from React with `useActionQuery` / `useActionMutation` from `@agent-native/core/client`. This keeps the UI and agent on one contract and lets mutating actions refresh action-backed queries automatically.
|
|
52
52
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
server/routes/api/
|
|
56
|
-
server/routes/api/items/[id].patch.ts → PATCH /api/items/:id
|
|
57
|
-
```
|
|
53
|
+
## Adding a Route-Only Endpoint
|
|
54
|
+
|
|
55
|
+
Use `server/routes/api/` only for protocols that cannot be modeled as JSON actions: multipart uploads, streaming/SSE/WebSocket, webhooks, OAuth callbacks/redirects, public SEO/OG endpoints, or binary/static asset serving. Do not add `/api/*` routes for normal CRUD, data queries, or pass-through wrappers around actions; the action endpoint already exists at `/_agent-native/actions/:name`.
|
|
58
56
|
|
|
59
|
-
Each
|
|
57
|
+
Each route-only endpoint still exports a default `defineEventHandler`, but keep shared app logic in actions or server libraries so agent and UI behavior do not fork.
|
|
60
58
|
|
|
61
59
|
## Server Plugins
|
|
62
60
|
|
|
@@ -84,10 +82,9 @@ export default defineNitroPlugin(async (nitroApp) => {
|
|
|
84
82
|
| Agent chat context state helpers | Optional advanced helpers for two-way sync with staged context chips |
|
|
85
83
|
| `agentChat` | Send messages to agent from scripts (server-side) |
|
|
86
84
|
|
|
87
|
-
## Adding
|
|
85
|
+
## Adding an Action
|
|
88
86
|
|
|
89
|
-
Create `actions
|
|
90
|
-
Run with: `pnpm action my-script --arg value`
|
|
87
|
+
Create `actions/<verb>-<resource>.ts` with `defineAction`. Run with `pnpm action <name> --id value`; React callers should use `useActionQuery` for GET actions and `useActionMutation` for mutating actions, not a matching `/api/*` wrapper.
|
|
91
88
|
|
|
92
89
|
## Sending to Agent Chat
|
|
93
90
|
|
|
@@ -7,6 +7,11 @@ contracts; some need new actions or helper modules first.
|
|
|
7
7
|
|
|
8
8
|
## Highest Priority
|
|
9
9
|
|
|
10
|
+
- 2026-06-07 follow-up: the same high-priority route-first clusters are still
|
|
11
|
+
present. The biggest migrations remain Analytics, Calendar, Mail, Slides, and
|
|
12
|
+
Content. Do not copy these patterns into new work; when editing the relevant
|
|
13
|
+
area, add or reuse actions first, then call them with `useActionQuery`,
|
|
14
|
+
`useActionMutation`, or `callAction`.
|
|
10
15
|
- `templates/analytics/app/pages/analyses/AnalysesList.tsx`,
|
|
11
16
|
`templates/analytics/app/pages/analyses/AnalysisDetail.tsx`,
|
|
12
17
|
`templates/analytics/app/components/layout/Sidebar.tsx`, and
|
|
@@ -43,6 +48,10 @@ contracts; some need new actions or helper modules first.
|
|
|
43
48
|
- Content comments and versions are partially migrated. Add missing actions such
|
|
44
49
|
as `resolve-comment`, `delete-comment`, `list-document-versions`, and
|
|
45
50
|
`restore-document-version`.
|
|
51
|
+
- Plans version history is the model to copy for new history/rollback work:
|
|
52
|
+
`list-plan-versions`, `get-plan-version`, and `restore-plan-version` are
|
|
53
|
+
action-native, and the UI calls them through action hooks. Do not copy
|
|
54
|
+
Content's legacy document-version `/api/*` helpers into new version panels.
|
|
46
55
|
|
|
47
56
|
## Acceptable Exceptions
|
|
48
57
|
|
|
@@ -74,6 +74,33 @@ Keep one canonical instructions file: `AGENTS.md`. If a client expects
|
|
|
74
74
|
hand-maintained files drift, and the agent ends up with contradictory rules.
|
|
75
75
|
One source of truth, linked where needed.
|
|
76
76
|
|
|
77
|
+
## Keep generated guidance in sync
|
|
78
|
+
|
|
79
|
+
Framework guidance is authored once in this repo and copied outward. Treat
|
|
80
|
+
`.agents/skills/` as the canonical source for shared skills. Generated
|
|
81
|
+
workspace skills in `packages/core/src/templates/workspace-core/.agents/skills/`
|
|
82
|
+
and first-party template copies of shared skills must stay byte-for-byte in
|
|
83
|
+
sync; run `pnpm sync:workspace-skills` after editing a shared skill, and
|
|
84
|
+
`pnpm guard:workspace-skills` before calling the guidance done.
|
|
85
|
+
|
|
86
|
+
Generated app and workspace instructions must teach the same action-first data
|
|
87
|
+
contract:
|
|
88
|
+
|
|
89
|
+
- Normal app data goes through `defineAction` files in `actions/`.
|
|
90
|
+
- React calls actions with `useActionQuery`, `useActionMutation`, or
|
|
91
|
+
`callAction`; route paths are a transport detail hidden behind helpers.
|
|
92
|
+
- Custom `/api/*` routes are only for route-shaped protocols such as uploads,
|
|
93
|
+
streaming, webhooks, OAuth callbacks, public SEO/OG endpoints, or binary
|
|
94
|
+
assets.
|
|
95
|
+
- Do not create pass-through routes whose main job is to call, repackage, or
|
|
96
|
+
re-export an action.
|
|
97
|
+
|
|
98
|
+
When documenting version history, restore, or audit trails, use actions for
|
|
99
|
+
full restorable snapshots (`list-<resource>-versions`,
|
|
100
|
+
`get-<resource>-version`, `restore-<resource>-version`). Do not copy legacy
|
|
101
|
+
raw-route version panels, such as document-version `/api/*` helpers, into new
|
|
102
|
+
features. The Plans version-history pattern is the preferred model.
|
|
103
|
+
|
|
77
104
|
## SKILL.md frontmatter must say what AND when
|
|
78
105
|
|
|
79
106
|
The `description` is the only thing the agent sees when deciding whether to read
|
|
@@ -33,7 +33,10 @@ The command installs `/visual-plan` plus the companion commands:
|
|
|
33
33
|
- `/ui-plan` for UI-first plans with mockups, states, and screen-level review.
|
|
34
34
|
- `/prototype-plan` for clickable prototype-first plans with live comments.
|
|
35
35
|
- `/visual-questions` for visual intake before a plan.
|
|
36
|
-
|
|
36
|
+
|
|
37
|
+
Use `/visual-plan` for both fresh plans and existing Codex, Claude Code,
|
|
38
|
+
Markdown, or pasted plans; when source plan text already exists, the agent builds
|
|
39
|
+
from that plan instead of starting over.
|
|
37
40
|
|
|
38
41
|
By default the CLI targets Codex. Add `--client claude-code` or `--client all`
|
|
39
42
|
when you want to configure another host:
|
|
@@ -62,7 +65,6 @@ After installation, ask your agent for the command that fits the work:
|
|
|
62
65
|
- `/prototype-plan` creates a clickable prototype above the plan document, with
|
|
63
66
|
static mocks, comments, and a focused browser popout.
|
|
64
67
|
- `/visual-questions` opens a visual intake questionnaire before planning.
|
|
65
|
-
- `/visualize-plan` imports a plan you already have and makes it reviewable.
|
|
66
68
|
|
|
67
69
|
The agent should inspect the codebase first, then create the visual plan when a
|
|
68
70
|
wrong direction would be costly. The returned Plans link opens the review UI so
|
|
@@ -101,7 +103,7 @@ it to the agent starts a revision turn against the existing plan.
|
|
|
101
103
|
- "Create a `/ui-plan` for the new onboarding screen with mobile and desktop states."
|
|
102
104
|
- "Create a `/prototype-plan` for the checkout flow so I can click through it."
|
|
103
105
|
- "Use `/visual-questions` to help me choose the dashboard direction first."
|
|
104
|
-
- "
|
|
106
|
+
- "Use `/visual-plan` on the Markdown plan below and make it easier to review."
|
|
105
107
|
|
|
106
108
|
## For developers
|
|
107
109
|
|
|
@@ -20,7 +20,7 @@ Install with the Agent-Native CLI. The command installs the skill instructions,
|
|
|
20
20
|
agent-native skills add visual-plan
|
|
21
21
|
```
|
|
22
22
|
|
|
23
|
-
Authentication is a one-time browser sign-in at setup — this is intended, and it is what lets the agent persist and share the plans it generates. This also installs the companion commands `/ui-plan`, `/
|
|
23
|
+
Authentication is a one-time browser sign-in at setup — this is intended, and it is what lets the agent persist and share the plans it generates. This also installs the companion commands `/ui-plan`, `/prototype-plan`, `/plan-design`, and `/visual-questions` (see [Invoking the skill](#invoke)).
|
|
24
24
|
|
|
25
25
|
What the auth step does depends on your client:
|
|
26
26
|
|
|
@@ -40,11 +40,14 @@ Once installed, use the slash command that fits the work:
|
|
|
40
40
|
|
|
41
41
|
- `/visual-plan` — the canonical command for any rich plan (architecture, backend, refactors, UI).
|
|
42
42
|
- `/ui-plan` — UI-first work that should start with the screens.
|
|
43
|
+
- `/prototype-plan` — prototype-first work that should start with a clickable flow.
|
|
44
|
+
- `/plan-design` — full-fidelity branded UI direction before implementation.
|
|
43
45
|
- `/visual-questions` — a short visual intake form before planning.
|
|
44
|
-
- `/visualize-plan` — turn an existing Codex, Claude Code, Markdown, or pasted plan into a visual companion.
|
|
45
46
|
|
|
46
47
|
The agent gates hard: it only builds a polished visual plan when a wrong direction would be costly, and skips it for trivial, unambiguous work. Each command generates a plan and opens the editor.
|
|
47
48
|
|
|
49
|
+
When a Codex, Claude Code, Markdown, or pasted plan already exists, use `/visual-plan`. The agent should preserve that source plan and build the richer review surface from it instead of starting over.
|
|
50
|
+
|
|
48
51
|
When a plan has unresolved decisions that are useful to answer after the first pass, the agent can put them in an **Open Questions** form at the bottom of the same plan. You can choose single or multiple options, fill in freeform answers, and send the answers back to the agent to revise the plan.
|
|
49
52
|
|
|
50
53
|
## Editing in the browser as a guest {#guest}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agent-native/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.40.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=22"
|
|
@@ -211,6 +211,8 @@
|
|
|
211
211
|
"@ai-sdk/groq": ">=3",
|
|
212
212
|
"@ai-sdk/mistral": ">=3",
|
|
213
213
|
"@ai-sdk/openai": ">=3",
|
|
214
|
+
"@excalidraw/excalidraw": ">=0.18",
|
|
215
|
+
"@excalidraw/mermaid-to-excalidraw": ">=2",
|
|
214
216
|
"@openrouter/ai-sdk-provider": ">=2",
|
|
215
217
|
"@supabase/supabase-js": ">=2",
|
|
216
218
|
"@tabler/icons-react": ">=3",
|
|
@@ -224,6 +226,7 @@
|
|
|
224
226
|
"ai-sdk-ollama": ">=3",
|
|
225
227
|
"convex": ">=1",
|
|
226
228
|
"drizzle-kit": ">=0.31",
|
|
229
|
+
"mermaid": ">=11",
|
|
227
230
|
"node-pty": ">=1",
|
|
228
231
|
"postgres": ">=3",
|
|
229
232
|
"react": ">=18",
|
|
@@ -259,6 +262,12 @@
|
|
|
259
262
|
"@ai-sdk/cohere": {
|
|
260
263
|
"optional": true
|
|
261
264
|
},
|
|
265
|
+
"@excalidraw/excalidraw": {
|
|
266
|
+
"optional": true
|
|
267
|
+
},
|
|
268
|
+
"@excalidraw/mermaid-to-excalidraw": {
|
|
269
|
+
"optional": true
|
|
270
|
+
},
|
|
262
271
|
"ai-sdk-ollama": {
|
|
263
272
|
"optional": true
|
|
264
273
|
},
|
|
@@ -292,6 +301,9 @@
|
|
|
292
301
|
"drizzle-kit": {
|
|
293
302
|
"optional": true
|
|
294
303
|
},
|
|
304
|
+
"mermaid": {
|
|
305
|
+
"optional": true
|
|
306
|
+
},
|
|
295
307
|
"@xterm/xterm": {
|
|
296
308
|
"optional": true
|
|
297
309
|
},
|
|
@@ -318,6 +330,8 @@
|
|
|
318
330
|
"@ai-sdk/openai": "^3.0.53",
|
|
319
331
|
"@assistant-ui/react": "^0.12.19",
|
|
320
332
|
"@assistant-ui/react-markdown": "^0.12.6",
|
|
333
|
+
"@excalidraw/excalidraw": "0.18.1",
|
|
334
|
+
"@excalidraw/mermaid-to-excalidraw": "2.2.2",
|
|
321
335
|
"@react-router/dev": "^7.16.0",
|
|
322
336
|
"@react-router/fs-routes": "^7.16.0",
|
|
323
337
|
"@supabase/supabase-js": "^2.49.0",
|
|
@@ -340,6 +354,7 @@
|
|
|
340
354
|
"autoprefixer": "^10.4.21",
|
|
341
355
|
"drizzle-kit": "^0.31.10",
|
|
342
356
|
"express": "^5.2.1",
|
|
357
|
+
"mermaid": "11.15.0",
|
|
343
358
|
"node-pty": "^1.1.0",
|
|
344
359
|
"playwright": "^1.60.0",
|
|
345
360
|
"react": "^19.2.7",
|