@farm.js/core 0.1.25 → 0.1.26

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 (133) hide show
  1. package/dist/agent-runtime.d.mts +2 -2
  2. package/dist/agent-runtime.d.ts +2 -2
  3. package/dist/api/route-manager.d.mts +2 -2
  4. package/dist/api/route-manager.d.ts +2 -2
  5. package/dist/api.d.mts +3 -3
  6. package/dist/api.d.ts +3 -3
  7. package/dist/{app-ZuWrAMc_.d.mts → app-29vG5tmY.d.mts} +3 -3
  8. package/dist/{app-BF-ctoxh.d.ts → app-Cx71s_PT.d.ts} +3 -3
  9. package/dist/app-markdown.cjs +6 -4
  10. package/dist/app-markdown.d.mts +3 -3
  11. package/dist/app-markdown.d.ts +3 -3
  12. package/dist/app-markdown.mjs +5 -3
  13. package/dist/{chunk-E3RDL2DA.cjs → chunk-2CT6XUNO.cjs} +61 -31
  14. package/dist/{chunk-R7LCG3BT.cjs → chunk-3TQG7CGC.cjs} +84 -77
  15. package/dist/{chunk-AXYTGLF3.cjs → chunk-3WSWXPYM.cjs} +4 -4
  16. package/dist/{chunk-2BIJGZR3.mjs → chunk-74RZNRY6.mjs} +1 -1
  17. package/dist/{chunk-TTVHACQV.cjs → chunk-ALIFMS4A.cjs} +1 -1
  18. package/dist/{chunk-T2OPSH6S.mjs → chunk-ARXCHQLX.mjs} +9 -2
  19. package/dist/{chunk-2KI3CL3N.mjs → chunk-DU2CASV6.mjs} +1 -1
  20. package/dist/chunk-J63ZH5OQ.cjs +62 -0
  21. package/dist/{chunk-XM4ZDVD7.mjs → chunk-JM5GQL4H.mjs} +1 -1
  22. package/dist/{chunk-6VEHUKZ2.mjs → chunk-MM5D6VLP.mjs} +4 -20
  23. package/dist/chunk-MVL2RAJW.mjs +62 -0
  24. package/dist/{chunk-YA6LLTIJ.cjs → chunk-ND224OE2.cjs} +4 -20
  25. package/dist/{chunk-XME4TCLB.mjs → chunk-OFKG57MZ.mjs} +2 -2
  26. package/dist/{chunk-U4MP7XTD.mjs → chunk-OOIL3BWR.mjs} +168 -16
  27. package/dist/{chunk-WOI2HOGA.mjs → chunk-PPIW3MH6.mjs} +1 -1
  28. package/dist/{chunk-2ITKVAIF.cjs → chunk-QIH2HD6H.cjs} +191 -39
  29. package/dist/{chunk-65P6OGYN.cjs → chunk-QJ4D3UKJ.cjs} +10 -3
  30. package/dist/{chunk-RYDW7GPR.cjs → chunk-QLXEYIAW.cjs} +13 -13
  31. package/dist/{chunk-WJYCI56T.mjs → chunk-QPPQHB6X.mjs} +43 -30
  32. package/dist/{chunk-RR6UGYUT.mjs → chunk-RAI7NULA.mjs} +39 -9
  33. package/dist/{chunk-6K4SPQWL.cjs → chunk-RCYINC4A.cjs} +3 -3
  34. package/dist/{chunk-QYMRIVG6.cjs → chunk-SZ4LYNUX.cjs} +110 -97
  35. package/dist/{chunk-N2Z4ZFDE.mjs → chunk-UXQXGB5A.mjs} +19 -12
  36. package/dist/{chunk-CFNOGDUS.cjs → chunk-W2HZKYES.cjs} +2 -2
  37. package/dist/{chunk-O5DVPF3R.cjs → chunk-WFPRVVF2.cjs} +10 -10
  38. package/dist/{chunk-5YYJ6Q2L.mjs → chunk-YMUH2BLR.mjs} +2 -2
  39. package/dist/{client-plugins-DPG0NeZN.d.mts → client-plugins-B8RPJnot.d.mts} +90 -3
  40. package/dist/{client-plugins-Fgni-_25.d.ts → client-plugins-bPBf4haK.d.ts} +90 -3
  41. package/dist/client-plugins.d.mts +2 -2
  42. package/dist/client-plugins.d.ts +2 -2
  43. package/dist/client.d.mts +6 -6
  44. package/dist/client.d.ts +6 -6
  45. package/dist/config.d.mts +2 -2
  46. package/dist/config.d.ts +2 -2
  47. package/dist/{devtools-I7TBFOKD.mjs → devtools-5D4ZDRPR.mjs} +5 -3
  48. package/dist/{devtools-6OA7FEF6.cjs → devtools-QZJEUOJW.cjs} +6 -4
  49. package/dist/docs.cjs +8 -6
  50. package/dist/docs.mjs +7 -5
  51. package/dist/index.cjs +17 -13
  52. package/dist/index.d.mts +13 -13
  53. package/dist/index.d.ts +13 -13
  54. package/dist/index.mjs +16 -12
  55. package/dist/integrations.d.mts +2 -2
  56. package/dist/integrations.d.ts +2 -2
  57. package/dist/internal/app-markdown-runtime.cjs +5 -3
  58. package/dist/internal/app-markdown-runtime.d.mts +2 -2
  59. package/dist/internal/app-markdown-runtime.d.ts +2 -2
  60. package/dist/internal/app-markdown-runtime.mjs +4 -2
  61. package/dist/internal/build-runtime.cjs +14 -13
  62. package/dist/internal/build-runtime.d.mts +4 -4
  63. package/dist/internal/build-runtime.d.ts +4 -4
  64. package/dist/internal/build-runtime.mjs +13 -12
  65. package/dist/internal/cli-runtime.cjs +6 -5
  66. package/dist/internal/cli-runtime.mjs +5 -4
  67. package/dist/internal/client-error-overlay.cjs +4 -4
  68. package/dist/internal/client-error-overlay.mjs +1 -1
  69. package/dist/internal/compression-runtime.d.mts +2 -2
  70. package/dist/internal/compression-runtime.d.ts +2 -2
  71. package/dist/internal/config-runtime.cjs +6 -4
  72. package/dist/internal/config-runtime.d.mts +3 -3
  73. package/dist/internal/config-runtime.d.ts +3 -3
  74. package/dist/internal/config-runtime.mjs +5 -3
  75. package/dist/internal/infra-analytics-runtime.cjs +4 -3
  76. package/dist/internal/infra-analytics-runtime.mjs +2 -1
  77. package/dist/internal/product-telemetry-runtime.cjs +2 -2
  78. package/dist/internal/product-telemetry-runtime.mjs +1 -1
  79. package/dist/internal/production-runtime.cjs +5 -4
  80. package/dist/internal/production-runtime.d.mts +11 -9
  81. package/dist/internal/production-runtime.d.ts +11 -9
  82. package/dist/internal/production-runtime.mjs +4 -3
  83. package/dist/markdown.cjs +4 -2
  84. package/dist/markdown.mjs +3 -1
  85. package/dist/{metadata-D0EF7esB.d.mts → metadata-C3na4CBj.d.mts} +1 -1
  86. package/dist/{metadata-CDnRHKVq.d.ts → metadata-CzBP4Mfp.d.ts} +1 -1
  87. package/dist/middleware.d.mts +4 -4
  88. package/dist/middleware.d.ts +4 -4
  89. package/dist/navigation.d.mts +5 -5
  90. package/dist/navigation.d.ts +5 -5
  91. package/dist/observability-BupkiN0m.d.mts +447 -0
  92. package/dist/observability-BupkiN0m.d.ts +447 -0
  93. package/dist/observability.d.mts +2 -417
  94. package/dist/observability.d.ts +2 -417
  95. package/dist/plugin.cjs +9 -8
  96. package/dist/plugin.d.mts +2 -2
  97. package/dist/plugin.d.ts +2 -2
  98. package/dist/plugin.mjs +8 -7
  99. package/dist/{production-runtime-DpCt0opU.d.ts → production-runtime-CYg4wM4E.d.ts} +1 -1
  100. package/dist/{production-runtime-x3W4wVqx.d.mts → production-runtime-DP94hPGe.d.mts} +1 -1
  101. package/dist/{render-plan-D5oFRVBV.d.ts → render-plan-Bl6Fzg5z.d.ts} +1 -1
  102. package/dist/{render-plan-tazUJalK.d.mts → render-plan-CKAJg0jC.d.mts} +1 -1
  103. package/dist/renderer-client.d.mts +4 -4
  104. package/dist/renderer-client.d.ts +4 -4
  105. package/dist/{request-CzZX0Aew.d.ts → request-CR-Bp1Px.d.ts} +1 -1
  106. package/dist/{request-CXmQy5ks.d.mts → request-CrBCcPZZ.d.mts} +1 -1
  107. package/dist/request.d.mts +3 -3
  108. package/dist/request.d.ts +3 -3
  109. package/dist/{route-rendering-B-qpe32B.d.mts → route-rendering-C1NAHo-C.d.mts} +1 -1
  110. package/dist/{route-rendering-Dw3C362T.d.ts → route-rendering-CZH5FegB.d.ts} +1 -1
  111. package/dist/{router-CafM2jlw.d.mts → router-B57eDJ3u.d.mts} +1 -1
  112. package/dist/{router-CLl3xHwl.d.ts → router-Cg_kD3Bd.d.ts} +1 -1
  113. package/dist/routes.d.mts +2 -2
  114. package/dist/routes.d.ts +2 -2
  115. package/dist/server-plugins.d.mts +3 -3
  116. package/dist/server-plugins.d.ts +3 -3
  117. package/dist/server.cjs +159 -102
  118. package/dist/server.d.mts +8 -8
  119. package/dist/server.d.ts +8 -8
  120. package/dist/server.mjs +140 -83
  121. package/dist/{spa-router-DePr2aZ6.d.ts → spa-router-BstQUO6Q.d.ts} +2 -2
  122. package/dist/{spa-router-6sJfsMlQ.d.mts → spa-router-DTdbuinx.d.mts} +2 -2
  123. package/dist/testing.d.mts +2 -2
  124. package/dist/testing.d.ts +2 -2
  125. package/dist/{utils-BPHr-1mP.d.mts → utils-CS3ZLnEJ.d.mts} +1 -1
  126. package/dist/{utils-BBKC3cf3.d.ts → utils-D3rdsIvM.d.ts} +1 -1
  127. package/dist/version.cjs +2 -2
  128. package/dist/version.mjs +1 -1
  129. package/dist/vite.cjs +9 -8
  130. package/dist/vite.d.mts +2 -2
  131. package/dist/vite.d.ts +2 -2
  132. package/dist/vite.mjs +8 -7
  133. package/package.json +1 -1
@@ -3,7 +3,10 @@ import {
3
3
  } from "./chunk-XAXTTBUT.mjs";
4
4
  import {
5
5
  serializeFarmLlmsTxt
6
- } from "./chunk-RR6UGYUT.mjs";
6
+ } from "./chunk-RAI7NULA.mjs";
7
+ import {
8
+ emitFarmAgentRead
9
+ } from "./chunk-MVL2RAJW.mjs";
7
10
  import {
8
11
  resolveFarmThemeConfig
9
12
  } from "./chunk-AELACLOB.mjs";
@@ -201,6 +204,9 @@ function createFarmMetadataRouteResponse(kind, value, routeModule = {}, options
201
204
  if (method !== "GET" && method !== "HEAD") {
202
205
  return new Response(null, { status: 405, headers: { Allow: "GET, HEAD" } });
203
206
  }
207
+ if ((kind === "llms" || kind === "llms-full") && options.request) {
208
+ emitFarmAgentRead(options.request, kind, isResponse(value) ? value.status : 200);
209
+ }
204
210
  if (isResponse(value)) {
205
211
  return method === "HEAD" ? omitFarmResponseBody(value) : value;
206
212
  }
@@ -486,7 +492,7 @@ function createFarmApiCatalog(input) {
486
492
  };
487
493
  }
488
494
  __name(createFarmApiCatalog, "createFarmApiCatalog");
489
- function createFarmApiCatalogResponse(method, input) {
495
+ function createFarmApiCatalogResponse(method, input, request) {
490
496
  const upperMethod = method.toUpperCase();
491
497
  if (upperMethod !== "GET" && upperMethod !== "HEAD") {
492
498
  return new Response("Method Not Allowed", {
@@ -494,6 +500,7 @@ function createFarmApiCatalogResponse(method, input) {
494
500
  headers: { Allow: "GET, HEAD", "Content-Type": "text/plain; charset=utf-8" }
495
501
  });
496
502
  }
503
+ if (request) emitFarmAgentRead(request, "api-catalog", 200);
497
504
  const catalog = createFarmApiCatalog(input);
498
505
  return new Response(upperMethod === "HEAD" ? null : JSON.stringify(catalog), {
499
506
  status: 200,
@@ -15,7 +15,7 @@ import {
15
15
  } from "./chunk-TVGP4BBZ.mjs";
16
16
  import {
17
17
  farmAcceptQuality
18
- } from "./chunk-U4MP7XTD.mjs";
18
+ } from "./chunk-OOIL3BWR.mjs";
19
19
  import {
20
20
  matchesFarmIfNoneMatch
21
21
  } from "./chunk-XF7Q24PF.mjs";
@@ -0,0 +1,62 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } }
2
+
3
+ var _chunkE3UK5IIBcjs = require('./chunk-E3UK5IIB.cjs');
4
+
5
+
6
+ var _chunkS3JO3N4Hcjs = require('./chunk-S3JO3N4H.cjs');
7
+
8
+ // src/agent-identity.ts
9
+ var AGENT_TOKENS = [
10
+ ["ChatGPT-User", "openai", "agent"],
11
+ ["OAI-SearchBot", "openai", "crawler"],
12
+ ["GPTBot", "openai", "crawler"],
13
+ ["Claude-User", "anthropic", "agent"],
14
+ ["Claude-SearchBot", "anthropic", "crawler"],
15
+ ["ClaudeBot", "anthropic", "crawler"],
16
+ ["Perplexity-User", "perplexity", "agent"],
17
+ ["PerplexityBot", "perplexity", "crawler"],
18
+ ["CCBot", "other", "crawler"],
19
+ ["Bytespider", "other", "crawler"],
20
+ ["Meta-ExternalAgent", "other", "crawler"]
21
+ ];
22
+ var AGENT_PATTERNS = AGENT_TOKENS.map(([token, family, category]) => ({
23
+ pattern: new RegExp(`(?:^|[\\s;(])${token}(?=[/\\s;)]|$)`, "i"),
24
+ family,
25
+ category
26
+ }));
27
+ var UNKNOWN = { family: "unknown", category: "unknown", identity: "unknown" };
28
+ function classifyFarmAgent(userAgent) {
29
+ const value = (_nullishCoalesce(userAgent, () => ( ""))).slice(0, 2048);
30
+ const matches = AGENT_PATTERNS.filter(({ pattern }) => pattern.test(value));
31
+ if (matches.length === 1) {
32
+ const { family, category } = matches[0];
33
+ return { family, category, identity: "self-reported" };
34
+ }
35
+ return { ...UNKNOWN };
36
+ }
37
+ _chunkS3JO3N4Hcjs.__name.call(void 0, classifyFarmAgent, "classifyFarmAgent");
38
+ var FARM_INTERNAL_READ_HEADER = "x-farm-internal-read";
39
+ function emitFarmAgentRead(request, surface, status, view) {
40
+ if (request.headers.has(FARM_INTERNAL_READ_HEADER)) return;
41
+ let route;
42
+ try {
43
+ route = new URL(request.url).pathname;
44
+ } catch (e) {
45
+ return;
46
+ }
47
+ _chunkE3UK5IIBcjs.emitFarmEvent.call(void 0, {
48
+ type: "agent.read",
49
+ surface,
50
+ route,
51
+ ...view ? { view } : {},
52
+ status,
53
+ agent: classifyFarmAgent(request.headers.get("user-agent"))
54
+ });
55
+ }
56
+ _chunkS3JO3N4Hcjs.__name.call(void 0, emitFarmAgentRead, "emitFarmAgentRead");
57
+
58
+
59
+
60
+
61
+
62
+ exports.classifyFarmAgent = classifyFarmAgent; exports.FARM_INTERNAL_READ_HEADER = FARM_INTERNAL_READ_HEADER; exports.emitFarmAgentRead = emitFarmAgentRead;
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  createFarmMarkdownViewResponse,
3
3
  requestAcceptsMarkdown
4
- } from "./chunk-U4MP7XTD.mjs";
4
+ } from "./chunk-OOIL3BWR.mjs";
5
5
  import {
6
6
  __name
7
7
  } from "./chunk-LPEX4YW6.mjs";
@@ -1,3 +1,6 @@
1
+ import {
2
+ classifyFarmAgent
3
+ } from "./chunk-MVL2RAJW.mjs";
1
4
  import {
2
5
  onFarmEvent
3
6
  } from "./chunk-FUZEBRP3.mjs";
@@ -74,27 +77,8 @@ function resolveFarmInfraAnalytics(env = processEnv()) {
74
77
  };
75
78
  }
76
79
  __name(resolveFarmInfraAnalytics, "resolveFarmInfraAnalytics");
77
- var AGENT_TOKENS = [
78
- ["ChatGPT-User", "openai", "agent"],
79
- ["OAI-SearchBot", "openai", "crawler"],
80
- ["GPTBot", "openai", "crawler"],
81
- ["Claude-User", "anthropic", "agent"],
82
- ["Claude-SearchBot", "anthropic", "crawler"],
83
- ["ClaudeBot", "anthropic", "crawler"]
84
- ];
85
- var AGENT_PATTERNS = AGENT_TOKENS.map(([token, family, category]) => ({
86
- pattern: new RegExp(`(?:^|[\\s;(])${token}(?=[/\\s;)]|$)`, "i"),
87
- family,
88
- category
89
- }));
90
80
  function classifyFarmInfraAgent(userAgent) {
91
- const value = (userAgent ?? "").slice(0, 2048);
92
- const matches = AGENT_PATTERNS.filter(({ pattern }) => pattern.test(value));
93
- if (matches.length === 1) {
94
- const { family, category } = matches[0];
95
- return { family, category, identity: "self-reported" };
96
- }
97
- return { family: "unknown", category: "unknown", identity: "unknown" };
81
+ return classifyFarmAgent(userAgent);
98
82
  }
99
83
  __name(classifyFarmInfraAgent, "classifyFarmInfraAgent");
100
84
  function routeTemplate(pattern) {
@@ -0,0 +1,62 @@
1
+ import {
2
+ emitFarmEvent
3
+ } from "./chunk-FUZEBRP3.mjs";
4
+ import {
5
+ __name
6
+ } from "./chunk-LPEX4YW6.mjs";
7
+
8
+ // src/agent-identity.ts
9
+ var AGENT_TOKENS = [
10
+ ["ChatGPT-User", "openai", "agent"],
11
+ ["OAI-SearchBot", "openai", "crawler"],
12
+ ["GPTBot", "openai", "crawler"],
13
+ ["Claude-User", "anthropic", "agent"],
14
+ ["Claude-SearchBot", "anthropic", "crawler"],
15
+ ["ClaudeBot", "anthropic", "crawler"],
16
+ ["Perplexity-User", "perplexity", "agent"],
17
+ ["PerplexityBot", "perplexity", "crawler"],
18
+ ["CCBot", "other", "crawler"],
19
+ ["Bytespider", "other", "crawler"],
20
+ ["Meta-ExternalAgent", "other", "crawler"]
21
+ ];
22
+ var AGENT_PATTERNS = AGENT_TOKENS.map(([token, family, category]) => ({
23
+ pattern: new RegExp(`(?:^|[\\s;(])${token}(?=[/\\s;)]|$)`, "i"),
24
+ family,
25
+ category
26
+ }));
27
+ var UNKNOWN = { family: "unknown", category: "unknown", identity: "unknown" };
28
+ function classifyFarmAgent(userAgent) {
29
+ const value = (userAgent ?? "").slice(0, 2048);
30
+ const matches = AGENT_PATTERNS.filter(({ pattern }) => pattern.test(value));
31
+ if (matches.length === 1) {
32
+ const { family, category } = matches[0];
33
+ return { family, category, identity: "self-reported" };
34
+ }
35
+ return { ...UNKNOWN };
36
+ }
37
+ __name(classifyFarmAgent, "classifyFarmAgent");
38
+ var FARM_INTERNAL_READ_HEADER = "x-farm-internal-read";
39
+ function emitFarmAgentRead(request, surface, status, view) {
40
+ if (request.headers.has(FARM_INTERNAL_READ_HEADER)) return;
41
+ let route;
42
+ try {
43
+ route = new URL(request.url).pathname;
44
+ } catch {
45
+ return;
46
+ }
47
+ emitFarmEvent({
48
+ type: "agent.read",
49
+ surface,
50
+ route,
51
+ ...view ? { view } : {},
52
+ status,
53
+ agent: classifyFarmAgent(request.headers.get("user-agent"))
54
+ });
55
+ }
56
+ __name(emitFarmAgentRead, "emitFarmAgentRead");
57
+
58
+ export {
59
+ classifyFarmAgent,
60
+ FARM_INTERNAL_READ_HEADER,
61
+ emitFarmAgentRead
62
+ };
@@ -1,5 +1,8 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
2
2
 
3
+ var _chunkJ63ZH5OQcjs = require('./chunk-J63ZH5OQ.cjs');
4
+
5
+
3
6
  var _chunkE3UK5IIBcjs = require('./chunk-E3UK5IIB.cjs');
4
7
 
5
8
 
@@ -74,27 +77,8 @@ function resolveFarmInfraAnalytics(env = processEnv()) {
74
77
  };
75
78
  }
76
79
  _chunkS3JO3N4Hcjs.__name.call(void 0, resolveFarmInfraAnalytics, "resolveFarmInfraAnalytics");
77
- var AGENT_TOKENS = [
78
- ["ChatGPT-User", "openai", "agent"],
79
- ["OAI-SearchBot", "openai", "crawler"],
80
- ["GPTBot", "openai", "crawler"],
81
- ["Claude-User", "anthropic", "agent"],
82
- ["Claude-SearchBot", "anthropic", "crawler"],
83
- ["ClaudeBot", "anthropic", "crawler"]
84
- ];
85
- var AGENT_PATTERNS = AGENT_TOKENS.map(([token, family, category]) => ({
86
- pattern: new RegExp(`(?:^|[\\s;(])${token}(?=[/\\s;)]|$)`, "i"),
87
- family,
88
- category
89
- }));
90
80
  function classifyFarmInfraAgent(userAgent) {
91
- const value = (_nullishCoalesce(userAgent, () => ( ""))).slice(0, 2048);
92
- const matches = AGENT_PATTERNS.filter(({ pattern }) => pattern.test(value));
93
- if (matches.length === 1) {
94
- const { family, category } = matches[0];
95
- return { family, category, identity: "self-reported" };
96
- }
97
- return { family: "unknown", category: "unknown", identity: "unknown" };
81
+ return _chunkJ63ZH5OQcjs.classifyFarmAgent.call(void 0, userAgent);
98
82
  }
99
83
  _chunkS3JO3N4Hcjs.__name.call(void 0, classifyFarmInfraAgent, "classifyFarmInfraAgent");
100
84
  function routeTemplate(pattern) {
@@ -3,14 +3,14 @@ import {
3
3
  loadFarmDocsPage,
4
4
  resolveFarmDocsContentDir,
5
5
  toFarmDocsMarkdownPage
6
- } from "./chunk-2KI3CL3N.mjs";
6
+ } from "./chunk-DU2CASV6.mjs";
7
7
  import {
8
8
  docsEngine,
9
9
  loadFarmDocsEngine
10
10
  } from "./chunk-2VQKKQ6D.mjs";
11
11
  import {
12
12
  resolveDocsConfig
13
- } from "./chunk-5YYJ6Q2L.mjs";
13
+ } from "./chunk-YMUH2BLR.mjs";
14
14
  import {
15
15
  getFarmDocsAdapterConfigModule
16
16
  } from "./chunk-VVBO3QH7.mjs";
@@ -1,3 +1,6 @@
1
+ import {
2
+ emitFarmAgentRead
3
+ } from "./chunk-MVL2RAJW.mjs";
1
4
  import {
2
5
  __name
3
6
  } from "./chunk-LPEX4YW6.mjs";
@@ -39,10 +42,12 @@ function parseFarmMarkdownHeadings(markdown) {
39
42
  end: lines.length
40
43
  });
41
44
  }
42
- for (let headingIndex = 0; headingIndex < headings.length; headingIndex++) {
43
- const heading = headings[headingIndex];
44
- const next = headings.slice(headingIndex + 1).find((candidate) => candidate.level <= heading.level);
45
- if (next) heading.end = next.start;
45
+ const open = [];
46
+ for (const heading of headings) {
47
+ while (open.length > 0 && open[open.length - 1].level >= heading.level) {
48
+ open.pop().end = heading.start;
49
+ }
50
+ open.push(heading);
46
51
  }
47
52
  return headings;
48
53
  }
@@ -55,23 +60,49 @@ function estimateFarmMarkdownTokens(text) {
55
60
  return Math.ceil(text.length / 4);
56
61
  }
57
62
  __name(estimateFarmMarkdownTokens, "estimateFarmMarkdownTokens");
63
+ var FARM_MARKDOWN_MIN_TOKEN_BUDGET = 100;
64
+ var FARM_MARKDOWN_VIEW_PARAMS = [
65
+ "outline",
66
+ "section",
67
+ "actions",
68
+ "max_tokens",
69
+ "cursor"
70
+ ];
58
71
  function selectFarmMarkdownView(markdown, searchParams, markdownPath) {
59
72
  const wantsOutline = searchParams.has("outline");
60
73
  const sectionId = searchParams.get("section");
61
- if (!wantsOutline && sectionId === null) return { status: 200, body: markdown };
74
+ const budget = searchParams.get("max_tokens");
75
+ if (!wantsOutline && sectionId === null && budget === null)
76
+ return { status: 200, body: markdown };
77
+ const viewUrl = /* @__PURE__ */ __name((view) => {
78
+ const query = new URLSearchParams(searchParams);
79
+ for (const name of FARM_MARKDOWN_VIEW_PARAMS) query.delete(name);
80
+ for (const [name, value] of Object.entries(view)) {
81
+ if (value !== null && value !== void 0) query.set(name, value);
82
+ }
83
+ const search = query.toString();
84
+ return search ? `${markdownPath}?${search}` : markdownPath;
85
+ }, "viewUrl");
86
+ const withinBudget = /* @__PURE__ */ __name((document) => budget === null ? { status: 200, body: document } : selectFarmMarkdownPart(
87
+ document,
88
+ budget,
89
+ searchParams.get("cursor"),
90
+ (cursor) => viewUrl({ section: sectionId, max_tokens: budget, cursor })
91
+ ), "withinBudget");
92
+ if (!wantsOutline && sectionId === null) return withinBudget(markdown);
62
93
  const lines = markdown.split("\n");
63
94
  const headings = parseFarmMarkdownHeadings(markdown);
64
95
  const sectionText = /* @__PURE__ */ __name((heading) => lines.slice(heading.start, heading.end).join("\n").trim(), "sectionText");
65
96
  if (sectionId !== null) {
66
97
  const heading = headings.find((candidate) => candidate.id === sectionId);
67
- if (heading) return { status: 200, body: `${sectionText(heading)}
68
- ` };
98
+ if (heading) return withinBudget(`${sectionText(heading)}
99
+ `);
69
100
  const available = headings.map((candidate) => `- \`${candidate.id}\``).join("\n");
70
101
  return {
71
102
  status: 404,
72
103
  body: `# Section not found
73
104
 
74
- \`${sectionId}\` is not a section of ${markdownPath}.
105
+ ${markdownCodeSpan(sectionId)} is not a section of ${markdownPath}.
75
106
 
76
107
  ` + (available ? `Available sections:
77
108
 
@@ -79,23 +110,31 @@ ${available}
79
110
  ` : "This page has no sections.\n")
80
111
  };
81
112
  }
82
- const minLevel = Math.min(...headings.map((heading) => heading.level));
113
+ const minLevel = headings.reduce((min, heading) => Math.min(min, heading.level), 6);
83
114
  const entries = headings.map((heading) => {
84
115
  const indent = " ".repeat(heading.level - minLevel);
85
116
  const tokens = estimateFarmMarkdownTokens(sectionText(heading));
86
- return `${indent}- [${heading.text}](${markdownPath}?section=${encodeURIComponent(heading.id)}) ~${tokens} tokens`;
117
+ return `${indent}- [${heading.text}](${viewUrl({ section: heading.id })}) ~${tokens} tokens`;
87
118
  });
88
119
  return {
89
120
  status: 200,
90
121
  body: `# Outline of ${markdownPath}
91
122
 
92
- About ${estimateFarmMarkdownTokens(markdown)} tokens in total. Request one section with \`?section=<id>\`.
123
+ About ${estimateFarmMarkdownTokens(markdown)} tokens in total. Request one section with \`?section=<id>\`, or read in parts with \`?max_tokens=<n>\`.
93
124
 
94
125
  ` + (entries.length > 0 ? `${entries.join("\n")}
95
126
  ` : "This page has no headings.\n")
96
127
  };
97
128
  }
98
129
  __name(selectFarmMarkdownView, "selectFarmMarkdownView");
130
+ function markdownCodeSpan(value) {
131
+ const text = value.replace(/[\p{Cc}\u2028\u2029]+/gu, " ");
132
+ const longestRun = (text.match(/`+/g) ?? []).reduce((max, run) => Math.max(max, run.length), 0);
133
+ const fence = "`".repeat(longestRun + 1);
134
+ const pad = text.startsWith("`") || text.endsWith("`") ? " " : "";
135
+ return `${fence}${pad}${text}${pad}${fence}`;
136
+ }
137
+ __name(markdownCodeSpan, "markdownCodeSpan");
99
138
  function selectFarmPageActionsView(markdownPath, actions, headers) {
100
139
  headers.set("Content-Type", "application/json; charset=utf-8");
101
140
  const page = markdownPath === "/index.md" ? "/" : markdownPath.replace(/\.md$/, "");
@@ -106,7 +145,117 @@ function selectFarmPageActionsView(markdownPath, actions, headers) {
106
145
  };
107
146
  }
108
147
  __name(selectFarmPageActionsView, "selectFarmPageActionsView");
148
+ function selectFarmMarkdownPart(document, rawBudget, rawCursor, partUrl) {
149
+ const budget = /^\d{1,9}$/.test(rawBudget) ? Number(rawBudget) : Number.NaN;
150
+ if (!(budget >= FARM_MARKDOWN_MIN_TOKEN_BUDGET)) {
151
+ return {
152
+ status: 400,
153
+ body: `# Invalid max_tokens
154
+
155
+ \`max_tokens\` must be a whole number of at least ${FARM_MARKDOWN_MIN_TOKEN_BUDGET}.
156
+ `
157
+ };
158
+ }
159
+ const lines = document.replace(/\n$/, "").split("\n");
160
+ const version = hashFarmMarkdown(document).slice(0, 8);
161
+ let start = 0;
162
+ if (rawCursor !== null) {
163
+ const match = /^(\d{1,9})\.([0-9a-z]+)$/.exec(rawCursor);
164
+ if (!match || Number(match[1]) <= 0 || Number(match[1]) >= lines.length) {
165
+ return {
166
+ status: 400,
167
+ body: `# Invalid cursor
168
+
169
+ Start again at ${partUrl()}.
170
+ `
171
+ };
172
+ }
173
+ if (match[2] !== version) {
174
+ return {
175
+ status: 409,
176
+ body: `# Page changed
177
+
178
+ The page changed after this cursor was issued. Start again at ${partUrl()}.
179
+ `
180
+ };
181
+ }
182
+ start = Number(match[1]);
183
+ }
184
+ const fences = readOpenFences(lines);
185
+ const reopen = fences[start];
186
+ const room = budget * 4 - 200;
187
+ let size = reopen ? reopen.opener.length + 1 : 0;
188
+ let end = start;
189
+ let lastBreak = -1;
190
+ while (end < lines.length) {
191
+ const length = lines[end].length + 1;
192
+ if (end > start && size + length > room) break;
193
+ size += length;
194
+ end++;
195
+ if (end < lines.length && isPartBreak(lines, fences, end)) lastBreak = end;
196
+ }
197
+ const head = reopen ? `${reopen.opener}
198
+ ` : "";
199
+ if (end >= lines.length) {
200
+ return { status: 200, body: `${head}${lines.slice(start).join("\n")}
201
+ ` };
202
+ }
203
+ if (lastBreak > start) end = lastBreak;
204
+ const open = fences[end];
205
+ const part = `${head}${lines.slice(start, end).join("\n").replace(/\n+$/, "")}${open ? `
206
+ ${open.closer}` : ""}`;
207
+ const next = partUrl(`${end}.${version}`);
208
+ const remaining = estimateFarmMarkdownTokens(lines.slice(end).join("\n"));
209
+ return {
210
+ status: 200,
211
+ body: `${part}
212
+
213
+ ---
214
+
215
+ Continue: ${next} (about ${remaining} more tokens)
216
+ `,
217
+ headers: { Link: `<${next}>; rel="next"` }
218
+ };
219
+ }
220
+ __name(selectFarmMarkdownPart, "selectFarmMarkdownPart");
221
+ function readOpenFences(lines) {
222
+ const open = [];
223
+ let fence;
224
+ let frontMatter = lines[0]?.trim() === "---";
225
+ for (let index = 0; index < lines.length; index++) {
226
+ open.push(frontMatter && index > 0 ? { opener: "", closer: "" } : fence);
227
+ const line = lines[index];
228
+ if (frontMatter) {
229
+ if (index > 0 && line.trim() === "---") frontMatter = false;
230
+ continue;
231
+ }
232
+ const match = FENCE.exec(line);
233
+ if (!match) continue;
234
+ const marker = match[1];
235
+ if (!fence) fence = { opener: line.trim(), closer: marker, marker };
236
+ else if (marker[0] === fence.marker[0] && marker.length >= fence.marker.length)
237
+ fence = void 0;
238
+ }
239
+ return open;
240
+ }
241
+ __name(readOpenFences, "readOpenFences");
242
+ function isPartBreak(lines, fences, index) {
243
+ if (fences[index]) return false;
244
+ return lines[index - 1].trim() === "" || ATX_HEADING.test(lines[index]);
245
+ }
246
+ __name(isPartBreak, "isPartBreak");
247
+ function readMarkdownViewName(searchParams) {
248
+ if (searchParams.has("actions")) return "actions";
249
+ if (searchParams.has("outline")) return "outline";
250
+ if (searchParams.has("max_tokens")) return "parts";
251
+ return searchParams.has("section") ? "section" : void 0;
252
+ }
253
+ __name(readMarkdownViewName, "readMarkdownViewName");
109
254
  function createFarmMarkdownETag(body) {
255
+ return `W/"${hashFarmMarkdown(body)}-${body.length.toString(36)}"`;
256
+ }
257
+ __name(createFarmMarkdownETag, "createFarmMarkdownETag");
258
+ function hashFarmMarkdown(body) {
110
259
  let h1 = 3735928559;
111
260
  let h2 = 1103547991;
112
261
  for (let index = 0; index < body.length; index++) {
@@ -116,10 +265,9 @@ function createFarmMarkdownETag(body) {
116
265
  }
117
266
  h1 = Math.imul(h1 ^ h1 >>> 16, 2246822507) ^ Math.imul(h2 ^ h2 >>> 13, 3266489909);
118
267
  h2 = Math.imul(h2 ^ h2 >>> 16, 2246822507) ^ Math.imul(h1 ^ h1 >>> 13, 3266489909);
119
- const hash = (4294967296 * (2097151 & h2) + (h1 >>> 0)).toString(36);
120
- return `W/"${hash}-${body.length.toString(36)}"`;
268
+ return (4294967296 * (2097151 & h2) + (h1 >>> 0)).toString(36);
121
269
  }
122
- __name(createFarmMarkdownETag, "createFarmMarkdownETag");
270
+ __name(hashFarmMarkdown, "hashFarmMarkdown");
123
271
  function ifNoneMatchIncludes(header, etag) {
124
272
  if (!header) return false;
125
273
  const opaque = etag.replace(/^W\//, "");
@@ -130,6 +278,9 @@ function createFarmMarkdownViewResponse(options) {
130
278
  const url = options.requestUrl ?? new URL(options.request.url);
131
279
  const view = url.searchParams.has("actions") ? selectFarmPageActionsView(options.markdownPath, options.actions ?? [], options.headers) : selectFarmMarkdownView(options.markdown, url.searchParams, options.markdownPath);
132
280
  const status = view.status === 200 ? options.status : view.status;
281
+ emitFarmAgentRead(options.request, "markdown", status, readMarkdownViewName(url.searchParams));
282
+ for (const [name, value] of Object.entries(view.headers ?? {}))
283
+ options.headers.append(name, value);
133
284
  const etag = createFarmMarkdownETag(view.body);
134
285
  options.headers.set("ETag", etag);
135
286
  if (status === 200 && ifNoneMatchIncludes(options.request.headers.get("if-none-match"), etag)) {
@@ -220,7 +371,7 @@ async function createMarkdownMirrorResponse(options) {
220
371
  }
221
372
  const pageUrl = new URL(options.request.url);
222
373
  pageUrl.pathname = target.pathname;
223
- for (const name of ["outline", "section", "actions"]) pageUrl.searchParams.delete(name);
374
+ for (const name of FARM_MARKDOWN_VIEW_PARAMS) pageUrl.searchParams.delete(name);
224
375
  const headers = new Headers(options.request.headers);
225
376
  headers.set("accept", "text/html");
226
377
  const pageResponse = await options.renderPage(
@@ -229,7 +380,8 @@ async function createMarkdownMirrorResponse(options) {
229
380
  headers
230
381
  })
231
382
  );
232
- if (!isHtmlResponse(pageResponse)) {
383
+ const redirects = pageResponse.status >= 300 && pageResponse.status < 400 && pageResponse.headers.has("location");
384
+ if (redirects || !isHtmlResponse(pageResponse)) {
233
385
  return createMarkdownAccessResponse(
234
386
  pageResponse,
235
387
  target.pathname,
@@ -1,5 +1,5 @@
1
1
  // package.json
2
- var version = "0.1.25";
2
+ var version = "0.1.26";
3
3
 
4
4
  // src/version.ts
5
5
  var FARM_VERSION = version;