@agent-native/core 0.141.3 → 0.141.5
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/corpus/README.md +1 -1
- package/corpus/templates/analytics/.agents/skills/analysis-workspace/SKILL.md +1 -1
- package/corpus/templates/analytics/actions/gong-calls.ts +56 -18
- package/corpus/templates/analytics/changelog/2026-08-05-analytics-queries-keep-every-table-tenant-scoped.md +6 -0
- package/corpus/templates/analytics/changelog/2026-08-05-fixed-sign-in-and-dashboard-requests-failing-when-background.md +6 -0
- package/corpus/templates/analytics/changelog/2026-08-05-historical-rollups-stay-complete-while-live-events-arrive.md +6 -0
- package/corpus/templates/analytics/server/db/schema.ts +1 -0
- package/corpus/templates/analytics/server/lib/dashboard-report.ts +2 -0
- package/corpus/templates/analytics/server/lib/emails.ts +51 -0
- package/corpus/templates/analytics/server/lib/first-party-analytics-health.ts +8 -12
- package/corpus/templates/analytics/server/lib/first-party-analytics-rollups.ts +9 -0
- package/corpus/templates/analytics/server/lib/first-party-analytics.ts +262 -13
- package/corpus/templates/analytics/server/lib/gong.ts +132 -33
- package/corpus/templates/analytics/server/plugins/agent-chat.ts +1 -1
- package/corpus/templates/analytics/server/plugins/auth.ts +21 -2
- package/corpus/templates/analytics/server/plugins/db.ts +11 -3
- package/corpus/templates/analytics/server/plugins/transactional-emails.ts +5 -0
- package/corpus/templates/calendar/app/components/calendar/InlineEventPickers.tsx +17 -7
- package/corpus/templates/calendar/server/lib/booking-emails.ts +154 -70
- package/corpus/templates/calendar/server/lib/emails.ts +167 -0
- package/corpus/templates/calendar/server/lib/event-guest-notifications.ts +64 -28
- package/corpus/templates/calendar/server/plugins/transactional-emails.ts +5 -0
- package/corpus/templates/clips/actions/invite-member.ts +39 -16
- package/corpus/templates/clips/app/components/player/share-dialog.tsx +73 -1
- package/corpus/templates/clips/app/i18n/en-US.ts +3 -0
- package/corpus/templates/clips/app/routes/r.$recordingId.tsx +10 -25
- package/corpus/templates/clips/app/routes/share.$shareId.tsx +2 -0
- package/corpus/templates/clips/changelog/2026-08-05-activity-is-now-the-default-clips-recording-tab-and-ai-setup.md +6 -0
- package/corpus/templates/clips/changelog/2026-08-05-clips-can-copy-a-linked-email-preview-for-public-recordings.md +6 -0
- package/corpus/templates/clips/changelog/2026-08-05-preparing-recording-now-uses-a-clean-shadow-free-status-card.md +6 -0
- package/corpus/templates/clips/desktop/src/styles.css +0 -3
- package/corpus/templates/clips/server/lib/emails.ts +256 -0
- package/corpus/templates/clips/server/lib/transactional-email-templates.ts +24 -0
- package/corpus/templates/clips/server/plugins/transactional-email-catalog.ts +5 -0
- package/corpus/templates/clips/server/routes/api/thumbnail/[recordingId].get.ts +4 -1
- package/corpus/templates/clips/shared/email-preview.ts +61 -0
- package/corpus/templates/content/server/lib/comment-notifications.ts +57 -26
- package/corpus/templates/content/server/lib/emails.ts +70 -0
- package/corpus/templates/content/server/plugins/transactional-emails.ts +5 -0
- package/corpus/templates/design/actions/import-design-tokens.ts +11 -8
- package/corpus/templates/design/actions/index-design-tokens.ts +13 -6
- package/corpus/templates/design/changelog/2026-08-05-design-token-imports-classify-typography-dimensions-correctly.md +6 -0
- package/corpus/templates/dispatch/app/routes/transactional-email.$appId.$id.tsx +4 -0
- package/corpus/templates/dispatch/app/routes/transactional-email.tsx +4 -0
- package/corpus/templates/dispatch/changelog/2026-08-05-transactional-email-catalogs-and-delivery-activity-are-available-again.md +6 -0
- package/corpus/templates/factory/AGENTS.md +18 -17
- package/corpus/templates/factory/actions/get-factory-automation-health.ts +50 -0
- package/corpus/templates/factory/actions/get-triage-config.ts +8 -0
- package/corpus/templates/factory/actions/save-triage-config.ts +26 -0
- package/corpus/templates/factory/app/i18n/en-US.ts +27 -0
- package/corpus/templates/factory/app/routes/factory.tsx +376 -206
- package/corpus/templates/factory/changelog/2026-08-05-factory-now-keeps-production-automations-running-shows-sched.md +6 -0
- package/corpus/templates/factory/server/db/schema.ts +6 -0
- package/corpus/templates/factory/server/plugins/factory-migrations.ts +10 -0
- package/corpus/templates/factory/server/plugins/factory-scheduler-job.ts +141 -2
- package/corpus/templates/forms/app/pages/FormsListPage.tsx +41 -21
- package/corpus/templates/forms/changelog/2026-08-05-form-links-can-now-be-cmd-clicked-to-open-in-a-new-tab.md +6 -0
- package/corpus/templates/forms/server/lib/emails.ts +52 -0
- package/corpus/templates/forms/server/lib/response-email.ts +2 -0
- package/corpus/templates/forms/server/plugins/transactional-emails.ts +5 -0
- package/corpus/templates/plan/actions/request-plan-access.ts +33 -12
- package/corpus/templates/plan/server/lib/comment-notifications.ts +53 -27
- package/corpus/templates/plan/server/lib/emails.ts +67 -0
- package/corpus/templates/plan/server/plugins/transactional-emails.ts +5 -0
- package/corpus/templates/slides/actions/import-from-url.ts +1 -0
- package/corpus/templates/slides/app/components/editor/NewDeckReferenceStep.tsx +492 -381
- package/corpus/templates/slides/app/components/editor/PromptDialog.tsx +8 -7
- package/corpus/templates/slides/app/components/layout/Layout.tsx +27 -23
- package/corpus/templates/slides/app/components/onboarding/FirstDeckOnboardingFlow.tsx +313 -0
- package/corpus/templates/slides/app/components/ui/command.tsx +1 -0
- package/corpus/templates/slides/app/i18n/en-US.ts +8 -2
- package/corpus/templates/slides/app/lib/create-deck-generation.ts +305 -0
- package/corpus/templates/slides/app/pages/DeckEditor.tsx +12 -12
- package/corpus/templates/slides/app/pages/Index.tsx +127 -137
- package/corpus/templates/slides/app/root.tsx +8 -0
- package/corpus/templates/slides/changelog/2026-08-05-deck-browsing-keeps-all-and-mine-in-the-header-with-a-tighte.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-05-new-deck-creation-now-flows-through-a-clean-full-screen-refe.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-05-website-imports-now-include-linked-stylesheets-for-more-accu.md +6 -0
- package/corpus/templates/slides/server/lib/comment-notifications.ts +44 -21
- package/corpus/templates/slides/server/lib/emails.ts +40 -0
- package/corpus/templates/slides/server/plugins/transactional-emails.ts +5 -0
- package/dist/brand-kit/index.d.ts +1 -0
- package/dist/brand-kit/index.js +1 -0
- package/dist/brand-kit/tokens.d.ts +91 -0
- package/dist/brand-kit/tokens.js +279 -0
- package/dist/brand-kit/types.d.ts +25 -0
- package/dist/client/AssistantChat.js +7 -7
- package/dist/client/onboarding/FirstRunOnboarding.js +26 -2
- package/dist/client/onboarding/first-run-registry.d.ts +25 -0
- package/dist/client/onboarding/first-run-registry.js +18 -0
- package/dist/client/onboarding/index.d.ts +2 -0
- package/dist/client/onboarding/index.js +1 -0
- package/dist/collab/routes.d.ts +2 -2
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/deploy/build.d.ts +8 -0
- package/dist/deploy/build.js +92 -3
- package/dist/deploy/workspace-deploy.js +86 -3
- package/dist/email-catalog/actions/list-email-activity.d.ts +5 -0
- package/dist/email-catalog/actions/list-email-activity.js +19 -0
- package/dist/email-catalog/actions/list-email-engagement.d.ts +5 -0
- package/dist/email-catalog/actions/list-email-engagement.js +15 -0
- package/dist/email-catalog/actions/list-email-log.d.ts +7 -0
- package/dist/email-catalog/actions/list-email-log.js +23 -0
- package/dist/email-catalog/actions/list-transactional-emails.d.ts +22 -0
- package/dist/email-catalog/actions/list-transactional-emails.js +67 -0
- package/dist/email-catalog/actions/render-transactional-email-preview.d.ts +9 -0
- package/dist/email-catalog/actions/render-transactional-email-preview.js +25 -0
- package/dist/email-catalog/authorize.d.ts +1 -0
- package/dist/email-catalog/authorize.js +9 -0
- package/dist/email-catalog/log.d.ts +60 -0
- package/dist/email-catalog/log.js +142 -0
- package/dist/email-catalog/provider-metrics.d.ts +34 -0
- package/dist/email-catalog/provider-metrics.js +182 -0
- package/dist/email-catalog/registry.d.ts +78 -0
- package/dist/email-catalog/registry.js +70 -0
- package/dist/email-catalog/schema.d.ts +231 -0
- package/dist/email-catalog/schema.js +53 -0
- package/dist/email-catalog/system-emails.d.ts +13 -0
- package/dist/email-catalog/system-emails.js +67 -0
- package/dist/jobs/index.d.ts +2 -0
- package/dist/jobs/index.js +2 -0
- package/dist/jobs/run-history.js +48 -1
- package/dist/jobs/scheduler-dispatch.d.ts +7 -0
- package/dist/jobs/scheduler-dispatch.js +7 -0
- package/dist/jobs/scheduler-health.d.ts +22 -0
- package/dist/jobs/scheduler-health.js +172 -0
- package/dist/jobs/scheduler.js +67 -2
- package/dist/localization/default-messages.d.ts +45 -0
- package/dist/localization/default-messages.js +45 -0
- package/dist/mcp/screen-memory-stdio.d.ts +7 -7
- package/dist/notifications/routes.d.ts +2 -2
- package/dist/observability/routes.d.ts +3 -3
- package/dist/org/handlers.js +9 -1
- package/dist/provider-api/actions/custom-provider-registration.d.ts +10 -10
- package/dist/provider-api/actions/provider-api.d.ts +8 -8
- package/dist/secrets/routes.d.ts +9 -9
- package/dist/server/action-discovery.js +22 -0
- package/dist/server/agent-chat/recurring-jobs-runtime.d.ts +7 -1
- package/dist/server/agent-chat/recurring-jobs-runtime.js +12 -0
- package/dist/server/agent-chat-plugin.d.ts +2 -1
- package/dist/server/agent-chat-plugin.js +39 -1
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/better-auth-instance.js +17 -2
- package/dist/server/design-token-utils.d.ts +6 -1
- package/dist/server/design-token-utils.js +252 -59
- package/dist/server/email.d.ts +11 -0
- package/dist/server/email.js +54 -3
- package/dist/server/index.d.ts +1 -0
- package/dist/server/index.js +1 -0
- package/dist/server/realtime-token.d.ts +1 -1
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/dist/vite/client.js +20 -14
- package/docs/AGENTS.md +1 -1
- package/docs/content/actions.mdx +1 -1
- package/docs/content/agent-surfaces.mdx +1 -1
- package/docs/content/agents.mdx +9 -0
- package/docs/content/database.mdx +2 -2
- package/docs/content/drop-in-agent.mdx +1 -1
- package/docs/content/notifications.mdx +1 -1
- package/docs/content/routing.mdx +1 -1
- package/docs/content/server-database.mdx +437 -0
- package/docs/content/server-middleware.mdx +151 -0
- package/docs/content/server-overview.mdx +234 -0
- package/docs/content/server-plugins.mdx +147 -0
- package/docs/content/server-routes.mdx +194 -0
- package/package.json +2 -1
- package/docs/content/server.mdx +0 -469
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Middleware"
|
|
3
|
+
description: "Nitro middleware in server/middleware/ — what it is, how to write your own, and how the built-in auth guard works."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Middleware
|
|
7
|
+
|
|
8
|
+
Middleware is code that runs on every incoming request before it reaches a route handler. It sits between callers and routes, making it the right place for cross-cutting concerns: authentication, logging, CORS headers, rate limiting, or anything that needs to apply regardless of which route handles the request.
|
|
9
|
+
|
|
10
|
+
<Diagram id="doc-block-server-middleware-1" title="Where middleware runs" summary="Middleware intercepts every request before it reaches a route. Allowed requests continue to the route handler; blocked requests get a redirect or error response.">
|
|
11
|
+
|
|
12
|
+
```html
|
|
13
|
+
<div class="diagram-mw">
|
|
14
|
+
<div class="diagram-col">
|
|
15
|
+
<div class="diagram-node">Browser / UI</div>
|
|
16
|
+
<div class="diagram-node">Agent loop</div>
|
|
17
|
+
<div class="diagram-node">
|
|
18
|
+
External clients<br /><small class="diagram-muted"
|
|
19
|
+
>HTTP · MCP · A2A</small
|
|
20
|
+
>
|
|
21
|
+
</div>
|
|
22
|
+
</div>
|
|
23
|
+
<div class="diagram-arrow diagram-muted" aria-hidden="true">→</div>
|
|
24
|
+
<div class="diagram-panel" data-rough>
|
|
25
|
+
<strong>Middleware</strong>
|
|
26
|
+
<small class="diagram-muted">server/middleware/</small>
|
|
27
|
+
<small class="diagram-muted">runs on every request</small>
|
|
28
|
+
</div>
|
|
29
|
+
<div class="mw-outcomes">
|
|
30
|
+
<div class="mw-outcome">
|
|
31
|
+
<span class="mw-label diagram-muted">allowed</span>
|
|
32
|
+
<span class="mw-arrow diagram-muted" aria-hidden="true">→</span>
|
|
33
|
+
<div class="diagram-box" data-rough>Routes & handlers</div>
|
|
34
|
+
</div>
|
|
35
|
+
<div class="mw-outcome">
|
|
36
|
+
<span class="mw-label diagram-muted">blocked</span>
|
|
37
|
+
<span class="mw-arrow diagram-muted" aria-hidden="true">→</span>
|
|
38
|
+
<div class="diagram-box" data-rough>Redirect / error</div>
|
|
39
|
+
</div>
|
|
40
|
+
</div>
|
|
41
|
+
</div>
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
```css
|
|
45
|
+
.diagram-mw {
|
|
46
|
+
display: flex;
|
|
47
|
+
align-items: center;
|
|
48
|
+
gap: 14px;
|
|
49
|
+
flex-wrap: wrap;
|
|
50
|
+
}
|
|
51
|
+
.diagram-mw .diagram-col {
|
|
52
|
+
display: flex;
|
|
53
|
+
flex-direction: column;
|
|
54
|
+
gap: 10px;
|
|
55
|
+
}
|
|
56
|
+
.diagram-mw .diagram-panel {
|
|
57
|
+
display: flex;
|
|
58
|
+
flex-direction: column;
|
|
59
|
+
gap: 4px;
|
|
60
|
+
padding: 12px 16px;
|
|
61
|
+
}
|
|
62
|
+
.diagram-mw .diagram-arrow {
|
|
63
|
+
font-size: 22px;
|
|
64
|
+
line-height: 1;
|
|
65
|
+
}
|
|
66
|
+
.mw-outcomes {
|
|
67
|
+
display: flex;
|
|
68
|
+
flex-direction: column;
|
|
69
|
+
gap: 10px;
|
|
70
|
+
}
|
|
71
|
+
.mw-outcome {
|
|
72
|
+
display: flex;
|
|
73
|
+
align-items: center;
|
|
74
|
+
gap: 8px;
|
|
75
|
+
}
|
|
76
|
+
.mw-label {
|
|
77
|
+
font-size: 11px;
|
|
78
|
+
min-width: 44px;
|
|
79
|
+
text-align: right;
|
|
80
|
+
}
|
|
81
|
+
.mw-arrow {
|
|
82
|
+
font-size: 16px;
|
|
83
|
+
line-height: 1;
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
</Diagram>
|
|
88
|
+
|
|
89
|
+
Files in `server/middleware/` are picked up automatically by Nitro — no registration required. Every file in that directory runs for every request, in alphabetical order.
|
|
90
|
+
|
|
91
|
+
## Writing Middleware {#writing-middleware}
|
|
92
|
+
|
|
93
|
+
A middleware file exports a `defineEventHandler`. To let the request continue, return nothing. To block it, throw a `createError` or return a redirect with `sendRedirect`.
|
|
94
|
+
|
|
95
|
+
```ts filename="server/middleware/cors.ts"
|
|
96
|
+
import { defineEventHandler, setResponseHeader } from "h3";
|
|
97
|
+
|
|
98
|
+
export default defineEventHandler((event) => {
|
|
99
|
+
setResponseHeader(event, "Access-Control-Allow-Origin", "*");
|
|
100
|
+
// returning nothing passes the request through to the route handler
|
|
101
|
+
});
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Multiple middleware files run in alphabetical filename order before the matched route handler. Each middleware can inspect or modify the request, set response headers, or short-circuit the response entirely.
|
|
105
|
+
|
|
106
|
+
For more middleware patterns — conditional logic, async operations, response interception — see the [Nitro middleware docs](https://nitro.build/guide/routing#middleware) and the [H3 docs](https://h3.unjs.io).
|
|
107
|
+
|
|
108
|
+
## The Auth Middleware {#auth-middleware}
|
|
109
|
+
|
|
110
|
+
Every agent-native app ships `server/middleware/auth.ts`. It enforces authentication across all routes, including public page routes and custom `/api/*` routes that would otherwise bypass the framework's built-in auth.
|
|
111
|
+
|
|
112
|
+
### The Auth Guard {#auth-guard}
|
|
113
|
+
|
|
114
|
+
```ts filename="server/middleware/auth.ts"
|
|
115
|
+
import { runAuthGuard } from "@agent-native/core/server";
|
|
116
|
+
import { defineEventHandler } from "h3";
|
|
117
|
+
|
|
118
|
+
export default defineEventHandler(async (event) => {
|
|
119
|
+
return runAuthGuard(event);
|
|
120
|
+
});
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
`runAuthGuard` checks every request against the auth configuration set up by the [auth plugin](/docs/server-plugins#auth-plugin). If the request is unauthenticated and the path is not in `publicPaths`, it redirects to the sign-in page.
|
|
124
|
+
|
|
125
|
+
### Why Middleware, Not a Plugin or Route Guard {#why-middleware}
|
|
126
|
+
|
|
127
|
+
The framework handler's built-in middleware registry is scoped to `/_agent-native/*` routes. Without a separate middleware file, page routes (`/`, `/settings`) and custom API routes (`/api/*`) bypass authentication entirely.
|
|
128
|
+
|
|
129
|
+
Plugins run at startup, not per-request, so they cannot enforce per-request auth. A route-level guard in each custom route handler is error-prone and easy to forget. Middleware in `server/middleware/` is the one place that runs for every request regardless of path.
|
|
130
|
+
|
|
131
|
+
### Adding Public Paths {#public-paths}
|
|
132
|
+
|
|
133
|
+
To allow unauthenticated access to specific paths, pass them to `createAuthPlugin` in `server/plugins/auth.ts` — not to the middleware directly:
|
|
134
|
+
|
|
135
|
+
```ts filename="server/plugins/auth.ts"
|
|
136
|
+
import { createAuthPlugin } from "@agent-native/core/server";
|
|
137
|
+
|
|
138
|
+
export default createAuthPlugin({
|
|
139
|
+
publicPaths: ["/public", "/api/webhooks/stripe"],
|
|
140
|
+
marketing: { appName: "My App", tagline: "..." },
|
|
141
|
+
});
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
`runAuthGuard` reads the configured public paths from the auth plugin at request time.
|
|
145
|
+
|
|
146
|
+
## What's next {#whats-next}
|
|
147
|
+
|
|
148
|
+
- [**Plugins**](/docs/server-plugins): auth plugin configuration that the middleware enforces
|
|
149
|
+
- [**Routes**](/docs/server-routes): custom routes that are protected by this middleware
|
|
150
|
+
- [**Security**](/docs/security): data scoping, access guards, and the full auth model
|
|
151
|
+
- [**Nitro middleware docs**](https://nitro.build/guide/routing#middleware): full middleware API and patterns
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Server"
|
|
3
|
+
description: "The Nitro server layer in an agent-native app: what it's for, when to reach for custom routes, and how its pieces connect."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Server
|
|
7
|
+
|
|
8
|
+
The `server/` directory is the infrastructure layer of an agent-native app. It handles startup tasks, authentication, and the HTTP surfaces that actions don't cover. Most product behavior belongs in [Actions](/docs/actions). The server is what makes those actions available.
|
|
9
|
+
|
|
10
|
+
<Diagram id="doc-block-server-overview-1" title="How requests flow through the server" summary="Callers reach the Nitro server, which handles most requests through Actions. Middleware and Routes cover cases Actions can't. Both paths can query the database.">
|
|
11
|
+
|
|
12
|
+
```html
|
|
13
|
+
<div class="diagram-srv">
|
|
14
|
+
<div class="diagram-col">
|
|
15
|
+
<div class="diagram-node">Browser / UI</div>
|
|
16
|
+
<div class="diagram-node">Agent loop</div>
|
|
17
|
+
<div class="diagram-node">
|
|
18
|
+
External clients<br /><small class="diagram-muted"
|
|
19
|
+
>HTTP · MCP · A2A</small
|
|
20
|
+
>
|
|
21
|
+
</div>
|
|
22
|
+
</div>
|
|
23
|
+
<div class="diagram-arrow diagram-muted" aria-hidden="true">→</div>
|
|
24
|
+
<div class="diagram-panel" data-rough>
|
|
25
|
+
<strong>Nitro server</strong>
|
|
26
|
+
<div class="srv-path">
|
|
27
|
+
<span class="diagram-pill accent">Actions</span
|
|
28
|
+
><small class="diagram-muted">primary path</small>
|
|
29
|
+
</div>
|
|
30
|
+
<div class="srv-or diagram-muted">or</div>
|
|
31
|
+
<div class="srv-path">
|
|
32
|
+
<span class="diagram-pill">Middleware</span
|
|
33
|
+
><span class="srv-inner-arrow diagram-muted" aria-hidden="true"
|
|
34
|
+
>→</span
|
|
35
|
+
><span class="diagram-pill">Routes</span>
|
|
36
|
+
</div>
|
|
37
|
+
</div>
|
|
38
|
+
<div class="diagram-arrow diagram-muted" aria-hidden="true">→</div>
|
|
39
|
+
<div class="diagram-box" data-rough>
|
|
40
|
+
SQL database<br /><small class="diagram-muted">Drizzle</small>
|
|
41
|
+
</div>
|
|
42
|
+
</div>
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
```css
|
|
46
|
+
.diagram-srv {
|
|
47
|
+
display: flex;
|
|
48
|
+
align-items: center;
|
|
49
|
+
gap: 14px;
|
|
50
|
+
flex-wrap: wrap;
|
|
51
|
+
}
|
|
52
|
+
.diagram-srv .diagram-col {
|
|
53
|
+
display: flex;
|
|
54
|
+
flex-direction: column;
|
|
55
|
+
gap: 10px;
|
|
56
|
+
}
|
|
57
|
+
.diagram-srv .diagram-panel {
|
|
58
|
+
display: flex;
|
|
59
|
+
flex-direction: column;
|
|
60
|
+
gap: 8px;
|
|
61
|
+
padding: 14px 16px;
|
|
62
|
+
}
|
|
63
|
+
.diagram-srv .diagram-arrow {
|
|
64
|
+
font-size: 22px;
|
|
65
|
+
line-height: 1;
|
|
66
|
+
}
|
|
67
|
+
.srv-path {
|
|
68
|
+
display: flex;
|
|
69
|
+
align-items: center;
|
|
70
|
+
gap: 8px;
|
|
71
|
+
}
|
|
72
|
+
.srv-or {
|
|
73
|
+
font-size: 11px;
|
|
74
|
+
text-transform: uppercase;
|
|
75
|
+
letter-spacing: 0.06em;
|
|
76
|
+
padding-left: 2px;
|
|
77
|
+
}
|
|
78
|
+
.srv-inner-arrow {
|
|
79
|
+
font-size: 14px;
|
|
80
|
+
line-height: 1;
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
</Diagram>
|
|
85
|
+
|
|
86
|
+
## Where the Server Fits {#role}
|
|
87
|
+
|
|
88
|
+
In a traditional web app, the server is where most logic lives. Business rules, data access, and presentation all happen inside route handlers. Agent-native apps work differently. Logic lives in actions, which the agent and UI share as equal partners. The server's job is coordination: run database migrations, configure authentication, mount the agent loop, and handle the narrow set of HTTP concerns that actions can't express on their own.
|
|
89
|
+
|
|
90
|
+
<Diagram id="doc-block-server-overview-2" title="Traditional server vs. Agent Native">
|
|
91
|
+
|
|
92
|
+
```html
|
|
93
|
+
<div class="diagram-cmp">
|
|
94
|
+
<div class="cmp-col">
|
|
95
|
+
<div class="cmp-label diagram-muted">Traditional</div>
|
|
96
|
+
<div class="diagram-node">Browser</div>
|
|
97
|
+
<div class="cmp-arrow diagram-muted" aria-hidden="true">↓</div>
|
|
98
|
+
<div class="diagram-panel" data-rough>
|
|
99
|
+
<strong>Server</strong>
|
|
100
|
+
<small class="diagram-muted">logic lives here</small>
|
|
101
|
+
<div class="cmp-pills">
|
|
102
|
+
<span class="cmp-tag">Route handlers</span>
|
|
103
|
+
<span class="cmp-tag">Business logic</span>
|
|
104
|
+
<span class="cmp-tag">Data access</span>
|
|
105
|
+
</div>
|
|
106
|
+
</div>
|
|
107
|
+
<div class="cmp-arrow diagram-muted" aria-hidden="true">↓</div>
|
|
108
|
+
<div class="diagram-box" data-rough>Database</div>
|
|
109
|
+
</div>
|
|
110
|
+
<div class="cmp-vs diagram-muted">vs</div>
|
|
111
|
+
<div class="cmp-col">
|
|
112
|
+
<div class="cmp-label diagram-muted">Agent Native</div>
|
|
113
|
+
<div class="cmp-callers">
|
|
114
|
+
<div class="diagram-node">Browser / UI</div>
|
|
115
|
+
<div class="diagram-node">Agent</div>
|
|
116
|
+
</div>
|
|
117
|
+
<div class="cmp-arrow diagram-muted" aria-hidden="true">↓</div>
|
|
118
|
+
<div class="diagram-panel" data-rough>
|
|
119
|
+
<strong>Server</strong>
|
|
120
|
+
<small class="diagram-muted">coordination only</small>
|
|
121
|
+
<div class="cmp-pills">
|
|
122
|
+
<span class="cmp-tag">Actions</span>
|
|
123
|
+
<span class="cmp-tag">Auth</span>
|
|
124
|
+
<span class="cmp-tag">Migrations</span>
|
|
125
|
+
</div>
|
|
126
|
+
</div>
|
|
127
|
+
<div class="cmp-arrow diagram-muted" aria-hidden="true">↓</div>
|
|
128
|
+
<div class="diagram-box" data-rough>Database</div>
|
|
129
|
+
</div>
|
|
130
|
+
</div>
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
```css
|
|
134
|
+
.diagram-cmp {
|
|
135
|
+
display: flex;
|
|
136
|
+
align-items: flex-start;
|
|
137
|
+
gap: 28px;
|
|
138
|
+
flex-wrap: wrap;
|
|
139
|
+
}
|
|
140
|
+
.cmp-col {
|
|
141
|
+
display: flex;
|
|
142
|
+
flex-direction: column;
|
|
143
|
+
align-items: center;
|
|
144
|
+
gap: 8px;
|
|
145
|
+
flex: 1;
|
|
146
|
+
min-width: 160px;
|
|
147
|
+
}
|
|
148
|
+
.cmp-label {
|
|
149
|
+
font-size: 11px;
|
|
150
|
+
text-transform: uppercase;
|
|
151
|
+
letter-spacing: 0.06em;
|
|
152
|
+
font-weight: 600;
|
|
153
|
+
}
|
|
154
|
+
.cmp-callers {
|
|
155
|
+
display: flex;
|
|
156
|
+
gap: 8px;
|
|
157
|
+
flex-wrap: wrap;
|
|
158
|
+
justify-content: center;
|
|
159
|
+
}
|
|
160
|
+
.cmp-vs {
|
|
161
|
+
font-size: 13px;
|
|
162
|
+
font-weight: 600;
|
|
163
|
+
padding-top: 52px;
|
|
164
|
+
}
|
|
165
|
+
.diagram-cmp .diagram-panel {
|
|
166
|
+
display: flex;
|
|
167
|
+
flex-direction: column;
|
|
168
|
+
gap: 6px;
|
|
169
|
+
padding: 12px 16px;
|
|
170
|
+
align-self: stretch;
|
|
171
|
+
align-items: flex-start;
|
|
172
|
+
}
|
|
173
|
+
.cmp-pills {
|
|
174
|
+
display: flex;
|
|
175
|
+
flex-wrap: wrap;
|
|
176
|
+
gap: 6px;
|
|
177
|
+
}
|
|
178
|
+
.cmp-tag {
|
|
179
|
+
font-size: 12px;
|
|
180
|
+
opacity: 0.7;
|
|
181
|
+
margin-right: 10px;
|
|
182
|
+
}
|
|
183
|
+
.cmp-arrow {
|
|
184
|
+
font-size: 18px;
|
|
185
|
+
line-height: 1;
|
|
186
|
+
}
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
</Diagram>
|
|
190
|
+
|
|
191
|
+
Browser requests, the agent loop, and external API clients all route through the same Nitro server and read from the same SQL database. There is no separate agent backend or UI backend. The server layer is what exposes actions to the outside world.
|
|
192
|
+
|
|
193
|
+
## What's in the server/ directory {#server-directory}
|
|
194
|
+
|
|
195
|
+
These are the directories and files inside `server/` that every agent-native app ships. Each corresponds to a specific piece of the server layer: what it does, when to reach for it, and how it connects to the rest of the framework.
|
|
196
|
+
|
|
197
|
+
| Page | What it covers |
|
|
198
|
+
| ----------------------------------------- | ----------------------------------------------------------------------------------- |
|
|
199
|
+
| **[Database](/docs/server-database)** | Schema definition with `table()` helpers, `getDb`, and ownable table patterns |
|
|
200
|
+
| **[Middleware](/docs/server-middleware)** | Auth guards in `server/middleware/` and why they run there instead of in a plugin |
|
|
201
|
+
| **[Plugins](/docs/server-plugins)** | The three startup plugins every app ships: db migrations, auth, and agent-chat |
|
|
202
|
+
| **[Routes](/docs/server-routes)** | File-based routes, the SSR catch-all, and scoping custom routes to the request user |
|
|
203
|
+
|
|
204
|
+
## Nitro {#nitro}
|
|
205
|
+
|
|
206
|
+
[Nitro](https://nitro.build) is the server toolkit that powers the agent-native HTTP layer. Most of what you'll configure in `server/` is Nitro: file-based routes, startup plugins, and middleware.
|
|
207
|
+
|
|
208
|
+
- **File-based routing**: the filename maps directly to an HTTP method and URL path, with no registration needed. `server/routes/api/health.get.ts` becomes `GET /api/health` automatically. Visit [Routes](/docs/server-routes) for more details.
|
|
209
|
+
- **Plugins**: code that runs once at server startup, before any request is served. Database migrations, auth configuration, and the agent-chat mount all happen in `server/plugins/`. Visit [Plugins](/docs/server-plugins) for more details.
|
|
210
|
+
- **Middleware**: code that runs on every incoming request before it reaches a route. The auth guard lives in `server/middleware/`. Visit [Middleware](/docs/server-middleware) for more details.
|
|
211
|
+
|
|
212
|
+
Nitro is also deployment-agnostic. The same app deploys to Node.js, Cloudflare Workers, Netlify, Vercel, and other runtimes with no code changes. Just set a preset. See [Deployment](/docs/deployment).
|
|
213
|
+
|
|
214
|
+
The underlying request/response API is [H3](https://h3.unjs.io). When you see `defineEventHandler`, `createError`, or `getQuery` in custom routes, that's H3. The [Nitro docs](https://nitro.build/guide) and [H3 docs](https://h3.unjs.io) are the reference for anything the framework doesn't cover directly.
|
|
215
|
+
|
|
216
|
+
## Default to Actions first {#actions-first}
|
|
217
|
+
|
|
218
|
+
Agent Native architecture is different. Whenever you think of a new feature for your application, consider first whether it can be an action. For example, if the UI and agent both need to do something, define an action instead of a custom API route. Actions automatically become:
|
|
219
|
+
|
|
220
|
+
- Agent tools.
|
|
221
|
+
- Typed frontend hooks.
|
|
222
|
+
- HTTP endpoints under `/_agent-native/actions/:name`.
|
|
223
|
+
- MCP and A2A-callable tools.
|
|
224
|
+
- CLI commands for development.
|
|
225
|
+
|
|
226
|
+
Use custom `/api/*` routes only when you need a route-shaped protocol or binary/streaming behavior. For more details, visit [Actions](/docs/actions).
|
|
227
|
+
|
|
228
|
+
## What's next {#whats-next}
|
|
229
|
+
|
|
230
|
+
- [**Actions**](/docs/actions): the default operation surface. Reach for a custom route only when it doesn't fit.
|
|
231
|
+
- [**Database**](/docs/server-database): the `getDb()`/schema pattern custom routes and actions both import
|
|
232
|
+
- [**Middleware**](/docs/server-middleware): auth guards and the `server/middleware/` directory
|
|
233
|
+
- [**Plugins**](/docs/server-plugins): startup plugins for migrations, auth, and the agent
|
|
234
|
+
- [**Routes**](/docs/server-routes): file-based routes, request context, and the SSR catch-all
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Plugins"
|
|
3
|
+
description: "Startup plugins in server/plugins/ — what they are, the two plugins every app ships, the optional database plugin, and how to write your own."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Plugins
|
|
7
|
+
|
|
8
|
+
Plugins are startup hooks. Each file in `server/plugins/` exports a function that Nitro calls once when the server initializes, before any route is served. They are the right place for one-time setup: configuring auth, mounting the agent loop, running database migrations, or registering any other initialization code that needs to complete before requests arrive.
|
|
9
|
+
|
|
10
|
+
Nitro discovers plugins automatically from the filesystem. No registration or imports are required. Files run in alphabetical order, so execution order is controlled by filename prefix.
|
|
11
|
+
|
|
12
|
+
Every agent-native app ships two plugins by default:
|
|
13
|
+
|
|
14
|
+
```text
|
|
15
|
+
server/plugins/
|
|
16
|
+
auth.ts -> configure auth provider and public paths
|
|
17
|
+
agent-chat.ts -> mount the agent loop with your actions and system prompt
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Apps that need custom database tables add a third:
|
|
21
|
+
|
|
22
|
+
```text
|
|
23
|
+
server/plugins/
|
|
24
|
+
db.ts -> run migrations on startup
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Auth Plugin {#auth-plugin}
|
|
28
|
+
|
|
29
|
+
`server/plugins/auth.ts` configures how users sign in. `createAuthPlugin` from `@agent-native/core/server` wires up the auth provider and sets the sign-in page branding:
|
|
30
|
+
|
|
31
|
+
```ts filename="server/plugins/auth.ts"
|
|
32
|
+
import { createAuthPlugin } from "@agent-native/core/server";
|
|
33
|
+
|
|
34
|
+
export default createAuthPlugin({
|
|
35
|
+
marketing: {
|
|
36
|
+
appName: "My App",
|
|
37
|
+
tagline: "A short description shown on the sign-in page.",
|
|
38
|
+
features: ["Feature one", "Feature two", "Feature three"],
|
|
39
|
+
},
|
|
40
|
+
});
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
To open specific routes to unauthenticated users, pass `publicPaths`:
|
|
44
|
+
|
|
45
|
+
```ts
|
|
46
|
+
export default createAuthPlugin({
|
|
47
|
+
publicPaths: ["/public", "/api/webhook"],
|
|
48
|
+
marketing: { appName: "My App", tagline: "..." },
|
|
49
|
+
});
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
The auth plugin configures the guard. The middleware in `server/middleware/auth.ts` enforces it on every request. See [Middleware](/docs/server-middleware).
|
|
53
|
+
|
|
54
|
+
## Agent-Chat Plugin {#agent-chat-plugin}
|
|
55
|
+
|
|
56
|
+
`server/plugins/agent-chat.ts` mounts the agent loop with your app's actions, system prompt, and initial tool set. This is the plugin that makes your app an agent-native app.
|
|
57
|
+
|
|
58
|
+
```ts filename="server/plugins/agent-chat.ts"
|
|
59
|
+
import { getOrgContext } from "@agent-native/core/org";
|
|
60
|
+
import {
|
|
61
|
+
createAgentChatPlugin,
|
|
62
|
+
loadActionsFromStaticRegistry,
|
|
63
|
+
} from "@agent-native/core/server";
|
|
64
|
+
|
|
65
|
+
import actionsRegistry from "../../.generated/actions-registry.js";
|
|
66
|
+
|
|
67
|
+
export default createAgentChatPlugin({
|
|
68
|
+
appId: "my-app",
|
|
69
|
+
actions: loadActionsFromStaticRegistry(actionsRegistry),
|
|
70
|
+
initialToolNames: ["view-screen", "navigate"],
|
|
71
|
+
resolveOrgId: async (event) => (await getOrgContext(event)).orgId,
|
|
72
|
+
systemPrompt: `You are the My App agent.
|
|
73
|
+
|
|
74
|
+
Use actions as the source of truth. Start by inspecting the current
|
|
75
|
+
screen when context matters.`,
|
|
76
|
+
});
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
`loadActionsFromStaticRegistry` picks up every action exported from `actions/` through the generated registry. `initialToolNames` controls which actions the agent has access to at the start of a conversation. It can still call others as needed.
|
|
80
|
+
|
|
81
|
+
## Database Plugin {#database-plugin}
|
|
82
|
+
|
|
83
|
+
If your app defines custom database tables, add `server/plugins/db.ts` to run schema migrations at startup. It uses `runMigrations` from `@agent-native/core/db`:
|
|
84
|
+
|
|
85
|
+
```ts filename="server/plugins/db.ts"
|
|
86
|
+
import { runMigrations } from "@agent-native/core/db";
|
|
87
|
+
|
|
88
|
+
export default runMigrations(
|
|
89
|
+
[
|
|
90
|
+
{
|
|
91
|
+
version: 1,
|
|
92
|
+
name: "projects-table",
|
|
93
|
+
sql: `CREATE TABLE IF NOT EXISTS projects (
|
|
94
|
+
id TEXT PRIMARY KEY,
|
|
95
|
+
title TEXT NOT NULL,
|
|
96
|
+
owner_email TEXT NOT NULL,
|
|
97
|
+
org_id TEXT,
|
|
98
|
+
created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
99
|
+
)`,
|
|
100
|
+
},
|
|
101
|
+
],
|
|
102
|
+
{ table: "my_app_migrations" },
|
|
103
|
+
);
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Each entry needs a `version` number and a `sql` string. Give it a stable `name` too — `runMigrations` tracks named entries independently of `version`, so it still applies exactly once even if another branch reuses the same version number for unrelated DDL. The `table` option names the migration tracking table. Use a name unique to your app so it does not collide with framework migrations. See [Database](/docs/server-database#migrations) for the full schema authoring guide and the name-based tracking rationale.
|
|
107
|
+
|
|
108
|
+
<Callout tone="warning">
|
|
109
|
+
Migrations must be additive. Never put destructive SQL (`DROP TABLE`, `ALTER
|
|
110
|
+
TABLE ... DROP COLUMN`, `DELETE FROM`) in startup plugins.
|
|
111
|
+
</Callout>
|
|
112
|
+
|
|
113
|
+
## Writing Custom Plugins {#custom-plugins}
|
|
114
|
+
|
|
115
|
+
The framework helpers (`createAuthPlugin`, `createAgentChatPlugin`, `runMigrations`) each return a Nitro plugin function. For anything outside those helpers, write a plugin using `defineNitroPlugin`:
|
|
116
|
+
|
|
117
|
+
```ts filename="server/plugins/my-plugin.ts"
|
|
118
|
+
import { defineNitroPlugin } from "nitropack/runtime";
|
|
119
|
+
|
|
120
|
+
export default defineNitroPlugin((nitro) => {
|
|
121
|
+
nitro.hooks.hook("request", (event) => {
|
|
122
|
+
// runs on every request
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
nitro.hooks.hookOnce("close", async () => {
|
|
126
|
+
// runs when the server shuts down
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Plugins can use any of Nitro's lifecycle hooks: `request`, `beforeResponse`, `close`, and others. The [Nitro plugin docs](https://nitro.build/guide/plugins) cover the full hook API and the plugin contract in detail.
|
|
132
|
+
|
|
133
|
+
## Startup Order {#startup-order}
|
|
134
|
+
|
|
135
|
+
Nitro discovers plugins in lexical filename order, so with the default names it invokes `agent-chat.ts`, then `auth.ts`, then `db.ts` — not the dependency order you might expect.
|
|
136
|
+
|
|
137
|
+
File order controls only when each plugin _starts_, not when it _finishes_. Nitro does not await one plugin's async default export before invoking the next, so a later plugin's synchronous setup — and the first incoming request — can run while an earlier plugin's async work (like migrations) is still in flight. `createAuthPlugin` and `createAgentChatPlugin` coordinate internally so framework routes wait for both to finish initializing before serving requests. `runMigrations` has no equivalent coordination: nothing blocks an action or route from querying the database before `db.ts` finishes running its migrations.
|
|
138
|
+
|
|
139
|
+
If you add custom plugins, prefix their filenames to control invocation order, but don't rely on filename order alone to sequence async work across plugins.
|
|
140
|
+
|
|
141
|
+
## What's next {#whats-next}
|
|
142
|
+
|
|
143
|
+
- [**Database**](/docs/server-database): schema helpers and the `getDb` pattern used inside plugins
|
|
144
|
+
- [**Middleware**](/docs/server-middleware): the auth guard that enforces what the auth plugin configures
|
|
145
|
+
- [**Routes**](/docs/server-routes): custom file routes served after plugins complete
|
|
146
|
+
- [**Writing Agent Instructions**](/docs/writing-agent-instructions): how to craft the `systemPrompt` in the agent-chat plugin
|
|
147
|
+
- [**Nitro plugin docs**](https://nitro.build/guide/plugins): the full plugin API and lifecycle hooks
|