@agent-native/core 0.63.1 → 0.63.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/harness/ai-sdk-adapter.d.ts +44 -0
- package/dist/agent/harness/ai-sdk-adapter.d.ts.map +1 -1
- package/dist/agent/harness/ai-sdk-adapter.js +120 -1
- package/dist/agent/harness/ai-sdk-adapter.js.map +1 -1
- package/dist/agent/harness/index.d.ts +1 -1
- package/dist/agent/harness/index.d.ts.map +1 -1
- package/dist/agent/harness/index.js.map +1 -1
- package/dist/client/blocks/library/AnnotatedCodeBlock.d.ts.map +1 -1
- package/dist/client/blocks/library/AnnotatedCodeBlock.js +29 -10
- package/dist/client/blocks/library/AnnotatedCodeBlock.js.map +1 -1
- package/dist/client/blocks/library/DiffBlock.d.ts.map +1 -1
- package/dist/client/blocks/library/DiffBlock.js +48 -20
- package/dist/client/blocks/library/DiffBlock.js.map +1 -1
- package/dist/client/blocks/library/diagram.d.ts.map +1 -1
- package/dist/client/blocks/library/diagram.js +14 -3
- 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 +14 -3
- package/dist/client/blocks/library/wireframe.js.map +1 -1
- package/dist/client/blocks/types.d.ts +5 -0
- package/dist/client/blocks/types.d.ts.map +1 -1
- package/dist/client/blocks/types.js.map +1 -1
- package/dist/server/action-discovery.d.ts.map +1 -1
- package/dist/server/action-discovery.js +24 -2
- package/dist/server/action-discovery.js.map +1 -1
- package/dist/server/deep-link.d.ts +2 -2
- package/dist/server/deep-link.d.ts.map +1 -1
- package/dist/server/deep-link.js +2 -2
- package/dist/server/deep-link.js.map +1 -1
- package/dist/styles/blocks.css +25 -3
- package/dist/tailwind.preset.d.ts.map +1 -1
- package/dist/tailwind.preset.js +8 -1
- package/dist/tailwind.preset.js.map +1 -1
- package/dist/templates/default/package.json +1 -0
- package/dist/templates/headless/AGENTS.md +3 -0
- package/dist/templates/headless/DEVELOPING.md +4 -0
- package/dist/templates/headless/actions/run.ts +6 -0
- 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 +30 -2
- 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 +39 -2
- 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 +49 -8
- 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 +60 -0
- package/docs/content/template-assets.md +68 -0
- package/docs/content/template-brain.md +83 -0
- package/docs/content/template-calendar.md +74 -0
- package/docs/content/template-chat.md +19 -0
- package/docs/content/template-clips.md +113 -0
- package/docs/content/template-content.md +133 -0
- package/docs/content/template-design.md +55 -0
- package/docs/content/template-dispatch.md +50 -0
- package/docs/content/template-forms.md +59 -0
- package/docs/content/template-mail.md +62 -0
- package/docs/content/template-plan.md +80 -5
- package/docs/content/template-slides.md +82 -0
- package/docs/content/template-videos.md +62 -0
- 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 +6 -2
- package/src/templates/default/package.json +1 -0
- package/src/templates/headless/AGENTS.md +3 -0
- package/src/templates/headless/DEVELOPING.md +4 -0
- package/src/templates/headless/actions/run.ts +6 -0
|
@@ -19,6 +19,13 @@ An agent-powered calendar app. Connect your Google Calendar and the agent can re
|
|
|
19
19
|
|
|
20
20
|
When you open the app, you'll see your calendar in the middle and the agent in the sidebar. The agent always knows which day, week, or event you're looking at, so you can say "schedule a 30-minute call with Alex on this day" without spelling everything out.
|
|
21
21
|
|
|
22
|
+
```an-diagram title="How a scheduling request flows" summary="Whether you click in the calendar or ask the agent, the same actions read live from Google Calendar and write back to the same view."
|
|
23
|
+
{
|
|
24
|
+
"html": "<div class=\"diagram-flow\"><div class=\"diagram-col\"><div class=\"diagram-node\">You click<br><small class=\"diagram-muted\">drag, toolbar, shortcuts</small></div><div class=\"diagram-node\">You ask the agent<br><small class=\"diagram-muted\">\"find a 1-hour slot next week\"</small></div></div><div class=\"diagram-arrow diagram-muted\" aria-hidden=\"true\">→</div><div class=\"diagram-panel center\"><span class=\"diagram-pill accent\">Actions</span><small class=\"diagram-muted\">list-events · check-availability · create-event</small></div><div class=\"diagram-arrow diagram-muted\" aria-hidden=\"true\">→</div><div class=\"diagram-col\"><div class=\"diagram-box\">Google Calendar<br><small class=\"diagram-muted\">live, multi-account</small></div><div class=\"diagram-box\">SQL<br><small class=\"diagram-muted\">bookings · availability</small></div></div><div class=\"diagram-arrow diagram-muted\" aria-hidden=\"true\">↻</div><div class=\"diagram-box\">Calendar view updates live</div></div>",
|
|
25
|
+
"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}"
|
|
26
|
+
}
|
|
27
|
+
```
|
|
28
|
+
|
|
22
29
|
## What you can do with it
|
|
23
30
|
|
|
24
31
|
- **See your real Google Calendar** in day, week, or month view, with multiple accounts overlayed.
|
|
@@ -150,6 +157,73 @@ Defined in `templates/calendar/server/db/schema.ts`. Only non-event data is stor
|
|
|
150
157
|
- `booking_slug_redirects` — remembers old slugs when a link is renamed so existing public URLs keep working.
|
|
151
158
|
- `booking_link_shares` — share grants for booking links.
|
|
152
159
|
|
|
160
|
+
```an-schema title="Calendar data model" summary="Only non-event data is stored locally — events live in Google Calendar. Booking links use ownableColumns so the sharing system applies."
|
|
161
|
+
{
|
|
162
|
+
"entities": [
|
|
163
|
+
{
|
|
164
|
+
"id": "booking_links",
|
|
165
|
+
"name": "booking_links",
|
|
166
|
+
"note": "Calendly-style link definitions (ownable)",
|
|
167
|
+
"fields": [
|
|
168
|
+
{ "name": "id", "type": "id", "pk": true },
|
|
169
|
+
{ "name": "slug", "type": "string", "note": "public page at /book/{slug}" },
|
|
170
|
+
{ "name": "title", "type": "string" },
|
|
171
|
+
{ "name": "description", "type": "string", "nullable": true },
|
|
172
|
+
{ "name": "duration", "type": "int", "note": "primary duration in minutes" },
|
|
173
|
+
{ "name": "durations", "type": "json", "nullable": true, "note": "alternative durations" },
|
|
174
|
+
{ "name": "customFields", "type": "json", "nullable": true },
|
|
175
|
+
{ "name": "conferencing", "type": "string", "note": "Google Meet / Zoom / custom" },
|
|
176
|
+
{ "name": "color", "type": "string", "nullable": true },
|
|
177
|
+
{ "name": "isActive", "type": "bool", "note": "pause without deleting" }
|
|
178
|
+
]
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
"id": "bookings",
|
|
182
|
+
"name": "bookings",
|
|
183
|
+
"note": "Confirmed appointments from public booking pages",
|
|
184
|
+
"fields": [
|
|
185
|
+
{ "name": "id", "type": "id", "pk": true },
|
|
186
|
+
{ "name": "slug", "type": "string", "fk": "booking_links.slug" },
|
|
187
|
+
{ "name": "name", "type": "string" },
|
|
188
|
+
{ "name": "email", "type": "string" },
|
|
189
|
+
{ "name": "start", "type": "datetime" },
|
|
190
|
+
{ "name": "end", "type": "datetime" },
|
|
191
|
+
{ "name": "notes", "type": "string", "nullable": true },
|
|
192
|
+
{ "name": "customFields", "type": "json", "nullable": true, "note": "custom field responses" },
|
|
193
|
+
{ "name": "meetingLink", "type": "string", "nullable": true },
|
|
194
|
+
{ "name": "cancelToken", "type": "string", "note": "powers /booking/manage/{token}" },
|
|
195
|
+
{ "name": "status", "type": "enum", "note": "confirmed | cancelled" }
|
|
196
|
+
]
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
"id": "booking_slug_redirects",
|
|
200
|
+
"name": "booking_slug_redirects",
|
|
201
|
+
"note": "Keeps old public URLs working after a link is renamed",
|
|
202
|
+
"fields": [
|
|
203
|
+
{ "name": "oldSlug", "type": "string", "pk": true },
|
|
204
|
+
{ "name": "linkId", "type": "id", "fk": "booking_links.id" }
|
|
205
|
+
]
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
"id": "booking_link_shares",
|
|
209
|
+
"name": "booking_link_shares",
|
|
210
|
+
"note": "Share grants for booking links",
|
|
211
|
+
"fields": [
|
|
212
|
+
{ "name": "id", "type": "id", "pk": true },
|
|
213
|
+
{ "name": "linkId", "type": "id", "fk": "booking_links.id" },
|
|
214
|
+
{ "name": "principal", "type": "string", "note": "user or org" },
|
|
215
|
+
{ "name": "role", "type": "enum", "note": "viewer | editor | admin" }
|
|
216
|
+
]
|
|
217
|
+
}
|
|
218
|
+
],
|
|
219
|
+
"relations": [
|
|
220
|
+
{ "from": "booking_links", "to": "bookings", "kind": "1-n", "label": "has bookings" },
|
|
221
|
+
{ "from": "booking_links", "to": "booking_slug_redirects", "kind": "1-n", "label": "has old slugs" },
|
|
222
|
+
{ "from": "booking_links", "to": "booking_link_shares", "kind": "1-n", "label": "has share grants" }
|
|
223
|
+
]
|
|
224
|
+
}
|
|
225
|
+
```
|
|
226
|
+
|
|
153
227
|
Availability rules and per-user configuration live in the settings table, keyed by `calendar-availability`. Google OAuth tokens live in the framework `oauth_tokens` table. Ephemeral UI state (current view, date, selected event) lives in `application_state` under the `navigation` key.
|
|
154
228
|
|
|
155
229
|
### Customizing it
|
|
@@ -38,6 +38,13 @@ If you want the smallest action-only runtime with no browser UI, start with [Pur
|
|
|
38
38
|
|
|
39
39
|
That's the point. Chat is a thin, useful default shell for your own agent, not a domain product pretending to be generic.
|
|
40
40
|
|
|
41
|
+
```an-diagram title="What ships in the Chat shell" summary="A thin chat surface over the framework's standard runtime — actions, durable threads, live sync, and auth — with room to add your own UI."
|
|
42
|
+
{
|
|
43
|
+
"html": "<div class=\"diagram-chat\"><div class=\"diagram-col left\"><div class=\"diagram-node\">Thread list<br><small class=\"diagram-muted\">create · reopen · pin · archive</small></div><div class=\"diagram-node\">Full-page chat<br><small class=\"diagram-muted\">framework chat surface on /</small></div></div><div class=\"diagram-arrow diagram-muted\" aria-hidden=\"true\">→</div><div class=\"diagram-panel center\"><span class=\"diagram-pill accent\">Actions</span><small class=\"diagram-muted\">hello.ts · view-screen · navigate</small></div><div class=\"diagram-arrow diagram-muted\" aria-hidden=\"true\">→</div><div class=\"diagram-col right\"><div class=\"diagram-box\">Core SQL tables<br><small class=\"diagram-muted\">threads · application_state · settings · sessions · runs</small></div><div class=\"diagram-pill ok\">Live sync ↻</div><div class=\"diagram-box\">Better Auth<br><small class=\"diagram-muted\">login · orgs · sessions</small></div></div></div>",
|
|
44
|
+
"css": ".diagram-chat{display:flex;align-items:center;gap:12px;flex-wrap:wrap}.diagram-chat .diagram-col{display:flex;flex-direction:column;gap:10px}.diagram-chat .diagram-arrow{font-size:22px;line-height:1}.diagram-chat .center{display:flex;flex-direction:column;align-items:center;gap:4px}"
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
41
48
|
## When to pick it {#when-to-pick}
|
|
42
49
|
|
|
43
50
|
- **You want a basic app users can talk to immediately** and then extend with actions and UI.
|
|
@@ -70,6 +77,18 @@ From there, copy the Chat template's `/` route and sidebar thread list into your
|
|
|
70
77
|
suggestions, empty state, composer, or surrounding layout here.
|
|
71
78
|
- `AGENTS.md` tells the built-in agent how to work inside this app.
|
|
72
79
|
|
|
80
|
+
```an-file-tree title="Chat template layout"
|
|
81
|
+
{
|
|
82
|
+
"entries": [
|
|
83
|
+
{ "path": "actions/hello.ts", "note": "the one example action; replace or add actions beside it" },
|
|
84
|
+
{ "path": "actions/view-screen.ts", "note": "standard context action the agent reads" },
|
|
85
|
+
{ "path": "actions/navigate.ts", "note": "standard navigation action" },
|
|
86
|
+
{ "path": "app/routes/_index.tsx", "note": "renders the full-page chat surface; edit suggestions, empty state, composer" },
|
|
87
|
+
{ "path": "AGENTS.md", "note": "chat-first guidance the built-in agent reads" }
|
|
88
|
+
]
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
73
92
|
The chat page is intentionally thin:
|
|
74
93
|
|
|
75
94
|
```tsx
|
|
@@ -19,6 +19,13 @@ A capture-everything app: screen recordings, meeting notes from your calendar, a
|
|
|
19
19
|
|
|
20
20
|
Think along the lines of Loom + Granola + Wispr Flow rolled into one app — but the agent is a first-class editor across every surface, and the recordings, meetings, and dictations are yours, not a SaaS vendor's. Clips also makes shared recordings agent-readable: paste a normal Clips share link into an agent, and it can "hear" the transcript and "see" timestamped frames even when the underlying model cannot ingest raw video or audio.
|
|
21
21
|
|
|
22
|
+
```an-diagram title="Capture, transcribe, reuse" summary="Three capture types land in one library; the agent transcribes, titles, and summarizes, then every transcript is searchable and shareable."
|
|
23
|
+
{
|
|
24
|
+
"html": "<div class=\"diagram-clips\"><div class=\"diagram-col\"><div class=\"diagram-node\">Screen recording</div><div class=\"diagram-node\">Calendar meeting</div><div class=\"diagram-node\">Fn-hold dictation</div></div><div class=\"diagram-arrow diagram-muted\" aria-hidden=\"true\">→</div><div class=\"diagram-box\" data-rough>One library<br><small class=\"diagram-muted\">recordings + transcripts (SQL)</small></div><div class=\"diagram-arrow diagram-muted\" aria-hidden=\"true\">→</div><div class=\"diagram-panel center\"><span class=\"diagram-pill accent\">Agent</span><small class=\"diagram-muted\">title · summary · chapters</small></div><div class=\"diagram-arrow diagram-muted\" aria-hidden=\"true\">→</div><div class=\"diagram-col\"><div class=\"diagram-pill\">Search</div><div class=\"diagram-pill\">Share</div><div class=\"diagram-pill\">Agent-readable links</div></div></div>",
|
|
25
|
+
"css": ".diagram-clips{display:flex;align-items:center;gap:12px;flex-wrap:wrap}.diagram-clips .diagram-col{display:flex;flex-direction:column;gap:8px}.diagram-clips .center{display:flex;flex-direction:column;align-items:center;gap:4px}.diagram-clips .diagram-arrow{font-size:22px;line-height:1}"
|
|
26
|
+
}
|
|
27
|
+
```
|
|
28
|
+
|
|
22
29
|
## What you can do with it
|
|
23
30
|
|
|
24
31
|
- **Record your screen** with a built-in recorder, webcam overlay, audio capture, and pause/trim.
|
|
@@ -49,6 +56,51 @@ Password-protected clips require the password once; successful responses return
|
|
|
49
56
|
short-lived tokenized links so downstream agents do not need the plaintext
|
|
50
57
|
password.
|
|
51
58
|
|
|
59
|
+
```an-api title="Agent context entry point"
|
|
60
|
+
{
|
|
61
|
+
"method": "GET",
|
|
62
|
+
"path": "/api/agent-context.json",
|
|
63
|
+
"summary": "Compact, agent-readable description of a shared clip",
|
|
64
|
+
"description": "Returns clip metadata, transcript status, chapters, CTAs, recommended frames, and links to the transcript and frame APIs. Advertised by the public share page so a text- or image-only agent can understand a recording without ingesting raw video.",
|
|
65
|
+
"auth": "Same public / password / expiry rules as the share page",
|
|
66
|
+
"params": [
|
|
67
|
+
{ "name": "id", "in": "query", "type": "string", "required": true, "description": "Recording id" }
|
|
68
|
+
],
|
|
69
|
+
"responses": [
|
|
70
|
+
{ "status": "200", "description": "Clip metadata plus transcript and frame API links" }
|
|
71
|
+
]
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
```an-api title="Timestamped transcript"
|
|
76
|
+
{
|
|
77
|
+
"method": "GET",
|
|
78
|
+
"path": "/api/agent-transcript.json",
|
|
79
|
+
"summary": "Timestamped transcript segments for a shared clip",
|
|
80
|
+
"params": [
|
|
81
|
+
{ "name": "id", "in": "query", "type": "string", "required": true, "description": "Recording id" }
|
|
82
|
+
],
|
|
83
|
+
"responses": [
|
|
84
|
+
{ "status": "200", "description": "Segments with startMs, endMs, readable timestamps, text, and optional source labels" }
|
|
85
|
+
]
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
```an-api title="Frame at a timestamp"
|
|
90
|
+
{
|
|
91
|
+
"method": "GET",
|
|
92
|
+
"path": "/api/agent-frame.jpg",
|
|
93
|
+
"summary": "A JPEG frame extracted from the video at an original-video timestamp",
|
|
94
|
+
"params": [
|
|
95
|
+
{ "name": "id", "in": "query", "type": "string", "required": true, "description": "Recording id" },
|
|
96
|
+
{ "name": "atMs", "in": "query", "type": "integer", "required": true, "description": "Original-video timestamp in milliseconds" }
|
|
97
|
+
],
|
|
98
|
+
"responses": [
|
|
99
|
+
{ "status": "200", "description": "image/jpeg frame" }
|
|
100
|
+
]
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
52
104
|
## Getting started
|
|
53
105
|
|
|
54
106
|
Live demo: [clips.agent-native.com](https://clips.agent-native.com).
|
|
@@ -105,6 +157,67 @@ Clips is a larger template with a native recorder (it ships a desktop companion
|
|
|
105
157
|
|
|
106
158
|
All data lives in SQL via Drizzle ORM. Schema: `templates/clips/server/db/schema.ts`. Recordings, meetings, dictations, calendar accounts, and vocabulary all carry the standard `ownableColumns` and have a matching framework shares table, so they slot into the per-user / per-org sharing model.
|
|
107
159
|
|
|
160
|
+
```an-schema title="Clips core data model" summary="recordings is the source of truth for media; transcripts, meetings, and dictations compose with it rather than duplicating video. (Engagement and org tables omitted for clarity — see the full table below.)"
|
|
161
|
+
{
|
|
162
|
+
"entities": [
|
|
163
|
+
{
|
|
164
|
+
"id": "recordings",
|
|
165
|
+
"name": "recordings",
|
|
166
|
+
"note": "Core resource; source of truth for media. ownableColumns",
|
|
167
|
+
"fields": [
|
|
168
|
+
{ "name": "id", "type": "text", "pk": true },
|
|
169
|
+
{ "name": "title", "type": "text" },
|
|
170
|
+
{ "name": "video_url", "type": "text", "note": "plus format / size / duration / thumbnails" },
|
|
171
|
+
{ "name": "status", "type": "text" },
|
|
172
|
+
{ "name": "edits_json", "type": "text", "note": "Non-destructive edits" },
|
|
173
|
+
{ "name": "chapters_json", "type": "text", "nullable": true },
|
|
174
|
+
{ "name": "password", "type": "text", "nullable": true, "note": "Privacy: password / expiry" }
|
|
175
|
+
]
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
"id": "recording_transcripts",
|
|
179
|
+
"name": "recording_transcripts",
|
|
180
|
+
"note": "Split out so the library and transcript views render fast",
|
|
181
|
+
"fields": [
|
|
182
|
+
{ "name": "recording_id", "type": "text", "fk": "recordings.id" },
|
|
183
|
+
{ "name": "segments_json", "type": "text", "note": "{ startMs, endMs, text }" },
|
|
184
|
+
{ "name": "full_text", "type": "text" },
|
|
185
|
+
{ "name": "language", "type": "text" },
|
|
186
|
+
{ "name": "status", "type": "text" }
|
|
187
|
+
]
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
"id": "clips_meetings",
|
|
191
|
+
"name": "clips_meetings",
|
|
192
|
+
"note": "Calendar-sourced or ad-hoc; owns a recording",
|
|
193
|
+
"fields": [
|
|
194
|
+
{ "name": "id", "type": "text", "pk": true },
|
|
195
|
+
{ "name": "recording_id", "type": "text", "fk": "recordings.id", "nullable": true },
|
|
196
|
+
{ "name": "summary_md", "type": "text", "nullable": true },
|
|
197
|
+
{ "name": "bullets_json", "type": "text", "nullable": true },
|
|
198
|
+
{ "name": "action_items_json", "type": "text", "nullable": true }
|
|
199
|
+
]
|
|
200
|
+
},
|
|
201
|
+
{
|
|
202
|
+
"id": "clips_dictations",
|
|
203
|
+
"name": "clips_dictations",
|
|
204
|
+
"note": "Push-to-talk dictation history; ownableColumns",
|
|
205
|
+
"fields": [
|
|
206
|
+
{ "name": "id", "type": "text", "pk": true },
|
|
207
|
+
{ "name": "full_text", "type": "text", "note": "Raw" },
|
|
208
|
+
{ "name": "cleaned_text", "type": "text", "nullable": true },
|
|
209
|
+
{ "name": "source", "type": "text", "note": "fn-hold, etc." },
|
|
210
|
+
{ "name": "target_app", "type": "text", "nullable": true }
|
|
211
|
+
]
|
|
212
|
+
}
|
|
213
|
+
],
|
|
214
|
+
"relations": [
|
|
215
|
+
{ "from": "recordings", "to": "recording_transcripts", "kind": "1-1", "label": "transcript" },
|
|
216
|
+
{ "from": "recordings", "to": "clips_meetings", "kind": "1-1", "label": "captured by" }
|
|
217
|
+
]
|
|
218
|
+
}
|
|
219
|
+
```
|
|
220
|
+
|
|
108
221
|
| Table | What it holds |
|
|
109
222
|
| ----------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
110
223
|
| `recordings` | The core resource — title, video URL/format/size, duration, thumbnails, status, non-destructive `edits_json`, `chapters_json`, privacy (password, expiry), and player toggles |
|
|
@@ -23,6 +23,13 @@ result whether you do it yourself or ask.
|
|
|
23
23
|
|
|
24
24
|
When you open the app, you'll see a sidebar tree of pages on the left, the editor in the middle, and the agent in the sidebar on the right. The agent always knows which page you're viewing and what text you have selected.
|
|
25
25
|
|
|
26
|
+
```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."
|
|
27
|
+
{
|
|
28
|
+
"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>",
|
|
29
|
+
"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}"
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
26
33
|
## What you can do with it
|
|
27
34
|
|
|
28
35
|
- **Write rich text** with headings, lists, tables, code blocks, images, and links. Slash commands (`/`) insert blocks; selecting text pops up a formatting toolbar.
|
|
@@ -269,6 +276,132 @@ Nine tables, all defined in `server/db/schema.ts`:
|
|
|
269
276
|
- **`document_property_values`** — per-document property values (`property_id` → `value_json`).
|
|
270
277
|
- **`document_shares`** — per-user and per-org grants created via `createSharesTable`.
|
|
271
278
|
|
|
279
|
+
```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."
|
|
280
|
+
{
|
|
281
|
+
"entities": [
|
|
282
|
+
{
|
|
283
|
+
"id": "documents",
|
|
284
|
+
"name": "documents",
|
|
285
|
+
"note": "The page tree (ownable, markdown body)",
|
|
286
|
+
"fields": [
|
|
287
|
+
{ "name": "id", "type": "id", "pk": true },
|
|
288
|
+
{ "name": "parent_id", "type": "id", "fk": "documents.id", "nullable": true, "note": "infinite nesting" },
|
|
289
|
+
{ "name": "title", "type": "string" },
|
|
290
|
+
{ "name": "content", "type": "markdown" },
|
|
291
|
+
{ "name": "icon", "type": "string", "nullable": true },
|
|
292
|
+
{ "name": "position", "type": "int", "note": "sibling ordering" },
|
|
293
|
+
{ "name": "is_favorite", "type": "bool" },
|
|
294
|
+
{ "name": "visibility", "type": "enum", "note": "private | org | public" },
|
|
295
|
+
{ "name": "owner_email", "type": "string" },
|
|
296
|
+
{ "name": "org_id", "type": "id", "nullable": true }
|
|
297
|
+
]
|
|
298
|
+
},
|
|
299
|
+
{
|
|
300
|
+
"id": "document_versions",
|
|
301
|
+
"name": "document_versions",
|
|
302
|
+
"note": "Full title/content snapshots for version history",
|
|
303
|
+
"fields": [
|
|
304
|
+
{ "name": "id", "type": "id", "pk": true },
|
|
305
|
+
{ "name": "document_id", "type": "id", "fk": "documents.id" },
|
|
306
|
+
{ "name": "title", "type": "string" },
|
|
307
|
+
{ "name": "content", "type": "markdown" }
|
|
308
|
+
]
|
|
309
|
+
},
|
|
310
|
+
{
|
|
311
|
+
"id": "document_comments",
|
|
312
|
+
"name": "document_comments",
|
|
313
|
+
"note": "Threaded comments with quoted-text anchors",
|
|
314
|
+
"fields": [
|
|
315
|
+
{ "name": "id", "type": "id", "pk": true },
|
|
316
|
+
{ "name": "document_id", "type": "id", "fk": "documents.id" },
|
|
317
|
+
{ "name": "thread_id", "type": "id" },
|
|
318
|
+
{ "name": "parent_id", "type": "id", "fk": "document_comments.id", "nullable": true },
|
|
319
|
+
{ "name": "quoted_text", "type": "string", "nullable": true },
|
|
320
|
+
{ "name": "resolved", "type": "bool" },
|
|
321
|
+
{ "name": "notion_comment_id", "type": "string", "nullable": true, "note": "bidirectional Notion sync" }
|
|
322
|
+
]
|
|
323
|
+
},
|
|
324
|
+
{
|
|
325
|
+
"id": "document_sync_links",
|
|
326
|
+
"name": "document_sync_links",
|
|
327
|
+
"note": "One row per Notion-linked document",
|
|
328
|
+
"fields": [
|
|
329
|
+
{ "name": "id", "type": "id", "pk": true },
|
|
330
|
+
{ "name": "document_id", "type": "id", "fk": "documents.id" },
|
|
331
|
+
{ "name": "notion_page_id", "type": "string" },
|
|
332
|
+
{ "name": "conflict", "type": "bool" },
|
|
333
|
+
{ "name": "content_hash", "type": "string" }
|
|
334
|
+
]
|
|
335
|
+
},
|
|
336
|
+
{
|
|
337
|
+
"id": "content_databases",
|
|
338
|
+
"name": "content_databases",
|
|
339
|
+
"note": "Inline database objects attached to a document",
|
|
340
|
+
"fields": [
|
|
341
|
+
{ "name": "id", "type": "id", "pk": true },
|
|
342
|
+
{ "name": "document_id", "type": "id", "fk": "documents.id" },
|
|
343
|
+
{ "name": "title", "type": "string" },
|
|
344
|
+
{ "name": "view_config", "type": "json" }
|
|
345
|
+
]
|
|
346
|
+
},
|
|
347
|
+
{
|
|
348
|
+
"id": "content_database_items",
|
|
349
|
+
"name": "content_database_items",
|
|
350
|
+
"note": "Rows in an inline database (each row is a document)",
|
|
351
|
+
"fields": [
|
|
352
|
+
{ "name": "id", "type": "id", "pk": true },
|
|
353
|
+
{ "name": "database_id", "type": "id", "fk": "content_databases.id" },
|
|
354
|
+
{ "name": "document_id", "type": "id", "fk": "documents.id" }
|
|
355
|
+
]
|
|
356
|
+
},
|
|
357
|
+
{
|
|
358
|
+
"id": "document_property_definitions",
|
|
359
|
+
"name": "document_property_definitions",
|
|
360
|
+
"note": "Column definitions for inline databases",
|
|
361
|
+
"fields": [
|
|
362
|
+
{ "name": "id", "type": "id", "pk": true },
|
|
363
|
+
{ "name": "name", "type": "string" },
|
|
364
|
+
{ "name": "type", "type": "string" },
|
|
365
|
+
{ "name": "options", "type": "json", "nullable": true },
|
|
366
|
+
{ "name": "position", "type": "int" }
|
|
367
|
+
]
|
|
368
|
+
},
|
|
369
|
+
{
|
|
370
|
+
"id": "document_property_values",
|
|
371
|
+
"name": "document_property_values",
|
|
372
|
+
"note": "Per-document property values",
|
|
373
|
+
"fields": [
|
|
374
|
+
{ "name": "id", "type": "id", "pk": true },
|
|
375
|
+
{ "name": "document_id", "type": "id", "fk": "documents.id" },
|
|
376
|
+
{ "name": "property_id", "type": "id", "fk": "document_property_definitions.id" },
|
|
377
|
+
{ "name": "value_json", "type": "json" }
|
|
378
|
+
]
|
|
379
|
+
},
|
|
380
|
+
{
|
|
381
|
+
"id": "document_shares",
|
|
382
|
+
"name": "document_shares",
|
|
383
|
+
"note": "Per-user and per-org grants (createSharesTable)",
|
|
384
|
+
"fields": [
|
|
385
|
+
{ "name": "id", "type": "id", "pk": true },
|
|
386
|
+
{ "name": "document_id", "type": "id", "fk": "documents.id" },
|
|
387
|
+
{ "name": "principal", "type": "string" },
|
|
388
|
+
{ "name": "role", "type": "enum", "note": "viewer | editor | admin" }
|
|
389
|
+
]
|
|
390
|
+
}
|
|
391
|
+
],
|
|
392
|
+
"relations": [
|
|
393
|
+
{ "from": "documents", "to": "documents", "kind": "1-n", "label": "has children" },
|
|
394
|
+
{ "from": "documents", "to": "document_versions", "kind": "1-n", "label": "has snapshots" },
|
|
395
|
+
{ "from": "documents", "to": "document_comments", "kind": "1-n", "label": "has comments" },
|
|
396
|
+
{ "from": "documents", "to": "document_sync_links", "kind": "1-1", "label": "links to Notion" },
|
|
397
|
+
{ "from": "documents", "to": "content_databases", "kind": "1-n", "label": "hosts databases" },
|
|
398
|
+
{ "from": "content_databases", "to": "content_database_items", "kind": "1-n", "label": "has rows" },
|
|
399
|
+
{ "from": "document_property_definitions", "to": "document_property_values", "kind": "1-n", "label": "has values" },
|
|
400
|
+
{ "from": "documents", "to": "document_shares", "kind": "1-n", "label": "has share grants" }
|
|
401
|
+
]
|
|
402
|
+
}
|
|
403
|
+
```
|
|
404
|
+
|
|
272
405
|
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
406
|
|
|
274
407
|
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.
|
|
@@ -11,6 +11,13 @@ Design is an agent-native HTML prototyping studio. Instead of a layered drawing
|
|
|
11
11
|
|
|
12
12
|
When you open the app, you see your designs on the left, the generated prototype rendered in an iframe in the middle, and the agent plus tweak controls on the right. Everything the agent produces is real HTML you can refine, export, or hand off.
|
|
13
13
|
|
|
14
|
+
```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."
|
|
15
|
+
{
|
|
16
|
+
"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>",
|
|
17
|
+
"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}"
|
|
18
|
+
}
|
|
19
|
+
```
|
|
20
|
+
|
|
14
21
|
## When to pick it
|
|
15
22
|
|
|
16
23
|
- **You want a polished landing-page concept, product UI direction, or brand exploration** that can leave the tool as real HTML — not a layered drawing canvas.
|
|
@@ -73,6 +80,54 @@ All data lives in SQL via Drizzle ORM. Schema: `templates/design/server/db/schem
|
|
|
73
80
|
| `design_systems` | Reusable brand tokens — `data` (colors/typography/spacing), `assets`, `custom_instructions`, and an `is_default` flag |
|
|
74
81
|
| `design_shares` / `design_system_shares` | Framework shares tables mapping principals (users or orgs) to roles (viewer, editor, admin) |
|
|
75
82
|
|
|
83
|
+
```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."
|
|
84
|
+
{
|
|
85
|
+
"entities": [
|
|
86
|
+
{ "id": "designs", "name": "designs", "note": "A design project (ownable)", "fields": [
|
|
87
|
+
{ "name": "id", "type": "id", "pk": true },
|
|
88
|
+
{ "name": "title", "type": "text" },
|
|
89
|
+
{ "name": "description", "type": "text", "nullable": true },
|
|
90
|
+
{ "name": "project_type", "type": "text", "note": "prototype / other" },
|
|
91
|
+
{ "name": "data", "type": "json", "note": "starts as {}" },
|
|
92
|
+
{ "name": "design_system_id", "type": "id", "fk": "design_systems.id", "nullable": true }
|
|
93
|
+
] },
|
|
94
|
+
{ "id": "files", "name": "design_files", "note": "Files in a design", "fields": [
|
|
95
|
+
{ "name": "design_id", "type": "id", "fk": "designs.id" },
|
|
96
|
+
{ "name": "filename", "type": "text" },
|
|
97
|
+
{ "name": "content", "type": "text" },
|
|
98
|
+
{ "name": "file_type", "type": "text", "note": "defaults to html" }
|
|
99
|
+
] },
|
|
100
|
+
{ "id": "versions", "name": "design_versions", "note": "History / rollback", "fields": [
|
|
101
|
+
{ "name": "design_id", "type": "id", "fk": "designs.id" },
|
|
102
|
+
{ "name": "snapshot", "type": "json" },
|
|
103
|
+
{ "name": "label", "type": "text", "nullable": true }
|
|
104
|
+
] },
|
|
105
|
+
{ "id": "systems", "name": "design_systems", "note": "Reusable brand tokens (ownable)", "fields": [
|
|
106
|
+
{ "name": "id", "type": "id", "pk": true },
|
|
107
|
+
{ "name": "data", "type": "json", "note": "colors / typography / spacing" },
|
|
108
|
+
{ "name": "assets", "type": "json", "nullable": true },
|
|
109
|
+
{ "name": "custom_instructions", "type": "text", "nullable": true },
|
|
110
|
+
{ "name": "is_default", "type": "boolean" }
|
|
111
|
+
] },
|
|
112
|
+
{ "id": "design_shares", "name": "design_shares", "note": "Framework shares table", "fields": [
|
|
113
|
+
{ "name": "design_id", "type": "id", "fk": "designs.id" },
|
|
114
|
+
{ "name": "role", "type": "text", "note": "viewer / editor / admin" }
|
|
115
|
+
] },
|
|
116
|
+
{ "id": "system_shares", "name": "design_system_shares", "note": "Framework shares table", "fields": [
|
|
117
|
+
{ "name": "design_system_id", "type": "id", "fk": "design_systems.id" },
|
|
118
|
+
{ "name": "role", "type": "text", "note": "viewer / editor / admin" }
|
|
119
|
+
] }
|
|
120
|
+
],
|
|
121
|
+
"relations": [
|
|
122
|
+
{ "from": "designs", "to": "files", "kind": "1-n" },
|
|
123
|
+
{ "from": "designs", "to": "versions", "kind": "1-n" },
|
|
124
|
+
{ "from": "systems", "to": "designs", "kind": "1-n", "label": "applied to" },
|
|
125
|
+
{ "from": "designs", "to": "design_shares", "kind": "1-n" },
|
|
126
|
+
{ "from": "systems", "to": "system_shares", "kind": "1-n" }
|
|
127
|
+
]
|
|
128
|
+
}
|
|
129
|
+
```
|
|
130
|
+
|
|
76
131
|
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
132
|
|
|
78
133
|
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`.
|
|
@@ -21,6 +21,13 @@ Dispatch is the **workspace control plane**. Where other templates are domain ap
|
|
|
21
21
|
|
|
22
22
|
If you're running an [multi-app workspace](/docs/multi-app-workspace) with many apps, Dispatch is the glue.
|
|
23
23
|
|
|
24
|
+
```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."
|
|
25
|
+
{
|
|
26
|
+
"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>",
|
|
27
|
+
"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}"
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
24
31
|
## What it does {#what-it-does}
|
|
25
32
|
|
|
26
33
|
- **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 +90,49 @@ _How it works under the hood (for developers)._
|
|
|
83
90
|
- **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
91
|
- **Slack / Telegram plugins.** Server plugins that register webhooks and forward incoming messages to the orchestrator agent.
|
|
85
92
|
- **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.
|
|
93
|
+
|
|
94
|
+
```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)."
|
|
95
|
+
{
|
|
96
|
+
"entities": [
|
|
97
|
+
{ "id": "secrets", "name": "vault_secrets", "note": "Stored credential values", "fields": [
|
|
98
|
+
{ "name": "id", "type": "text", "pk": true },
|
|
99
|
+
{ "name": "owner_email", "type": "text" },
|
|
100
|
+
{ "name": "org_id", "type": "text", "nullable": true },
|
|
101
|
+
{ "name": "name", "type": "text" },
|
|
102
|
+
{ "name": "credential_key", "type": "text" },
|
|
103
|
+
{ "name": "value", "type": "text", "note": "secret value" },
|
|
104
|
+
{ "name": "provider", "type": "text", "nullable": true }
|
|
105
|
+
] },
|
|
106
|
+
{ "id": "grants", "name": "vault_grants", "note": "Per-app access grant", "fields": [
|
|
107
|
+
{ "name": "id", "type": "text", "pk": true },
|
|
108
|
+
{ "name": "secret_id", "type": "text", "fk": "vault_secrets.id" },
|
|
109
|
+
{ "name": "app_id", "type": "text" },
|
|
110
|
+
{ "name": "granted_by", "type": "text" },
|
|
111
|
+
{ "name": "status", "type": "text" }
|
|
112
|
+
] },
|
|
113
|
+
{ "id": "requests", "name": "vault_requests", "note": "Access request + review", "fields": [
|
|
114
|
+
{ "name": "id", "type": "text", "pk": true },
|
|
115
|
+
{ "name": "credential_key", "type": "text" },
|
|
116
|
+
{ "name": "app_id", "type": "text" },
|
|
117
|
+
{ "name": "reason", "type": "text", "nullable": true },
|
|
118
|
+
{ "name": "status", "type": "text" },
|
|
119
|
+
{ "name": "reviewed_by", "type": "text", "nullable": true }
|
|
120
|
+
] },
|
|
121
|
+
{ "id": "audit", "name": "vault_audit_log", "note": "Who used which secret when", "fields": [
|
|
122
|
+
{ "name": "id", "type": "text", "pk": true },
|
|
123
|
+
{ "name": "secret_id", "type": "text", "fk": "vault_secrets.id", "nullable": true },
|
|
124
|
+
{ "name": "app_id", "type": "text", "nullable": true },
|
|
125
|
+
{ "name": "action", "type": "text" },
|
|
126
|
+
{ "name": "actor", "type": "text" }
|
|
127
|
+
] }
|
|
128
|
+
],
|
|
129
|
+
"relations": [
|
|
130
|
+
{ "from": "secrets", "to": "grants", "kind": "1-n", "label": "granted via" },
|
|
131
|
+
{ "from": "secrets", "to": "audit", "kind": "1-n", "label": "use recorded by" }
|
|
132
|
+
]
|
|
133
|
+
}
|
|
134
|
+
```
|
|
135
|
+
|
|
86
136
|
- **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
137
|
|
|
88
138
|
## Dreams {#dreams}
|