@publish.os/nextjs 0.0.1-alpha.91 → 0.0.1-alpha.92

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.
Files changed (153) hide show
  1. package/compiler-assets/nextjs/defaults/group/index.tsx +16 -11
  2. package/compiler-assets/nextjs/defaults/group/layout.tsx +6 -2
  3. package/compiler-assets/nextjs/defaults/group/page.tsx +7 -6
  4. package/compiler-assets/nextjs/defaults/project/next.config.mjs +2 -1
  5. package/compiler-assets/nextjs/defaults/root/index.tsx +16 -11
  6. package/compiler-assets/nextjs/defaults/root/layout.tsx +7 -3
  7. package/compiler-assets/nextjs/shims/agent-user-agents.ts +65 -0
  8. package/compiler-assets/nextjs/shims/document.tsx +9 -1
  9. package/compiler-assets/nextjs/shims/generated-leaf-page.tsx +3 -0
  10. package/compiler-assets/nextjs/shims/proxy.ts +156 -54
  11. package/dist/{build-operation-5QMLXF7N.js → build-operation-CJDUL4OW.js} +5 -5
  12. package/dist/{chunk-GBPLER5H.js → chunk-3T4HVDSC.js} +2 -2
  13. package/dist/{chunk-UYGCOWRF.js → chunk-DX7PXFCM.js} +860 -50
  14. package/dist/{chunk-F3AGNDF4.js → chunk-DZ3VWEV5.js} +860 -575
  15. package/dist/{chunk-OXOFRXEI.js → chunk-NHSLTARU.js} +1284 -1164
  16. package/dist/{chunk-ORIUWJBQ.js → chunk-SBMDONTV.js} +3 -2
  17. package/dist/compiler.js +42 -23
  18. package/dist/components/blocks/agent-actions.d.ts +7 -7
  19. package/dist/components/blocks/agent-actions.js +1 -32
  20. package/dist/components/blocks/toc.d.ts +7 -7
  21. package/dist/components/ui/button.d.ts +1 -2
  22. package/dist/{compose-CVBJRAF6.js → compose-44GJSMXD.js} +2 -2
  23. package/dist/config/createNextConfig.js +2 -0
  24. package/dist/{dev-operation-OSHHWRWK.js → dev-operation-WNECBHZ5.js} +17 -7
  25. package/dist/{ide-support-CU6Z5PVR.js → ide-support-TG74L4FF.js} +3 -3
  26. package/dist/index.d.ts +143 -126
  27. package/dist/index.js +25 -0
  28. package/dist/kernel/components/blocks/AgentActions.d.ts +7 -7
  29. package/dist/kernel/components/blocks/AgentActions.js +1 -32
  30. package/dist/kernel/components/blocks/agent-actions.d.ts +1 -2
  31. package/dist/kernel/components/blocks/agent-actions.js +1 -32
  32. package/dist/kernel/components/blocks/animated-icon-swap.d.ts +2 -2
  33. package/dist/kernel/components/blocks/color-palette.d.ts +2 -2
  34. package/dist/kernel/components/blocks/logo-block.d.ts +2 -2
  35. package/dist/kernel/components/blocks/nav-breadcrumb.d.ts +6 -5
  36. package/dist/kernel/components/blocks/nav-breadcrumb.js +19 -13
  37. package/dist/kernel/components/blocks/navbar.d.ts +5 -4
  38. package/dist/kernel/components/blocks/navbar.js +62 -42
  39. package/dist/kernel/components/blocks/navigation-progress.d.ts +2 -2
  40. package/dist/kernel/components/blocks/next-prev.d.ts +4 -4
  41. package/dist/kernel/components/blocks/next-prev.js +29 -6
  42. package/dist/kernel/components/blocks/page-list.d.ts +4 -4
  43. package/dist/kernel/components/blocks/page-list.js +30 -7
  44. package/dist/kernel/components/blocks/search.d.ts +9 -15
  45. package/dist/kernel/components/blocks/sidebar-node.d.ts +3 -5
  46. package/dist/kernel/components/blocks/sidebar-node.js +12 -2
  47. package/dist/kernel/components/blocks/sidebar.d.ts +6 -7
  48. package/dist/kernel/components/blocks/sidebar.js +132 -26
  49. package/dist/kernel/components/blocks/theme-toggle.d.ts +3 -4
  50. package/dist/kernel/components/blocks/toc-client.d.ts +7 -7
  51. package/dist/kernel/components/blocks/toc.d.ts +3 -3
  52. package/dist/kernel/components/mdx/components/blockquote.d.ts +2 -2
  53. package/dist/kernel/components/mdx/components/callout.d.ts +3 -3
  54. package/dist/kernel/components/mdx/components/code-block.d.ts +2 -2
  55. package/dist/kernel/components/mdx/components/copy-code-button.d.ts +2 -2
  56. package/dist/kernel/components/mdx/components/figure-caption.d.ts +2 -2
  57. package/dist/kernel/components/mdx/components/figure.d.ts +3 -3
  58. package/dist/kernel/components/mdx/components/footnotes.d.ts +2 -2
  59. package/dist/kernel/components/mdx/components/heading-copy-link.d.ts +2 -2
  60. package/dist/kernel/components/mdx/components/heading.d.ts +2 -2
  61. package/dist/kernel/components/mdx/components/hr.d.ts +4 -4
  62. package/dist/kernel/components/mdx/components/image-zoom.d.ts +3 -3
  63. package/dist/kernel/components/mdx/components/image-zoom.js +3 -2
  64. package/dist/kernel/components/mdx/components/image.d.ts +2 -2
  65. package/dist/kernel/components/mdx/components/image.js +1 -1
  66. package/dist/kernel/components/mdx/components/inline-code.d.ts +2 -2
  67. package/dist/kernel/components/mdx/components/kbd.d.ts +3 -3
  68. package/dist/kernel/components/mdx/components/link.d.ts +3 -3
  69. package/dist/kernel/components/mdx/components/paragraph.d.ts +2 -2
  70. package/dist/kernel/components/mdx/components/strikethrough.d.ts +2 -2
  71. package/dist/kernel/components/mdx/components/table.d.ts +7 -7
  72. package/dist/kernel/components/mdx/components/task-list.d.ts +3 -3
  73. package/dist/kernel/components/mdx/components/video-player.d.ts +2 -2
  74. package/dist/kernel/components/mdx/components/video.d.ts +2 -3
  75. package/dist/kernel/components/mdx/error-boundary.d.ts +2 -3
  76. package/dist/kernel/components/mdx/error-fallback.d.ts +2 -2
  77. package/dist/kernel/components/mdx/mdx.d.ts +42 -11
  78. package/dist/kernel/components/mdx/mdx.js +1 -1
  79. package/dist/kernel/components/next-image.d.ts +3 -3
  80. package/dist/kernel/components/ui/accordion.d.ts +7 -7
  81. package/dist/kernel/components/ui/breadcrumb-trail.d.ts +2 -3
  82. package/dist/kernel/components/ui/breadcrumb.d.ts +13 -13
  83. package/dist/kernel/components/ui/button-group.d.ts +5 -5
  84. package/dist/kernel/components/ui/button.d.ts +3 -3
  85. package/dist/kernel/components/ui/card.d.ts +7 -7
  86. package/dist/kernel/components/ui/dialog.d.ts +10 -10
  87. package/dist/kernel/components/ui/drawer.d.ts +12 -12
  88. package/dist/kernel/components/ui/kbd.d.ts +3 -3
  89. package/dist/kernel/components/ui/link.d.ts +3 -3
  90. package/dist/kernel/components/ui/menu.d.ts +22 -22
  91. package/dist/kernel/components/ui/mod-key.d.ts +2 -3
  92. package/dist/kernel/components/ui/navigation-menu.d.ts +15 -15
  93. package/dist/kernel/components/ui/popover.d.ts +11 -11
  94. package/dist/kernel/components/ui/progress.d.ts +7 -7
  95. package/dist/kernel/components/ui/scroll-area.d.ts +1 -2
  96. package/dist/kernel/components/ui/select.d.ts +16 -16
  97. package/dist/kernel/components/ui/separator.d.ts +3 -3
  98. package/dist/kernel/components/ui/table.d.ts +7 -7
  99. package/dist/kernel/components/ui/tabs.d.ts +12 -12
  100. package/dist/kernel/components/ui/tag.d.ts +3 -3
  101. package/dist/kernel/components/ui/text.d.ts +4 -4
  102. package/dist/kernel/components/ui/toast.d.ts +11 -11
  103. package/dist/kernel/components/ui/tooltip.d.ts +9 -9
  104. package/dist/kernel/defaults.registry.d.ts +2 -2
  105. package/dist/kernel/defaults.registry.js +2 -2
  106. package/dist/kernel/routes/agent/markdown.d.ts +4 -0
  107. package/dist/kernel/routes/agent/markdown.js +11 -7
  108. package/dist/kernel/routes/layouts/group.d.ts +1 -1
  109. package/dist/kernel/routes/metadata/feed.d.ts +1 -2
  110. package/dist/kernel/routes/metadata/feed.js +34 -29
  111. package/dist/kernel/routes/metadata/llms.d.ts +3 -31
  112. package/dist/kernel/routes/metadata/llms.js +2 -200
  113. package/dist/kernel/routes/metadata/robots.d.ts +5 -3
  114. package/dist/kernel/routes/metadata/robots.js +4 -25
  115. package/dist/kernel/routes/metadata/sitemap.d.ts +15 -1
  116. package/dist/kernel/routes/metadata/sitemap.js +200 -112
  117. package/dist/kernel/routes/not-found.js +1 -1
  118. package/dist/kernel/routes/pages/group.d.ts +3 -3
  119. package/dist/kernel/routes/pages/group.js +10 -4
  120. package/dist/kernel/routes/pages/leaf.d.ts +9 -4
  121. package/dist/kernel/routes/pages/leaf.js +16 -8
  122. package/dist/kernel/routes/pages/root.d.ts +3 -3
  123. package/dist/kernel/routes/pages/root.js +20 -5
  124. package/dist/keyboard-shortcuts.d.ts +2 -2
  125. package/dist/manifest-types-CcVPH_jh.d.ts +83 -0
  126. package/dist/resolvers/manifest-resolver.d.ts +2 -2
  127. package/dist/resolvers/manifest-resolver.js +65 -35
  128. package/dist/search.d.ts +2 -9
  129. package/dist/search.js +2 -7
  130. package/dist/sidebar-types-CMrMM0Nj.d.ts +105 -0
  131. package/dist/theme-scope.d.ts +2 -2
  132. package/dist/types-BbqmOzLC.d.ts +168 -0
  133. package/dist/types-TjH1ek0X.d.ts +22 -0
  134. package/dist/types.d.ts +116 -91
  135. package/dist/{validate-local-source-SV44DBQT.js → validate-local-source-EN2GW4FR.js} +3 -3
  136. package/dist/{validate-publish-os-source-NZJF3TB2.js → validate-publish-os-source-OEWQDB7B.js} +2 -2
  137. package/init/seed/minimal/publish.os/blog/index.tsx +25 -22
  138. package/init/seed/minimal/publish.os/blog/page.tsx +31 -16
  139. package/init/seed/minimal/publish.os/components/blog/copy-link.tsx +1 -1
  140. package/init/seed/minimal/publish.os/components/blog/frontmatter.ts +41 -0
  141. package/init/seed/minimal/publish.os/publish.os.config.json +13 -2
  142. package/init/seed/minimal/seed.json +1 -0
  143. package/init/seed/scratch/publish.os/publish.os.config.json +1 -1
  144. package/package.json +4 -4
  145. package/release/app/phosphor/package.json +1 -1
  146. package/release/app/phosphor/pnpm-lock.yaml.template +53 -127
  147. package/release/compiler/pnpm-lock.yaml.template +49 -123
  148. package/release/release.json +4 -4
  149. package/dist/sidebar-types-DKpR27II.d.ts +0 -25
  150. package/dist/types-CJWRG05y.d.ts +0 -76
  151. package/dist/types-CUtrppxt.d.ts +0 -69
  152. package/dist/types-J2w_puPF.d.ts +0 -128
  153. package/dist/{button-BdCScEKi.d.ts → button-D6Xp2HBm.d.ts} +1 -1
@@ -1,3 +1,4 @@
1
+ import { isMarkdownClient } from "@app/agent-user-agents";
1
2
  import {
2
3
  createNotFoundTextResponse,
3
4
  resolveNotFoundScope,
@@ -6,8 +7,6 @@ import { agentRouteConfig } from "@source/.publishos/agent-route-config.generate
6
7
  import type { NextRequest } from "next/server";
7
8
  import { NextResponse } from "next/server";
8
9
 
9
- const AGENT_USER_AGENT_PATTERN =
10
- /\b(?:axios|got|node-fetch|undici|curl|wget|python-requests|httpx|aiohttp|claude-code|claudebot|claude|cursor|chatgpt|openai|perplexity|anthropic-ai)\b/i;
11
10
  const INTERNAL_MARKDOWN_PREFIX = "/__publishos/md";
12
11
  const FRAMEWORK_PREFIX = "__PUBLISHOS_FRAMEWORK_PREFIX__";
13
12
  const TEXT_METHODS = new Set(["GET", "HEAD"]);
@@ -36,11 +35,15 @@ function normalizePagePath(pathname: string): string {
36
35
  return pathname.replace(/\/+$/, "");
37
36
  }
38
37
 
39
- function markdownRoutePath(pathname: string): string {
38
+ function markdownRoutePath(
39
+ pathname: string,
40
+ reason: "accept" | "extension",
41
+ ): string {
40
42
  const normalized = normalizePagePath(pathname);
41
- const pagePath = normalized.endsWith(".md")
42
- ? normalized.slice(0, -".md".length)
43
- : normalized;
43
+ const pagePath =
44
+ reason === "extension" && normalized.endsWith(".md")
45
+ ? normalized.slice(0, -".md".length)
46
+ : normalized;
44
47
  return pagePath === "/"
45
48
  ? INTERNAL_MARKDOWN_PREFIX
46
49
  : `${INTERNAL_MARKDOWN_PREFIX}${pagePath}`;
@@ -51,13 +54,21 @@ function markdownAlternatePath(pathname: string): string {
51
54
  if (normalized === "/") {
52
55
  return agentRouteConfig.discoveryLinks.sitemap ?? "/sitemap.md";
53
56
  }
54
- return normalized.endsWith(".md") ? normalized : `${normalized}.md`;
57
+ return `${normalized}.md`;
58
+ }
59
+
60
+ function rootMarkdownSitemapPath(requestUrl: URL): string {
61
+ return new URL(
62
+ agentRouteConfig.discoveryLinks.sitemap ?? "/sitemap.md",
63
+ requestUrl,
64
+ ).pathname;
55
65
  }
56
66
 
57
67
  function explicitAcceptQuality(accept: string, mimeType: string): number {
58
- if (!accept) return 0;
68
+ if (!accept.trim()) return 1;
59
69
 
60
70
  const [targetType, targetSubtype] = mimeType.toLowerCase().split("/");
71
+ let bestSpecificity = -1;
61
72
  let bestQuality = 0;
62
73
 
63
74
  for (const entry of accept.split(",")) {
@@ -69,17 +80,31 @@ function explicitAcceptQuality(accept: string, mimeType: string): number {
69
80
  if (!rawType) continue;
70
81
 
71
82
  const [type, subtype] = rawType.split("/");
72
- if (type !== targetType || subtype !== targetSubtype) continue;
83
+ const specificity =
84
+ type === targetType && subtype === targetSubtype
85
+ ? 2
86
+ : type === targetType && subtype === "*"
87
+ ? 1
88
+ : type === "*" && subtype === "*"
89
+ ? 0
90
+ : -1;
91
+ if (specificity < 0) continue;
73
92
 
74
93
  let quality = 1;
75
94
  for (const param of rawParams) {
76
95
  const [key, value] = param.split("=").map((part) => part.trim());
77
96
  if (key !== "q") continue;
78
- const parsed = Number.parseFloat(value);
79
- quality = Number.isFinite(parsed) ? parsed : 0;
97
+ const parsed = Number(value);
98
+ quality =
99
+ Number.isFinite(parsed) && parsed >= 0 && parsed <= 1 ? parsed : 0;
80
100
  }
81
101
 
82
- if (quality > bestQuality) bestQuality = quality;
102
+ if (specificity > bestSpecificity) {
103
+ bestSpecificity = specificity;
104
+ bestQuality = quality;
105
+ } else if (specificity === bestSpecificity) {
106
+ bestQuality = Math.max(bestQuality, quality);
107
+ }
83
108
  }
84
109
 
85
110
  return bestQuality;
@@ -87,48 +112,99 @@ function explicitAcceptQuality(accept: string, mimeType: string): number {
87
112
 
88
113
  function negotiatedTextType(
89
114
  request: NextRequest,
90
- ): "text/markdown; charset=utf-8" | "text/plain; charset=utf-8" | undefined {
91
- if (!TEXT_METHODS.has(request.method)) return undefined;
92
-
115
+ ): "text/markdown; charset=utf-8" | "text/html; charset=utf-8" | undefined {
93
116
  const accept = request.headers.get("accept") ?? "";
94
117
  const markdownQuality = agentRouteConfig.markdownAccept
95
118
  ? explicitAcceptQuality(accept, "text/markdown")
96
119
  : 0;
97
- const plainQuality = agentRouteConfig.plainTextAccept
98
- ? explicitAcceptQuality(accept, "text/plain")
120
+ const htmlQuality = explicitAcceptQuality(accept, "text/html");
121
+
122
+ if (markdownQuality === 0 && htmlQuality === 0) return undefined;
123
+ if (markdownQuality > htmlQuality) return "text/markdown; charset=utf-8";
124
+ if (markdownQuality < htmlQuality) return "text/html; charset=utf-8";
125
+ if (looksLikeAgent(request)) return "text/markdown; charset=utf-8";
126
+ return htmlQuality > 0 && markdownQuality > 0
127
+ ? "text/html; charset=utf-8"
128
+ : undefined;
129
+ }
130
+
131
+ function negotiatedPlainNotFound(request: NextRequest): boolean {
132
+ if (!TEXT_METHODS.has(request.method)) return false;
133
+
134
+ const accept = request.headers.get("accept") ?? "";
135
+ const plainQuality = explicitAcceptQuality(accept, "text/plain");
136
+ const markdownQuality = agentRouteConfig.markdownAccept
137
+ ? explicitAcceptQuality(accept, "text/markdown")
99
138
  : 0;
100
139
  const htmlQuality = explicitAcceptQuality(accept, "text/html");
101
140
 
102
- if (markdownQuality > 0 && markdownQuality >= htmlQuality) {
103
- return "text/markdown; charset=utf-8";
104
- }
105
- if (plainQuality > 0 && htmlQuality === 0 && markdownQuality === 0) {
106
- return "text/plain; charset=utf-8";
141
+ return plainQuality > Math.max(markdownQuality, htmlQuality);
142
+ }
143
+
144
+ function removeDisabledDiscoveryHeaders(response: Response): Response {
145
+ if (!agentRouteConfig.enabled || !agentRouteConfig.discoveryHeaders) {
146
+ for (const name of ["link", "x-publishos-llms", "x-publishos-sitemap"])
147
+ response.headers.delete(name);
107
148
  }
108
- return undefined;
149
+ return response;
109
150
  }
110
151
 
111
152
  function looksLikeAgent(request: NextRequest): boolean {
112
153
  if (!TEXT_METHODS.has(request.method)) return false;
113
154
  if (!agentRouteConfig.agentDetection) return false;
114
- if (explicitAcceptQuality(request.headers.get("accept") ?? "", "text/html")) {
115
- return false;
155
+ return isMarkdownClient(request.headers.get("user-agent") ?? "");
156
+ }
157
+
158
+ function mergeVary(response: Response, values: string[]): void {
159
+ const existing = (response.headers.get("vary") ?? "")
160
+ .split(",")
161
+ .map((value) => value.trim())
162
+ .filter(Boolean);
163
+ if (existing.some((value) => value === "*")) return;
164
+ const merged = [...existing];
165
+ for (const value of values) {
166
+ if (!merged.some((item) => item.toLowerCase() === value.toLowerCase()))
167
+ merged.push(value);
116
168
  }
117
- return AGENT_USER_AGENT_PATTERN.test(request.headers.get("user-agent") ?? "");
169
+ if (merged.length) response.headers.set("vary", merged.join(", "));
170
+ }
171
+
172
+ function negotiationVary(): string[] {
173
+ if (!agentRouteConfig.enabled || !agentRouteConfig.markdownAccept) return [];
174
+ return ["Accept", ...(agentRouteConfig.agentDetection ? ["User-Agent"] : [])];
175
+ }
176
+
177
+ function isNextNavigationRequest(request: NextRequest): boolean {
178
+ return [
179
+ "rsc",
180
+ "next-router-prefetch",
181
+ "next-router-state-tree",
182
+ "next-router-segment-prefetch",
183
+ ].some((name) => request.headers.has(name));
118
184
  }
119
185
 
120
186
  function markdownRequestReason(
121
187
  request: NextRequest,
122
- ): "accept" | "agent" | "extension" | undefined {
188
+ ): "accept" | "extension" | undefined {
123
189
  if (!agentRouteConfig.enabled) return undefined;
190
+ if (!TEXT_METHODS.has(request.method) || isNextNavigationRequest(request))
191
+ return undefined;
124
192
  if (
125
193
  agentRouteConfig.markdownRoutes &&
126
194
  request.nextUrl.pathname.endsWith(".md")
127
195
  ) {
128
- return "extension";
196
+ let decoded: string;
197
+ try {
198
+ decoded = normalizePagePath(
199
+ decodeURIComponent(request.nextUrl.pathname),
200
+ ).normalize("NFC");
201
+ } catch {
202
+ decoded = request.nextUrl.pathname;
203
+ }
204
+ if (!PUBLIC_PATHS.has(decoded)) return "extension";
129
205
  }
130
- if (negotiatedTextType(request)) return "accept";
131
- if (looksLikeAgent(request)) return "agent";
206
+ const selectedType = negotiatedTextType(request);
207
+ if (selectedType === "text/markdown; charset=utf-8") return "accept";
132
208
  return undefined;
133
209
  }
134
210
 
@@ -171,14 +247,14 @@ function rewriteToMarkdown({
171
247
  requestHeaders,
172
248
  }: {
173
249
  request: NextRequest;
174
- reason: "accept" | "agent" | "extension";
250
+ reason: "accept" | "extension";
175
251
  requestHeaders: Headers;
176
252
  }): NextResponse {
177
253
  const url = new URL(request.url);
178
254
  url.pathname =
179
255
  normalizePagePath(url.pathname) === "/"
180
- ? "/sitemap.md"
181
- : markdownRoutePath(url.pathname);
256
+ ? rootMarkdownSitemapPath(url)
257
+ : markdownRoutePath(url.pathname, reason);
182
258
  const revision = request.nextUrl.searchParams.get("publishos_revision");
183
259
  url.search = "";
184
260
  url.hash = "";
@@ -195,20 +271,25 @@ function rewriteToMarkdown({
195
271
  userAgent: request.headers.get("user-agent") ?? undefined,
196
272
  });
197
273
 
198
- return NextResponse.rewrite(url, {
274
+ const response = NextResponse.rewrite(url, {
199
275
  request: {
200
276
  headers: requestHeaders,
201
277
  },
202
278
  });
279
+ if (reason !== "extension") mergeVary(response, negotiationVary());
280
+ return response;
203
281
  }
204
282
 
205
283
  function withDiscoveryHeaders(
206
284
  response: NextResponse,
207
285
  pathname: string,
208
286
  ): NextResponse {
287
+ mergeVary(response, negotiationVary());
209
288
  const markdownUrl = markdownAlternatePath(pathname);
210
289
  const links = [
211
- `<${markdownUrl}>; rel="alternate"; type="text/markdown"`,
290
+ agentRouteConfig.markdownRoutes
291
+ ? `<${markdownUrl}>; rel="alternate"; type="text/markdown"`
292
+ : undefined,
212
293
  agentRouteConfig.discoveryLinks.llms
213
294
  ? `<${agentRouteConfig.discoveryLinks.llms}>; rel="llms-txt"; type="text/plain"`
214
295
  : undefined,
@@ -216,8 +297,9 @@ function withDiscoveryHeaders(
216
297
  ? `<${agentRouteConfig.discoveryLinks.sitemap}>; rel="alternate"; type="text/markdown"; title="Markdown sitemap"`
217
298
  : undefined,
218
299
  ].filter((link): link is string => Boolean(link));
219
- response.headers.set("link", links.join(", "));
220
- response.headers.set("x-publishos-markdown", markdownUrl);
300
+ if (links.length) response.headers.set("link", links.join(", "));
301
+ if (agentRouteConfig.markdownRoutes)
302
+ response.headers.set("x-publishos-markdown", markdownUrl);
221
303
  if (agentRouteConfig.discoveryLinks.llms) {
222
304
  response.headers.set(
223
305
  "x-publishos-llms",
@@ -283,10 +365,13 @@ export function proxy(request: NextRequest) {
283
365
  if (markdownReason) {
284
366
  let htmlPath: string | undefined;
285
367
  try {
286
- const decoded = normalizePagePath(decodeURIComponent(pathname));
287
- htmlPath = decoded.endsWith(".md")
288
- ? decoded.slice(0, -3) || "/"
289
- : decoded;
368
+ const decoded = normalizePagePath(decodeURIComponent(pathname)).normalize(
369
+ "NFC",
370
+ );
371
+ htmlPath =
372
+ markdownReason === "extension" && decoded.endsWith(".md")
373
+ ? decoded.slice(0, -3) || "/"
374
+ : decoded;
290
375
  } catch {
291
376
  htmlPath = undefined;
292
377
  }
@@ -296,7 +381,7 @@ export function proxy(request: NextRequest) {
296
381
  });
297
382
  const hasArtifact =
298
383
  htmlPath === "/"
299
- ? OUTPUT_PATHS.has("/sitemap.md")
384
+ ? OUTPUT_PATHS.has(rootMarkdownSitemapPath(new URL(request.url)))
300
385
  : htmlPath !== undefined && MARKDOWN_PATHS.has(htmlPath);
301
386
  if (!scope || !hasArtifact) {
302
387
  const response = createNotFoundTextResponse({
@@ -307,16 +392,7 @@ export function proxy(request: NextRequest) {
307
392
  markdownReason === "accept" ? negotiatedTextType(request) : undefined,
308
393
  vary: markdownReason !== "extension",
309
394
  });
310
- if (!agentRouteConfig.enabled || !agentRouteConfig.discoveryHeaders) {
311
- for (const name of [
312
- "link",
313
- "x-publishos-llms",
314
- "x-publishos-sitemap",
315
- ]) {
316
- response.headers.delete(name);
317
- }
318
- }
319
- return response;
395
+ return removeDisabledDiscoveryHeaders(response);
320
396
  }
321
397
  return rewriteToMarkdown({
322
398
  request,
@@ -327,7 +403,7 @@ export function proxy(request: NextRequest) {
327
403
 
328
404
  let pagePath: string;
329
405
  try {
330
- pagePath = normalizePagePath(decodeURIComponent(pathname));
406
+ pagePath = normalizePagePath(decodeURIComponent(pathname)).normalize("NFC");
331
407
  } catch {
332
408
  pagePath = pathname;
333
409
  }
@@ -337,6 +413,17 @@ export function proxy(request: NextRequest) {
337
413
  scopes: agentRouteConfig.notFoundScopes,
338
414
  pathname,
339
415
  });
416
+ if (negotiatedPlainNotFound(request)) {
417
+ return removeDisabledDiscoveryHeaders(
418
+ createNotFoundTextResponse({
419
+ scope,
420
+ pathname,
421
+ method: request.method,
422
+ contentType: "text/plain; charset=utf-8",
423
+ vary: true,
424
+ }),
425
+ );
426
+ }
340
427
  requestHeaders.set(NOT_FOUND_SCOPE_HEADER, scope?.id ?? "none");
341
428
  const url = new URL(request.url);
342
429
  url.pathname = "/_not-found";
@@ -365,6 +452,17 @@ export function proxy(request: NextRequest) {
365
452
  return response;
366
453
  }
367
454
 
455
+ if (
456
+ agentRouteConfig.enabled &&
457
+ TEXT_METHODS.has(request.method) &&
458
+ !isNextNavigationRequest(request) &&
459
+ !negotiatedTextType(request)
460
+ ) {
461
+ const response = new NextResponse(null, { status: 406 });
462
+ mergeVary(response, negotiationVary());
463
+ return response;
464
+ }
465
+
368
466
  if (!agentRouteConfig.enabled || !agentRouteConfig.discoveryHeaders) {
369
467
  debugAgentRoute("pass", {
370
468
  method: request.method,
@@ -373,7 +471,11 @@ export function proxy(request: NextRequest) {
373
471
  ? "discovery-disabled"
374
472
  : "agent-routes-disabled",
375
473
  });
376
- return NextResponse.next({ request: { headers: requestHeaders } });
474
+ const response = NextResponse.next({
475
+ request: { headers: requestHeaders },
476
+ });
477
+ mergeVary(response, negotiationVary());
478
+ return response;
377
479
  }
378
480
 
379
481
  debugAgentRoute("html", {
@@ -7,18 +7,18 @@ import {
7
7
  } from "./chunk-IL4RJOKI.js";
8
8
  import {
9
9
  prepareIdeSupport
10
- } from "./chunk-GBPLER5H.js";
10
+ } from "./chunk-3T4HVDSC.js";
11
11
  import "./chunk-6D2E6UMD.js";
12
12
  import {
13
13
  composeFrameworkSource
14
- } from "./chunk-OXOFRXEI.js";
14
+ } from "./chunk-NHSLTARU.js";
15
15
  import {
16
16
  validateLocalSource
17
- } from "./chunk-ORIUWJBQ.js";
17
+ } from "./chunk-SBMDONTV.js";
18
18
  import "./chunk-NNBJZPFM.js";
19
- import "./chunk-F3AGNDF4.js";
19
+ import "./chunk-DZ3VWEV5.js";
20
20
  import "./chunk-7NY22B5U.js";
21
- import "./chunk-UYGCOWRF.js";
21
+ import "./chunk-DX7PXFCM.js";
22
22
  import "./chunk-EFO6AWXN.js";
23
23
  import "./chunk-5KAD7W53.js";
24
24
  import "./chunk-WL75GQ5M.js";
@@ -5,14 +5,14 @@ import {
5
5
  } from "./chunk-6D2E6UMD.js";
6
6
  import {
7
7
  createIdeSourceArtifacts
8
- } from "./chunk-OXOFRXEI.js";
8
+ } from "./chunk-NHSLTARU.js";
9
9
  import {
10
10
  assertFrameworkSelection,
11
11
  readCheckoutTypeScriptConfig
12
12
  } from "./chunk-NNBJZPFM.js";
13
13
  import {
14
14
  supportedNextjsSourceImports
15
- } from "./chunk-UYGCOWRF.js";
15
+ } from "./chunk-DX7PXFCM.js";
16
16
  import {
17
17
  runtimePackageVersion
18
18
  } from "./chunk-AI2UULNX.js";