@agent-native/core 0.15.10 → 0.15.12

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 (69) hide show
  1. package/dist/a2a/server.d.ts +1 -0
  2. package/dist/a2a/server.d.ts.map +1 -1
  3. package/dist/a2a/server.js +25 -13
  4. package/dist/a2a/server.js.map +1 -1
  5. package/dist/a2a/types.d.ts +8 -0
  6. package/dist/a2a/types.d.ts.map +1 -1
  7. package/dist/a2a/types.js +0 -1
  8. package/dist/a2a/types.js.map +1 -1
  9. package/dist/action.d.ts +15 -0
  10. package/dist/action.d.ts.map +1 -1
  11. package/dist/action.js +6 -0
  12. package/dist/action.js.map +1 -1
  13. package/dist/agent/production-agent.d.ts +3 -0
  14. package/dist/agent/production-agent.d.ts.map +1 -1
  15. package/dist/agent/production-agent.js.map +1 -1
  16. package/dist/agent-web/config.d.ts +41 -0
  17. package/dist/agent-web/config.d.ts.map +1 -0
  18. package/dist/agent-web/config.js +162 -0
  19. package/dist/agent-web/config.js.map +1 -0
  20. package/dist/agent-web/generator.d.ts +95 -0
  21. package/dist/agent-web/generator.d.ts.map +1 -0
  22. package/dist/agent-web/generator.js +270 -0
  23. package/dist/agent-web/generator.js.map +1 -0
  24. package/dist/agent-web/index.d.ts +3 -0
  25. package/dist/agent-web/index.d.ts.map +1 -0
  26. package/dist/agent-web/index.js +3 -0
  27. package/dist/agent-web/index.js.map +1 -0
  28. package/dist/cli/audit-agent-web.d.ts +2 -0
  29. package/dist/cli/audit-agent-web.d.ts.map +1 -0
  30. package/dist/cli/audit-agent-web.js +201 -0
  31. package/dist/cli/audit-agent-web.js.map +1 -0
  32. package/dist/cli/index.js +17 -0
  33. package/dist/cli/index.js.map +1 -1
  34. package/dist/cli/migrate.d.ts +10 -0
  35. package/dist/cli/migrate.d.ts.map +1 -0
  36. package/dist/cli/migrate.js +78 -0
  37. package/dist/cli/migrate.js.map +1 -0
  38. package/dist/cli/templates-meta.d.ts.map +1 -1
  39. package/dist/cli/templates-meta.js +12 -0
  40. package/dist/cli/templates-meta.js.map +1 -1
  41. package/dist/client/settings/SettingsPanel.d.ts.map +1 -1
  42. package/dist/client/settings/SettingsPanel.js +6 -5
  43. package/dist/client/settings/SettingsPanel.js.map +1 -1
  44. package/dist/client/settings/useBuilderStatus.d.ts.map +1 -1
  45. package/dist/client/settings/useBuilderStatus.js +79 -37
  46. package/dist/client/settings/useBuilderStatus.js.map +1 -1
  47. package/dist/client/settings/useBuilderStatus.spec.js +84 -6
  48. package/dist/client/settings/useBuilderStatus.spec.js.map +1 -1
  49. package/dist/index.d.ts +2 -1
  50. package/dist/index.d.ts.map +1 -1
  51. package/dist/index.js +2 -0
  52. package/dist/index.js.map +1 -1
  53. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  54. package/dist/server/agent-chat-plugin.js +2 -0
  55. package/dist/server/agent-chat-plugin.js.map +1 -1
  56. package/dist/server/credential-provider.d.ts.map +1 -1
  57. package/dist/server/credential-provider.js +4 -2
  58. package/dist/server/credential-provider.js.map +1 -1
  59. package/dist/vite/agent-web-plugin.d.ts +17 -0
  60. package/dist/vite/agent-web-plugin.d.ts.map +1 -0
  61. package/dist/vite/agent-web-plugin.js +48 -0
  62. package/dist/vite/agent-web-plugin.js.map +1 -0
  63. package/dist/vite/index.d.ts +1 -0
  64. package/dist/vite/index.d.ts.map +1 -1
  65. package/dist/vite/index.js +1 -0
  66. package/dist/vite/index.js.map +1 -1
  67. package/docs/content/agent-web-surfaces.md +143 -0
  68. package/docs/content/migration-workbench.md +110 -0
  69. package/package.json +2 -1
@@ -0,0 +1,41 @@
1
+ import { type WorkspaceAppAudience } from "../shared/workspace-app-audience.js";
2
+ export declare const AGENT_WEB_CRAWLER_CATEGORIES: readonly ["training", "search", "userTriggered", "codingAgents", "autonomousAgents"];
3
+ export type AgentWebCrawlerCategory = (typeof AGENT_WEB_CRAWLER_CATEGORIES)[number];
4
+ export type AgentWebCrawlerDecision = "allow" | "disallow";
5
+ export type AgentWebCrawlerPolicy = "discoverable-no-training" | "allow-all" | "disallow-all";
6
+ export type AgentWebCrawlerOverrides = Partial<Record<AgentWebCrawlerCategory, AgentWebCrawlerDecision>>;
7
+ export interface AgentWebInputConfig {
8
+ discoverable?: boolean;
9
+ markdownTwins?: boolean;
10
+ llmsTxt?: boolean;
11
+ jsonLd?: boolean;
12
+ publicAgentCard?: boolean;
13
+ publicMcp?: boolean;
14
+ crawlerPolicy?: AgentWebCrawlerPolicy;
15
+ crawlers?: AgentWebCrawlerOverrides;
16
+ }
17
+ export interface AgentWebConfig {
18
+ discoverable: boolean;
19
+ markdownTwins: boolean;
20
+ llmsTxt: boolean;
21
+ jsonLd: boolean;
22
+ publicAgentCard: boolean;
23
+ publicMcp: boolean;
24
+ crawlerPolicy: AgentWebCrawlerPolicy;
25
+ crawlers: AgentWebCrawlerOverrides;
26
+ }
27
+ export interface DeriveAgentWebPublicRoutesOptions {
28
+ audience?: WorkspaceAppAudience;
29
+ publicPaths?: string[];
30
+ protectedPaths?: string[];
31
+ routes?: string[];
32
+ }
33
+ export declare const DEFAULT_AGENT_WEB_CRAWLER_POLICY: AgentWebCrawlerPolicy;
34
+ export declare function normalizeAgentWebConfig(value: unknown, options?: {
35
+ hasPublicRoutes?: boolean;
36
+ }): AgentWebConfig;
37
+ export declare function agentWebConfigFromPackageJson(pkg: unknown): AgentWebInputConfig | boolean | undefined;
38
+ export declare function resolveAgentWebCrawlerPolicy(config: Pick<AgentWebConfig, "crawlerPolicy" | "crawlers">): Record<AgentWebCrawlerCategory, AgentWebCrawlerDecision>;
39
+ export declare function deriveAgentWebPublicRoutes(options: DeriveAgentWebPublicRoutesOptions): string[];
40
+ export declare function pathPatternMatches(pattern: string, route: string): boolean;
41
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/agent-web/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,oBAAoB,EAC1B,MAAM,qCAAqC,CAAC;AAE7C,eAAO,MAAM,4BAA4B,sFAM/B,CAAC;AAEX,MAAM,MAAM,uBAAuB,GACjC,CAAC,OAAO,4BAA4B,CAAC,CAAC,MAAM,CAAC,CAAC;AAEhD,MAAM,MAAM,uBAAuB,GAAG,OAAO,GAAG,UAAU,CAAC;AAE3D,MAAM,MAAM,qBAAqB,GAC7B,0BAA0B,GAC1B,WAAW,GACX,cAAc,CAAC;AAEnB,MAAM,MAAM,wBAAwB,GAAG,OAAO,CAC5C,MAAM,CAAC,uBAAuB,EAAE,uBAAuB,CAAC,CACzD,CAAC;AAEF,MAAM,WAAW,mBAAmB;IAClC,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,aAAa,CAAC,EAAE,qBAAqB,CAAC;IACtC,QAAQ,CAAC,EAAE,wBAAwB,CAAC;CACrC;AAED,MAAM,WAAW,cAAc;IAC7B,YAAY,EAAE,OAAO,CAAC;IACtB,aAAa,EAAE,OAAO,CAAC;IACvB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;IAChB,eAAe,EAAE,OAAO,CAAC;IACzB,SAAS,EAAE,OAAO,CAAC;IACnB,aAAa,EAAE,qBAAqB,CAAC;IACrC,QAAQ,EAAE,wBAAwB,CAAC;CACpC;AAED,MAAM,WAAW,iCAAiC;IAChD,QAAQ,CAAC,EAAE,oBAAoB,CAAC;IAChC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,eAAO,MAAM,gCAAgC,EAAE,qBACnB,CAAC;AAE7B,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,OAAO,EACd,OAAO,GAAE;IAAE,eAAe,CAAC,EAAE,OAAO,CAAA;CAAO,GAC1C,cAAc,CA4BhB;AAED,wBAAgB,6BAA6B,CAC3C,GAAG,EAAE,OAAO,GACX,mBAAmB,GAAG,OAAO,GAAG,SAAS,CAW3C;AAED,wBAAgB,4BAA4B,CAC1C,MAAM,EAAE,IAAI,CAAC,cAAc,EAAE,eAAe,GAAG,UAAU,CAAC,GACzD,MAAM,CAAC,uBAAuB,EAAE,uBAAuB,CAAC,CA+B1D;AAED,wBAAgB,0BAA0B,CACxC,OAAO,EAAE,iCAAiC,GACzC,MAAM,EAAE,CAkCV;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAe1E"}
@@ -0,0 +1,162 @@
1
+ import { normalizeWorkspaceAppAudience, normalizeWorkspaceAppPathList, } from "../shared/workspace-app-audience.js";
2
+ export const AGENT_WEB_CRAWLER_CATEGORIES = [
3
+ "training",
4
+ "search",
5
+ "userTriggered",
6
+ "codingAgents",
7
+ "autonomousAgents",
8
+ ];
9
+ export const DEFAULT_AGENT_WEB_CRAWLER_POLICY = "discoverable-no-training";
10
+ export function normalizeAgentWebConfig(value, options = {}) {
11
+ const record = value && typeof value === "object" && !Array.isArray(value)
12
+ ? value
13
+ : {};
14
+ const disabled = value === false;
15
+ const hasPublicRoutes = options.hasPublicRoutes === true;
16
+ return {
17
+ discoverable: disabled
18
+ ? false
19
+ : typeof record.discoverable === "boolean"
20
+ ? record.discoverable
21
+ : hasPublicRoutes,
22
+ markdownTwins: typeof record.markdownTwins === "boolean" ? record.markdownTwins : true,
23
+ llmsTxt: typeof record.llmsTxt === "boolean" ? record.llmsTxt : true,
24
+ jsonLd: typeof record.jsonLd === "boolean" ? record.jsonLd : true,
25
+ publicAgentCard: typeof record.publicAgentCard === "boolean"
26
+ ? record.publicAgentCard
27
+ : true,
28
+ publicMcp: typeof record.publicMcp === "boolean" ? record.publicMcp : false,
29
+ crawlerPolicy: isCrawlerPolicy(record.crawlerPolicy)
30
+ ? record.crawlerPolicy
31
+ : DEFAULT_AGENT_WEB_CRAWLER_POLICY,
32
+ crawlers: normalizeCrawlerOverrides(record.crawlers),
33
+ };
34
+ }
35
+ export function agentWebConfigFromPackageJson(pkg) {
36
+ const config = agentNativeConfigFromPackageJson(pkg);
37
+ const raw = config?.workspaceApp?.agentWeb ??
38
+ config?.workspace?.agentWeb ??
39
+ config?.agentWeb ??
40
+ config?.root?.agentWeb;
41
+ if (raw === undefined)
42
+ return undefined;
43
+ if (raw === false)
44
+ return false;
45
+ if (!raw || typeof raw !== "object" || Array.isArray(raw))
46
+ return undefined;
47
+ return raw;
48
+ }
49
+ export function resolveAgentWebCrawlerPolicy(config) {
50
+ const baseline = config.crawlerPolicy === "allow-all"
51
+ ? {
52
+ training: "allow",
53
+ search: "allow",
54
+ userTriggered: "allow",
55
+ codingAgents: "allow",
56
+ autonomousAgents: "allow",
57
+ }
58
+ : config.crawlerPolicy === "disallow-all"
59
+ ? {
60
+ training: "disallow",
61
+ search: "disallow",
62
+ userTriggered: "disallow",
63
+ codingAgents: "disallow",
64
+ autonomousAgents: "disallow",
65
+ }
66
+ : {
67
+ training: "disallow",
68
+ search: "allow",
69
+ userTriggered: "allow",
70
+ codingAgents: "allow",
71
+ autonomousAgents: "allow",
72
+ };
73
+ for (const category of AGENT_WEB_CRAWLER_CATEGORIES) {
74
+ const override = config.crawlers[category];
75
+ if (override)
76
+ baseline[category] = override;
77
+ }
78
+ return baseline;
79
+ }
80
+ export function deriveAgentWebPublicRoutes(options) {
81
+ const audience = normalizeWorkspaceAppAudience(options.audience);
82
+ const publicPaths = normalizeWorkspaceAppPathList(options.publicPaths ?? []);
83
+ const protectedPaths = normalizeWorkspaceAppPathList(options.protectedPaths ?? []);
84
+ const routes = normalizeWorkspaceAppPathList(options.routes ?? []);
85
+ const sourceRoutes = routes.length > 0
86
+ ? routes
87
+ : audience === "public"
88
+ ? publicPaths.length > 0
89
+ ? publicPaths
90
+ : ["/"]
91
+ : publicPaths;
92
+ const publicRoutes = audience === "public"
93
+ ? sourceRoutes.filter((route) => !protectedPaths.some((pattern) => pathPatternMatches(pattern, route)))
94
+ : sourceRoutes.filter((route) => publicPaths.some((pattern) => pathPatternMatches(pattern, route)));
95
+ return Array.from(new Set(publicRoutes)).sort((a, b) => {
96
+ if (a === "/")
97
+ return -1;
98
+ if (b === "/")
99
+ return 1;
100
+ return a.localeCompare(b);
101
+ });
102
+ }
103
+ export function pathPatternMatches(pattern, route) {
104
+ const normalizedPattern = normalizeWorkspaceAppPathList([pattern])[0];
105
+ const normalizedRoute = normalizeWorkspaceAppPathList([route])[0];
106
+ if (!normalizedPattern || !normalizedRoute)
107
+ return false;
108
+ if (normalizedPattern === "/*" || normalizedPattern === "/**")
109
+ return true;
110
+ if (normalizedPattern.endsWith("/*") || normalizedPattern.endsWith("/**")) {
111
+ const base = normalizedPattern.replace(/\/\*\*?$/, "") || "/";
112
+ return (normalizedRoute === base ||
113
+ (base === "/"
114
+ ? normalizedRoute.startsWith("/")
115
+ : normalizedRoute.startsWith(`${base}/`)));
116
+ }
117
+ return normalizedPattern === normalizedRoute;
118
+ }
119
+ function normalizeCrawlerOverrides(value) {
120
+ if (!value || typeof value !== "object" || Array.isArray(value))
121
+ return {};
122
+ const record = value;
123
+ const out = {};
124
+ for (const category of AGENT_WEB_CRAWLER_CATEGORIES) {
125
+ const decision = record[category];
126
+ if (decision === "allow" || decision === "disallow") {
127
+ out[category] = decision;
128
+ }
129
+ }
130
+ return out;
131
+ }
132
+ function isCrawlerPolicy(value) {
133
+ return (value === "discoverable-no-training" ||
134
+ value === "allow-all" ||
135
+ value === "disallow-all");
136
+ }
137
+ function agentNativeConfigFromPackageJson(pkg) {
138
+ if (!pkg || typeof pkg !== "object" || Array.isArray(pkg))
139
+ return undefined;
140
+ const record = pkg;
141
+ const config = record["agent-native"] ?? record.agentNative;
142
+ const nested = config && typeof config === "object" && !Array.isArray(config)
143
+ ? config
144
+ : {};
145
+ const workspaceApp = nested.workspaceApp &&
146
+ typeof nested.workspaceApp === "object" &&
147
+ !Array.isArray(nested.workspaceApp)
148
+ ? nested.workspaceApp
149
+ : undefined;
150
+ const workspace = nested.workspace &&
151
+ typeof nested.workspace === "object" &&
152
+ !Array.isArray(nested.workspace)
153
+ ? nested.workspace
154
+ : undefined;
155
+ return {
156
+ root: record,
157
+ workspaceApp,
158
+ workspace,
159
+ agentWeb: nested.agentWeb,
160
+ };
161
+ }
162
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/agent-web/config.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n normalizeWorkspaceAppAudience,\n normalizeWorkspaceAppPathList,\n type WorkspaceAppAudience,\n} from \"../shared/workspace-app-audience.js\";\n\nexport const AGENT_WEB_CRAWLER_CATEGORIES = [\n \"training\",\n \"search\",\n \"userTriggered\",\n \"codingAgents\",\n \"autonomousAgents\",\n] as const;\n\nexport type AgentWebCrawlerCategory =\n (typeof AGENT_WEB_CRAWLER_CATEGORIES)[number];\n\nexport type AgentWebCrawlerDecision = \"allow\" | \"disallow\";\n\nexport type AgentWebCrawlerPolicy =\n | \"discoverable-no-training\"\n | \"allow-all\"\n | \"disallow-all\";\n\nexport type AgentWebCrawlerOverrides = Partial<\n Record<AgentWebCrawlerCategory, AgentWebCrawlerDecision>\n>;\n\nexport interface AgentWebInputConfig {\n discoverable?: boolean;\n markdownTwins?: boolean;\n llmsTxt?: boolean;\n jsonLd?: boolean;\n publicAgentCard?: boolean;\n publicMcp?: boolean;\n crawlerPolicy?: AgentWebCrawlerPolicy;\n crawlers?: AgentWebCrawlerOverrides;\n}\n\nexport interface AgentWebConfig {\n discoverable: boolean;\n markdownTwins: boolean;\n llmsTxt: boolean;\n jsonLd: boolean;\n publicAgentCard: boolean;\n publicMcp: boolean;\n crawlerPolicy: AgentWebCrawlerPolicy;\n crawlers: AgentWebCrawlerOverrides;\n}\n\nexport interface DeriveAgentWebPublicRoutesOptions {\n audience?: WorkspaceAppAudience;\n publicPaths?: string[];\n protectedPaths?: string[];\n routes?: string[];\n}\n\nexport const DEFAULT_AGENT_WEB_CRAWLER_POLICY: AgentWebCrawlerPolicy =\n \"discoverable-no-training\";\n\nexport function normalizeAgentWebConfig(\n value: unknown,\n options: { hasPublicRoutes?: boolean } = {},\n): AgentWebConfig {\n const record =\n value && typeof value === \"object\" && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : {};\n const disabled = value === false;\n const hasPublicRoutes = options.hasPublicRoutes === true;\n\n return {\n discoverable: disabled\n ? false\n : typeof record.discoverable === \"boolean\"\n ? record.discoverable\n : hasPublicRoutes,\n markdownTwins:\n typeof record.markdownTwins === \"boolean\" ? record.markdownTwins : true,\n llmsTxt: typeof record.llmsTxt === \"boolean\" ? record.llmsTxt : true,\n jsonLd: typeof record.jsonLd === \"boolean\" ? record.jsonLd : true,\n publicAgentCard:\n typeof record.publicAgentCard === \"boolean\"\n ? record.publicAgentCard\n : true,\n publicMcp: typeof record.publicMcp === \"boolean\" ? record.publicMcp : false,\n crawlerPolicy: isCrawlerPolicy(record.crawlerPolicy)\n ? record.crawlerPolicy\n : DEFAULT_AGENT_WEB_CRAWLER_POLICY,\n crawlers: normalizeCrawlerOverrides(record.crawlers),\n };\n}\n\nexport function agentWebConfigFromPackageJson(\n pkg: unknown,\n): AgentWebInputConfig | boolean | undefined {\n const config = agentNativeConfigFromPackageJson(pkg);\n const raw =\n config?.workspaceApp?.agentWeb ??\n config?.workspace?.agentWeb ??\n config?.agentWeb ??\n config?.root?.agentWeb;\n if (raw === undefined) return undefined;\n if (raw === false) return false;\n if (!raw || typeof raw !== \"object\" || Array.isArray(raw)) return undefined;\n return raw as AgentWebInputConfig;\n}\n\nexport function resolveAgentWebCrawlerPolicy(\n config: Pick<AgentWebConfig, \"crawlerPolicy\" | \"crawlers\">,\n): Record<AgentWebCrawlerCategory, AgentWebCrawlerDecision> {\n const baseline: Record<AgentWebCrawlerCategory, AgentWebCrawlerDecision> =\n config.crawlerPolicy === \"allow-all\"\n ? {\n training: \"allow\",\n search: \"allow\",\n userTriggered: \"allow\",\n codingAgents: \"allow\",\n autonomousAgents: \"allow\",\n }\n : config.crawlerPolicy === \"disallow-all\"\n ? {\n training: \"disallow\",\n search: \"disallow\",\n userTriggered: \"disallow\",\n codingAgents: \"disallow\",\n autonomousAgents: \"disallow\",\n }\n : {\n training: \"disallow\",\n search: \"allow\",\n userTriggered: \"allow\",\n codingAgents: \"allow\",\n autonomousAgents: \"allow\",\n };\n\n for (const category of AGENT_WEB_CRAWLER_CATEGORIES) {\n const override = config.crawlers[category];\n if (override) baseline[category] = override;\n }\n return baseline;\n}\n\nexport function deriveAgentWebPublicRoutes(\n options: DeriveAgentWebPublicRoutesOptions,\n): string[] {\n const audience = normalizeWorkspaceAppAudience(options.audience);\n const publicPaths = normalizeWorkspaceAppPathList(options.publicPaths ?? []);\n const protectedPaths = normalizeWorkspaceAppPathList(\n options.protectedPaths ?? [],\n );\n const routes = normalizeWorkspaceAppPathList(options.routes ?? []);\n\n const sourceRoutes =\n routes.length > 0\n ? routes\n : audience === \"public\"\n ? publicPaths.length > 0\n ? publicPaths\n : [\"/\"]\n : publicPaths;\n\n const publicRoutes =\n audience === \"public\"\n ? sourceRoutes.filter(\n (route) =>\n !protectedPaths.some((pattern) =>\n pathPatternMatches(pattern, route),\n ),\n )\n : sourceRoutes.filter((route) =>\n publicPaths.some((pattern) => pathPatternMatches(pattern, route)),\n );\n\n return Array.from(new Set(publicRoutes)).sort((a, b) => {\n if (a === \"/\") return -1;\n if (b === \"/\") return 1;\n return a.localeCompare(b);\n });\n}\n\nexport function pathPatternMatches(pattern: string, route: string): boolean {\n const normalizedPattern = normalizeWorkspaceAppPathList([pattern])[0];\n const normalizedRoute = normalizeWorkspaceAppPathList([route])[0];\n if (!normalizedPattern || !normalizedRoute) return false;\n if (normalizedPattern === \"/*\" || normalizedPattern === \"/**\") return true;\n if (normalizedPattern.endsWith(\"/*\") || normalizedPattern.endsWith(\"/**\")) {\n const base = normalizedPattern.replace(/\\/\\*\\*?$/, \"\") || \"/\";\n return (\n normalizedRoute === base ||\n (base === \"/\"\n ? normalizedRoute.startsWith(\"/\")\n : normalizedRoute.startsWith(`${base}/`))\n );\n }\n return normalizedPattern === normalizedRoute;\n}\n\nfunction normalizeCrawlerOverrides(value: unknown): AgentWebCrawlerOverrides {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return {};\n const record = value as Record<string, unknown>;\n const out: AgentWebCrawlerOverrides = {};\n for (const category of AGENT_WEB_CRAWLER_CATEGORIES) {\n const decision = record[category];\n if (decision === \"allow\" || decision === \"disallow\") {\n out[category] = decision;\n }\n }\n return out;\n}\n\nfunction isCrawlerPolicy(value: unknown): value is AgentWebCrawlerPolicy {\n return (\n value === \"discoverable-no-training\" ||\n value === \"allow-all\" ||\n value === \"disallow-all\"\n );\n}\n\nfunction agentNativeConfigFromPackageJson(pkg: unknown):\n | {\n root: Record<string, any>;\n workspaceApp?: Record<string, any>;\n workspace?: Record<string, any>;\n agentWeb?: unknown;\n }\n | undefined {\n if (!pkg || typeof pkg !== \"object\" || Array.isArray(pkg)) return undefined;\n const record = pkg as Record<string, any>;\n const config = record[\"agent-native\"] ?? record.agentNative;\n const nested =\n config && typeof config === \"object\" && !Array.isArray(config)\n ? (config as Record<string, any>)\n : {};\n const workspaceApp =\n nested.workspaceApp &&\n typeof nested.workspaceApp === \"object\" &&\n !Array.isArray(nested.workspaceApp)\n ? (nested.workspaceApp as Record<string, any>)\n : undefined;\n const workspace =\n nested.workspace &&\n typeof nested.workspace === \"object\" &&\n !Array.isArray(nested.workspace)\n ? (nested.workspace as Record<string, any>)\n : undefined;\n return {\n root: record,\n workspaceApp,\n workspace,\n agentWeb: nested.agentWeb,\n };\n}\n"]}
@@ -0,0 +1,95 @@
1
+ import { type AgentWebConfig, type AgentWebCrawlerCategory } from "./config.js";
2
+ export interface AgentWebPage {
3
+ path: string;
4
+ title: string;
5
+ description?: string;
6
+ markdown?: string;
7
+ markdownPath?: string;
8
+ lastmod?: string | Date;
9
+ }
10
+ export interface BuildAgentWebStaticFilesOptions {
11
+ siteName: string;
12
+ siteUrl: string;
13
+ description?: string;
14
+ pages: AgentWebPage[];
15
+ config: AgentWebConfig;
16
+ organization?: {
17
+ name: string;
18
+ url?: string;
19
+ sameAs?: string[];
20
+ };
21
+ }
22
+ export interface AgentWebStaticFile {
23
+ path: string;
24
+ content: string;
25
+ }
26
+ export interface MarkdownResponseHeadersOptions {
27
+ siteUrl: string;
28
+ pagePath: string;
29
+ markdownPath?: string;
30
+ markdown: string;
31
+ }
32
+ export declare const AGENT_WEB_CRAWLER_USER_AGENTS: Record<AgentWebCrawlerCategory, string[]>;
33
+ export declare function buildAgentWebStaticFiles(options: BuildAgentWebStaticFilesOptions): AgentWebStaticFile[];
34
+ export declare function buildRobotsTxt(options: {
35
+ siteUrl: string;
36
+ config: Pick<AgentWebConfig, "crawlerPolicy" | "crawlers">;
37
+ sitemapPath?: string;
38
+ }): string;
39
+ export declare function buildSitemapXml(pages: AgentWebPage[], siteUrl: string): string;
40
+ export declare function buildLlmsTxt(options: Omit<BuildAgentWebStaticFilesOptions, "config">): string;
41
+ export declare function buildLlmsFullTxt(options: Omit<BuildAgentWebStaticFilesOptions, "config">): string;
42
+ export declare function buildBaseJsonLd(options: {
43
+ siteName: string;
44
+ siteUrl: string;
45
+ description?: string;
46
+ organization?: {
47
+ name: string;
48
+ url?: string;
49
+ sameAs?: string[];
50
+ };
51
+ }): ({
52
+ sameAs?: string[];
53
+ "@context": string;
54
+ "@type": string;
55
+ name: string;
56
+ url: string;
57
+ } | {
58
+ description?: string;
59
+ "@context": string;
60
+ "@type": string;
61
+ name: string;
62
+ url: string;
63
+ })[];
64
+ export declare function buildPageJsonLd(options: {
65
+ siteName: string;
66
+ siteUrl: string;
67
+ page: AgentWebPage;
68
+ }): ({
69
+ isPartOf: {
70
+ "@type": string;
71
+ name: string;
72
+ url: string;
73
+ };
74
+ description?: string;
75
+ "@context": string;
76
+ "@type": string;
77
+ name: string;
78
+ url: string;
79
+ itemListElement?: undefined;
80
+ } | {
81
+ "@context": string;
82
+ "@type": string;
83
+ itemListElement: {
84
+ "@type": string;
85
+ position: number;
86
+ name: string;
87
+ item: string;
88
+ }[];
89
+ })[];
90
+ export declare function buildMarkdownResponseHeaders(options: MarkdownResponseHeadersOptions): Record<string, string>;
91
+ export declare function estimateMarkdownTokens(markdown: string): number;
92
+ export declare function markdownUrlForPage(pagePath: string, markdownPath?: string): string;
93
+ export declare function markdownFilePathForPage(pagePath: string, markdownPath?: string): string;
94
+ export declare function absoluteUrl(siteUrl: string, pagePath: string): string;
95
+ //# sourceMappingURL=generator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generator.d.ts","sourceRoot":"","sources":["../../src/agent-web/generator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,270 @@
1
+ import { resolveAgentWebCrawlerPolicy, } from "./config.js";
2
+ export const AGENT_WEB_CRAWLER_USER_AGENTS = {
3
+ training: [
4
+ "GPTBot",
5
+ "ClaudeBot",
6
+ "CCBot",
7
+ "Google-Extended",
8
+ "Applebot-Extended",
9
+ "Bytespider",
10
+ "Meta-ExternalAgent",
11
+ "Amazonbot",
12
+ ],
13
+ search: ["OAI-SearchBot", "Claude-SearchBot", "PerplexityBot", "YouBot"],
14
+ userTriggered: ["ChatGPT-User", "Claude-User", "Perplexity-User"],
15
+ codingAgents: ["Claude-Code", "Gemini-CLI", "Devin", "OpenHands"],
16
+ autonomousAgents: ["ChatGPT-Agent", "Operator", "Gemini-Deep-Research"],
17
+ };
18
+ export function buildAgentWebStaticFiles(options) {
19
+ const files = [
20
+ {
21
+ path: "robots.txt",
22
+ content: buildRobotsTxt({
23
+ siteUrl: options.siteUrl,
24
+ config: options.config,
25
+ }),
26
+ },
27
+ {
28
+ path: "sitemap.xml",
29
+ content: buildSitemapXml(options.pages, options.siteUrl),
30
+ },
31
+ ];
32
+ if (options.config.llmsTxt) {
33
+ files.push({
34
+ path: "llms.txt",
35
+ content: buildLlmsTxt(options),
36
+ });
37
+ files.push({
38
+ path: "llms-full.txt",
39
+ content: buildLlmsFullTxt(options),
40
+ });
41
+ }
42
+ if (options.config.markdownTwins) {
43
+ for (const page of options.pages) {
44
+ if (!page.markdown)
45
+ continue;
46
+ files.push({
47
+ path: markdownFilePathForPage(page.path, page.markdownPath),
48
+ content: page.markdown,
49
+ });
50
+ }
51
+ }
52
+ return files;
53
+ }
54
+ export function buildRobotsTxt(options) {
55
+ const decisions = resolveAgentWebCrawlerPolicy(options.config);
56
+ const lines = [
57
+ "# Agent Web crawler policy",
58
+ `# Preset: ${options.config.crawlerPolicy}`,
59
+ "",
60
+ ];
61
+ for (const [category, userAgents] of Object.entries(AGENT_WEB_CRAWLER_USER_AGENTS)) {
62
+ lines.push(`# ${category}: ${decisions[category]}`);
63
+ for (const userAgent of userAgents) {
64
+ lines.push(`User-agent: ${userAgent}`);
65
+ }
66
+ lines.push(decisions[category] === "allow" ? "Allow: /" : "Disallow: /");
67
+ lines.push("");
68
+ }
69
+ lines.push("User-agent: *", "Allow: /", "");
70
+ lines.push(`Sitemap: ${absoluteUrl(options.siteUrl, options.sitemapPath ?? "/sitemap.xml")}`);
71
+ return `${lines.join("\n")}\n`;
72
+ }
73
+ export function buildSitemapXml(pages, siteUrl) {
74
+ const entries = pages
75
+ .map((page) => {
76
+ const lines = [
77
+ " <url>",
78
+ ` <loc>${xmlEscape(absoluteUrl(siteUrl, page.path))}</loc>`,
79
+ ];
80
+ const lastmod = normalizeLastmod(page.lastmod);
81
+ if (lastmod)
82
+ lines.push(` <lastmod>${xmlEscape(lastmod)}</lastmod>`);
83
+ lines.push(" </url>");
84
+ return lines.join("\n");
85
+ })
86
+ .join("\n");
87
+ return `<?xml version="1.0" encoding="UTF-8"?>
88
+ <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
89
+ ${entries}
90
+ </urlset>
91
+ `;
92
+ }
93
+ export function buildLlmsTxt(options) {
94
+ const lines = [
95
+ `# ${options.siteName}`,
96
+ "",
97
+ options.description ? `> ${options.description}` : undefined,
98
+ options.description ? "" : undefined,
99
+ "## Pages",
100
+ ...options.pages.map((page) => {
101
+ const description = page.description ? `: ${page.description}` : "";
102
+ return `- [${page.title}](${absoluteUrl(options.siteUrl, page.path)})${description}`;
103
+ }),
104
+ "",
105
+ "## Markdown",
106
+ ...options.pages
107
+ .filter((page) => page.markdown)
108
+ .map((page) => `- [${page.title}](${absoluteUrl(options.siteUrl, markdownUrlForPage(page.path, page.markdownPath))})`),
109
+ ].filter((line) => typeof line === "string");
110
+ return `${lines.join("\n")}\n`;
111
+ }
112
+ export function buildLlmsFullTxt(options) {
113
+ const lines = [
114
+ `# ${options.siteName}`,
115
+ "",
116
+ options.description ?? "",
117
+ "",
118
+ ...options.pages.flatMap((page) => [
119
+ `## ${page.title}`,
120
+ "",
121
+ `Source: ${absoluteUrl(options.siteUrl, page.path)}`,
122
+ page.markdown
123
+ ? `Markdown: ${absoluteUrl(options.siteUrl, markdownUrlForPage(page.path, page.markdownPath))}`
124
+ : undefined,
125
+ page.description ? `Description: ${page.description}` : undefined,
126
+ "",
127
+ page.markdown ?? "",
128
+ "",
129
+ ]),
130
+ ].filter((line) => typeof line === "string");
131
+ return `${lines.join("\n").replace(/\n{4,}/g, "\n\n\n")}\n`;
132
+ }
133
+ export function buildBaseJsonLd(options) {
134
+ const siteUrl = trimTrailingSlash(options.siteUrl);
135
+ return [
136
+ {
137
+ "@context": "https://schema.org",
138
+ "@type": "Organization",
139
+ name: options.organization?.name ?? options.siteName,
140
+ url: options.organization?.url ?? siteUrl,
141
+ ...(options.organization?.sameAs?.length
142
+ ? { sameAs: options.organization.sameAs }
143
+ : {}),
144
+ },
145
+ {
146
+ "@context": "https://schema.org",
147
+ "@type": "WebSite",
148
+ name: options.siteName,
149
+ url: siteUrl,
150
+ ...(options.description ? { description: options.description } : {}),
151
+ },
152
+ ];
153
+ }
154
+ export function buildPageJsonLd(options) {
155
+ const breadcrumbs = breadcrumbItemsForPath(options.page.path);
156
+ return [
157
+ {
158
+ "@context": "https://schema.org",
159
+ "@type": "WebPage",
160
+ name: options.page.title,
161
+ url: absoluteUrl(options.siteUrl, options.page.path),
162
+ ...(options.page.description
163
+ ? { description: options.page.description }
164
+ : {}),
165
+ isPartOf: {
166
+ "@type": "WebSite",
167
+ name: options.siteName,
168
+ url: trimTrailingSlash(options.siteUrl),
169
+ },
170
+ },
171
+ ...(breadcrumbs.length > 1
172
+ ? [
173
+ {
174
+ "@context": "https://schema.org",
175
+ "@type": "BreadcrumbList",
176
+ itemListElement: breadcrumbs.map((item, index) => ({
177
+ "@type": "ListItem",
178
+ position: index + 1,
179
+ name: item.name,
180
+ item: absoluteUrl(options.siteUrl, item.path),
181
+ })),
182
+ },
183
+ ]
184
+ : []),
185
+ ];
186
+ }
187
+ export function buildMarkdownResponseHeaders(options) {
188
+ return {
189
+ "content-type": "text/markdown; charset=utf-8",
190
+ "x-markdown-tokens": String(estimateMarkdownTokens(options.markdown)),
191
+ link: `<${absoluteUrl(options.siteUrl, "/llms.txt")}>; rel="llms-txt", <${absoluteUrl(options.siteUrl, markdownUrlForPage(options.pagePath, options.markdownPath))}>; rel="alternate"; type="text/markdown"`,
192
+ };
193
+ }
194
+ export function estimateMarkdownTokens(markdown) {
195
+ const trimmed = markdown.trim();
196
+ if (!trimmed)
197
+ return 0;
198
+ return Math.max(1, Math.ceil(trimmed.length / 4));
199
+ }
200
+ export function markdownUrlForPage(pagePath, markdownPath) {
201
+ if (markdownPath)
202
+ return normalizePagePath(markdownPath);
203
+ const normalized = normalizePagePath(pagePath);
204
+ if (normalized === "/")
205
+ return "/index.md";
206
+ return `${normalized}.md`;
207
+ }
208
+ export function markdownFilePathForPage(pagePath, markdownPath) {
209
+ return markdownUrlForPage(pagePath, markdownPath).replace(/^\//, "");
210
+ }
211
+ export function absoluteUrl(siteUrl, pagePath) {
212
+ const base = trimTrailingSlash(siteUrl);
213
+ const path = normalizePagePath(pagePath);
214
+ return `${base}${path}`;
215
+ }
216
+ function normalizePagePath(pagePath) {
217
+ const withSlash = pagePath.startsWith("/") ? pagePath : `/${pagePath}`;
218
+ if (withSlash.length > 1 && withSlash.endsWith("/")) {
219
+ return withSlash.slice(0, -1);
220
+ }
221
+ return withSlash;
222
+ }
223
+ function trimTrailingSlash(value) {
224
+ return value.replace(/\/+$/, "");
225
+ }
226
+ function normalizeLastmod(value) {
227
+ if (!value)
228
+ return undefined;
229
+ if (value instanceof Date)
230
+ return value.toISOString().slice(0, 10);
231
+ const trimmed = value.trim();
232
+ if (!trimmed)
233
+ return undefined;
234
+ const parsed = new Date(trimmed);
235
+ if (Number.isNaN(parsed.getTime()))
236
+ return trimmed;
237
+ return parsed.toISOString().slice(0, 10);
238
+ }
239
+ function breadcrumbItemsForPath(pagePath) {
240
+ const normalized = normalizePagePath(pagePath);
241
+ if (normalized === "/")
242
+ return [{ name: "Home", path: "/" }];
243
+ const segments = normalized.split("/").filter(Boolean);
244
+ const items = [{ name: "Home", path: "/" }];
245
+ let current = "";
246
+ for (const segment of segments) {
247
+ current += `/${segment}`;
248
+ items.push({
249
+ name: titleFromSegment(segment),
250
+ path: current,
251
+ });
252
+ }
253
+ return items;
254
+ }
255
+ function titleFromSegment(segment) {
256
+ return segment
257
+ .split("-")
258
+ .filter(Boolean)
259
+ .map((part) => part.charAt(0).toUpperCase() + part.slice(1))
260
+ .join(" ");
261
+ }
262
+ function xmlEscape(value) {
263
+ return value
264
+ .replace(/&/g, "&amp;")
265
+ .replace(/</g, "&lt;")
266
+ .replace(/>/g, "&gt;")
267
+ .replace(/"/g, "&quot;")
268
+ .replace(/'/g, "&apos;");
269
+ }
270
+ //# sourceMappingURL=generator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generator.js","sourceRoot":"","sources":["../../src/agent-web/generator.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n type AgentWebConfig,\n type AgentWebCrawlerCategory,\n resolveAgentWebCrawlerPolicy,\n} from \"./config.js\";\n\nexport interface AgentWebPage {\n path: string;\n title: string;\n description?: string;\n markdown?: string;\n markdownPath?: string;\n lastmod?: string | Date;\n}\n\nexport interface BuildAgentWebStaticFilesOptions {\n siteName: string;\n siteUrl: string;\n description?: string;\n pages: AgentWebPage[];\n config: AgentWebConfig;\n organization?: {\n name: string;\n url?: string;\n sameAs?: string[];\n };\n}\n\nexport interface AgentWebStaticFile {\n path: string;\n content: string;\n}\n\nexport interface MarkdownResponseHeadersOptions {\n siteUrl: string;\n pagePath: string;\n markdownPath?: string;\n markdown: string;\n}\n\nexport const AGENT_WEB_CRAWLER_USER_AGENTS: Record<\n AgentWebCrawlerCategory,\n string[]\n> = {\n training: [\n \"GPTBot\",\n \"ClaudeBot\",\n \"CCBot\",\n \"Google-Extended\",\n \"Applebot-Extended\",\n \"Bytespider\",\n \"Meta-ExternalAgent\",\n \"Amazonbot\",\n ],\n search: [\"OAI-SearchBot\", \"Claude-SearchBot\", \"PerplexityBot\", \"YouBot\"],\n userTriggered: [\"ChatGPT-User\", \"Claude-User\", \"Perplexity-User\"],\n codingAgents: [\"Claude-Code\", \"Gemini-CLI\", \"Devin\", \"OpenHands\"],\n autonomousAgents: [\"ChatGPT-Agent\", \"Operator\", \"Gemini-Deep-Research\"],\n};\n\nexport function buildAgentWebStaticFiles(\n options: BuildAgentWebStaticFilesOptions,\n): AgentWebStaticFile[] {\n const files: AgentWebStaticFile[] = [\n {\n path: \"robots.txt\",\n content: buildRobotsTxt({\n siteUrl: options.siteUrl,\n config: options.config,\n }),\n },\n {\n path: \"sitemap.xml\",\n content: buildSitemapXml(options.pages, options.siteUrl),\n },\n ];\n\n if (options.config.llmsTxt) {\n files.push({\n path: \"llms.txt\",\n content: buildLlmsTxt(options),\n });\n files.push({\n path: \"llms-full.txt\",\n content: buildLlmsFullTxt(options),\n });\n }\n\n if (options.config.markdownTwins) {\n for (const page of options.pages) {\n if (!page.markdown) continue;\n files.push({\n path: markdownFilePathForPage(page.path, page.markdownPath),\n content: page.markdown,\n });\n }\n }\n\n return files;\n}\n\nexport function buildRobotsTxt(options: {\n siteUrl: string;\n config: Pick<AgentWebConfig, \"crawlerPolicy\" | \"crawlers\">;\n sitemapPath?: string;\n}): string {\n const decisions = resolveAgentWebCrawlerPolicy(options.config);\n const lines: string[] = [\n \"# Agent Web crawler policy\",\n `# Preset: ${options.config.crawlerPolicy}`,\n \"\",\n ];\n\n for (const [category, userAgents] of Object.entries(\n AGENT_WEB_CRAWLER_USER_AGENTS,\n ) as [AgentWebCrawlerCategory, string[]][]) {\n lines.push(`# ${category}: ${decisions[category]}`);\n for (const userAgent of userAgents) {\n lines.push(`User-agent: ${userAgent}`);\n }\n lines.push(decisions[category] === \"allow\" ? \"Allow: /\" : \"Disallow: /\");\n lines.push(\"\");\n }\n\n lines.push(\"User-agent: *\", \"Allow: /\", \"\");\n lines.push(\n `Sitemap: ${absoluteUrl(options.siteUrl, options.sitemapPath ?? \"/sitemap.xml\")}`,\n );\n\n return `${lines.join(\"\\n\")}\\n`;\n}\n\nexport function buildSitemapXml(\n pages: AgentWebPage[],\n siteUrl: string,\n): string {\n const entries = pages\n .map((page) => {\n const lines = [\n \" <url>\",\n ` <loc>${xmlEscape(absoluteUrl(siteUrl, page.path))}</loc>`,\n ];\n const lastmod = normalizeLastmod(page.lastmod);\n if (lastmod) lines.push(` <lastmod>${xmlEscape(lastmod)}</lastmod>`);\n lines.push(\" </url>\");\n return lines.join(\"\\n\");\n })\n .join(\"\\n\");\n\n return `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\n${entries}\n</urlset>\n`;\n}\n\nexport function buildLlmsTxt(\n options: Omit<BuildAgentWebStaticFilesOptions, \"config\">,\n): string {\n const lines = [\n `# ${options.siteName}`,\n \"\",\n options.description ? `> ${options.description}` : undefined,\n options.description ? \"\" : undefined,\n \"## Pages\",\n ...options.pages.map((page) => {\n const description = page.description ? `: ${page.description}` : \"\";\n return `- [${page.title}](${absoluteUrl(options.siteUrl, page.path)})${description}`;\n }),\n \"\",\n \"## Markdown\",\n ...options.pages\n .filter((page) => page.markdown)\n .map(\n (page) =>\n `- [${page.title}](${absoluteUrl(\n options.siteUrl,\n markdownUrlForPage(page.path, page.markdownPath),\n )})`,\n ),\n ].filter((line): line is string => typeof line === \"string\");\n\n return `${lines.join(\"\\n\")}\\n`;\n}\n\nexport function buildLlmsFullTxt(\n options: Omit<BuildAgentWebStaticFilesOptions, \"config\">,\n): string {\n const lines = [\n `# ${options.siteName}`,\n \"\",\n options.description ?? \"\",\n \"\",\n ...options.pages.flatMap((page) => [\n `## ${page.title}`,\n \"\",\n `Source: ${absoluteUrl(options.siteUrl, page.path)}`,\n page.markdown\n ? `Markdown: ${absoluteUrl(\n options.siteUrl,\n markdownUrlForPage(page.path, page.markdownPath),\n )}`\n : undefined,\n page.description ? `Description: ${page.description}` : undefined,\n \"\",\n page.markdown ?? \"\",\n \"\",\n ]),\n ].filter((line): line is string => typeof line === \"string\");\n\n return `${lines.join(\"\\n\").replace(/\\n{4,}/g, \"\\n\\n\\n\")}\\n`;\n}\n\nexport function buildBaseJsonLd(options: {\n siteName: string;\n siteUrl: string;\n description?: string;\n organization?: {\n name: string;\n url?: string;\n sameAs?: string[];\n };\n}) {\n const siteUrl = trimTrailingSlash(options.siteUrl);\n return [\n {\n \"@context\": \"https://schema.org\",\n \"@type\": \"Organization\",\n name: options.organization?.name ?? options.siteName,\n url: options.organization?.url ?? siteUrl,\n ...(options.organization?.sameAs?.length\n ? { sameAs: options.organization.sameAs }\n : {}),\n },\n {\n \"@context\": \"https://schema.org\",\n \"@type\": \"WebSite\",\n name: options.siteName,\n url: siteUrl,\n ...(options.description ? { description: options.description } : {}),\n },\n ];\n}\n\nexport function buildPageJsonLd(options: {\n siteName: string;\n siteUrl: string;\n page: AgentWebPage;\n}) {\n const breadcrumbs = breadcrumbItemsForPath(options.page.path);\n return [\n {\n \"@context\": \"https://schema.org\",\n \"@type\": \"WebPage\",\n name: options.page.title,\n url: absoluteUrl(options.siteUrl, options.page.path),\n ...(options.page.description\n ? { description: options.page.description }\n : {}),\n isPartOf: {\n \"@type\": \"WebSite\",\n name: options.siteName,\n url: trimTrailingSlash(options.siteUrl),\n },\n },\n ...(breadcrumbs.length > 1\n ? [\n {\n \"@context\": \"https://schema.org\",\n \"@type\": \"BreadcrumbList\",\n itemListElement: breadcrumbs.map((item, index) => ({\n \"@type\": \"ListItem\",\n position: index + 1,\n name: item.name,\n item: absoluteUrl(options.siteUrl, item.path),\n })),\n },\n ]\n : []),\n ];\n}\n\nexport function buildMarkdownResponseHeaders(\n options: MarkdownResponseHeadersOptions,\n): Record<string, string> {\n return {\n \"content-type\": \"text/markdown; charset=utf-8\",\n \"x-markdown-tokens\": String(estimateMarkdownTokens(options.markdown)),\n link: `<${absoluteUrl(options.siteUrl, \"/llms.txt\")}>; rel=\"llms-txt\", <${absoluteUrl(\n options.siteUrl,\n markdownUrlForPage(options.pagePath, options.markdownPath),\n )}>; rel=\"alternate\"; type=\"text/markdown\"`,\n };\n}\n\nexport function estimateMarkdownTokens(markdown: string): number {\n const trimmed = markdown.trim();\n if (!trimmed) return 0;\n return Math.max(1, Math.ceil(trimmed.length / 4));\n}\n\nexport function markdownUrlForPage(\n pagePath: string,\n markdownPath?: string,\n): string {\n if (markdownPath) return normalizePagePath(markdownPath);\n const normalized = normalizePagePath(pagePath);\n if (normalized === \"/\") return \"/index.md\";\n return `${normalized}.md`;\n}\n\nexport function markdownFilePathForPage(\n pagePath: string,\n markdownPath?: string,\n): string {\n return markdownUrlForPage(pagePath, markdownPath).replace(/^\\//, \"\");\n}\n\nexport function absoluteUrl(siteUrl: string, pagePath: string): string {\n const base = trimTrailingSlash(siteUrl);\n const path = normalizePagePath(pagePath);\n return `${base}${path}`;\n}\n\nfunction normalizePagePath(pagePath: string): string {\n const withSlash = pagePath.startsWith(\"/\") ? pagePath : `/${pagePath}`;\n if (withSlash.length > 1 && withSlash.endsWith(\"/\")) {\n return withSlash.slice(0, -1);\n }\n return withSlash;\n}\n\nfunction trimTrailingSlash(value: string): string {\n return value.replace(/\\/+$/, \"\");\n}\n\nfunction normalizeLastmod(\n value: string | Date | undefined,\n): string | undefined {\n if (!value) return undefined;\n if (value instanceof Date) return value.toISOString().slice(0, 10);\n const trimmed = value.trim();\n if (!trimmed) return undefined;\n const parsed = new Date(trimmed);\n if (Number.isNaN(parsed.getTime())) return trimmed;\n return parsed.toISOString().slice(0, 10);\n}\n\nfunction breadcrumbItemsForPath(\n pagePath: string,\n): { name: string; path: string }[] {\n const normalized = normalizePagePath(pagePath);\n if (normalized === \"/\") return [{ name: \"Home\", path: \"/\" }];\n const segments = normalized.split(\"/\").filter(Boolean);\n const items = [{ name: \"Home\", path: \"/\" }];\n let current = \"\";\n for (const segment of segments) {\n current += `/${segment}`;\n items.push({\n name: titleFromSegment(segment),\n path: current,\n });\n }\n return items;\n}\n\nfunction titleFromSegment(segment: string): string {\n return segment\n .split(\"-\")\n .filter(Boolean)\n .map((part) => part.charAt(0).toUpperCase() + part.slice(1))\n .join(\" \");\n}\n\nfunction xmlEscape(value: string): string {\n return value\n .replace(/&/g, \"&amp;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\")\n .replace(/\"/g, \"&quot;\")\n .replace(/'/g, \"&apos;\");\n}\n"]}