@agent-native/core 0.63.2 → 0.63.4
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/client/blocks/library/AnnotatedCodeBlock.d.ts.map +1 -1
- package/dist/client/blocks/library/AnnotatedCodeBlock.js +23 -19
- package/dist/client/blocks/library/AnnotatedCodeBlock.js.map +1 -1
- package/dist/client/blocks/library/diagram.d.ts.map +1 -1
- package/dist/client/blocks/library/diagram.js +10 -11
- package/dist/client/blocks/library/diagram.js.map +1 -1
- package/dist/client/blocks/library/wireframe.d.ts.map +1 -1
- package/dist/client/blocks/library/wireframe.js +2 -1
- package/dist/client/blocks/library/wireframe.js.map +1 -1
- package/dist/server/auth.d.ts.map +1 -1
- package/dist/server/auth.js +5 -1
- package/dist/server/auth.js.map +1 -1
- package/dist/server/onboarding-html.d.ts.map +1 -1
- package/dist/server/onboarding-html.js +50 -5
- package/dist/server/onboarding-html.js.map +1 -1
- package/dist/styles/blocks.css +25 -3
- package/docs/content/a2a-protocol.md +48 -10
- package/docs/content/actions.md +35 -16
- package/docs/content/agent-mentions.md +25 -32
- package/docs/content/agent-surfaces.md +31 -0
- package/docs/content/agent-teams.md +17 -14
- package/docs/content/agent-web-surfaces.md +24 -15
- package/docs/content/authentication.md +21 -0
- package/docs/content/automations.md +37 -21
- package/docs/content/blueprint-installer.md +7 -0
- package/docs/content/cli-adapters.md +7 -0
- package/docs/content/client.md +14 -0
- package/docs/content/cloneable-saas.md +14 -0
- package/docs/content/code-agents-ui.md +27 -0
- package/docs/content/components.md +21 -0
- package/docs/content/context-awareness.md +33 -48
- package/docs/content/creating-templates.md +43 -52
- package/docs/content/cross-app-sso.md +41 -0
- package/docs/content/database.md +41 -21
- package/docs/content/deployment.md +23 -6
- package/docs/content/dispatch.md +27 -0
- package/docs/content/drop-in-agent.md +26 -27
- package/docs/content/durable-resume.md +13 -1
- package/docs/content/embedding-sdk.md +14 -0
- package/docs/content/evals.md +14 -0
- package/docs/content/extensions.md +19 -0
- package/docs/content/external-agents.md +38 -1
- package/docs/content/faq.md +14 -0
- package/docs/content/file-uploads.md +20 -0
- package/docs/content/frames.md +14 -0
- package/docs/content/getting-started.md +34 -16
- package/docs/content/harness-agents.md +14 -0
- package/docs/content/human-approval.md +15 -30
- package/docs/content/key-concepts.md +37 -0
- package/docs/content/local-file-mode.md +26 -19
- package/docs/content/mcp-apps.md +36 -1
- package/docs/content/mcp-clients.md +49 -0
- package/docs/content/mcp-protocol.md +36 -0
- package/docs/content/messaging.md +34 -8
- package/docs/content/migration-workbench.md +7 -0
- package/docs/content/multi-app-workspace.md +29 -16
- package/docs/content/multi-tenancy.md +14 -0
- package/docs/content/native-chat-ui.md +20 -3
- package/docs/content/notifications.md +30 -0
- package/docs/content/observability.md +20 -1
- package/docs/content/observational-memory.md +14 -0
- package/docs/content/onboarding.md +32 -41
- package/docs/content/plan-plugin.md +14 -0
- package/docs/content/pr-visual-recap.md +14 -0
- package/docs/content/processors.md +7 -0
- package/docs/content/progress.md +23 -0
- package/docs/content/pure-agent-apps.md +7 -0
- package/docs/content/real-time-collaboration.md +19 -18
- package/docs/content/recurring-jobs.md +22 -19
- package/docs/content/routing.md +8 -0
- package/docs/content/sandbox-adapters.md +19 -0
- package/docs/content/security.md +38 -0
- package/docs/content/server.md +47 -25
- package/docs/content/sharing.md +50 -0
- package/docs/content/skills-guide.md +27 -42
- package/docs/content/template-analytics.md +71 -41
- package/docs/content/template-assets.md +76 -3
- package/docs/content/template-brain.md +89 -1
- package/docs/content/template-calendar.md +86 -58
- package/docs/content/template-chat.md +25 -9
- package/docs/content/template-clips.md +124 -16
- package/docs/content/template-content.md +146 -47
- package/docs/content/template-design.md +62 -2
- package/docs/content/template-dispatch.md +56 -9
- package/docs/content/template-forms.md +69 -13
- package/docs/content/template-mail.md +73 -26
- package/docs/content/template-plan.md +80 -1
- package/docs/content/template-slides.md +95 -74
- package/docs/content/template-videos.md +73 -52
- package/docs/content/tracking.md +21 -0
- package/docs/content/using-your-agent.md +14 -0
- package/docs/content/voice-input.md +31 -10
- package/docs/content/what-is-agent-native.md +25 -13
- package/docs/content/workspace-connections.md +49 -0
- package/docs/content/workspace-management.md +24 -0
- package/docs/content/workspace.md +50 -19
- package/docs/content/writing-agent-instructions.md +7 -0
- package/package.json +1 -1
|
@@ -11,17 +11,21 @@ you. Open a doc, ask "rewrite this paragraph to be more concise" or "create a
|
|
|
11
11
|
page called Q4 Planning with sub-pages for Goals, Metrics, and Risks" - same
|
|
12
12
|
result whether you do it yourself or ask.
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
-->
|
|
14
|
+
```an-wireframe
|
|
15
|
+
{
|
|
16
|
+
"surface": "desktop",
|
|
17
|
+
"html": "<div style='display:grid;grid-template-columns:210px 1fr;gap:14px;padding:16px;min-height:500px;box-sizing:border-box'><aside class='wf-card' style='display:flex;flex-direction:column;gap:10px'><strong>Content</strong><span class='wf-pill accent'>Q3 Roadmap</span><span class='wf-pill'>Goals</span><span class='wf-pill'>Metrics</span><span class='wf-pill'>Risks</span><hr/><span class='wf-pill'>Engineering wiki</span><span class='wf-pill'>Reading list</span><span class='wf-pill'>Weekly sync</span></aside><main style='display:flex;flex-direction:column;gap:12px;min-width:0;padding:8px 20px'><div style='display:flex;align-items:center;gap:10px'><h1 style='margin:0'>Q3 Roadmap</h1><div style='flex:1'></div><button>Share</button><button class='primary'>Publish</button></div><div class='wf-card' style='flex:1;display:flex;flex-direction:column;gap:12px;padding:22px'><h2 style='margin:0'>Launch goals</h2><p style='margin:0'>Ship the onboarding flow, reduce setup time, and document owner handoffs.</p><div class='wf-box'>At a glance · owner, window, status</div><div class='wf-box'>Top objectives</div><div class='wf-box'>Workstreams table</div></div></main></div>"
|
|
18
|
+
}
|
|
19
|
+
```
|
|
21
20
|
|
|
22
|
-
|
|
21
|
+
When you open the app, you'll see a page tree next to the editor. The agent always knows which page you're viewing and what text you have selected, so document edits can stay grounded in the current page.
|
|
23
22
|
|
|
24
|
-
|
|
23
|
+
```an-diagram title="One document, many editors" summary="You and the agent both write through the same Yjs pipeline. SQL is the canonical store; local files and Notion are optional sync surfaces."
|
|
24
|
+
{
|
|
25
|
+
"html": "<div class=\"diagram-flow\"><div class=\"diagram-col\"><div class=\"diagram-node\">You type<br><small class=\"diagram-muted\">slash menu, toolbar</small></div><div class=\"diagram-node\">Agent edits<br><small class=\"diagram-muted\">edit-document find/replace</small></div></div><div class=\"diagram-arrow diagram-muted\" aria-hidden=\"true\">→</div><div class=\"diagram-panel center\"><span class=\"diagram-pill accent\">Yjs CRDT</span><small class=\"diagram-muted\">live, conflict-free merge</small></div><div class=\"diagram-arrow diagram-muted\" aria-hidden=\"true\">→</div><div class=\"diagram-box\">documents (markdown)<br><small class=\"diagram-muted\">canonical SQL store</small></div><div class=\"diagram-arrow diagram-muted\" aria-hidden=\"true\">↔</div><div class=\"diagram-col\"><div class=\"diagram-box\">Local .md / .mdx<br><small class=\"diagram-muted\">/local-files</small></div><div class=\"diagram-box\">Notion pages<br><small class=\"diagram-muted\">pull · push</small></div></div></div>",
|
|
26
|
+
"css": ".diagram-flow{display:flex;align-items:center;gap:12px;flex-wrap:wrap}.diagram-flow .diagram-col{display:flex;flex-direction:column;gap:10px}.diagram-flow .diagram-arrow{font-size:22px;line-height:1}.diagram-flow .center{display:flex;flex-direction:column;align-items:center;gap:4px}"
|
|
27
|
+
}
|
|
28
|
+
```
|
|
25
29
|
|
|
26
30
|
## What you can do with it
|
|
27
31
|
|
|
@@ -101,50 +105,19 @@ pnpm install
|
|
|
101
105
|
pnpm dev
|
|
102
106
|
```
|
|
103
107
|
|
|
104
|
-
Open `http://localhost:8083` and create your first page.
|
|
105
|
-
|
|
106
|
-
### Key features (technical) {#key-features}
|
|
107
|
-
|
|
108
|
-
### Hierarchical pages
|
|
109
|
-
|
|
110
|
-
Documents nest infinitely via a `parent_id` column. The sidebar renders a draggable tree; children move with their parents and ordering uses an integer `position` field. See `app/components/sidebar/DocumentSidebar.tsx` and `app/components/sidebar/DocumentTreeItem.tsx`.
|
|
111
|
-
|
|
112
|
-
### Rich-text editor
|
|
113
|
-
|
|
114
|
-
The editor is built on Tiptap with a custom extension set. It supports headings, lists, tables, code blocks with syntax highlighting, images, and links. Implementation lives in `app/components/editor/DocumentEditor.tsx` and `app/components/editor/VisualEditor.tsx`, with custom nodes under `app/components/editor/extensions/` (`CodeBlockNode.tsx`, `ImageNode.ts`, `DragHandle.tsx`, `NotionExtensions.tsx`).
|
|
108
|
+
Open `http://localhost:8083` and create your first page. Then ask the agent to "create a page called Onboarding and add three sub-pages under it".
|
|
115
109
|
|
|
116
|
-
|
|
110
|
+
### Key features {#key-features}
|
|
117
111
|
|
|
118
|
-
|
|
119
|
-
- `SlashCommandMenu.tsx` — slash-command inserter for blocks
|
|
120
|
-
- `LinkHoverPreview.tsx` — hover previews for inline links
|
|
121
|
-
- `TableHoverControls.tsx` — add/remove table rows and columns
|
|
122
|
-
- `EmojiPicker.tsx` — emoji picker for page icons
|
|
112
|
+
**Nested pages.** Documents form a draggable tree with favorites, icons, ordering, and page-level sharing.
|
|
123
113
|
|
|
124
|
-
|
|
114
|
+
**Rich MDX editor.** Tiptap powers headings, lists, tables, code blocks, images, links, slash commands, selection toolbars, and local React components.
|
|
125
115
|
|
|
126
|
-
|
|
116
|
+
**Live collaboration.** Yjs keeps multiple editors and agent edits in sync without clobbering each other.
|
|
127
117
|
|
|
128
|
-
|
|
118
|
+
**Search and comments.** Full-text search, anchored comments, version history, and restore flows are built into the document surface.
|
|
129
119
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
### Favorites and icons
|
|
133
|
-
|
|
134
|
-
Each document can be favorited (`is_favorite`) and given an emoji `icon`. The index route auto-opens your first favorite on load — see `app/routes/_app._index.tsx`.
|
|
135
|
-
|
|
136
|
-
### Notion sync
|
|
137
|
-
|
|
138
|
-
Documents can be linked to a Notion page and synced in either direction:
|
|
139
|
-
|
|
140
|
-
- `connect-notion-status` — check whether a Notion integration is connected
|
|
141
|
-
- `link-notion-page` — link a local doc to a Notion page
|
|
142
|
-
- `pull-notion-page` — overwrite local content from Notion
|
|
143
|
-
- `push-notion-page` — overwrite Notion content from local
|
|
144
|
-
- `list-notion-links` — list all linked documents
|
|
145
|
-
- `sync-notion-comments` — bidirectionally sync comment threads
|
|
146
|
-
|
|
147
|
-
Sync state is tracked in the `document_sync_links` table (last synced time, conflict flag, last error). Markdown-to-Notion block conversion lives in `shared/notion-markdown.ts`. Conflict and status UI is in `app/components/editor/NotionConflictBanner.tsx` and `NotionSyncBar.tsx`. See the `notion-integration` skill for the full flow.
|
|
120
|
+
**Sync surfaces.** Documents can sync with Notion or local Markdown/MDX folders, with SQL acting as the collaborative cache/history layer.
|
|
148
121
|
|
|
149
122
|
### Local file sync
|
|
150
123
|
|
|
@@ -269,6 +242,132 @@ Nine tables, all defined in `server/db/schema.ts`:
|
|
|
269
242
|
- **`document_property_values`** — per-document property values (`property_id` → `value_json`).
|
|
270
243
|
- **`document_shares`** — per-user and per-org grants created via `createSharesTable`.
|
|
271
244
|
|
|
245
|
+
```an-schema title="Content data model" summary="Nine tables in server/db/schema.ts. documents is the page tree; the rest hang off it for versions, comments, Notion sync, inline databases, and sharing."
|
|
246
|
+
{
|
|
247
|
+
"entities": [
|
|
248
|
+
{
|
|
249
|
+
"id": "documents",
|
|
250
|
+
"name": "documents",
|
|
251
|
+
"note": "The page tree (ownable, markdown body)",
|
|
252
|
+
"fields": [
|
|
253
|
+
{ "name": "id", "type": "id", "pk": true },
|
|
254
|
+
{ "name": "parent_id", "type": "id", "fk": "documents.id", "nullable": true, "note": "infinite nesting" },
|
|
255
|
+
{ "name": "title", "type": "string" },
|
|
256
|
+
{ "name": "content", "type": "markdown" },
|
|
257
|
+
{ "name": "icon", "type": "string", "nullable": true },
|
|
258
|
+
{ "name": "position", "type": "int", "note": "sibling ordering" },
|
|
259
|
+
{ "name": "is_favorite", "type": "bool" },
|
|
260
|
+
{ "name": "visibility", "type": "enum", "note": "private | org | public" },
|
|
261
|
+
{ "name": "owner_email", "type": "string" },
|
|
262
|
+
{ "name": "org_id", "type": "id", "nullable": true }
|
|
263
|
+
]
|
|
264
|
+
},
|
|
265
|
+
{
|
|
266
|
+
"id": "document_versions",
|
|
267
|
+
"name": "document_versions",
|
|
268
|
+
"note": "Full title/content snapshots for version history",
|
|
269
|
+
"fields": [
|
|
270
|
+
{ "name": "id", "type": "id", "pk": true },
|
|
271
|
+
{ "name": "document_id", "type": "id", "fk": "documents.id" },
|
|
272
|
+
{ "name": "title", "type": "string" },
|
|
273
|
+
{ "name": "content", "type": "markdown" }
|
|
274
|
+
]
|
|
275
|
+
},
|
|
276
|
+
{
|
|
277
|
+
"id": "document_comments",
|
|
278
|
+
"name": "document_comments",
|
|
279
|
+
"note": "Threaded comments with quoted-text anchors",
|
|
280
|
+
"fields": [
|
|
281
|
+
{ "name": "id", "type": "id", "pk": true },
|
|
282
|
+
{ "name": "document_id", "type": "id", "fk": "documents.id" },
|
|
283
|
+
{ "name": "thread_id", "type": "id" },
|
|
284
|
+
{ "name": "parent_id", "type": "id", "fk": "document_comments.id", "nullable": true },
|
|
285
|
+
{ "name": "quoted_text", "type": "string", "nullable": true },
|
|
286
|
+
{ "name": "resolved", "type": "bool" },
|
|
287
|
+
{ "name": "notion_comment_id", "type": "string", "nullable": true, "note": "bidirectional Notion sync" }
|
|
288
|
+
]
|
|
289
|
+
},
|
|
290
|
+
{
|
|
291
|
+
"id": "document_sync_links",
|
|
292
|
+
"name": "document_sync_links",
|
|
293
|
+
"note": "One row per Notion-linked document",
|
|
294
|
+
"fields": [
|
|
295
|
+
{ "name": "id", "type": "id", "pk": true },
|
|
296
|
+
{ "name": "document_id", "type": "id", "fk": "documents.id" },
|
|
297
|
+
{ "name": "notion_page_id", "type": "string" },
|
|
298
|
+
{ "name": "conflict", "type": "bool" },
|
|
299
|
+
{ "name": "content_hash", "type": "string" }
|
|
300
|
+
]
|
|
301
|
+
},
|
|
302
|
+
{
|
|
303
|
+
"id": "content_databases",
|
|
304
|
+
"name": "content_databases",
|
|
305
|
+
"note": "Inline database objects attached to a document",
|
|
306
|
+
"fields": [
|
|
307
|
+
{ "name": "id", "type": "id", "pk": true },
|
|
308
|
+
{ "name": "document_id", "type": "id", "fk": "documents.id" },
|
|
309
|
+
{ "name": "title", "type": "string" },
|
|
310
|
+
{ "name": "view_config", "type": "json" }
|
|
311
|
+
]
|
|
312
|
+
},
|
|
313
|
+
{
|
|
314
|
+
"id": "content_database_items",
|
|
315
|
+
"name": "content_database_items",
|
|
316
|
+
"note": "Rows in an inline database (each row is a document)",
|
|
317
|
+
"fields": [
|
|
318
|
+
{ "name": "id", "type": "id", "pk": true },
|
|
319
|
+
{ "name": "database_id", "type": "id", "fk": "content_databases.id" },
|
|
320
|
+
{ "name": "document_id", "type": "id", "fk": "documents.id" }
|
|
321
|
+
]
|
|
322
|
+
},
|
|
323
|
+
{
|
|
324
|
+
"id": "document_property_definitions",
|
|
325
|
+
"name": "document_property_definitions",
|
|
326
|
+
"note": "Column definitions for inline databases",
|
|
327
|
+
"fields": [
|
|
328
|
+
{ "name": "id", "type": "id", "pk": true },
|
|
329
|
+
{ "name": "name", "type": "string" },
|
|
330
|
+
{ "name": "type", "type": "string" },
|
|
331
|
+
{ "name": "options", "type": "json", "nullable": true },
|
|
332
|
+
{ "name": "position", "type": "int" }
|
|
333
|
+
]
|
|
334
|
+
},
|
|
335
|
+
{
|
|
336
|
+
"id": "document_property_values",
|
|
337
|
+
"name": "document_property_values",
|
|
338
|
+
"note": "Per-document property values",
|
|
339
|
+
"fields": [
|
|
340
|
+
{ "name": "id", "type": "id", "pk": true },
|
|
341
|
+
{ "name": "document_id", "type": "id", "fk": "documents.id" },
|
|
342
|
+
{ "name": "property_id", "type": "id", "fk": "document_property_definitions.id" },
|
|
343
|
+
{ "name": "value_json", "type": "json" }
|
|
344
|
+
]
|
|
345
|
+
},
|
|
346
|
+
{
|
|
347
|
+
"id": "document_shares",
|
|
348
|
+
"name": "document_shares",
|
|
349
|
+
"note": "Per-user and per-org grants (createSharesTable)",
|
|
350
|
+
"fields": [
|
|
351
|
+
{ "name": "id", "type": "id", "pk": true },
|
|
352
|
+
{ "name": "document_id", "type": "id", "fk": "documents.id" },
|
|
353
|
+
{ "name": "principal", "type": "string" },
|
|
354
|
+
{ "name": "role", "type": "enum", "note": "viewer | editor | admin" }
|
|
355
|
+
]
|
|
356
|
+
}
|
|
357
|
+
],
|
|
358
|
+
"relations": [
|
|
359
|
+
{ "from": "documents", "to": "documents", "kind": "1-n", "label": "has children" },
|
|
360
|
+
{ "from": "documents", "to": "document_versions", "kind": "1-n", "label": "has snapshots" },
|
|
361
|
+
{ "from": "documents", "to": "document_comments", "kind": "1-n", "label": "has comments" },
|
|
362
|
+
{ "from": "documents", "to": "document_sync_links", "kind": "1-1", "label": "links to Notion" },
|
|
363
|
+
{ "from": "documents", "to": "content_databases", "kind": "1-n", "label": "hosts databases" },
|
|
364
|
+
{ "from": "content_databases", "to": "content_database_items", "kind": "1-n", "label": "has rows" },
|
|
365
|
+
{ "from": "document_property_definitions", "to": "document_property_values", "kind": "1-n", "label": "has values" },
|
|
366
|
+
{ "from": "documents", "to": "document_shares", "kind": "1-n", "label": "has share grants" }
|
|
367
|
+
]
|
|
368
|
+
}
|
|
369
|
+
```
|
|
370
|
+
|
|
272
371
|
Content is stored as markdown. The editor converts to and from the Tiptap JSON model in memory; the SQL row is always markdown so actions, search, and Notion sync can operate on a single canonical format.
|
|
273
372
|
|
|
274
373
|
All ownable tables include `owner_email` and `org_id` via `ownableColumns()`, so every row is scoped to the signed-in user (and optionally their active organization) from the moment it's created.
|
|
@@ -7,9 +7,21 @@ description: "An agent-native HTML prototyping studio — generate, refine, prev
|
|
|
7
7
|
|
|
8
8
|
Design is an agent-native HTML prototyping studio. Instead of a layered drawing canvas, the agent generates complete self-contained Alpine/Tailwind HTML prototypes, renders them in an iframe, and lets you refine the result with prompts and tweak controls.
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
```an-wireframe
|
|
11
|
+
{
|
|
12
|
+
"surface": "desktop",
|
|
13
|
+
"html": "<div style='display:flex;flex-direction:column;gap:14px;padding:18px;min-height:520px;box-sizing:border-box'><div style='display:flex;align-items:center;gap:10px'><h1 style='margin:0'>Product launch page</h1><span class='wf-pill accent'>Desktop</span><span class='wf-pill'>Tablet</span><span class='wf-pill'>Mobile</span><div style='flex:1'></div><button>Preview</button><button class='primary'>Export code</button></div><div class='wf-card' style='flex:1;display:grid;grid-template-rows:auto 1fr auto;gap:12px'><div style='display:flex;gap:8px'><span class='wf-pill accent'>Hero</span><span class='wf-pill'>Pricing</span><span class='wf-pill'>FAQ</span></div><div class='wf-box' style='display:flex;align-items:center;justify-content:center;min-height:230px'><strong>Generated HTML prototype</strong></div><div class='wf-card' style='display:flex;align-items:center;gap:10px'><span class='wf-muted'>Make the hero denser and the CTA clearer.</span><div style='flex:1'></div><button class='primary'>Apply revision</button></div></div></div>"
|
|
14
|
+
}
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
When you open the app, the generated prototype is the center of the workspace, with preview modes, prompt revisions, and export controls close at hand. Everything the agent produces is real HTML you can refine, export, or hand off.
|
|
11
18
|
|
|
12
|
-
|
|
19
|
+
```an-diagram title="One artifact, no translation" summary="The agent generates standalone Alpine/Tailwind HTML; the iframe, the editable source, and every export all read the same files. A linked design system feeds tokens into each pass."
|
|
20
|
+
{
|
|
21
|
+
"html": "<div class=\"diagram-design\"><div class=\"diagram-col\"><div class=\"diagram-node\">Prompt<br><small class=\"diagram-muted\">describe screen / page</small></div><div class=\"diagram-pill\">Design system</div></div><div class=\"diagram-arrow diagram-muted\" aria-hidden=\"true\">→</div><div class=\"diagram-box\" data-rough><span class=\"diagram-pill accent\">Agent generate</span><small class=\"diagram-muted\">standalone HTML / JSX files</small></div><div class=\"diagram-arrow diagram-muted\" aria-hidden=\"true\">→</div><div class=\"diagram-box\" data-rough>iframe preview<br><small class=\"diagram-muted\">tweak knobs · Cmd+I refine</small></div><div class=\"diagram-arrow diagram-muted\" aria-hidden=\"true\">↻</div><div class=\"diagram-panel center\"><span class=\"diagram-pill ok\">Export</span><small class=\"diagram-muted\">HTML · ZIP · PDF · handoff</small></div></div>",
|
|
22
|
+
"css": ".diagram-design{display:flex;align-items:center;gap:12px;flex-wrap:wrap}.diagram-design .diagram-col{display:flex;flex-direction:column;gap:8px;align-items:flex-start}.diagram-design .diagram-box{display:flex;flex-direction:column;gap:4px}.diagram-design .diagram-arrow{font-size:20px;line-height:1}.diagram-design .center{display:flex;flex-direction:column;align-items:center;gap:4px}"
|
|
23
|
+
}
|
|
24
|
+
```
|
|
13
25
|
|
|
14
26
|
## When to pick it
|
|
15
27
|
|
|
@@ -73,6 +85,54 @@ All data lives in SQL via Drizzle ORM. Schema: `templates/design/server/db/schem
|
|
|
73
85
|
| `design_systems` | Reusable brand tokens — `data` (colors/typography/spacing), `assets`, `custom_instructions`, and an `is_default` flag |
|
|
74
86
|
| `design_shares` / `design_system_shares` | Framework shares tables mapping principals (users or orgs) to roles (viewer, editor, admin) |
|
|
75
87
|
|
|
88
|
+
```an-schema title="Design data model" summary="A design owns its files and versioned snapshots, and optionally links a reusable design system. Both designs and systems are ownable, each with a framework shares table."
|
|
89
|
+
{
|
|
90
|
+
"entities": [
|
|
91
|
+
{ "id": "designs", "name": "designs", "note": "A design project (ownable)", "fields": [
|
|
92
|
+
{ "name": "id", "type": "id", "pk": true },
|
|
93
|
+
{ "name": "title", "type": "text" },
|
|
94
|
+
{ "name": "description", "type": "text", "nullable": true },
|
|
95
|
+
{ "name": "project_type", "type": "text", "note": "prototype / other" },
|
|
96
|
+
{ "name": "data", "type": "json", "note": "starts as {}" },
|
|
97
|
+
{ "name": "design_system_id", "type": "id", "fk": "design_systems.id", "nullable": true }
|
|
98
|
+
] },
|
|
99
|
+
{ "id": "files", "name": "design_files", "note": "Files in a design", "fields": [
|
|
100
|
+
{ "name": "design_id", "type": "id", "fk": "designs.id" },
|
|
101
|
+
{ "name": "filename", "type": "text" },
|
|
102
|
+
{ "name": "content", "type": "text" },
|
|
103
|
+
{ "name": "file_type", "type": "text", "note": "defaults to html" }
|
|
104
|
+
] },
|
|
105
|
+
{ "id": "versions", "name": "design_versions", "note": "History / rollback", "fields": [
|
|
106
|
+
{ "name": "design_id", "type": "id", "fk": "designs.id" },
|
|
107
|
+
{ "name": "snapshot", "type": "json" },
|
|
108
|
+
{ "name": "label", "type": "text", "nullable": true }
|
|
109
|
+
] },
|
|
110
|
+
{ "id": "systems", "name": "design_systems", "note": "Reusable brand tokens (ownable)", "fields": [
|
|
111
|
+
{ "name": "id", "type": "id", "pk": true },
|
|
112
|
+
{ "name": "data", "type": "json", "note": "colors / typography / spacing" },
|
|
113
|
+
{ "name": "assets", "type": "json", "nullable": true },
|
|
114
|
+
{ "name": "custom_instructions", "type": "text", "nullable": true },
|
|
115
|
+
{ "name": "is_default", "type": "boolean" }
|
|
116
|
+
] },
|
|
117
|
+
{ "id": "design_shares", "name": "design_shares", "note": "Framework shares table", "fields": [
|
|
118
|
+
{ "name": "design_id", "type": "id", "fk": "designs.id" },
|
|
119
|
+
{ "name": "role", "type": "text", "note": "viewer / editor / admin" }
|
|
120
|
+
] },
|
|
121
|
+
{ "id": "system_shares", "name": "design_system_shares", "note": "Framework shares table", "fields": [
|
|
122
|
+
{ "name": "design_system_id", "type": "id", "fk": "design_systems.id" },
|
|
123
|
+
{ "name": "role", "type": "text", "note": "viewer / editor / admin" }
|
|
124
|
+
] }
|
|
125
|
+
],
|
|
126
|
+
"relations": [
|
|
127
|
+
{ "from": "designs", "to": "files", "kind": "1-n" },
|
|
128
|
+
{ "from": "designs", "to": "versions", "kind": "1-n" },
|
|
129
|
+
{ "from": "systems", "to": "designs", "kind": "1-n", "label": "applied to" },
|
|
130
|
+
{ "from": "designs", "to": "design_shares", "kind": "1-n" },
|
|
131
|
+
{ "from": "systems", "to": "system_shares", "kind": "1-n" }
|
|
132
|
+
]
|
|
133
|
+
}
|
|
134
|
+
```
|
|
135
|
+
|
|
76
136
|
A design project is a shell until it has content: `create-design` makes an empty row (`data: "{}"`), then `generate-design` writes the actual standalone HTML/JSX files. The generated artifact, the editable source, and every export all come from the same HTML, so there is no separate "AI mockup" format to translate. A linked design system supplies tokens and `custom_instructions` that the agent honors on every generation pass.
|
|
77
137
|
|
|
78
138
|
Routes in the UI live under `templates/design/app/routes/`: `_index.tsx` (list), `design.$id.tsx` (editor), `present.$id.tsx` (presentation), `design-systems.tsx` and `design-systems_.setup.tsx`, `templates.tsx`, `examples.tsx`, plus `settings.tsx` and `team.tsx`.
|
|
@@ -9,18 +9,22 @@ description: "Dispatch is the workspace control plane — central inbox, cross-a
|
|
|
9
9
|
|
|
10
10
|
Dispatch is the **workspace control plane**. Where other templates are domain apps (Mail, Calendar, Analytics, Brain), Dispatch is the app you run _alongside_ them to coordinate everything: a central inbox, a secrets vault, scheduled jobs, Slack/Telegram integration, and an orchestrator agent that delegates domain work to the right specialist app over [A2A](/docs/a2a-protocol).
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
-->
|
|
19
|
-
|
|
20
|
-

|
|
12
|
+
```an-wireframe
|
|
13
|
+
{
|
|
14
|
+
"surface": "desktop",
|
|
15
|
+
"html": "<div style='display:flex;flex-direction:column;gap:14px;padding:18px;min-height:520px;box-sizing:border-box'><div style='display:flex;align-items:center;gap:10px'><h1 style='margin:0'>Dispatch</h1><span class='wf-pill accent'>Overview</span><span class='wf-pill'>Inbox</span><span class='wf-pill'>Secrets</span><span class='wf-pill'>Approvals</span><div style='flex:1'></div><button>Schedules</button></div><div class='wf-card' style='display:flex;flex-direction:column;gap:10px'><strong>What should we do next?</strong><div class='wf-box'>Ask Analytics for this week's signups and draft a Slack update.</div><button class='primary'>Delegate</button></div><div style='display:grid;grid-template-columns:repeat(3,1fr);gap:10px'><div class='wf-card'><strong>Mail</strong><br/><small>/mail</small></div><div class='wf-card'><strong>Calendar</strong><br/><small>/calendar</small></div><div class='wf-card'><strong>Analytics</strong><br/><small>/analytics</small></div><div class='wf-card'><strong>Slides</strong><br/><small>/slides</small></div><div class='wf-card'><strong>Forms</strong><br/><small>/forms</small></div><div class='wf-card'><strong>Create app</strong><br/><small>+</small></div></div><div class='wf-card' style='display:grid;grid-template-columns:repeat(3,1fr);gap:8px'><div class='wf-box'>Slack DM needs reply</div><div class='wf-box'>A2A task completed</div><div class='wf-box'>Approval required</div></div></div>"
|
|
16
|
+
}
|
|
17
|
+
```
|
|
21
18
|
|
|
22
19
|
If you're running an [multi-app workspace](/docs/multi-app-workspace) with many apps, Dispatch is the glue.
|
|
23
20
|
|
|
21
|
+
```an-diagram title="Orchestrate, don't specialize" summary="Messages from every channel land in one inbox; the orchestrator triages and delegates domain work to the right specialist app over A2A — secrets, resources, and approvals stay central."
|
|
22
|
+
{
|
|
23
|
+
"html": "<div class=\"diagram-dispatch\"><div class=\"diagram-col\"><div class=\"diagram-node\">Slack · Telegram</div><div class=\"diagram-node\">Email</div><div class=\"diagram-node\">A2A requests</div></div><div class=\"diagram-arrow diagram-muted\" aria-hidden=\"true\">→</div><div class=\"diagram-box\" data-rough><span class=\"diagram-pill accent\">Orchestrator</span><small class=\"diagram-muted\">central inbox · triage · route</small></div><div class=\"diagram-arrow diagram-muted\" aria-hidden=\"true\">→</div><div class=\"diagram-col\"><div class=\"diagram-node\">Mail agent</div><div class=\"diagram-node\">Analytics agent</div><div class=\"diagram-node\">Brain · Slides …</div></div></div><div class=\"diagram-shared\"><span class=\"diagram-pill\">Secrets vault</span><span class=\"diagram-pill\">Workspace resources</span><span class=\"diagram-pill warn\">Approvals</span><span class=\"diagram-pill\">Scheduled jobs</span></div>",
|
|
24
|
+
"css": ".diagram-dispatch{display:flex;align-items:center;gap:12px;flex-wrap:wrap}.diagram-dispatch .diagram-col{display:flex;flex-direction:column;gap:8px}.diagram-dispatch .diagram-box{display:flex;flex-direction:column;gap:4px}.diagram-dispatch .diagram-arrow{font-size:20px;line-height:1}.diagram-shared{display:flex;gap:8px;flex-wrap:wrap;margin-top:12px}"
|
|
25
|
+
}
|
|
26
|
+
```
|
|
27
|
+
|
|
24
28
|
## What it does {#what-it-does}
|
|
25
29
|
|
|
26
30
|
- **Central inbox.** Slack DMs, Telegram messages, email notifications, A2A requests from other agents — all land in one place. The Dispatch agent triages and either handles them itself or delegates. See [Messaging](/docs/messaging) for how to wire Slack, email, and Telegram into your workspace.
|
|
@@ -83,6 +87,49 @@ _How it works under the hood (for developers)._
|
|
|
83
87
|
- **Vault schema.** Drizzle tables for secrets, grants, requests, approvals, and audit logs. These live in the `@agent-native/dispatch` package (`packages/dispatch/src/db/schema.ts`) and are re-exported into the template via `templates/dispatch/server/db/index.ts` — there is no template-local `server/db/schema.ts`. Dispatch's runtime ships in the package, not in template source (consistent with the note below that `@agent-native/dispatch` owns the shell, sidebar, and built-in pages).
|
|
84
88
|
- **Slack / Telegram plugins.** Server plugins that register webhooks and forward incoming messages to the orchestrator agent.
|
|
85
89
|
- **Workspace MCP resources.** Add HTTP MCP server definitions under `mcp-servers/*.json` in Resources, then scope them to All apps or selected app grants just like skills and context.
|
|
90
|
+
|
|
91
|
+
```an-schema title="Secrets vault schema" summary="Secrets are stored once; grants give a named app access; requests + reviews gate sensitive access; the audit log records who used which secret when. Defined in @agent-native/dispatch (packages/dispatch/src/db/schema.ts)."
|
|
92
|
+
{
|
|
93
|
+
"entities": [
|
|
94
|
+
{ "id": "secrets", "name": "vault_secrets", "note": "Stored credential values", "fields": [
|
|
95
|
+
{ "name": "id", "type": "text", "pk": true },
|
|
96
|
+
{ "name": "owner_email", "type": "text" },
|
|
97
|
+
{ "name": "org_id", "type": "text", "nullable": true },
|
|
98
|
+
{ "name": "name", "type": "text" },
|
|
99
|
+
{ "name": "credential_key", "type": "text" },
|
|
100
|
+
{ "name": "value", "type": "text", "note": "secret value" },
|
|
101
|
+
{ "name": "provider", "type": "text", "nullable": true }
|
|
102
|
+
] },
|
|
103
|
+
{ "id": "grants", "name": "vault_grants", "note": "Per-app access grant", "fields": [
|
|
104
|
+
{ "name": "id", "type": "text", "pk": true },
|
|
105
|
+
{ "name": "secret_id", "type": "text", "fk": "vault_secrets.id" },
|
|
106
|
+
{ "name": "app_id", "type": "text" },
|
|
107
|
+
{ "name": "granted_by", "type": "text" },
|
|
108
|
+
{ "name": "status", "type": "text" }
|
|
109
|
+
] },
|
|
110
|
+
{ "id": "requests", "name": "vault_requests", "note": "Access request + review", "fields": [
|
|
111
|
+
{ "name": "id", "type": "text", "pk": true },
|
|
112
|
+
{ "name": "credential_key", "type": "text" },
|
|
113
|
+
{ "name": "app_id", "type": "text" },
|
|
114
|
+
{ "name": "reason", "type": "text", "nullable": true },
|
|
115
|
+
{ "name": "status", "type": "text" },
|
|
116
|
+
{ "name": "reviewed_by", "type": "text", "nullable": true }
|
|
117
|
+
] },
|
|
118
|
+
{ "id": "audit", "name": "vault_audit_log", "note": "Who used which secret when", "fields": [
|
|
119
|
+
{ "name": "id", "type": "text", "pk": true },
|
|
120
|
+
{ "name": "secret_id", "type": "text", "fk": "vault_secrets.id", "nullable": true },
|
|
121
|
+
{ "name": "app_id", "type": "text", "nullable": true },
|
|
122
|
+
{ "name": "action", "type": "text" },
|
|
123
|
+
{ "name": "actor", "type": "text" }
|
|
124
|
+
] }
|
|
125
|
+
],
|
|
126
|
+
"relations": [
|
|
127
|
+
{ "from": "secrets", "to": "grants", "kind": "1-n", "label": "granted via" },
|
|
128
|
+
{ "from": "secrets", "to": "audit", "kind": "1-n", "label": "use recorded by" }
|
|
129
|
+
]
|
|
130
|
+
}
|
|
131
|
+
```
|
|
132
|
+
|
|
86
133
|
- **MCP hub mode.** Dispatch can still act as the workspace's [MCP hub](/docs/mcp-clients#hub) so every other app in the workspace pulls the same org-scope MCP server list. Separately, Dispatch's own `/_agent-native/mcp` endpoint is the recommended external MCP connector for Claude, ChatGPT, and other hosts that should reach multiple workspace apps.
|
|
87
134
|
|
|
88
135
|
## Dreams {#dreams}
|
|
@@ -7,18 +7,22 @@ description: "Agent-native form builder — create, edit, publish, and route for
|
|
|
7
7
|
|
|
8
8
|
Forms is an agent-native form builder. Describe the form you want, refine it in the editor, and publish a public form that stores submissions in your own SQL database.
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
-->
|
|
17
|
-
|
|
18
|
-

|
|
10
|
+
```an-wireframe
|
|
11
|
+
{
|
|
12
|
+
"surface": "desktop",
|
|
13
|
+
"html": "<div style='display:flex;flex-direction:column;min-height:520px;box-sizing:border-box'><div style='display:flex;align-items:center;gap:10px;padding:14px 16px;border-bottom:1.4px solid var(--wf-line)'><strong>Beta signup</strong><span class='wf-pill accent'>published</span><div style='flex:1'></div><button>Share</button><button class='primary'>Unpublish</button></div><div style='display:flex;gap:8px;padding:12px 16px;border-bottom:1.4px solid var(--wf-line)'><span class='wf-pill accent'>Edit</span><span class='wf-pill'>Results 187</span><span class='wf-pill'>Settings</span><span class='wf-pill'>Integrations</span></div><div style='display:flex;flex-direction:column;gap:12px;padding:30px 78px;overflow:hidden'><h2 style='margin:0'>Beta signup</h2><p class='wf-muted' style='margin:0'>Reserve a spot in the upcoming private beta cohort.</p><div class='wf-card'><strong>Full name</strong><input value='Ada Lovelace'/></div><div class='wf-card'><strong>Work email</strong><input value='you@company.com'/></div><div class='wf-card'><strong>Your role</strong><input value='Select...'/></div><div class='wf-card'><strong>Team size</strong><input value='Select...'/></div></div></div>"
|
|
14
|
+
}
|
|
15
|
+
```
|
|
19
16
|
|
|
20
17
|
When you open the app, you see your forms, the current editor, and a live preview. The agent can create a form from a prompt, update field labels and options, change validation, and connect submission destinations using the same actions the UI uses.
|
|
21
18
|
|
|
19
|
+
```an-diagram title="Build, publish, collect" summary="The agent and the visual editor edit one SQL-backed form definition. The public fill page is unauthenticated, and submissions route server-side to your destinations."
|
|
20
|
+
{
|
|
21
|
+
"html": "<div class=\"diagram-flow\"><div class=\"diagram-col\"><div class=\"diagram-node\">Agent prompt<br><small class=\"diagram-muted\">\"add an NPS question\"</small></div><div class=\"diagram-node\">Visual editor<br><small class=\"diagram-muted\">labels, validation, order</small></div></div><div class=\"diagram-arrow diagram-muted\" aria-hidden=\"true\">→</div><div class=\"diagram-panel center\"><span class=\"diagram-pill accent\">create-form · update-form</span><small class=\"diagram-muted\">fields JSON, settings JSON</small></div><div class=\"diagram-arrow diagram-muted\" aria-hidden=\"true\">→</div><div class=\"diagram-box\">forms table<br><small class=\"diagram-muted\">SQL via Drizzle</small></div><div class=\"diagram-arrow diagram-muted\" aria-hidden=\"true\">→</div><div class=\"diagram-col\"><div class=\"diagram-box\">Public fill page<br><small class=\"diagram-muted\">unauthenticated</small></div><div class=\"diagram-box\">responses<br><small class=\"diagram-muted\">+ Slack / webhook / Sheets</small></div></div></div>",
|
|
22
|
+
"css": ".diagram-flow{display:flex;align-items:center;gap:12px;flex-wrap:wrap}.diagram-flow .diagram-col{display:flex;flex-direction:column;gap:10px}.diagram-flow .diagram-arrow{font-size:22px;line-height:1}.diagram-flow .center{display:flex;flex-direction:column;align-items:center;gap:4px}"
|
|
23
|
+
}
|
|
24
|
+
```
|
|
25
|
+
|
|
22
26
|
## What you can do with it
|
|
23
27
|
|
|
24
28
|
- **Build forms conversationally.** "Create a contact form," "add an NPS score question," "make the email field required." The agent updates the form schema and the preview updates from SQL-backed state.
|
|
@@ -70,13 +74,13 @@ npx @agent-native/core@latest create my-platform
|
|
|
70
74
|
|
|
71
75
|
Pick Forms and any other templates you want during the workspace setup.
|
|
72
76
|
|
|
73
|
-
### Key features
|
|
77
|
+
### Key features {#key-features}
|
|
74
78
|
|
|
75
|
-
|
|
79
|
+
**JSON form definitions.** Fields live in one `fields` JSON column, so the agent can make surgical edits without schema changes for every field type.
|
|
76
80
|
|
|
77
|
-
|
|
81
|
+
**Public fill pages.** Respondents can submit unauthenticated forms, while private settings are stripped before data reaches the browser.
|
|
78
82
|
|
|
79
|
-
|
|
83
|
+
**Server-side destinations.** Slack, Discord, Google Sheets, and webhook integrations live in form settings and run after submission.
|
|
80
84
|
|
|
81
85
|
### Data model
|
|
82
86
|
|
|
@@ -90,6 +94,58 @@ All data lives in SQL via Drizzle ORM. Schema: `templates/forms/server/db/schema
|
|
|
90
94
|
|
|
91
95
|
The `fields` and `settings` JSON shapes are defined in `templates/forms/shared/types.ts` (`FormField`, `FormSettings`). Owner-private settings such as integration webhook URLs and allowed origins are stripped before any data reaches the public fill page via `toPublicFormSettings`.
|
|
92
96
|
|
|
97
|
+
```an-schema title="Forms data model" summary="Three tables. Fields and integrations are JSON columns on forms, so the agent's edits are surgical patches rather than cross-table row changes."
|
|
98
|
+
{
|
|
99
|
+
"entities": [
|
|
100
|
+
{
|
|
101
|
+
"id": "forms",
|
|
102
|
+
"name": "forms",
|
|
103
|
+
"note": "A form definition (ownable)",
|
|
104
|
+
"fields": [
|
|
105
|
+
{ "name": "id", "type": "id", "pk": true },
|
|
106
|
+
{ "name": "title", "type": "string" },
|
|
107
|
+
{ "name": "description", "type": "string", "nullable": true },
|
|
108
|
+
{ "name": "slug", "type": "string", "note": "unique; public URL" },
|
|
109
|
+
{ "name": "fields", "type": "json", "note": "FormField[] — all field types" },
|
|
110
|
+
{ "name": "settings", "type": "json", "note": "FormSettings — integrations, etc." },
|
|
111
|
+
{ "name": "status", "type": "enum", "note": "draft | published | closed" },
|
|
112
|
+
{ "name": "deleted_at", "type": "datetime", "nullable": true, "note": "soft delete" },
|
|
113
|
+
{ "name": "owner_email", "type": "string" },
|
|
114
|
+
{ "name": "org_id", "type": "id", "nullable": true }
|
|
115
|
+
]
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
"id": "responses",
|
|
119
|
+
"name": "responses",
|
|
120
|
+
"note": "One submission per row",
|
|
121
|
+
"fields": [
|
|
122
|
+
{ "name": "id", "type": "id", "pk": true },
|
|
123
|
+
{ "name": "form_id", "type": "id", "fk": "forms.id" },
|
|
124
|
+
{ "name": "data", "type": "json", "note": "{ fieldId: value }" },
|
|
125
|
+
{ "name": "submitted_at", "type": "datetime" },
|
|
126
|
+
{ "name": "ip", "type": "string", "nullable": true },
|
|
127
|
+
{ "name": "submitter_email", "type": "string", "nullable": true }
|
|
128
|
+
]
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
"id": "form_shares",
|
|
132
|
+
"name": "form_shares",
|
|
133
|
+
"note": "Framework shares table — principals to roles per form",
|
|
134
|
+
"fields": [
|
|
135
|
+
{ "name": "id", "type": "id", "pk": true },
|
|
136
|
+
{ "name": "form_id", "type": "id", "fk": "forms.id" },
|
|
137
|
+
{ "name": "principal", "type": "string", "note": "user or org" },
|
|
138
|
+
{ "name": "role", "type": "enum", "note": "viewer | editor | admin" }
|
|
139
|
+
]
|
|
140
|
+
}
|
|
141
|
+
],
|
|
142
|
+
"relations": [
|
|
143
|
+
{ "from": "forms", "to": "responses", "kind": "1-n", "label": "has responses" },
|
|
144
|
+
{ "from": "forms", "to": "form_shares", "kind": "1-n", "label": "has share grants" }
|
|
145
|
+
]
|
|
146
|
+
}
|
|
147
|
+
```
|
|
148
|
+
|
|
93
149
|
### Key actions
|
|
94
150
|
|
|
95
151
|
Every operation is a TypeScript file in `templates/forms/actions/`, auto-mounted at `POST /_agent-native/actions/:name`:
|