@caprail-dev/agent-pages 0.3.0 → 0.4.1
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 +7 -13
- package/dist/codegen.d.ts +1 -0
- package/dist/codegen.d.ts.map +1 -1
- package/dist/codegen.js +17 -7
- package/dist/codegen.js.map +1 -1
- package/dist/config.d.ts +2 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +6 -2
- package/dist/config.js.map +1 -1
- package/dist/core.d.ts +23 -22
- package/dist/core.d.ts.map +1 -1
- package/dist/core.js +22 -45
- package/dist/core.js.map +1 -1
- package/dist/frontmatter.d.ts +3 -0
- package/dist/frontmatter.d.ts.map +1 -1
- package/dist/frontmatter.js +1 -1
- package/dist/frontmatter.js.map +1 -1
- package/dist/mdx-twin.d.ts +14 -0
- package/dist/mdx-twin.d.ts.map +1 -0
- package/dist/mdx-twin.js +62 -0
- package/dist/mdx-twin.js.map +1 -0
- package/dist/next.d.ts +7 -0
- package/dist/next.d.ts.map +1 -1
- package/dist/next.js +36 -17
- package/dist/next.js.map +1 -1
- package/package.json +6 -5
package/README.md
CHANGED
|
@@ -1,21 +1,15 @@
|
|
|
1
1
|
# @caprail-dev/agent-pages
|
|
2
2
|
|
|
3
3
|
Markdown-first pages for AI agents in Next.js: co-locate a `page.md` next to
|
|
4
|
-
each `page.tsx` and serve it
|
|
4
|
+
each `page.tsx` and serve it via `Accept`-header content negotiation —
|
|
5
5
|
plus generated `/llms.txt` and `/llms-full.txt`.
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
crawlers/fetchers get markdown; search bots and agentic browsers keep
|
|
14
|
-
HTML (serving indexers different content is cloaking);
|
|
15
|
-
3. **`Signature-Agent` header** (RFC 9421) — signed agents get markdown even
|
|
16
|
-
with a browser-like UA;
|
|
17
|
-
4. **Heuristic fallback** — no `sec-fetch-mode` (real browsers always send
|
|
18
|
-
it) + a bot-like UA, except search/link-preview bots that need the HTML.
|
|
7
|
+
A `GET`/`HEAD` request is served the markdown twin when its `Accept` header
|
|
8
|
+
lists `text/markdown` with `q > 0` and at least as strongly as `text/html`
|
|
9
|
+
(a bare `*/*` is not a preference — browsers send it). Everything else gets
|
|
10
|
+
HTML. A negotiated response `Vary`s on `Accept` so caches key the two
|
|
11
|
+
representations separately. A direct `.md` URL (`/terms.md`) and the
|
|
12
|
+
`/llms.txt` / `/llms-full.txt` aggregates are served unconditionally.
|
|
19
13
|
|
|
20
14
|
## Install
|
|
21
15
|
|
package/dist/codegen.d.ts
CHANGED
package/dist/codegen.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"codegen.d.ts","sourceRoot":"","sources":["../src/codegen.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;
|
|
1
|
+
{"version":3,"file":"codegen.d.ts","sourceRoot":"","sources":["../src/codegen.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAcH,0EAA0E;AAC1E,MAAM,MAAM,QAAQ,GAAG;IACrB,2EAA2E;IAC3E,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,wEAAwE;IACxE,MAAM,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAC3C,2EAA2E;IAC3E,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,+DAA+D;IAC/D,MAAM,EAAE,MAAM,CAAC;IACf;;mCAE+B;IAC/B,IAAI,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC1B,SAAS,CAAC,EAAE,QAAQ,EAAE,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,kFAAkF;IAClF,IAAI,EAAE,KAAK,CAAC;QACV,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;QACxB,MAAM,EAAE,MAAM,CAAC;QACf,KAAK,EAAE,MAAM,CAAC;QACd,WAAW,EAAE,MAAM,CAAC;QACpB,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,CAAC,CAAC;IACH,gDAAgD;IAChD,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,4DAA4D;IAC5D,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,gEAAgE;IAChE,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB,CAAC;AAgMF,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,eAAe,GAAG,cAAc,CAiGxE"}
|
package/dist/codegen.js
CHANGED
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
import fs from "node:fs";
|
|
15
15
|
import path from "node:path";
|
|
16
16
|
import { parseFrontmatter } from "./frontmatter.js";
|
|
17
|
+
import { mdxToMarkdownTwin } from "./mdx-twin.js";
|
|
17
18
|
/** First line of every generated file — the overwrite/cleanup sentinel. */
|
|
18
19
|
const MARKER = "// @generated by @caprail-dev/agent-pages";
|
|
19
20
|
const HEADER = `${MARKER} — do not edit; regenerated on every \`next dev\`/\`next build\`.
|
|
@@ -35,10 +36,12 @@ function scan(appDir) {
|
|
|
35
36
|
const abs = path.join(dir, entry.name);
|
|
36
37
|
if (entry.isDirectory()) {
|
|
37
38
|
if (entry.name.includes("[")) {
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
39
|
+
for (const name of ["page.md", "page.mdx"]) {
|
|
40
|
+
const page = path.join(abs, name);
|
|
41
|
+
if (fs.existsSync(page)) {
|
|
42
|
+
console.warn(`[agent-pages] skipping ${rel(page)}: dynamic segments are unsupported in v1`);
|
|
43
|
+
skipped.push(rel(page));
|
|
44
|
+
}
|
|
42
45
|
}
|
|
43
46
|
continue;
|
|
44
47
|
}
|
|
@@ -60,7 +63,7 @@ function scan(appDir) {
|
|
|
60
63
|
path.basename(dir) === "llms-full.txt")) {
|
|
61
64
|
candidates.push(abs);
|
|
62
65
|
}
|
|
63
|
-
if (entry.name !== "page.md")
|
|
66
|
+
if (entry.name !== "page.md" && entry.name !== "page.mdx")
|
|
64
67
|
continue;
|
|
65
68
|
const htmlPath = "/" + segments.join("/");
|
|
66
69
|
const mdPath = htmlPath === "/" ? "/index.md" : `${htmlPath}.md`;
|
|
@@ -71,7 +74,10 @@ function scan(appDir) {
|
|
|
71
74
|
mdPath,
|
|
72
75
|
title: fm.title || mdPath,
|
|
73
76
|
description: fm.description,
|
|
74
|
-
|
|
77
|
+
// A page.mdx is the HTML page itself (compiled by @next/mdx); its
|
|
78
|
+
// markdown twin is derived by stripping ESM/JSX.
|
|
79
|
+
markdown: entry.name === "page.mdx" ? mdxToMarkdownTwin(fm, rel(abs)) : fm.body,
|
|
80
|
+
publishedAt: fm.fields.publishedAt,
|
|
75
81
|
});
|
|
76
82
|
}
|
|
77
83
|
};
|
|
@@ -125,6 +131,9 @@ function manifestModule(siteUrl, intro, docs) {
|
|
|
125
131
|
fit(" ", "title:", quote(d.title), ","),
|
|
126
132
|
fit(" ", "description:", quote(d.description), ","),
|
|
127
133
|
fit(" ", "markdown:", d.importedAs ?? quote(d.body ?? ""), ","),
|
|
134
|
+
...(d.publishedAt
|
|
135
|
+
? [fit(" ", "publishedAt:", JSON.stringify(d.publishedAt), ",")]
|
|
136
|
+
: []),
|
|
128
137
|
" },",
|
|
129
138
|
];
|
|
130
139
|
return lines.join("\n");
|
|
@@ -227,9 +236,10 @@ export function generateAgentPages(opts) {
|
|
|
227
236
|
}
|
|
228
237
|
}
|
|
229
238
|
return {
|
|
230
|
-
docs: docs.map(({ htmlPath, mdPath, title, description }) => ({
|
|
239
|
+
docs: docs.map(({ htmlPath, mdPath, title, description, publishedAt }) => ({
|
|
231
240
|
htmlPath,
|
|
232
241
|
mdPath,
|
|
242
|
+
publishedAt,
|
|
233
243
|
title,
|
|
234
244
|
description,
|
|
235
245
|
})),
|
package/dist/codegen.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"codegen.js","sourceRoot":"","sources":["../src/codegen.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"codegen.js","sourceRoot":"","sources":["../src/codegen.ts"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* `next.config.js` wrapper: runs codegen when the config is evaluated (every
|
|
3
3
|
* `next dev` start and `next build` — plain Node, no bundler hooks, so it is
|
|
4
|
-
* Turbopack-safe by construction) and, in dev, watches for `page.md`
|
|
4
|
+
* Turbopack-safe by construction) and, in dev, watches for `page.md`/`page.mdx`
|
|
5
|
+
* changes.
|
|
5
6
|
*
|
|
6
7
|
* Note for fresh clones: this module is consumed from the package's compiled
|
|
7
8
|
* `dist/` — build the package before running bare `next dev`/`next build`.
|
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAMH,OAAO,EAEL,KAAK,QAAQ,EAEd,MAAM,cAAc,CAAC;AAEtB,MAAM,MAAM,iBAAiB,GAAG;IAC9B,kFAAkF;IAClF,OAAO,EAAE,MAAM,CAAC;IAChB,8EAA8E;IAC9E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;2DACuD;IACvD,IAAI,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC1B,SAAS,CAAC,EAAE,QAAQ,EAAE,CAAC;CACxB,CAAC;AAYF;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,CAAC,SAAS,MAAM,EAC7C,UAAU,EAAE,CAAC,EACb,IAAI,EAAE,iBAAiB,GACtB,CAAC,CA6CH"}
|
package/dist/config.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* `next.config.js` wrapper: runs codegen when the config is evaluated (every
|
|
3
3
|
* `next dev` start and `next build` — plain Node, no bundler hooks, so it is
|
|
4
|
-
* Turbopack-safe by construction) and, in dev, watches for `page.md`
|
|
4
|
+
* Turbopack-safe by construction) and, in dev, watches for `page.md`/`page.mdx`
|
|
5
|
+
* changes.
|
|
5
6
|
*
|
|
6
7
|
* Note for fresh clones: this module is consumed from the package's compiled
|
|
7
8
|
* `dist/` — build the package before running bare `next dev`/`next build`.
|
|
@@ -39,8 +40,11 @@ export function withAgentPages(nextConfig, opts) {
|
|
|
39
40
|
slots[WATCHER_KEY] = true;
|
|
40
41
|
let timer;
|
|
41
42
|
const watcher = fs.watch(appDir, { recursive: true }, (_event, filename) => {
|
|
42
|
-
if (!filename ||
|
|
43
|
+
if (!filename ||
|
|
44
|
+
(path.basename(filename) !== "page.md" &&
|
|
45
|
+
path.basename(filename) !== "page.mdx")) {
|
|
43
46
|
return;
|
|
47
|
+
}
|
|
44
48
|
clearTimeout(timer);
|
|
45
49
|
timer = setTimeout(() => {
|
|
46
50
|
try {
|
package/dist/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEvD,OAAO,EACL,kBAAkB,GAGnB,MAAM,cAAc,CAAC;AAatB,iFAAiF;AACjF,MAAM,WAAW,GAAG,MAAM,CAAC,GAAG,CAAC,kCAAkC,CAAC,CAAC;AAEnE,SAAS,MAAM,CAAC,MAAsB;IACpC,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,OAAO;QAAE,OAAO,CAAC,GAAG,CAAC,uBAAuB,IAAI,EAAE,CAAC,CAAC;IAC9E,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;QAClC,OAAO,CAAC,GAAG,CAAC,yBAAyB,IAAI,EAAE,CAAC,CAAC;IAC/C,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAC5B,UAAa,EACb,IAAuB;IAEvB,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IAC7E,MAAM,GAAG,GAAG,GAAG,EAAE,CACf,kBAAkB,CAAC;QACjB,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,MAAM;QACN,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,SAAS,EAAE,IAAI,CAAC,SAAS;KAC1B,CAAC,CAAC;IAEL,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC;IAEd,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,aAAa,EAAE,CAAC;QAC3C,MAAM,KAAK,GAAG,UAAqC,CAAC;QACpD,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,EAAE,CAAC;YACxB,KAAK,CAAC,WAAW,CAAC,GAAG,IAAI,CAAC;YAC1B,IAAI,KAAiC,CAAC;YACtC,MAAM,OAAO,GAAG,EAAE,CAAC,KAAK,CACtB,MAAM,EACN,EAAE,SAAS,EAAE,IAAI,EAAE,EACnB,CAAC,MAAM,EAAE,QAAQ,EAAE,EAAE;gBACnB,IACE,CAAC,QAAQ;oBACT,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,KAAK,SAAS;wBACpC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,KAAK,UAAU,CAAC,EACzC,CAAC;oBACD,OAAO;gBACT,CAAC;gBACD,YAAY,CAAC,KAAK,CAAC,CAAC;gBACpB,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;oBACtB,IAAI,CAAC;wBACH,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC;oBAChB,CAAC;oBAAC,OAAO,GAAG,EAAE,CAAC;wBACb,oEAAoE;wBACpE,OAAO,CAAC,KAAK,CAAC,+BAA+B,EAAE,GAAG,CAAC,CAAC;oBACtD,CAAC;gBACH,CAAC,EAAE,GAAG,CAAC,CAAC;gBACR,KAAK,CAAC,KAAK,EAAE,CAAC;YAChB,CAAC,CACF,CAAC;YACF,OAAO,CAAC,KAAK,EAAE,CAAC;QAClB,CAAC;IACH,CAAC;IAED,OAAO,UAAU,CAAC;AACpB,CAAC"}
|
package/dist/core.d.ts
CHANGED
|
@@ -19,27 +19,13 @@ export declare function prefersMarkdown(accept: string | null): boolean;
|
|
|
19
19
|
export type MarkdownRequest = {
|
|
20
20
|
method: string;
|
|
21
21
|
accept: string | null;
|
|
22
|
-
userAgent: string | null;
|
|
23
|
-
signatureAgent?: string | null;
|
|
24
|
-
secFetchMode?: string | null;
|
|
25
22
|
};
|
|
26
23
|
/**
|
|
27
24
|
* Whether this client should be served markdown instead of HTML (path-agnostic
|
|
28
|
-
* — the caller decides the page has a markdown twin). Markdown wins when
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
* 2. the UA classifies as an AI crawler/fetcher — the consumers that want
|
|
33
|
-
* markdown. `search` engines (Googlebot, Bingbot, OAI-SearchBot, …) are
|
|
34
|
-
* excluded on purpose: serving indexers different content than humans is
|
|
35
|
-
* cloaking. `browser` agents (ChatGPT Agent / Atlas) render real pages,
|
|
36
|
-
* so they get HTML too — both verdicts are final and skip the heuristics;
|
|
37
|
-
* 3. the request carries a `Signature-Agent` header (RFC 9421) — AI agents
|
|
38
|
-
* that sign their requests (e.g. ChatGPT's) identify themselves this way
|
|
39
|
-
* even when their UA looks like a plain browser;
|
|
40
|
-
* 4. heuristic fallback for agents our classifier doesn't know yet: no
|
|
41
|
-
* `sec-fetch-mode` header (real browsers always send it) and a bot-like
|
|
42
|
-
* UA — except search/preview bots that need the HTML (see NEEDS_HTML).
|
|
25
|
+
* — the caller decides the page has a markdown twin). Markdown wins when the
|
|
26
|
+
* client asks for it: a `GET`/`HEAD` whose `Accept` header lists `text/markdown`
|
|
27
|
+
* at least as strongly as HTML (see `prefersMarkdown`). Everything else — every
|
|
28
|
+
* UA, signed or not — gets HTML.
|
|
43
29
|
*/
|
|
44
30
|
export declare function clientWantsMarkdown(input: MarkdownRequest): boolean;
|
|
45
31
|
/**
|
|
@@ -52,11 +38,12 @@ export declare function resolveMarkdownRewrite(input: MarkdownRequest & {
|
|
|
52
38
|
pathname: string;
|
|
53
39
|
}, rewrites: MarkdownRewrites): string | null;
|
|
54
40
|
/**
|
|
55
|
-
* The negotiation
|
|
56
|
-
*
|
|
57
|
-
*
|
|
41
|
+
* The negotiation header every markdown-negotiated response varies on — set on
|
|
42
|
+
* both the rewritten and the HTML branch of a negotiated path so non-Vercel
|
|
43
|
+
* intermediaries cache the two representations separately. Negotiation keys
|
|
44
|
+
* solely off `Accept`.
|
|
58
45
|
*/
|
|
59
|
-
export declare const AGENT_PAGES_VARY = "Accept
|
|
46
|
+
export declare const AGENT_PAGES_VARY = "Accept";
|
|
60
47
|
/** One agent-readable doc — drives the rewrite map, llms.txt, and routes. */
|
|
61
48
|
export type AgentDoc = {
|
|
62
49
|
/** The HTML page this doc twins, or null when the doc is markdown-only. */
|
|
@@ -67,7 +54,21 @@ export type AgentDoc = {
|
|
|
67
54
|
/** One-liner for the `/llms.txt` link list ("" when none was provided). */
|
|
68
55
|
description: string;
|
|
69
56
|
markdown: string;
|
|
57
|
+
/**
|
|
58
|
+
* Publication date (`YYYY-MM-DD`) from frontmatter, when the source carried
|
|
59
|
+
* one. Docs dated in the future are withheld from agent surfaces until their
|
|
60
|
+
* date arrives (see `isPublished`); undated docs are always served.
|
|
61
|
+
*/
|
|
62
|
+
publishedAt?: string;
|
|
70
63
|
};
|
|
64
|
+
/** Today's date as `YYYY-MM-DD` in UTC — the cutoff for `isPublished`. */
|
|
65
|
+
export declare function todayUtc(now?: Date): string;
|
|
66
|
+
/**
|
|
67
|
+
* Whether a doc dated `publishedAt` is visible as of `today` (both `YYYY-MM-DD`,
|
|
68
|
+
* UTC). Undated docs are always visible; a future date is withheld until it
|
|
69
|
+
* arrives. String comparison is correct for the fixed-width ISO date format.
|
|
70
|
+
*/
|
|
71
|
+
export declare function isPublished(publishedAt: string | undefined, today: string): boolean;
|
|
71
72
|
/** `/llms.txt` index per the llmstxt.org convention. */
|
|
72
73
|
export declare function llmsTxt(opts: {
|
|
73
74
|
siteUrl: string;
|
package/dist/core.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../src/core.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;
|
|
1
|
+
{"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../src/core.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,sEAAsE;AACtE,MAAM,MAAM,gBAAgB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAEtD;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CA4B9D;AAED,2EAA2E;AAC3E,MAAM,MAAM,eAAe,GAAG;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB,CAAC;AAEF;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAInE;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,eAAe,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,EAC7C,QAAQ,EAAE,gBAAgB,GACzB,MAAM,GAAG,IAAI,CAQf;AAED;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,WAAW,CAAC;AAEzC,6EAA6E;AAC7E,MAAM,MAAM,QAAQ,GAAG;IACrB,2EAA2E;IAC3E,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,oCAAoC;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,2EAA2E;IAC3E,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,0EAA0E;AAC1E,wBAAgB,QAAQ,CAAC,GAAG,GAAE,IAAiB,GAAG,MAAM,CAEvD;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CACzB,WAAW,EAAE,MAAM,GAAG,SAAS,EAC/B,KAAK,EAAE,MAAM,GACZ,OAAO,CAET;AAED,wDAAwD;AACxD,wBAAgB,OAAO,CAAC,IAAI,EAAE;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,4EAA4E;IAC5E,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,SAAS,QAAQ,EAAE,CAAC;CAC3B,GAAG,MAAM,CAQT;AAED,mEAAmE;AACnE,wBAAgB,WAAW,CAAC,IAAI,EAAE,SAAS,QAAQ,EAAE,GAAG,MAAM,CAE7D;AAED,0DAA0D;AAC1D,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,CAOvD"}
|
package/dist/core.js
CHANGED
|
@@ -6,7 +6,6 @@
|
|
|
6
6
|
* Pure and edge-safe — no request objects, no Node APIs, just primitives —
|
|
7
7
|
* so it is unit-testable and runs unchanged in the Edge runtime.
|
|
8
8
|
*/
|
|
9
|
-
import { classify } from "@caprail-dev/analytics";
|
|
10
9
|
/**
|
|
11
10
|
* Whether the `Accept` header asks for markdown at least as strongly as HTML.
|
|
12
11
|
* Minimal q-value parse: `text/markdown` must be listed explicitly (a bare
|
|
@@ -42,52 +41,17 @@ export function prefersMarkdown(accept) {
|
|
|
42
41
|
}
|
|
43
42
|
return qMd !== null && qMd > 0 && qMd >= qHtml;
|
|
44
43
|
}
|
|
45
|
-
/**
|
|
46
|
-
* Bot-like UA pattern for the heuristic fallback: generic bot vocabulary plus
|
|
47
|
-
* the HTTP client libraries agent frameworks ride on. Deliberately loose —
|
|
48
|
-
* it only fires when `sec-fetch-mode` is also absent, and serving markdown
|
|
49
|
-
* to a misjudged non-AI bot is low-harm.
|
|
50
|
-
*/
|
|
51
|
-
const BOT_LIKE = /bot|crawler|spider|scraper|python-requests|python-httpx|aiohttp|go-http-client|node-fetch|axios|libwww/i;
|
|
52
|
-
/**
|
|
53
|
-
* Bot-like UAs that must keep getting HTML: search indexers our classifier
|
|
54
|
-
* doesn't know (serving them markdown is cloaking) and link-preview bots
|
|
55
|
-
* that read OpenGraph tags from the HTML head.
|
|
56
|
-
*/
|
|
57
|
-
const NEEDS_HTML = /yandex|baidu|duckduckbot|applebot|seznambot|naver|sogou|petalbot|msnbot|slackbot|twitterbot|facebookexternalhit|facebot|discordbot|linkedinbot|whatsapp|telegrambot|pinterest|skypeuripreview|embedly|redditbot/i;
|
|
58
44
|
/**
|
|
59
45
|
* Whether this client should be served markdown instead of HTML (path-agnostic
|
|
60
|
-
* — the caller decides the page has a markdown twin). Markdown wins when
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
* 2. the UA classifies as an AI crawler/fetcher — the consumers that want
|
|
65
|
-
* markdown. `search` engines (Googlebot, Bingbot, OAI-SearchBot, …) are
|
|
66
|
-
* excluded on purpose: serving indexers different content than humans is
|
|
67
|
-
* cloaking. `browser` agents (ChatGPT Agent / Atlas) render real pages,
|
|
68
|
-
* so they get HTML too — both verdicts are final and skip the heuristics;
|
|
69
|
-
* 3. the request carries a `Signature-Agent` header (RFC 9421) — AI agents
|
|
70
|
-
* that sign their requests (e.g. ChatGPT's) identify themselves this way
|
|
71
|
-
* even when their UA looks like a plain browser;
|
|
72
|
-
* 4. heuristic fallback for agents our classifier doesn't know yet: no
|
|
73
|
-
* `sec-fetch-mode` header (real browsers always send it) and a bot-like
|
|
74
|
-
* UA — except search/preview bots that need the HTML (see NEEDS_HTML).
|
|
46
|
+
* — the caller decides the page has a markdown twin). Markdown wins when the
|
|
47
|
+
* client asks for it: a `GET`/`HEAD` whose `Accept` header lists `text/markdown`
|
|
48
|
+
* at least as strongly as HTML (see `prefersMarkdown`). Everything else — every
|
|
49
|
+
* UA, signed or not — gets HTML.
|
|
75
50
|
*/
|
|
76
51
|
export function clientWantsMarkdown(input) {
|
|
77
52
|
if (input.method !== "GET" && input.method !== "HEAD")
|
|
78
53
|
return false;
|
|
79
|
-
|
|
80
|
-
return true;
|
|
81
|
-
const agent = classify(input.userAgent);
|
|
82
|
-
if (agent.isAgent) {
|
|
83
|
-
return agent.type === "fetcher" || agent.type === "crawler";
|
|
84
|
-
}
|
|
85
|
-
if (input.signatureAgent)
|
|
86
|
-
return true;
|
|
87
|
-
return (!input.secFetchMode &&
|
|
88
|
-
!!input.userAgent &&
|
|
89
|
-
BOT_LIKE.test(input.userAgent) &&
|
|
90
|
-
!NEEDS_HTML.test(input.userAgent));
|
|
54
|
+
return prefersMarkdown(input.accept);
|
|
91
55
|
}
|
|
92
56
|
/**
|
|
93
57
|
* Resolve the markdown rewrite target for a request, or null to serve the page
|
|
@@ -106,11 +70,24 @@ export function resolveMarkdownRewrite(input, rewrites) {
|
|
|
106
70
|
return clientWantsMarkdown(input) ? target : null;
|
|
107
71
|
}
|
|
108
72
|
/**
|
|
109
|
-
* The negotiation
|
|
110
|
-
*
|
|
111
|
-
*
|
|
73
|
+
* The negotiation header every markdown-negotiated response varies on — set on
|
|
74
|
+
* both the rewritten and the HTML branch of a negotiated path so non-Vercel
|
|
75
|
+
* intermediaries cache the two representations separately. Negotiation keys
|
|
76
|
+
* solely off `Accept`.
|
|
112
77
|
*/
|
|
113
|
-
export const AGENT_PAGES_VARY = "Accept
|
|
78
|
+
export const AGENT_PAGES_VARY = "Accept";
|
|
79
|
+
/** Today's date as `YYYY-MM-DD` in UTC — the cutoff for `isPublished`. */
|
|
80
|
+
export function todayUtc(now = new Date()) {
|
|
81
|
+
return now.toISOString().slice(0, 10);
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Whether a doc dated `publishedAt` is visible as of `today` (both `YYYY-MM-DD`,
|
|
85
|
+
* UTC). Undated docs are always visible; a future date is withheld until it
|
|
86
|
+
* arrives. String comparison is correct for the fixed-width ISO date format.
|
|
87
|
+
*/
|
|
88
|
+
export function isPublished(publishedAt, today) {
|
|
89
|
+
return !publishedAt || publishedAt <= today;
|
|
90
|
+
}
|
|
114
91
|
/** `/llms.txt` index per the llmstxt.org convention. */
|
|
115
92
|
export function llmsTxt(opts) {
|
|
116
93
|
const links = opts.docs
|
package/dist/core.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"core.js","sourceRoot":"","sources":["../src/core.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;
|
|
1
|
+
{"version":3,"file":"core.js","sourceRoot":"","sources":["../src/core.ts"],"names":[],"mappings":"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"}
|
package/dist/frontmatter.d.ts
CHANGED
|
@@ -9,6 +9,9 @@ export type Frontmatter = {
|
|
|
9
9
|
description: string;
|
|
10
10
|
/** The markdown with the frontmatter block (and leading blank lines) stripped. */
|
|
11
11
|
body: string;
|
|
12
|
+
/** Every raw `key: value` pair from the block — extra keys (e.g. a blog's
|
|
13
|
+
* `publishedAt`, `tags`) are the caller's to interpret. */
|
|
14
|
+
fields: Record<string, string>;
|
|
12
15
|
};
|
|
13
16
|
/**
|
|
14
17
|
* Parse a `page.md` file. Frontmatter is only recognized when the first line
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"frontmatter.d.ts","sourceRoot":"","sources":["../src/frontmatter.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,MAAM,WAAW,GAAG;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,kFAAkF;IAClF,IAAI,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"frontmatter.d.ts","sourceRoot":"","sources":["../src/frontmatter.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,MAAM,WAAW,GAAG;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,kFAAkF;IAClF,IAAI,EAAE,MAAM,CAAC;IACb;+DAC2D;IAC3D,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAChC,CAAC;AAcF;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,WAAW,CAwC7E"}
|
package/dist/frontmatter.js
CHANGED
|
@@ -53,6 +53,6 @@ export function parseFrontmatter(raw, sourcePath) {
|
|
|
53
53
|
if (!description) {
|
|
54
54
|
console.warn(`[agent-pages] ${sourcePath}: no "description" frontmatter — its /llms.txt entry will have no summary`);
|
|
55
55
|
}
|
|
56
|
-
return { title, description, body };
|
|
56
|
+
return { title, description, body, fields };
|
|
57
57
|
}
|
|
58
58
|
//# sourceMappingURL=frontmatter.js.map
|
package/dist/frontmatter.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"frontmatter.js","sourceRoot":"","sources":["../src/frontmatter.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;
|
|
1
|
+
{"version":3,"file":"frontmatter.js","sourceRoot":"","sources":["../src/frontmatter.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAYH,+EAA+E;AAC/E,SAAS,OAAO,CAAC,KAAa;IAC5B,IACE,KAAK,CAAC,MAAM,IAAI,CAAC;QACjB,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;QAChD,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAE,CAAC,EACzB,CAAC;QACD,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC5B,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,gBAAgB,CAAC,GAAW,EAAE,UAAkB;IAC9D,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACjC,MAAM,MAAM,GAA2B,EAAE,CAAC;IAC1C,IAAI,IAAI,GAAG,GAAG,CAAC;IAEf,IAAI,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,KAAK,EAAE,CAAC;QAC/B,MAAM,GAAG,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,IAAI,EAAE,KAAK,KAAK,CAAC,CAAC;QACzE,IAAI,GAAG,GAAG,CAAC,EAAE,CAAC;YACZ,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC;gBACvC,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;gBAChC,IAAI,KAAK,KAAK,CAAC,CAAC;oBAAE,SAAS;gBAC3B,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC;gBACxC,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;gBACpD,IAAI,GAAG;oBAAE,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;YAC/B,CAAC;YACD,IAAI,GAAG,KAAK;iBACT,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC;iBACd,IAAI,CAAC,IAAI,CAAC;iBACV,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QACzB,CAAC;IACH,CAAC;IAED,IAAI,KAAK,GAAG,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC;IAC/B,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,KAAK,GAAG,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;QAClD,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,CAAC,IAAI,CACV,iBAAiB,UAAU,wEAAwE,CACpG,CAAC;QACJ,CAAC;IACH,CAAC;IAED,MAAM,WAAW,GAAG,MAAM,CAAC,WAAW,IAAI,EAAE,CAAC;IAC7C,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,OAAO,CAAC,IAAI,CACV,iBAAiB,UAAU,2EAA2E,CACvG,CAAC;IACJ,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;AAC9C,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Derive a plain-markdown twin from a `page.mdx` body. Zero deps, line-based:
|
|
3
|
+
* MDX is markdown plus ESM statements, JSX components, and `{expressions}` —
|
|
4
|
+
* the twin strips the first two and keeps everything else verbatim.
|
|
5
|
+
*
|
|
6
|
+
* Authoring convention this relies on (enforced here only loosely): components
|
|
7
|
+
* are presentational extras written as blank-line-delimited blocks with no
|
|
8
|
+
* internal blank lines, and the prose must stand alone without them. A JSX
|
|
9
|
+
* block that violates this leaves fragments in the twin — the codegen tests
|
|
10
|
+
* pin the supported shapes.
|
|
11
|
+
*/
|
|
12
|
+
import type { Frontmatter } from "./frontmatter.js";
|
|
13
|
+
export declare function mdxToMarkdownTwin(fm: Frontmatter, sourcePath: string): string;
|
|
14
|
+
//# sourceMappingURL=mdx-twin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mdx-twin.d.ts","sourceRoot":"","sources":["../src/mdx-twin.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AASpD,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CA+C7E"}
|
package/dist/mdx-twin.js
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Derive a plain-markdown twin from a `page.mdx` body. Zero deps, line-based:
|
|
3
|
+
* MDX is markdown plus ESM statements, JSX components, and `{expressions}` —
|
|
4
|
+
* the twin strips the first two and keeps everything else verbatim.
|
|
5
|
+
*
|
|
6
|
+
* Authoring convention this relies on (enforced here only loosely): components
|
|
7
|
+
* are presentational extras written as blank-line-delimited blocks with no
|
|
8
|
+
* internal blank lines, and the prose must stand alone without them. A JSX
|
|
9
|
+
* block that violates this leaves fragments in the twin — the codegen tests
|
|
10
|
+
* pin the supported shapes.
|
|
11
|
+
*/
|
|
12
|
+
const FENCE = /^(```|~~~)/;
|
|
13
|
+
const ESM_START = /^(import|export)\s/;
|
|
14
|
+
/** JSX flow block: an uppercase component tag opening at column 0. */
|
|
15
|
+
const JSX_START = /^<[A-Z]/;
|
|
16
|
+
/** Inline component tags — strip the tag, keep any children text. */
|
|
17
|
+
const INLINE_TAG = /<\/?[A-Z][\w.]*(\s[^>]*)?\/?>/g;
|
|
18
|
+
export function mdxToMarkdownTwin(fm, sourcePath) {
|
|
19
|
+
const lines = fm.body.split("\n");
|
|
20
|
+
const kept = [];
|
|
21
|
+
let inFence = false;
|
|
22
|
+
let skipUntilBlank = false;
|
|
23
|
+
for (const line of lines) {
|
|
24
|
+
if (inFence) {
|
|
25
|
+
kept.push(line);
|
|
26
|
+
if (FENCE.test(line))
|
|
27
|
+
inFence = false;
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
if (skipUntilBlank) {
|
|
31
|
+
if (line.trim() === "")
|
|
32
|
+
skipUntilBlank = false;
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
if (FENCE.test(line)) {
|
|
36
|
+
inFence = true;
|
|
37
|
+
kept.push(line);
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
if (ESM_START.test(line) || JSX_START.test(line)) {
|
|
41
|
+
skipUntilBlank = true;
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
kept.push(line.replace(INLINE_TAG, ""));
|
|
45
|
+
}
|
|
46
|
+
const body = kept
|
|
47
|
+
.join("\n")
|
|
48
|
+
.replace(/\n{3,}/g, "\n\n")
|
|
49
|
+
.replace(/^\n+/, "")
|
|
50
|
+
.replace(/\n+$/, "\n");
|
|
51
|
+
const publishedAt = fm.fields.publishedAt ?? "";
|
|
52
|
+
if (!publishedAt) {
|
|
53
|
+
throw new Error(`[agent-pages] ${sourcePath}: page.mdx needs a "publishedAt" frontmatter field (YYYY-MM-DD)`);
|
|
54
|
+
}
|
|
55
|
+
const tags = fm.fields.tags ?? "";
|
|
56
|
+
const meta = `_${publishedAt}${tags ? ` · ${tags}` : ""}_`;
|
|
57
|
+
// Posts do not write their own H1 (the HTML page renders one from the
|
|
58
|
+
// frontmatter); synthesize it here — unless the body defensively has one.
|
|
59
|
+
const heading = body.startsWith("# ") ? "" : `# ${fm.title}\n\n`;
|
|
60
|
+
return `${heading}${meta}\n\n${body}`;
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=mdx-twin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mdx-twin.js","sourceRoot":"","sources":["../src/mdx-twin.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,MAAM,KAAK,GAAG,YAAY,CAAC;AAC3B,MAAM,SAAS,GAAG,oBAAoB,CAAC;AACvC,sEAAsE;AACtE,MAAM,SAAS,GAAG,SAAS,CAAC;AAC5B,qEAAqE;AACrE,MAAM,UAAU,GAAG,gCAAgC,CAAC;AAEpD,MAAM,UAAU,iBAAiB,CAAC,EAAe,EAAE,UAAkB;IACnE,MAAM,KAAK,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAClC,MAAM,IAAI,GAAa,EAAE,CAAC;IAC1B,IAAI,OAAO,GAAG,KAAK,CAAC;IACpB,IAAI,cAAc,GAAG,KAAK,CAAC;IAE3B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,OAAO,EAAE,CAAC;YACZ,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAChB,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC;gBAAE,OAAO,GAAG,KAAK,CAAC;YACtC,SAAS;QACX,CAAC;QACD,IAAI,cAAc,EAAE,CAAC;YACnB,IAAI,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE;gBAAE,cAAc,GAAG,KAAK,CAAC;YAC/C,SAAS;QACX,CAAC;QACD,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YACrB,OAAO,GAAG,IAAI,CAAC;YACf,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAChB,SAAS;QACX,CAAC;QACD,IAAI,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YACjD,cAAc,GAAG,IAAI,CAAC;YACtB,SAAS;QACX,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,CAAC;IAC1C,CAAC;IAED,MAAM,IAAI,GAAG,IAAI;SACd,IAAI,CAAC,IAAI,CAAC;SACV,OAAO,CAAC,SAAS,EAAE,MAAM,CAAC;SAC1B,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;SACnB,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAEzB,MAAM,WAAW,GAAG,EAAE,CAAC,MAAM,CAAC,WAAW,IAAI,EAAE,CAAC;IAChD,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CACb,iBAAiB,UAAU,iEAAiE,CAC7F,CAAC;IACJ,CAAC;IACD,MAAM,IAAI,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;IAClC,MAAM,IAAI,GAAG,IAAI,WAAW,GAAG,IAAI,CAAC,CAAC,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC;IAE3D,sEAAsE;IACtE,0EAA0E;IAC1E,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,KAAK,MAAM,CAAC;IACjE,OAAO,GAAG,OAAO,GAAG,IAAI,OAAO,IAAI,EAAE,CAAC;AACxC,CAAC"}
|
package/dist/next.d.ts
CHANGED
|
@@ -39,9 +39,16 @@ export type LlmsOption = {
|
|
|
39
39
|
* - an HTML page whose twin the client wants as markdown → the twin's markdown;
|
|
40
40
|
* - anything else → HTML (with `negotiated` set when a twin exists, so the
|
|
41
41
|
* caller can add `Vary`).
|
|
42
|
+
*
|
|
43
|
+
* Docs with a future `publishedAt` are withheld from every agent surface
|
|
44
|
+
* (llms.txt, llms-full.txt, direct `.md`, and negotiated twins) until their
|
|
45
|
+
* date arrives. The cutoff is `opts.today` (default: today in UTC), evaluated
|
|
46
|
+
* by the caller per request, so a scheduled doc reveals itself on its date
|
|
47
|
+
* without a rebuild. Undated docs are always served.
|
|
42
48
|
*/
|
|
43
49
|
export declare function decideAgentPages(req: NextRequest, docs: readonly AgentDoc[], opts?: {
|
|
44
50
|
llms?: LlmsOption;
|
|
51
|
+
today?: string;
|
|
45
52
|
}): AgentPagesDecision;
|
|
46
53
|
/**
|
|
47
54
|
* Build the markdown `Response` for a `kind: "markdown"` decision, with `Vary`
|
package/dist/next.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"next.d.ts","sourceRoot":"","sources":["../src/next.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,
|
|
1
|
+
{"version":3,"file":"next.d.ts","sourceRoot":"","sources":["../src/next.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,KAAK,cAAc,EAAE,MAAM,aAAa,CAAC;AAE7E,OAAO,EAQL,KAAK,QAAQ,EACd,MAAM,WAAW,CAAC;AAEnB,MAAM,MAAM,kBAAkB,GAC1B;IACE,IAAI,EAAE,UAAU,CAAC;IACjB,oEAAoE;IACpE,MAAM,EAAE,MAAM,CAAC;IACf,0EAA0E;IAC1E,IAAI,EAAE,MAAM,CAAC;IACb,wEAAwE;IACxE,UAAU,EAAE,OAAO,CAAC;CACrB,GACD;IACE,IAAI,EAAE,MAAM,CAAC;IACb,yEAAyE;IACzE,UAAU,EAAE,OAAO,CAAC;CACrB,CAAC;AAEN,4EAA4E;AAC5E,MAAM,MAAM,UAAU,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,KAAK,CAAC;AAEpE;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,WAAW,EAChB,IAAI,EAAE,SAAS,QAAQ,EAAE,EACzB,IAAI,CAAC,EAAE;IAAE,IAAI,CAAC,EAAE,UAAU,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GAC3C,kBAAkB,CAwDpB;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,OAAO,CAAC,kBAAkB,EAAE;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,CAAC,GAC1D,QAAQ,CAIV;AAED;;;;;;GAMG;AACH,MAAM,MAAM,kBAAkB,GAAG,CAC/B,GAAG,EAAE,WAAW,EAChB,EAAE,EAAE,cAAc,KACf,OAAO,CAAC;AAEb;;;;;;GAMG;AACH,MAAM,MAAM,wBAAwB,GAAG,CACrC,GAAG,EAAE,WAAW,EAChB,EAAE,EAAE,cAAc,KACf,QAAQ,GAAG,YAAY,CAAC;AAE7B;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,0BAA0B,CAAC,IAAI,EAAE;IAC/C,IAAI,EAAE,SAAS,QAAQ,EAAE,CAAC;IAC1B,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,OAAO,CAAC,EAAE,kBAAkB,GAAG,SAAS,kBAAkB,EAAE,CAAC;IAC7D,IAAI,CAAC,EAAE,wBAAwB,CAAC;CACjC,IASS,KAAK,WAAW,EAAE,IAAI,cAAc,KAAG,QAAQ,GAAG,YAAY,CAkCvE"}
|
package/dist/next.js
CHANGED
|
@@ -11,8 +11,8 @@
|
|
|
11
11
|
* fly. The middleware therefore imports the manifest content; keep doc sets
|
|
12
12
|
* reasonable (this is the trade for "author only `page.md`, no route files").
|
|
13
13
|
*/
|
|
14
|
-
import { NextRequest, NextResponse
|
|
15
|
-
import { AGENT_PAGES_VARY, clientWantsMarkdown, llmsFullTxt, llmsTxt, markdownResponse, } from "./core.js";
|
|
14
|
+
import { NextRequest, NextResponse } from "next/server";
|
|
15
|
+
import { AGENT_PAGES_VARY, clientWantsMarkdown, isPublished, llmsFullTxt, llmsTxt, markdownResponse, todayUtc, } from "./core.js";
|
|
16
16
|
/**
|
|
17
17
|
* Decide what to serve for a request, sourcing content from the manifest docs:
|
|
18
18
|
*
|
|
@@ -21,17 +21,25 @@ import { AGENT_PAGES_VARY, clientWantsMarkdown, llmsFullTxt, llmsTxt, markdownRe
|
|
|
21
21
|
* - an HTML page whose twin the client wants as markdown → the twin's markdown;
|
|
22
22
|
* - anything else → HTML (with `negotiated` set when a twin exists, so the
|
|
23
23
|
* caller can add `Vary`).
|
|
24
|
+
*
|
|
25
|
+
* Docs with a future `publishedAt` are withheld from every agent surface
|
|
26
|
+
* (llms.txt, llms-full.txt, direct `.md`, and negotiated twins) until their
|
|
27
|
+
* date arrives. The cutoff is `opts.today` (default: today in UTC), evaluated
|
|
28
|
+
* by the caller per request, so a scheduled doc reveals itself on its date
|
|
29
|
+
* without a rebuild. Undated docs are always served.
|
|
24
30
|
*/
|
|
25
31
|
export function decideAgentPages(req, docs, opts) {
|
|
26
32
|
const path = req.nextUrl.pathname;
|
|
27
33
|
const llms = opts?.llms;
|
|
34
|
+
const today = opts?.today ?? todayUtc();
|
|
35
|
+
const visible = docs.filter((d) => isPublished(d.publishedAt, today));
|
|
28
36
|
if (llms && (req.method === "GET" || req.method === "HEAD")) {
|
|
29
37
|
if (path === "/llms.txt") {
|
|
30
38
|
return {
|
|
31
39
|
kind: "markdown",
|
|
32
40
|
mdPath: path,
|
|
33
41
|
negotiated: false,
|
|
34
|
-
body: llmsTxt({ siteUrl: llms.siteUrl, intro: llms.intro, docs }),
|
|
42
|
+
body: llmsTxt({ siteUrl: llms.siteUrl, intro: llms.intro, docs: visible }),
|
|
35
43
|
};
|
|
36
44
|
}
|
|
37
45
|
if (path === "/llms-full.txt") {
|
|
@@ -39,13 +47,13 @@ export function decideAgentPages(req, docs, opts) {
|
|
|
39
47
|
kind: "markdown",
|
|
40
48
|
mdPath: path,
|
|
41
49
|
negotiated: false,
|
|
42
|
-
body: llmsFullTxt(
|
|
50
|
+
body: llmsFullTxt(visible),
|
|
43
51
|
};
|
|
44
52
|
}
|
|
45
53
|
}
|
|
46
54
|
// Direct `.md` URL — served regardless of negotiation (agents fetch these
|
|
47
55
|
// straight from `/llms.txt` links).
|
|
48
|
-
const direct =
|
|
56
|
+
const direct = visible.find((d) => d.mdPath === path);
|
|
49
57
|
if (direct) {
|
|
50
58
|
return {
|
|
51
59
|
kind: "markdown",
|
|
@@ -55,14 +63,11 @@ export function decideAgentPages(req, docs, opts) {
|
|
|
55
63
|
};
|
|
56
64
|
}
|
|
57
65
|
// HTML page with a markdown twin — negotiate.
|
|
58
|
-
const twin =
|
|
66
|
+
const twin = visible.find((d) => d.htmlPath === path);
|
|
59
67
|
if (twin) {
|
|
60
68
|
const wantsMarkdown = clientWantsMarkdown({
|
|
61
69
|
method: req.method,
|
|
62
70
|
accept: req.headers.get("accept"),
|
|
63
|
-
userAgent: req.headers.get("user-agent"),
|
|
64
|
-
signatureAgent: req.headers.get("signature-agent"),
|
|
65
|
-
secFetchMode: req.headers.get("sec-fetch-mode"),
|
|
66
71
|
});
|
|
67
72
|
if (wantsMarkdown) {
|
|
68
73
|
return {
|
|
@@ -102,20 +107,34 @@ export function serveAgentPages(decision) {
|
|
|
102
107
|
* rewrites paths (e.g. `/terms` → `/en/terms`) never hides a markdown twin.
|
|
103
108
|
*/
|
|
104
109
|
export function createAgentPagesMiddleware(opts) {
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
:
|
|
110
|
+
// `typeof` rather than `Array.isArray`: the latter narrows a readonly
|
|
111
|
+
// array union to `any[]`, losing the element type.
|
|
112
|
+
const observers = !opts.observe
|
|
113
|
+
? []
|
|
114
|
+
: typeof opts.observe === "function"
|
|
115
|
+
? [opts.observe]
|
|
116
|
+
: opts.observe;
|
|
110
117
|
return (req, ev) => {
|
|
111
|
-
|
|
118
|
+
// `todayUtc()` is read per request so a scheduled doc reveals itself on its
|
|
119
|
+
// date without a redeploy.
|
|
120
|
+
const decision = decideAgentPages(req, opts.docs, {
|
|
121
|
+
llms: opts.llms,
|
|
122
|
+
today: todayUtc(),
|
|
123
|
+
});
|
|
112
124
|
if (decision.kind === "markdown") {
|
|
113
125
|
if (observers.length) {
|
|
114
126
|
// Hand observers the served `.md` path, not the requested one, so a
|
|
115
|
-
// beacon grades this request as markdown
|
|
127
|
+
// beacon grades this request as markdown — while preserving the
|
|
128
|
+
// original headers so the beacon still attributes the agent
|
|
129
|
+
// (user-agent → vendor, IP, country, referrer), not just the path.
|
|
130
|
+
// Dropping the headers here records the crawler as an empty "human"
|
|
131
|
+
// hit; rewriting only the pathname keeps the markdown grade.
|
|
116
132
|
const url = req.nextUrl.clone();
|
|
117
133
|
url.pathname = decision.mdPath;
|
|
118
|
-
const served = new NextRequest(url, {
|
|
134
|
+
const served = new NextRequest(url, {
|
|
135
|
+
method: req.method,
|
|
136
|
+
headers: req.headers,
|
|
137
|
+
});
|
|
119
138
|
for (const observe of observers)
|
|
120
139
|
observe(served, ev);
|
|
121
140
|
}
|
package/dist/next.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"next.js","sourceRoot":"","sources":["../src/next.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,
|
|
1
|
+
{"version":3,"file":"next.js","sourceRoot":"","sources":["../src/next.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@caprail-dev/agent-pages",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Markdown-first pages for AI agents — co-located page.md twins served inline via
|
|
3
|
+
"version": "0.4.1",
|
|
4
|
+
"description": "Markdown-first pages for AI agents — co-located page.md twins served inline via Accept-header content negotiation for Next.js.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
7
7
|
"license": "MIT",
|
|
@@ -23,6 +23,10 @@
|
|
|
23
23
|
"./config": {
|
|
24
24
|
"types": "./dist/config.d.ts",
|
|
25
25
|
"default": "./dist/config.js"
|
|
26
|
+
},
|
|
27
|
+
"./frontmatter": {
|
|
28
|
+
"types": "./dist/frontmatter.d.ts",
|
|
29
|
+
"default": "./dist/frontmatter.js"
|
|
26
30
|
}
|
|
27
31
|
},
|
|
28
32
|
"publishConfig": {
|
|
@@ -40,8 +44,5 @@
|
|
|
40
44
|
"next": {
|
|
41
45
|
"optional": true
|
|
42
46
|
}
|
|
43
|
-
},
|
|
44
|
-
"dependencies": {
|
|
45
|
-
"@caprail-dev/analytics": "^0.5.0"
|
|
46
47
|
}
|
|
47
48
|
}
|