@agent-native/core 0.32.0 → 0.32.2

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.
@@ -1 +1 @@
1
- {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/deploy/build.ts"],"names":[],"mappings":";AAEA;;;;;;;;;;;;GAYG;AAOH,OAAO,EAML,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACtB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAEL,KAAK,oBAAoB,EAC1B,MAAM,qBAAqB,CAAC;AAwC7B,wBAAgB,wCAAwC,CACtD,WAAW,EAAE,MAAM,EAAE,GACpB,MAAM,CAaR;AAgBD,KAAK,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,CAAC,CAAC;AAgBvE,wBAAgB,yCAAyC,CACvD,UAAU,EAAE,UAAU,EACtB,SAAS,EAAE,MAAM,EACjB,WAAW,SAAK,GACf,IAAI,CAQN;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,eAAe,EAAE,EACzB,WAAW,EAAE,MAAM,EAAE,EACrB,kBAAkB,GAAE,MAAM,EAAO,EACjC,OAAO,GAAE,gBAAgB,EAAO,EAChC,aAAa,GAAE,oBAAoB,GAAG,IAAW,EACjD,mBAAmB,GAAE,MAAM,EAAO,EAClC,gBAAgB,SAAmC,GAClD,MAAM,CA0hBR;AA4VD,wBAAgB,mBAAmB,IAAI,MAAM,EAAE,CAE9C;AAmVD;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACvC,gBAAgB,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAChD,UAAU,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3C;AAED,MAAM,WAAW,yBAAyB;IACxC,KAAK,EAAE,GAAG,CAAC;IACX,KAAK,EAAE,eAAe,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,WAAW,EAAE,MAAM,CAAC;IACpB,GAAG,EAAE,MAAM,CAAC;CACb;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,qBAAqB,CACzC,IAAI,EAAE,yBAAyB,GAC9B,OAAO,CAAC,IAAI,CAAC,CA+Bf"}
1
+ {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/deploy/build.ts"],"names":[],"mappings":";AAEA;;;;;;;;;;;;GAYG;AAOH,OAAO,EAML,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACtB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAEL,KAAK,oBAAoB,EAC1B,MAAM,qBAAqB,CAAC;AA0C7B,wBAAgB,wCAAwC,CACtD,WAAW,EAAE,MAAM,EAAE,GACpB,MAAM,CAaR;AAgBD,KAAK,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,CAAC,CAAC;AAgBvE,wBAAgB,yCAAyC,CACvD,UAAU,EAAE,UAAU,EACtB,SAAS,EAAE,MAAM,EACjB,WAAW,SAAK,GACf,IAAI,CAQN;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,eAAe,EAAE,EACzB,WAAW,EAAE,MAAM,EAAE,EACrB,kBAAkB,GAAE,MAAM,EAAO,EACjC,OAAO,GAAE,gBAAgB,EAAO,EAChC,aAAa,GAAE,oBAAoB,GAAG,IAAW,EACjD,mBAAmB,GAAE,MAAM,EAAO,EAClC,gBAAgB,SAAmC,GAClD,MAAM,CA+gBR;AA4VD,wBAAgB,mBAAmB,IAAI,MAAM,EAAE,CAE9C;AAmVD;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACvC,gBAAgB,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAChD,UAAU,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3C;AAED,MAAM,WAAW,yBAAyB;IACxC,KAAK,EAAE,GAAG,CAAC;IACX,KAAK,EAAE,eAAe,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,WAAW,EAAE,MAAM,CAAC;IACpB,GAAG,EAAE,MAAM,CAAC;CACb;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,qBAAqB,CACzC,IAAI,EAAE,yBAAyB,GAC9B,OAAO,CAAC,IAAI,CAAC,CA+Bf"}
@@ -22,10 +22,10 @@ import { getWorkspaceCoreExports, } from "./workspace-core.js";
22
22
  import { generateActionRegistryForProject } from "../vite/action-types-plugin.js";
23
23
  import { mcpEmbedStaticAssetRouteRules } from "../shared/mcp-embed-headers.js";
24
24
  import { AGENT_NATIVE_DEFAULT_SOCIAL_IMAGE } from "../shared/social-meta.js";
25
+ import { DEFAULT_SPECULATION_RULES_PATH, DEFAULT_SSR_CACHE_CONTROL, } from "../shared/cache-control.js";
25
26
  import { collectImmutableAssetPaths, IMMUTABLE_ASSET_CACHE_CONTROL, IMMUTABLE_ASSET_CACHE_HEADERS, prefixAssetPath, } from "./immutable-assets.js";
26
27
  const cwd = process.cwd();
27
28
  const preset = process.env.NITRO_PRESET || "node";
28
- const DEFAULT_SSR_CACHE_CONTROL = "public, max-age=5, stale-while-revalidate=604800, stale-if-error=3600";
29
29
  function normalizeConfiguredAppBasePath() {
30
30
  const raw = process.env.VITE_APP_BASE_PATH || process.env.APP_BASE_PATH;
31
31
  if (!raw || raw === "/")
@@ -324,10 +324,9 @@ function injectHeadScript(html, script) {
324
324
  }
325
325
 
326
326
  const DEFAULT_SSR_CACHE_CONTROL = ${JSON.stringify(DEFAULT_SSR_CACHE_CONTROL)};
327
+ const DEFAULT_SPECULATION_RULES_PATH = ${JSON.stringify(DEFAULT_SPECULATION_RULES_PATH)};
327
328
  const IMMUTABLE_ASSET_CACHE_CONTROL = ${JSON.stringify(IMMUTABLE_ASSET_CACHE_CONTROL)};
328
329
  const IMMUTABLE_ASSET_PATHS = new Set(${JSON.stringify([...new Set(immutableAssetPaths)].sort())});
329
- const ANONYMOUS_SESSION_COOKIE_NAMES = new Set(["an_docs_session"]);
330
- const BETTER_AUTH_SESSION_COOKIE_RE = /\\.session_(?:token|data)$/;
331
330
  const AGENT_NATIVE_DEFAULT_SOCIAL_IMAGE = ${JSON.stringify(AGENT_NATIVE_DEFAULT_SOCIAL_IMAGE)};
332
331
  const OG_IMAGE_META_RE = /<meta\\b(?=[^>]*\\bproperty=(["'])og:image\\1)[^>]*>/i;
333
332
  const TWITTER_CARD_META_RE = /<meta\\b(?=[^>]*\\bname=(["'])twitter:card\\1)[^>]*>/i;
@@ -355,63 +354,54 @@ function injectDefaultSocialImageMeta(html) {
355
354
  return html.slice(0, headCloseIdx) + tags.join("") + html.slice(headCloseIdx);
356
355
  }
357
356
 
358
- function requestHasAuthenticatedCookie(cookieHeader) {
359
- if (!cookieHeader) return false;
360
- return cookieHeader
361
- .split(";")
362
- .map((cookie) => (cookie.trim().split("=", 1)[0] || "").trim())
363
- .filter(Boolean)
364
- .some(isAuthenticatedCookieName);
365
- }
366
-
367
- function isAuthenticatedCookieName(name) {
368
- if (ANONYMOUS_SESSION_COOKIE_NAMES.has(name)) return false;
369
- const bareName = name.replace(/^__(?:Secure|Host)-/, "");
370
- return (
371
- bareName === "an_embed_session" ||
372
- bareName === "an_session" ||
373
- bareName === "an_session_workspace" ||
374
- bareName.startsWith("an_session_") ||
375
- BETTER_AUTH_SESSION_COOKIE_RE.test(bareName)
376
- );
377
- }
378
-
379
- function requestHasAuthSignal(request) {
380
- const headers = request.headers;
381
- const url = new URL(request.url);
382
- return Boolean(
383
- headers.get("authorization") ||
384
- requestHasAuthenticatedCookie(headers.get("cookie")) ||
385
- url.searchParams.has("__an_embed_token") ||
386
- url.searchParams.has("_session")
387
- );
388
- }
389
-
390
- function shouldUseDefaultSsrCacheHeader(headers, status, pathname, hasAuthSignal) {
357
+ function shouldUseDefaultSsrCacheHeader(headers, status, pathname) {
391
358
  if (status < 200 || status >= 400) return false;
392
- if (hasAuthSignal) return false;
393
359
 
394
360
  const contentType = (headers.get("content-type") || "").toLowerCase();
395
361
  if (contentType.includes("text/html")) {
396
- return !headers.has("cache-control");
362
+ // SSR HTML is public app shell in this framework; any per-user state is
363
+ // fetched after hydration. Always enforce the framework SWR default here;
364
+ // route-level no-cache/private headers on SSR HTML recreate the same
365
+ // origin stampede this cache policy is meant to prevent.
366
+ return true;
397
367
  }
398
368
 
399
369
  if (!pathname.endsWith(".data")) return false;
400
370
  if (!contentType.includes("text/x-script")) return false;
401
371
 
402
372
  // React Router marks loader .data responses no-cache by default. Agent-Native
403
- // default. For public loader responses, replace that default with the same
404
- // short-fresh/long-SWR policy as HTML so route prefetch warms the CDN. Keep
405
- // explicit route cache policies and any authenticated request untouched.
406
- const cacheControl = headers.get("cache-control");
407
- return !cacheControl || cacheControl.trim().toLowerCase() === "no-cache";
373
+ // SSR is public app shell, even for browsers carrying auth-looking cookies;
374
+ // user/org-specific data is loaded client-side through actions/API routes
375
+ // after hydration. Keep .data on the same SWR policy as HTML so normal route
376
+ // data fetches fill CDN cache instead of bypassing it and slamming origin.
377
+ // Do not re-add a blanket auth-signal bypass here; logged-in browsers still
378
+ // need CDN-cached public route data. Worker SSR does not populate
379
+ // getRequestUserEmail()/accessFilter() context for private loaders, and
380
+ // Node/H3 has an auth-context access guard for older loaders that still do.
381
+ // Also do not preserve route-level private/no-store for React Router .data:
382
+ // if a route needs per-user data, it belongs behind a client-side action/API
383
+ // call rather than in the shared SSR payload.
384
+ return true;
408
385
  }
409
386
 
410
- function applyDefaultSsrCacheHeader(headers, status, pathname, hasAuthSignal) {
411
- if (!shouldUseDefaultSsrCacheHeader(headers, status, pathname, hasAuthSignal)) return;
387
+ function applyDefaultSsrCacheHeader(headers, status, pathname) {
388
+ if (!shouldUseDefaultSsrCacheHeader(headers, status, pathname)) return;
412
389
  headers.set("cache-control", DEFAULT_SSR_CACHE_CONTROL);
413
390
  }
414
391
 
392
+ function applyDefaultSpeculationRulesHeader(headers, status, basePath) {
393
+ if (status < 200 || status >= 400) return;
394
+ if (headers.has("speculation-rules")) return;
395
+
396
+ const contentType = (headers.get("content-type") || "").toLowerCase();
397
+ if (!contentType.includes("text/html")) return;
398
+
399
+ // Cloudflare Speed Brain injects Speculation-Rules when origin omits this
400
+ // header. Those browser prefetches carry Sec-Purpose: prefetch and
401
+ // Cloudflare can return 503 before the request reaches origin. Publish an
402
+ // explicit no-op ruleset by default; apps can still provide their own header.
403
+ headers.set("speculation-rules", '"' + prefixMountedPath(DEFAULT_SPECULATION_RULES_PATH, basePath) + '"');
404
+ }
415
405
  function isImmutableAssetRequest(request) {
416
406
  const pathname = stripAppBasePath(new URL(request.url).pathname);
417
407
  return IMMUTABLE_ASSET_PATHS.has(pathname);
@@ -432,10 +422,11 @@ function applyImmutableAssetCacheHeaders(response, request) {
432
422
  });
433
423
  }
434
424
 
435
- async function rewriteMountedResponse(response, basePath, pathname, hasAuthSignal) {
425
+ async function rewriteMountedResponse(response, basePath, pathname) {
436
426
  const sentryClientConfigScript = getSentryClientConfigScript();
437
427
  const headers = new Headers(response.headers);
438
- applyDefaultSsrCacheHeader(headers, response.status, pathname, hasAuthSignal);
428
+ applyDefaultSsrCacheHeader(headers, response.status, pathname);
429
+ applyDefaultSpeculationRulesHeader(headers, response.status, basePath);
439
430
 
440
431
  const location = headers.get("location");
441
432
  if (location?.startsWith("/") && !location.startsWith("//")) {
@@ -552,7 +543,6 @@ ${actionRegistrations.join("\n")}
552
543
  return new Response(null, { status: 404 });
553
544
  }
554
545
  const request = requestWithPathname(event.req, p);
555
- const hasAuthSignal = requestHasAuthSignal(request);
556
546
  if (event.req.method === "HEAD") {
557
547
  const getRequest = requestWithMethod(request, "GET");
558
548
  const response = await rrHandler(getRequest);
@@ -563,11 +553,10 @@ ${actionRegistrations.join("\n")}
563
553
  headers: response.headers,
564
554
  }),
565
555
  basePath,
566
- p,
567
- hasAuthSignal,
556
+ p
568
557
  );
569
558
  }
570
- return rewriteMountedResponse(await rrHandler(request), basePath, p, hasAuthSignal);
559
+ return rewriteMountedResponse(await rrHandler(request), basePath, p);
571
560
  }));
572
561
 
573
562
  _handler = app.fetch.bind(app);