blume 2.0.3 → 2.1.0
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.
- package/AGENTS.md +1 -0
- package/CHANGELOG.md +48 -0
- package/README.md +1 -1
- package/dist/cli/{chunk-1d7ve1dm.js → chunk-0gz36akr.js} +18 -2
- package/dist/cli/{chunk-1d7ve1dm.js.map → chunk-0gz36akr.js.map} +3 -3
- package/dist/cli/{chunk-2eytanqx.js → chunk-1n228xqb.js} +2 -2
- package/dist/cli/{chunk-yfyb25rh.js → chunk-2f3ndkpw.js} +24 -8
- package/dist/cli/chunk-2f3ndkpw.js.map +14 -0
- package/dist/cli/{chunk-r20tn01b.js → chunk-2f7n4qzt.js} +8 -2
- package/dist/cli/{chunk-r20tn01b.js.map → chunk-2f7n4qzt.js.map} +3 -3
- package/dist/cli/{chunk-35d4wj9f.js → chunk-2n4ps1b3.js} +7 -7
- package/dist/cli/{chunk-j85vccga.js → chunk-43zcf4gz.js} +97 -57
- package/dist/cli/{chunk-j85vccga.js.map → chunk-43zcf4gz.js.map} +6 -6
- package/dist/cli/{chunk-e04dxsz1.js → chunk-4ejxbzee.js} +1 -1
- package/dist/cli/{chunk-5m5nmvyq.js → chunk-4h8z9vv5.js} +233 -39
- package/dist/cli/chunk-4h8z9vv5.js.map +16 -0
- package/dist/cli/{chunk-5f86nr5m.js → chunk-5cg2rzgf.js} +18 -16
- package/dist/cli/{chunk-5f86nr5m.js.map → chunk-5cg2rzgf.js.map} +2 -2
- package/dist/cli/{chunk-tzmab476.js → chunk-5ffywsmb.js} +4 -4
- package/dist/cli/{chunk-2z928egk.js → chunk-5wj2qwn2.js} +5 -5
- package/dist/cli/chunk-6bm0xpgd.js +18 -0
- package/dist/cli/chunk-6bm0xpgd.js.map +10 -0
- package/dist/cli/{chunk-vg9r4eb9.js → chunk-713mngdq.js} +12 -5
- package/dist/cli/{chunk-vg9r4eb9.js.map → chunk-713mngdq.js.map} +3 -3
- package/dist/cli/{chunk-5xvm6tfj.js → chunk-9geymqns.js} +17 -15
- package/dist/cli/{chunk-5xvm6tfj.js.map → chunk-9geymqns.js.map} +2 -2
- package/dist/cli/{chunk-q58y5e6a.js → chunk-9xr4dgee.js} +26 -17
- package/dist/cli/chunk-9xr4dgee.js.map +10 -0
- package/dist/cli/{chunk-b07cmahc.js → chunk-amrb6hgh.js} +2 -2
- package/dist/cli/chunk-cm89scdv.js +443 -0
- package/dist/cli/chunk-cm89scdv.js.map +11 -0
- package/dist/cli/{chunk-akbpwfxc.js → chunk-cmtcnh9f.js} +2 -2
- package/dist/cli/chunk-cy5bm0j0.js +104 -0
- package/dist/cli/chunk-cy5bm0j0.js.map +11 -0
- package/dist/cli/{chunk-crgn1q09.js → chunk-e7vvk5ya.js} +4 -4
- package/dist/cli/{chunk-pehfxfta.js → chunk-g2z9x01v.js} +6 -98
- package/dist/cli/chunk-g2z9x01v.js.map +10 -0
- package/dist/cli/{chunk-tkacnehg.js → chunk-gp84za0h.js} +2 -2
- package/dist/cli/{chunk-wrr3j9w9.js → chunk-h2a48yhd.js} +186 -63
- package/dist/cli/chunk-h2a48yhd.js.map +36 -0
- package/dist/cli/{chunk-hm3vjy5s.js → chunk-jnwj5kjj.js} +14 -9
- package/dist/cli/{chunk-hm3vjy5s.js.map → chunk-jnwj5kjj.js.map} +4 -4
- package/dist/cli/chunk-kwrg63tm.js +31 -0
- package/dist/cli/chunk-kwrg63tm.js.map +10 -0
- package/dist/cli/{chunk-2hsdwb9n.js → chunk-nd1821sk.js} +18 -16
- package/dist/cli/{chunk-2hsdwb9n.js.map → chunk-nd1821sk.js.map} +2 -2
- package/dist/cli/{chunk-6dsbexzp.js → chunk-ntv4qrt7.js} +17 -15
- package/dist/cli/{chunk-6dsbexzp.js.map → chunk-ntv4qrt7.js.map} +2 -2
- package/dist/cli/{chunk-r9rcc4w7.js → chunk-p804f3pe.js} +7 -7
- package/dist/cli/{chunk-ey84smr6.js → chunk-py62fewh.js} +6 -6
- package/dist/cli/{chunk-ey84smr6.js.map → chunk-py62fewh.js.map} +1 -1
- package/dist/cli/chunk-q3wxxq39.js +126 -0
- package/dist/cli/chunk-q3wxxq39.js.map +11 -0
- package/dist/cli/{chunk-9t7a85s3.js → chunk-rekqz4qg.js} +23 -13
- package/dist/cli/chunk-rekqz4qg.js.map +10 -0
- package/dist/cli/{chunk-8ktnccpt.js → chunk-ta27feev.js} +1 -1
- package/dist/cli/{chunk-pv29h0wf.js → chunk-xkz5xbtv.js} +3476 -822
- package/dist/cli/chunk-xkz5xbtv.js.map +213 -0
- package/dist/cli/{chunk-a58773jm.js → chunk-y4ykbark.js} +2 -2
- package/dist/cli/{chunk-p3v96n38.js → chunk-y5h4r2y0.js} +4 -4
- package/dist/cli/{chunk-acanzt5p.js → chunk-yj17vs39.js} +6 -6
- package/dist/cli/{chunk-p73c0m7w.js → chunk-yxmk4pec.js} +16 -14
- package/dist/cli/{chunk-p73c0m7w.js.map → chunk-yxmk4pec.js.map} +2 -2
- package/dist/cli/{chunk-3em5wd2y.js → chunk-zccbjcj0.js} +4 -3
- package/dist/cli/{chunk-3em5wd2y.js.map → chunk-zccbjcj0.js.map} +2 -2
- package/dist/cli/{chunk-c8chx29p.js → chunk-zf748avv.js} +384 -207
- package/dist/cli/chunk-zf748avv.js.map +37 -0
- package/dist/cli/{chunk-g4hq16wv.js → chunk-zhvd6adm.js} +16 -14
- package/dist/cli/{chunk-g4hq16wv.js.map → chunk-zhvd6adm.js.map} +2 -2
- package/dist/cli/index.js +26 -20
- package/dist/cli/index.js.map +5 -5
- package/dist/types/ai/agent-surface.d.ts +8 -7
- package/dist/types/ai/ai-catalog.d.ts +7 -0
- package/dist/types/ai/ask-context.d.ts +22 -0
- package/dist/types/ai/ask.d.ts +271 -58
- package/dist/types/ai/index.d.ts +2 -2
- package/dist/types/ai/site-skill.d.ts +26 -0
- package/dist/types/ai/skills.d.ts +16 -0
- package/dist/types/astro/integration.d.ts +8 -0
- package/dist/types/captcha/hcaptcha.d.ts +27 -0
- package/dist/types/captcha/index.d.ts +28 -0
- package/dist/types/captcha/schema.d.ts +29 -0
- package/dist/types/captcha/turnstile.d.ts +28 -0
- package/dist/types/components/content/api-field.d.ts +59 -0
- package/dist/types/components/content/api-page.d.ts +95 -0
- package/dist/types/components/layout/nav-utils.d.ts +26 -0
- package/dist/types/components/openapi/helpers.d.ts +137 -0
- package/dist/types/components/openapi/security.d.ts +85 -0
- package/dist/types/consent/ethyca.d.ts +48 -0
- package/dist/types/consent/index.d.ts +37 -0
- package/dist/types/consent/native.d.ts +28 -0
- package/dist/types/consent/osano.d.ts +42 -0
- package/dist/types/consent/schema.d.ts +110 -0
- package/dist/types/core/config-input.d.ts +187 -20
- package/dist/types/core/data.d.ts +49 -4
- package/dist/types/core/footer.d.ts +8 -0
- package/dist/types/core/i18n-ui.d.ts +86 -0
- package/dist/types/core/includes.d.ts +8 -2
- package/dist/types/core/localizable.d.ts +7 -0
- package/dist/types/core/page-modes.d.ts +29 -0
- package/dist/types/core/redirect-patterns.d.ts +144 -0
- package/dist/types/core/related.d.ts +40 -0
- package/dist/types/core/schema.d.ts +551 -56
- package/dist/types/core/sources/read.d.ts +5 -0
- package/dist/types/core/types.d.ts +1 -1
- package/dist/types/core/variables.d.ts +42 -0
- package/dist/types/deploy/node-headers.d.ts +13 -2
- package/dist/types/deploy/platforms/cloudflare.d.ts +5 -0
- package/dist/types/deploy/platforms/netlify.d.ts +7 -0
- package/dist/types/deploy/platforms/vercel.d.ts +6 -0
- package/dist/types/deploy/redirects.d.ts +39 -11
- package/dist/types/deploy/vercel-negotiation.d.ts +9 -0
- package/dist/types/markdown/code-title.d.ts +17 -0
- package/dist/types/markdown/features.d.ts +3 -2
- package/dist/types/narration/build.d.ts +70 -0
- package/dist/types/narration/provider.d.ts +26 -0
- package/dist/types/narration/script.d.ts +154 -0
- package/dist/types/openapi/model.d.ts +12 -6
- package/dist/types/openapi/overlay.d.ts +54 -0
- package/dist/types/openapi/parse.d.ts +13 -0
- package/dist/types/openapi/references.d.ts +14 -4
- package/dist/types/ratelimit/cloudflare.d.ts +39 -0
- package/dist/types/ratelimit/index.d.ts +27 -0
- package/dist/types/ratelimit/memory.d.ts +36 -0
- package/dist/types/ratelimit/schema.d.ts +111 -0
- package/dist/types/ratelimit/upstash.d.ts +21 -0
- package/dist/types/ratelimit/wrangler.d.ts +23 -0
- package/dist/types/reference/asyncapi.d.ts +10 -10
- package/dist/types/reference/graphql.d.ts +13 -10
- package/dist/types/reference/openapi.d.ts +33 -12
- package/dist/types/reference/options.d.ts +45 -5
- package/dist/types/reference/scalar.d.ts +13 -0
- package/dist/types/reference/schema.d.ts +60 -36
- package/dist/types/search/documents.d.ts +12 -1
- package/dist/types/search/orama-index.d.ts +4 -0
- package/dist/types/seo/metatags.d.ts +20 -0
- package/docs/02-deployment.mdx +41 -5
- package/docs/03-upgrading.mdx +4 -4
- package/docs/04-migrating.mdx +1 -1
- package/docs/advanced/changelog.mdx +2 -2
- package/docs/advanced/skills.mdx +14 -0
- package/docs/cli/audit.mdx +21 -1
- package/docs/cli/index.mdx +1 -0
- package/docs/configuration/analytics.mdx +3 -1
- package/docs/configuration/assistant.mdx +188 -36
- package/docs/configuration/consent.mdx +100 -0
- package/docs/configuration/customization.mdx +4 -4
- package/docs/configuration/index.mdx +63 -5
- package/docs/configuration/meta.ts +3 -0
- package/docs/configuration/narration.mdx +119 -0
- package/docs/configuration/rate-limiting.mdx +69 -0
- package/docs/configuration/search.mdx +29 -1
- package/docs/configuration/theming.mdx +3 -1
- package/docs/content/components.mdx +106 -0
- package/docs/content/frontmatter.mdx +76 -0
- package/docs/content/i18n.mdx +38 -3
- package/docs/content/includes.mdx +16 -0
- package/docs/content/meta.mdx +1 -0
- package/docs/content/meta.ts +1 -0
- package/docs/content/navigation.mdx +28 -6
- package/docs/content/sources/contentful.mdx +32 -0
- package/docs/content/sources/custom.mdx +39 -0
- package/docs/content/sources/github-releases.mdx +31 -0
- package/docs/content/sources/index.mdx +91 -0
- package/docs/content/sources/meta.ts +16 -0
- package/docs/content/sources/notion.mdx +32 -0
- package/docs/content/sources/obsidian.mdx +37 -0
- package/docs/content/sources/payload.mdx +30 -0
- package/docs/content/sources/remote-mdx.mdx +40 -0
- package/docs/content/sources/sanity.mdx +29 -0
- package/docs/content/sources/strapi.mdx +31 -0
- package/docs/content/syntax.mdx +67 -2
- package/docs/content/variables.mdx +41 -0
- package/docs/discoverability/agent-discovery.mdx +29 -2
- package/docs/discoverability/index.mdx +1 -1
- package/docs/discoverability/llms-txt.mdx +1 -1
- package/docs/discoverability/metadata.mdx +17 -0
- package/docs/references/api-pages.mdx +74 -0
- package/docs/references/asyncapi.mdx +1 -1
- package/docs/references/graphql.mdx +2 -2
- package/docs/references/meta.ts +1 -1
- package/docs/references/openapi.mdx +102 -3
- package/docs/references/scalar.mdx +3 -1
- package/package.json +36 -1
- package/skills/blume/SKILL.md +3 -0
- package/skills/blume-migrate/SKILL.md +5 -5
- package/skills/blume-migrate/references/docusaurus.md +3 -3
- package/skills/blume-migrate/references/mintlify.md +37 -19
- package/skills/blume-migrate/references/nextra.md +2 -2
- package/skills/blume-migrate/references/starlight.md +2 -1
- package/skills/blume-migrate/scripts/mintlify-codemod.mjs +60 -14
- package/skills/blume-write-skill/SKILL.md +82 -0
- package/src/ai/agent-readability.ts +2 -1
- package/src/ai/agent-surface.ts +9 -7
- package/src/ai/ai-catalog.ts +6 -3
- package/src/ai/ask-context.ts +73 -20
- package/src/ai/ask-data.ts +6 -0
- package/src/ai/ask-tools.ts +142 -0
- package/src/ai/ask.ts +354 -76
- package/src/ai/component-markdown.ts +75 -0
- package/src/ai/cors.ts +2 -0
- package/src/ai/index.ts +12 -0
- package/src/ai/llms.ts +6 -2
- package/src/ai/markdown.ts +2 -1
- package/src/ai/mcp/data.ts +6 -0
- package/src/ai/openapi-components.ts +9 -3
- package/src/ai/site-skill.ts +274 -0
- package/src/ai/skills.ts +35 -2
- package/src/ai/write-skill.ts +97 -0
- package/src/astro/generate.ts +132 -18
- package/src/astro/index.ts +1 -0
- package/src/astro/integration.ts +35 -0
- package/src/astro/module-types.ts +6 -0
- package/src/astro/templates.ts +283 -30
- package/src/astro/variables.ts +31 -0
- package/src/audit/catalog.ts +19 -0
- package/src/audit/checks/contrast.ts +183 -0
- package/src/audit/checks/i18n.ts +2 -3
- package/src/audit/checks/indexability.ts +2 -3
- package/src/audit/checks/links.ts +5 -12
- package/src/audit/checks/sitemap.ts +2 -3
- package/src/audit/redirects.ts +46 -15
- package/src/audit/run.ts +2 -0
- package/src/audit/types.ts +2 -1
- package/src/blume-modules.d.ts +7 -0
- package/src/captcha/client.ts +152 -0
- package/src/captcha/hcaptcha.ts +36 -0
- package/src/captcha/index.ts +28 -0
- package/src/captcha/schema.ts +32 -0
- package/src/captcha/turnstile.ts +38 -0
- package/src/captcha/verify.ts +71 -0
- package/src/cli/command-meta.ts +5 -0
- package/src/cli/commands/doctor.ts +22 -16
- package/src/cli/commands/skill.ts +96 -0
- package/src/cli/index.ts +5 -0
- package/src/cli/required-secrets.ts +71 -29
- package/src/components/BlumePage.astro +2 -0
- package/src/components/content/ApiEndpoint.astro +18 -0
- package/src/components/content/ApiField.astro +79 -0
- package/src/components/content/ApiPlayground.astro +62 -0
- package/src/components/content/ApiRail.astro +19 -0
- package/src/components/content/Color.astro +1 -0
- package/src/components/content/FileTree.astro +1 -0
- package/src/components/content/GithubInfo.astro +1 -0
- package/src/components/content/Panel.astro +1 -0
- package/src/components/content/ParamField.astro +25 -0
- package/src/components/content/RequestExample.astro +17 -0
- package/src/components/content/ResponseExample.astro +17 -0
- package/src/components/content/ResponseField.astro +32 -0
- package/src/components/content/Step.astro +1 -0
- package/src/components/content/Tile.astro +1 -0
- package/src/components/content/Tooltip.astro +1 -0
- package/src/components/content/Tree.astro +1 -0
- package/src/components/content/TypeTable.astro +4 -1
- package/src/components/content/View.astro +21 -0
- package/src/components/content/ViewSwitcher.astro +168 -0
- package/src/components/content/api-field.ts +100 -0
- package/src/components/content/api-page.ts +224 -0
- package/src/components/content/view-switcher.ts +71 -0
- package/src/components/index.ts +2 -0
- package/src/components/islands/Assistant.astro +10 -1
- package/src/components/islands/assistant.tsx +104 -14
- package/src/components/islands/code-question.ts +62 -0
- package/src/components/islands/hooks.ts +110 -21
- package/src/components/islands/support-link.ts +68 -0
- package/src/components/layout/Analytics.astro +11 -2
- package/src/components/layout/Banner.astro +14 -10
- package/src/components/layout/Breadcrumbs.astro +6 -2
- package/src/components/layout/ConsentBanner.astro +62 -0
- package/src/components/layout/ConsentHead.astro +38 -0
- package/src/components/layout/Directory.astro +94 -0
- package/src/components/layout/DrawerSwitchers.astro +51 -0
- package/src/components/layout/Empty.astro +2 -2
- package/src/components/layout/Header.astro +122 -80
- package/src/components/layout/LanguageSwitcher.astro +48 -15
- package/src/components/layout/NarrationPlayer.astro +1085 -0
- package/src/components/layout/NavSelector.astro +33 -7
- package/src/components/layout/PageFeedback.astro +54 -49
- package/src/components/layout/PageLayout.astro +71 -3
- package/src/components/layout/ReferenceLayout.astro +17 -6
- package/src/components/layout/RelatedPages.astro +42 -0
- package/src/components/layout/RootLayout.astro +308 -45
- package/src/components/layout/Search.astro +31 -17
- package/src/components/layout/SiteFooter.astro +124 -0
- package/src/components/layout/SiteMetatags.astro +16 -0
- package/src/components/layout/consent/native.ts +79 -0
- package/src/components/layout/consent/types.ts +37 -0
- package/src/components/layout/footer-links.ts +53 -0
- package/src/components/layout/footer-socials.ts +87 -0
- package/src/components/layout/locale-redirect.ts +107 -0
- package/src/components/layout/nav-utils.ts +83 -0
- package/src/components/layout/page-feedback.ts +96 -0
- package/src/components/layout/search/analytics.ts +98 -0
- package/src/components/layout/search/flexsearch.ts +17 -5
- package/src/components/layout/search/orama-cloud.ts +26 -14
- package/src/components/layout/search/types.ts +20 -0
- package/src/components/layout/search/typesense.ts +5 -1
- package/src/components/openapi/Operation.astro +161 -13
- package/src/components/openapi/RequestBody.astro +6 -4
- package/src/components/openapi/RequestPanel.astro +59 -7
- package/src/components/openapi/Responses.astro +6 -4
- package/src/components/openapi/async-snippets.ts +4 -4
- package/src/components/openapi/code-samples.ts +97 -0
- package/src/components/openapi/security.ts +6 -3
- package/src/components/openapi/snippets.ts +869 -8
- package/src/components/props.ts +6 -0
- package/src/consent/client.ts +95 -0
- package/src/consent/clients.ts +19 -0
- package/src/consent/ethyca.ts +71 -0
- package/src/consent/head.ts +24 -0
- package/src/consent/index.ts +37 -0
- package/src/consent/init.ts +29 -0
- package/src/consent/native.ts +36 -0
- package/src/consent/osano.ts +59 -0
- package/src/consent/schema.ts +30 -0
- package/src/core/builtin-tags.ts +5 -0
- package/src/core/client-address.ts +19 -0
- package/src/core/config-input.ts +194 -20
- package/src/core/data.ts +44 -4
- package/src/core/diagnostics.ts +3 -2
- package/src/core/footer.ts +26 -0
- package/src/core/graph.ts +39 -36
- package/src/core/i18n-ui.ts +82 -2
- package/src/core/includes.ts +20 -3
- package/src/core/links.ts +16 -2
- package/src/core/localizable.ts +26 -0
- package/src/core/navigation.ts +43 -12
- package/src/core/page-modes.ts +56 -0
- package/src/core/project-graph.ts +111 -5
- package/src/core/redirect-patterns.ts +491 -0
- package/src/core/related.ts +131 -0
- package/src/core/schema.ts +318 -64
- package/src/core/sources/normalize.ts +2 -1
- package/src/core/sources/read.ts +8 -3
- package/src/core/types.ts +1 -1
- package/src/core/ui-packs/ar.ts +43 -0
- package/src/core/ui-packs/bg.ts +45 -0
- package/src/core/ui-packs/bn.ts +43 -0
- package/src/core/ui-packs/ca.ts +46 -0
- package/src/core/ui-packs/cs.ts +44 -0
- package/src/core/ui-packs/da.ts +45 -0
- package/src/core/ui-packs/de.ts +46 -0
- package/src/core/ui-packs/el.ts +45 -0
- package/src/core/ui-packs/es.ts +46 -0
- package/src/core/ui-packs/fa.ts +45 -0
- package/src/core/ui-packs/fi.ts +45 -0
- package/src/core/ui-packs/fr.ts +46 -0
- package/src/core/ui-packs/he.ts +43 -0
- package/src/core/ui-packs/hi.ts +44 -0
- package/src/core/ui-packs/hr.ts +45 -0
- package/src/core/ui-packs/hu.ts +44 -0
- package/src/core/ui-packs/id.ts +45 -0
- package/src/core/ui-packs/it.ts +45 -0
- package/src/core/ui-packs/ja.ts +45 -0
- package/src/core/ui-packs/ko.ts +44 -0
- package/src/core/ui-packs/nl.ts +46 -0
- package/src/core/ui-packs/no.ts +44 -0
- package/src/core/ui-packs/pl.ts +45 -0
- package/src/core/ui-packs/pt-br.ts +46 -0
- package/src/core/ui-packs/pt.ts +45 -0
- package/src/core/ui-packs/ro.ts +45 -0
- package/src/core/ui-packs/ru.ts +45 -0
- package/src/core/ui-packs/sk.ts +44 -0
- package/src/core/ui-packs/sr.ts +45 -0
- package/src/core/ui-packs/sv.ts +44 -0
- package/src/core/ui-packs/th.ts +43 -0
- package/src/core/ui-packs/tr.ts +45 -0
- package/src/core/ui-packs/uk.ts +45 -0
- package/src/core/ui-packs/vi.ts +45 -0
- package/src/core/ui-packs/zh-tw.ts +43 -0
- package/src/core/ui-packs/zh.ts +43 -0
- package/src/core/variables.ts +103 -0
- package/src/deploy/artifacts.ts +77 -8
- package/src/deploy/cloudflare-negotiation.ts +35 -5
- package/src/deploy/headers.ts +2 -1
- package/src/deploy/node-headers.ts +63 -9
- package/src/deploy/platforms/cloudflare.ts +32 -0
- package/src/deploy/platforms/netlify.ts +33 -1
- package/src/deploy/platforms/vercel.ts +37 -2
- package/src/deploy/redirects.ts +91 -24
- package/src/deploy/vercel-negotiation.ts +36 -0
- package/src/markdown/api-rail.ts +259 -0
- package/src/markdown/code-title.ts +35 -9
- package/src/markdown/features.ts +3 -2
- package/src/markdown/fence-meta.ts +2 -0
- package/src/markdown/include.ts +11 -1
- package/src/markdown/index.ts +28 -5
- package/src/markdown/math.ts +4 -4
- package/src/markdown/variables.ts +56 -0
- package/src/markdown/views.ts +82 -0
- package/src/narration/build.ts +412 -0
- package/src/narration/player.ts +249 -0
- package/src/narration/provider.ts +29 -0
- package/src/narration/script.ts +592 -0
- package/src/og/card.ts +7 -6
- package/src/openapi/model.ts +57 -24
- package/src/openapi/overlay.ts +256 -0
- package/src/openapi/parse.ts +55 -2
- package/src/openapi/references.ts +21 -5
- package/src/openapi/render-mdx.ts +5 -1
- package/src/openapi/scalar.ts +40 -6
- package/src/openapi/source.ts +1 -1
- package/src/ratelimit/cloudflare.ts +54 -0
- package/src/ratelimit/index.ts +30 -0
- package/src/ratelimit/memory.ts +45 -0
- package/src/ratelimit/runtime.ts +229 -0
- package/src/ratelimit/schema.ts +28 -0
- package/src/ratelimit/upstash.ts +30 -0
- package/src/ratelimit/wrangler.ts +70 -0
- package/src/reference/asyncapi.ts +2 -2
- package/src/reference/graphql.ts +5 -2
- package/src/reference/openapi.ts +21 -7
- package/src/reference/options.ts +51 -7
- package/src/reference/scalar.ts +33 -8
- package/src/registry/eject.ts +20 -4
- package/src/registry/registry.ts +7 -0
- package/src/search/documents.ts +26 -2
- package/src/search/orama-index.ts +28 -3
- package/src/search/pagefind-ranking.ts +39 -0
- package/src/search/sync/algolia.ts +15 -4
- package/src/search/sync/orama-cloud.ts +3 -0
- package/src/search/sync/typesense.ts +5 -0
- package/src/seo/metatags.ts +67 -0
- package/src/theme/chrome-icons.ts +1 -0
- package/src/theme/color.ts +500 -0
- package/src/theme/entry.ts +56 -3
- package/src/theme/palette.ts +121 -45
- package/src/translate/prompts.ts +1 -0
- package/src/translate/validate.ts +8 -2
- package/src/upgrade/upgrade.ts +4 -171
- package/dist/cli/chunk-364znk6q.js +0 -75
- package/dist/cli/chunk-364znk6q.js.map +0 -11
- package/dist/cli/chunk-5m5nmvyq.js.map +0 -13
- package/dist/cli/chunk-9t7a85s3.js.map +0 -10
- package/dist/cli/chunk-c8chx29p.js.map +0 -36
- package/dist/cli/chunk-pehfxfta.js.map +0 -10
- package/dist/cli/chunk-pv29h0wf.js.map +0 -190
- package/dist/cli/chunk-q58y5e6a.js.map +0 -10
- package/dist/cli/chunk-wrr3j9w9.js.map +0 -35
- package/dist/cli/chunk-yfyb25rh.js.map +0 -14
- package/docs/content/sources.mdx +0 -334
- /package/dist/cli/{chunk-2eytanqx.js.map → chunk-1n228xqb.js.map} +0 -0
- /package/dist/cli/{chunk-35d4wj9f.js.map → chunk-2n4ps1b3.js.map} +0 -0
- /package/dist/cli/{chunk-e04dxsz1.js.map → chunk-4ejxbzee.js.map} +0 -0
- /package/dist/cli/{chunk-tzmab476.js.map → chunk-5ffywsmb.js.map} +0 -0
- /package/dist/cli/{chunk-2z928egk.js.map → chunk-5wj2qwn2.js.map} +0 -0
- /package/dist/cli/{chunk-b07cmahc.js.map → chunk-amrb6hgh.js.map} +0 -0
- /package/dist/cli/{chunk-akbpwfxc.js.map → chunk-cmtcnh9f.js.map} +0 -0
- /package/dist/cli/{chunk-crgn1q09.js.map → chunk-e7vvk5ya.js.map} +0 -0
- /package/dist/cli/{chunk-tkacnehg.js.map → chunk-gp84za0h.js.map} +0 -0
- /package/dist/cli/{chunk-r9rcc4w7.js.map → chunk-p804f3pe.js.map} +0 -0
- /package/dist/cli/{chunk-8ktnccpt.js.map → chunk-ta27feev.js.map} +0 -0
- /package/dist/cli/{chunk-a58773jm.js.map → chunk-y4ykbark.js.map} +0 -0
- /package/dist/cli/{chunk-p3v96n38.js.map → chunk-y5h4r2y0.js.map} +0 -0
- /package/dist/cli/{chunk-acanzt5p.js.map → chunk-yj17vs39.js.map} +0 -0
|
@@ -8,6 +8,7 @@ import { buildRssFeeds } from "../deploy/rss.ts";
|
|
|
8
8
|
import { AI_CATALOG_PATH, hasAiCatalog } from "./ai-catalog.ts";
|
|
9
9
|
import { hasApiCatalog } from "./api-catalog.ts";
|
|
10
10
|
import { API_PAGES_PATH, API_SEARCH_PATH, OPENAPI_PATH } from "./api/paths.ts";
|
|
11
|
+
import { servesSkillsIndex } from "./skills.ts";
|
|
11
12
|
|
|
12
13
|
/** Token map for the machine-readable content-usage echo. */
|
|
13
14
|
const USAGE_TOKENS: [keyof ContentSignalPolicy, string][] = [
|
|
@@ -145,7 +146,7 @@ const wellKnownArtifacts = (
|
|
|
145
146
|
if (hasApiCatalog(config)) {
|
|
146
147
|
artifacts.apiCatalog = abs("/.well-known/api-catalog");
|
|
147
148
|
}
|
|
148
|
-
if (config
|
|
149
|
+
if (servesSkillsIndex(config)) {
|
|
149
150
|
artifacts.agentSkills = abs("/.well-known/agent-skills/index.json");
|
|
150
151
|
}
|
|
151
152
|
return artifacts;
|
package/src/ai/agent-surface.ts
CHANGED
|
@@ -11,7 +11,8 @@ export interface EmittedAgentSurface {
|
|
|
11
11
|
mcp: boolean;
|
|
12
12
|
/**
|
|
13
13
|
* A skills discovery index is served: generated from `agents.skills` (at
|
|
14
|
-
* least one valid skill)
|
|
14
|
+
* least one valid skill) or the site skill (`agents.skillMd`), or shipped
|
|
15
|
+
* by the user in `public/`.
|
|
15
16
|
*/
|
|
16
17
|
skills: boolean;
|
|
17
18
|
}
|
|
@@ -33,12 +34,12 @@ export const servesMcp = (
|
|
|
33
34
|
);
|
|
34
35
|
|
|
35
36
|
/**
|
|
36
|
-
* The config the discovery documents are built from: `agents.mcp
|
|
37
|
-
* `agents.skills` switched off when the build didn't
|
|
38
|
-
* agent-readability.json, the catalogs, and the
|
|
39
|
-
* what is there. A config flag says what was asked
|
|
40
|
-
* skipped when a page owns its route, and skills
|
|
41
|
-
* directory is missing or holds no valid skill.
|
|
37
|
+
* The config the discovery documents are built from: `agents.mcp`,
|
|
38
|
+
* `agents.skills`, and `agents.skillMd` switched off when the build didn't
|
|
39
|
+
* emit them, so llms.txt, agent-readability.json, the catalogs, and the
|
|
40
|
+
* header rules only point at what is there. A config flag says what was asked
|
|
41
|
+
* for; the MCP server is skipped when a page owns its route, and skills
|
|
42
|
+
* publish nothing when their directory is missing or holds no valid skill.
|
|
42
43
|
*/
|
|
43
44
|
export const advertisedConfig = (
|
|
44
45
|
config: ResolvedConfig,
|
|
@@ -51,6 +52,7 @@ export const advertisedConfig = (
|
|
|
51
52
|
...config.agents.mcp,
|
|
52
53
|
enabled: config.agents.mcp.enabled && emitted.mcp,
|
|
53
54
|
},
|
|
55
|
+
skillMd: config.agents.skillMd && emitted.skills,
|
|
54
56
|
skills: emitted.skills ? config.agents.skills : undefined,
|
|
55
57
|
},
|
|
56
58
|
});
|
package/src/ai/ai-catalog.ts
CHANGED
|
@@ -10,7 +10,7 @@ import { resolveReferences } from "../openapi/references.ts";
|
|
|
10
10
|
import { API_CATALOG_PATH, hasApiCatalog } from "./api-catalog.ts";
|
|
11
11
|
import { OPENAPI_PATH } from "./api/paths.ts";
|
|
12
12
|
import { asciiSlugify } from "./mcp/discovery.ts";
|
|
13
|
-
import { AGENT_SKILLS_DIR } from "./skills.ts";
|
|
13
|
+
import { AGENT_SKILLS_DIR, servesSkillsIndex } from "./skills.ts";
|
|
14
14
|
import type { SkillArtifact } from "./skills.ts";
|
|
15
15
|
|
|
16
16
|
/**
|
|
@@ -86,7 +86,7 @@ export const hasAiCatalog = (config: ResolvedConfig): boolean =>
|
|
|
86
86
|
(config.agents.mcp.enabled ||
|
|
87
87
|
config.agents.api ||
|
|
88
88
|
config.agents.llmsTxt.enabled ||
|
|
89
|
-
|
|
89
|
+
servesSkillsIndex(config) ||
|
|
90
90
|
resolveReferences(config).length > 0);
|
|
91
91
|
|
|
92
92
|
/**
|
|
@@ -118,7 +118,10 @@ const NAMES_DOCS = /\b(?:docs|documentation)$/iu;
|
|
|
118
118
|
* reads "the Acme documentation" and "Acme Docs" reads "the Acme Docs", not
|
|
119
119
|
* "the Acme Docs docs".
|
|
120
120
|
*/
|
|
121
|
-
const docsPhrase = (
|
|
121
|
+
export const docsPhrase = (
|
|
122
|
+
title: string,
|
|
123
|
+
noun: "docs" | "documentation"
|
|
124
|
+
): string =>
|
|
122
125
|
NAMES_DOCS.test(title.trim()) ? `the ${title}` : `the ${title} ${noun}`;
|
|
123
126
|
|
|
124
127
|
const entrySeeds = (
|
package/src/ai/ask-context.ts
CHANGED
|
@@ -228,6 +228,17 @@ const queryTerms = (query: string): string[] =>
|
|
|
228
228
|
const BASE_INSTRUCTION =
|
|
229
229
|
"You are a helpful documentation assistant for this project. Answer the user's question using ONLY the documentation excerpts below. Each excerpt is headed by its page as `## Page Title (/route)`. If the answer is not covered by the excerpts, say you don't know and suggest where in the docs to look — do not invent details. Always cite the pages you drew from, and write every citation as a Markdown link to that page using its route, e.g. [Page Title](/route).";
|
|
230
230
|
|
|
231
|
+
/**
|
|
232
|
+
* Appended when the endpoint gives the model the docs tools (see
|
|
233
|
+
* `ask-tools.ts`): the excerpts are a head start, not the whole of the docs.
|
|
234
|
+
*/
|
|
235
|
+
const TOOL_INSTRUCTION =
|
|
236
|
+
"You can also search the documentation yourself. When the excerpts don't fully answer the question, call search_docs with a focused query to find other pages, and read_page to read a page in full (one an excerpt cuts off, say) before you answer. Treat tool results exactly like the excerpts: answer only from them, and cite the pages you drew from the same way.";
|
|
237
|
+
|
|
238
|
+
/** Said instead of the excerpts when retrieval found none but tools can look. */
|
|
239
|
+
const NO_EXCERPTS_WITH_TOOLS =
|
|
240
|
+
"No documentation excerpts matched this question up front. Use search_docs to look before you answer.";
|
|
241
|
+
|
|
231
242
|
/** The non-empty user turns, oldest first. Assistant turns never seed retrieval. */
|
|
232
243
|
const userTurns = (messages: AskMessage[]): string[] =>
|
|
233
244
|
messages
|
|
@@ -591,6 +602,48 @@ export const sectionExcerpt = (
|
|
|
591
602
|
max: number
|
|
592
603
|
): string => excerptPage(parsePage(content), query, max);
|
|
593
604
|
|
|
605
|
+
// One Orama index per snapshot, shared by the grounding function and the
|
|
606
|
+
// docs tools so a cold endpoint builds it once.
|
|
607
|
+
const indexes = new WeakMap<AskData, ReturnType<typeof buildOramaIndex>>();
|
|
608
|
+
|
|
609
|
+
/** The search index over an assistant snapshot, built on first use. */
|
|
610
|
+
export const askIndex = (data: AskData): ReturnType<typeof buildOramaIndex> => {
|
|
611
|
+
let index = indexes.get(data);
|
|
612
|
+
if (!index) {
|
|
613
|
+
index = buildOramaIndex(data.documents, data.defaultLocale);
|
|
614
|
+
indexes.set(data, index);
|
|
615
|
+
}
|
|
616
|
+
return index;
|
|
617
|
+
};
|
|
618
|
+
|
|
619
|
+
/** The page the reader is on, and the search filters it implies. */
|
|
620
|
+
export interface ReaderScope {
|
|
621
|
+
current: OramaDoc | undefined;
|
|
622
|
+
filters: { locale: string | undefined; version: string | undefined };
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
/**
|
|
626
|
+
* Where the reader is: their page, when it's in the snapshot, and the locale
|
|
627
|
+
* and docs version retrieval keeps to. Without a page, a versioned site
|
|
628
|
+
* grounds in the current docs rather than every archived copy of each page.
|
|
629
|
+
*/
|
|
630
|
+
export const readerScope = (
|
|
631
|
+
data: AskData,
|
|
632
|
+
byRoute: ReadonlyMap<string, OramaDoc>,
|
|
633
|
+
page?: AskPage
|
|
634
|
+
): ReaderScope => {
|
|
635
|
+
const current = page?.path
|
|
636
|
+
? byRoute.get(normalizeRoute(page.path))
|
|
637
|
+
: undefined;
|
|
638
|
+
return {
|
|
639
|
+
current,
|
|
640
|
+
filters: {
|
|
641
|
+
locale: current?.locale || undefined,
|
|
642
|
+
version: data.versioned ? (current?.version ?? "") : undefined,
|
|
643
|
+
},
|
|
644
|
+
};
|
|
645
|
+
};
|
|
646
|
+
|
|
594
647
|
/**
|
|
595
648
|
* Build the request-time grounding function for the assistant endpoint.
|
|
596
649
|
*
|
|
@@ -607,20 +660,22 @@ export const sectionExcerpt = (
|
|
|
607
660
|
*
|
|
608
661
|
* `options.retrieval` (the `ai.assistant.retrieval` config) sizes how much
|
|
609
662
|
* documentation each question carries; omitted fields keep today's defaults.
|
|
663
|
+
*
|
|
664
|
+
* `options.tools` says the endpoint also hands the model the docs tools: the
|
|
665
|
+
* prompt then says so, and a question retrieval found nothing for still gets
|
|
666
|
+
* a grounded prompt, since the model can go and search.
|
|
610
667
|
*/
|
|
611
668
|
export const createAskContext = (
|
|
612
669
|
data: AskData,
|
|
613
|
-
options?: {
|
|
670
|
+
options?: {
|
|
671
|
+
instructions?: string;
|
|
672
|
+
retrieval?: AskRetrievalOptions;
|
|
673
|
+
tools?: boolean;
|
|
674
|
+
}
|
|
614
675
|
): ((
|
|
615
676
|
messages: AskMessage[],
|
|
616
677
|
page?: AskPage
|
|
617
678
|
) => Promise<string | undefined>) => {
|
|
618
|
-
let dbPromise: Promise<Awaited<ReturnType<typeof buildOramaIndex>>> | null =
|
|
619
|
-
null;
|
|
620
|
-
const index = () => {
|
|
621
|
-
dbPromise ??= buildOramaIndex(data.documents, data.defaultLocale);
|
|
622
|
-
return dbPromise;
|
|
623
|
-
};
|
|
624
679
|
const byRoute = new Map(data.documents.map((doc) => [doc.route, doc]));
|
|
625
680
|
// Section splitting and tokenizing are per page, not per question, so each
|
|
626
681
|
// page is parsed on first use and reused for the life of the endpoint.
|
|
@@ -633,9 +688,12 @@ export const createAskContext = (
|
|
|
633
688
|
}
|
|
634
689
|
return page;
|
|
635
690
|
};
|
|
636
|
-
const
|
|
637
|
-
? `${BASE_INSTRUCTION}
|
|
691
|
+
const base = options?.tools
|
|
692
|
+
? `${BASE_INSTRUCTION} ${TOOL_INSTRUCTION}`
|
|
638
693
|
: BASE_INSTRUCTION;
|
|
694
|
+
const instruction = options?.instructions
|
|
695
|
+
? `${base}\n\n${options.instructions}`
|
|
696
|
+
: base;
|
|
639
697
|
const maxResults = options?.retrieval?.maxResults ?? MAX_RESULTS;
|
|
640
698
|
const excerptChars = options?.retrieval?.excerptChars ?? EXCERPT_CHARS;
|
|
641
699
|
const contextBudget = options?.retrieval?.contextBudget ?? CONTEXT_BUDGET;
|
|
@@ -652,16 +710,9 @@ export const createAskContext = (
|
|
|
652
710
|
const [query = ""] = queries;
|
|
653
711
|
|
|
654
712
|
// The current page anchors retrieval to its locale and docs version, and
|
|
655
|
-
// is injected first.
|
|
656
|
-
|
|
657
|
-
const
|
|
658
|
-
? byRoute.get(normalizeRoute(page.path))
|
|
659
|
-
: undefined;
|
|
660
|
-
const db = await index();
|
|
661
|
-
const filters = {
|
|
662
|
-
locale: current?.locale || undefined,
|
|
663
|
-
version: data.versioned ? (current?.version ?? "") : undefined,
|
|
664
|
-
};
|
|
713
|
+
// is injected first.
|
|
714
|
+
const { current, filters } = readerScope(data, byRoute, page);
|
|
715
|
+
const db = await askIndex(data);
|
|
665
716
|
const hits = interleave(
|
|
666
717
|
await Promise.all(
|
|
667
718
|
queries.map((text) => queryOramaIndex(db, text, maxResults, filters))
|
|
@@ -700,7 +751,9 @@ export const createAskContext = (
|
|
|
700
751
|
}
|
|
701
752
|
|
|
702
753
|
if (sections.length === 0) {
|
|
703
|
-
return
|
|
754
|
+
return options?.tools
|
|
755
|
+
? `${instruction}\n\n${NO_EXCERPTS_WITH_TOOLS}`
|
|
756
|
+
: undefined;
|
|
704
757
|
}
|
|
705
758
|
return `${instruction}\n\n<docs>\n${sections.join("\n\n")}\n</docs>`;
|
|
706
759
|
};
|
package/src/ai/ask-data.ts
CHANGED
|
@@ -36,6 +36,12 @@ export const buildAskData = async (project: BlumeProject): Promise<AskData> => {
|
|
|
36
36
|
if (versioned) {
|
|
37
37
|
document.version = doc.version;
|
|
38
38
|
}
|
|
39
|
+
if (doc.boost !== undefined) {
|
|
40
|
+
document.boost = doc.boost;
|
|
41
|
+
}
|
|
42
|
+
if (doc.keywords) {
|
|
43
|
+
document.keywords = doc.keywords;
|
|
44
|
+
}
|
|
39
45
|
return document;
|
|
40
46
|
}),
|
|
41
47
|
site: project.config.deployment.options.site ?? null,
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { jsonSchema, tool } from "ai";
|
|
2
|
+
|
|
3
|
+
import { normalizeRoute } from "../core/base-path.ts";
|
|
4
|
+
import { queryOramaIndex } from "../search/orama-index.ts";
|
|
5
|
+
import type { OramaDoc } from "../search/orama-index.ts";
|
|
6
|
+
import { askIndex, readerScope, sectionExcerpt } from "./ask-context.ts";
|
|
7
|
+
import type { AskData, AskPage, ReaderScope } from "./ask-context.ts";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* The assistant's docs tools: what lets it look beyond the excerpts the
|
|
11
|
+
* endpoint injects up front. `search_docs` runs the same Orama search the
|
|
12
|
+
* grounding does, scoped to the reader's language and docs version;
|
|
13
|
+
* `read_page` returns a whole page, for when an excerpt stops short of the
|
|
14
|
+
* answer. Both read the assistant snapshot the endpoint already imports, so
|
|
15
|
+
* they add no build output and no network call.
|
|
16
|
+
*
|
|
17
|
+
* The generated `/api/ask` route passes them to `streamText` with a step cap
|
|
18
|
+
* ({@link ASK_MAX_STEPS}), so the model can search, read, and then answer
|
|
19
|
+
* within one request.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* The most model steps one answer may take: up to four rounds of tool calls,
|
|
24
|
+
* then the answer. Enough to search, read a page or two, and search again,
|
|
25
|
+
* while bounding what one question can spend.
|
|
26
|
+
*/
|
|
27
|
+
export const ASK_MAX_STEPS = 5;
|
|
28
|
+
|
|
29
|
+
/** Pages one search returns. */
|
|
30
|
+
const SEARCH_RESULTS = 5;
|
|
31
|
+
|
|
32
|
+
/** Characters of each search result's most relevant excerpt. */
|
|
33
|
+
const SEARCH_EXCERPT_CHARS = 700;
|
|
34
|
+
|
|
35
|
+
/** Characters of a page `read_page` returns; a longer page is cut here. */
|
|
36
|
+
const PAGE_CHARS = 20_000;
|
|
37
|
+
|
|
38
|
+
/** A result block, headed the way the injected excerpts are, for citing. */
|
|
39
|
+
const block = (doc: OramaDoc, body: string): string =>
|
|
40
|
+
`## ${doc.title} (${doc.route})\n${body}`;
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Search the docs for `query` within the reader's scope: the most relevant
|
|
44
|
+
* excerpt of each of the top pages, or a note that nothing matched.
|
|
45
|
+
*/
|
|
46
|
+
export const searchDocs = async (
|
|
47
|
+
data: AskData,
|
|
48
|
+
scope: ReaderScope,
|
|
49
|
+
query: string
|
|
50
|
+
): Promise<string> => {
|
|
51
|
+
const hits = await queryOramaIndex(
|
|
52
|
+
await askIndex(data),
|
|
53
|
+
query,
|
|
54
|
+
SEARCH_RESULTS,
|
|
55
|
+
scope.filters
|
|
56
|
+
);
|
|
57
|
+
if (hits.length === 0) {
|
|
58
|
+
return `No pages matched "${query}". Try other words, or a broader query.`;
|
|
59
|
+
}
|
|
60
|
+
return hits
|
|
61
|
+
.map((doc) =>
|
|
62
|
+
block(doc, sectionExcerpt(doc.content, query, SEARCH_EXCERPT_CHARS))
|
|
63
|
+
)
|
|
64
|
+
.join("\n\n");
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* The route a model asked for, as the snapshot keys it: a full URL on the
|
|
69
|
+
* site becomes its path, and a query string or fragment is dropped.
|
|
70
|
+
*/
|
|
71
|
+
const routeOf = (data: AskData, requested: string): string => {
|
|
72
|
+
let path = requested.trim();
|
|
73
|
+
if (data.site && path.startsWith(data.site)) {
|
|
74
|
+
path = path.slice(data.site.replace(/\/$/u, "").length) || "/";
|
|
75
|
+
}
|
|
76
|
+
path = path.replace(/[?#].*$/u, "");
|
|
77
|
+
return normalizeRoute(path.startsWith("/") ? path : `/${path}`);
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
/** A whole page by route, cut at {@link PAGE_CHARS}, or a note that it doesn't exist. */
|
|
81
|
+
export const readPage = (
|
|
82
|
+
data: AskData,
|
|
83
|
+
byRoute: ReadonlyMap<string, OramaDoc>,
|
|
84
|
+
requested: string
|
|
85
|
+
): string => {
|
|
86
|
+
const route = routeOf(data, requested);
|
|
87
|
+
const doc = byRoute.get(route);
|
|
88
|
+
if (!doc) {
|
|
89
|
+
return `There is no page at ${route}. Use search_docs to find the right one.`;
|
|
90
|
+
}
|
|
91
|
+
const text =
|
|
92
|
+
doc.content.length > PAGE_CHARS
|
|
93
|
+
? `${doc.content.slice(0, PAGE_CHARS)}\n\n[The page continues; this is its first ${PAGE_CHARS.toLocaleString("en-US")} characters.]`
|
|
94
|
+
: doc.content;
|
|
95
|
+
return block(doc, text);
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* The tools for one request, given the page the reader is on. Built per
|
|
100
|
+
* request because the search scope follows the reader's locale and version.
|
|
101
|
+
*/
|
|
102
|
+
export const createAskTools = (data: AskData) => {
|
|
103
|
+
const byRoute = new Map(data.documents.map((doc) => [doc.route, doc]));
|
|
104
|
+
return (page?: AskPage) => {
|
|
105
|
+
const scope = readerScope(data, byRoute, page);
|
|
106
|
+
return {
|
|
107
|
+
read_page: tool({
|
|
108
|
+
description:
|
|
109
|
+
"Read one documentation page in full, by its route (the path in parentheses after a page title, such as /docs/getting-started).",
|
|
110
|
+
execute: ({ route }) => Promise.resolve(readPage(data, byRoute, route)),
|
|
111
|
+
inputSchema: jsonSchema<{ route: string }>({
|
|
112
|
+
additionalProperties: false,
|
|
113
|
+
properties: {
|
|
114
|
+
route: {
|
|
115
|
+
description: "The page's route, such as /docs/getting-started.",
|
|
116
|
+
type: "string",
|
|
117
|
+
},
|
|
118
|
+
},
|
|
119
|
+
required: ["route"],
|
|
120
|
+
type: "object",
|
|
121
|
+
}),
|
|
122
|
+
}),
|
|
123
|
+
search_docs: tool({
|
|
124
|
+
description:
|
|
125
|
+
"Search this project's documentation. Returns the most relevant excerpt of each matching page, headed by its title and route.",
|
|
126
|
+
execute: ({ query }) => searchDocs(data, scope, query),
|
|
127
|
+
inputSchema: jsonSchema<{ query: string }>({
|
|
128
|
+
additionalProperties: false,
|
|
129
|
+
properties: {
|
|
130
|
+
query: {
|
|
131
|
+
description:
|
|
132
|
+
"A few focused keywords, such as the feature or option the question is about.",
|
|
133
|
+
type: "string",
|
|
134
|
+
},
|
|
135
|
+
},
|
|
136
|
+
required: ["query"],
|
|
137
|
+
type: "object",
|
|
138
|
+
}),
|
|
139
|
+
}),
|
|
140
|
+
};
|
|
141
|
+
};
|
|
142
|
+
};
|