@pseolint/core 0.4.1 → 0.5.3

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 (321) hide show
  1. package/README.md +264 -169
  2. package/dist/ai/manifest/diff.d.ts +78 -0
  3. package/dist/ai/manifest/diff.d.ts.map +1 -0
  4. package/dist/ai/manifest/diff.js +139 -0
  5. package/dist/ai/manifest/diff.js.map +1 -0
  6. package/dist/ai/manifest/index.d.ts +18 -0
  7. package/dist/ai/manifest/index.d.ts.map +1 -0
  8. package/dist/ai/manifest/index.js +15 -0
  9. package/dist/ai/manifest/index.js.map +1 -0
  10. package/dist/ai/manifest/validate-manifest.d.ts +37 -0
  11. package/dist/ai/manifest/validate-manifest.d.ts.map +1 -0
  12. package/dist/ai/manifest/validate-manifest.js +67 -0
  13. package/dist/ai/manifest/validate-manifest.js.map +1 -0
  14. package/dist/ai/manifest/validators/domain-patches.d.ts +15 -0
  15. package/dist/ai/manifest/validators/domain-patches.d.ts.map +1 -0
  16. package/dist/ai/manifest/validators/domain-patches.js +110 -0
  17. package/dist/ai/manifest/validators/domain-patches.js.map +1 -0
  18. package/dist/ai/manifest/validators/index.d.ts +5 -0
  19. package/dist/ai/manifest/validators/index.d.ts.map +1 -0
  20. package/dist/ai/manifest/validators/index.js +4 -0
  21. package/dist/ai/manifest/validators/index.js.map +1 -0
  22. package/dist/ai/manifest/validators/page-changes.d.ts +36 -0
  23. package/dist/ai/manifest/validators/page-changes.d.ts.map +1 -0
  24. package/dist/ai/manifest/validators/page-changes.js +221 -0
  25. package/dist/ai/manifest/validators/page-changes.js.map +1 -0
  26. package/dist/ai/manifest/validators/types.d.ts +17 -0
  27. package/dist/ai/manifest/validators/types.d.ts.map +1 -0
  28. package/dist/ai/manifest/validators/types.js +5 -0
  29. package/dist/ai/manifest/validators/types.js.map +1 -0
  30. package/dist/ai/orchestrate.d.ts +74 -0
  31. package/dist/ai/orchestrate.d.ts.map +1 -0
  32. package/dist/ai/orchestrate.js +54 -0
  33. package/dist/ai/orchestrate.js.map +1 -0
  34. package/dist/ai/orchestrator/budget.d.ts +57 -0
  35. package/dist/ai/orchestrator/budget.d.ts.map +1 -0
  36. package/dist/ai/orchestrator/budget.js +114 -0
  37. package/dist/ai/orchestrator/budget.js.map +1 -0
  38. package/dist/ai/orchestrator/finish-tool.d.ts +568 -0
  39. package/dist/ai/orchestrator/finish-tool.d.ts.map +1 -0
  40. package/dist/ai/orchestrator/finish-tool.js +114 -0
  41. package/dist/ai/orchestrator/finish-tool.js.map +1 -0
  42. package/dist/ai/orchestrator/index.d.ts +25 -0
  43. package/dist/ai/orchestrator/index.d.ts.map +1 -0
  44. package/dist/ai/orchestrator/index.js +21 -0
  45. package/dist/ai/orchestrator/index.js.map +1 -0
  46. package/dist/ai/orchestrator/log.d.ts +24 -0
  47. package/dist/ai/orchestrator/log.d.ts.map +1 -0
  48. package/dist/ai/orchestrator/log.js +48 -0
  49. package/dist/ai/orchestrator/log.js.map +1 -0
  50. package/dist/ai/orchestrator/page-cache.d.ts +64 -0
  51. package/dist/ai/orchestrator/page-cache.d.ts.map +1 -0
  52. package/dist/ai/orchestrator/page-cache.js +127 -0
  53. package/dist/ai/orchestrator/page-cache.js.map +1 -0
  54. package/dist/ai/orchestrator/prompt.d.ts +16 -0
  55. package/dist/ai/orchestrator/prompt.d.ts.map +1 -0
  56. package/dist/ai/orchestrator/prompt.js +52 -0
  57. package/dist/ai/orchestrator/prompt.js.map +1 -0
  58. package/dist/ai/orchestrator/runner.d.ts +65 -0
  59. package/dist/ai/orchestrator/runner.d.ts.map +1 -0
  60. package/dist/ai/orchestrator/runner.js +223 -0
  61. package/dist/ai/orchestrator/runner.js.map +1 -0
  62. package/dist/ai/orchestrator/session.d.ts +44 -0
  63. package/dist/ai/orchestrator/session.d.ts.map +1 -0
  64. package/dist/ai/orchestrator/session.js +64 -0
  65. package/dist/ai/orchestrator/session.js.map +1 -0
  66. package/dist/ai/orchestrator/types.d.ts +99 -0
  67. package/dist/ai/orchestrator/types.d.ts.map +1 -0
  68. package/dist/ai/orchestrator/types.js +8 -0
  69. package/dist/ai/orchestrator/types.js.map +1 -0
  70. package/dist/ai/probes/cache.d.ts +12 -0
  71. package/dist/ai/probes/cache.d.ts.map +1 -0
  72. package/dist/ai/probes/cache.js +46 -0
  73. package/dist/ai/probes/cache.js.map +1 -0
  74. package/dist/ai/tools/ask-ai-engine.d.ts +77 -0
  75. package/dist/ai/tools/ask-ai-engine.d.ts.map +1 -0
  76. package/dist/ai/tools/ask-ai-engine.js +253 -0
  77. package/dist/ai/tools/ask-ai-engine.js.map +1 -0
  78. package/dist/ai/tools/check-domain-crawler-access.d.ts +71 -0
  79. package/dist/ai/tools/check-domain-crawler-access.d.ts.map +1 -0
  80. package/dist/ai/tools/check-domain-crawler-access.js +76 -0
  81. package/dist/ai/tools/check-domain-crawler-access.js.map +1 -0
  82. package/dist/ai/tools/check-domain-llms-txt.d.ts +70 -0
  83. package/dist/ai/tools/check-domain-llms-txt.d.ts.map +1 -0
  84. package/dist/ai/tools/check-domain-llms-txt.js +75 -0
  85. package/dist/ai/tools/check-domain-llms-txt.js.map +1 -0
  86. package/dist/ai/tools/check-indexability.d.ts +58 -0
  87. package/dist/ai/tools/check-indexability.d.ts.map +1 -0
  88. package/dist/ai/tools/check-indexability.js +64 -0
  89. package/dist/ai/tools/check-indexability.js.map +1 -0
  90. package/dist/ai/tools/check-robots.d.ts +68 -0
  91. package/dist/ai/tools/check-robots.d.ts.map +1 -0
  92. package/dist/ai/tools/check-robots.js +90 -0
  93. package/dist/ai/tools/check-robots.js.map +1 -0
  94. package/dist/ai/tools/check-rule-answer-first.d.ts +54 -0
  95. package/dist/ai/tools/check-rule-answer-first.d.ts.map +1 -0
  96. package/dist/ai/tools/check-rule-answer-first.js +50 -0
  97. package/dist/ai/tools/check-rule-answer-first.js.map +1 -0
  98. package/dist/ai/tools/check-rule-canonical-consistency.d.ts +66 -0
  99. package/dist/ai/tools/check-rule-canonical-consistency.d.ts.map +1 -0
  100. package/dist/ai/tools/check-rule-canonical-consistency.js +51 -0
  101. package/dist/ai/tools/check-rule-canonical-consistency.js.map +1 -0
  102. package/dist/ai/tools/check-rule-citable-facts.d.ts +58 -0
  103. package/dist/ai/tools/check-rule-citable-facts.d.ts.map +1 -0
  104. package/dist/ai/tools/check-rule-citable-facts.js +41 -0
  105. package/dist/ai/tools/check-rule-citable-facts.js.map +1 -0
  106. package/dist/ai/tools/check-rule-content-modularity.d.ts +58 -0
  107. package/dist/ai/tools/check-rule-content-modularity.d.ts.map +1 -0
  108. package/dist/ai/tools/check-rule-content-modularity.js +45 -0
  109. package/dist/ai/tools/check-rule-content-modularity.js.map +1 -0
  110. package/dist/ai/tools/check-rule-faq-coverage.d.ts +54 -0
  111. package/dist/ai/tools/check-rule-faq-coverage.d.ts.map +1 -0
  112. package/dist/ai/tools/check-rule-faq-coverage.js +39 -0
  113. package/dist/ai/tools/check-rule-faq-coverage.js.map +1 -0
  114. package/dist/ai/tools/check-rule-freshness-signals.d.ts +54 -0
  115. package/dist/ai/tools/check-rule-freshness-signals.d.ts.map +1 -0
  116. package/dist/ai/tools/check-rule-freshness-signals.js +45 -0
  117. package/dist/ai/tools/check-rule-freshness-signals.js.map +1 -0
  118. package/dist/ai/tools/check-rule-json-ld-valid.d.ts +54 -0
  119. package/dist/ai/tools/check-rule-json-ld-valid.d.ts.map +1 -0
  120. package/dist/ai/tools/check-rule-json-ld-valid.js +44 -0
  121. package/dist/ai/tools/check-rule-json-ld-valid.js.map +1 -0
  122. package/dist/ai/tools/check-rule-missing-author.d.ts +54 -0
  123. package/dist/ai/tools/check-rule-missing-author.d.ts.map +1 -0
  124. package/dist/ai/tools/check-rule-missing-author.js +45 -0
  125. package/dist/ai/tools/check-rule-missing-author.js.map +1 -0
  126. package/dist/ai/tools/check-rule-near-duplicate.d.ts +82 -0
  127. package/dist/ai/tools/check-rule-near-duplicate.d.ts.map +1 -0
  128. package/dist/ai/tools/check-rule-near-duplicate.js +63 -0
  129. package/dist/ai/tools/check-rule-near-duplicate.js.map +1 -0
  130. package/dist/ai/tools/check-rule-required-fields.d.ts +50 -0
  131. package/dist/ai/tools/check-rule-required-fields.d.ts.map +1 -0
  132. package/dist/ai/tools/check-rule-required-fields.js +38 -0
  133. package/dist/ai/tools/check-rule-required-fields.js.map +1 -0
  134. package/dist/ai/tools/check-rule-schema-consistency.d.ts +54 -0
  135. package/dist/ai/tools/check-rule-schema-consistency.d.ts.map +1 -0
  136. package/dist/ai/tools/check-rule-schema-consistency.js +44 -0
  137. package/dist/ai/tools/check-rule-schema-consistency.js.map +1 -0
  138. package/dist/ai/tools/check-rule-summary-bait.d.ts +54 -0
  139. package/dist/ai/tools/check-rule-summary-bait.d.ts.map +1 -0
  140. package/dist/ai/tools/check-rule-summary-bait.js +39 -0
  141. package/dist/ai/tools/check-rule-summary-bait.js.map +1 -0
  142. package/dist/ai/tools/check-rule-thin-content.d.ts +66 -0
  143. package/dist/ai/tools/check-rule-thin-content.d.ts.map +1 -0
  144. package/dist/ai/tools/check-rule-thin-content.js +58 -0
  145. package/dist/ai/tools/check-rule-thin-content.js.map +1 -0
  146. package/dist/ai/tools/detect-templates.d.ts +60 -0
  147. package/dist/ai/tools/detect-templates.d.ts.map +1 -0
  148. package/dist/ai/tools/detect-templates.js +43 -0
  149. package/dist/ai/tools/detect-templates.js.map +1 -0
  150. package/dist/ai/tools/fetch-page.d.ts +70 -0
  151. package/dist/ai/tools/fetch-page.d.ts.map +1 -0
  152. package/dist/ai/tools/fetch-page.js +93 -0
  153. package/dist/ai/tools/fetch-page.js.map +1 -0
  154. package/dist/ai/tools/fetch-sitemap.d.ts +60 -0
  155. package/dist/ai/tools/fetch-sitemap.d.ts.map +1 -0
  156. package/dist/ai/tools/fetch-sitemap.js +116 -0
  157. package/dist/ai/tools/fetch-sitemap.js.map +1 -0
  158. package/dist/ai/tools/index.d.ts +1555 -0
  159. package/dist/ai/tools/index.d.ts.map +1 -0
  160. package/dist/ai/tools/index.js +119 -0
  161. package/dist/ai/tools/index.js.map +1 -0
  162. package/dist/ai/tools/parse-page.d.ts +94 -0
  163. package/dist/ai/tools/parse-page.d.ts.map +1 -0
  164. package/dist/ai/tools/parse-page.js +108 -0
  165. package/dist/ai/tools/parse-page.js.map +1 -0
  166. package/dist/ai/tools/query-serp.d.ts +113 -0
  167. package/dist/ai/tools/query-serp.d.ts.map +1 -0
  168. package/dist/ai/tools/query-serp.js +131 -0
  169. package/dist/ai/tools/query-serp.js.map +1 -0
  170. package/dist/ai/tools/sample-template.d.ts +67 -0
  171. package/dist/ai/tools/sample-template.d.ts.map +1 -0
  172. package/dist/ai/tools/sample-template.js +75 -0
  173. package/dist/ai/tools/sample-template.js.map +1 -0
  174. package/dist/ai/tools/types.d.ts +73 -0
  175. package/dist/ai/tools/types.d.ts.map +1 -0
  176. package/dist/ai/tools/types.js +64 -0
  177. package/dist/ai/tools/types.js.map +1 -0
  178. package/dist/ai/tools/validate-jsonld.d.ts +62 -0
  179. package/dist/ai/tools/validate-jsonld.d.ts.map +1 -0
  180. package/dist/ai/tools/validate-jsonld.js +84 -0
  181. package/dist/ai/tools/validate-jsonld.js.map +1 -0
  182. package/dist/auditor.d.ts +16 -1
  183. package/dist/auditor.d.ts.map +1 -1
  184. package/dist/auditor.js +862 -88
  185. package/dist/auditor.js.map +1 -1
  186. package/dist/backpressure.d.ts.map +1 -1
  187. package/dist/backpressure.js +10 -3
  188. package/dist/backpressure.js.map +1 -1
  189. package/dist/enrich-findings.d.ts.map +1 -1
  190. package/dist/enrich-findings.js +15 -1
  191. package/dist/enrich-findings.js.map +1 -1
  192. package/dist/formatters/bucket-findings.d.ts +43 -0
  193. package/dist/formatters/bucket-findings.d.ts.map +1 -0
  194. package/dist/formatters/bucket-findings.js +110 -0
  195. package/dist/formatters/bucket-findings.js.map +1 -0
  196. package/dist/formatters/console.d.ts.map +1 -1
  197. package/dist/formatters/console.js +116 -34
  198. package/dist/formatters/console.js.map +1 -1
  199. package/dist/formatters/fixplan.d.ts +13 -0
  200. package/dist/formatters/fixplan.d.ts.map +1 -0
  201. package/dist/formatters/fixplan.js +328 -0
  202. package/dist/formatters/fixplan.js.map +1 -0
  203. package/dist/formatters/html.d.ts.map +1 -1
  204. package/dist/formatters/html.js +27 -0
  205. package/dist/formatters/html.js.map +1 -1
  206. package/dist/formatters/index.d.ts +2 -0
  207. package/dist/formatters/index.d.ts.map +1 -1
  208. package/dist/formatters/index.js +1 -0
  209. package/dist/formatters/index.js.map +1 -1
  210. package/dist/formatters/markdown.d.ts.map +1 -1
  211. package/dist/formatters/markdown.js +97 -9
  212. package/dist/formatters/markdown.js.map +1 -1
  213. package/dist/index.d.ts +12 -1
  214. package/dist/index.d.ts.map +1 -1
  215. package/dist/index.js +8 -0
  216. package/dist/index.js.map +1 -1
  217. package/dist/page-filter.d.ts +64 -6
  218. package/dist/page-filter.d.ts.map +1 -1
  219. package/dist/page-filter.js +124 -3
  220. package/dist/page-filter.js.map +1 -1
  221. package/dist/rule-references.d.ts.map +1 -1
  222. package/dist/rule-references.js +5 -0
  223. package/dist/rule-references.js.map +1 -1
  224. package/dist/rules/aeo/answer-first.d.ts.map +1 -1
  225. package/dist/rules/aeo/answer-first.js +17 -3
  226. package/dist/rules/aeo/answer-first.js.map +1 -1
  227. package/dist/rules/aeo/citable-facts.d.ts.map +1 -1
  228. package/dist/rules/aeo/citable-facts.js +12 -1
  229. package/dist/rules/aeo/citable-facts.js.map +1 -1
  230. package/dist/rules/aeo/content-modularity.d.ts.map +1 -1
  231. package/dist/rules/aeo/content-modularity.js +3 -0
  232. package/dist/rules/aeo/content-modularity.js.map +1 -1
  233. package/dist/rules/aeo/crawler-access.d.ts.map +1 -1
  234. package/dist/rules/aeo/crawler-access.js +6 -0
  235. package/dist/rules/aeo/crawler-access.js.map +1 -1
  236. package/dist/rules/aeo/faq-coverage.d.ts.map +1 -1
  237. package/dist/rules/aeo/faq-coverage.js +4 -0
  238. package/dist/rules/aeo/faq-coverage.js.map +1 -1
  239. package/dist/rules/aeo/freshness-signals.d.ts.map +1 -1
  240. package/dist/rules/aeo/freshness-signals.js +9 -2
  241. package/dist/rules/aeo/freshness-signals.js.map +1 -1
  242. package/dist/rules/aeo/llms-txt.d.ts.map +1 -1
  243. package/dist/rules/aeo/llms-txt.js +6 -1
  244. package/dist/rules/aeo/llms-txt.js.map +1 -1
  245. package/dist/rules/aeo/summary-bait.d.ts.map +1 -1
  246. package/dist/rules/aeo/summary-bait.js +5 -2
  247. package/dist/rules/aeo/summary-bait.js.map +1 -1
  248. package/dist/rules/content/heading-structure.d.ts +21 -0
  249. package/dist/rules/content/heading-structure.d.ts.map +1 -0
  250. package/dist/rules/content/heading-structure.js +56 -0
  251. package/dist/rules/content/heading-structure.js.map +1 -0
  252. package/dist/rules/content/image-alt-text.d.ts +18 -0
  253. package/dist/rules/content/image-alt-text.d.ts.map +1 -0
  254. package/dist/rules/content/image-alt-text.js +77 -0
  255. package/dist/rules/content/image-alt-text.js.map +1 -0
  256. package/dist/rules/content/missing-author.d.ts.map +1 -1
  257. package/dist/rules/content/missing-author.js +10 -2
  258. package/dist/rules/content/missing-author.js.map +1 -1
  259. package/dist/rules/content/title-uniqueness.d.ts +18 -0
  260. package/dist/rules/content/title-uniqueness.d.ts.map +1 -0
  261. package/dist/rules/content/title-uniqueness.js +70 -0
  262. package/dist/rules/content/title-uniqueness.js.map +1 -0
  263. package/dist/rules/links/host-section-divergence.d.ts +3 -0
  264. package/dist/rules/links/host-section-divergence.d.ts.map +1 -0
  265. package/dist/rules/links/host-section-divergence.js +158 -0
  266. package/dist/rules/links/host-section-divergence.js.map +1 -0
  267. package/dist/rules/links/link-depth.d.ts +12 -1
  268. package/dist/rules/links/link-depth.d.ts.map +1 -1
  269. package/dist/rules/links/link-depth.js +25 -12
  270. package/dist/rules/links/link-depth.js.map +1 -1
  271. package/dist/rules/scope.d.ts.map +1 -1
  272. package/dist/rules/scope.js +5 -0
  273. package/dist/rules/scope.js.map +1 -1
  274. package/dist/rules/spam/doorway-pattern.d.ts.map +1 -1
  275. package/dist/rules/spam/doorway-pattern.js +27 -4
  276. package/dist/rules/spam/doorway-pattern.js.map +1 -1
  277. package/dist/rules/spam/publication-velocity.d.ts +1 -1
  278. package/dist/rules/spam/publication-velocity.d.ts.map +1 -1
  279. package/dist/rules/spam/publication-velocity.js +9 -4
  280. package/dist/rules/spam/publication-velocity.js.map +1 -1
  281. package/dist/rules/spam/template-coverage.js +1 -1
  282. package/dist/rules/spam/template-coverage.js.map +1 -1
  283. package/dist/rules/spam/template-diversity.js +1 -1
  284. package/dist/rules/spam/template-diversity.js.map +1 -1
  285. package/dist/rules/spam/thin-content.d.ts.map +1 -1
  286. package/dist/rules/spam/thin-content.js +9 -1
  287. package/dist/rules/spam/thin-content.js.map +1 -1
  288. package/dist/rules/tech/hreflang-consistency.d.ts.map +1 -1
  289. package/dist/rules/tech/hreflang-consistency.js +33 -4
  290. package/dist/rules/tech/hreflang-consistency.js.map +1 -1
  291. package/dist/rules/tech/og-completeness.d.ts +11 -0
  292. package/dist/rules/tech/og-completeness.d.ts.map +1 -1
  293. package/dist/rules/tech/og-completeness.js +22 -23
  294. package/dist/rules/tech/og-completeness.js.map +1 -1
  295. package/dist/ruleset-version.d.ts +8 -0
  296. package/dist/ruleset-version.d.ts.map +1 -0
  297. package/dist/ruleset-version.js +8 -0
  298. package/dist/ruleset-version.js.map +1 -0
  299. package/dist/scrape-strategy.d.ts +42 -0
  300. package/dist/scrape-strategy.d.ts.map +1 -0
  301. package/dist/scrape-strategy.js +101 -0
  302. package/dist/scrape-strategy.js.map +1 -0
  303. package/dist/site-classifier.d.ts +1 -1
  304. package/dist/site-classifier.d.ts.map +1 -1
  305. package/dist/site-classifier.js +217 -0
  306. package/dist/site-classifier.js.map +1 -1
  307. package/dist/state.d.ts +36 -1
  308. package/dist/state.d.ts.map +1 -1
  309. package/dist/state.js +3 -1
  310. package/dist/state.js.map +1 -1
  311. package/dist/stratified-sample.d.ts +9 -1
  312. package/dist/stratified-sample.d.ts.map +1 -1
  313. package/dist/stratified-sample.js +23 -6
  314. package/dist/stratified-sample.js.map +1 -1
  315. package/dist/types.d.ts +179 -2
  316. package/dist/types.d.ts.map +1 -1
  317. package/dist/types.js.map +1 -1
  318. package/dist/url-normalize.d.ts.map +1 -1
  319. package/dist/url-normalize.js +13 -1
  320. package/dist/url-normalize.js.map +1 -1
  321. package/package.json +90 -90
@@ -0,0 +1,221 @@
1
+ import { load } from "cheerio";
2
+ import { fail, VALID } from "./types.js";
3
+ const REQUIRED_PROPERTIES_BY_TYPE = {
4
+ Article: ["headline", "datePublished", "author"],
5
+ NewsArticle: ["headline", "datePublished", "author"],
6
+ BlogPosting: ["headline", "datePublished", "author"],
7
+ Product: ["name"],
8
+ FAQPage: ["mainEntity"],
9
+ HowTo: ["name", "step"],
10
+ Recipe: ["name", "recipeIngredient", "recipeInstructions"],
11
+ Event: ["name", "startDate", "location"],
12
+ Organization: ["name"],
13
+ LocalBusiness: ["name", "address"],
14
+ Person: ["name"],
15
+ BreadcrumbList: ["itemListElement"],
16
+ VideoObject: ["name", "description", "thumbnailUrl", "uploadDate"],
17
+ };
18
+ const MARKDOWN_LEAK_RE = /(\*\*|^#{1,6}\s|`{1,3}|\[[^\]]+\]\([^)]+\))/m;
19
+ const PROMO_CTA_RE = /\b(buy now|click here|sign up|subscribe|limited time|act now|don'?t miss|shop now)\b/i;
20
+ const UNSAFE_TAGS = new Set([
21
+ "script",
22
+ "iframe",
23
+ "object",
24
+ "embed",
25
+ "form",
26
+ "input",
27
+ "button",
28
+ "textarea",
29
+ "select",
30
+ "style",
31
+ "link",
32
+ "meta",
33
+ "base",
34
+ ]);
35
+ const UNSAFE_ATTR_VALUE_RE = /^\s*(javascript|data|vbscript):/i;
36
+ function jsonLdTypesOf(block) {
37
+ const t = block["@type"];
38
+ if (typeof t === "string")
39
+ return [t];
40
+ if (Array.isArray(t))
41
+ return t.filter((x) => typeof x === "string");
42
+ return [];
43
+ }
44
+ /** Schema.org required-property check for proposed JSON-LD blocks. */
45
+ export function validateAddJsonLd(c) {
46
+ if (typeof c.block !== "object" || c.block === null) {
47
+ return fail("add_jsonld: block must be a JSON object");
48
+ }
49
+ const block = c.block;
50
+ if (block["@context"] === undefined) {
51
+ return fail("add_jsonld: missing @context");
52
+ }
53
+ const types = jsonLdTypesOf(block);
54
+ if (types.length === 0) {
55
+ return fail("add_jsonld: missing or invalid @type");
56
+ }
57
+ for (const t of types) {
58
+ const required = REQUIRED_PROPERTIES_BY_TYPE[t];
59
+ if (!required)
60
+ continue;
61
+ const missing = required.filter((p) => block[p] === undefined);
62
+ if (missing.length > 0) {
63
+ return fail(`add_jsonld: ${t} missing required properties: ${missing.join(", ")}`);
64
+ }
65
+ }
66
+ return VALID;
67
+ }
68
+ export function validateReplaceH1(c) {
69
+ if (!c.after.trim())
70
+ return fail("replace_h1: after-text is empty");
71
+ if (c.after.length > 200)
72
+ return fail(`replace_h1: after-text too long (${c.after.length} > 200 chars)`);
73
+ if (MARKDOWN_LEAK_RE.test(c.after))
74
+ return fail("replace_h1: after-text contains markdown syntax");
75
+ if (c.after === c.before)
76
+ return fail("replace_h1: after-text identical to before-text");
77
+ return VALID;
78
+ }
79
+ export function validateRewriteMeta(c) {
80
+ if (!c.after.trim())
81
+ return fail(`rewrite_meta[${c.field}]: after-text is empty`);
82
+ if (MARKDOWN_LEAK_RE.test(c.after))
83
+ return fail(`rewrite_meta[${c.field}]: after-text contains markdown syntax`);
84
+ if (c.field === "title") {
85
+ if (c.after.length < 10)
86
+ return fail(`rewrite_meta[title]: too short (${c.after.length} < 10 chars)`);
87
+ if (c.after.length > 70)
88
+ return fail(`rewrite_meta[title]: too long (${c.after.length} > 70 chars)`);
89
+ }
90
+ else if (c.field === "description") {
91
+ if (c.after.length < 50)
92
+ return fail(`rewrite_meta[description]: too short (${c.after.length} < 50 chars)`);
93
+ if (c.after.length > 160)
94
+ return fail(`rewrite_meta[description]: too long (${c.after.length} > 160 chars)`);
95
+ }
96
+ return VALID;
97
+ }
98
+ /**
99
+ * HTML-safety check using a cheerio-based allowlist. Rejects script/iframe/
100
+ * object/embed/form/style elements and any href/src that uses
101
+ * javascript:/data:/vbscript: schemes. Defense in depth — the LLM-generated
102
+ * patch is being prepared for paste into a CMS, not auto-applied, but a
103
+ * malicious patch in a public manifest is still a footgun.
104
+ */
105
+ export function validateAddFaqBlock(c) {
106
+ if (!c.html.trim())
107
+ return fail("add_faq_block: html is empty");
108
+ let $;
109
+ try {
110
+ $ = load(c.html, null, false);
111
+ }
112
+ catch (e) {
113
+ return fail(`add_faq_block: html could not be parsed (${e instanceof Error ? e.message : String(e)})`);
114
+ }
115
+ // Helper closures: return the offending value or null. Cleaner than
116
+ // mutating an outer variable inside cheerio's `.each` callback (TS
117
+ // control-flow analysis can't see callback side effects, so the post-
118
+ // loop value gets narrowed to `never`).
119
+ const findUnsafeTag = () => {
120
+ const matches = [];
121
+ $("*").each((_, el) => {
122
+ const tag = (el.tagName ?? "").toLowerCase();
123
+ if (UNSAFE_TAGS.has(tag))
124
+ matches.push(tag);
125
+ });
126
+ return matches[0] ?? null;
127
+ };
128
+ const findUnsafeAttr = () => {
129
+ const matches = [];
130
+ $("[href], [src]").each((_, el) => {
131
+ const attribs = el.attribs ?? {};
132
+ const href = attribs.href ?? attribs.src ?? "";
133
+ if (UNSAFE_ATTR_VALUE_RE.test(href))
134
+ matches.push(href);
135
+ });
136
+ return matches[0] ?? null;
137
+ };
138
+ const unsafeTag = findUnsafeTag();
139
+ if (unsafeTag)
140
+ return fail(`add_faq_block: unsafe tag <${unsafeTag}>`);
141
+ const unsafeAttr = findUnsafeAttr();
142
+ if (unsafeAttr)
143
+ return fail(`add_faq_block: unsafe href/src scheme (${unsafeAttr.slice(0, 30)})`);
144
+ return VALID;
145
+ }
146
+ export function validateRewriteIntro(c) {
147
+ const after = c.after.trim();
148
+ if (after.length < 50)
149
+ return fail(`rewrite_intro: too short (${after.length} < 50 chars)`);
150
+ if (after.length > 500)
151
+ return fail(`rewrite_intro: too long (${after.length} > 500 chars)`);
152
+ if (PROMO_CTA_RE.test(after))
153
+ return fail("rewrite_intro: contains promotional CTA language");
154
+ if (MARKDOWN_LEAK_RE.test(after))
155
+ return fail("rewrite_intro: contains markdown syntax");
156
+ return VALID;
157
+ }
158
+ export function validateAddInternalLink(c) {
159
+ let fromHost;
160
+ let toHost;
161
+ try {
162
+ fromHost = new URL(c.from).hostname;
163
+ }
164
+ catch {
165
+ return fail("add_internal_link: from is not a valid URL");
166
+ }
167
+ try {
168
+ toHost = new URL(c.to).hostname;
169
+ }
170
+ catch {
171
+ return fail("add_internal_link: to is not a valid URL");
172
+ }
173
+ if (fromHost !== toHost) {
174
+ return fail(`add_internal_link: cross-domain (${fromHost} → ${toHost}); this rule emits internal links only`);
175
+ }
176
+ if (c.from === c.to) {
177
+ return fail("add_internal_link: from and to are identical (would create a self-link)");
178
+ }
179
+ if (!c.anchor.trim()) {
180
+ return fail("add_internal_link: anchor text is empty");
181
+ }
182
+ if (c.anchor.length > 100) {
183
+ return fail(`add_internal_link: anchor text too long (${c.anchor.length} > 100 chars)`);
184
+ }
185
+ return VALID;
186
+ }
187
+ export function validateRemoveThinBlock(c) {
188
+ const sel = c.selector.trim();
189
+ if (!sel)
190
+ return fail("remove_thin_block: selector is empty");
191
+ // Smoke-parse via cheerio: load empty doc and call .find(selector); a
192
+ // throw indicates a malformed selector. Doesn't catch all selector bugs
193
+ // (e.g. dependent on actual DOM) but rejects the obvious bad ones.
194
+ try {
195
+ load("<html></html>")(sel);
196
+ }
197
+ catch (e) {
198
+ return fail(`remove_thin_block: invalid selector (${e instanceof Error ? e.message : String(e)})`);
199
+ }
200
+ return VALID;
201
+ }
202
+ /** Dispatcher: routes a `PageChange` to its specific validator. */
203
+ export function validatePageChange(c) {
204
+ switch (c.type) {
205
+ case "replace_h1":
206
+ return validateReplaceH1(c);
207
+ case "rewrite_meta":
208
+ return validateRewriteMeta(c);
209
+ case "add_jsonld":
210
+ return validateAddJsonLd(c);
211
+ case "add_faq_block":
212
+ return validateAddFaqBlock(c);
213
+ case "rewrite_intro":
214
+ return validateRewriteIntro(c);
215
+ case "add_internal_link":
216
+ return validateAddInternalLink(c);
217
+ case "remove_thin_block":
218
+ return validateRemoveThinBlock(c);
219
+ }
220
+ }
221
+ //# sourceMappingURL=page-changes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"page-changes.js","sourceRoot":"","sources":["../../../../src/ai/manifest/validators/page-changes.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Validator result. Patch validators return one of these for each proposed
3
+ * change; the dispatcher aggregates per-manifest. `reason` is a one-line
4
+ * human-readable explanation suitable for surfacing in the manifest UI
5
+ * ("dropped: H1 too long (250 chars > 200)").
6
+ */
7
+ export interface ValidationOk {
8
+ valid: true;
9
+ }
10
+ export interface ValidationErr {
11
+ valid: false;
12
+ reason: string;
13
+ }
14
+ export type ValidationResult = ValidationOk | ValidationErr;
15
+ export declare const VALID: ValidationOk;
16
+ export declare function fail(reason: string): ValidationErr;
17
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/ai/manifest/validators/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,IAAI,CAAC;CACb;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,KAAK,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,MAAM,gBAAgB,GAAG,YAAY,GAAG,aAAa,CAAC;AAE5D,eAAO,MAAM,KAAK,EAAE,YAA8B,CAAC;AAEnD,wBAAgB,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,aAAa,CAElD"}
@@ -0,0 +1,5 @@
1
+ export const VALID = { valid: true };
2
+ export function fail(reason) {
3
+ return { valid: false, reason };
4
+ }
5
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/ai/manifest/validators/types.ts"],"names":[],"mappings":"AAiBA,MAAM,CAAC,MAAM,KAAK,GAAiB,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;AAEnD,MAAM,UAAU,IAAI,CAAC,MAAc;IACjC,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;AAClC,CAAC"}
@@ -0,0 +1,74 @@
1
+ import type { LanguageModel } from "ai";
2
+ import { type ManifestValidationReport } from "./manifest/validate-manifest.js";
3
+ import { type ManifestDiff } from "./manifest/diff.js";
4
+ import type { FixManifest } from "./orchestrator/finish-tool.js";
5
+ import type { EventSink } from "./orchestrator/log.js";
6
+ import type { BudgetCaps, SessionResult } from "./orchestrator/types.js";
7
+ import type { AiOptions } from "../types.js";
8
+ export interface OrchestrateOptions {
9
+ /** Site to audit. Origin (e.g. https://example.com) is fine; the orchestrator's first move is fetching the sitemap. */
10
+ domain: string;
11
+ /** Caller identity. Persisted on the session row in the web app's DB; stub allowed for CLI/dogfood use. */
12
+ userId: string;
13
+ /**
14
+ * AI provider configuration. Falls through to `createLanguageModel`'s
15
+ * auto-detection when omitted (env-var based: `ANTHROPIC_API_KEY`, etc.).
16
+ */
17
+ ai?: AiOptions;
18
+ /** Override default budget caps. Merge with `DEFAULT_BUDGET`. */
19
+ budget?: Partial<BudgetCaps>;
20
+ /** Optional path for durable NDJSON session log. */
21
+ ndjsonPath?: string;
22
+ /** Optional event sink — SSE/R2 fanout in the web app, console.log in the CLI. */
23
+ onEvent?: EventSink;
24
+ /** External abort signal. */
25
+ signal?: AbortSignal;
26
+ /** Per-model-call retry count for transient errors. Default 2. */
27
+ maxRetries?: number;
28
+ /**
29
+ * @internal Test-only escape hatch — inject a pre-resolved model to skip
30
+ * `createLanguageModel`. Production callers always go through `ai`.
31
+ */
32
+ _resolvedModel?: {
33
+ model: LanguageModel;
34
+ providerId: string;
35
+ modelId: string;
36
+ };
37
+ }
38
+ export interface OrchestrateResult {
39
+ /** Raw session output: events, usage, stop reason. */
40
+ session: SessionResult;
41
+ /** Final manifest if the LLM called `finish_audit`; null otherwise. */
42
+ manifest: FixManifest | null;
43
+ /** Patch-by-patch validation report. Null when no manifest was produced. */
44
+ validation: ManifestValidationReport | null;
45
+ /** Structured diff projection of the manifest. Null when no manifest was produced. */
46
+ diff: ManifestDiff | null;
47
+ }
48
+ /**
49
+ * Public entry point that ties Phases 1–6 together. One call audits a
50
+ * domain, validates every patch, and emits structured diffs:
51
+ *
52
+ * ```ts
53
+ * const { manifest, validation, diff } = await orchestrate({
54
+ * domain: "https://example.com",
55
+ * userId: "demo",
56
+ * onEvent: (e) => console.log(e),
57
+ * });
58
+ * ```
59
+ *
60
+ * Composition (the elegant part):
61
+ * 1. Resolve provider via existing `createLanguageModel`
62
+ * 2. Drive the LLM tool loop via `runOrchestrator`
63
+ * 3. Validate every patch the LLM proposed via `validateManifest`
64
+ * 4. Produce structured diffs for every patch via `diffManifest`
65
+ *
66
+ * Each layer is independently testable; this function exists to give
67
+ * callers (web app, CLI, MCP, scripts) one stable API surface.
68
+ *
69
+ * Returns null `manifest`/`validation`/`diff` when the session terminated
70
+ * for any reason other than `finish_audit` (budget breach, abort, error).
71
+ * Callers should branch on `session.reason` to handle these.
72
+ */
73
+ export declare function orchestrate(opts: OrchestrateOptions): Promise<OrchestrateResult>;
74
+ //# sourceMappingURL=orchestrate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orchestrate.d.ts","sourceRoot":"","sources":["../../src/ai/orchestrate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,IAAI,CAAC;AAExC,OAAO,EAEL,KAAK,wBAAwB,EAC9B,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAgB,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAErE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AACjE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACzE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAE7C,MAAM,WAAW,kBAAkB;IACjC,uHAAuH;IACvH,MAAM,EAAE,MAAM,CAAC;IACf,2GAA2G;IAC3G,MAAM,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,EAAE,CAAC,EAAE,SAAS,CAAC;IACf,iEAAiE;IACjE,MAAM,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;IAC7B,oDAAoD;IACpD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,kFAAkF;IAClF,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,6BAA6B;IAC7B,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,kEAAkE;IAClE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,cAAc,CAAC,EAAE;QAAE,KAAK,EAAE,aAAa,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;CAChF;AAED,MAAM,WAAW,iBAAiB;IAChC,sDAAsD;IACtD,OAAO,EAAE,aAAa,CAAC;IACvB,uEAAuE;IACvE,QAAQ,EAAE,WAAW,GAAG,IAAI,CAAC;IAC7B,4EAA4E;IAC5E,UAAU,EAAE,wBAAwB,GAAG,IAAI,CAAC;IAC5C,sFAAsF;IACtF,IAAI,EAAE,YAAY,GAAG,IAAI,CAAC;CAC3B;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAsB,WAAW,CAAC,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CA0BtF"}
@@ -0,0 +1,54 @@
1
+ import { createLanguageModel } from "./adapters/index.js";
2
+ import { validateManifest, } from "./manifest/validate-manifest.js";
3
+ import { diffManifest } from "./manifest/diff.js";
4
+ import { runOrchestrator } from "./orchestrator/runner.js";
5
+ /**
6
+ * Public entry point that ties Phases 1–6 together. One call audits a
7
+ * domain, validates every patch, and emits structured diffs:
8
+ *
9
+ * ```ts
10
+ * const { manifest, validation, diff } = await orchestrate({
11
+ * domain: "https://example.com",
12
+ * userId: "demo",
13
+ * onEvent: (e) => console.log(e),
14
+ * });
15
+ * ```
16
+ *
17
+ * Composition (the elegant part):
18
+ * 1. Resolve provider via existing `createLanguageModel`
19
+ * 2. Drive the LLM tool loop via `runOrchestrator`
20
+ * 3. Validate every patch the LLM proposed via `validateManifest`
21
+ * 4. Produce structured diffs for every patch via `diffManifest`
22
+ *
23
+ * Each layer is independently testable; this function exists to give
24
+ * callers (web app, CLI, MCP, scripts) one stable API surface.
25
+ *
26
+ * Returns null `manifest`/`validation`/`diff` when the session terminated
27
+ * for any reason other than `finish_audit` (budget breach, abort, error).
28
+ * Callers should branch on `session.reason` to handle these.
29
+ */
30
+ export async function orchestrate(opts) {
31
+ const resolved = opts._resolvedModel ?? (await createLanguageModel(opts.ai ?? {}));
32
+ const session = await runOrchestrator({
33
+ domain: opts.domain,
34
+ userId: opts.userId,
35
+ model: resolved.model,
36
+ providerId: resolved.providerId,
37
+ modelId: resolved.modelId,
38
+ budget: opts.budget,
39
+ ndjsonPath: opts.ndjsonPath,
40
+ onEvent: opts.onEvent,
41
+ signal: opts.signal,
42
+ maxRetries: opts.maxRetries,
43
+ });
44
+ if (!session.manifest) {
45
+ return { session, manifest: null, validation: null, diff: null };
46
+ }
47
+ return {
48
+ session,
49
+ manifest: session.manifest,
50
+ validation: validateManifest(session.manifest),
51
+ diff: diffManifest(session.manifest),
52
+ };
53
+ }
54
+ //# sourceMappingURL=orchestrate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orchestrate.js","sourceRoot":"","sources":["../../src/ai/orchestrate.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EACL,gBAAgB,GAEjB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,YAAY,EAAqB,MAAM,oBAAoB,CAAC;AACrE,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AA4C3D;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,IAAwB;IACxD,MAAM,QAAQ,GAAG,IAAI,CAAC,cAAc,IAAI,CAAC,MAAM,mBAAmB,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAEnF,MAAM,OAAO,GAAG,MAAM,eAAe,CAAC;QACpC,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,KAAK,EAAE,QAAQ,CAAC,KAAK;QACrB,UAAU,EAAE,QAAQ,CAAC,UAAU;QAC/B,OAAO,EAAE,QAAQ,CAAC,OAAO;QACzB,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,UAAU,EAAE,IAAI,CAAC,UAAU;QAC3B,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,UAAU,EAAE,IAAI,CAAC,UAAU;KAC5B,CAAC,CAAC;IAEH,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;QACtB,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IACnE,CAAC;IAED,OAAO;QACL,OAAO;QACP,QAAQ,EAAE,OAAO,CAAC,QAAQ;QAC1B,UAAU,EAAE,gBAAgB,CAAC,OAAO,CAAC,QAAQ,CAAC;QAC9C,IAAI,EAAE,YAAY,CAAC,OAAO,CAAC,QAAQ,CAAC;KACrC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,57 @@
1
+ import type { BudgetCaps, StopReason, UsageSnapshot } from "./types.js";
2
+ /**
3
+ * Tracks per-session usage against `BudgetCaps`. Consumed by the runner's
4
+ * step boundary: after every LLM step + tool batch, we record the usage and
5
+ * ask `nextStopReason()` whether to terminate.
6
+ *
7
+ * Wall time is measured from `start()`. Cost is estimated using the existing
8
+ * `estimateCostUsd` table; for unknown providers/models, cost defaults to 0
9
+ * which means USD caps don't fire — caller is responsible for ensuring
10
+ * provider/model are recognized when USD enforcement matters.
11
+ */
12
+ export declare class BudgetTracker {
13
+ private readonly caps;
14
+ private readonly providerId;
15
+ private readonly modelId;
16
+ private inputTokens;
17
+ private outputTokens;
18
+ private toolCallCount;
19
+ private externalUsd;
20
+ private startedAt;
21
+ /** Largest observed input-token count for any single step. Drives the projection. */
22
+ private maxStepInputTokens;
23
+ private maxStepOutputTokens;
24
+ private stepCount;
25
+ constructor(caps: BudgetCaps, providerId: string, modelId: string);
26
+ start(): void;
27
+ recordStepUsage(usage: {
28
+ inputTokens?: number;
29
+ outputTokens?: number;
30
+ }): number;
31
+ recordToolCalls(n: number): void;
32
+ /**
33
+ * Record a non-LLM external API cost (SerpAPI calls, AI-engine probes,
34
+ * etc.) so the session budget accurately reflects total spend, not just
35
+ * orchestrator-LLM tokens.
36
+ */
37
+ recordExternalCost(usd: number): void;
38
+ estimatedUsd(): number;
39
+ snapshot(): UsageSnapshot;
40
+ /**
41
+ * Returns the StopReason that fires now, or null when no cap is breached.
42
+ * Order matters — earlier checks take priority when multiple caps exceed
43
+ * simultaneously (most informative reason wins).
44
+ */
45
+ nextStopReason(): StopReason | null;
46
+ /**
47
+ * Pre-flight projection: would executing one more step at the worst-case
48
+ * (max observed) per-step cost push us over the USD or input-token cap?
49
+ * Used by `stopWhen` to refuse the next step before it overshoots, rather
50
+ * than reactively after.
51
+ *
52
+ * Returns null until at least one step has completed — we have nothing
53
+ * to project from before that.
54
+ */
55
+ projectedNextStopReason(): StopReason | null;
56
+ }
57
+ //# sourceMappingURL=budget.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"budget.d.ts","sourceRoot":"","sources":["../../../src/ai/orchestrator/budget.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAExE;;;;;;;;;GASG;AACH,qBAAa,aAAa;IAYtB,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,OAAO;IAb1B,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,YAAY,CAAK;IACzB,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,SAAS,CAAK;IACtB,qFAAqF;IACrF,OAAO,CAAC,kBAAkB,CAAK;IAC/B,OAAO,CAAC,mBAAmB,CAAK;IAChC,OAAO,CAAC,SAAS,CAAK;gBAGH,IAAI,EAAE,UAAU,EAChB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM;IAGlC,KAAK,IAAI,IAAI;IAIb,eAAe,CAAC,KAAK,EAAE;QAAE,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,MAAM;IAW/E,eAAe,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI;IAIhC;;;;OAIG;IACH,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAIrC,YAAY,IAAI,MAAM;IAStB,QAAQ,IAAI,aAAa;IAUzB;;;;OAIG;IACH,cAAc,IAAI,UAAU,GAAG,IAAI;IAUnC;;;;;;;;OAQG;IACH,uBAAuB,IAAI,UAAU,GAAG,IAAI;CAe7C"}
@@ -0,0 +1,114 @@
1
+ import { estimateCostUsd } from "../cost.js";
2
+ /**
3
+ * Tracks per-session usage against `BudgetCaps`. Consumed by the runner's
4
+ * step boundary: after every LLM step + tool batch, we record the usage and
5
+ * ask `nextStopReason()` whether to terminate.
6
+ *
7
+ * Wall time is measured from `start()`. Cost is estimated using the existing
8
+ * `estimateCostUsd` table; for unknown providers/models, cost defaults to 0
9
+ * which means USD caps don't fire — caller is responsible for ensuring
10
+ * provider/model are recognized when USD enforcement matters.
11
+ */
12
+ export class BudgetTracker {
13
+ caps;
14
+ providerId;
15
+ modelId;
16
+ inputTokens = 0;
17
+ outputTokens = 0;
18
+ toolCallCount = 0;
19
+ externalUsd = 0;
20
+ startedAt = 0;
21
+ /** Largest observed input-token count for any single step. Drives the projection. */
22
+ maxStepInputTokens = 0;
23
+ maxStepOutputTokens = 0;
24
+ stepCount = 0;
25
+ constructor(caps, providerId, modelId) {
26
+ this.caps = caps;
27
+ this.providerId = providerId;
28
+ this.modelId = modelId;
29
+ }
30
+ start() {
31
+ this.startedAt = Date.now();
32
+ }
33
+ recordStepUsage(usage) {
34
+ const input = usage.inputTokens ?? 0;
35
+ const output = usage.outputTokens ?? 0;
36
+ this.inputTokens += input;
37
+ this.outputTokens += output;
38
+ if (input > this.maxStepInputTokens)
39
+ this.maxStepInputTokens = input;
40
+ if (output > this.maxStepOutputTokens)
41
+ this.maxStepOutputTokens = output;
42
+ this.stepCount += 1;
43
+ return this.estimatedUsd();
44
+ }
45
+ recordToolCalls(n) {
46
+ this.toolCallCount += n;
47
+ }
48
+ /**
49
+ * Record a non-LLM external API cost (SerpAPI calls, AI-engine probes,
50
+ * etc.) so the session budget accurately reflects total spend, not just
51
+ * orchestrator-LLM tokens.
52
+ */
53
+ recordExternalCost(usd) {
54
+ if (usd > 0)
55
+ this.externalUsd += usd;
56
+ }
57
+ estimatedUsd() {
58
+ const llmUsd = estimateCostUsd(this.providerId, this.modelId, {
59
+ input: this.inputTokens,
60
+ output: this.outputTokens,
61
+ }) ?? 0;
62
+ return llmUsd + this.externalUsd;
63
+ }
64
+ snapshot() {
65
+ return {
66
+ inputTokens: this.inputTokens,
67
+ outputTokens: this.outputTokens,
68
+ estimatedUsd: this.estimatedUsd(),
69
+ toolCallCount: this.toolCallCount,
70
+ elapsedMs: this.startedAt === 0 ? 0 : Date.now() - this.startedAt,
71
+ };
72
+ }
73
+ /**
74
+ * Returns the StopReason that fires now, or null when no cap is breached.
75
+ * Order matters — earlier checks take priority when multiple caps exceed
76
+ * simultaneously (most informative reason wins).
77
+ */
78
+ nextStopReason() {
79
+ if (this.toolCallCount >= this.caps.maxToolCalls)
80
+ return "tool_call_limit";
81
+ if (this.inputTokens >= this.caps.maxInputTokensTotal)
82
+ return "input_token_limit";
83
+ if (this.estimatedUsd() >= this.caps.maxSessionUsd)
84
+ return "usd_limit";
85
+ if (this.startedAt > 0 && Date.now() - this.startedAt >= this.caps.maxWallSeconds * 1000) {
86
+ return "wall_time_limit";
87
+ }
88
+ return null;
89
+ }
90
+ /**
91
+ * Pre-flight projection: would executing one more step at the worst-case
92
+ * (max observed) per-step cost push us over the USD or input-token cap?
93
+ * Used by `stopWhen` to refuse the next step before it overshoots, rather
94
+ * than reactively after.
95
+ *
96
+ * Returns null until at least one step has completed — we have nothing
97
+ * to project from before that.
98
+ */
99
+ projectedNextStopReason() {
100
+ if (this.stepCount === 0)
101
+ return null;
102
+ const projectedInput = this.inputTokens + this.maxStepInputTokens;
103
+ if (projectedInput >= this.caps.maxInputTokensTotal)
104
+ return "input_token_limit";
105
+ const projectedLlmUsd = estimateCostUsd(this.providerId, this.modelId, {
106
+ input: projectedInput,
107
+ output: this.outputTokens + this.maxStepOutputTokens,
108
+ }) ?? 0;
109
+ if (projectedLlmUsd + this.externalUsd >= this.caps.maxSessionUsd)
110
+ return "usd_limit";
111
+ return null;
112
+ }
113
+ }
114
+ //# sourceMappingURL=budget.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"budget.js","sourceRoot":"","sources":["../../../src/ai/orchestrator/budget.ts"],"names":[],"mappings":"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"}