@shoalrun/cli 0.1.0-alpha.16 → 0.1.0-alpha.18

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 (703) hide show
  1. package/AUTHORING.md +29 -0
  2. package/CHANGELOG.md +40 -0
  3. package/DEPLOYMENT-PROFILES.md +96 -5
  4. package/README.md +59 -3
  5. package/agent-docs/.well-known/shoalrun/navigation/project-updates-50f26fe22670.txt +21 -17
  6. package/agent-docs/SNAPSHOT.json +5 -5
  7. package/agent-docs/api-docs/focused-contracts.md +4 -4
  8. package/agent-docs/api-docs/generate.md +11 -11
  9. package/agent-docs/api-docs/generate.sections/add-useful-examples.md +3 -3
  10. package/agent-docs/api-docs/generate.sections/choose-generated-references-or-mdx.md +4 -4
  11. package/agent-docs/api-docs/generate.sections/describe-filters-that-do-not-use-their-openapi-parameter-name.md +1 -1
  12. package/agent-docs/api-docs/generate.sections/generate-many-pages-selectively.md +2 -2
  13. package/agent-docs/api-docs/generate.sections/link-guides-to-api-references.md +1 -1
  14. package/agent-docs/api-docs/generate.sections/map-extension-values-to-shoalrun-status.md +1 -1
  15. package/agent-docs/api-docs/generate.sections/override-generated-reference-order-in-navigation.md +4 -4
  16. package/agent-docs/api-docs/generate.sections/related-reading.md +1 -1
  17. package/agent-docs/api-docs/generate.sections/use-a-template-for-editorial-context.md +2 -2
  18. package/agent-docs/api-docs/support.md +7 -7
  19. package/agent-docs/author/add-page.md +3 -3
  20. package/agent-docs/author/agent-overview.md +3 -3
  21. package/agent-docs/author/agent-workflow.md +7 -7
  22. package/agent-docs/author/analytics.md +27 -27
  23. package/agent-docs/author/analytics.sections/adapter-exports-and-consent.md +3 -3
  24. package/agent-docs/author/analytics.sections/built-in-events.md +15 -15
  25. package/agent-docs/author/analytics.sections/configure-an-adapter.md +1 -1
  26. package/agent-docs/author/analytics.sections/custom-interactions.md +2 -2
  27. package/agent-docs/author/analytics.sections/event-format.md +2 -2
  28. package/agent-docs/author/analytics.sections/html-markdown-and-agents.md +4 -4
  29. package/agent-docs/author/analytics.sections/inspect-events-locally.md +2 -2
  30. package/agent-docs/author/analytics.sections/map-events-to-your-service.md +3 -3
  31. package/agent-docs/author/analytics.sections/posthog-example.md +3 -3
  32. package/agent-docs/author/analytics.sections/related-reading.md +1 -1
  33. package/agent-docs/author/authoring-agent.md +3 -3
  34. package/agent-docs/author/coding-agent.md +4 -4
  35. package/agent-docs/author/components/api-embeds.md +6 -6
  36. package/agent-docs/author/components/api-embeds.sections/apiexample.md +3 -3
  37. package/agent-docs/author/components/api-embeds.sections/html-markdown-and-agents.md +1 -1
  38. package/agent-docs/author/components/api-embeds.sections/related-reading.md +1 -1
  39. package/agent-docs/author/components/badge.md +2 -2
  40. package/agent-docs/author/components/callout.md +2 -2
  41. package/agent-docs/author/components/cards.md +16 -16
  42. package/agent-docs/author/components/cards.sections/add-a-lucide-icon.md +4 -4
  43. package/agent-docs/author/components/cards.sections/build-a-collection.md +7 -7
  44. package/agent-docs/author/components/cards.sections/curate-a-reading-list.md +9 -9
  45. package/agent-docs/author/components/cards.sections/html-markdown-and-agents.md +3 -3
  46. package/agent-docs/author/components/cards.sections/link-to-one-document.md +3 -3
  47. package/agent-docs/author/components/cards.sections/override-card-text.md +5 -5
  48. package/agent-docs/author/components/cards.sections/related-reading.md +3 -3
  49. package/agent-docs/author/components/code-blocks.md +2 -2
  50. package/agent-docs/author/components/collapsible.md +3 -3
  51. package/agent-docs/author/components/cookbook-chooser.md +5 -5
  52. package/agent-docs/author/components/custom/react.md +8 -8
  53. package/agent-docs/author/components/custom/react.sections/html-markdown-and-agents.md +3 -3
  54. package/agent-docs/author/components/custom/react.sections/interactive-react-example.md +2 -2
  55. package/agent-docs/author/components/custom/react.sections/registration.md +1 -1
  56. package/agent-docs/author/components/custom/react.sections/related-reading.md +1 -1
  57. package/agent-docs/author/components/custom/react.sections/share-the-model-with-the-browser.md +3 -3
  58. package/agent-docs/author/components/custom/react.sections/where-the-content-lives.md +3 -3
  59. package/agent-docs/author/components/custom.md +7 -7
  60. package/agent-docs/author/components/definition-list.md +2 -2
  61. package/agent-docs/author/components/diagrams/d2-gallery.md +2 -2
  62. package/agent-docs/author/components/diagrams/d2-gallery.sections/basic-shapes.md +2 -2
  63. package/agent-docs/author/components/diagrams/d2-gallery.sections/flows-and-structures.md +2 -2
  64. package/agent-docs/author/components/diagrams/d2-gallery.sections/html-markdown-and-agents.md +2 -2
  65. package/agent-docs/author/components/diagrams/d2-gallery.sections/layout-engines.md +2 -2
  66. package/agent-docs/author/components/diagrams/d2-gallery.sections/related-reading.md +2 -2
  67. package/agent-docs/author/components/diagrams/d2-gallery.sections/sequences-and-grids.md +2 -2
  68. package/agent-docs/author/components/diagrams/d2-gallery.sections/styles-and-code.md +2 -2
  69. package/agent-docs/author/components/diagrams/pele-gallery.md +3 -3
  70. package/agent-docs/author/components/diagrams/pele-gallery.sections/charts-and-planning.md +2 -2
  71. package/agent-docs/author/components/diagrams/pele-gallery.sections/flowchart-shapes.md +2 -2
  72. package/agent-docs/author/components/diagrams/pele-gallery.sections/flows-and-behavior.md +2 -2
  73. package/agent-docs/author/components/diagrams/pele-gallery.sections/html-markdown-and-agents.md +3 -3
  74. package/agent-docs/author/components/diagrams/pele-gallery.sections/related-reading.md +2 -2
  75. package/agent-docs/author/components/diagrams/pele-gallery.sections/specialized-diagrams.md +2 -2
  76. package/agent-docs/author/components/diagrams/pele-gallery.sections/systems-and-structures.md +2 -2
  77. package/agent-docs/author/components/diagrams.md +8 -8
  78. package/agent-docs/author/components/doc-link.md +3 -3
  79. package/agent-docs/author/components/fields.md +18 -18
  80. package/agent-docs/author/components/file-tree.md +2 -2
  81. package/agent-docs/author/components/images.md +5 -5
  82. package/agent-docs/author/components/info-hint.md +3 -3
  83. package/agent-docs/author/components/kbd.md +2 -2
  84. package/agent-docs/author/components/math.md +2 -2
  85. package/agent-docs/author/components/only.md +3 -3
  86. package/agent-docs/author/components/progress.md +3 -3
  87. package/agent-docs/author/components/steps.md +2 -2
  88. package/agent-docs/author/components/tables.md +2 -2
  89. package/agent-docs/author/components/tabs.md +5 -5
  90. package/agent-docs/author/components/timeline.md +2 -2
  91. package/agent-docs/author/components/tooltips.md +2 -2
  92. package/agent-docs/author/components/walkthroughs.md +2 -2
  93. package/agent-docs/author/components/walkthroughs.sections/attributes.md +1 -1
  94. package/agent-docs/author/components/walkthroughs.sections/build-up-code.md +1 -1
  95. package/agent-docs/author/components/walkthroughs.sections/choose-a-layout.md +2 -2
  96. package/agent-docs/author/components/walkthroughs.sections/explain-one-file.md +1 -1
  97. package/agent-docs/author/components/walkthroughs.sections/html-markdown-and-agents.md +1 -1
  98. package/agent-docs/author/components/walkthroughs.sections/related-reading.md +1 -1
  99. package/agent-docs/author/components/walkthroughs.sections/syntax.md +1 -1
  100. package/agent-docs/author/components/walkthroughs.sections/take-code-from-a-file.md +1 -1
  101. package/agent-docs/author/components.md +2 -2
  102. package/agent-docs/author/content.md +3 -3
  103. package/agent-docs/author/cookbooks.md +9 -9
  104. package/agent-docs/author/css.md +4 -4
  105. package/agent-docs/author/css.sections/borders-fields-and-navigation-tokens.md +3 -3
  106. package/agent-docs/author/css.sections/core-color-tokens.md +3 -3
  107. package/agent-docs/author/css.sections/html-markdown-and-agents.md +4 -4
  108. package/agent-docs/author/css.sections/page-attributes.md +3 -3
  109. package/agent-docs/author/css.sections/page-transitions.md +3 -3
  110. package/agent-docs/author/css.sections/responsive-behavior.md +3 -3
  111. package/agent-docs/author/css.sections/status-code-and-callout-tokens.md +3 -3
  112. package/agent-docs/author/css.sections/typography-shape-and-width-tokens.md +3 -3
  113. package/agent-docs/author/custom-metadata.md +13 -13
  114. package/agent-docs/author/custom-metadata.sections/add-a-custom-page-field.md +4 -4
  115. package/agent-docs/author/custom-metadata.sections/choose-text-for-each-surface.md +3 -3
  116. package/agent-docs/author/custom-metadata.sections/preview-changes-to-metadata-providers.md +2 -2
  117. package/agent-docs/author/custom-metadata.sections/read-metadata-from-a-project-module.md +3 -3
  118. package/agent-docs/author/custom-metadata.sections/related-reading.md +1 -1
  119. package/agent-docs/author/design-templates.md +3 -3
  120. package/agent-docs/author/design-writing-guides.md +3 -3
  121. package/agent-docs/author/frontmatter-reference.md +59 -16
  122. package/agent-docs/author/frontmatter-reference.sections/categorize-connect-and-present-the-page.md +64 -0
  123. package/agent-docs/author/frontmatter-reference.sections/choose-a-publication-and-visibility.md +14 -12
  124. package/agent-docs/author/frontmatter-reference.sections/control-output-details.md +2 -2
  125. package/agent-docs/author/frontmatter-reference.sections/feature-availability.md +59 -0
  126. package/agent-docs/author/frontmatter-reference.sections/global-defaults-and-enforced-values.md +2 -2
  127. package/agent-docs/author/frontmatter-reference.sections/html-markdown-and-agents.md +3 -3
  128. package/agent-docs/author/frontmatter-reference.sections/identify-and-route-a-page.md +2 -2
  129. package/agent-docs/author/frontmatter-reference.sections/point-agents-to-it.md +2 -2
  130. package/agent-docs/author/frontmatter-reference.sections/product-publication-fields.md +37 -0
  131. package/agent-docs/author/frontmatter-reference.sections/project-defined-fields.md +2 -2
  132. package/agent-docs/author/frontmatter-reference.sections/related-reading.md +2 -2
  133. package/agent-docs/author/frontmatter-reference.sections/use-the-local-files-while-authoring.md +4 -4
  134. package/agent-docs/author/frontmatter-reference.sections/when-the-files-update.md +2 -2
  135. package/agent-docs/author/frontmatter.md +13 -13
  136. package/agent-docs/author/frontmatter.sections/audience-badges.md +3 -3
  137. package/agent-docs/author/frontmatter.sections/give-deprecation-guidance.md +4 -4
  138. package/agent-docs/author/frontmatter.sections/global-defaults-and-enforced-values.md +1 -1
  139. package/agent-docs/author/frontmatter.sections/optional-native-fields.md +4 -4
  140. package/agent-docs/author/frontmatter.sections/publication-fields.md +2 -2
  141. package/agent-docs/author/frontmatter.sections/publishing-policy.md +1 -1
  142. package/agent-docs/author/frontmatter.sections/related-metadata-tasks.md +1 -1
  143. package/agent-docs/author/frontmatter.sections/related-reading.md +1 -1
  144. package/agent-docs/author/frontmatter.sections/required-after-inheritance.md +1 -1
  145. package/agent-docs/author/frontmatter.sections/seo-fields.md +2 -2
  146. package/agent-docs/author/frontmatter.sections/validation-rules.md +3 -3
  147. package/agent-docs/author/markdown-metadata.md +20 -20
  148. package/agent-docs/author/navigation.md +12 -12
  149. package/agent-docs/author/navigation.sections/arrange-authored-pages.md +4 -4
  150. package/agent-docs/author/navigation.sections/fill-an-api-tag-group.md +2 -2
  151. package/agent-docs/author/navigation.sections/hide-group-page-counts.md +4 -4
  152. package/agent-docs/author/navigation.sections/html-markdown-and-agents.md +4 -4
  153. package/agent-docs/author/navigation.sections/local-api-preview.md +2 -2
  154. package/agent-docs/author/navigation.sections/mix-guides-and-api-references.md +3 -3
  155. package/agent-docs/author/navigation.sections/optionally-split-a-large-menu-into-files.md +2 -2
  156. package/agent-docs/author/navigation.sections/reach-navigation-while-reading.md +2 -2
  157. package/agent-docs/author/navigation.sections/related-reading.md +2 -2
  158. package/agent-docs/author/navigation.sections/split-navigation-into-tabs.md +4 -4
  159. package/agent-docs/author/navigation.sections/subject-lifecycle-labels.md +3 -3
  160. package/agent-docs/author/reader-views.md +9 -9
  161. package/agent-docs/author/reader-views.sections/configure-the-choices.md +2 -2
  162. package/agent-docs/author/reader-views.sections/connect-your-own-control.md +1 -1
  163. package/agent-docs/author/reader-views.sections/how-it-works-for-agents.md +3 -3
  164. package/agent-docs/author/reader-views.sections/mark-pages.md +3 -3
  165. package/agent-docs/author/reader-views.sections/mark-sections-and-add-an-entry-choice.md +2 -2
  166. package/agent-docs/author/reader-views.sections/place-filter-controls.md +2 -2
  167. package/agent-docs/author/reader-views.sections/try-the-controls-here.md +2 -2
  168. package/agent-docs/author/recipe-drafts.md +5 -5
  169. package/agent-docs/author/recipe-drafts.sections/1-write-one-reusable-step.md +2 -2
  170. package/agent-docs/author/recipe-drafts.sections/2-list-the-steps-for-one-complete-goal.md +2 -2
  171. package/agent-docs/author/recipe-drafts.sections/3-generate-a-draft-and-review-it.md +1 -1
  172. package/agent-docs/author/recipe-drafts.sections/4-maintain-shoalrun-s-published-recipe-snapshots.md +2 -2
  173. package/agent-docs/author/recipe-drafts.sections/related-reading.md +1 -1
  174. package/agent-docs/author/recipe-drafts.sections/start-an-ingredient-from-an-api-example.md +2 -2
  175. package/agent-docs/author/recipes.md +9 -9
  176. package/agent-docs/author/recipes.sections/how-agents-use-this.md +3 -3
  177. package/agent-docs/author/recipes.sections/one-example-from-shoalrun.md +3 -3
  178. package/agent-docs/author/recipes.sections/related-reading.md +2 -2
  179. package/agent-docs/author/recipes.sections/try-a-complete-workflow.md +3 -3
  180. package/agent-docs/author/recipes.sections/use-recipes-for-task-oriented-how-tos.md +4 -4
  181. package/agent-docs/author/recipes.sections/what-changing-an-ingredient-updates.md +3 -3
  182. package/agent-docs/author/recipes.sections/what-each-file-does.md +2 -2
  183. package/agent-docs/author/recipes.sections/what-happens-and-when.md +3 -3
  184. package/agent-docs/author/related-reading.md +11 -11
  185. package/agent-docs/author/related-reading.sections/automatic-footers.md +3 -3
  186. package/agent-docs/author/related-reading.sections/declare-relationships.md +3 -3
  187. package/agent-docs/author/related-reading.sections/display-related-documents.md +3 -3
  188. package/agent-docs/author/related-reading.sections/html-markdown-and-agents.md +1 -1
  189. package/agent-docs/author/related-reading.sections/inspect-output-and-changes.md +2 -2
  190. package/agent-docs/author/related-reading.sections/reading-paths-in-section-markdown.md +3 -3
  191. package/agent-docs/author/related-reading.sections/related-reading.md +1 -1
  192. package/agent-docs/author/related-reading.sections/where-relationship-explanations-come-from.md +2 -2
  193. package/agent-docs/author/release-notes.md +8 -8
  194. package/agent-docs/author/search.md +82 -29
  195. package/agent-docs/author/search.sections/agent-and-mcp-search-scope.md +52 -0
  196. package/agent-docs/author/search.sections/choose-a-provider.md +8 -7
  197. package/agent-docs/author/search.sections/cli-and-mcp-ranking-details.md +4 -4
  198. package/agent-docs/author/search.sections/enable-included-semantic-search.md +66 -0
  199. package/agent-docs/author/search.sections/hosted-semantic-search-limits.md +3 -3
  200. package/agent-docs/author/search.sections/html-markdown-and-agents.md +3 -3
  201. package/agent-docs/author/search.sections/lexical-search.md +6 -6
  202. package/agent-docs/author/search.sections/local-semantic-preview.md +3 -3
  203. package/agent-docs/author/search.sections/read-a-search-result-with-an-agent.md +2 -2
  204. package/agent-docs/author/search.sections/related-reading.md +2 -2
  205. package/agent-docs/author/search.sections/reuse-the-lexical-index.md +5 -5
  206. package/agent-docs/author/search.sections/turn-search-off.md +3 -3
  207. package/agent-docs/author/search.sections/use-the-search-box.md +2 -2
  208. package/agent-docs/author/search.sections/write-a-custom-provider.md +11 -11
  209. package/agent-docs/author/snippets.md +3 -3
  210. package/agent-docs/author/taxonomy.md +3 -3
  211. package/agent-docs/author/templates.md +16 -14
  212. package/agent-docs/author/templates.sections/built-in-feature-templates.md +2 -2
  213. package/agent-docs/author/templates.sections/built-in-templates.md +2 -2
  214. package/agent-docs/author/templates.sections/choose-formatting-enforcement-for-your-project.md +7 -7
  215. package/agent-docs/author/templates.sections/create-or-edit-a-project-template.md +8 -6
  216. package/agent-docs/author/templates.sections/keep-the-four-shapes-distinct.md +2 -2
  217. package/agent-docs/author/templates.sections/project-added-templates.md +3 -3
  218. package/agent-docs/author/templates.sections/related-reading.md +2 -2
  219. package/agent-docs/author/templates.sections/scaffold-a-page.md +2 -2
  220. package/agent-docs/author/templates.sections/short-cli-and-derived-values.md +3 -3
  221. package/agent-docs/author/templates.sections/what-every-template-gives-you.md +3 -3
  222. package/agent-docs/author/workspace/commands.md +4 -4
  223. package/agent-docs/author/workspace.md +7 -7
  224. package/agent-docs/author/writing-style.md +33 -18
  225. package/agent-docs/author/writing-style.sections/adapt-this-example.md +2 -2
  226. package/agent-docs/author/writing-style.sections/choose-components-by-reader-need.md +3 -3
  227. package/agent-docs/author/writing-style.sections/evidence-and-uncertainty.md +4 -4
  228. package/agent-docs/author/writing-style.sections/example-audience-and-scope.md +2 -2
  229. package/agent-docs/author/writing-style.sections/feature-availability.md +20 -7
  230. package/agent-docs/author/writing-style.sections/ingredients-recipes-and-cookbooks.md +5 -5
  231. package/agent-docs/author/writing-style.sections/page-purpose-and-structure.md +4 -4
  232. package/agent-docs/author/writing-style.sections/procedures-and-examples.md +4 -4
  233. package/agent-docs/author/writing-style.sections/related-reading.md +2 -2
  234. package/agent-docs/author/writing-style.sections/review-a-draft.md +3 -3
  235. package/agent-docs/author/writing-style.sections/reviewed-writing-examples.md +2 -2
  236. package/agent-docs/author/writing-style.sections/voice-and-explanations.md +4 -2
  237. package/agent-docs/changelog/2026-10-14-agent-readiness.md +2 -2
  238. package/agent-docs/changelog/2026-10-15-evaluation-builds.md +9 -9
  239. package/agent-docs/changelog/2026-10-16-navigation-layouts.md +4 -4
  240. package/agent-docs/changelog/2026-10-17-mcp-hosting.md +2 -2
  241. package/agent-docs/changelog/2026-10-18-search-and-tooltips.md +3 -3
  242. package/agent-docs/changelog/2026-10-19-visual-navigation.md +3 -3
  243. package/agent-docs/changelog/2026-10-25.md +2 -2
  244. package/agent-docs/changelog/2026-10-26.md +4 -4
  245. package/agent-docs/changelog/2026-10-27.md +1 -1
  246. package/agent-docs/changelog/2026-10-28.md +3 -3
  247. package/agent-docs/changelog/2026-10-30.md +1 -1
  248. package/agent-docs/changelog/2026-11-03.md +5 -5
  249. package/agent-docs/changelog/2026-11-04-runtime-packaging.md +46 -0
  250. package/agent-docs/changelog/authoring-preview.md +3 -3
  251. package/agent-docs/changelog/authoring-search.md +1 -1
  252. package/agent-docs/changelog/authoring-tools.md +2 -2
  253. package/agent-docs/changelog/product-publications.md +60 -0
  254. package/agent-docs/changelog/working-tree-skill.md +1 -1
  255. package/agent-docs/changelog.md +17 -1
  256. package/agent-docs/chat/checks.md +11 -11
  257. package/agent-docs/chat/checks.sections/answer-ahead-of-time.md +1 -1
  258. package/agent-docs/chat/checks.sections/answer-for-one-audience.md +2 -2
  259. package/agent-docs/chat/checks.sections/answer-without-a-model.md +2 -2
  260. package/agent-docs/chat/checks.sections/follow-up-questions.md +2 -2
  261. package/agent-docs/chat/checks.sections/how-an-answer-is-checked.md +3 -3
  262. package/agent-docs/chat/checks.sections/questions-with-several-parts.md +3 -3
  263. package/agent-docs/chat/checks.sections/related-reading.md +1 -1
  264. package/agent-docs/chat/checks.sections/reuse-answers.md +4 -4
  265. package/agent-docs/chat/host.md +8 -8
  266. package/agent-docs/chat/host.sections/cap-the-daily-spend.md +2 -2
  267. package/agent-docs/chat/host.sections/keep-a-record-of-questions.md +3 -3
  268. package/agent-docs/chat/host.sections/related-reading.md +2 -2
  269. package/agent-docs/chat/passage-index.md +31 -27
  270. package/agent-docs/chat/passage-index.sections/build-the-index.md +3 -3
  271. package/agent-docs/chat/passage-index.sections/embed-passages.md +4 -4
  272. package/agent-docs/chat/passage-index.sections/how-the-default-chunker-splits-a-page.md +3 -3
  273. package/agent-docs/chat/passage-index.sections/limits.md +3 -3
  274. package/agent-docs/chat/passage-index.sections/passage-ids-and-links.md +14 -10
  275. package/agent-docs/chat/passage-index.sections/related-reading.md +3 -3
  276. package/agent-docs/chat/passage-index.sections/what-a-passage-contains.md +19 -19
  277. package/agent-docs/chat/prepared-answers.md +4 -4
  278. package/agent-docs/chat/settings.md +3 -3
  279. package/agent-docs/chat/settings.sections/choose-the-scorer.md +1 -1
  280. package/agent-docs/chat/settings.sections/configure-chat.md +1 -1
  281. package/agent-docs/chat/settings.sections/configure-retrieval.md +1 -1
  282. package/agent-docs/chat/settings.sections/related-reading.md +1 -1
  283. package/agent-docs/chat/settings.sections/send-extra-request-fields.md +2 -2
  284. package/agent-docs/chat/settings.sections/use-more-than-one-model.md +2 -2
  285. package/agent-docs/chat/settings.sections/when-the-scorer-is-down.md +1 -1
  286. package/agent-docs/chat/setup.md +2 -2
  287. package/agent-docs/chat.md +3 -3
  288. package/agent-docs/cli.md +73 -59
  289. package/agent-docs/cli.sections/audit-a-project-and-api-sources.md +11 -7
  290. package/agent-docs/cli.sections/author-pages.md +16 -12
  291. package/agent-docs/cli.sections/build-and-serve.md +30 -18
  292. package/agent-docs/cli.sections/inspect-config-and-operations.md +13 -9
  293. package/agent-docs/cli.sections/npm-scripts-in-this-repository.md +7 -3
  294. package/agent-docs/cli.sections/related-reading.md +6 -2
  295. package/agent-docs/cli.sections/search-and-chat.md +24 -18
  296. package/agent-docs/cli.sections/start-a-project.md +7 -3
  297. package/agent-docs/cli.sections/working-tree-authoring-tools.md +7 -3
  298. package/agent-docs/concepts.md +2 -2
  299. package/agent-docs/config/apis.md +2 -2
  300. package/agent-docs/config/content.md +3 -3
  301. package/agent-docs/config/content.sections/authoring.md +3 -3
  302. package/agent-docs/config/content.sections/badges.md +1 -1
  303. package/agent-docs/config/content.sections/callouts.md +1 -1
  304. package/agent-docs/config/content.sections/cookbooks.md +1 -1
  305. package/agent-docs/config/content.sections/frontmatter.md +1 -1
  306. package/agent-docs/config/content.sections/readerfilters.md +1 -1
  307. package/agent-docs/config/content.sections/related-reading.md +1 -1
  308. package/agent-docs/config/content.sections/relationships.md +1 -1
  309. package/agent-docs/config/content.sections/snippets.md +1 -1
  310. package/agent-docs/config/content.sections/templates.md +1 -1
  311. package/agent-docs/config/content.sections/variables.md +1 -1
  312. package/agent-docs/config/examples.md +4 -4
  313. package/agent-docs/config/examples.sections/feature-showcase.md +4 -4
  314. package/agent-docs/config/examples.sections/minimal-site.md +2 -2
  315. package/agent-docs/config/examples.sections/multilingual-help-center.md +2 -2
  316. package/agent-docs/config/examples.sections/parcel-api-documentation.md +2 -2
  317. package/agent-docs/config/examples.sections/related-reading.md +2 -2
  318. package/agent-docs/config/examples.sections/shared-company-preset.md +2 -2
  319. package/agent-docs/config/integrations.md +4 -4
  320. package/agent-docs/config/outputs.md +22 -16
  321. package/agent-docs/config/outputs.sections/exports.md +19 -13
  322. package/agent-docs/config/outputs.sections/metadata.md +2 -2
  323. package/agent-docs/config/outputs.sections/related-reading.md +1 -1
  324. package/agent-docs/config/publishing.md +29 -19
  325. package/agent-docs/config/publishing.sections/navigation.md +2 -2
  326. package/agent-docs/config/publishing.sections/redirects.md +8 -8
  327. package/agent-docs/config/publishing.sections/related-reading.md +2 -2
  328. package/agent-docs/config/site.md +42 -18
  329. package/agent-docs/config/site.sections/related-reading.md +1 -1
  330. package/agent-docs/config/site.sections/theme.md +1 -1
  331. package/agent-docs/config.md +2 -2
  332. package/agent-docs/configuration.md +19 -19
  333. package/agent-docs/configuration.sections/build-several-sites-from-shared-content.md +1 -1
  334. package/agent-docs/configuration.sections/change-inherited-lists-deliberately.md +5 -5
  335. package/agent-docs/configuration.sections/extract-a-section-with-include.md +1 -1
  336. package/agent-docs/configuration.sections/inspect-and-validate-changes.md +5 -5
  337. package/agent-docs/configuration.sections/related-reading.md +1 -1
  338. package/agent-docs/configuration.sections/separate-config-inheritance-from-page-metadata.md +5 -5
  339. package/agent-docs/configuration.sections/share-defaults-through-extends.md +3 -3
  340. package/agent-docs/configuration.sections/start-with-one-working-file.md +2 -2
  341. package/agent-docs/configuration.sections/understand-the-three-stages.md +3 -3
  342. package/agent-docs/configuration.sections/understand-where-paths-point.md +2 -2
  343. package/agent-docs/connect/mcp.md +24 -15
  344. package/agent-docs/content-delivery/agents.md +6 -6
  345. package/agent-docs/content-delivery/api.md +29 -16
  346. package/agent-docs/content-delivery/client.md +14 -8
  347. package/agent-docs/content-delivery/http-api/operations/get-content-representation-fa1d2e3f.md +10 -2
  348. package/agent-docs/content-delivery/http-api/operations/get-content-representation-head-4052375c.md +10 -2
  349. package/agent-docs/content-delivery/http-api/operations/get-content-resource-849f1c49.md +537 -3
  350. package/agent-docs/content-delivery/http-api/operations/get-content-resource-head-0a352acd.md +10 -2
  351. package/agent-docs/content-delivery/http-api/operations/list-content-resources-8e977ec7.md +545 -3
  352. package/agent-docs/content-delivery/http-api/operations/list-content-resources-head-b67cbad9.md +10 -2
  353. package/agent-docs/content-delivery/http-api.md +21 -7
  354. package/agent-docs/content-delivery/manifest.md +30 -8
  355. package/agent-docs/content-delivery/publish.md +5 -5
  356. package/agent-docs/content-delivery/render.md +6 -6
  357. package/agent-docs/content-delivery/rest.md +16 -8
  358. package/agent-docs/content-delivery/sections.md +11 -11
  359. package/agent-docs/content-delivery/select.md +6 -6
  360. package/agent-docs/content-delivery.md +4 -4
  361. package/agent-docs/contribute/agent-skills.md +3 -3
  362. package/agent-docs/cookbooks/authoring.md +3 -3
  363. package/agent-docs/cookbooks/site-workflows.md +2 -2
  364. package/agent-docs/cookbooks/welcome-email.md +14 -11
  365. package/agent-docs/documents.json +2445 -1942
  366. package/agent-docs/example-api/cedar.md +4 -4
  367. package/agent-docs/features.md +49 -0
  368. package/agent-docs/glossary.md +22 -22
  369. package/agent-docs/index.md +5 -5
  370. package/agent-docs/ingredients/audit-site.md +2 -2
  371. package/agent-docs/ingredients/build-site.md +2 -2
  372. package/agent-docs/ingredients/complete-page.md +2 -2
  373. package/agent-docs/ingredients/refresh-agent-bundle.md +2 -2
  374. package/agent-docs/non-goals.md +4 -4
  375. package/agent-docs/provenance.json +10 -4
  376. package/agent-docs/publish/agent-discovery.md +8 -2
  377. package/agent-docs/publish/agent-friendliness.md +21 -21
  378. package/agent-docs/publish/agent-friendliness.sections/discover-a-page-with-a-small-context-budget.md +5 -5
  379. package/agent-docs/publish/agent-friendliness.sections/distinguish-examples-from-a-real-service.md +5 -5
  380. package/agent-docs/publish/agent-friendliness.sections/evidence-has-a-scope.md +5 -5
  381. package/agent-docs/publish/agent-friendliness.sections/keep-shared-instructions-complete.md +5 -5
  382. package/agent-docs/publish/agent-friendliness.sections/related-reading.md +3 -3
  383. package/agent-docs/publish/agent-friendliness.sections/secret-handshake.md +3 -3
  384. package/agent-docs/publish/agent-friendliness.sections/try-the-page-controls.md +3 -3
  385. package/agent-docs/publish/agent-friendliness.sections/use-the-transport-your-client-supports.md +4 -4
  386. package/agent-docs/publish/agent-friendliness.sections/verify-the-page-and-detect-changes.md +9 -9
  387. package/agent-docs/publish/agent-friendliness.sections/what-an-agent-reads.md +5 -5
  388. package/agent-docs/publish/agent-friendliness.sections/what-happens-to-an-unsupported-component.md +4 -4
  389. package/agent-docs/publish/api-references.md +5 -5
  390. package/agent-docs/publish/api-references.sections/author-the-reference-page.md +2 -2
  391. package/agent-docs/publish/api-references.sections/build-and-verify-the-output.md +3 -3
  392. package/agent-docs/publish/api-references.sections/inspect-the-machine-readable-contract.md +2 -2
  393. package/agent-docs/publish/api-references.sections/next-steps.md +2 -2
  394. package/agent-docs/publish/api-references.sections/preview-a-small-api-reference.md +2 -2
  395. package/agent-docs/publish/api-references.sections/put-the-spec-in-your-project.md +2 -2
  396. package/agent-docs/publish/api-references.sections/register-the-operation.md +2 -2
  397. package/agent-docs/publish/api-references.sections/related-reading.md +2 -2
  398. package/agent-docs/publish/api-references.sections/review-imported-content-before-publishing.md +3 -3
  399. package/agent-docs/publish/api-references.sections/what-readers-get.md +3 -3
  400. package/agent-docs/publish/audit.md +8 -8
  401. package/agent-docs/publish/audit.sections/add-project-tests.md +2 -2
  402. package/agent-docs/publish/audit.sections/check-agent-evaluation-reports.md +2 -2
  403. package/agent-docs/publish/audit.sections/check-before-pushing.md +3 -3
  404. package/agent-docs/publish/audit.sections/connect-a-documentation-test-suite.md +2 -2
  405. package/agent-docs/publish/audit.sections/read-the-report.md +3 -3
  406. package/agent-docs/publish/audit.sections/related-reading.md +1 -1
  407. package/agent-docs/publish/content-export.md +37 -15
  408. package/agent-docs/publish/content-export.sections/assets-downloads-and-notices.md +4 -4
  409. package/agent-docs/publish/content-export.sections/check-the-result.md +2 -2
  410. package/agent-docs/publish/content-export.sections/inspect-the-manifest.md +3 -3
  411. package/agent-docs/publish/content-export.sections/prerequisites.md +4 -4
  412. package/agent-docs/publish/content-export.sections/related-reading.md +2 -2
  413. package/agent-docs/publish/content-export.sections/review-exported-api-material.md +3 -3
  414. package/agent-docs/publish/content-export.sections/try-the-help-drawer-example.md +2 -2
  415. package/agent-docs/publish/content-export.sections/what-the-representations-retain.md +4 -4
  416. package/agent-docs/publish/content-negotiation.md +10 -10
  417. package/agent-docs/publish/content-negotiation.sections/hosting-contract.md +2 -2
  418. package/agent-docs/publish/content-negotiation.sections/missing-pages.md +3 -3
  419. package/agent-docs/publish/content-negotiation.sections/related-reading.md +1 -1
  420. package/agent-docs/publish/content-negotiation.sections/validators-and-manifest-links.md +2 -2
  421. package/agent-docs/publish/content-negotiation.sections/verify-the-deployed-url.md +2 -2
  422. package/agent-docs/publish/content-negotiation.sections/what-if-the-host-cannot-negotiate.md +3 -3
  423. package/agent-docs/publish/content-negotiation.sections/what-shoalrun-builds-and-what-the-host-does.md +2 -2
  424. package/agent-docs/publish/content-negotiation.sections/why-this-matters.md +2 -2
  425. package/agent-docs/publish/deployment-check.md +6 -6
  426. package/agent-docs/publish/deployment-profiles.md +60 -26
  427. package/agent-docs/publish/deployment-profiles.sections/before-you-begin.md +5 -5
  428. package/agent-docs/publish/deployment-profiles.sections/build-and-inspect-the-edition.md +9 -9
  429. package/agent-docs/publish/deployment-profiles.sections/check-the-result.md +7 -7
  430. package/agent-docs/publish/deployment-profiles.sections/choose-navigation-labels.md +6 -6
  431. package/agent-docs/publish/deployment-profiles.sections/current-limits.md +7 -7
  432. package/agent-docs/publish/deployment-profiles.sections/define-the-shared-sku-manifest.md +6 -6
  433. package/agent-docs/publish/deployment-profiles.sections/html-markdown-and-agents.md +7 -7
  434. package/agent-docs/publish/deployment-profiles.sections/mark-pages-and-shared-sections.md +13 -13
  435. package/agent-docs/publish/deployment-profiles.sections/preview-and-edit-a-customer-edition.md +55 -0
  436. package/agent-docs/publish/deployment-profiles.sections/related-reading.md +6 -6
  437. package/agent-docs/publish/deployment-profiles.sections/select-each-product-release.md +55 -0
  438. package/agent-docs/publish/deployment-profiles.sections/supply-the-profile-from-the-deployment.md +6 -6
  439. package/agent-docs/publish/evals.md +16 -16
  440. package/agent-docs/publish/evals.sections/add-the-audit-hook.md +5 -5
  441. package/agent-docs/publish/evals.sections/check-the-report.md +4 -4
  442. package/agent-docs/publish/evals.sections/define-a-task-file.md +5 -5
  443. package/agent-docs/publish/evals.sections/diagnose-a-different-build.md +5 -5
  444. package/agent-docs/publish/evals.sections/prepare-a-report-for-the-built-site.md +5 -5
  445. package/agent-docs/publish/evals.sections/related-reading.md +3 -3
  446. package/agent-docs/publish/evals.sections/run-and-review-the-tasks.md +4 -4
  447. package/agent-docs/publish/evals.sections/shoalrun-s-own-example.md +6 -6
  448. package/agent-docs/publish/host-adapters.md +6 -6
  449. package/agent-docs/publish/manni.md +16 -16
  450. package/agent-docs/publish/manni.sections/check-the-result.md +3 -3
  451. package/agent-docs/publish/manni.sections/how-this-site-uses-manni.md +6 -6
  452. package/agent-docs/publish/manni.sections/optional-custom-policies.md +4 -4
  453. package/agent-docs/publish/manni.sections/prerequisites.md +2 -2
  454. package/agent-docs/publish/mcp-analytics.md +12 -12
  455. package/agent-docs/publish/mcp-analytics.sections/adapter-exports.md +4 -4
  456. package/agent-docs/publish/mcp-analytics.sections/enable-analytics.md +4 -4
  457. package/agent-docs/publish/mcp-analytics.sections/event-fields-and-service-mappings.md +4 -4
  458. package/agent-docs/publish/mcp-analytics.sections/optionally-collect-intent-and-group-calls.md +4 -4
  459. package/agent-docs/publish/mcp-analytics.sections/optionally-identify-the-client-and-model.md +5 -5
  460. package/agent-docs/publish/mcp-analytics.sections/related-reading.md +3 -3
  461. package/agent-docs/publish/mcp-analytics.sections/safeguards-and-limits.md +5 -5
  462. package/agent-docs/publish/mcp.md +56 -29
  463. package/agent-docs/publish/mcp.sections/check-budgets-and-errors.md +8 -8
  464. package/agent-docs/publish/mcp.sections/choose-the-documentation-source.md +4 -4
  465. package/agent-docs/publish/mcp.sections/configure-the-client.md +4 -4
  466. package/agent-docs/publish/mcp.sections/discover-product-releases-before-searching.md +52 -0
  467. package/agent-docs/publish/mcp.sections/generate-a-vercel-endpoint.md +6 -6
  468. package/agent-docs/publish/mcp.sections/html-markdown-and-agents.md +38 -0
  469. package/agent-docs/publish/mcp.sections/related-reading.md +3 -3
  470. package/agent-docs/publish/mcp.sections/search-then-read.md +13 -12
  471. package/agent-docs/publish/mcp.sections/serve-a-public-endpoint-on-node.md +12 -8
  472. package/agent-docs/publish/mcp.sections/verify-the-connection.md +4 -4
  473. package/agent-docs/publish/mcp.sections/why-offer-mcp-for-public-docs.md +4 -4
  474. package/agent-docs/publish/openapi-extension-mappings.md +12 -12
  475. package/agent-docs/publish/output.md +20 -20
  476. package/agent-docs/publish/output.sections/api-contracts.md +1 -1
  477. package/agent-docs/publish/output.sections/code-highlighting.md +1 -1
  478. package/agent-docs/publish/output.sections/current-limits.md +1 -1
  479. package/agent-docs/publish/output.sections/incremental-sync.md +4 -4
  480. package/agent-docs/publish/output.sections/manifest-records-and-sections.md +3 -3
  481. package/agent-docs/publish/output.sections/navigation-section-indexes.md +1 -1
  482. package/agent-docs/publish/output.sections/page-formats.md +2 -2
  483. package/agent-docs/publish/output.sections/published-output-contract.md +5 -5
  484. package/agent-docs/publish/output.sections/reader-appearance-and-controls.md +1 -1
  485. package/agent-docs/publish/output.sections/related-reading.md +1 -1
  486. package/agent-docs/publish/output.sections/response-identity.md +1 -1
  487. package/agent-docs/publish/output.sections/site-files.md +6 -6
  488. package/agent-docs/publish/output.sections/validate-an-existing-build-locally.md +3 -3
  489. package/agent-docs/publish/output.sections/where-files-go.md +3 -3
  490. package/agent-docs/publish/publications.md +108 -19
  491. package/agent-docs/publish/publications.sections/add-a-language.md +60 -0
  492. package/agent-docs/publish/publications.sections/change-just-one-part-of-a-shared-page.md +63 -0
  493. package/agent-docs/publish/publications.sections/give-each-api-version-its-own-contract.md +34 -0
  494. package/agent-docs/publish/publications.sections/keep-an-unchanged-page-in-one-file.md +53 -0
  495. package/agent-docs/publish/publications.sections/publish-versions-without-a-product-catalog.md +49 -0
  496. package/agent-docs/publish/publications.sections/related-reading.md +42 -0
  497. package/agent-docs/publish/publications.sections/version-products-independently.md +115 -0
  498. package/agent-docs/publish/publications.sections/what-agents-receive.md +38 -0
  499. package/agent-docs/publish/revisions.md +4 -4
  500. package/agent-docs/publish/seo.md +10 -10
  501. package/agent-docs/publish/seo.sections/related-reading.md +2 -2
  502. package/agent-docs/publish/seo.sections/set-the-public-address.md +3 -3
  503. package/agent-docs/publish/seo.sections/what-agents-receive.md +3 -3
  504. package/agent-docs/publish/seo.sections/what-the-build-adds.md +2 -2
  505. package/agent-docs/publish/seo.sections/write-the-page-title-and-summary.md +2 -2
  506. package/agent-docs/publish/single-source-sites.md +5 -5
  507. package/agent-docs/publish/troubleshooting.md +10 -10
  508. package/agent-docs/publish/vercel.md +5 -5
  509. package/agent-docs/publish/vercel.sections/check-the-deployment.md +1 -1
  510. package/agent-docs/publish/vercel.sections/include-an-mcp-endpoint.md +2 -2
  511. package/agent-docs/publish/vercel.sections/prepare-your-project.md +2 -2
  512. package/agent-docs/publish/vercel.sections/related-reading.md +1 -1
  513. package/agent-docs/publish.md +2 -2
  514. package/agent-docs/recipes/add-page.md +5 -5
  515. package/agent-docs/recipes/add-page.sections/audit-the-shoalrun-docs-project.md +2 -2
  516. package/agent-docs/recipes/add-page.sections/before-you-start.md +1 -1
  517. package/agent-docs/recipes/add-page.sections/build-the-shoalrun-docs-site.md +2 -2
  518. package/agent-docs/recipes/add-page.sections/check-agent-search-and-page-lookup.md +1 -1
  519. package/agent-docs/recipes/add-page.sections/check-the-built-page-artifacts.md +1 -1
  520. package/agent-docs/recipes/add-page.sections/check-the-outcome.md +1 -1
  521. package/agent-docs/recipes/add-page.sections/complete-the-guide-and-add-navigation.md +2 -2
  522. package/agent-docs/recipes/add-page.sections/install-the-site-dependencies.md +1 -1
  523. package/agent-docs/recipes/add-page.sections/regenerate-the-agent-documentation-bundle.md +2 -2
  524. package/agent-docs/recipes/add-page.sections/related-reading.md +1 -1
  525. package/agent-docs/recipes/add-page.sections/scaffold-a-new-guide.md +1 -1
  526. package/agent-docs/recipes/audit-docs.md +4 -4
  527. package/agent-docs/recipes/build-docs.md +2 -2
  528. package/agent-docs/recipes/preview-hybrid-search.md +5 -5
  529. package/agent-docs/recipes/preview-page.md +2 -2
  530. package/agent-docs/recipes/queue-email.md +3 -3
  531. package/agent-docs/recipes/refresh-agent-docs.md +4 -4
  532. package/agent-docs/recipes/send-welcome-email.md +15 -15
  533. package/agent-docs/reference/agent-skills.md +7 -7
  534. package/agent-docs/search-and-chat.md +4 -4
  535. package/agent-docs/search-index.json +1 -1
  536. package/agent-docs/start.md +5 -5
  537. package/agent-docs/start.sections/add-the-page-to-navigation.md +3 -3
  538. package/agent-docs/start.sections/build-and-check-both-outputs.md +3 -3
  539. package/agent-docs/start.sections/build-this-site.md +2 -2
  540. package/agent-docs/start.sections/check-writing-style.md +2 -2
  541. package/agent-docs/start.sections/create-a-page.md +2 -2
  542. package/agent-docs/start.sections/make-it-yours.md +2 -2
  543. package/agent-docs/start.sections/migrating-from-github-packages.md +2 -2
  544. package/agent-docs/start.sections/prerequisites.md +2 -2
  545. package/agent-docs/start.sections/related-reading.md +2 -2
  546. package/agent-docs/start.sections/start-your-own-project.md +3 -3
  547. package/agent-docs/status.md +14 -4
  548. package/agent-docs/styling/color-modes.md +2 -2
  549. package/agent-docs/styling/footer.md +2 -2
  550. package/agent-docs/styling/header.md +2 -2
  551. package/agent-docs/styling/layouts.md +3 -3
  552. package/agent-docs/styling/layouts.sections/build-a-landing-page.md +1 -1
  553. package/agent-docs/styling/layouts.sections/build-a-splash-page.md +1 -1
  554. package/agent-docs/styling/layouts.sections/control-navigation-tabs.md +2 -2
  555. package/agent-docs/styling/layouts.sections/customize-the-hero.md +1 -1
  556. package/agent-docs/styling/layouts.sections/hero.md +1 -1
  557. package/agent-docs/styling/layouts.sections/hide-the-table-of-contents-or-give-content-more-room.md +1 -1
  558. package/agent-docs/styling/layouts.sections/html-markdown-and-agents.md +2 -2
  559. package/agent-docs/styling/layouts.sections/related-reading.md +1 -1
  560. package/agent-docs/styling/palettes.md +3 -3
  561. package/agent-docs/styling/share-images.md +3 -3
  562. package/agent-docs/styling/themes.md +2 -2
  563. package/agent-docs/styling/try.md +2 -2
  564. package/agent-docs/what-is-shoalrun.md +7 -3
  565. package/assets/ask-widget.js +20 -6
  566. package/assets/navigation.js +5 -0
  567. package/dist/ai-directory.d.ts +1 -0
  568. package/dist/ai-directory.js +12 -0
  569. package/dist/answer-cards.js +1 -1
  570. package/dist/api-materialize.d.ts +2 -1
  571. package/dist/api-materialize.js +21 -9
  572. package/dist/api-publication-plan.d.ts +2 -0
  573. package/dist/api-publication-plan.js +23 -7
  574. package/dist/api-publication-review.js +4 -3
  575. package/dist/api-selection.d.ts +5 -2
  576. package/dist/api-selection.js +18 -11
  577. package/dist/artifact-bundle.js +9 -6
  578. package/dist/ask-function.d.ts +4 -18
  579. package/dist/ask-function.js +12 -71
  580. package/dist/ask-runtime.d.ts +46 -0
  581. package/dist/ask-runtime.js +101 -0
  582. package/dist/ask-setup.d.ts +3 -42
  583. package/dist/ask-setup.js +5 -93
  584. package/dist/authored-change.js +2 -1
  585. package/dist/authoring-project.js +1 -1
  586. package/dist/cards.js +2 -1
  587. package/dist/cli-discovery.d.ts +2 -2
  588. package/dist/cli-discovery.js +9 -4
  589. package/dist/cli.js +48 -23
  590. package/dist/compiler-config.d.ts +17 -0
  591. package/dist/compiler-config.js +43 -2
  592. package/dist/compiler.d.ts +21 -0
  593. package/dist/compiler.js +16 -12
  594. package/dist/component-transform.d.ts +2 -4
  595. package/dist/component-transform.js +20 -7
  596. package/dist/config.d.ts +1 -0
  597. package/dist/config.js +2 -1
  598. package/dist/content-delivery-contract.d.ts +2 -1
  599. package/dist/content-delivery-validation.d.ts +2 -2
  600. package/dist/content-delivery-validation.js +6 -4
  601. package/dist/content-export-command.d.ts +1 -1
  602. package/dist/content-export-command.js +4 -4
  603. package/dist/content-export-comparison.js +6 -5
  604. package/dist/content-export-config.js +3 -1
  605. package/dist/content-export.js +9 -8
  606. package/dist/content-rest-client.js +4 -2
  607. package/dist/content-rest-contract.d.ts +2 -2
  608. package/dist/content-rest-server.js +11 -6
  609. package/dist/content-source.d.ts +13 -0
  610. package/dist/content-source.js +5 -2
  611. package/dist/content-workspace.d.ts +12 -0
  612. package/dist/content-workspace.js +2 -1
  613. package/dist/content.js +3 -2
  614. package/dist/cookbook-chooser.js +2 -1
  615. package/dist/deployment-profile.d.ts +2 -1
  616. package/dist/deployment-profile.js +38 -8
  617. package/dist/dev.d.ts +3 -1
  618. package/dist/dev.js +99 -12
  619. package/dist/docs-author.js +2 -1
  620. package/dist/docs-command.js +2 -2
  621. package/dist/docs-eval.d.ts +1 -0
  622. package/dist/docs-eval.js +2 -2
  623. package/dist/docs-mcp.d.ts +1 -0
  624. package/dist/docs-mcp.js +10 -5
  625. package/dist/docs-tool.d.ts +4 -10
  626. package/dist/document-sync.d.ts +1 -0
  627. package/dist/document-sync.js +2 -2
  628. package/dist/documentation-core.d.ts +29 -10
  629. package/dist/documentation-core.js +38 -4
  630. package/dist/embeddings.d.ts +1 -1
  631. package/dist/embeddings.js +1 -1
  632. package/dist/freshness.js +2 -2
  633. package/dist/frontmatter.js +13 -7
  634. package/dist/function-package.js +5 -0
  635. package/dist/function-runtime.d.ts +24 -0
  636. package/dist/function-runtime.js +45 -0
  637. package/dist/index-build.d.ts +2 -2
  638. package/dist/index-build.js +5 -13
  639. package/dist/ingredient-draft.js +20 -10
  640. package/dist/mcp-analytics.d.ts +1 -0
  641. package/dist/mcp-artifacts.js +13 -4
  642. package/dist/mcp-config.d.ts +1 -0
  643. package/dist/mcp-config.js +3 -1
  644. package/dist/mcp-http.js +1 -1
  645. package/dist/page-materialization.d.ts +3 -4
  646. package/dist/page-materialization.js +15 -8
  647. package/dist/page-renderer.d.ts +6 -0
  648. package/dist/page-renderer.js +16 -5
  649. package/dist/project-navigation.js +2 -1
  650. package/dist/publication-identity.d.ts +12 -0
  651. package/dist/publication-identity.js +17 -0
  652. package/dist/publication-manifest.d.ts +24 -1
  653. package/dist/publication-manifest.js +14 -6
  654. package/dist/publication-plan.js +21 -9
  655. package/dist/publication-render.js +24 -8
  656. package/dist/recipe-draft.js +9 -6
  657. package/dist/retrieval-runtime.d.ts +5 -0
  658. package/dist/retrieval-runtime.js +21 -0
  659. package/dist/scaffold.d.ts +7 -4
  660. package/dist/scaffold.js +16 -16
  661. package/dist/search-function.d.ts +2 -0
  662. package/dist/search-function.js +30 -0
  663. package/dist/search-handler.js +2 -2
  664. package/dist/search-identifier-core.d.ts +4 -0
  665. package/dist/search-identifier-core.js +30 -0
  666. package/dist/search-identifier.d.ts +3 -3
  667. package/dist/search-identifier.js +7 -30
  668. package/dist/search-literal.js +1 -1
  669. package/dist/search-query.d.ts +4 -10
  670. package/dist/search-query.js +10 -9
  671. package/dist/search-results.js +1 -1
  672. package/dist/search-snippet.d.ts +1 -1
  673. package/dist/search-snippet.js +2 -14
  674. package/dist/search-text.d.ts +1 -0
  675. package/dist/search-text.js +14 -0
  676. package/dist/server.d.ts +8 -0
  677. package/dist/server.js +14 -3
  678. package/dist/subject-deprecation.js +2 -1
  679. package/dist/vercel-function.js +11 -3
  680. package/example-configs/products/README.md +37 -0
  681. package/example-configs/products/content/operations.mdx +50 -0
  682. package/example-configs/products/content/payments-v2.mdx +30 -0
  683. package/example-configs/products/content/payments-v3.mdx +38 -0
  684. package/example-configs/products/content/priority-settlement.mdx +23 -0
  685. package/example-configs/products/content/reporting-v1.mdx +36 -0
  686. package/example-configs/products/content/scheduled-exports.mdx +23 -0
  687. package/example-configs/products/docs.config.yaml +56 -0
  688. package/example-configs/products/profiles/all-releases.yaml +9 -0
  689. package/example-configs/products/profiles/customer-a.yaml +13 -0
  690. package/example-configs/products/profiles/customer-b.yaml +13 -0
  691. package/example-configs/products/skus.yaml +11 -0
  692. package/examples/content-delivery/preview.mjs +1 -1
  693. package/package.json +1 -1
  694. package/schemas/content-export.schema.json +41 -3
  695. package/schemas/content-rest.openapi.json +184 -37
  696. package/skills/shoalrun-author/SKILL.md +6 -2
  697. package/skills/shoalrun-author/references/customer-editions.md +34 -4
  698. package/skills/shoalrun-author/references/publications.md +60 -0
  699. package/skills/shoalrun-recipes/SKILL.md +2 -0
  700. package/skills/shoalrun-setup/SKILL.md +3 -1
  701. package/styles/header.css +3 -0
  702. package/styles/site.css +3 -0
  703. package/agent-docs/publish/content-export.sections/export-selected-pages.md +0 -116
package/dist/docs-mcp.js CHANGED
@@ -3,20 +3,20 @@ import { attemptAnalytics } from './mcp-analytics.js';
3
3
  import { McpServer } from '@modelcontextprotocol/server';
4
4
  import { serveStdio } from '@modelcontextprotocol/server/stdio';
5
5
  import * as z from 'zod/v4';
6
- import { bundledDocumentation, DocumentationError, documentationFailure, getDocumentationOutline, getDocumentationSection, getDocumentationPage, searchDocumentation } from './documentation-core.js';
6
+ import { bundledDocumentation, DocumentationError, documentationFailure, getDocumentationOutline, getDocumentationSection, getDocumentationPage, listDocumentationPublications, searchDocumentation } from './documentation-core.js';
7
7
  export function createDocsMcpServer(directory = bundledDocumentation, publication, analytics, discardAnalyticsArguments = false) {
8
8
  const server = new McpServer({ name: 'shoalrun-docs', version: '0.0.0' }, { maxToolInputElements: 1024 });
9
9
  const scope = (filters) => {
10
10
  if (!publication)
11
11
  return filters;
12
- for (const key of ['channel', 'version', 'language'])
12
+ for (const key of ['product', 'channel', 'version', 'language'])
13
13
  if (filters[key] !== undefined && filters[key] !== publication[key])
14
14
  throw new DocumentationError('invalid_input', 'This MCP endpoint serves a different publication');
15
15
  return { ...filters, ...publication };
16
16
  };
17
17
  const coordinate = (key) => z.string().optional().describe(publication ? `This endpoint serves ${key}=${publication[key]}; omit this argument or pass that exact value.` : `Select the documentation ${key}.`);
18
18
  const options = {
19
- channel: coordinate('channel'), version: coordinate('version'), language: coordinate('language'),
19
+ product: coordinate('product'), channel: coordinate('channel'), version: coordinate('version'), language: coordinate('language'),
20
20
  maxTokens: z.number().int().min(256).max(100_000).default(4096).describe('Maximum serialized result tokens, counted with cl100k_base, including metadata.'),
21
21
  };
22
22
  // A client may cache the instrumented schema after withdrawing consent.
@@ -57,13 +57,18 @@ export function createDocsMcpServer(directory = bundledDocumentation, publicatio
57
57
  await attemptAnalytics(() => analytics.capture({ name: 'mcp_tool_call', ...(analytics.clientMetadata ? mcpClientMetadata(context, server.server.getClientVersion()) : {}), tool, durationMs: Math.max(0, performance.now() - start), isError, ...(errorCode ? { errorCode } : {}), ...(pageId ? { pageId } : {}), ...(sectionId ? { sectionId } : {}), buildId: analytics.buildId, publication: { ...publication } }));
58
58
  }
59
59
  };
60
+ server.registerTool('get_publications', {
61
+ description: 'Discover available product/channel/version/language coordinates before searching. Returns one compact page and concise product defaults; follow nextOffset for more. Products have independent versions. Preserve the selected product and publication coordinates in subsequent search and read calls. This endpoint lists only its published scope.',
62
+ inputSchema: schema(z.object({ ...options, maxTokens: z.number().int().min(256).max(100_000).default(2048), limit: z.number().int().min(1).max(100).default(20), offset: z.number().int().min(0).default(0) }).strict()),
63
+ annotations,
64
+ }, (filters, context) => respond('get_publications', context, () => listDocumentationPublications(directory, { ...scope(filters), ...(publication ? { publication } : {}) })));
60
65
  server.registerTool('search_docs', {
61
- description: 'Search the documentation by keyword. Partial fallback favors field relevance among results within one meaningful term of the best coverage (at least two matched). Complete lexical matches normally precede partial fallback; stronger near-complete matches can outrank body-only complete matches (matchMode: mixed). Search covers titles, summaries, headings, and bounded article text. For each chosen result, call read.tool with read.arguments exactly. Section recommendations require an author declaration of self-contained content. The result markdownUrl fetches the recommended section or full page; pageMarkdownUrl is always the full-page fallback. Do not guess a section ID or request an outline first.',
66
+ description: 'Search the documentation by keyword. Use get_publications to discover product/version scope when unknown. Partial fallback favors field relevance among results within one meaningful term of the best coverage (at least two matched). Complete lexical matches normally precede partial fallback; stronger near-complete matches can outrank body-only complete matches (matchMode: mixed). Search covers titles, summaries, headings, and bounded article text. For each chosen result, call read.tool with read.arguments exactly, retaining product and all publication coordinates. Section recommendations require an author declaration of self-contained content. The result markdownUrl fetches the recommended section or full page; pageMarkdownUrl is always the full-page fallback. Do not guess a section ID or request an outline first.',
62
67
  inputSchema: schema(z.object({ query: z.string(), limit: z.number().int().min(1).max(100).default(8), ...options }).strict()),
63
68
  annotations,
64
69
  }, ({ query, ...filters }, context) => respond('search_docs', context, () => searchDocumentation(directory, query, scope(filters))));
65
70
  server.registerTool('get_page', {
66
- description: 'Read a published Markdown page by the stable document ID returned from search_docs. Includes all reader-marked sections. Check budget.truncated; increase maxTokens if needed.',
71
+ description: 'Read a published Markdown page by the stable document ID returned from search_docs. Retain its product/channel/version/language coordinates; IDs can repeat across products. Includes all reader-marked sections. Check budget.truncated; increase maxTokens if needed.',
67
72
  inputSchema: schema(z.object({ id: z.string(), ...options }).strict()),
68
73
  annotations,
69
74
  }, ({ id, ...filters }, context) => respond('get_page', context, () => getDocumentationPage(directory, id, scope(filters))));
@@ -20,6 +20,7 @@ export declare function searchShoalrunDocs(query: string): Promise<({
20
20
  channel: string;
21
21
  version: string;
22
22
  language: string;
23
+ product?: string | undefined;
23
24
  section?: string | undefined;
24
25
  id: string;
25
26
  };
@@ -27,11 +28,7 @@ export declare function searchShoalrunDocs(query: string): Promise<({
27
28
  }[];
28
29
  status: string;
29
30
  query: string;
30
- publication: {
31
- channel: string;
32
- version: string;
33
- language: string;
34
- };
31
+ publication: import("./publication-identity.js").PublicationCoordinate;
35
32
  total: number;
36
33
  matchMode?: undefined;
37
34
  } | {
@@ -56,6 +53,7 @@ export declare function searchShoalrunDocs(query: string): Promise<({
56
53
  channel: string;
57
54
  version: string;
58
55
  language: string;
56
+ product?: string | undefined;
59
57
  section?: string | undefined;
60
58
  id: string;
61
59
  };
@@ -63,11 +61,7 @@ export declare function searchShoalrunDocs(query: string): Promise<({
63
61
  }[];
64
62
  status: string;
65
63
  query: string;
66
- publication: {
67
- channel: string;
68
- version: string;
69
- language: string;
70
- };
64
+ publication: import("./publication-identity.js").PublicationCoordinate;
71
65
  total: number;
72
66
  matchMode: string;
73
67
  }) & {
@@ -2,6 +2,7 @@ export declare function canonicalJson(value: unknown): string;
2
2
  export type SyncDocument = {
3
3
  id: string;
4
4
  variant: {
5
+ product?: string;
5
6
  channel: string;
6
7
  version: string;
7
8
  language: string;
@@ -5,7 +5,7 @@ export function canonicalJson(value) {
5
5
  return JSON.stringify(value, (_key, item) => item && typeof item === 'object' && !Array.isArray(item)
6
6
  ? Object.fromEntries(Object.keys(item).sort().map(key => [key, item[key]])) : item);
7
7
  }
8
- const key = (doc) => JSON.stringify([doc.id, doc.variant.channel, doc.variant.version, doc.variant.language]);
8
+ const key = (doc) => JSON.stringify([doc.id, doc.variant.channel, doc.variant.version, doc.variant.language, ...(doc.variant.product === undefined ? [] : [doc.variant.product])]);
9
9
  export function documentSnapshot(manifest, buildId) {
10
10
  const { documents, dependencies, buildId: _buildId, ...metadata } = manifest;
11
11
  const records = documents.map(doc => ({ id: doc.id, variant: doc.variant, url: doc.url, markdownUrl: doc.markdownUrl,
@@ -32,7 +32,7 @@ export function parseDocumentSnapshot(value) {
32
32
  const seen = new Set();
33
33
  for (const doc of value.documents) {
34
34
  const variant = object(doc) && object(doc.variant) ? doc.variant : {};
35
- if (!object(doc) || typeof doc.id !== 'string' || !doc.id.trim() || !object(doc.variant) || ['channel', 'version', 'language'].some(field => typeof variant[field] !== 'string' || !variant[field].trim()) || !route(doc.url) || !route(doc.markdownUrl) || !doc.markdownUrl.endsWith('.md') || !hex(doc.digest) || !hex(doc.contentDigest) || !hex(doc.recordDigest))
35
+ if (!object(doc) || typeof doc.id !== 'string' || !doc.id.trim() || !object(doc.variant) || (variant.product !== undefined && (typeof variant.product !== 'string' || !variant.product.trim())) || ['channel', 'version', 'language'].some(field => typeof variant[field] !== 'string' || !variant[field].trim()) || !route(doc.url) || !route(doc.markdownUrl) || !doc.markdownUrl.endsWith('.md') || !hex(doc.digest) || !hex(doc.contentDigest) || !hex(doc.recordDigest))
36
36
  throw new Error('Invalid document sync record');
37
37
  const identity = key(doc);
38
38
  if (seen.has(identity))
@@ -1,4 +1,5 @@
1
1
  import { type SearchOptions } from './search-query.js';
2
+ import { type PublicationCoordinate } from './publication-identity.js';
2
3
  export declare const bundledDocumentation: string;
3
4
  export type DocumentationErrorCode = 'invalid_input' | 'unknown_page' | 'unknown_section' | 'missing_index' | 'internal_error';
4
5
  export declare class DocumentationError extends Error {
@@ -16,6 +17,29 @@ export type DocumentationOptions = SearchOptions & {
16
17
  maxTokens?: number;
17
18
  };
18
19
  export declare const documentationTokens: (value: string) => number;
20
+ /** Compact discovery of published coordinates, without returning page inventories. */
21
+ export declare function listDocumentationPublications(directory: string, options?: DocumentationOptions & {
22
+ offset?: number;
23
+ publication?: PublicationCoordinate;
24
+ }): Promise<{
25
+ nextOffset?: number | undefined;
26
+ products?: {
27
+ defaultVersion?: any;
28
+ label?: any;
29
+ id: string;
30
+ }[] | undefined;
31
+ status: "ok";
32
+ total: number;
33
+ offset: number;
34
+ publications: PublicationCoordinate[];
35
+ } & {
36
+ budget: {
37
+ maxTokens: number;
38
+ encoding: string;
39
+ tokens: number;
40
+ truncated: boolean;
41
+ };
42
+ }>;
19
43
  export declare function searchDocumentation(directory: string, query: string, options?: DocumentationOptions): Promise<({
20
44
  results: never[] | {
21
45
  snippet: string;
@@ -38,6 +62,7 @@ export declare function searchDocumentation(directory: string, query: string, op
38
62
  channel: string;
39
63
  version: string;
40
64
  language: string;
65
+ product?: string | undefined;
41
66
  section?: string | undefined;
42
67
  id: string;
43
68
  };
@@ -45,11 +70,7 @@ export declare function searchDocumentation(directory: string, query: string, op
45
70
  }[];
46
71
  status: string;
47
72
  query: string;
48
- publication: {
49
- channel: string;
50
- version: string;
51
- language: string;
52
- };
73
+ publication: PublicationCoordinate;
53
74
  total: number;
54
75
  matchMode?: undefined;
55
76
  } | {
@@ -74,6 +95,7 @@ export declare function searchDocumentation(directory: string, query: string, op
74
95
  channel: string;
75
96
  version: string;
76
97
  language: string;
98
+ product?: string | undefined;
77
99
  section?: string | undefined;
78
100
  id: string;
79
101
  };
@@ -81,11 +103,7 @@ export declare function searchDocumentation(directory: string, query: string, op
81
103
  }[];
82
104
  status: string;
83
105
  query: string;
84
- publication: {
85
- channel: string;
86
- version: string;
87
- language: string;
88
- };
106
+ publication: PublicationCoordinate;
89
107
  total: number;
90
108
  matchMode: string;
91
109
  }) & {
@@ -104,6 +122,7 @@ export declare function getDocumentationPage(directory: string, id: string, opti
104
122
  url: string;
105
123
  markdownUrl: string;
106
124
  publication: {
125
+ product?: string;
107
126
  channel: string;
108
127
  version: string;
109
128
  language: string;
@@ -4,6 +4,7 @@ import path from 'node:path';
4
4
  import { fileURLToPath } from 'node:url';
5
5
  import { markdownTokens } from './markdown-size.js';
6
6
  import { queryBuiltSite } from './search-query.js';
7
+ import { publicationKey, samePublication } from './publication-identity.js';
7
8
  export const bundledDocumentation = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../agent-docs');
8
9
  export class DocumentationError extends Error {
9
10
  code;
@@ -18,7 +19,7 @@ function validate(options) {
18
19
  const maxTokens = options.maxTokens ?? 4096;
19
20
  if (!Number.isSafeInteger(maxTokens) || maxTokens < 256 || maxTokens > 100_000)
20
21
  throw new DocumentationError('invalid_input', 'maxTokens must be an integer from 256 to 100000');
21
- for (const key of ['channel', 'version', 'language'])
22
+ for (const key of ['product', 'channel', 'version', 'language'])
22
23
  if (options[key] !== undefined && (typeof options[key] !== 'string' || !options[key]?.trim() || options[key].length > 128))
23
24
  throw new DocumentationError('invalid_input', `${key} must be nonempty text of at most 128 characters`);
24
25
  return maxTokens;
@@ -45,6 +46,39 @@ async function loadJson(directory, name) {
45
46
  throw new DocumentationError('internal_error', `Cannot read valid ${name}. Rebuild the documentation.`);
46
47
  }
47
48
  }
49
+ /** Compact discovery of published coordinates, without returning page inventories. */
50
+ export async function listDocumentationPublications(directory, options = {}) {
51
+ const maxTokens = validate({ ...options, maxTokens: options.maxTokens ?? 2048 });
52
+ const limit = options.limit ?? 20;
53
+ const offset = options.offset ?? 0;
54
+ if (!Number.isSafeInteger(limit) || limit < 1 || limit > 100 || !Number.isSafeInteger(offset) || offset < 0)
55
+ throw new DocumentationError('invalid_input', 'limit must be from 1 to 100 and offset must be a nonnegative safe integer');
56
+ const manifest = await loadJson(directory, 'documents.json');
57
+ const source = manifest?.publications?.enabled ?? manifest?.documents?.map((doc) => doc.variant);
58
+ const valid = (item) => item && typeof item === 'object' && !Array.isArray(item) && ['channel', 'version', 'language'].every(key => typeof item[key] === 'string' && item[key].length > 0 && item[key].length <= 128) && (item.product === undefined || typeof item.product === 'string' && item.product.length > 0 && item.product.length <= 128);
59
+ if (manifest?.schemaVersion !== 1 || !Array.isArray(source) || source.some(item => !valid(item)))
60
+ throw new DocumentationError('internal_error', 'Invalid publication metadata. Rebuild the documentation.');
61
+ const coordinates = source.map((item) => ({ channel: item.channel, version: item.version, language: item.language, ...(item.product === undefined ? {} : { product: item.product }) }));
62
+ const available = [...new Map(coordinates.map((item) => [publicationKey(item), item])).values()]
63
+ .filter(item => (!options.publication || samePublication(item, options.publication)) && ['product', 'channel', 'version', 'language'].every(key => !options[key] || item[key] === options[key]))
64
+ .sort((a, b) => publicationKey(a).localeCompare(publicationKey(b)));
65
+ const total = available.length;
66
+ let publications = available.slice(offset, offset + limit);
67
+ while (true) {
68
+ const products = [...new Set(publications.flatMap(item => item.product === undefined ? [] : [item.product]))].map(id => {
69
+ const catalog = manifest.publications?.products?.[id];
70
+ const defaultVersion = typeof catalog?.defaultVersion === 'string' && available.some(item => item.product === id && item.version === catalog.defaultVersion) ? catalog.defaultVersion : undefined;
71
+ return { id, ...(typeof catalog?.label === 'string' ? { label: catalog.label.slice(0, 160) } : {}), ...(defaultVersion === undefined ? {} : { defaultVersion }) };
72
+ });
73
+ const nextOffset = offset + publications.length < total ? offset + publications.length : undefined;
74
+ const result = budget({ status: 'ok', total, offset, publications, ...(products.length ? { products } : {}), ...(nextOffset === undefined ? {} : { nextOffset }) }, maxTokens, nextOffset !== undefined);
75
+ if (result.fits)
76
+ return result.result;
77
+ if (!publications.length || publications.length === 1)
78
+ throw new DocumentationError('invalid_input', 'maxTokens is too small for publication metadata. Increase the budget.');
79
+ publications = publications.slice(0, -1);
80
+ }
81
+ }
48
82
  export async function searchDocumentation(directory, query, options = {}) {
49
83
  const maxTokens = validate(options);
50
84
  if (typeof query !== 'string' || !query.trim() || query.length > 512)
@@ -76,14 +110,14 @@ async function selectDocument(directory, id, options) {
76
110
  if (typeof id !== 'string' || !id.trim() || id.length > 256)
77
111
  throw new DocumentationError('invalid_input', 'id must be nonempty text of at most 256 characters');
78
112
  const manifest = await loadJson(directory, 'documents.json');
79
- if (manifest?.schemaVersion !== 1 || !Array.isArray(manifest.documents) || manifest.documents.some((doc) => !doc || typeof doc.id !== 'string' || typeof doc.title !== 'string' || typeof doc.url !== 'string' || typeof doc.markdownUrl !== 'string' || !doc.variant || ['channel', 'version', 'language'].some(key => typeof doc.variant[key] !== 'string')))
113
+ if (manifest?.schemaVersion !== 1 || !Array.isArray(manifest.documents) || manifest.documents.some((doc) => !doc || typeof doc.id !== 'string' || typeof doc.title !== 'string' || typeof doc.url !== 'string' || typeof doc.markdownUrl !== 'string' || !doc.variant || (doc.variant.product !== undefined && (typeof doc.variant.product !== 'string' || !doc.variant.product)) || ['channel', 'version', 'language'].some(key => typeof doc.variant[key] !== 'string')))
80
114
  throw new DocumentationError('internal_error', 'Invalid documents.json. Rebuild the documentation.');
81
115
  const matching = manifest.documents.filter((doc) => doc.id === id);
82
116
  if (!matching.length)
83
117
  throw new DocumentationError('unknown_page', `No document with ID ${id}; search the documentation first.`);
84
- const selected = matching.filter((doc) => ['channel', 'version', 'language'].every(key => !options[key] || doc.variant[key] === options[key]));
118
+ const selected = matching.filter((doc) => ['product', 'channel', 'version', 'language'].every(key => !options[key] || doc.variant[key] === options[key]));
85
119
  if (selected.length !== 1)
86
- throw new DocumentationError('invalid_input', selected.length ? 'Page has multiple publications; select channel, version, and language.' : 'Page does not match the selected publication.');
120
+ throw new DocumentationError('invalid_input', selected.length ? 'Page has multiple publications; select product where applicable, channel, version, and language.' : 'Page does not match the selected publication.');
87
121
  return selected[0];
88
122
  }
89
123
  async function readMarkdown(directory, markdownUrl) {
@@ -1,4 +1,4 @@
1
- import { type Chunk, type ChunkIndex } from './index-build.js';
1
+ import type { Chunk, ChunkIndex } from './index-build.js';
2
2
  import { type Transport } from './provider-http.js';
3
3
  export type EmbedInputType = 'document' | 'query';
4
4
  export type EmbeddingProvider = {
@@ -1,7 +1,7 @@
1
1
  import { readFile, realpath, writeFile } from 'node:fs/promises';
2
2
  import { createHash } from 'node:crypto';
3
3
  import path from 'node:path';
4
- import { aiDirectory } from './index-build.js';
4
+ import { aiDirectory } from './ai-directory.js';
5
5
  import { postJson, throwIfCancelled } from './provider-http.js';
6
6
  const hash = (value) => createHash('sha256').update(JSON.stringify(value)).digest('hex');
7
7
  function normalize(vector) {
package/dist/freshness.js CHANGED
@@ -10,7 +10,7 @@ function stable(value) {
10
10
  return value;
11
11
  }
12
12
  export function contentDigest(doc, htmlTree, markdownTree) {
13
- const fields = ['id', 'title', 'summary', 'description', 'type', 'slug', 'date', 'releaseVersion', 'subjectLifecycle', 'audiences', 'readerFilters', 'product', 'area', 'subarea', 'operations', 'displayText'];
13
+ const fields = ['id', 'title', 'summary', 'description', 'type', 'slug', 'date', 'releaseVersion', 'availability', 'subjectLifecycle', 'audiences', 'readerFilters', 'product', 'area', 'subarea', 'operations', 'displayText'];
14
14
  return createHash('sha256').update(JSON.stringify(stable({ metadata: Object.fromEntries(fields.map(key => [key, doc.frontmatter[key]])), html: htmlTree, markdown: markdownTree }))).digest('hex');
15
15
  }
16
16
  export async function loadFreshness(value, base, today = new Date().toISOString().slice(0, 10)) {
@@ -40,7 +40,7 @@ export async function loadFreshness(value, base, today = new Date().toISOString(
40
40
  const current = {};
41
41
  return {
42
42
  resolve(doc, digest, fallback) {
43
- const key = JSON.stringify([doc.frontmatter.id, doc.variant.channel, doc.variant.version, doc.variant.language]);
43
+ const key = JSON.stringify([doc.frontmatter.id, doc.variant.channel, doc.variant.version, doc.variant.language, ...(doc.variant.product === undefined ? [] : [doc.variant.product])]);
44
44
  const previous = history.documents[key];
45
45
  const updated = previous ? previous.contentDigest === digest ? previous.updated : today : doc.frontmatter.updated ?? fallback ?? today;
46
46
  current[key] = { contentDigest: digest, updated };
@@ -3,7 +3,7 @@ import { validateSubjectDeprecation } from './subject-deprecation.js';
3
3
  import { validateCardMetadata } from './cards.js';
4
4
  import { resolveTaxonomy, validateTaxonomy, taxonomySchema } from './taxonomy.js';
5
5
  import { validateStandaloneSectionDeclarations } from './section-identity.js';
6
- export const nativePublicFields = new Set(['id', 'title', 'type', 'summary', 'description', 'language', 'locale', 'date', 'updated', 'verified', 'releaseVersion', 'product', 'area', 'subarea', 'operations', 'relatedApiReferences', 'audiences', 'readerFilters', 'tags', 'subjectLifecycle', 'subjectDeprecation', 'change', 'lifecycle']);
6
+ export const nativePublicFields = new Set(['id', 'title', 'type', 'summary', 'description', 'language', 'locale', 'date', 'updated', 'verified', 'releaseVersion', 'availability', 'product', 'area', 'subarea', 'operations', 'relatedApiReferences', 'audiences', 'readerFilters', 'tags', 'subjectLifecycle', 'subjectDeprecation', 'change', 'lifecycle']);
7
7
  export const protectedMetadataRoots = new Set(['shared', 'requires', 'standaloneSections', 'access', 'seo', 'markdownMetadata', 'variables', 'tocDepth', 'layout', 'showNavigationTabs', 'showVerified', 'image', 'private', 'internal', 'card', 'displayText', 'publications']);
8
8
  const fieldTypes = new Set(['string', 'number', 'integer', 'boolean', 'object', 'array']);
9
9
  const safePath = (value) => /^[A-Za-z_][A-Za-z0-9_-]*(?:\.[A-Za-z_][A-Za-z0-9_-]*)*$/.test(value);
@@ -33,7 +33,7 @@ export function frontmatterLayers(config = {}) {
33
33
  const layer = config[name] === undefined ? {} : config[name];
34
34
  if (!object(layer))
35
35
  throw new Error(`frontmatter.${name} must be a mapping`);
36
- for (const field of ['id', 'slug', 'shared', 'publications', 'standaloneSections', 'subjectDeprecation', 'change'])
36
+ for (const field of ['id', 'slug', 'shared', 'publications', 'standaloneSections', 'subjectDeprecation', 'change', 'availability'])
37
37
  if (Object.hasOwn(layer, field))
38
38
  throw new Error(`frontmatter.${name}.${field} must stay page-specific`);
39
39
  layers[name] = mergeMetadata({}, layer);
@@ -126,6 +126,11 @@ export function validateFrontmatter(frontmatter, config, file, source) {
126
126
  if (frontmatter.type === 'changelog-entry' &&
127
127
  (mode === 'date' && frontmatter.date === undefined || mode === 'version' && frontmatter.releaseVersion === undefined || mode === 'either' && frontmatter.date === undefined && frontmatter.releaseVersion === undefined))
128
128
  throw new Error(`${file}: changelog-entry pages need ${mode === 'either' ? 'date or releaseVersion' : mode === 'version' ? 'releaseVersion' : 'date'}`);
129
+ if (frontmatter.availability !== undefined) {
130
+ const value = frontmatter.availability;
131
+ if (!object(value) || !Object.keys(value).length || Object.keys(value).some(key => !['since', 'through'].includes(key)) || Object.values(value).some(label => typeof label !== 'string' || !label.trim()))
132
+ throw new Error(`${file}: availability must contain nonempty since and/or through version labels`);
133
+ }
129
134
  if (frontmatter.releaseVersion !== undefined && (typeof frontmatter.releaseVersion !== 'string' || !frontmatter.releaseVersion.trim()))
130
135
  throw new Error(`${file}: releaseVersion must be nonempty text`);
131
136
  for (const field of ['date', 'verified'])
@@ -151,10 +156,10 @@ export function validateFrontmatter(frontmatter, config, file, source) {
151
156
  }
152
157
  if (frontmatter.publications !== undefined) {
153
158
  const publications = frontmatter.publications;
154
- if (!Array.isArray(publications) || !publications.length || publications.some(item => !object(item) || Object.keys(item).some(key => !['channel', 'version'].includes(key)) || typeof item.channel !== 'string' || !item.channel.trim() || typeof item.version !== 'string' || !item.version.trim())) {
159
+ if (!Array.isArray(publications) || !publications.length || publications.some(item => !object(item) || Object.keys(item).some(key => !['product', 'channel', 'version'].includes(key)) || (item.product !== undefined && (typeof item.product !== 'string' || !item.product.trim())) || typeof item.channel !== 'string' || !item.channel.trim() || typeof item.version !== 'string' || !item.version.trim())) {
155
160
  throw new Error(`${file}: publications must list channel and version pairs`);
156
161
  }
157
- const keys = publications.map(item => `${item.channel}|${item.version}`);
162
+ const keys = publications.map(item => `${item.product ?? ''}|${item.channel}|${item.version}`);
158
163
  if (new Set(keys).size !== keys.length)
159
164
  throw new Error(`${file}: publications has duplicate channel/version pairs`);
160
165
  }
@@ -230,14 +235,15 @@ export function frontmatterSchema(config) {
230
235
  date: { type: 'string', format: 'date', description: 'Publication date in YYYY-MM-DD format; optional for release notes and one possible changelog identifier.' },
231
236
  updated: { type: 'string', description: 'Date of the last meaningful page update: YYYY-MM-DD or a timezone-qualified ISO timestamp. Used as sitemap lastmod.' },
232
237
  verified: { type: 'string', format: 'date', description: 'Date someone verified the technical claims; independent of content revision and never assigned by the build.' },
238
+ availability: { type: 'object', minProperties: 1, additionalProperties: false, properties: { since: { type: 'string', minLength: 1, pattern: '\\S' }, through: { type: 'string', minLength: 1, pattern: '\\S' } }, description: 'Inclusive feature availability labels shown beside page dates and retained in Markdown and the document manifest. Does not select or hide publications; labels are not compared or inferred.' },
233
239
  releaseVersion: { type: 'string', minLength: 1, description: 'Release label for a note or changelog entry; separate from the documentation publication version.' },
234
240
  slug: { type: 'string', description: 'Page URL path before channel, version, and language prefixes.' },
235
241
  channel: { type: 'string', description: 'Publication environment, such as sandbox or production; selects an enabled publication and API source.' },
236
242
  version: { type: 'string', description: 'API or documentation edition, such as v1; selects an enabled publication and API source.' },
237
- publications: { type: 'array', minItems: 1, items: { type: 'object', properties: { channel: { type: 'string' }, version: { type: 'string' } }, required: ['channel', 'version'], additionalProperties: false }, description: 'Publish this one page file in each listed channel/version pair. Use instead of page-level channel and version; language stays the same.' },
243
+ publications: { type: 'array', minItems: 1, items: { type: 'object', properties: { product: { type: 'string', minLength: 1 }, channel: { type: 'string' }, version: { type: 'string' } }, required: ['channel', 'version'], additionalProperties: false }, description: 'Publish this one page file in each listed product/channel/version coordinate. Use instead of page-level channel and version; language stays the same.' },
238
244
  language: { type: 'string', description: 'Content language; uses frontmatter defaults/enforced values, then publications.defaults.language, then en.' },
239
245
  locale: { type: 'string', description: 'Formatting conventions used in the content; can inherit a project locale for the page language and can be overridden per page.' },
240
- product: { type: 'string', minLength: 1, description: 'Optional product category. Also selects the product reader facet when that facet is configured.' },
246
+ product: { type: 'string', minLength: 1, description: 'Product publication ID when publications.products is configured; otherwise an optional category and reader facet.' },
241
247
  area: { type: 'string', minLength: 1, description: 'Optional area category. Also selects the area reader facet when that facet is configured.' },
242
248
  subarea: { type: 'string', minLength: 1, description: 'Optional finer category. Also selects the subarea reader facet when that facet is configured.' },
243
249
  operations: { type: 'array', items: { type: 'string' }, description: 'Stable API operation IDs that connect this page to endpoint references and related documents.' },
@@ -326,7 +332,7 @@ export function frontmatterReference(config, sectionsOnly = false) {
326
332
  'Language is the content language and selects a publication. Locale describes formatting conventions in the content and does not select a publication. `frontmatter.locales` can set a project locale for each language; pages may override it.', '',
327
333
  '## Categorize, connect, and present the page', '',
328
334
  'By default, `product`, `area`, and `subarea` are optional, nonempty string categories. They can come from project defaults and appear in the document manifest and search index. A matching configured reader facet makes each category a page filter; without that facet it remains taxonomy only. `operations` links a guide or reference to stable API operation IDs. On a guide or how-to page, `relatedApiReferences` names API reference page IDs to add cross links in both directions within the same publication. Tags help document collections find the page. Card settings change its preview when another page links to it; they do not change the destination. `subjectLifecycle` displays the status of the documented API or feature; `lifecycle` is available for the document\'s editorial state. `tocDepth` limits the HTML page table of contents; use 0 to hide it. `layout` picks the HTML page layout: `docs`, `wide`, `landing`, or `splash`. `showNavigationTabs` overrides the navigation tab bar for this page; landing and splash pages hide it by default. `image` replaces the generated link-preview image. `date` and `releaseVersion` can identify a changelog entry under the project\'s `frontmatter.changelogIdentifier` rule.', '',
329
- ...table, ...nativeRows(['product', 'area', 'subarea', 'operations', 'relatedApiReferences', 'tags', 'date', 'releaseVersion', 'subjectLifecycle', 'subjectDeprecation', 'change', 'lifecycle', 'card', 'standaloneSections', 'tocDepth', 'layout', 'showNavigationTabs', 'showVerified', 'image']), '',
335
+ ...table, ...nativeRows(['availability', 'product', 'area', 'subarea', 'operations', 'relatedApiReferences', 'tags', 'date', 'releaseVersion', 'subjectLifecycle', 'subjectDeprecation', 'change', 'lifecycle', 'card', 'standaloneSections', 'tocDepth', 'layout', 'showNavigationTabs', 'showVerified', 'image']), '',
330
336
  'Projects can opt into built-in category enforcement with `frontmatter.taxonomy`. It declares areas and their allowed subareas, optional required fields, and optional explicit-field requirements for authored pages. Its `multiple` list permits arrays for selected category fields; otherwise each field allows one value. Defaults and enforced values still apply; generated API references use resolved categories. Definitions appear in the document manifest and constrain the generated frontmatter schema. Omit taxonomy or set it to false to preserve optional category behavior.', '',
331
337
  'With `profiles.requireClassification: true`, every public source page in the shared enabled publications needs an explicit `shared: true` or `requires` declaration before customer selection. Defaults do not count. Shared pages may contain feature-specific sections wrapped in `<ForFeature>`; unwrapped text remains shared.', '',
332
338
  '## Control output details', '',
@@ -55,4 +55,9 @@ export async function copyFunctionRuntime(dist, entry, target) {
55
55
  const done = new Set();
56
56
  for (const name of packages)
57
57
  await copyPackage(name, dist, target, done);
58
+ // Preserve the runtime author's license as well as the licenses retained in
59
+ // copied dependency packages. Custom runtime directories may have no parent license.
60
+ const license = path.join(dist, '..', 'LICENSE');
61
+ if (await stat(license).then(info => info.isFile(), () => false))
62
+ await cp(license, path.join(target, 'LICENSE.shoalrun'));
58
63
  }
@@ -0,0 +1,24 @@
1
+ import type { IncomingMessage, ServerResponse } from 'node:http';
2
+ export type FunctionRuntime = {
3
+ schemaVersion: 1;
4
+ settings: Record<string, unknown>;
5
+ variant?: {
6
+ product?: string;
7
+ channel: string;
8
+ version: string;
9
+ language: string;
10
+ };
11
+ hosts?: string[];
12
+ callerHeader?: string;
13
+ maxRequestsPerMinute?: number;
14
+ searchStore?: {
15
+ provider: 'upstash';
16
+ urlEnv: string;
17
+ tokenEnv: string;
18
+ };
19
+ };
20
+ export type AskFunction = (request: Request) => Promise<Response>;
21
+ export declare function allowedHosts(runtime: FunctionRuntime, env: NodeJS.ProcessEnv): string[];
22
+ export declare function nodeAdapter(load: () => Promise<AskFunction>, limits?: {
23
+ bodyBytes: number;
24
+ }): (req: IncomingMessage, res: ServerResponse) => Promise<void>;
@@ -0,0 +1,45 @@
1
+ export function allowedHosts(runtime, env) {
2
+ return [...new Set([...(runtime.hosts ?? []), env.VERCEL_URL, env.VERCEL_BRANCH_URL, env.VERCEL_PROJECT_PRODUCTION_URL, ...(env.SHOALRUN_ASK_HOSTS?.split(',') ?? [])].map(host => host?.trim().toLowerCase()).filter((host) => Boolean(host)))];
3
+ }
4
+ const failure = (status, message) => new Response(JSON.stringify({ error: message }), { status, headers: { 'Content-Type': 'application/json; charset=utf-8', 'Cache-Control': 'no-store' } });
5
+ // Vercel's Node runtime calls `(req, res)`. This turns that into a Web request and back. Starting up happens on the first request, and a
6
+ // failed start is tried again on the next one. The reader never sees why it failed; the reason goes to the function log.
7
+ export function nodeAdapter(load, limits = { bodyBytes: 32_768 }) {
8
+ let ready;
9
+ const write = async (res, response) => {
10
+ res.statusCode = response.status;
11
+ response.headers.forEach((value, name) => { if (name !== 'set-cookie')
12
+ res.setHeader(name, value); });
13
+ const cookies = response.headers.getSetCookie();
14
+ if (cookies.length)
15
+ res.setHeader('set-cookie', cookies);
16
+ res.end(Buffer.from(await response.arrayBuffer()));
17
+ };
18
+ return async (req, res) => {
19
+ try {
20
+ const handler = await (ready ??= load().catch(error => { ready = undefined; throw error; }));
21
+ const chunks = [];
22
+ let size = 0;
23
+ for await (const chunk of req) {
24
+ size += chunk.length;
25
+ if (size > limits.bodyBytes) {
26
+ await write(res, failure(413, 'The request is too large.'));
27
+ return;
28
+ }
29
+ chunks.push(chunk);
30
+ }
31
+ const headers = new Headers();
32
+ for (const [name, value] of Object.entries(req.headers))
33
+ for (const item of Array.isArray(value) ? value : value === undefined ? [] : [value])
34
+ headers.append(name, item);
35
+ const method = req.method ?? 'GET';
36
+ const request = new Request(`https://${req.headers.host ?? 'localhost'}${req.url ?? '/'}`, { method, headers, ...(method === 'GET' || method === 'HEAD' ? {} : { body: Buffer.concat(chunks) }) });
37
+ await write(res, await handler(request));
38
+ }
39
+ catch (error) {
40
+ console.error(`The answer function failed: ${error.message}`);
41
+ if (!res.headersSent)
42
+ await write(res, failure(503, 'The chat is unavailable right now.'));
43
+ }
44
+ };
45
+ }
@@ -1,3 +1,4 @@
1
+ export { aiDirectory } from './ai-directory.js';
1
2
  import { type PreparedSearchPassage } from './search-snippet.js';
2
3
  export type Chunk = {
3
4
  id: string;
@@ -35,6 +36,7 @@ type ManifestDocument = {
35
36
  digest: string;
36
37
  readerFilters?: Record<string, string[]>;
37
38
  variant: {
39
+ product?: string;
38
40
  channel: string;
39
41
  version: string;
40
42
  language: string;
@@ -46,10 +48,8 @@ export declare function chunkMarkdown(markdown: string, document: ChunkSource, a
46
48
  id: string;
47
49
  title: string;
48
50
  }>, options?: ChunkOptions): Chunk[];
49
- export declare function aiDirectory(directory: string): Promise<string>;
50
51
  export declare function buildChunkIndex(directory: string, options?: ChunkOptions): Promise<{
51
52
  index: ChunkIndex;
52
53
  output: string;
53
54
  documents: number;
54
55
  }>;
55
- export {};
@@ -1,5 +1,8 @@
1
+ import { publicationKey } from './publication-identity.js';
2
+ import { aiDirectory } from './ai-directory.js';
3
+ export { aiDirectory } from './ai-directory.js';
1
4
  import { createHash } from 'node:crypto';
2
- import { mkdir, readFile, realpath, writeFile } from 'node:fs/promises';
5
+ import { readFile, realpath, writeFile } from 'node:fs/promises';
3
6
  import path from 'node:path';
4
7
  import { validateSearchSynonyms } from './search-synonyms.js';
5
8
  import { prepareSearchPassage } from './search-snippet.js';
@@ -187,16 +190,6 @@ async function readJson(file) {
187
190
  }
188
191
  // The directory that holds the passage and vector files. It is created on demand, and it must stay inside the site even if
189
192
  // `ai` is a symlink.
190
- export async function aiDirectory(directory) {
191
- const root = path.resolve(directory);
192
- const target = path.join(root, 'ai');
193
- await mkdir(target, { recursive: true });
194
- const real = await realpath(root);
195
- const inside = await realpath(target);
196
- if (inside !== real && !inside.startsWith(real + path.sep))
197
- throw new Error('The ai directory leaves the site directory');
198
- return target;
199
- }
200
193
  export async function buildChunkIndex(directory, options = {}) {
201
194
  const root = path.resolve(directory);
202
195
  const manifest = await readJson(path.join(root, 'documents.json'));
@@ -218,8 +211,7 @@ export async function buildChunkIndex(directory, options = {}) {
218
211
  if (!inside(await realpath(file)))
219
212
  throw new Error(`Markdown path for ${document.id} leaves the site directory`);
220
213
  const markdown = await readFile(file, 'utf8');
221
- const { channel, version, language } = document.variant;
222
- chunks.push(...chunkMarkdown(markdown, { ...document, variant: `${channel}|${version}|${language}` }, anchors.get(document.url), options));
214
+ chunks.push(...chunkMarkdown(markdown, { ...document, variant: publicationKey(document.variant) }, anchors.get(document.url), options));
223
215
  }
224
216
  // Generation identity includes publication membership, routes, reader marks,
225
217
  // and prepared search evidence. Embedding digests remain content-only.
@@ -1,3 +1,5 @@
1
+ import { samePublication } from './publication-identity.js';
2
+ import { resolvePublication } from './compiler-config.js';
1
3
  import { createHash } from 'node:crypto';
2
4
  import { mkdir, readFile, writeFile } from 'node:fs/promises';
3
5
  import path from 'node:path';
@@ -10,13 +12,15 @@ const object = (value) => !!value && typeof value === 'object' && !Array.isArray
10
12
  const digest = (value) => createHash('sha256').update(value).digest('hex');
11
13
  function parseSpec(value) {
12
14
  const fields = ['schemaVersion', 'id', 'title', 'summary', 'slug', 'operation', 'requestExample'];
13
- if (!object(value) || value.schemaVersion !== 1 || Object.keys(value).some(key => ![...fields, 'workflow'].includes(key)))
15
+ if (!object(value) || value.schemaVersion !== 1 || Object.keys(value).some(key => ![...fields, 'workflow', 'publication'].includes(key)))
14
16
  throw new Error('Ingredient spec needs schemaVersion: 1 and only supported fields');
15
17
  for (const field of fields.slice(1))
16
18
  if (typeof value[field] !== 'string' || !value[field].trim())
17
19
  throw new Error(`Ingredient spec needs ${field}`);
18
20
  if (!/^\/[a-z0-9/-]+$/.test(value.slug) || value.slug.includes('//') || value.slug.split('/').includes('..'))
19
21
  throw new Error('Ingredient slug must be a lowercase absolute path');
22
+ if (value.publication !== undefined && (!object(value.publication) || Object.keys(value.publication).some(key => !['product', 'channel', 'version', 'language'].includes(key)) || Object.values(value.publication).some(item => typeof item !== 'string' || !item)))
23
+ throw new Error('Ingredient publication must declare product/channel/version/language strings');
20
24
  const workflow = ingredientWorkflow(value.workflow, 'Ingredient workflow');
21
25
  return { ...value, ...(workflow ? { workflow } : {}) };
22
26
  }
@@ -39,10 +43,20 @@ export async function renderIngredientDraft(configFile, specFile) {
39
43
  if (matching.length !== 1)
40
44
  throw new Error(`Ingredient operation ${spec.operation} must name one explicitly configured API operation`);
41
45
  const { apiId, api, operation } = matching[0];
42
- if (api.source?.kind !== 'file' || typeof api.source.path !== 'string')
43
- throw new Error(`Ingredient operation ${spec.operation} needs a local OpenAPI source in the default publication`);
44
- const origin = explain(loaded, `apis.${apiId}.source.path`).source.file;
45
- const source = path.resolve(path.dirname(origin), api.source.path);
46
+ const defaults = config.publications?.defaults ?? {};
47
+ const product = config.publications.products ? spec.publication?.product ?? api.product ?? defaults.product : undefined;
48
+ const publication = resolvePublication(config.publications, { ...defaults, ...spec.publication, ...(product ? { product, version: spec.publication?.version } : {}) }, defaultLanguage(config));
49
+ const publicationIndex = api.publications?.findIndex((item) => item.product === publication.product && item.channel === publication.channel && item.version === publication.version) ?? -1;
50
+ const defaultSourcePublication = api.source ? resolvePublication(config.publications, { ...defaults, ...(config.publications.products && api.product ? { product: api.product, version: undefined } : {}) }, defaultLanguage(config)) : undefined;
51
+ const binding = publicationIndex >= 0 ? api.publications[publicationIndex].source : defaultSourcePublication && publication.product === defaultSourcePublication.product && publication.channel === defaultSourcePublication.channel && publication.version === defaultSourcePublication.version ? api.source : undefined;
52
+ if (!config.publications.enabled?.some((item) => samePublication(resolvePublication(config.publications, item, defaultLanguage(config)), publication)))
53
+ throw new Error('Ingredient publication is not enabled');
54
+ if (publicationIndex < 0 && config.publications.products && publication.product !== (api.product ?? defaults.product))
55
+ throw new Error('Ingredient needs an OpenAPI source for its selected product');
56
+ if (binding?.kind !== 'file' || typeof binding.path !== 'string')
57
+ throw new Error(`Ingredient operation ${spec.operation} needs a local OpenAPI source in the selected publication`);
58
+ const origin = explain(loaded, publicationIndex >= 0 ? `apis.${apiId}.publications.${publicationIndex}.source.path` : `apis.${apiId}.source.path`).source.file;
59
+ const source = path.resolve(path.dirname(origin), binding.path);
46
60
  const reader = new ApiReader(root);
47
61
  const details = await reader.operation(source, operation.sourceOperationId, spec.operation);
48
62
  const sourceDigest = digest((await Promise.all([...reader.dependencies].sort().map(async (file) => `${path.relative(root, file)}\n${await readFile(file, 'utf8')}`))).join('\n'));
@@ -52,13 +66,9 @@ export async function renderIngredientDraft(configFile, specFile) {
52
66
  if (requests.length !== 1 || !requests[0].curl)
53
67
  throw new Error(`Request example ${spec.requestExample} needs one inline example with a generated cURL command`);
54
68
  const response = details.examples.find(example => example.location === 'response' && /^2\d\d$/.test(example.status ?? '') && example.value !== undefined);
55
- const defaults = config.publications?.defaults ?? {};
56
- if (!defaults.channel || !defaults.version)
57
- throw new Error('Ingredient draft needs a default channel and version');
58
- const language = defaults.language ?? defaultLanguage(config);
59
69
  const header = {
60
70
  id: spec.id, title: spec.title, summary: spec.summary, type: 'ingredient', slug: spec.slug,
61
- channel: defaults.channel, version: defaults.version, language,
71
+ ...publication,
62
72
  operations: [spec.operation], access: { policy: 'draft' }, ...(spec.workflow ? { workflow: spec.workflow } : {})
63
73
  };
64
74
  const reference = operation.reference ? `[${details.method.toUpperCase()} ${details.route}](doc:${operation.reference})` : `\`${details.method.toUpperCase()} ${details.route}\``;
@@ -10,6 +10,7 @@ export type McpAnalyticsEvent = McpClientMetadata & {
10
10
  sectionId?: string;
11
11
  buildId: string;
12
12
  publication: {
13
+ product?: string;
13
14
  channel: string;
14
15
  version: string;
15
16
  language: string;