@noodleseed/one 0.126.0 → 0.127.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.
Files changed (214) hide show
  1. package/dist/commands/knowledge.d.ts.map +1 -1
  2. package/dist/commands/knowledge.js +27 -9
  3. package/dist/commands/knowledge.js.map +1 -1
  4. package/dist/index.d.ts +1 -1
  5. package/dist/index.d.ts.map +1 -1
  6. package/dist/index.js +1 -1
  7. package/dist/index.js.map +1 -1
  8. package/node_modules/@noodle-borg/agent-kit/dist/curated/command-groups.js +1 -1
  9. package/node_modules/@noodle-borg/agent-kit/dist/curated/command-groups.js.map +1 -1
  10. package/node_modules/@noodle-borg/agent-kit/dist/generated/example-files.js +1 -1
  11. package/node_modules/@noodle-borg/agent-kit/dist/generated/example-files.js.map +1 -1
  12. package/node_modules/@noodle-borg/agent-kit/dist/generated/surface.d.ts.map +1 -1
  13. package/node_modules/@noodle-borg/agent-kit/dist/generated/surface.js +4 -0
  14. package/node_modules/@noodle-borg/agent-kit/dist/generated/surface.js.map +1 -1
  15. package/node_modules/@noodle-borg/agent-kit/dist/skill-authoring-refs.d.ts.map +1 -1
  16. package/node_modules/@noodle-borg/agent-kit/dist/skill-authoring-refs.js +4 -2
  17. package/node_modules/@noodle-borg/agent-kit/dist/skill-authoring-refs.js.map +1 -1
  18. package/node_modules/@noodle-borg/agent-kit/dist/skill-embedded-assistant-ref.d.ts.map +1 -1
  19. package/node_modules/@noodle-borg/agent-kit/dist/skill-embedded-assistant-ref.js +2 -0
  20. package/node_modules/@noodle-borg/agent-kit/dist/skill-embedded-assistant-ref.js.map +1 -1
  21. package/node_modules/@noodle-borg/agent-kit/package.json +1 -1
  22. package/node_modules/@noodle-borg/assistant-gateway/package.json +1 -1
  23. package/node_modules/@noodle-borg/authoring/dist/index.d.ts +1 -1
  24. package/node_modules/@noodle-borg/authoring/dist/index.d.ts.map +1 -1
  25. package/node_modules/@noodle-borg/authoring/dist/index.js +1 -1
  26. package/node_modules/@noodle-borg/authoring/dist/index.js.map +1 -1
  27. package/node_modules/@noodle-borg/authoring/dist/knowledge.d.ts +66 -2
  28. package/node_modules/@noodle-borg/authoring/dist/knowledge.d.ts.map +1 -1
  29. package/node_modules/@noodle-borg/authoring/dist/knowledge.js +54 -2
  30. package/node_modules/@noodle-borg/authoring/dist/knowledge.js.map +1 -1
  31. package/node_modules/@noodle-borg/cli-catalog/dist/catalog-data-hosted-observability.d.ts.map +1 -1
  32. package/node_modules/@noodle-borg/cli-catalog/dist/catalog-data-hosted-observability.js +17 -1
  33. package/node_modules/@noodle-borg/cli-catalog/dist/catalog-data-hosted-observability.js.map +1 -1
  34. package/node_modules/@noodle-borg/compiler/dist/manifest/schema.d.ts +58 -0
  35. package/node_modules/@noodle-borg/compiler/dist/manifest/schema.d.ts.map +1 -1
  36. package/node_modules/@noodle-borg/knowledge/dist/algolia-index.d.ts +30 -0
  37. package/node_modules/@noodle-borg/knowledge/dist/algolia-index.d.ts.map +1 -0
  38. package/node_modules/@noodle-borg/knowledge/dist/algolia-index.js +141 -0
  39. package/node_modules/@noodle-borg/knowledge/dist/algolia-index.js.map +1 -0
  40. package/node_modules/@noodle-borg/knowledge/dist/compile.d.ts +4 -0
  41. package/node_modules/@noodle-borg/knowledge/dist/compile.d.ts.map +1 -1
  42. package/node_modules/@noodle-borg/knowledge/dist/compile.js +3 -0
  43. package/node_modules/@noodle-borg/knowledge/dist/compile.js.map +1 -1
  44. package/node_modules/@noodle-borg/knowledge/dist/google-agent-search.d.ts +2 -15
  45. package/node_modules/@noodle-borg/knowledge/dist/google-agent-search.d.ts.map +1 -1
  46. package/node_modules/@noodle-borg/knowledge/dist/google-agent-search.js +0 -59
  47. package/node_modules/@noodle-borg/knowledge/dist/google-agent-search.js.map +1 -1
  48. package/node_modules/@noodle-borg/knowledge/dist/index.d.ts +2 -0
  49. package/node_modules/@noodle-borg/knowledge/dist/index.d.ts.map +1 -1
  50. package/node_modules/@noodle-borg/knowledge/dist/index.js +2 -0
  51. package/node_modules/@noodle-borg/knowledge/dist/index.js.map +1 -1
  52. package/node_modules/@noodle-borg/knowledge/dist/limits.d.ts +6 -0
  53. package/node_modules/@noodle-borg/knowledge/dist/limits.d.ts.map +1 -1
  54. package/node_modules/@noodle-borg/knowledge/dist/limits.js +6 -0
  55. package/node_modules/@noodle-borg/knowledge/dist/limits.js.map +1 -1
  56. package/node_modules/@noodle-borg/knowledge/dist/manifest-schema.d.ts +58 -0
  57. package/node_modules/@noodle-borg/knowledge/dist/manifest-schema.d.ts.map +1 -1
  58. package/node_modules/@noodle-borg/knowledge/dist/manifest-schema.js +28 -0
  59. package/node_modules/@noodle-borg/knowledge/dist/manifest-schema.js.map +1 -1
  60. package/node_modules/@noodle-borg/knowledge/dist/meilisearch-index.d.ts +33 -0
  61. package/node_modules/@noodle-borg/knowledge/dist/meilisearch-index.d.ts.map +1 -0
  62. package/node_modules/@noodle-borg/knowledge/dist/meilisearch-index.js +153 -0
  63. package/node_modules/@noodle-borg/knowledge/dist/meilisearch-index.js.map +1 -0
  64. package/node_modules/@noodle-borg/knowledge/dist/postgres-revision-store.d.ts +1 -0
  65. package/node_modules/@noodle-borg/knowledge/dist/postgres-revision-store.d.ts.map +1 -1
  66. package/node_modules/@noodle-borg/knowledge/dist/postgres-revision-store.js +3 -0
  67. package/node_modules/@noodle-borg/knowledge/dist/postgres-revision-store.js.map +1 -1
  68. package/node_modules/@noodle-borg/knowledge/dist/provider-index-shared.d.ts +19 -0
  69. package/node_modules/@noodle-borg/knowledge/dist/provider-index-shared.d.ts.map +1 -0
  70. package/node_modules/@noodle-borg/knowledge/dist/provider-index-shared.js +47 -0
  71. package/node_modules/@noodle-borg/knowledge/dist/provider-index-shared.js.map +1 -0
  72. package/node_modules/@noodle-borg/knowledge/dist/revision-store.d.ts +7 -0
  73. package/node_modules/@noodle-borg/knowledge/dist/revision-store.d.ts.map +1 -1
  74. package/node_modules/@noodle-borg/knowledge/dist/revision-store.js +4 -0
  75. package/node_modules/@noodle-borg/knowledge/dist/revision-store.js.map +1 -1
  76. package/node_modules/@noodle-borg/knowledge-crawl/dist/bounds.d.ts +3 -0
  77. package/node_modules/@noodle-borg/knowledge-crawl/dist/bounds.d.ts.map +1 -0
  78. package/node_modules/@noodle-borg/knowledge-crawl/dist/bounds.js +30 -0
  79. package/node_modules/@noodle-borg/knowledge-crawl/dist/bounds.js.map +1 -0
  80. package/node_modules/@noodle-borg/knowledge-crawl/dist/firecrawl.d.ts +13 -0
  81. package/node_modules/@noodle-borg/knowledge-crawl/dist/firecrawl.d.ts.map +1 -0
  82. package/node_modules/@noodle-borg/knowledge-crawl/dist/firecrawl.js +90 -0
  83. package/node_modules/@noodle-borg/knowledge-crawl/dist/firecrawl.js.map +1 -0
  84. package/node_modules/@noodle-borg/knowledge-crawl/dist/first-party.d.ts +11 -0
  85. package/node_modules/@noodle-borg/knowledge-crawl/dist/first-party.d.ts.map +1 -0
  86. package/node_modules/@noodle-borg/knowledge-crawl/dist/first-party.js +108 -0
  87. package/node_modules/@noodle-borg/knowledge-crawl/dist/first-party.js.map +1 -0
  88. package/node_modules/@noodle-borg/knowledge-crawl/dist/html-text.d.ts +19 -0
  89. package/node_modules/@noodle-borg/knowledge-crawl/dist/html-text.d.ts.map +1 -0
  90. package/node_modules/@noodle-borg/knowledge-crawl/dist/html-text.js +62 -0
  91. package/node_modules/@noodle-borg/knowledge-crawl/dist/html-text.js.map +1 -0
  92. package/node_modules/@noodle-borg/knowledge-crawl/dist/index.d.ts +5 -0
  93. package/node_modules/@noodle-borg/knowledge-crawl/dist/index.d.ts.map +1 -0
  94. package/node_modules/@noodle-borg/knowledge-crawl/dist/index.js +4 -0
  95. package/node_modules/@noodle-borg/knowledge-crawl/dist/index.js.map +1 -0
  96. package/node_modules/@noodle-borg/knowledge-crawl/dist/origin.d.ts +3 -0
  97. package/node_modules/@noodle-borg/knowledge-crawl/dist/origin.d.ts.map +1 -0
  98. package/node_modules/@noodle-borg/knowledge-crawl/dist/origin.js +30 -0
  99. package/node_modules/@noodle-borg/knowledge-crawl/dist/origin.js.map +1 -0
  100. package/node_modules/@noodle-borg/knowledge-crawl/dist/ports.d.ts +28 -0
  101. package/node_modules/@noodle-borg/knowledge-crawl/dist/ports.d.ts.map +1 -0
  102. package/node_modules/@noodle-borg/knowledge-crawl/dist/ports.js +8 -0
  103. package/node_modules/@noodle-borg/knowledge-crawl/dist/ports.js.map +1 -0
  104. package/node_modules/@noodle-borg/knowledge-crawl/dist/robots.d.ts +12 -0
  105. package/node_modules/@noodle-borg/knowledge-crawl/dist/robots.d.ts.map +1 -0
  106. package/node_modules/@noodle-borg/knowledge-crawl/dist/robots.js +64 -0
  107. package/node_modules/@noodle-borg/knowledge-crawl/dist/robots.js.map +1 -0
  108. package/node_modules/@noodle-borg/knowledge-crawl/dist/sitemap.d.ts +3 -0
  109. package/node_modules/@noodle-borg/knowledge-crawl/dist/sitemap.d.ts.map +1 -0
  110. package/node_modules/@noodle-borg/knowledge-crawl/dist/sitemap.js +11 -0
  111. package/node_modules/@noodle-borg/knowledge-crawl/dist/sitemap.js.map +1 -0
  112. package/node_modules/@noodle-borg/knowledge-crawl/dist/tavily.d.ts +11 -0
  113. package/node_modules/@noodle-borg/knowledge-crawl/dist/tavily.d.ts.map +1 -0
  114. package/node_modules/@noodle-borg/knowledge-crawl/dist/tavily.js +53 -0
  115. package/node_modules/@noodle-borg/knowledge-crawl/dist/tavily.js.map +1 -0
  116. package/node_modules/@noodle-borg/knowledge-crawl/package.json +32 -0
  117. package/node_modules/@noodle-borg/knowledge-operations/dist/crawl-lifecycle.d.ts +71 -0
  118. package/node_modules/@noodle-borg/knowledge-operations/dist/crawl-lifecycle.d.ts.map +1 -0
  119. package/node_modules/@noodle-borg/knowledge-operations/dist/crawl-lifecycle.js +138 -0
  120. package/node_modules/@noodle-borg/knowledge-operations/dist/crawl-lifecycle.js.map +1 -0
  121. package/node_modules/@noodle-borg/knowledge-operations/dist/dispatch.d.ts.map +1 -1
  122. package/node_modules/@noodle-borg/knowledge-operations/dist/dispatch.js +11 -3
  123. package/node_modules/@noodle-borg/knowledge-operations/dist/dispatch.js.map +1 -1
  124. package/node_modules/@noodle-borg/knowledge-operations/dist/executor.d.ts +7 -13
  125. package/node_modules/@noodle-borg/knowledge-operations/dist/executor.d.ts.map +1 -1
  126. package/node_modules/@noodle-borg/knowledge-operations/dist/executor.js +16 -27
  127. package/node_modules/@noodle-borg/knowledge-operations/dist/executor.js.map +1 -1
  128. package/node_modules/@noodle-borg/knowledge-operations/dist/index.d.ts +2 -2
  129. package/node_modules/@noodle-borg/knowledge-operations/dist/index.d.ts.map +1 -1
  130. package/node_modules/@noodle-borg/knowledge-operations/dist/index.js +2 -2
  131. package/node_modules/@noodle-borg/knowledge-operations/dist/index.js.map +1 -1
  132. package/node_modules/@noodle-borg/knowledge-operations/dist/paths.d.ts +4 -0
  133. package/node_modules/@noodle-borg/knowledge-operations/dist/paths.d.ts.map +1 -1
  134. package/node_modules/@noodle-borg/knowledge-operations/dist/paths.js +6 -0
  135. package/node_modules/@noodle-borg/knowledge-operations/dist/paths.js.map +1 -1
  136. package/node_modules/@noodle-borg/knowledge-operations/dist/postgres-crawl-state.d.ts +12 -0
  137. package/node_modules/@noodle-borg/knowledge-operations/dist/postgres-crawl-state.d.ts.map +1 -0
  138. package/node_modules/@noodle-borg/knowledge-operations/dist/postgres-crawl-state.js +58 -0
  139. package/node_modules/@noodle-borg/knowledge-operations/dist/postgres-crawl-state.js.map +1 -0
  140. package/node_modules/@noodle-borg/knowledge-operations/dist/publication.d.ts +14 -1
  141. package/node_modules/@noodle-borg/knowledge-operations/dist/publication.d.ts.map +1 -1
  142. package/node_modules/@noodle-borg/knowledge-operations/dist/publication.js +84 -42
  143. package/node_modules/@noodle-borg/knowledge-operations/dist/publication.js.map +1 -1
  144. package/node_modules/@noodle-borg/knowledge-operations/dist/service-wiring.d.ts +18 -11
  145. package/node_modules/@noodle-borg/knowledge-operations/dist/service-wiring.d.ts.map +1 -1
  146. package/node_modules/@noodle-borg/knowledge-operations/dist/service-wiring.js +149 -26
  147. package/node_modules/@noodle-borg/knowledge-operations/dist/service-wiring.js.map +1 -1
  148. package/node_modules/@noodle-borg/knowledge-operations/dist/status-routes.d.ts +13 -4
  149. package/node_modules/@noodle-borg/knowledge-operations/dist/status-routes.d.ts.map +1 -1
  150. package/node_modules/@noodle-borg/knowledge-operations/dist/status-routes.js +28 -0
  151. package/node_modules/@noodle-borg/knowledge-operations/dist/status-routes.js.map +1 -1
  152. package/node_modules/@noodle-borg/knowledge-operations/package.json +1 -0
  153. package/node_modules/@noodle-borg/protocol/dist/sdk-server.d.ts +3 -0
  154. package/node_modules/@noodle-borg/protocol/dist/sdk-server.d.ts.map +1 -1
  155. package/node_modules/@noodle-borg/protocol/dist/sdk-server.js.map +1 -1
  156. package/node_modules/@noodle-borg/protocol/dist/v2/server.d.ts +1 -1
  157. package/node_modules/@noodle-borg/protocol/dist/v2/server.d.ts.map +1 -1
  158. package/node_modules/@noodle-borg/protocol/dist/v2/server.js +26 -4
  159. package/node_modules/@noodle-borg/protocol/dist/v2/server.js.map +1 -1
  160. package/node_modules/@noodle-borg/protocol/dist/v2/skills.d.ts +30 -0
  161. package/node_modules/@noodle-borg/protocol/dist/v2/skills.d.ts.map +1 -0
  162. package/node_modules/@noodle-borg/protocol/dist/v2/skills.js +126 -0
  163. package/node_modules/@noodle-borg/protocol/dist/v2/skills.js.map +1 -0
  164. package/node_modules/@noodle-borg/protocol/package.json +3 -1
  165. package/node_modules/@noodle-borg/service/dist/assistant-bindings.d.ts.map +1 -1
  166. package/node_modules/@noodle-borg/service/dist/assistant-bindings.js +29 -1
  167. package/node_modules/@noodle-borg/service/dist/assistant-bindings.js.map +1 -1
  168. package/node_modules/@noodle-borg/service/dist/knowledge-wiring.d.ts +8 -0
  169. package/node_modules/@noodle-borg/service/dist/knowledge-wiring.d.ts.map +1 -0
  170. package/node_modules/@noodle-borg/service/dist/knowledge-wiring.js +10 -0
  171. package/node_modules/@noodle-borg/service/dist/knowledge-wiring.js.map +1 -0
  172. package/node_modules/@noodle-borg/service/dist/registry-targets.d.ts.map +1 -1
  173. package/node_modules/@noodle-borg/service/dist/registry-targets.js +10 -2
  174. package/node_modules/@noodle-borg/service/dist/registry-targets.js.map +1 -1
  175. package/node_modules/@noodle-borg/service/dist/routes/paths.d.ts.map +1 -1
  176. package/node_modules/@noodle-borg/service/dist/routes/paths.js +84 -321
  177. package/node_modules/@noodle-borg/service/dist/routes/paths.js.map +1 -1
  178. package/node_modules/@noodle-borg/service/dist/service.d.ts.map +1 -1
  179. package/node_modules/@noodle-borg/service/dist/service.js +3 -3
  180. package/node_modules/@noodle-borg/service/dist/service.js.map +1 -1
  181. package/node_modules/@noodle-borg/service/package.json +1 -1
  182. package/node_modules/@noodle-borg/transport-http/dist/admission-context.js +5 -1
  183. package/node_modules/@noodle-borg/transport-http/dist/admission-context.js.map +1 -1
  184. package/node_modules/@noodle-borg/transport-http/dist/request-capture.d.ts.map +1 -1
  185. package/node_modules/@noodle-borg/transport-http/dist/request-capture.js +4 -1
  186. package/node_modules/@noodle-borg/transport-http/dist/request-capture.js.map +1 -1
  187. package/node_modules/@noodle-borg/wire-contracts/dist/knowledge.d.ts +41 -0
  188. package/node_modules/@noodle-borg/wire-contracts/dist/knowledge.d.ts.map +1 -1
  189. package/node_modules/@noodle-borg/wire-contracts/dist/knowledge.js +14 -0
  190. package/node_modules/@noodle-borg/wire-contracts/dist/knowledge.js.map +1 -1
  191. package/node_modules/@noodleseed/assistant/dist/{chunk-MZNENVFY.js → chunk-RFETV5KQ.js} +158 -6
  192. package/node_modules/@noodleseed/assistant/dist/chunk-RFETV5KQ.js.map +1 -0
  193. package/node_modules/@noodleseed/assistant/dist/{chunk-RIKRQFKS.js → chunk-S373FCAI.js} +2 -1
  194. package/node_modules/@noodleseed/assistant/dist/client.js +1 -1
  195. package/node_modules/@noodleseed/assistant/dist/embed.global.js +57 -57
  196. package/node_modules/@noodleseed/assistant/dist/index.cjs +268 -117
  197. package/node_modules/@noodleseed/assistant/dist/index.cjs.map +1 -1
  198. package/node_modules/@noodleseed/assistant/dist/index.js +2 -2
  199. package/node_modules/@noodleseed/assistant/dist/react/client.js +1 -1
  200. package/node_modules/@noodleseed/assistant/dist/react.cjs +268 -117
  201. package/node_modules/@noodleseed/assistant/dist/react.cjs.map +1 -1
  202. package/node_modules/@noodleseed/assistant/dist/react.js +2 -2
  203. package/node_modules/@noodleseed/assistant/package.json +1 -1
  204. package/package.json +3 -2
  205. package/node_modules/@noodle-borg/knowledge-operations/dist/google-identity.d.ts +0 -15
  206. package/node_modules/@noodle-borg/knowledge-operations/dist/google-identity.d.ts.map +0 -1
  207. package/node_modules/@noodle-borg/knowledge-operations/dist/google-identity.js +0 -50
  208. package/node_modules/@noodle-borg/knowledge-operations/dist/google-identity.js.map +0 -1
  209. package/node_modules/@noodle-borg/knowledge-operations/dist/managed-google.d.ts +0 -34
  210. package/node_modules/@noodle-borg/knowledge-operations/dist/managed-google.d.ts.map +0 -1
  211. package/node_modules/@noodle-borg/knowledge-operations/dist/managed-google.js +0 -79
  212. package/node_modules/@noodle-borg/knowledge-operations/dist/managed-google.js.map +0 -1
  213. package/node_modules/@noodleseed/assistant/dist/chunk-MZNENVFY.js.map +0 -1
  214. /package/node_modules/@noodleseed/assistant/dist/{chunk-RIKRQFKS.js.map → chunk-S373FCAI.js.map} +0 -0
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Deliberately small HTML→text extraction for a lexical index: strip non-content blocks and
3
+ * markup, decode the common entities, collapse whitespace. Fetched pages are untrusted input —
4
+ * this reduces them to bounded plain text and nothing here evaluates or resolves anything.
5
+ */
6
+ const NON_CONTENT_BLOCKS = /<(script|style|noscript|template|svg)\b[\s\S]*?<\/\1\s*>/gi;
7
+ const BLOCK_BREAK = /<\/?(p|div|li|ul|ol|table|tr|td|th|h[1-6]|br|hr|section|article|header|footer|nav|blockquote|pre)\b[^>]*>/gi;
8
+ const NAMED_ENTITIES = {
9
+ amp: '&',
10
+ lt: '<',
11
+ gt: '>',
12
+ quot: '"',
13
+ apos: "'",
14
+ nbsp: ' ',
15
+ mdash: '—',
16
+ ndash: '–',
17
+ hellip: '…',
18
+ rsquo: '’',
19
+ lsquo: '‘',
20
+ rdquo: '”',
21
+ ldquo: '“',
22
+ copy: '©',
23
+ };
24
+ function decodeEntities(text) {
25
+ return text
26
+ .replace(/&#x([0-9a-f]+);/gi, (_, hex) => String.fromCodePoint(Number.parseInt(hex, 16)))
27
+ .replace(/&#(\d+);/g, (_, dec) => String.fromCodePoint(Number.parseInt(dec, 10)))
28
+ .replace(/&([a-z]+);/gi, (match, name) => NAMED_ENTITIES[name.toLowerCase()] ?? match);
29
+ }
30
+ export function extractHtmlText(html) {
31
+ const withoutBlocks = html.replace(NON_CONTENT_BLOCKS, ' ');
32
+ const withBreaks = withoutBlocks.replace(BLOCK_BREAK, ' ');
33
+ const withoutTags = withBreaks.replace(/<[^>]+>/g, '');
34
+ return decodeEntities(withoutTags).replace(/\s+/g, ' ').trim();
35
+ }
36
+ /**
37
+ * The content-extraction seam: (content type, bytes) → indexable `{ html, title, text }`, or
38
+ * `undefined` for media we cannot yet extract. Future formats — PDF is the named next candidate
39
+ * (ADR 0202 deferred triggers) — become one new case here; everything downstream (sealing,
40
+ * revisions, indexing, fusion, citations) is format-agnostic.
41
+ */
42
+ export function extractPageContent(contentType, bytes) {
43
+ if (!contentType.startsWith('text/html'))
44
+ return undefined;
45
+ const html = new TextDecoder().decode(bytes);
46
+ return { html, title: extractHtmlTitle(html), text: extractHtmlText(html) };
47
+ }
48
+ export function extractHtmlTitle(html) {
49
+ const title = /<title[^>]*>([\s\S]*?)<\/title\s*>/i.exec(html)?.[1];
50
+ if (title !== undefined && title.trim() !== '')
51
+ return decodeEntities(title).replace(/\s+/g, ' ').trim();
52
+ const heading = /<h1[^>]*>([\s\S]*?)<\/h1\s*>/i.exec(html)?.[1];
53
+ if (heading !== undefined) {
54
+ const text = decodeEntities(heading.replace(/<[^>]+>/g, ''))
55
+ .replace(/\s+/g, ' ')
56
+ .trim();
57
+ if (text !== '')
58
+ return text;
59
+ }
60
+ return '';
61
+ }
62
+ //# sourceMappingURL=html-text.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"html-text.js","sourceRoot":"","sources":["../src/html-text.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export { FirecrawlSiteFetcher, type FirecrawlSiteFetcherOptions } from './firecrawl.js';
2
+ export { FirstPartySiteFetcher, type FirstPartySiteFetcherOptions } from './first-party.js';
3
+ export type { CrawlPage, SiteCrawlRequest, SiteFetcher } from './ports.js';
4
+ export { TavilySiteFetcher, type TavilySiteFetcherOptions } from './tavily.js';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,KAAK,2BAA2B,EAAE,MAAM,gBAAgB,CAAC;AACxF,OAAO,EAAE,qBAAqB,EAAE,KAAK,4BAA4B,EAAE,MAAM,kBAAkB,CAAC;AAC5F,YAAY,EAAE,SAAS,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC3E,OAAO,EAAE,iBAAiB,EAAE,KAAK,wBAAwB,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,4 @@
1
+ export { FirecrawlSiteFetcher } from './firecrawl.js';
2
+ export { FirstPartySiteFetcher } from './first-party.js';
3
+ export { TavilySiteFetcher } from './tavily.js';
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAoC,MAAM,gBAAgB,CAAC;AACxF,OAAO,EAAE,qBAAqB,EAAqC,MAAM,kBAAkB,CAAC;AAE5F,OAAO,EAAE,iBAAiB,EAAiC,MAAM,aAAa,CAAC"}
@@ -0,0 +1,3 @@
1
+ export declare function parseOrigin(origin: string): URL;
2
+ export declare function safeUrl(href: string, base?: string): URL | undefined;
3
+ //# sourceMappingURL=origin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"origin.d.ts","sourceRoot":"","sources":["../src/origin.ts"],"names":[],"mappings":"AAIA,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,GAAG,CAe/C;AAED,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,GAAG,GAAG,SAAS,CAOpE"}
@@ -0,0 +1,30 @@
1
+ /** Shared origin/URL validation for every fetcher (managed and BYO). */
2
+ import { isIP } from 'node:net';
3
+ import { KnowledgeError } from '@noodle-borg/knowledge';
4
+ export function parseOrigin(origin) {
5
+ let url;
6
+ try {
7
+ url = new URL(origin);
8
+ }
9
+ catch {
10
+ throw new KnowledgeError('request', `site origin ${origin} is not a valid URL`);
11
+ }
12
+ if (url.protocol !== 'https:') {
13
+ throw new KnowledgeError('request', 'site origin must use https');
14
+ }
15
+ if (isIP(url.hostname.replace(/^\[|\]$/g, '')) !== 0) {
16
+ // A literal-IP host has no DNS step, which would bypass the socket-level SSRF guard.
17
+ throw new KnowledgeError('request', 'site origin must be a DNS hostname, not an IP address');
18
+ }
19
+ return url;
20
+ }
21
+ export function safeUrl(href, base) {
22
+ try {
23
+ const url = base === undefined ? new URL(href) : new URL(href, base);
24
+ return url.protocol === 'https:' ? url : undefined;
25
+ }
26
+ catch {
27
+ return undefined;
28
+ }
29
+ }
30
+ //# sourceMappingURL=origin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"origin.js","sourceRoot":"","sources":["../src/origin.ts"],"names":[],"mappings":"AAAA,wEAAwE;AACxE,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAChC,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAExD,MAAM,UAAU,WAAW,CAAC,MAAc;IACxC,IAAI,GAAQ,CAAC;IACb,IAAI,CAAC;QACH,GAAG,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC;IACxB,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,cAAc,CAAC,SAAS,EAAE,eAAe,MAAM,qBAAqB,CAAC,CAAC;IAClF,CAAC;IACD,IAAI,GAAG,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAC9B,MAAM,IAAI,cAAc,CAAC,SAAS,EAAE,4BAA4B,CAAC,CAAC;IACpE,CAAC;IACD,IAAI,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC;QACrD,qFAAqF;QACrF,MAAM,IAAI,cAAc,CAAC,SAAS,EAAE,uDAAuD,CAAC,CAAC;IAC/F,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,IAAY,EAAE,IAAa;IACjD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QACrE,OAAO,GAAG,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC;IACrD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Provider-neutral site crawling port (ADR 0202 amendment 2026-08-18): one bounded call in, a
3
+ * deterministic ordered list of plain-text pages out. Every fetcher — the managed first-party
4
+ * crawler and the BYO provider adapters — satisfies this contract and its shared tests; provider
5
+ * concepts (job ids, credits, raw payloads) never cross it.
6
+ */
7
+ export interface SiteCrawlRequest {
8
+ /** Exact HTTPS origin, no path. Literal-IP hosts are rejected (they bypass the DNS SSRF guard). */
9
+ readonly origin: string;
10
+ /** Path globs a page must match to be indexed; discovery may touch only these plus the root. */
11
+ readonly include: readonly string[];
12
+ readonly maxPages: number;
13
+ readonly maxPageBytes: number;
14
+ }
15
+ export interface CrawlPage {
16
+ readonly url: string;
17
+ readonly title: string;
18
+ readonly text: string;
19
+ }
20
+ export interface SiteFetcher {
21
+ /**
22
+ * Crawl the site within the request bounds. Returns pages sorted by URL; individual page
23
+ * failures are skipped, a total provider failure throws a `KnowledgeError` with an
24
+ * attributable layer and no content.
25
+ */
26
+ fetchSite(request: SiteCrawlRequest): Promise<readonly CrawlPage[]>;
27
+ }
28
+ //# sourceMappingURL=ports.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ports.d.ts","sourceRoot":"","sources":["../src/ports.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,WAAW,gBAAgB;IAC/B,mGAAmG;IACnG,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,gGAAgG;IAChG,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC/B;AAED,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,WAAW;IAC1B;;;;OAIG;IACH,SAAS,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,SAAS,SAAS,EAAE,CAAC,CAAC;CACrE"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Provider-neutral site crawling port (ADR 0202 amendment 2026-08-18): one bounded call in, a
3
+ * deterministic ordered list of plain-text pages out. Every fetcher — the managed first-party
4
+ * crawler and the BYO provider adapters — satisfies this contract and its shared tests; provider
5
+ * concepts (job ids, credits, raw payloads) never cross it.
6
+ */
7
+ export {};
8
+ //# sourceMappingURL=ports.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ports.js","sourceRoot":"","sources":["../src/ports.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Minimal robots.txt evaluation for the managed crawler: `*` user-agent groups only, with the
3
+ * de-facto longest-match precedence between Allow and Disallow (Allow wins an exact-length tie),
4
+ * plus global `Sitemap:` collection. Deliberately dependency-free; if richer semantics are ever
5
+ * needed, verify the dependency license first (root rules).
6
+ */
7
+ export interface Robots {
8
+ isAllowed(path: string): boolean;
9
+ readonly sitemaps: readonly string[];
10
+ }
11
+ export declare function parseRobots(text: string): Robots;
12
+ //# sourceMappingURL=robots.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"robots.d.ts","sourceRoot":"","sources":["../src/robots.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAOH,MAAM,WAAW,MAAM;IACrB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IACjC,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;CACtC;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAmDhD"}
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Minimal robots.txt evaluation for the managed crawler: `*` user-agent groups only, with the
3
+ * de-facto longest-match precedence between Allow and Disallow (Allow wins an exact-length tie),
4
+ * plus global `Sitemap:` collection. Deliberately dependency-free; if richer semantics are ever
5
+ * needed, verify the dependency license first (root rules).
6
+ */
7
+ export function parseRobots(text) {
8
+ const rules = [];
9
+ const sitemaps = [];
10
+ let inStarGroup = false;
11
+ let groupHasAgents = false;
12
+ for (const rawLine of text.split(/\r?\n/)) {
13
+ const line = rawLine.replace(/#.*$/, '').trim();
14
+ if (line === '')
15
+ continue;
16
+ const separator = line.indexOf(':');
17
+ if (separator === -1)
18
+ continue;
19
+ const field = line.slice(0, separator).trim().toLowerCase();
20
+ const value = line.slice(separator + 1).trim();
21
+ if (field === 'sitemap') {
22
+ if (value !== '')
23
+ sitemaps.push(value);
24
+ continue;
25
+ }
26
+ if (field === 'user-agent') {
27
+ // Consecutive user-agent lines share one group; a rule line closes the agent list, so a
28
+ // user-agent line after rules starts a fresh group.
29
+ if (groupHasAgents) {
30
+ inStarGroup = false;
31
+ groupHasAgents = false;
32
+ }
33
+ if (value === '*')
34
+ inStarGroup = true;
35
+ continue;
36
+ }
37
+ if (field === 'allow' || field === 'disallow') {
38
+ groupHasAgents = true;
39
+ if (!inStarGroup)
40
+ continue;
41
+ // A bare "Disallow:" means allow-all per the de-facto standard.
42
+ if (value === '')
43
+ continue;
44
+ rules.push({ allow: field === 'allow', path: value });
45
+ }
46
+ }
47
+ return {
48
+ sitemaps,
49
+ isAllowed(path) {
50
+ let best;
51
+ for (const rule of rules) {
52
+ if (!path.startsWith(rule.path))
53
+ continue;
54
+ if (best === undefined ||
55
+ rule.path.length > best.path.length ||
56
+ (rule.path.length === best.path.length && rule.allow)) {
57
+ best = rule;
58
+ }
59
+ }
60
+ return best?.allow ?? true;
61
+ },
62
+ };
63
+ }
64
+ //# sourceMappingURL=robots.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"robots.js","sourceRoot":"","sources":["../src/robots.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAYH,MAAM,UAAU,WAAW,CAAC,IAAY;IACtC,MAAM,KAAK,GAAiB,EAAE,CAAC;IAC/B,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,IAAI,WAAW,GAAG,KAAK,CAAC;IACxB,IAAI,cAAc,GAAG,KAAK,CAAC;IAC3B,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;QAC1C,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QAChD,IAAI,IAAI,KAAK,EAAE;YAAE,SAAS;QAC1B,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QACpC,IAAI,SAAS,KAAK,CAAC,CAAC;YAAE,SAAS;QAC/B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAC5D,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAC/C,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,IAAI,KAAK,KAAK,EAAE;gBAAE,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACvC,SAAS;QACX,CAAC;QACD,IAAI,KAAK,KAAK,YAAY,EAAE,CAAC;YAC3B,wFAAwF;YACxF,oDAAoD;YACpD,IAAI,cAAc,EAAE,CAAC;gBACnB,WAAW,GAAG,KAAK,CAAC;gBACpB,cAAc,GAAG,KAAK,CAAC;YACzB,CAAC;YACD,IAAI,KAAK,KAAK,GAAG;gBAAE,WAAW,GAAG,IAAI,CAAC;YACtC,SAAS;QACX,CAAC;QACD,IAAI,KAAK,KAAK,OAAO,IAAI,KAAK,KAAK,UAAU,EAAE,CAAC;YAC9C,cAAc,GAAG,IAAI,CAAC;YACtB,IAAI,CAAC,WAAW;gBAAE,SAAS;YAC3B,gEAAgE;YAChE,IAAI,KAAK,KAAK,EAAE;gBAAE,SAAS;YAC3B,KAAK,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,KAAK,KAAK,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QACxD,CAAC;IACH,CAAC;IACD,OAAO;QACL,QAAQ;QACR,SAAS,CAAC,IAAY;YACpB,IAAI,IAA4B,CAAC;YACjC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;gBACzB,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC;oBAAE,SAAS;gBAC1C,IACE,IAAI,KAAK,SAAS;oBAClB,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM;oBACnC,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,KAAK,IAAI,CAAC,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,KAAK,CAAC,EACrD,CAAC;oBACD,IAAI,GAAG,IAAI,CAAC;gBACd,CAAC;YACH,CAAC;YACD,OAAO,IAAI,EAAE,KAAK,IAAI,IAAI,CAAC;QAC7B,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,3 @@
1
+ /** Bounded `<loc>` extraction from sitemap XML — locations only, nothing else is read. */
2
+ export declare function parseSitemapLocations(xml: string): readonly string[];
3
+ //# sourceMappingURL=sitemap.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sitemap.d.ts","sourceRoot":"","sources":["../src/sitemap.ts"],"names":[],"mappings":"AAAA,0FAA0F;AAC1F,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAOpE"}
@@ -0,0 +1,11 @@
1
+ /** Bounded `<loc>` extraction from sitemap XML — locations only, nothing else is read. */
2
+ export function parseSitemapLocations(xml) {
3
+ const locations = [];
4
+ for (const match of xml.matchAll(/<loc>\s*([^<]+?)\s*<\/loc>/gi)) {
5
+ const location = match[1];
6
+ if (location !== undefined && location !== '')
7
+ locations.push(location);
8
+ }
9
+ return locations;
10
+ }
11
+ //# sourceMappingURL=sitemap.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sitemap.js","sourceRoot":"","sources":["../src/sitemap.ts"],"names":[],"mappings":"AAAA,0FAA0F;AAC1F,MAAM,UAAU,qBAAqB,CAAC,GAAW;IAC/C,MAAM,SAAS,GAAa,EAAE,CAAC;IAC/B,KAAK,MAAM,KAAK,IAAI,GAAG,CAAC,QAAQ,CAAC,8BAA8B,CAAC,EAAE,CAAC;QACjE,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QAC1B,IAAI,QAAQ,KAAK,SAAS,IAAI,QAAQ,KAAK,EAAE;YAAE,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC1E,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC"}
@@ -0,0 +1,11 @@
1
+ import type { CrawlPage, SiteCrawlRequest, SiteFetcher } from './ports.js';
2
+ export interface TavilySiteFetcherOptions {
3
+ readonly apiKey: string;
4
+ readonly fetchImpl?: typeof fetch;
5
+ }
6
+ export declare class TavilySiteFetcher implements SiteFetcher {
7
+ #private;
8
+ constructor(options: TavilySiteFetcherOptions);
9
+ fetchSite(request: SiteCrawlRequest): Promise<readonly CrawlPage[]>;
10
+ }
11
+ //# sourceMappingURL=tavily.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tavily.d.ts","sourceRoot":"","sources":["../src/tavily.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,SAAS,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAI3E,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;CACnC;AAED,qBAAa,iBAAkB,YAAW,WAAW;;gBAIvC,OAAO,EAAE,wBAAwB;IAKvC,SAAS,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,SAAS,SAAS,EAAE,CAAC;CAqC1E"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * BYO Tavily fetcher (ADR 0202 amendment 2026-08-18): the customer's own Tavily account crawls
3
+ * the site through the synchronous hosted REST API. Wire shape transcribed from the official API
4
+ * reference 2026-08-18: `POST https://api.tavily.com/crawl` with Bearer auth and
5
+ * `{ url, limit, allow_external, format, extract_depth }` → `{ results: [{ url, raw_content }] }`.
6
+ * Crawled pages carry no separate title field, so the URL stands in. Errors are attributable and
7
+ * content-free — provider bodies and the API key never cross the port.
8
+ */
9
+ import { KnowledgeError } from '@noodle-borg/knowledge';
10
+ import { boundPages } from './bounds.js';
11
+ import { parseOrigin } from './origin.js';
12
+ const API = 'https://api.tavily.com/crawl';
13
+ export class TavilySiteFetcher {
14
+ #apiKey;
15
+ #fetch;
16
+ constructor(options) {
17
+ this.#apiKey = options.apiKey;
18
+ this.#fetch = options.fetchImpl ?? fetch;
19
+ }
20
+ async fetchSite(request) {
21
+ const origin = parseOrigin(request.origin);
22
+ let response;
23
+ try {
24
+ response = await this.#fetch(API, {
25
+ method: 'POST',
26
+ headers: {
27
+ authorization: `Bearer ${this.#apiKey}`,
28
+ 'content-type': 'application/json',
29
+ },
30
+ body: JSON.stringify({
31
+ url: origin.origin,
32
+ limit: request.maxPages,
33
+ allow_external: false,
34
+ format: 'text',
35
+ extract_depth: 'basic',
36
+ }),
37
+ });
38
+ }
39
+ catch {
40
+ throw new KnowledgeError('provider', 'tavily crawl request failed');
41
+ }
42
+ if (!response.ok) {
43
+ throw new KnowledgeError('provider', `tavily crawl returned HTTP ${response.status}`);
44
+ }
45
+ const body = (await response.json().catch(() => ({})));
46
+ return boundPages((body.results ?? []).map((result) => ({
47
+ url: result.url ?? '',
48
+ title: '',
49
+ text: result.raw_content ?? '',
50
+ })), request, origin);
51
+ }
52
+ }
53
+ //# sourceMappingURL=tavily.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tavily.js","sourceRoot":"","sources":["../src/tavily.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAG1C,MAAM,GAAG,GAAG,8BAA8B,CAAC;AAO3C,MAAM,OAAO,iBAAiB;IACnB,OAAO,CAAS;IAChB,MAAM,CAAe;IAE9B,YAAY,OAAiC;QAC3C,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC;QAC9B,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,SAAS,IAAI,KAAK,CAAC;IAC3C,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,OAAyB;QACvC,MAAM,MAAM,GAAG,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAC3C,IAAI,QAAkB,CAAC;QACvB,IAAI,CAAC;YACH,QAAQ,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE;gBAChC,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE;oBACP,aAAa,EAAE,UAAU,IAAI,CAAC,OAAO,EAAE;oBACvC,cAAc,EAAE,kBAAkB;iBACnC;gBACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;oBACnB,GAAG,EAAE,MAAM,CAAC,MAAM;oBAClB,KAAK,EAAE,OAAO,CAAC,QAAQ;oBACvB,cAAc,EAAE,KAAK;oBACrB,MAAM,EAAE,MAAM;oBACd,aAAa,EAAE,OAAO;iBACvB,CAAC;aACH,CAAC,CAAC;QACL,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,IAAI,cAAc,CAAC,UAAU,EAAE,6BAA6B,CAAC,CAAC;QACtE,CAAC;QACD,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,cAAc,CAAC,UAAU,EAAE,8BAA8B,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;QACxF,CAAC;QACD,MAAM,IAAI,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAEpD,CAAC;QACF,OAAO,UAAU,CACf,CAAC,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;YACpC,GAAG,EAAE,MAAM,CAAC,GAAG,IAAI,EAAE;YACrB,KAAK,EAAE,EAAE;YACT,IAAI,EAAE,MAAM,CAAC,WAAW,IAAI,EAAE;SAC/B,CAAC,CAAC,EACH,OAAO,EACP,MAAM,CACP,CAAC;IACJ,CAAC;CACF"}
@@ -0,0 +1,32 @@
1
+ {
2
+ "name": "@noodle-borg/knowledge-crawl",
3
+ "version": "0.0.0",
4
+ "private": true,
5
+ "license": "Apache-2.0",
6
+ "type": "module",
7
+ "engines": {
8
+ "node": ">=24"
9
+ },
10
+ "main": "./dist/index.js",
11
+ "types": "./dist/index.d.ts",
12
+ "exports": {
13
+ ".": {
14
+ "types": "./dist/index.d.ts",
15
+ "import": "./dist/index.js"
16
+ }
17
+ },
18
+ "files": [
19
+ "dist"
20
+ ],
21
+ "scripts": {
22
+ "build": "tsc -p tsconfig.json",
23
+ "typecheck": "tsc -p tsconfig.json --noEmit"
24
+ },
25
+ "dependencies": {
26
+ "@noodle-borg/connector-http": "0.0.0",
27
+ "@noodle-borg/knowledge": "0.0.0"
28
+ },
29
+ "devDependencies": {
30
+ "@types/node": "^24.13.1"
31
+ }
32
+ }
@@ -0,0 +1,71 @@
1
+ import { type SearchBudgetCeilings, type SearchBudgetStore, type SearchHit, type SearchRequest } from '@noodle-borg/knowledge';
2
+ import type { SiteFetcher } from '@noodle-borg/knowledge-crawl';
3
+ import type { KnowledgeDeployHooks } from './publication.js';
4
+ import type { KnowledgeTenantRef } from './routes.js';
5
+ /** The reserved revision namespace for a component's crawled site corpus. */
6
+ export declare function siteCorpusName(componentName: string): string;
7
+ export type CrawlStatus = 'not_started' | 'in_progress' | 'completed' | 'failed';
8
+ export interface SiteCrawlState {
9
+ readonly status: CrawlStatus;
10
+ readonly lastCompletedAt?: number;
11
+ readonly lastError?: string;
12
+ readonly pagesIndexed: number;
13
+ readonly nextRefreshAt?: number;
14
+ }
15
+ export interface CrawlStateStore {
16
+ get(tenant: KnowledgeTenantRef, componentName: string): Promise<SiteCrawlState | undefined>;
17
+ put(tenant: KnowledgeTenantRef, componentName: string, state: SiteCrawlState): Promise<void>;
18
+ }
19
+ export declare class InMemoryCrawlStateStore implements CrawlStateStore {
20
+ private readonly states;
21
+ get(tenant: KnowledgeTenantRef, componentName: string): Promise<SiteCrawlState | undefined>;
22
+ put(tenant: KnowledgeTenantRef, componentName: string, state: SiteCrawlState): Promise<void>;
23
+ }
24
+ /** A provider config reference by name (variable()/secret() doctrine) — never a value. */
25
+ export interface ProviderConfigRef {
26
+ readonly kind: 'variable' | 'secret';
27
+ readonly name: string;
28
+ }
29
+ /** The component facts a crawl needs; a structural subset of the compiled component. */
30
+ export interface CrawlableComponent {
31
+ readonly name: string;
32
+ readonly sites: readonly {
33
+ readonly origin: string;
34
+ readonly include: readonly string[];
35
+ readonly refreshMinutes?: number | undefined;
36
+ }[];
37
+ readonly crawler?: {
38
+ readonly provider: 'firecrawl' | 'tavily';
39
+ readonly config: {
40
+ readonly apiKey: ProviderConfigRef;
41
+ };
42
+ } | undefined;
43
+ readonly index?: {
44
+ readonly provider: 'algolia' | 'meilisearch';
45
+ readonly config: Readonly<Record<string, ProviderConfigRef>>;
46
+ } | undefined;
47
+ }
48
+ export interface CrawlDeps {
49
+ readonly hooks: KnowledgeDeployHooks;
50
+ readonly crawlState: CrawlStateStore;
51
+ readonly fetcherFor: (tenant: KnowledgeTenantRef, component: CrawlableComponent) => SiteFetcher;
52
+ readonly budget?: {
53
+ readonly store: SearchBudgetStore;
54
+ readonly ceilings: (tenant: KnowledgeTenantRef) => Promise<SearchBudgetCeilings>;
55
+ };
56
+ readonly now?: () => number;
57
+ }
58
+ /**
59
+ * Crawl one component's sites and publish the site revision. Never throws: the outcome —
60
+ * including budget refusal and provider failure — lands in the crawl state, and the previous
61
+ * corpus keeps serving on any failure.
62
+ */
63
+ export declare function runComponentCrawl(deps: CrawlDeps, tenant: KnowledgeTenantRef, component: CrawlableComponent): Promise<SiteCrawlState>;
64
+ /** Crawl every served component whose refresh is due (or that has never crawled). */
65
+ export declare function runDueCrawls(deps: CrawlDeps, servedComponents: () => Promise<readonly {
66
+ tenant: KnowledgeTenantRef;
67
+ component: CrawlableComponent;
68
+ }[]>, at: number): Promise<void>;
69
+ /** Serve the crawled corpus: the bundled index over the site revision, hits remapped to `site`. */
70
+ export declare function searchSiteCorpus(hooks: KnowledgeDeployHooks, tenant: KnowledgeTenantRef, componentName: string, request: SearchRequest): Promise<readonly SearchHit[]>;
71
+ //# sourceMappingURL=crawl-lifecycle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crawl-lifecycle.d.ts","sourceRoot":"","sources":["../src/crawl-lifecycle.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,138 @@
1
+ /**
2
+ * Site crawl lifecycle (ADR 0202 amendment 2026-08-18): a crawl fetches the component's declared
3
+ * sites through the selected `SiteFetcher`, meters the page count against the org/app crawl
4
+ * budget, and publishes the pages as a **site revision** — the reserved `<name>#site` component
5
+ * namespace in the same revision store and bundled index that serve documents. Site revisions
6
+ * refresh latest-wins and are never deployment-pinned ("live site never rolls back" survives as
7
+ * "rollback keeps serving the latest crawl"); a failed crawl keeps the last good corpus serving
8
+ * and records an attributable, content-free failure in the crawl state.
9
+ */
10
+ import { createHash } from 'node:crypto';
11
+ import { KnowledgeError, } from '@noodle-borg/knowledge';
12
+ import { DEFAULT_SITE_REFRESH_MINUTES, MAX_CRAWL_PAGE_BYTES, MAX_CRAWL_PAGES_PER_SITE, } from '@noodle-borg/knowledge/limits';
13
+ /** The reserved revision namespace for a component's crawled site corpus. */
14
+ export function siteCorpusName(componentName) {
15
+ return `${componentName}#site`;
16
+ }
17
+ export class InMemoryCrawlStateStore {
18
+ states = new Map();
19
+ async get(tenant, componentName) {
20
+ return this.states.get(stateKey(tenant, componentName));
21
+ }
22
+ async put(tenant, componentName, state) {
23
+ this.states.set(stateKey(tenant, componentName), state);
24
+ }
25
+ }
26
+ function stateKey(tenant, componentName) {
27
+ return `${tenant.org}/${tenant.app}/${tenant.env}#${componentName}`;
28
+ }
29
+ /**
30
+ * Crawl one component's sites and publish the site revision. Never throws: the outcome —
31
+ * including budget refusal and provider failure — lands in the crawl state, and the previous
32
+ * corpus keeps serving on any failure.
33
+ */
34
+ export async function runComponentCrawl(deps, tenant, component) {
35
+ const now = deps.now ?? Date.now;
36
+ if (component.sites.length === 0) {
37
+ const state = { status: 'not_started', pagesIndexed: 0 };
38
+ await deps.crawlState.put(tenant, component.name, state);
39
+ return state;
40
+ }
41
+ const previous = await deps.crawlState.get(tenant, component.name);
42
+ const refreshMinutes = Math.min(...component.sites.map((site) => site.refreshMinutes ?? DEFAULT_SITE_REFRESH_MINUTES));
43
+ await deps.crawlState.put(tenant, component.name, {
44
+ status: 'in_progress',
45
+ pagesIndexed: previous?.pagesIndexed ?? 0,
46
+ ...(previous?.lastCompletedAt === undefined
47
+ ? {}
48
+ : { lastCompletedAt: previous.lastCompletedAt }),
49
+ });
50
+ const fail = async (lastError) => {
51
+ const state = {
52
+ status: 'failed',
53
+ lastError,
54
+ pagesIndexed: previous?.pagesIndexed ?? 0,
55
+ ...(previous?.lastCompletedAt === undefined
56
+ ? {}
57
+ : { lastCompletedAt: previous.lastCompletedAt }),
58
+ nextRefreshAt: now() + refreshMinutes * 60 * 1000,
59
+ };
60
+ await deps.crawlState.put(tenant, component.name, state);
61
+ return state;
62
+ };
63
+ const documents = [];
64
+ try {
65
+ const fetcher = deps.fetcherFor(tenant, component);
66
+ for (const site of component.sites) {
67
+ const pages = await fetcher.fetchSite({
68
+ origin: site.origin,
69
+ include: site.include,
70
+ maxPages: MAX_CRAWL_PAGES_PER_SITE,
71
+ maxPageBytes: MAX_CRAWL_PAGE_BYTES,
72
+ });
73
+ for (const page of pages) {
74
+ documents.push({
75
+ descriptor: {
76
+ path: page.url,
77
+ title: page.title,
78
+ sha256: createHash('sha256').update(page.text).digest('hex'),
79
+ bytes: Buffer.byteLength(page.text, 'utf8'),
80
+ sourceUrl: page.url,
81
+ },
82
+ text: page.text,
83
+ });
84
+ }
85
+ }
86
+ }
87
+ catch (error) {
88
+ // Request-layer messages are our own (content-free by construction — e.g. the exact
89
+ // `noodle secrets set` fix for an unset BYO key) and stay visible; provider messages may
90
+ // carry URLs, bodies, or credentials and reduce to the attributable layer alone.
91
+ if (error instanceof KnowledgeError && error.layer === 'request') {
92
+ return fail(error.message);
93
+ }
94
+ const layer = error instanceof KnowledgeError ? error.layer : 'provider';
95
+ return fail(`crawl failed at the ${layer} layer`);
96
+ }
97
+ if (deps.budget !== undefined && documents.length > 0) {
98
+ const ceilings = await deps.budget.ceilings(tenant);
99
+ const decision = await deps.budget.store.consume({ org: tenant.org, app: tenant.app }, documents.length, ceilings);
100
+ if (!decision.granted)
101
+ return fail('crawl page budget exhausted for this month');
102
+ }
103
+ try {
104
+ await deps.hooks.publishSiteCorpus({ org: tenant.org, app: tenant.app, env: tenant.env }, siteCorpusName(component.name), documents);
105
+ }
106
+ catch {
107
+ return fail('site corpus publication failed at the store layer');
108
+ }
109
+ const state = {
110
+ status: 'completed',
111
+ lastCompletedAt: now(),
112
+ pagesIndexed: documents.length,
113
+ nextRefreshAt: now() + refreshMinutes * 60 * 1000,
114
+ };
115
+ await deps.crawlState.put(tenant, component.name, state);
116
+ return state;
117
+ }
118
+ /** Crawl every served component whose refresh is due (or that has never crawled). */
119
+ export async function runDueCrawls(deps, servedComponents, at) {
120
+ for (const { tenant, component } of await servedComponents()) {
121
+ if (component.sites.length === 0)
122
+ continue;
123
+ const state = await deps.crawlState.get(tenant, component.name);
124
+ if (state?.status === 'in_progress')
125
+ continue;
126
+ if (state?.nextRefreshAt !== undefined && state.nextRefreshAt > at)
127
+ continue;
128
+ if (state?.status === 'completed' && state.nextRefreshAt === undefined)
129
+ continue;
130
+ await runComponentCrawl({ ...deps, now: () => at }, tenant, component);
131
+ }
132
+ }
133
+ /** Serve the crawled corpus: the bundled index over the site revision, hits remapped to `site`. */
134
+ export async function searchSiteCorpus(hooks, tenant, componentName, request) {
135
+ const hits = await hooks.searchDocuments({ org: tenant.org, app: tenant.app, env: tenant.env }, siteCorpusName(componentName), request);
136
+ return hits.map((hit) => ({ ...hit, sourceKind: 'site' }));
137
+ }
138
+ //# sourceMappingURL=crawl-lifecycle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crawl-lifecycle.js","sourceRoot":"","sources":["../src/crawl-lifecycle.ts"],"names":[],"mappings":"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"}