@agent-native/core 0.48.2 → 0.48.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/README.md +4 -4
- package/dist/cli/skills.js +173 -30
- package/dist/cli/skills.js.map +1 -1
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +10 -19
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/ErrorBoundary.d.ts.map +1 -1
- package/dist/client/ErrorBoundary.js +34 -1
- package/dist/client/ErrorBoundary.js.map +1 -1
- package/dist/client/index.d.ts +2 -1
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +2 -1
- package/dist/client/index.js.map +1 -1
- package/dist/client/require-session.d.ts +61 -0
- package/dist/client/require-session.d.ts.map +1 -0
- package/dist/client/require-session.js +75 -0
- package/dist/client/require-session.js.map +1 -0
- package/dist/client/route-chunk-recovery.d.ts +17 -0
- package/dist/client/route-chunk-recovery.d.ts.map +1 -1
- package/dist/client/route-chunk-recovery.js +67 -0
- package/dist/client/route-chunk-recovery.js.map +1 -1
- package/dist/deploy/build.d.ts.map +1 -1
- package/dist/deploy/build.js +15 -71
- package/dist/deploy/build.js.map +1 -1
- package/dist/mcp/actions/service-token-access.d.ts.map +1 -1
- package/dist/mcp/actions/service-token-access.js +30 -2
- package/dist/mcp/actions/service-token-access.js.map +1 -1
- package/dist/server/auth.d.ts.map +1 -1
- package/dist/server/auth.js +3 -0
- package/dist/server/auth.js.map +1 -1
- package/dist/server/onboarding-html.d.ts.map +1 -1
- package/dist/server/onboarding-html.js +12 -11
- package/dist/server/onboarding-html.js.map +1 -1
- package/dist/server/ssr-handler.d.ts.map +1 -1
- package/dist/server/ssr-handler.js +42 -130
- package/dist/server/ssr-handler.js.map +1 -1
- package/dist/templates/workspace-core/.agents/skills/authentication/SKILL.md +36 -1
- package/docs/content/agent-web-surfaces.md +2 -2
- package/docs/content/authentication.md +1 -1
- package/docs/content/cloneable-saas.md +2 -2
- package/docs/content/code-agents-ui.md +16 -17
- package/docs/content/creating-templates.md +3 -3
- package/docs/content/deployment.md +18 -18
- package/docs/content/dispatch.md +2 -2
- package/docs/content/external-agents.md +21 -28
- package/docs/content/faq.md +1 -1
- package/docs/content/frames.md +1 -1
- package/docs/content/getting-started.md +7 -7
- package/docs/content/mcp-apps.md +1 -1
- package/docs/content/mcp-protocol.md +2 -2
- package/docs/content/migration-workbench.md +2 -2
- package/docs/content/multi-app-workspace.md +8 -8
- package/docs/content/multi-tenancy.md +1 -1
- package/docs/content/plan-plugin.md +6 -8
- package/docs/content/pr-visual-recap.md +23 -23
- package/docs/content/pure-agent-apps.md +1 -1
- package/docs/content/skills-guide.md +3 -3
- package/docs/content/template-analytics.md +1 -1
- package/docs/content/template-assets.md +4 -4
- package/docs/content/template-brain.md +1 -1
- package/docs/content/template-calendar.md +1 -1
- package/docs/content/template-clips.md +1 -1
- package/docs/content/template-content.md +1 -1
- package/docs/content/template-design.md +1 -1
- package/docs/content/template-dispatch.md +1 -1
- package/docs/content/template-forms.md +2 -2
- package/docs/content/template-mail.md +2 -2
- package/docs/content/template-plan.md +6 -12
- package/docs/content/template-slides.md +1 -1
- package/docs/content/template-starter.md +2 -2
- package/docs/content/template-videos.md +1 -1
- package/docs/content/workspace-management.md +1 -1
- package/package.json +1 -1
- package/src/templates/workspace-core/.agents/skills/authentication/SKILL.md +36 -1
|
@@ -20,43 +20,10 @@ import { defineEventHandler } from "h3";
|
|
|
20
20
|
import { getSentryClientConfigScript } from "./sentry-config.js";
|
|
21
21
|
import { computeInlineScriptHash } from "./security-headers.js";
|
|
22
22
|
import { getAppBasePathFromViteEnv, stripAppBasePath as canonicalStripAppBasePath, } from "./app-base-path.js";
|
|
23
|
-
import { BETTER_AUTH_COOKIE_PREFIX, COOKIE_NAME, getSession } from "./auth.js";
|
|
24
23
|
import { runWithRequestContext } from "./request-context.js";
|
|
25
|
-
import { requestHasEmbedAuthMarker } from "./embed-session.js";
|
|
26
|
-
import { EMBED_SESSION_COOKIE, EMBED_TOKEN_QUERY_PARAM, } from "../shared/embed-auth.js";
|
|
27
24
|
import { AGENT_NATIVE_SOCIAL_IMAGE_ALT, AGENT_NATIVE_SOCIAL_IMAGE_HEIGHT, AGENT_NATIVE_SOCIAL_IMAGE_PATH, AGENT_NATIVE_SOCIAL_IMAGE_TYPE, AGENT_NATIVE_SOCIAL_IMAGE_WIDTH, } from "../shared/social-meta.js";
|
|
28
25
|
import { DEFAULT_SSR_CACHE_HEADERS, DEFAULT_SPECULATION_RULES_PATH, } from "../shared/cache-control.js";
|
|
29
26
|
export { DEFAULT_SSR_CACHE_HEADERS, DEFAULT_SPECULATION_RULES_HEADER, DEFAULT_SSR_CACHE_CONTROL, } from "../shared/cache-control.js";
|
|
30
|
-
const ANONYMOUS_SESSION_COOKIE_NAMES = new Set(["an_docs_session"]);
|
|
31
|
-
const BETTER_AUTH_SESSION_COOKIE_RE = /\.session_(?:token|data)$/;
|
|
32
|
-
/**
|
|
33
|
-
* Read the active org for a request without forcing every template to bundle
|
|
34
|
-
* the org module. Mirrors what `core-routes-plugin` does for action handlers.
|
|
35
|
-
*
|
|
36
|
-
* Fast path: when the session already carries a valid orgId (backfilled by
|
|
37
|
-
* backfillSessionOrg during getSession), return it directly — no additional
|
|
38
|
-
* org_members round trip. Only when the session has no orgId do we fall
|
|
39
|
-
* through to getOrgContext for the full membership lookup.
|
|
40
|
-
*/
|
|
41
|
-
async function readOrgIdForEvent(event, session) {
|
|
42
|
-
// Reuse orgId already resolved by backfillSessionOrg inside getSession.
|
|
43
|
-
const sessionOrgId = typeof session?.orgId === "string" && session.orgId.trim()
|
|
44
|
-
? session.orgId.trim()
|
|
45
|
-
: undefined;
|
|
46
|
-
if (sessionOrgId)
|
|
47
|
-
return sessionOrgId;
|
|
48
|
-
// No orgId on the session — full org_members lookup needed.
|
|
49
|
-
// getOrgContext is per-event memoized, so this is at most one DB read
|
|
50
|
-
// even if other request code calls getOrgContext independently.
|
|
51
|
-
try {
|
|
52
|
-
const { getOrgContext } = await import("../org/context.js");
|
|
53
|
-
const ctx = await getOrgContext(event);
|
|
54
|
-
return ctx?.orgId ?? undefined;
|
|
55
|
-
}
|
|
56
|
-
catch {
|
|
57
|
-
return undefined;
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
27
|
function getAppBasePath() {
|
|
61
28
|
return getAppBasePathFromViteEnv();
|
|
62
29
|
}
|
|
@@ -162,37 +129,6 @@ function injectDefaultSocialImageMeta(html, imageUrl) {
|
|
|
162
129
|
return html;
|
|
163
130
|
return html.slice(0, headCloseIdx) + tags.join("") + html.slice(headCloseIdx);
|
|
164
131
|
}
|
|
165
|
-
function requestHasAuthSignal(event) {
|
|
166
|
-
const headers = event.req.headers;
|
|
167
|
-
return Boolean(headers.get("authorization") ||
|
|
168
|
-
requestHasAuthenticatedCookie(headers.get("cookie")) ||
|
|
169
|
-
event.url.searchParams.has(EMBED_TOKEN_QUERY_PARAM) ||
|
|
170
|
-
event.url.searchParams.has("_session") ||
|
|
171
|
-
requestHasEmbedAuthMarker(event));
|
|
172
|
-
}
|
|
173
|
-
function requestHasAuthenticatedCookie(cookieHeader) {
|
|
174
|
-
if (!cookieHeader)
|
|
175
|
-
return false;
|
|
176
|
-
return cookieHeader
|
|
177
|
-
.split(";")
|
|
178
|
-
.map((cookie) => cookie.trim().split("=", 1)[0]?.trim())
|
|
179
|
-
.filter((name) => Boolean(name))
|
|
180
|
-
.some(isAuthenticatedCookieName);
|
|
181
|
-
}
|
|
182
|
-
function isAuthenticatedCookieName(name) {
|
|
183
|
-
if (ANONYMOUS_SESSION_COOKIE_NAMES.has(name))
|
|
184
|
-
return false;
|
|
185
|
-
const bareName = name.replace(/^__(?:Secure|Host)-/, "");
|
|
186
|
-
return (bareName === COOKIE_NAME ||
|
|
187
|
-
bareName === EMBED_SESSION_COOKIE ||
|
|
188
|
-
bareName === "an_session" ||
|
|
189
|
-
bareName === "an_session_workspace" ||
|
|
190
|
-
bareName.startsWith("an_session_") ||
|
|
191
|
-
bareName === `${BETTER_AUTH_COOKIE_PREFIX}.session_token` ||
|
|
192
|
-
bareName === `${BETTER_AUTH_COOKIE_PREFIX}.session_data` ||
|
|
193
|
-
BETTER_AUTH_SESSION_COOKIE_RE.test(bareName));
|
|
194
|
-
}
|
|
195
|
-
const PRIVATE_NO_STORE = "private, no-store";
|
|
196
132
|
function isSsrHtmlOrDataResponse(headers, status, pathname) {
|
|
197
133
|
if (status < 200 || status >= 400)
|
|
198
134
|
return false;
|
|
@@ -202,47 +138,36 @@ function isSsrHtmlOrDataResponse(headers, status, pathname) {
|
|
|
202
138
|
return pathname.endsWith(".data") && contentType.includes("text/x-script");
|
|
203
139
|
}
|
|
204
140
|
/**
|
|
205
|
-
* Apply the
|
|
206
|
-
*
|
|
207
|
-
* Anonymous requests (no auth signal on the incoming request) get the public
|
|
208
|
-
* stale-while-revalidate default so the CDN can serve shared app-shell HTML
|
|
209
|
-
* and React Router loader data to every unauthenticated visitor without
|
|
210
|
-
* hammering origin.
|
|
211
|
-
*
|
|
212
|
-
* Authenticated requests must never be publicly CDN-cached: the loader may
|
|
213
|
-
* have embedded session-personalized data. If the route already returned a
|
|
214
|
-
* Cache-Control header we respect it; otherwise we fall back to
|
|
215
|
-
* `private, no-store` so the browser re-fetches but no shared cache stores
|
|
216
|
-
* the response.
|
|
141
|
+
* Apply the SSR cache policy to the response headers.
|
|
217
142
|
*
|
|
218
|
-
*
|
|
219
|
-
*
|
|
220
|
-
*
|
|
143
|
+
* ┌──────────────────────────────────────────────────────────────────────────┐
|
|
144
|
+
* │ SSR IS A PUBLIC, HARD-CDN-CACHED SHELL — SERVED IDENTICALLY TO EVERYONE. │
|
|
145
|
+
* │ │
|
|
146
|
+
* │ Every SSR HTML / React Router `.data` response gets the same public │
|
|
147
|
+
* │ stale-while-revalidate policy for ALL visitors, authenticated or not, so │
|
|
148
|
+
* │ the edge serves one shared copy and never stampedes origin. │
|
|
149
|
+
* │ │
|
|
150
|
+
* │ DO NOT reintroduce per-user / cookie-based cache variation here (no │
|
|
151
|
+
* │ `private`, no `no-store`, no `Vary: Cookie`, no "authenticated → don't │
|
|
152
|
+
* │ cache" branch). That makes pages uncacheable for every logged-in visitor, │
|
|
153
|
+
* │ which is slow and expensive — exactly the regression this guardrail │
|
|
154
|
+
* │ prevents. The reason it is SAFE to hard-cache is that the SSR response is │
|
|
155
|
+
* │ impersonal: `createH3SSRHandler` renders without reading the request's │
|
|
156
|
+
* │ session/cookies, so there is no per-user data baked into the HTML. ALL │
|
|
157
|
+
* │ per-user state (who's logged in, private records, access checks) is │
|
|
158
|
+
* │ resolved CLIENT-SIDE after load. Keep it that way: if you need the SSR │
|
|
159
|
+
* │ output to differ per user, the fix is to move that work client-side, not │
|
|
160
|
+
* │ to disable caching here. │
|
|
161
|
+
* └──────────────────────────────────────────────────────────────────────────┘
|
|
221
162
|
*/
|
|
222
|
-
function applyDefaultSsrCacheHeader(headers, status, pathname
|
|
163
|
+
function applyDefaultSsrCacheHeader(headers, status, pathname) {
|
|
223
164
|
if (!isSsrHtmlOrDataResponse(headers, status, pathname))
|
|
224
165
|
return;
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
// potentially personalized response.
|
|
231
|
-
const existingCc = headers.get("cache-control") ?? "";
|
|
232
|
-
if (!existingCc.includes("public")) {
|
|
233
|
-
headers.set("cache-control", PRIVATE_NO_STORE);
|
|
234
|
-
}
|
|
235
|
-
// Never propagate CDN-specific cache headers on authenticated responses,
|
|
236
|
-
// regardless of what the route set.
|
|
237
|
-
headers.delete("cdn-cache-control");
|
|
238
|
-
headers.delete("netlify-cdn-cache-control");
|
|
239
|
-
return;
|
|
240
|
-
}
|
|
241
|
-
// Netlify Functions/proxies are not cached by default, and production docs
|
|
242
|
-
// requests often carry stale auth/doc cookies. Keep all three cache headers:
|
|
243
|
-
// Cache-Control for browsers, CDN-Cache-Control for generic CDNs, and
|
|
244
|
-
// Netlify-CDN-Cache-Control (with durable) so Netlify's shared cache actually
|
|
245
|
-
// serves SSR HTML/.data instead of forwarding every request to origin.
|
|
166
|
+
// Netlify Functions/proxies are not cached by default. Set all three cache
|
|
167
|
+
// headers: Cache-Control for browsers, CDN-Cache-Control for generic CDNs,
|
|
168
|
+
// and Netlify-CDN-Cache-Control (with durable) so Netlify's shared cache
|
|
169
|
+
// actually serves SSR HTML/.data from the edge instead of forwarding every
|
|
170
|
+
// request to origin — for every visitor, authenticated or not.
|
|
246
171
|
for (const [name, value] of Object.entries(DEFAULT_SSR_CACHE_HEADERS)) {
|
|
247
172
|
headers.set(name, value);
|
|
248
173
|
}
|
|
@@ -346,10 +271,10 @@ function isFrameworkOrAssetPath(pathname) {
|
|
|
346
271
|
pathname === "/favicon.png" ||
|
|
347
272
|
(/\.\w+$/.test(pathname) && !pathname.endsWith(".data")));
|
|
348
273
|
}
|
|
349
|
-
async function rewriteMountedResponse(response, basePath, pathname, requestUrl
|
|
274
|
+
async function rewriteMountedResponse(response, basePath, pathname, requestUrl) {
|
|
350
275
|
const sentryClientConfigScript = getSentryClientConfigScript();
|
|
351
276
|
const headers = new Headers(response.headers);
|
|
352
|
-
applyDefaultSsrCacheHeader(headers, response.status, pathname
|
|
277
|
+
applyDefaultSsrCacheHeader(headers, response.status, pathname);
|
|
353
278
|
applyDefaultSpeculationRulesHeader(headers, response.status, basePath);
|
|
354
279
|
const location = headers.get("location");
|
|
355
280
|
if (location?.startsWith("/") && !location.startsWith("//")) {
|
|
@@ -386,31 +311,18 @@ export function createH3SSRHandler(getBuild) {
|
|
|
386
311
|
}
|
|
387
312
|
try {
|
|
388
313
|
const request = requestWithPathname(event.req, p, basePath);
|
|
389
|
-
//
|
|
390
|
-
//
|
|
391
|
-
//
|
|
392
|
-
//
|
|
393
|
-
//
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
// Auth lookup failures must not break SSR; treat as unauthenticated.
|
|
402
|
-
}
|
|
403
|
-
}
|
|
404
|
-
// readOrgIdForEvent fast-paths when session.orgId is already backfilled
|
|
405
|
-
// (the common case), avoiding a duplicate org_members query. A second
|
|
406
|
-
// query only fires for authenticated users whose session has no orgId.
|
|
407
|
-
const orgId = session?.email
|
|
408
|
-
? await readOrgIdForEvent(event, session)
|
|
409
|
-
: undefined;
|
|
410
|
-
const ctx = {
|
|
411
|
-
userEmail: session?.email ?? undefined,
|
|
412
|
-
orgId,
|
|
413
|
-
};
|
|
314
|
+
// SSR renders an IMPERSONAL public shell — we deliberately do NOT read the
|
|
315
|
+
// request's session/cookies here, and pin an explicitly anonymous request
|
|
316
|
+
// context. That keeps the SSR HTML/.data identical for every visitor so it
|
|
317
|
+
// can be hard-cached at the CDN for everyone (see applyDefaultSsrCacheHeader).
|
|
318
|
+
//
|
|
319
|
+
// Consequence: SSR loaders that call `getRequestUserEmail()` / `accessFilter()`
|
|
320
|
+
// always see the unauthenticated branch and render public content only. Any
|
|
321
|
+
// per-user view (private records, share-grant access, who's logged in) MUST
|
|
322
|
+
// be resolved CLIENT-SIDE after load, never baked into SSR. Do not re-pin the
|
|
323
|
+
// session here to "fix" a per-user page — that silently makes the page
|
|
324
|
+
// uncacheable and/or leaks one user's data into another's cached copy.
|
|
325
|
+
const ctx = { userEmail: undefined, orgId: undefined };
|
|
414
326
|
if (request.method === "HEAD") {
|
|
415
327
|
const getRequest = new Request(request.url, {
|
|
416
328
|
method: "GET",
|
|
@@ -422,9 +334,9 @@ export function createH3SSRHandler(getBuild) {
|
|
|
422
334
|
status: response.status,
|
|
423
335
|
statusText: response.statusText,
|
|
424
336
|
headers: response.headers,
|
|
425
|
-
}), basePath, p, request.url
|
|
337
|
+
}), basePath, p, request.url);
|
|
426
338
|
}
|
|
427
|
-
return await rewriteMountedResponse(await runWithRequestContext(ctx, () => handler(request)), basePath, p, request.url
|
|
339
|
+
return await rewriteMountedResponse(await runWithRequestContext(ctx, () => handler(request)), basePath, p, request.url);
|
|
428
340
|
}
|
|
429
341
|
catch (err) {
|
|
430
342
|
// Log the full stack server-side, but never leak it to the client.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ssr-handler.js","sourceRoot":"","sources":["../../src/server/ssr-handler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,EAAE,kBAAkB,EAAgB,MAAM,IAAI,CAAC;AACtD,OAAO,EAAE,2BAA2B,EAAE,MAAM,oBAAoB,CAAC;AACjE,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EACL,yBAAyB,EACzB,gBAAgB,IAAI,yBAAyB,GAC9C,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,yBAAyB,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAC/E,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,yBAAyB,EAAE,MAAM,oBAAoB,CAAC;AAC/D,OAAO,EACL,oBAAoB,EACpB,uBAAuB,GACxB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,6BAA6B,EAC7B,gCAAgC,EAChC,8BAA8B,EAC9B,8BAA8B,EAC9B,+BAA+B,GAChC,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,yBAAyB,EACzB,8BAA8B,GAC/B,MAAM,4BAA4B,CAAC;AAEpC,OAAO,EACL,yBAAyB,EACzB,gCAAgC,EAChC,yBAAyB,GAC1B,MAAM,4BAA4B,CAAC;AACpC,MAAM,8BAA8B,GAAG,IAAI,GAAG,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC;AACpE,MAAM,6BAA6B,GAAG,2BAA2B,CAAC;AAElE;;;;;;;;GAQG;AACH,KAAK,UAAU,iBAAiB,CAC9B,KAAc,EACd,OAA+C;IAE/C,wEAAwE;IACxE,MAAM,YAAY,GAChB,OAAO,OAAO,EAAE,KAAK,KAAK,QAAQ,IAAI,OAAO,CAAC,KAAK,CAAC,IAAI,EAAE;QACxD,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,EAAE;QACtB,CAAC,CAAC,SAAS,CAAC;IAChB,IAAI,YAAY;QAAE,OAAO,YAAY,CAAC;IAEtC,4DAA4D;IAC5D,sEAAsE;IACtE,gEAAgE;IAChE,IAAI,CAAC;QACH,MAAM,EAAE,aAAa,EAAE,GAAG,MAAM,MAAM,CAAC,mBAAmB,CAAC,CAAC;QAC5D,MAAM,GAAG,GAAG,MAAM,aAAa,CAAC,KAAK,CAAC,CAAC;QACvC,OAAO,GAAG,EAAE,KAAK,IAAI,SAAS,CAAC;IACjC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED,SAAS,cAAc;IACrB,OAAO,yBAAyB,EAAE,CAAC;AACrC,CAAC;AAED,SAAS,gBAAgB,CAAC,QAAgB;IACxC,OAAO,yBAAyB,CAAC,QAAQ,EAAE,cAAc,EAAE,CAAC,CAAC;AAC/D,CAAC;AAED,SAAS,aAAa,CAAC,QAAgB,EAAE,QAAgB;IACvD,IAAI,CAAC,QAAQ;QAAE,OAAO,QAAQ,CAAC;IAC/B,IAAI,QAAQ,KAAK,QAAQ;QAAE,OAAO,GAAG,CAAC;IACtC,IAAI,QAAQ,CAAC,UAAU,CAAC,GAAG,QAAQ,GAAG,CAAC,EAAE,CAAC;QACxC,OAAO,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,GAAG,CAAC;IAChD,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,SAAS,mBAAmB,CAC1B,OAAgB,EAChB,QAAgB,EAChB,QAAgB;IAEhB,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACjC,IAAI,OAAO,GAAG,KAAK,CAAC;IACpB,IAAI,QAAQ,IAAI,QAAQ,KAAK,aAAa,EAAE,CAAC;QAC3C,MAAM,KAAK,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAC5C,IAAI,KAAK,EAAE,CAAC;YACV,MAAM,aAAa,GAAG,KAAK;iBACxB,KAAK,CAAC,GAAG,CAAC;iBACV,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,aAAa,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;iBAC5C,IAAI,CAAC,GAAG,CAAC,CAAC;YACb,IAAI,aAAa,KAAK,KAAK,EAAE,CAAC;gBAC5B,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC;gBAC7C,OAAO,GAAG,IAAI,CAAC;YACjB,CAAC;QACH,CAAC;IACH,CAAC;IACD,IAAI,GAAG,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAC9B,GAAG,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACxB,OAAO,GAAG,IAAI,CAAC;IACjB,CAAC;IACD,IAAI,CAAC,OAAO;QAAE,OAAO,OAAO,CAAC;IAC7B,MAAM,IAAI,GAAsC;QAC9C,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,MAAM,EAAE,OAAO,CAAC,MAAM;KACvB,CAAC;IACF,IAAI,OAAO,CAAC,IAAI,IAAI,CAAC,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,EAAE,CAAC;QAC5E,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;QACzB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;IACD,OAAO,IAAI,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;AAChC,CAAC;AAED,SAAS,iBAAiB,CAAC,IAAY,EAAE,QAAgB;IACvD,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IAC7E,IAAI,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,QAAQ,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IACtE,OAAO,GAAG,QAAQ,GAAG,IAAI,EAAE,CAAC;AAC9B,CAAC;AAED,SAAS,iBAAiB,CAAC,IAAY,EAAE,QAAgB;IACvD,IAAI,CAAC,QAAQ;QAAE,OAAO,IAAI,CAAC;IAC3B,OAAO,IAAI;SACR,OAAO,CACN,iEAAiE,EACjE,CAAC,MAAM,EAAE,IAAY,EAAE,KAAa,EAAE,IAAY,EAAE,EAAE,CACpD,GAAG,IAAI,IAAI,KAAK,GAAG,iBAAiB,CAAC,IAAI,EAAE,QAAQ,CAAC,GAAG,KAAK,EAAE,CACjE;SACA,OAAO,CAAC,qCAAqC,EAAE,CAAC,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;QACtE,MAAM,CAAC,GAAG,KAAK,IAAI,EAAE,CAAC;QACtB,OAAO,OAAO,CAAC,GAAG,iBAAiB,CAAC,IAAI,EAAE,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC;IAC7D,CAAC,CAAC,CAAC;AACP,CAAC;AAED,SAAS,gBAAgB,CAAC,IAAY,EAAE,MAAqB;IAC3D,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IACzB,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAC7C,IAAI,YAAY,KAAK,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IACrC,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,YAAY,CAAC,GAAG,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;AACzE,CAAC;AAED,MAAM,gBAAgB,GAAG,oDAAoD,CAAC;AAC9E,MAAM,oBAAoB,GACxB,oDAAoD,CAAC;AACvD,MAAM,qBAAqB,GACzB,qDAAqD,CAAC;AAExD,SAAS,qBAAqB,CAAC,UAAkB,EAAE,QAAgB;IACjE,OAAO,IAAI,GAAG,CACZ,iBAAiB,CAAC,8BAA8B,EAAE,QAAQ,CAAC,EAC3D,UAAU,CACX,CAAC,QAAQ,EAAE,CAAC;AACf,CAAC;AAED,SAAS,4BAA4B,CAAC,IAAY,EAAE,QAAgB;IAClE,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAC7C,IAAI,YAAY,KAAK,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IAErC,MAAM,iBAAiB,GACrB,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAClE,MAAM,IAAI,GAAa,EAAE,CAAC;IAE1B,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACvB,IAAI,CAAC,IAAI,CAAC,sCAAsC,QAAQ,IAAI,CAAC,CAAC;QAC9D,IAAI,CAAC,IAAI,CAAC,iDAAiD,QAAQ,IAAI,CAAC,CAAC;QACzE,IAAI,CAAC,IAAI,CACP,2CAA2C,8BAA8B,IAAI,CAC9E,CAAC;QACF,IAAI,CAAC,IAAI,CACP,4CAA4C,+BAA+B,IAAI,CAChF,CAAC;QACF,IAAI,CAAC,IAAI,CACP,6CAA6C,gCAAgC,IAAI,CAClF,CAAC;QACF,IAAI,CAAC,IAAI,CACP,0CAA0C,6BAA6B,IAAI,CAC5E,CAAC;IACJ,CAAC;IACD,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACrC,IAAI,CAAC,IAAI,CAAC,0DAA0D,CAAC,CAAC;IACxE,CAAC;IACD,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACvB,IAAI,CAAC,IAAI,CAAC,uCAAuC,QAAQ,IAAI,CAAC,CAAC;QAC/D,IAAI,CAAC,IAAI,CACP,2CAA2C,6BAA6B,IAAI,CAC7E,CAAC;IACJ,CAAC;IAED,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACnC,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,YAAY,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;AAChF,CAAC;AAED,SAAS,oBAAoB,CAAC,KAAc;IAC1C,MAAM,OAAO,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC;IAClC,OAAO,OAAO,CACZ,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC;QAC5B,6BAA6B,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACpD,KAAK,CAAC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,uBAAuB,CAAC;QACnD,KAAK,CAAC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,UAAU,CAAC;QACtC,yBAAyB,CAAC,KAAK,CAAC,CACjC,CAAC;AACJ,CAAC;AAED,SAAS,6BAA6B,CAAC,YAA2B;IAChE,IAAI,CAAC,YAAY;QAAE,OAAO,KAAK,CAAC;IAChC,OAAO,YAAY;SAChB,KAAK,CAAC,GAAG,CAAC;SACV,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC;SACvD,MAAM,CAAC,CAAC,IAAI,EAAkB,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;SAC/C,IAAI,CAAC,yBAAyB,CAAC,CAAC;AACrC,CAAC;AAED,SAAS,yBAAyB,CAAC,IAAY;IAC7C,IAAI,8BAA8B,CAAC,GAAG,CAAC,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IAC3D,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,qBAAqB,EAAE,EAAE,CAAC,CAAC;IACzD,OAAO,CACL,QAAQ,KAAK,WAAW;QACxB,QAAQ,KAAK,oBAAoB;QACjC,QAAQ,KAAK,YAAY;QACzB,QAAQ,KAAK,sBAAsB;QACnC,QAAQ,CAAC,UAAU,CAAC,aAAa,CAAC;QAClC,QAAQ,KAAK,GAAG,yBAAyB,gBAAgB;QACzD,QAAQ,KAAK,GAAG,yBAAyB,eAAe;QACxD,6BAA6B,CAAC,IAAI,CAAC,QAAQ,CAAC,CAC7C,CAAC;AACJ,CAAC;AAED,MAAM,gBAAgB,GAAG,mBAAmB,CAAC;AAE7C,SAAS,uBAAuB,CAC9B,OAAgB,EAChB,MAAc,EACd,QAAgB;IAEhB,IAAI,MAAM,GAAG,GAAG,IAAI,MAAM,IAAI,GAAG;QAAE,OAAO,KAAK,CAAC;IAChD,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC;IACrE,IAAI,WAAW,CAAC,QAAQ,CAAC,WAAW,CAAC;QAAE,OAAO,IAAI,CAAC;IACnD,OAAO,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,WAAW,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAC;AAC7E,CAAC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,SAAS,0BAA0B,CACjC,OAAgB,EAChB,MAAc,EACd,QAAgB,EAChB,aAAsB;IAEtB,IAAI,CAAC,uBAAuB,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC;QAAE,OAAO;IAEhE,IAAI,aAAa,EAAE,CAAC;QAClB,2EAA2E;QAC3E,+EAA+E;QAC/E,8EAA8E;QAC9E,sEAAsE;QACtE,qCAAqC;QACrC,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,IAAI,EAAE,CAAC;QACtD,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;YACnC,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,gBAAgB,CAAC,CAAC;QACjD,CAAC;QACD,yEAAyE;QACzE,oCAAoC;QACpC,OAAO,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC;QACpC,OAAO,CAAC,MAAM,CAAC,2BAA2B,CAAC,CAAC;QAC5C,OAAO;IACT,CAAC;IAED,2EAA2E;IAC3E,6EAA6E;IAC7E,sEAAsE;IACtE,8EAA8E;IAC9E,uEAAuE;IACvE,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,yBAAyB,CAAC,EAAE,CAAC;QACtE,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAC3B,CAAC;AACH,CAAC;AAED,SAAS,kCAAkC,CACzC,OAAgB,EAChB,MAAc,EACd,QAAgB;IAEhB,IAAI,MAAM,GAAG,GAAG,IAAI,MAAM,IAAI,GAAG;QAAE,OAAO;IAC1C,IAAI,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC;QAAE,OAAO;IAE7C,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC;IACrE,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,WAAW,CAAC;QAAE,OAAO;IAE/C,2EAA2E;IAC3E,4EAA4E;IAC5E,0EAA0E;IAC1E,6EAA6E;IAC7E,6EAA6E;IAC7E,4EAA4E;IAC5E,sBAAsB;IACtB,MAAM,SAAS,GAAG,iBAAiB,CAAC,8BAA8B,EAAE,QAAQ,CAAC,CAAC;IAC9E,OAAO,CAAC,GAAG,CAAC,mBAAmB,EAAE,IAAI,SAAS,GAAG,CAAC,CAAC;AACrD,CAAC;AAED;;;;;;GAMG;AACH,SAAS,iBAAiB,CAAC,SAAwB;IACjD,IAAI,CAAC,SAAS;QAAE,OAAO,IAAI,CAAC;IAC5B,MAAM,KAAK,GAAG,SAAS,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACzC,MAAM,GAAG,GAAG,SAAS,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC;IAC/C,IAAI,KAAK,IAAI,CAAC,IAAI,GAAG,GAAG,KAAK;QAAE,OAAO,IAAI,CAAC;IAC3C,OAAO,SAAS,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;AACrC,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,SAAS,gBAAgB,CAAC,OAAgB,EAAE,YAA2B;IACrE,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY;QAAE,OAAO;IAClD,IAAI,OAAO,CAAC,GAAG,CAAC,4BAA4B,KAAK,GAAG;QAAE,OAAO;IAE7D,0EAA0E;IAC1E,yEAAyE;IACzE,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC,IAAI,EAAE,CAAC;IAC9D,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,CAAC,GAAG,CACT,yBAAyB,EACzB,oCAAoC,CACrC,CAAC;IACJ,CAAC;IAED,6EAA6E;IAC7E,uEAAuE;IACvE,yEAAyE;IACzE,wEAAwE;IACxE,MAAM,UAAU,GAAG,iBAAiB,CAAC,YAAY,CAAC,CAAC;IACnD,MAAM,UAAU,GAAG,UAAU,CAAC,CAAC,CAAC,uBAAuB,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC3E,MAAM,eAAe,GAAG,CAAC,QAAQ,EAAE,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACxE,MAAM,SAAS,GAAG,cAAc,eAAe,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;IAE5D,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,qCAAqC,CAAC,IAAI,EAAE,CAAC;IAC5E,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,OAAO,CAAC,GAAG,CAAC,qCAAqC,EAAE,SAAS,CAAC,CAAC;IAChE,CAAC;AACH,CAAC;AAED,SAAS,sBAAsB,CAAC,QAAgB;IAC9C,OAAO,CACL,QAAQ,CAAC,UAAU,CAAC,eAAe,CAAC;QACpC,QAAQ,CAAC,UAAU,CAAC,iBAAiB,CAAC;QACtC,QAAQ,CAAC,UAAU,CAAC,iBAAiB,CAAC;QACtC,QAAQ,CAAC,UAAU,CAAC,OAAO,CAAC;QAC5B,QAAQ,CAAC,UAAU,CAAC,SAAS,CAAC;QAC9B,QAAQ,CAAC,UAAU,CAAC,OAAO,CAAC;QAC5B,QAAQ,CAAC,UAAU,CAAC,OAAO,CAAC;QAC5B,QAAQ,KAAK,iBAAiB;QAC9B,QAAQ,KAAK,cAAc;QAC3B,QAAQ,KAAK,mBAAmB;QAChC,QAAQ,KAAK,cAAc;QAC3B,QAAQ,KAAK,cAAc;QAC3B,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CACzD,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,sBAAsB,CACnC,QAAkB,EAClB,QAAgB,EAChB,QAAgB,EAChB,UAAkB,EAClB,aAAsB;IAEtB,MAAM,wBAAwB,GAAG,2BAA2B,EAAE,CAAC;IAC/D,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IAC9C,0BAA0B,CAAC,OAAO,EAAE,QAAQ,CAAC,MAAM,EAAE,QAAQ,EAAE,aAAa,CAAC,CAAC;IAC9E,kCAAkC,CAAC,OAAO,EAAE,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAEvE,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IACzC,IAAI,QAAQ,EAAE,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QAC5D,OAAO,CAAC,GAAG,CAAC,UAAU,EAAE,iBAAiB,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC;IACjE,CAAC;IAED,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC;IACtD,IAAI,CAAC,WAAW,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;QACvE,OAAO,IAAI,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE;YACjC,MAAM,EAAE,QAAQ,CAAC,MAAM;YACvB,UAAU,EAAE,QAAQ,CAAC,UAAU;YAC/B,OAAO;SACR,CAAC,CAAC;IACL,CAAC;IAED,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;IACnC,OAAO,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC;IACjC,gBAAgB,CAAC,OAAO,EAAE,wBAAwB,CAAC,CAAC;IACpD,OAAO,IAAI,QAAQ,CACjB,gBAAgB,CACd,4BAA4B,CAC1B,iBAAiB,CAAC,IAAI,EAAE,QAAQ,CAAC,EACjC,qBAAqB,CAAC,UAAU,EAAE,QAAQ,CAAC,CAC5C,EACD,wBAAwB,CACzB,EACD;QACE,MAAM,EAAE,QAAQ,CAAC,MAAM;QACvB,UAAU,EAAE,QAAQ,CAAC,UAAU;QAC/B,OAAO;KACR,CACF,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,QAA0C;IAC3E,MAAM,OAAO,GAAG,oBAAoB,CAAC,QAAe,CAAC,CAAC;IACtD,OAAO,kBAAkB,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;QACxC,MAAM,QAAQ,GAAG,cAAc,EAAE,CAAC;QAClC,MAAM,CAAC,GAAG,gBAAgB,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC/C,IAAI,sBAAsB,CAAC,CAAC,CAAC,EAAE,CAAC;YAC9B,OAAO,IAAI,QAAQ,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;QAC7C,CAAC;QACD,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,mBAAmB,CAAC,KAAK,CAAC,GAAc,EAAE,CAAC,EAAE,QAAQ,CAAC,CAAC;YACvE,wEAAwE;YACxE,uEAAuE;YACvE,gEAAgE;YAChE,uEAAuE;YACvE,+DAA+D;YAC/D,IAAI,OAAO,GAAkD,IAAI,CAAC;YAClE,MAAM,aAAa,GAAG,oBAAoB,CAAC,KAAK,CAAC,CAAC;YAClD,IAAI,aAAa,EAAE,CAAC;gBAClB,IAAI,CAAC;oBACH,OAAO,GAAG,MAAM,UAAU,CAAC,KAAK,CAAC,CAAC;gBACpC,CAAC;gBAAC,MAAM,CAAC;oBACP,qEAAqE;gBACvE,CAAC;YACH,CAAC;YACD,wEAAwE;YACxE,sEAAsE;YACtE,uEAAuE;YACvE,MAAM,KAAK,GAAG,OAAO,EAAE,KAAK;gBAC1B,CAAC,CAAC,MAAM,iBAAiB,CAAC,KAAK,EAAE,OAAO,CAAC;gBACzC,CAAC,CAAC,SAAS,CAAC;YACd,MAAM,GAAG,GAAG;gBACV,SAAS,EAAE,OAAO,EAAE,KAAK,IAAI,SAAS;gBACtC,KAAK;aACN,CAAC;YACF,IAAI,OAAO,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;gBAC9B,MAAM,UAAU,GAAG,IAAI,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE;oBAC1C,MAAM,EAAE,KAAK;oBACb,OAAO,EAAE,OAAO,CAAC,OAAO;oBACxB,MAAM,EAAE,OAAO,CAAC,MAAM;iBACvB,CAAC,CAAC;gBACH,MAAM,QAAQ,GAAG,MAAM,qBAAqB,CAAC,GAAG,EAAE,GAAG,EAAE,CACrD,OAAO,CAAC,UAAU,CAAC,CACpB,CAAC;gBACF,OAAO,MAAM,sBAAsB,CACjC,IAAI,QAAQ,CAAC,IAAI,EAAE;oBACjB,MAAM,EAAE,QAAQ,CAAC,MAAM;oBACvB,UAAU,EAAE,QAAQ,CAAC,UAAU;oBAC/B,OAAO,EAAE,QAAQ,CAAC,OAAO;iBAC1B,CAAC,EACF,QAAQ,EACR,CAAC,EACD,OAAO,CAAC,GAAG,EACX,aAAa,CACd,CAAC;YACJ,CAAC;YACD,OAAO,MAAM,sBAAsB,CACjC,MAAM,qBAAqB,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,EACxD,QAAQ,EACR,CAAC,EACD,OAAO,CAAC,GAAG,EACX,aAAa,CACd,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,mEAAmE;YACnE,uEAAuE;YACvE,sEAAsE;YACtE,oEAAoE;YACpE,OAAO,CAAC,KAAK,CAAC,0BAA0B,EAAE,GAAG,CAAC,CAAC;YAC/C,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,CAAC;YACrD,MAAM,IAAI,GAAG,MAAM;gBACjB,CAAC,CAAC,uBAAuB;gBACzB,CAAC,CAAC,0BAA2B,GAAa,EAAE,OAAO,IAAI,GAAG,EAAE,CAAC;YAC/D,OAAO,IAAI,QAAQ,CAAC,IAAI,EAAE;gBACxB,MAAM,EAAE,GAAG;gBACX,OAAO,EAAE,EAAE,cAAc,EAAE,YAAY,EAAE;aAC1C,CAAC,CAAC;QACL,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC","sourcesContent":["/**\n * Shared SSR catch-all handler for React Router framework mode.\n *\n * Templates wire this up via:\n *\n * // server/routes/[...page].get.ts\n * import { createH3SSRHandler } from \"@agent-native/core/server/ssr-handler\";\n * export default createH3SSRHandler(\n * () => import(\"virtual:react-router/server-build\"),\n * );\n *\n * The `getBuild` callback MUST live in the template's own source so Vite's\n * @react-router/dev plugin can resolve the `virtual:` module. Pulling the\n * import into core (e.g. via a re-export) puts it in node_modules where\n * Vite's SSR externalizer leaves it untouched and Node's ESM loader rejects\n * the unknown scheme — silently 302'ing every request to \"/\".\n */\nimport { createRequestHandler } from \"react-router\";\nimport { defineEventHandler, type H3Event } from \"h3\";\nimport { getSentryClientConfigScript } from \"./sentry-config.js\";\nimport { computeInlineScriptHash } from \"./security-headers.js\";\nimport {\n getAppBasePathFromViteEnv,\n stripAppBasePath as canonicalStripAppBasePath,\n} from \"./app-base-path.js\";\nimport { BETTER_AUTH_COOKIE_PREFIX, COOKIE_NAME, getSession } from \"./auth.js\";\nimport { runWithRequestContext } from \"./request-context.js\";\nimport { requestHasEmbedAuthMarker } from \"./embed-session.js\";\nimport {\n EMBED_SESSION_COOKIE,\n EMBED_TOKEN_QUERY_PARAM,\n} from \"../shared/embed-auth.js\";\nimport {\n AGENT_NATIVE_SOCIAL_IMAGE_ALT,\n AGENT_NATIVE_SOCIAL_IMAGE_HEIGHT,\n AGENT_NATIVE_SOCIAL_IMAGE_PATH,\n AGENT_NATIVE_SOCIAL_IMAGE_TYPE,\n AGENT_NATIVE_SOCIAL_IMAGE_WIDTH,\n} from \"../shared/social-meta.js\";\nimport {\n DEFAULT_SSR_CACHE_HEADERS,\n DEFAULT_SPECULATION_RULES_PATH,\n} from \"../shared/cache-control.js\";\n\nexport {\n DEFAULT_SSR_CACHE_HEADERS,\n DEFAULT_SPECULATION_RULES_HEADER,\n DEFAULT_SSR_CACHE_CONTROL,\n} from \"../shared/cache-control.js\";\nconst ANONYMOUS_SESSION_COOKIE_NAMES = new Set([\"an_docs_session\"]);\nconst BETTER_AUTH_SESSION_COOKIE_RE = /\\.session_(?:token|data)$/;\n\n/**\n * Read the active org for a request without forcing every template to bundle\n * the org module. Mirrors what `core-routes-plugin` does for action handlers.\n *\n * Fast path: when the session already carries a valid orgId (backfilled by\n * backfillSessionOrg during getSession), return it directly — no additional\n * org_members round trip. Only when the session has no orgId do we fall\n * through to getOrgContext for the full membership lookup.\n */\nasync function readOrgIdForEvent(\n event: H3Event,\n session: Awaited<ReturnType<typeof getSession>>,\n): Promise<string | undefined> {\n // Reuse orgId already resolved by backfillSessionOrg inside getSession.\n const sessionOrgId =\n typeof session?.orgId === \"string\" && session.orgId.trim()\n ? session.orgId.trim()\n : undefined;\n if (sessionOrgId) return sessionOrgId;\n\n // No orgId on the session — full org_members lookup needed.\n // getOrgContext is per-event memoized, so this is at most one DB read\n // even if other request code calls getOrgContext independently.\n try {\n const { getOrgContext } = await import(\"../org/context.js\");\n const ctx = await getOrgContext(event);\n return ctx?.orgId ?? undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction getAppBasePath(): string {\n return getAppBasePathFromViteEnv();\n}\n\nfunction stripAppBasePath(pathname: string): string {\n return canonicalStripAppBasePath(pathname, getAppBasePath());\n}\n\nfunction stripBasePath(pathname: string, basePath: string): string {\n if (!basePath) return pathname;\n if (pathname === basePath) return \"/\";\n if (pathname.startsWith(`${basePath}/`)) {\n return pathname.slice(basePath.length) || \"/\";\n }\n return pathname;\n}\n\nfunction requestWithPathname(\n request: Request,\n pathname: string,\n basePath: string,\n): Request {\n const url = new URL(request.url);\n let changed = false;\n if (basePath && pathname === \"/__manifest\") {\n const paths = url.searchParams.get(\"paths\");\n if (paths) {\n const strippedPaths = paths\n .split(\",\")\n .map((path) => stripBasePath(path, basePath))\n .join(\",\");\n if (strippedPaths !== paths) {\n url.searchParams.set(\"paths\", strippedPaths);\n changed = true;\n }\n }\n }\n if (url.pathname !== pathname) {\n url.pathname = pathname;\n changed = true;\n }\n if (!changed) return request;\n const init: RequestInit & { duplex?: \"half\" } = {\n method: request.method,\n headers: request.headers,\n signal: request.signal,\n };\n if (request.body && ![\"GET\", \"HEAD\"].includes(request.method.toUpperCase())) {\n init.body = request.body;\n init.duplex = \"half\";\n }\n return new Request(url, init);\n}\n\nfunction prefixMountedPath(path: string, basePath: string): string {\n if (!basePath || !path.startsWith(\"/\") || path.startsWith(\"//\")) return path;\n if (path === basePath || path.startsWith(`${basePath}/`)) return path;\n return `${basePath}${path}`;\n}\n\nfunction prefixMountedHtml(html: string, basePath: string): string {\n if (!basePath) return html;\n return html\n .replace(\n /\\b(href|src|action|formaction|poster)=([\"'])(\\/(?!\\/)[^\"']*)\\2/g,\n (_match, attr: string, quote: string, path: string) =>\n `${attr}=${quote}${prefixMountedPath(path, basePath)}${quote}`,\n )\n .replace(/url\\(([\"']?)(\\/(?!\\/)[^)'\" ]+)\\1\\)/g, (_match, quote, path) => {\n const q = quote || \"\";\n return `url(${q}${prefixMountedPath(path, basePath)}${q})`;\n });\n}\n\nfunction injectHeadScript(html: string, script: string | null): string {\n if (!script) return html;\n const headCloseIdx = html.indexOf(\"</head>\");\n if (headCloseIdx === -1) return html;\n return html.slice(0, headCloseIdx) + script + html.slice(headCloseIdx);\n}\n\nconst OG_IMAGE_META_RE = /<meta\\b(?=[^>]*\\bproperty=([\"'])og:image\\1)[^>]*>/i;\nconst TWITTER_CARD_META_RE =\n /<meta\\b(?=[^>]*\\bname=([\"'])twitter:card\\1)[^>]*>/i;\nconst TWITTER_IMAGE_META_RE =\n /<meta\\b(?=[^>]*\\bname=([\"'])twitter:image\\1)[^>]*>/i;\n\nfunction defaultSocialImageUrl(requestUrl: string, basePath: string): string {\n return new URL(\n prefixMountedPath(AGENT_NATIVE_SOCIAL_IMAGE_PATH, basePath),\n requestUrl,\n ).toString();\n}\n\nfunction injectDefaultSocialImageMeta(html: string, imageUrl: string): string {\n const headCloseIdx = html.indexOf(\"</head>\");\n if (headCloseIdx === -1) return html;\n\n const hasAnySocialImage =\n OG_IMAGE_META_RE.test(html) || TWITTER_IMAGE_META_RE.test(html);\n const tags: string[] = [];\n\n if (!hasAnySocialImage) {\n tags.push(`<meta property=\"og:image\" content=\"${imageUrl}\">`);\n tags.push(`<meta property=\"og:image:secure_url\" content=\"${imageUrl}\">`);\n tags.push(\n `<meta property=\"og:image:type\" content=\"${AGENT_NATIVE_SOCIAL_IMAGE_TYPE}\">`,\n );\n tags.push(\n `<meta property=\"og:image:width\" content=\"${AGENT_NATIVE_SOCIAL_IMAGE_WIDTH}\">`,\n );\n tags.push(\n `<meta property=\"og:image:height\" content=\"${AGENT_NATIVE_SOCIAL_IMAGE_HEIGHT}\">`,\n );\n tags.push(\n `<meta property=\"og:image:alt\" content=\"${AGENT_NATIVE_SOCIAL_IMAGE_ALT}\">`,\n );\n }\n if (!TWITTER_CARD_META_RE.test(html)) {\n tags.push(`<meta name=\"twitter:card\" content=\"summary_large_image\">`);\n }\n if (!hasAnySocialImage) {\n tags.push(`<meta name=\"twitter:image\" content=\"${imageUrl}\">`);\n tags.push(\n `<meta name=\"twitter:image:alt\" content=\"${AGENT_NATIVE_SOCIAL_IMAGE_ALT}\">`,\n );\n }\n\n if (tags.length === 0) return html;\n return html.slice(0, headCloseIdx) + tags.join(\"\") + html.slice(headCloseIdx);\n}\n\nfunction requestHasAuthSignal(event: H3Event): boolean {\n const headers = event.req.headers;\n return Boolean(\n headers.get(\"authorization\") ||\n requestHasAuthenticatedCookie(headers.get(\"cookie\")) ||\n event.url.searchParams.has(EMBED_TOKEN_QUERY_PARAM) ||\n event.url.searchParams.has(\"_session\") ||\n requestHasEmbedAuthMarker(event),\n );\n}\n\nfunction requestHasAuthenticatedCookie(cookieHeader: string | null): boolean {\n if (!cookieHeader) return false;\n return cookieHeader\n .split(\";\")\n .map((cookie) => cookie.trim().split(\"=\", 1)[0]?.trim())\n .filter((name): name is string => Boolean(name))\n .some(isAuthenticatedCookieName);\n}\n\nfunction isAuthenticatedCookieName(name: string): boolean {\n if (ANONYMOUS_SESSION_COOKIE_NAMES.has(name)) return false;\n const bareName = name.replace(/^__(?:Secure|Host)-/, \"\");\n return (\n bareName === COOKIE_NAME ||\n bareName === EMBED_SESSION_COOKIE ||\n bareName === \"an_session\" ||\n bareName === \"an_session_workspace\" ||\n bareName.startsWith(\"an_session_\") ||\n bareName === `${BETTER_AUTH_COOKIE_PREFIX}.session_token` ||\n bareName === `${BETTER_AUTH_COOKIE_PREFIX}.session_data` ||\n BETTER_AUTH_SESSION_COOKIE_RE.test(bareName)\n );\n}\n\nconst PRIVATE_NO_STORE = \"private, no-store\";\n\nfunction isSsrHtmlOrDataResponse(\n headers: Headers,\n status: number,\n pathname: string,\n): boolean {\n if (status < 200 || status >= 400) return false;\n const contentType = headers.get(\"content-type\")?.toLowerCase() ?? \"\";\n if (contentType.includes(\"text/html\")) return true;\n return pathname.endsWith(\".data\") && contentType.includes(\"text/x-script\");\n}\n\n/**\n * Apply the correct SSR cache policy to the response headers.\n *\n * Anonymous requests (no auth signal on the incoming request) get the public\n * stale-while-revalidate default so the CDN can serve shared app-shell HTML\n * and React Router loader data to every unauthenticated visitor without\n * hammering origin.\n *\n * Authenticated requests must never be publicly CDN-cached: the loader may\n * have embedded session-personalized data. If the route already returned a\n * Cache-Control header we respect it; otherwise we fall back to\n * `private, no-store` so the browser re-fetches but no shared cache stores\n * the response.\n *\n * The distinction is on the *incoming* auth signal, not on whether the loader\n * actually used the session — that would require inspecting the response body.\n * Erring toward private for any credentialed request is the safe default.\n */\nfunction applyDefaultSsrCacheHeader(\n headers: Headers,\n status: number,\n pathname: string,\n hasAuthSignal: boolean,\n) {\n if (!isSsrHtmlOrDataResponse(headers, status, pathname)) return;\n\n if (hasAuthSignal) {\n // A route that explicitly opts into public caching (e.g. a share page that\n // accepts an optional auth cookie) can signal intent via a `public` directive.\n // Any other route-level or framework-default value (no-cache, private, unset)\n // is overridden with private/no-store so no shared CDN cache stores a\n // potentially personalized response.\n const existingCc = headers.get(\"cache-control\") ?? \"\";\n if (!existingCc.includes(\"public\")) {\n headers.set(\"cache-control\", PRIVATE_NO_STORE);\n }\n // Never propagate CDN-specific cache headers on authenticated responses,\n // regardless of what the route set.\n headers.delete(\"cdn-cache-control\");\n headers.delete(\"netlify-cdn-cache-control\");\n return;\n }\n\n // Netlify Functions/proxies are not cached by default, and production docs\n // requests often carry stale auth/doc cookies. Keep all three cache headers:\n // Cache-Control for browsers, CDN-Cache-Control for generic CDNs, and\n // Netlify-CDN-Cache-Control (with durable) so Netlify's shared cache actually\n // serves SSR HTML/.data instead of forwarding every request to origin.\n for (const [name, value] of Object.entries(DEFAULT_SSR_CACHE_HEADERS)) {\n headers.set(name, value);\n }\n}\n\nfunction applyDefaultSpeculationRulesHeader(\n headers: Headers,\n status: number,\n basePath: string,\n) {\n if (status < 200 || status >= 400) return;\n if (headers.has(\"speculation-rules\")) return;\n\n const contentType = headers.get(\"content-type\")?.toLowerCase() ?? \"\";\n if (!contentType.includes(\"text/html\")) return;\n\n // Cloudflare Speed Brain injects its own Speculation-Rules header when the\n // origin omits one. Those browser prefetches carry `Sec-Purpose: prefetch`,\n // and Cloudflare refuses cache-ineligible dynamic pages with a 503 before\n // the request can reach Netlify/origin. We publish an explicit no-op ruleset\n // by default so Cloudflare does not inject its edge prefetch rules. Preserve\n // an app-provided Speculation-Rules header above if a template deliberately\n // owns this behavior.\n const rulesPath = prefixMountedPath(DEFAULT_SPECULATION_RULES_PATH, basePath);\n headers.set(\"speculation-rules\", `\"${rulesPath}\"`);\n}\n\n/**\n * Extract the plain JS body from a `<script ...>body</script>` string.\n * Returns `null` if the input is falsy or has no recognisable `</script>` end.\n * Used to compute the sha256 hash of framework-injected inline scripts so the\n * hash can be listed in the `script-src` CSP directive without relying on\n * `'unsafe-inline'`.\n */\nfunction extractScriptBody(scriptTag: string | null): string | null {\n if (!scriptTag) return null;\n const start = scriptTag.indexOf(\">\") + 1;\n const end = scriptTag.lastIndexOf(\"</script>\");\n if (start <= 0 || end < start) return null;\n return scriptTag.slice(start, end);\n}\n\n/**\n * Apply a Content-Security-Policy header to HTML document responses.\n *\n * Two directives are always enforced in production:\n *\n * - `object-src 'none'` — disables Flash / Java / PDF plugin execution,\n * which are a reliable code-execution vector even in modern browsers.\n * - `base-uri 'self'` — prevents a `<base href=\"...\">` injection from\n * hijacking all relative URLs in the document (a common attack target when\n * user-controlled content reaches the HTML).\n *\n * A third directive, `script-src`, is emitted via `Content-Security-Policy-\n * Report-Only` rather than enforced. The framework injects one deterministic\n * inline script per process (the Sentry config block — its hash is computed\n * once at process startup from the resolved env vars). Templates additionally\n * render a theme-init inline script whose exact content varies by template\n * (default theme param, custom docs variant, etc.) and which is rendered by\n * React Router, not this handler, so its hash is not available here. Shipping\n * script-src as Report-Only surfaces violations without breaking template\n * customisations; teams can graduate to enforcement once their hashes are\n * enumerated.\n *\n * Skipped in development (`NODE_ENV !== 'production'`) so HMR eval and Vite\n * dev-server injects are never blocked. Set `AGENT_NATIVE_DISABLE_DOC_CSP=1`\n * to opt out in production for a template with exotic needs.\n */\nfunction applyDocumentCsp(headers: Headers, sentryScript: string | null): void {\n if (process.env.NODE_ENV !== \"production\") return;\n if (process.env.AGENT_NATIVE_DISABLE_DOC_CSP === \"1\") return;\n\n // object-src / base-uri: enforced; neither directive mentions scripts, so\n // they are safe even when a template's inline script hashes are unknown.\n const existing = headers.get(\"content-security-policy\") ?? \"\";\n if (!existing) {\n headers.set(\n \"content-security-policy\",\n \"object-src 'none'; base-uri 'self'\",\n );\n }\n\n // script-src as Report-Only: list 'self' plus the hash for the Sentry config\n // script the SSR handler injects into every HTML response (the hash is\n // computed once from the resolved env vars at process startup). Template\n // theme-init hashes are NOT included here — see function comment above.\n const sentryBody = extractScriptBody(sentryScript);\n const sentryHash = sentryBody ? computeInlineScriptHash(sentryBody) : null;\n const scriptSrcTokens = [\"'self'\", ...(sentryHash ? [sentryHash] : [])];\n const scriptSrc = `script-src ${scriptSrcTokens.join(\" \")}`;\n\n const existingRo = headers.get(\"content-security-policy-report-only\") ?? \"\";\n if (!existingRo) {\n headers.set(\"content-security-policy-report-only\", scriptSrc);\n }\n}\n\nfunction isFrameworkOrAssetPath(pathname: string): boolean {\n return (\n pathname.startsWith(\"/.well-known/\") ||\n pathname.startsWith(\"/_agent_native/\") ||\n pathname.startsWith(\"/_agent-native/\") ||\n pathname.startsWith(\"/api/\") ||\n pathname.startsWith(\"/@vite/\") ||\n pathname.startsWith(\"/@id/\") ||\n pathname.startsWith(\"/@fs/\") ||\n pathname === \"/@react-refresh\" ||\n pathname === \"/__vite_ping\" ||\n pathname === \"/__open-in-editor\" ||\n pathname === \"/favicon.ico\" ||\n pathname === \"/favicon.png\" ||\n (/\\.\\w+$/.test(pathname) && !pathname.endsWith(\".data\"))\n );\n}\n\nasync function rewriteMountedResponse(\n response: Response,\n basePath: string,\n pathname: string,\n requestUrl: string,\n hasAuthSignal: boolean,\n): Promise<Response> {\n const sentryClientConfigScript = getSentryClientConfigScript();\n const headers = new Headers(response.headers);\n applyDefaultSsrCacheHeader(headers, response.status, pathname, hasAuthSignal);\n applyDefaultSpeculationRulesHeader(headers, response.status, basePath);\n\n const location = headers.get(\"location\");\n if (location?.startsWith(\"/\") && !location.startsWith(\"//\")) {\n headers.set(\"location\", prefixMountedPath(location, basePath));\n }\n\n const contentType = headers.get(\"content-type\") ?? \"\";\n if (!contentType.toLowerCase().includes(\"text/html\") || !response.body) {\n return new Response(response.body, {\n status: response.status,\n statusText: response.statusText,\n headers,\n });\n }\n\n const html = await response.text();\n headers.delete(\"content-length\");\n applyDocumentCsp(headers, sentryClientConfigScript);\n return new Response(\n injectHeadScript(\n injectDefaultSocialImageMeta(\n prefixMountedHtml(html, basePath),\n defaultSocialImageUrl(requestUrl, basePath),\n ),\n sentryClientConfigScript,\n ),\n {\n status: response.status,\n statusText: response.statusText,\n headers,\n },\n );\n}\n\n/**\n * Create an h3 catch-all that hands page routes to React Router and\n * returns 404 for framework / asset paths that React Router doesn't own.\n */\nexport function createH3SSRHandler(getBuild: () => Promise<unknown> | unknown) {\n const handler = createRequestHandler(getBuild as any);\n return defineEventHandler(async (event) => {\n const basePath = getAppBasePath();\n const p = stripAppBasePath(event.url.pathname);\n if (isFrameworkOrAssetPath(p)) {\n return new Response(null, { status: 404 });\n }\n try {\n const request = requestWithPathname(event.req as Request, p, basePath);\n // Pin the active session onto the async request context so React Router\n // loaders that call `getRequestUserEmail()` / `accessFilter()` see the\n // signed-in user. Without this, SSR loaders fall through to the\n // unauthenticated branch even when the user is logged in — which broke\n // shared-deck \"Presentation link\" access for non-public decks.\n let session: Awaited<ReturnType<typeof getSession>> | null = null;\n const hasAuthSignal = requestHasAuthSignal(event);\n if (hasAuthSignal) {\n try {\n session = await getSession(event);\n } catch {\n // Auth lookup failures must not break SSR; treat as unauthenticated.\n }\n }\n // readOrgIdForEvent fast-paths when session.orgId is already backfilled\n // (the common case), avoiding a duplicate org_members query. A second\n // query only fires for authenticated users whose session has no orgId.\n const orgId = session?.email\n ? await readOrgIdForEvent(event, session)\n : undefined;\n const ctx = {\n userEmail: session?.email ?? undefined,\n orgId,\n };\n if (request.method === \"HEAD\") {\n const getRequest = new Request(request.url, {\n method: \"GET\",\n headers: request.headers,\n signal: request.signal,\n });\n const response = await runWithRequestContext(ctx, () =>\n handler(getRequest),\n );\n return await rewriteMountedResponse(\n new Response(null, {\n status: response.status,\n statusText: response.statusText,\n headers: response.headers,\n }),\n basePath,\n p,\n request.url,\n hasAuthSignal,\n );\n }\n return await rewriteMountedResponse(\n await runWithRequestContext(ctx, () => handler(request)),\n basePath,\n p,\n request.url,\n hasAuthSignal,\n );\n } catch (err) {\n // Log the full stack server-side, but never leak it to the client.\n // Stack traces expose file paths, library versions, and code structure\n // that aid reconnaissance attacks. In dev we surface the message text\n // so devtools shows something useful; in prod we return a bare 500.\n console.error(\"[ssr-handler] SSR error:\", err);\n const isProd = process.env.NODE_ENV === \"production\";\n const body = isProd\n ? \"Internal Server Error\"\n : `Internal Server Error: ${(err as Error)?.message ?? err}`;\n return new Response(body, {\n status: 500,\n headers: { \"content-type\": \"text/plain\" },\n });\n }\n });\n}\n"]}
|
|
1
|
+
{"version":3,"file":"ssr-handler.js","sourceRoot":"","sources":["../../src/server/ssr-handler.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Shared SSR catch-all handler for React Router framework mode.\n *\n * Templates wire this up via:\n *\n * // server/routes/[...page].get.ts\n * import { createH3SSRHandler } from \"@agent-native/core/server/ssr-handler\";\n * export default createH3SSRHandler(\n * () => import(\"virtual:react-router/server-build\"),\n * );\n *\n * The `getBuild` callback MUST live in the template's own source so Vite's\n * @react-router/dev plugin can resolve the `virtual:` module. Pulling the\n * import into core (e.g. via a re-export) puts it in node_modules where\n * Vite's SSR externalizer leaves it untouched and Node's ESM loader rejects\n * the unknown scheme — silently 302'ing every request to \"/\".\n */\nimport { createRequestHandler } from \"react-router\";\nimport { defineEventHandler } from \"h3\";\nimport { getSentryClientConfigScript } from \"./sentry-config.js\";\nimport { computeInlineScriptHash } from \"./security-headers.js\";\nimport {\n getAppBasePathFromViteEnv,\n stripAppBasePath as canonicalStripAppBasePath,\n} from \"./app-base-path.js\";\nimport { runWithRequestContext } from \"./request-context.js\";\nimport {\n AGENT_NATIVE_SOCIAL_IMAGE_ALT,\n AGENT_NATIVE_SOCIAL_IMAGE_HEIGHT,\n AGENT_NATIVE_SOCIAL_IMAGE_PATH,\n AGENT_NATIVE_SOCIAL_IMAGE_TYPE,\n AGENT_NATIVE_SOCIAL_IMAGE_WIDTH,\n} from \"../shared/social-meta.js\";\nimport {\n DEFAULT_SSR_CACHE_HEADERS,\n DEFAULT_SPECULATION_RULES_PATH,\n} from \"../shared/cache-control.js\";\n\nexport {\n DEFAULT_SSR_CACHE_HEADERS,\n DEFAULT_SPECULATION_RULES_HEADER,\n DEFAULT_SSR_CACHE_CONTROL,\n} from \"../shared/cache-control.js\";\n\nfunction getAppBasePath(): string {\n return getAppBasePathFromViteEnv();\n}\n\nfunction stripAppBasePath(pathname: string): string {\n return canonicalStripAppBasePath(pathname, getAppBasePath());\n}\n\nfunction stripBasePath(pathname: string, basePath: string): string {\n if (!basePath) return pathname;\n if (pathname === basePath) return \"/\";\n if (pathname.startsWith(`${basePath}/`)) {\n return pathname.slice(basePath.length) || \"/\";\n }\n return pathname;\n}\n\nfunction requestWithPathname(\n request: Request,\n pathname: string,\n basePath: string,\n): Request {\n const url = new URL(request.url);\n let changed = false;\n if (basePath && pathname === \"/__manifest\") {\n const paths = url.searchParams.get(\"paths\");\n if (paths) {\n const strippedPaths = paths\n .split(\",\")\n .map((path) => stripBasePath(path, basePath))\n .join(\",\");\n if (strippedPaths !== paths) {\n url.searchParams.set(\"paths\", strippedPaths);\n changed = true;\n }\n }\n }\n if (url.pathname !== pathname) {\n url.pathname = pathname;\n changed = true;\n }\n if (!changed) return request;\n const init: RequestInit & { duplex?: \"half\" } = {\n method: request.method,\n headers: request.headers,\n signal: request.signal,\n };\n if (request.body && ![\"GET\", \"HEAD\"].includes(request.method.toUpperCase())) {\n init.body = request.body;\n init.duplex = \"half\";\n }\n return new Request(url, init);\n}\n\nfunction prefixMountedPath(path: string, basePath: string): string {\n if (!basePath || !path.startsWith(\"/\") || path.startsWith(\"//\")) return path;\n if (path === basePath || path.startsWith(`${basePath}/`)) return path;\n return `${basePath}${path}`;\n}\n\nfunction prefixMountedHtml(html: string, basePath: string): string {\n if (!basePath) return html;\n return html\n .replace(\n /\\b(href|src|action|formaction|poster)=([\"'])(\\/(?!\\/)[^\"']*)\\2/g,\n (_match, attr: string, quote: string, path: string) =>\n `${attr}=${quote}${prefixMountedPath(path, basePath)}${quote}`,\n )\n .replace(/url\\(([\"']?)(\\/(?!\\/)[^)'\" ]+)\\1\\)/g, (_match, quote, path) => {\n const q = quote || \"\";\n return `url(${q}${prefixMountedPath(path, basePath)}${q})`;\n });\n}\n\nfunction injectHeadScript(html: string, script: string | null): string {\n if (!script) return html;\n const headCloseIdx = html.indexOf(\"</head>\");\n if (headCloseIdx === -1) return html;\n return html.slice(0, headCloseIdx) + script + html.slice(headCloseIdx);\n}\n\nconst OG_IMAGE_META_RE = /<meta\\b(?=[^>]*\\bproperty=([\"'])og:image\\1)[^>]*>/i;\nconst TWITTER_CARD_META_RE =\n /<meta\\b(?=[^>]*\\bname=([\"'])twitter:card\\1)[^>]*>/i;\nconst TWITTER_IMAGE_META_RE =\n /<meta\\b(?=[^>]*\\bname=([\"'])twitter:image\\1)[^>]*>/i;\n\nfunction defaultSocialImageUrl(requestUrl: string, basePath: string): string {\n return new URL(\n prefixMountedPath(AGENT_NATIVE_SOCIAL_IMAGE_PATH, basePath),\n requestUrl,\n ).toString();\n}\n\nfunction injectDefaultSocialImageMeta(html: string, imageUrl: string): string {\n const headCloseIdx = html.indexOf(\"</head>\");\n if (headCloseIdx === -1) return html;\n\n const hasAnySocialImage =\n OG_IMAGE_META_RE.test(html) || TWITTER_IMAGE_META_RE.test(html);\n const tags: string[] = [];\n\n if (!hasAnySocialImage) {\n tags.push(`<meta property=\"og:image\" content=\"${imageUrl}\">`);\n tags.push(`<meta property=\"og:image:secure_url\" content=\"${imageUrl}\">`);\n tags.push(\n `<meta property=\"og:image:type\" content=\"${AGENT_NATIVE_SOCIAL_IMAGE_TYPE}\">`,\n );\n tags.push(\n `<meta property=\"og:image:width\" content=\"${AGENT_NATIVE_SOCIAL_IMAGE_WIDTH}\">`,\n );\n tags.push(\n `<meta property=\"og:image:height\" content=\"${AGENT_NATIVE_SOCIAL_IMAGE_HEIGHT}\">`,\n );\n tags.push(\n `<meta property=\"og:image:alt\" content=\"${AGENT_NATIVE_SOCIAL_IMAGE_ALT}\">`,\n );\n }\n if (!TWITTER_CARD_META_RE.test(html)) {\n tags.push(`<meta name=\"twitter:card\" content=\"summary_large_image\">`);\n }\n if (!hasAnySocialImage) {\n tags.push(`<meta name=\"twitter:image\" content=\"${imageUrl}\">`);\n tags.push(\n `<meta name=\"twitter:image:alt\" content=\"${AGENT_NATIVE_SOCIAL_IMAGE_ALT}\">`,\n );\n }\n\n if (tags.length === 0) return html;\n return html.slice(0, headCloseIdx) + tags.join(\"\") + html.slice(headCloseIdx);\n}\n\nfunction isSsrHtmlOrDataResponse(\n headers: Headers,\n status: number,\n pathname: string,\n): boolean {\n if (status < 200 || status >= 400) return false;\n const contentType = headers.get(\"content-type\")?.toLowerCase() ?? \"\";\n if (contentType.includes(\"text/html\")) return true;\n return pathname.endsWith(\".data\") && contentType.includes(\"text/x-script\");\n}\n\n/**\n * Apply the SSR cache policy to the response headers.\n *\n * ┌──────────────────────────────────────────────────────────────────────────┐\n * │ SSR IS A PUBLIC, HARD-CDN-CACHED SHELL — SERVED IDENTICALLY TO EVERYONE. │\n * │ │\n * │ Every SSR HTML / React Router `.data` response gets the same public │\n * │ stale-while-revalidate policy for ALL visitors, authenticated or not, so │\n * │ the edge serves one shared copy and never stampedes origin. │\n * │ │\n * │ DO NOT reintroduce per-user / cookie-based cache variation here (no │\n * │ `private`, no `no-store`, no `Vary: Cookie`, no \"authenticated → don't │\n * │ cache\" branch). That makes pages uncacheable for every logged-in visitor, │\n * │ which is slow and expensive — exactly the regression this guardrail │\n * │ prevents. The reason it is SAFE to hard-cache is that the SSR response is │\n * │ impersonal: `createH3SSRHandler` renders without reading the request's │\n * │ session/cookies, so there is no per-user data baked into the HTML. ALL │\n * │ per-user state (who's logged in, private records, access checks) is │\n * │ resolved CLIENT-SIDE after load. Keep it that way: if you need the SSR │\n * │ output to differ per user, the fix is to move that work client-side, not │\n * │ to disable caching here. │\n * └──────────────────────────────────────────────────────────────────────────┘\n */\nfunction applyDefaultSsrCacheHeader(\n headers: Headers,\n status: number,\n pathname: string,\n) {\n if (!isSsrHtmlOrDataResponse(headers, status, pathname)) return;\n\n // Netlify Functions/proxies are not cached by default. Set all three cache\n // headers: Cache-Control for browsers, CDN-Cache-Control for generic CDNs,\n // and Netlify-CDN-Cache-Control (with durable) so Netlify's shared cache\n // actually serves SSR HTML/.data from the edge instead of forwarding every\n // request to origin — for every visitor, authenticated or not.\n for (const [name, value] of Object.entries(DEFAULT_SSR_CACHE_HEADERS)) {\n headers.set(name, value);\n }\n}\n\nfunction applyDefaultSpeculationRulesHeader(\n headers: Headers,\n status: number,\n basePath: string,\n) {\n if (status < 200 || status >= 400) return;\n if (headers.has(\"speculation-rules\")) return;\n\n const contentType = headers.get(\"content-type\")?.toLowerCase() ?? \"\";\n if (!contentType.includes(\"text/html\")) return;\n\n // Cloudflare Speed Brain injects its own Speculation-Rules header when the\n // origin omits one. Those browser prefetches carry `Sec-Purpose: prefetch`,\n // and Cloudflare refuses cache-ineligible dynamic pages with a 503 before\n // the request can reach Netlify/origin. We publish an explicit no-op ruleset\n // by default so Cloudflare does not inject its edge prefetch rules. Preserve\n // an app-provided Speculation-Rules header above if a template deliberately\n // owns this behavior.\n const rulesPath = prefixMountedPath(DEFAULT_SPECULATION_RULES_PATH, basePath);\n headers.set(\"speculation-rules\", `\"${rulesPath}\"`);\n}\n\n/**\n * Extract the plain JS body from a `<script ...>body</script>` string.\n * Returns `null` if the input is falsy or has no recognisable `</script>` end.\n * Used to compute the sha256 hash of framework-injected inline scripts so the\n * hash can be listed in the `script-src` CSP directive without relying on\n * `'unsafe-inline'`.\n */\nfunction extractScriptBody(scriptTag: string | null): string | null {\n if (!scriptTag) return null;\n const start = scriptTag.indexOf(\">\") + 1;\n const end = scriptTag.lastIndexOf(\"</script>\");\n if (start <= 0 || end < start) return null;\n return scriptTag.slice(start, end);\n}\n\n/**\n * Apply a Content-Security-Policy header to HTML document responses.\n *\n * Two directives are always enforced in production:\n *\n * - `object-src 'none'` — disables Flash / Java / PDF plugin execution,\n * which are a reliable code-execution vector even in modern browsers.\n * - `base-uri 'self'` — prevents a `<base href=\"...\">` injection from\n * hijacking all relative URLs in the document (a common attack target when\n * user-controlled content reaches the HTML).\n *\n * A third directive, `script-src`, is emitted via `Content-Security-Policy-\n * Report-Only` rather than enforced. The framework injects one deterministic\n * inline script per process (the Sentry config block — its hash is computed\n * once at process startup from the resolved env vars). Templates additionally\n * render a theme-init inline script whose exact content varies by template\n * (default theme param, custom docs variant, etc.) and which is rendered by\n * React Router, not this handler, so its hash is not available here. Shipping\n * script-src as Report-Only surfaces violations without breaking template\n * customisations; teams can graduate to enforcement once their hashes are\n * enumerated.\n *\n * Skipped in development (`NODE_ENV !== 'production'`) so HMR eval and Vite\n * dev-server injects are never blocked. Set `AGENT_NATIVE_DISABLE_DOC_CSP=1`\n * to opt out in production for a template with exotic needs.\n */\nfunction applyDocumentCsp(headers: Headers, sentryScript: string | null): void {\n if (process.env.NODE_ENV !== \"production\") return;\n if (process.env.AGENT_NATIVE_DISABLE_DOC_CSP === \"1\") return;\n\n // object-src / base-uri: enforced; neither directive mentions scripts, so\n // they are safe even when a template's inline script hashes are unknown.\n const existing = headers.get(\"content-security-policy\") ?? \"\";\n if (!existing) {\n headers.set(\n \"content-security-policy\",\n \"object-src 'none'; base-uri 'self'\",\n );\n }\n\n // script-src as Report-Only: list 'self' plus the hash for the Sentry config\n // script the SSR handler injects into every HTML response (the hash is\n // computed once from the resolved env vars at process startup). Template\n // theme-init hashes are NOT included here — see function comment above.\n const sentryBody = extractScriptBody(sentryScript);\n const sentryHash = sentryBody ? computeInlineScriptHash(sentryBody) : null;\n const scriptSrcTokens = [\"'self'\", ...(sentryHash ? [sentryHash] : [])];\n const scriptSrc = `script-src ${scriptSrcTokens.join(\" \")}`;\n\n const existingRo = headers.get(\"content-security-policy-report-only\") ?? \"\";\n if (!existingRo) {\n headers.set(\"content-security-policy-report-only\", scriptSrc);\n }\n}\n\nfunction isFrameworkOrAssetPath(pathname: string): boolean {\n return (\n pathname.startsWith(\"/.well-known/\") ||\n pathname.startsWith(\"/_agent_native/\") ||\n pathname.startsWith(\"/_agent-native/\") ||\n pathname.startsWith(\"/api/\") ||\n pathname.startsWith(\"/@vite/\") ||\n pathname.startsWith(\"/@id/\") ||\n pathname.startsWith(\"/@fs/\") ||\n pathname === \"/@react-refresh\" ||\n pathname === \"/__vite_ping\" ||\n pathname === \"/__open-in-editor\" ||\n pathname === \"/favicon.ico\" ||\n pathname === \"/favicon.png\" ||\n (/\\.\\w+$/.test(pathname) && !pathname.endsWith(\".data\"))\n );\n}\n\nasync function rewriteMountedResponse(\n response: Response,\n basePath: string,\n pathname: string,\n requestUrl: string,\n): Promise<Response> {\n const sentryClientConfigScript = getSentryClientConfigScript();\n const headers = new Headers(response.headers);\n applyDefaultSsrCacheHeader(headers, response.status, pathname);\n applyDefaultSpeculationRulesHeader(headers, response.status, basePath);\n\n const location = headers.get(\"location\");\n if (location?.startsWith(\"/\") && !location.startsWith(\"//\")) {\n headers.set(\"location\", prefixMountedPath(location, basePath));\n }\n\n const contentType = headers.get(\"content-type\") ?? \"\";\n if (!contentType.toLowerCase().includes(\"text/html\") || !response.body) {\n return new Response(response.body, {\n status: response.status,\n statusText: response.statusText,\n headers,\n });\n }\n\n const html = await response.text();\n headers.delete(\"content-length\");\n applyDocumentCsp(headers, sentryClientConfigScript);\n return new Response(\n injectHeadScript(\n injectDefaultSocialImageMeta(\n prefixMountedHtml(html, basePath),\n defaultSocialImageUrl(requestUrl, basePath),\n ),\n sentryClientConfigScript,\n ),\n {\n status: response.status,\n statusText: response.statusText,\n headers,\n },\n );\n}\n\n/**\n * Create an h3 catch-all that hands page routes to React Router and\n * returns 404 for framework / asset paths that React Router doesn't own.\n */\nexport function createH3SSRHandler(getBuild: () => Promise<unknown> | unknown) {\n const handler = createRequestHandler(getBuild as any);\n return defineEventHandler(async (event) => {\n const basePath = getAppBasePath();\n const p = stripAppBasePath(event.url.pathname);\n if (isFrameworkOrAssetPath(p)) {\n return new Response(null, { status: 404 });\n }\n try {\n const request = requestWithPathname(event.req as Request, p, basePath);\n // SSR renders an IMPERSONAL public shell — we deliberately do NOT read the\n // request's session/cookies here, and pin an explicitly anonymous request\n // context. That keeps the SSR HTML/.data identical for every visitor so it\n // can be hard-cached at the CDN for everyone (see applyDefaultSsrCacheHeader).\n //\n // Consequence: SSR loaders that call `getRequestUserEmail()` / `accessFilter()`\n // always see the unauthenticated branch and render public content only. Any\n // per-user view (private records, share-grant access, who's logged in) MUST\n // be resolved CLIENT-SIDE after load, never baked into SSR. Do not re-pin the\n // session here to \"fix\" a per-user page — that silently makes the page\n // uncacheable and/or leaks one user's data into another's cached copy.\n const ctx = { userEmail: undefined, orgId: undefined };\n if (request.method === \"HEAD\") {\n const getRequest = new Request(request.url, {\n method: \"GET\",\n headers: request.headers,\n signal: request.signal,\n });\n const response = await runWithRequestContext(ctx, () =>\n handler(getRequest),\n );\n return await rewriteMountedResponse(\n new Response(null, {\n status: response.status,\n statusText: response.statusText,\n headers: response.headers,\n }),\n basePath,\n p,\n request.url,\n );\n }\n return await rewriteMountedResponse(\n await runWithRequestContext(ctx, () => handler(request)),\n basePath,\n p,\n request.url,\n );\n } catch (err) {\n // Log the full stack server-side, but never leak it to the client.\n // Stack traces expose file paths, library versions, and code structure\n // that aid reconnaissance attacks. In dev we surface the message text\n // so devtools shows something useful; in prod we return a bare 500.\n console.error(\"[ssr-handler] SSR error:\", err);\n const isProd = process.env.NODE_ENV === \"production\";\n const body = isProd\n ? \"Internal Server Error\"\n : `Internal Server Error: ${(err as Error)?.message ?? err}`;\n return new Response(body, {\n status: 500,\n headers: { \"content-type\": \"text/plain\" },\n });\n }\n });\n}\n"]}
|
|
@@ -119,7 +119,42 @@ window.location.href =
|
|
|
119
119
|
|
|
120
120
|
After successful sign-in (token / email-password / Google OAuth), the framework 302s to `return`. The path is validated as same-origin via the URL parser — open-redirect / header-injection inputs fall back to `/`.
|
|
121
121
|
|
|
122
|
-
Bookmarked private paths already work
|
|
122
|
+
Bookmarked private paths already work _when the request reaches the server_ — the auth guard serves the login page at the requested URL and post-login reload returns the user there.
|
|
123
|
+
|
|
124
|
+
## Gating the App Shell (avoid the logged-out infinite spinner)
|
|
125
|
+
|
|
126
|
+
The server auth guard only protects requests that actually reach the Nitro
|
|
127
|
+
function. A statically-served / CDN-cached SPA shell, or a client-side (React
|
|
128
|
+
Router) navigation made after the session expired, never re-hits the guard — so
|
|
129
|
+
the app boots with **no session**, every data query 401s, and the UI sticks on
|
|
130
|
+
its loading state forever. Server-side protection alone is not enough; gate on
|
|
131
|
+
the client too.
|
|
132
|
+
|
|
133
|
+
For a fully private app (every page requires auth, like mail), wrap the routed
|
|
134
|
+
shell with the framework's `RequireSession`. It resolves the session on the
|
|
135
|
+
client and redirects signed-out visitors to `/_agent-native/sign-in?return=…`
|
|
136
|
+
instead of spinning:
|
|
137
|
+
|
|
138
|
+
```tsx
|
|
139
|
+
import { AppProviders, RequireSession } from "@agent-native/core/client";
|
|
140
|
+
|
|
141
|
+
<AppProviders queryClient={queryClient}>
|
|
142
|
+
<RequireSession bypass={isMcpEmbedSurface()}>
|
|
143
|
+
<AppLayout>
|
|
144
|
+
<Outlet />
|
|
145
|
+
</AppLayout>
|
|
146
|
+
</RequireSession>
|
|
147
|
+
</AppProviders>;
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
- Place it **inside** `AppProviders` (so the loading fallback is themed) and
|
|
151
|
+
**around** the layout/outlet — also around any always-mounted effects (poll,
|
|
152
|
+
automation trigger) so they don't fire 401s for logged-out visitors.
|
|
153
|
+
- Pass `bypass` for surfaces that authenticate by another mechanism (embed /
|
|
154
|
+
popout iframes carrying their own token) so they are never bounced to sign-in.
|
|
155
|
+
- Apps with public/anonymous routes (share pages) must **not** wrap the whole
|
|
156
|
+
app — gate only the private subtree, or use the `redirect={false}` +
|
|
157
|
+
`signedOut` props to render an inline call-to-action instead of redirecting.
|
|
123
158
|
|
|
124
159
|
## Related Skills
|
|
125
160
|
|
|
@@ -15,7 +15,7 @@ The docs site is the reference implementation. Today it ships:
|
|
|
15
15
|
- Markdown mirrors such as `/docs/getting-started.md`.
|
|
16
16
|
- `Accept: text/markdown` responses for public docs pages after a production build.
|
|
17
17
|
- JSON-LD for base organization, website, and page metadata.
|
|
18
|
-
- An audit CLI (`agent-native audit-agent-web`) that checks all of the above.
|
|
18
|
+
- An audit CLI (`npx @agent-native/core@latest audit-agent-web`) that checks all of the above.
|
|
19
19
|
|
|
20
20
|
Setting `publicMcp: true` additionally exposes opted-in actions as a public MCP endpoint, allowing external agents to call them directly (see [MCP Protocol](/docs/mcp-protocol)).
|
|
21
21
|
|
|
@@ -128,7 +128,7 @@ Vite apps can use `createAgentWebVitePlugin` from `@agent-native/core/vite` to w
|
|
|
128
128
|
Use the CLI audit against a deployed site or a local production server:
|
|
129
129
|
|
|
130
130
|
```bash
|
|
131
|
-
agent-native audit-agent-web --url https://www.agent-native.com
|
|
131
|
+
npx @agent-native/core@latest audit-agent-web --url https://www.agent-native.com
|
|
132
132
|
```
|
|
133
133
|
|
|
134
134
|
The audit checks for:
|
|
@@ -130,7 +130,7 @@ Unauthenticated MCP requests return a `WWW-Authenticate` challenge pointing at `
|
|
|
130
130
|
|
|
131
131
|
Access tokens are signed with `A2A_SECRET` when set, otherwise `BETTER_AUTH_SECRET`. They carry the signed user/org identity and the `mcp:read`, `mcp:write`, and/or `mcp:apps` scopes, and are audience-bound to the exact MCP resource URL. Refresh tokens are stored only as hashes and rotate on every refresh. Tool calls and MCP Apps resource reads run inside the same request context as the signed-in user; the embedded MCP App iframe never receives raw OAuth tokens.
|
|
132
132
|
|
|
133
|
-
`agent-native connect <url> --client claude-code` writes the URL-only MCP entry for this standard flow. For clients that cannot perform remote MCP OAuth, use the Connect page or `agent-native connect --token <token>` fallback to write an explicit bearer-token entry.
|
|
133
|
+
`npx @agent-native/core@latest connect <url> --client claude-code` writes the URL-only MCP entry for this standard flow. For clients that cannot perform remote MCP OAuth, use the Connect page or `npx @agent-native/core@latest connect --token <token>` fallback to write an explicit bearer-token entry.
|
|
134
134
|
|
|
135
135
|
## Bring Your Own Auth {#byoa}
|
|
136
136
|
|
|
@@ -87,13 +87,13 @@ Not ready to scaffold? You can add agent-native superpowers to a coding agent yo
|
|
|
87
87
|
If you're scaffolding now, the CLI command is:
|
|
88
88
|
|
|
89
89
|
```bash
|
|
90
|
-
npx @agent-native/core create my-platform
|
|
90
|
+
npx @agent-native/core@latest create my-platform
|
|
91
91
|
```
|
|
92
92
|
|
|
93
93
|
You'll get a multi-select picker. Pick one app (standalone) or several (workspace — apps share auth, brand, agent config, and database). Each picked template is scaffolded into `apps/<name>/` with every file you need.
|
|
94
94
|
|
|
95
95
|
Fill in `.env` (mostly `ANTHROPIC_API_KEY` and `DATABASE_URL`), `pnpm install`, `pnpm dev`, and it works. No "TODO: implement login," no placeholder routes.
|
|
96
96
|
|
|
97
|
-
Deploy targets: any Nitro-compatible host (Node, Cloudflare, Netlify, Vercel, Deno, Lambda, Bun) and any Drizzle-compatible SQL database (SQLite, Postgres, Turso, D1, Supabase, Neon). For workspaces, `agent-native deploy` builds every app at once and ships them behind a single origin. See [Deployment](/docs/deployment).
|
|
97
|
+
Deploy targets: any Nitro-compatible host (Node, Cloudflare, Netlify, Vercel, Deno, Lambda, Bun) and any Drizzle-compatible SQL database (SQLite, Postgres, Turso, D1, Supabase, Neon). For workspaces, `npx @agent-native/core@latest deploy` builds every app at once and ships them behind a single origin. See [Deployment](/docs/deployment).
|
|
98
98
|
|
|
99
99
|
To author and publish your own template, see [Creating Templates](/docs/creating-templates).
|
|
@@ -5,11 +5,11 @@ description: "Build and customize Agent-Native Code surfaces with the shared UI
|
|
|
5
5
|
|
|
6
6
|
# Agent-Native Code UI
|
|
7
7
|
|
|
8
|
-
Agent-Native Code is the Agent-Native coding surface: a local Claude Code/Codex-style workspace for coding sessions, slash commands, migrations, audits, transcripts, run controls, and follow-ups. A bare `npx @agent-native/core@latest`
|
|
8
|
+
Agent-Native Code is the Agent-Native coding surface: a local Claude Code/Codex-style workspace for coding sessions, slash commands, migrations, audits, transcripts, run controls, and follow-ups. A bare `npx @agent-native/core@latest` command opens this workspace; `npx @agent-native/core@latest code` is the explicit subcommand for the same experience.
|
|
9
9
|
|
|
10
10
|
There are three layers:
|
|
11
11
|
|
|
12
|
-
- **CLI**: `npx @agent-native/core@latest
|
|
12
|
+
- **CLI**: `npx @agent-native/core@latest` and `npx @agent-native/core@latest code` start, resume, inspect, and stop runs.
|
|
13
13
|
- **Desktop**: the left-sidebar Code tab adds native terminal launch, app webviews, and desktop deep links while using the same run model.
|
|
14
14
|
- **Shared UI**: `@agent-native/code-agents-ui` renders the reusable React surface.
|
|
15
15
|
|
|
@@ -95,19 +95,18 @@ The top-level CLI behaves like Claude Code or Codex:
|
|
|
95
95
|
|
|
96
96
|
```bash
|
|
97
97
|
npx @agent-native/core@latest
|
|
98
|
-
agent-native
|
|
99
|
-
agent-native
|
|
100
|
-
agent-native code
|
|
98
|
+
npx @agent-native/core@latest "fix the failing auth tests"
|
|
99
|
+
npx @agent-native/core@latest code
|
|
101
100
|
```
|
|
102
101
|
|
|
103
|
-
Use `agent-native code` when you want the explicit namespace. Built-in slash
|
|
102
|
+
Use `npx @agent-native/core@latest code` when you want the explicit namespace. Built-in slash
|
|
104
103
|
goals and project commands can run inside the interactive workspace or directly
|
|
105
104
|
from the shell:
|
|
106
105
|
|
|
107
106
|
```bash
|
|
108
|
-
agent-native code /migrate ./legacy-app --emit ./migration-dossier
|
|
109
|
-
agent-native code /audit --url https://example.com
|
|
110
|
-
agent-native code /release-check
|
|
107
|
+
npx @agent-native/core@latest code /migrate ./legacy-app --emit ./migration-dossier
|
|
108
|
+
npx @agent-native/core@latest code /audit --url https://example.com
|
|
109
|
+
npx @agent-native/core@latest code /release-check
|
|
111
110
|
```
|
|
112
111
|
|
|
113
112
|
Here `/migrate` and `/audit` are built-in goals (the built-in goals are
|
|
@@ -118,13 +117,13 @@ commands come from `.agents/commands/*.md`; project skills come from
|
|
|
118
117
|
records that the Desktop Code tab and shared UI display:
|
|
119
118
|
|
|
120
119
|
```bash
|
|
121
|
-
agent-native code list
|
|
122
|
-
agent-native code status --last
|
|
123
|
-
agent-native code attach --last
|
|
124
|
-
agent-native code logs --last
|
|
125
|
-
agent-native code resume --last
|
|
126
|
-
agent-native code stop --last
|
|
127
|
-
agent-native code ui
|
|
120
|
+
npx @agent-native/core@latest code list
|
|
121
|
+
npx @agent-native/core@latest code status --last
|
|
122
|
+
npx @agent-native/core@latest code attach --last
|
|
123
|
+
npx @agent-native/core@latest code logs --last
|
|
124
|
+
npx @agent-native/core@latest code resume --last
|
|
125
|
+
npx @agent-native/core@latest code stop --last
|
|
126
|
+
npx @agent-native/core@latest code ui
|
|
128
127
|
```
|
|
129
128
|
|
|
130
129
|
`resume` appends context and continues a run, `status` reports the latest run
|
|
@@ -267,7 +266,7 @@ Project skills live in:
|
|
|
267
266
|
.agents/skills/*/SKILL.md
|
|
268
267
|
```
|
|
269
268
|
|
|
270
|
-
When the host implements `listCodePacks`, the shared UI shows project commands and skills in the rail. Command rows insert `/<command>`, and skill rows insert a focused “Use the <skill> skill…” prompt so the rail stays actionable. The built-in slash goals `/migrate` and `/audit` stay reserved for the global Agent-Native Code controls, as do run-control names such as `status` and `resume` — those are subcommands invoked without a slash (`agent-native code status`, `agent-native code resume`), not slash goals.
|
|
269
|
+
When the host implements `listCodePacks`, the shared UI shows project commands and skills in the rail. Command rows insert `/<command>`, and skill rows insert a focused “Use the <skill> skill…” prompt so the rail stays actionable. The built-in slash goals `/migrate` and `/audit` stay reserved for the global Agent-Native Code controls, as do run-control names such as `status` and `resume` — those are subcommands invoked without a slash (`npx @agent-native/core@latest code status`, `npx @agent-native/core@latest code resume`), not slash goals.
|
|
271
270
|
|
|
272
271
|
Do not create a separate slash-command registry for a new Code host. Project
|
|
273
272
|
commands and skills are discovered from `.agents/commands/*.md` and
|
|
@@ -22,13 +22,13 @@ A good template:
|
|
|
22
22
|
Use the CLI-only Starter scaffold when you want a blank app with the framework wiring already in place:
|
|
23
23
|
|
|
24
24
|
```bash
|
|
25
|
-
|
|
25
|
+
npx @agent-native/core@latest create my-template --template starter --standalone
|
|
26
26
|
```
|
|
27
27
|
|
|
28
28
|
For a workspace with multiple apps, run the picker and include Starter with any domain templates you want:
|
|
29
29
|
|
|
30
30
|
```bash
|
|
31
|
-
|
|
31
|
+
npx @agent-native/core@latest create my-platform
|
|
32
32
|
```
|
|
33
33
|
|
|
34
34
|
Starter gives you auth, the agent sidebar, SQL-backed resources, tools, application state, actions, and polling sync. You add the domain model and product UI.
|
|
@@ -388,7 +388,7 @@ Before sharing:
|
|
|
388
388
|
Community templates can be created from a GitHub repo:
|
|
389
389
|
|
|
390
390
|
```bash
|
|
391
|
-
|
|
391
|
+
npx @agent-native/core@latest create my-app --template github:user/repo
|
|
392
392
|
```
|
|
393
393
|
|
|
394
394
|
## Contributing to the framework monorepo {#contributing}
|